Хорошо, это всего лишь забавное упражнение, но это не может быть слишком сложная компиляция программ для некоторых старых Linux-систем, или это возможно?
У меня есть доступ к нескольким древним системам, в которых работает весь Linux, и, возможно, было бы интересно посмотреть, как они работают под нагрузкой. Например, мы хотим сделать некоторую линейную алгебру, используя Eigen, которая является хорошей библиотекой только для заголовка. Есть ли возможность скомпилировать его в целевой системе?
[email protected]:~ $ uname -a
Linux local 2.2.16 #5 Sat Jul 8 20:36:25 MEST 2000 i586 unknown
[email protected]:~ $ gcc --version
egcs-2.91.66
Возможно, нет... Так что давайте скомпилируем его в текущей системе. Ниже приведены мои попытки, в основном неудачные. Любые идеи очень приветствуются.
-
Скомпилировать с помощью
-m32 -march=i386
[email protected]:~ $ ./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
: выполняется на всех довольно недавних версиях ядра, но не удается, если они немного старше с известным сообщением об ошибке[email protected]:~ $ ./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
с поддержкой самого старого ядра. Этот пост описывает его более подробно, но по существу он похож на этот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
Поскольку мы делаем статический компилятор, порядок ссылок важен и может потребовать некоторых проб и ошибок, но в основном мы узнаем, из каких опций
gcc
дает к компоновщику:$ g++ -m32 -static -Wl,-v file.o
Заметьте,
crtbeginT.o
иcrtend.o
также связаны с тем, что мне не нужно для моих программ, поэтому я их оставил. Вывод также включает строку типа--start-group -lgcc -lgcc_eh -lc --end-group
, которая указывает на взаимозависимость между библиотеками, см. этот пост. Я просто упомянул-lc
дважды в командной строкеgcc
, которая также решает взаимозависимость.Правильно, тяжелая работа окупилась, и теперь я получаю
$ file ./prog ./prog: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.0.10, not stripped
Блестящий я подумал, теперь попробуй его на старой системе:
[email protected]:~ $ ./prog set_thread_area failed when setting up thread-local storage Segmentation fault
Это, опять же, сообщение об ошибке
glibc
от./nptl/sysdeps/i386/tls.h
. Я не понимаю деталей и сдаюсь. -
Скомпилируйте новую систему
g++ -c -m32 -march=i386
и ссылку на старую. Ничего себе, это действительно работает для C и простых программ на С++ (не используя объекты С++), по крайней мере для тех немногих, которые я тестировал. Это не слишком удивительно, поскольку все, что мне нужно отlibc
, этоprintf
(и, может быть, некоторые математические данные), интерфейс которого не изменился, но интерфейс кlibstdc++
теперь сильно отличается. -
Установите виртуальную коробку со старой системой Linux и gcc версии 2.95. Затем скомпилируйте gcc версию 4.x.x... извините, но слишком ленив для этого прямо сейчас...
-
???