как перенести приложения c / c ++ на устаревшие версии ядра Linux

Хорошо, это всего лишь немного забавное упражнение, но это не может быть слишком сложно компилировать программы для некоторых старых систем 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

Может быть, нет ... Итак, давайте скомпилируем его в текущей системе. Ниже представлены мои попытки, в основном неудачные. Любые другие идеи очень приветствуются.

  1. Скомпилировать с помощью -m32 -march = i386

     user @ Ancient: ~ $ ./a.out
    ОШИБКА В DYNAMIC LINKER ld.so: dynamic-link.h: 53: elf_get_dynamic_info: Утверждение `! "плохой динамический тег" не удалось!
    
  2. Скомпилировать с помощью -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, не урезанный
    
  3. Скомпилировать 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 . Я не понимаю деталей и сдаюсь.

  4. Скомпилируйте в новой системе g ++ -c -m32 -march = i386 и сделайте ссылку на старую. Вау, это действительно работает для C и простых программ C ++ (не использующих объекты C ++),по крайней мере, для тех немногих, что я тестировал. Это не слишком удивительно, поскольку все, что мне нужно от libc , это printf (и, возможно, некоторые математические данные), интерфейс которых не изменился, но интерфейс к libstdc ++ сейчас совсем другое.

  5. Установите виртуальный ящик со старой системой Linux и версией gcc 2.95. Затем скомпилируйте gcc версии 4.x.x ... извините, но сейчас слишком ленив для этого ...

  6. ???

14
задан Community 23 May 2017 в 12:33
поделиться