2012-05-30 2 views
33

Мне нужно скомпилировать программу на текущем ubuntu (12.04). Затем эта программа должна запускаться в кластере с помощью CentOS с более старым ядром (2.6.18). К сожалению, я не могу скомпилировать кластер. Если я просто скомпилирую и скопирую программу без каких-либо изменений, я получаю сообщение об ошибке «Ядро слишком старое».Компиляция со старым libc (версия `GLIBC_2.14 'не найдена)

Как я понял, причина в том, что это не столько версия ядра, сколько версия libc, которая использовалась для компиляции. Поэтому я попытался скомпилировать мою программу, динамически связывая libc из кластера и статически связывая все остальное.

Исследование

Есть уже много вопросов по этому поводу на SO, но ни один из ответов на самом деле не работает для меня. Так вот мое исследование по этой теме:

  • This question объясняет причину для ядра слишком старого сообщения
  • This question похож, но более специализирован и не имеет никаких ответов
  • Связывание статический, как предложено here не работает потому что libc слишком старен в кластере. В одном ответе также упоминается создание с использованием старого libc, но не объясняет, как это сделать.
  • One way заключается в компиляции в виртуальной машине, работающей на старой ОС. Это сработало, но сложно. Я также читал, что you should not link libc statically
  • Apparently это is possible скомпилировать для другой версии LibC с опцией -rpath, но это не работает для меня (смотри ниже)

Текущее состояние

Я скопировал следующие файлы из кластера в каталог /path/to/copied/libs

  • libc-2.5.so
  • libgcc_s.so.1
  • libstdC++. 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) 

Я m несколько смущает ошибка, поскольку использует правильный путь (т. е. libc из кластера), но все же жалуется на недостающую версию glibc. При запуске ldd в кластере он возвращает not a dynamic executable и выполняет двоичные результаты в тех же двух ошибках, упомянутых выше. Также похоже, что есть другие библиотеки (linux-vdso.so.1, ld-linux-x86-64.so.2 и libm.so.6). Должен ли я использовать более старые версии для них?

Так что теперь у меня есть два основных вопроса:

  • Это даже правильный подход здесь?
  • Если да: как правильно связать старый libc?

ответ

10

См. this Ответ.

Неужели это даже правильный подход здесь

Нет, вы не можете использовать несоответствующие версии Glibc, как ваша команда делает ссылку. Вы использовали crt0.o и ld-linux.so от новый (системный) libc, но libc.so.6 из старого (скопированного из кластера) libc. Это просто не сработает.

2

-rpath устанавливает тег DT_RPATH, но не говорит, компоновщик искать там LIBS, вы хотите -L для этого.

Смежные вопросы