Мне нужно скомпилировать программу на текущем ubuntu (12.04). Затем эта программа должна запускаться в кластере с помощью CentOS с более старым ядром (2.6.18). К сожалению, я не могу скомпилировать кластер. Если я просто скомпилирую и скопирую программу без каких-либо изменений, я получаю сообщение об ошибке "Ядро слишком старое".
Как я это понял, причиной этого является не столько версия ядра, сколько версия libc, которая использовалась для компиляции. Поэтому я попытался скомпилировать мою программу, динамически связывая libc из кластера и статически связывая все остальное.
Исследование
Об этом уже много вопросов, но ни один из ответов на самом деле не работал у меня. Итак, вот мои исследования по этой теме:
- Этот вопрос объясняет причину слишком старого сообщения ядра.
- Этот вопрос похож, но более специализирован и не имеет ответов.
- Связывание статически, как предлагалось здесь, не работало, потому что libc слишком старен в кластере. Один ответ также упоминает о том, чтобы строить с использованием старого libc, но не объясняет, как это сделать.
- Один из способов заключается в компиляции в виртуальной машине, работающей на старой ОС. Это сработало, но сложно. Я также читал, что вам не следует связывать libc статически
- По-видимому можно компилировать для другой версии libc с опцией
-rpath
, но это не работает для меня (см. ниже).
Текущее состояние
Я скопировал следующие файлы из кластера в каталог /path/to/copied/libs
- libc-2.5.so
- libgcc_s.so.1
- libstdС++. So.6
и компиляция с параметрами -nodefaultlibs -Xlinker -rpath=/path/to/copied/libs -Wl,-Bstatic,-lrt,-lboost_system,-lboost_filesystem -Wl,-Bdynamic,-lc,-lstdc++,-lgcc_s
Вывод ldd в скомпилированном двоичном файле
mybin: /path/to/copied/libs/libc.so.6: version `GLIBC_2.14' not found (required by mybin)
mybin: /path/to/copied/libs/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by mybin)
linux-vdso.so.1 => (0x00007ffff36bb000)
libc.so.6 => /path/to/copied/libs/libc.so.6 (0x00007fbe3789a000)
libstdc++.so.6 => /path/to/copied/libs/libstdc++.so.6 (0x00007fbe37599000)
libgcc_s.so.1 => /path/to/copied/libs/libgcc_s.so.1 (0x00007fbe3738b000)
/lib64/ld-linux-x86-64.so.2 (0x00007fbe37bf3000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fbe37071000)
Я немного смущен ошибкой, потому что он использует правильный путь (т.е. libc из кластера), но все еще жалуется на отсутствующую версию glibc. При запуске ldd в кластере он возвращает not a dynamic executable
и выполняет двоичные результаты в тех же двух ошибках, упомянутых выше. Также похоже, что есть другие библиотеки (linux-vdso.so.1, ld-linux-x86-64.so.2 и libm.so.6). Должен ли я использовать более старые версии для них?
Итак, теперь у меня есть два основных вопроса:
- Это даже правильный подход здесь?
- Если да: как правильно связать старый libc?