Подтвердить что ты не робот

Компиляция со старым libc (версия `GLIBC_2.14 'не найдена)

Мне нужно скомпилировать программу на текущем 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?
4b9b3361

Ответ 1

См. этот ответ.

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

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

Ответ 2

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