Хорошо, это всего лишь немного забавное упражнение, но это не может быть слишком сложно компилировать программы для некоторых старых систем 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
ОШИБКА В DYNAMIC LINKER ld.so: dynamic-link.h: 53: elf_get_dynamic_info: Утверждение `! "плохой динамический тег" не удалось!
Скомпилировать с помощью -m32 -march = i386 -static
: Работает на всех сравнительно последних версиях ядра, но терпит неудачу, если они немного старше, с хорошо известным сообщением об ошибке
user @ Ancient: ~ $. /a.out
FATAL: ядро слишком старое
Ошибка сегментации
Это ошибка glibc
, имеющая минимальную поддерживаемую версию ядра, например ядро 2.6.4 в моей системе:
$ file a.out
a.out: 32-разрядный исполняемый файл LSB ELF, Intel 80386, версия 1 (SYSV),
статически связанный, для GNU / Linux 2.6.4, не урезанный
Скомпилировать glibc
самостоятельно с поддержкой самого старого ядра из возможных. Этот пост описывает это более подробно, но по сути он выглядит так
wget ftp://ftp.gnu.org/gnu/glibc/glibc-2.14.tar.bz2
tar -xjf glibc-2.14.tar.bz2
компакт-диск 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"
сделать -j 4
сделать intall
Не уверен, что параметры - with-cpu
и - host
что-то делают, наиболее важно принудительно использовать флаги компилятора -m32 -march = i486
для 32-битных сборок (к сожалению, -march = i386
выдает ошибку через некоторое время) и - enable-kernel = 2.0.0
, чтобы сделать библиотеку совместимой со старыми ядрами. Между прочим, во время configure
я получил предупреждение
WARNING: минимальная версия ядра сброшена на 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 -статическая прог. o $ {LIBC_FLAGS} -o прог.
Поскольку мы выполняем статическую компиляцию, порядок ссылок важен и может потребовать некоторых проб и ошибок, но в основном мы узнаем, какие параметры 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: 32-разрядный исполняемый файл LSB ELF, Intel 80386, версия 1 (SYSV),
статически связанный, для GNU / Linux 2.0.10, не урезанный
Отлично, я подумал, а теперь попробуйте на старой системе:
user @ Ancient: ~ $./ прог
set_thread_area не удалось при настройке локального хранилища потока
Ошибка сегментации
Это снова сообщение об ошибке glibc
из ./ nptl / sysdeps / i386 / tls.h
. Я не понимаю деталей и сдаюсь.
Скомпилируйте в новой системе g ++ -c -m32 -march = i386
и сделайте ссылку на старую. Вау, это действительно работает для C и простых программ C ++ (не использующих объекты C ++),по крайней мере, для тех немногих, что я тестировал. Это не слишком удивительно, поскольку все, что мне нужно от libc
, это printf
(и, возможно, некоторые математические данные), интерфейс которых не изменился, но интерфейс к libstdc ++
сейчас совсем другое.
Установите виртуальный ящик со старой системой Linux и версией gcc 2.95. Затем скомпилируйте gcc версии 4.x.x ... извините, но сейчас слишком ленив для этого ...
???