好的,这只是一个有趣的练习,但是对于一些较旧的
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 bails out with errors after a while)和–enable-kernel = 2.0.0以使库与旧内核兼容.偶然地,在配置期间我得到了警告
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两次,这也解决了-dependence.
对,艰苦的工作已经得到回报,现在我得到了
$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 …对不起,但是现在太懒了…
> ????