【发布时间】:2012-02-16 05:04:40
【问题描述】:
好的,这只是一个有趣的练习,但是为一些较旧的 linux 系统编译程序不会太难,或者可以吗?
我可以访问几个都运行 linux 的古老系统,也许看看它们在负载下的表现会很有趣。举个例子,我们想使用Eigen 做一些线性代数,这是一个不错的纯标题库。有机会在目标系统上编译它吗?
user@ancient:~ $ uname -a
Linux local 2.2.16 #5 Sat Jul 8 20:36:25 MEST 2000 i586 unknown
user@ancient:~ $ gcc --version
egcs-2.91.66
也许不是...所以让我们在当前系统上编译它。以下是我的尝试,主要是失败的。任何更多的想法都非常欢迎。
-
使用
-m32 -march=i386编译user@ancient:~ $ ./a.out BUG IN DYNAMIC LINKER ld.so: dynamic-link.h: 53: elf_get_dynamic_info: Assertion `! "bad dynamic tag"' failed! -
使用
-m32 -march=i386 -static编译:可在所有相当新的内核版本上运行,但如果它们稍旧并出现众所周知的错误消息,则会失败user@ancient:~ $ ./a.out FATAL: kernel too old Segmentation fault这是一个
glibc错误,它具有它支持的最低内核版本,例如我的系统上的内核 2.6.4:$ file a.out a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.4, not stripped -
自己编译
glibc并尽可能支持最旧的内核。 This post 更详细地描述了它,但本质上是这样的wget ftp://ftp.gnu.org/gnu/glibc/glibc-2.14.tar.bz2 tar -xjf glibc-2.14.tar.bz2 cd glibc-2.14 mkdir build; cd build ../configure --prefix=/usr/local/glibc_32 \ --enable-kernel=2.0.0 \ --with-cpu=i486 --host=i486-linux-gnu \ CC="gcc -m32 -march=i486" CXX="g++ -m32 -march=i486" make -j 4 make intall不确定
--with-cpu和--host选项是否有任何作用,最重要的是强制将编译器标志-m32 -march=i486用于32 位构建(不幸的是-march=i386在一段时间后因错误而退出)和--enable-kernel=2.0.0使库与旧内核兼容。顺便说一句,在configure期间,我收到了警告WARNING: minimum kernel version reset to 2.0.10我想这仍然是可以接受的。有关随不同内核变化的内容列表,请参阅
./sysdeps/unix/sysv/linux/kernel-features.h。好的,让我们链接到新编译的
glibc库,虽然有点乱,但还是这样:$ export LIBC_PATH=/usr/local/glibc_32 $ export LIBC_FLAGS=-nostdlib -L${LIBC_PATH} \ ${LIBC_PATH}/crt1.o ${LIBC_PATH}/crti.o \ -lm -lc -lgcc -lgcc_eh -lstdc++ -lc \ ${LIBC_PATH}/crtn.o $ g++ -m32 -static prog.o ${LIBC_FLAGS} -o prog由于我们正在进行静态编译,link order 很重要,并且可能需要一些试验和错误,但基本上我们从
gcc为链接器提供的选项中学习:$ g++ -m32 -static -Wl,-v file.o注意,
crtbeginT.o和crtend.o也与我的程序不需要的链接相关联,因此我将它们排除在外。输出还包括类似--start-group -lgcc -lgcc_eh -lc --end-group的行,表示库之间的相互依赖关系,请参阅this post。我刚刚在gcc命令行中提到了两次-lc,这也解决了相互依赖问题。好的,努力得到了回报,现在我明白了
$ file ./prog ./prog: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.0.10, not stripped我认为很棒,现在在旧系统上尝试一下:
user@ancient:~ $ ./prog set_thread_area failed when setting up thread-local storage Segmentation fault这又是来自
./nptl/sysdeps/i386/tls.h的glibc错误消息。看不懂细节就放弃了。 在新系统
g++ -c -m32 -march=i386上编译并在旧系统上链接。哇,这实际上适用于 C 和简单的 C++ 程序(不使用 C++ 对象),至少对于我测试过的少数程序。这并不奇怪,因为我从libc需要的只是printf(也许还有一些数学),其中的接口没有改变,但libstdc++的接口现在非常不同。使用旧的 linux 系统和 gcc 2.95 版设置一个虚拟机。然后编译 gcc 版本 4.x.x ......对不起,但现在太懒了......
???
【问题讨论】:
-
编译?一个只有标题的模板库?
-
编译一个使用这个模板库的测试程序。这只是一些由于 gcc 版本过时而无法在目标机器上编译的代码示例。
-
啊,好吧。抱歉,刚才误会了。
标签: c++ linux gcc linux-kernel glibc