Я пытаюсь получить очень базовую программу, скомпилированную и запущенную на нескольких ОС. Программа просто пытается напечатать это имя файла для потока, используя boost::filesystem
, чтобы я мог проверить, что загрузка .so
работает так, как ожидалось.
Я скомпилирую его в поле Ubuntu:
$ uname -a
Linux ubuntu 3.13.0-48-generic #80-Ubuntu SMP Thu Mar 12 11:16:15 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
И у меня есть поле CentOS, в котором я пытаюсь запустить его:
$ uname -a
Linux localhost.localdomain 3.10.0-123.20.1.el7.x86_64 #1 SMP Thu Jan 29 18:05:33 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
Я скомпилирую исполняемый файл с помощью $ORIGIN
чтобы связанные библиотеки boost были выбраны из моего каталога, затем я ldd
библиотеки boost и cp
их в то же самое. Итак, каталог lib выглядит следующим образом:
deliverable/
deliverable/hello
deliverable/.lib/
deliverable/.lib/libc.so.6
deliverable/.lib/libboost_system.so.1.58.0
deliverable/.lib/libpthread.so.0
deliverable/.lib/libm.so.6
deliverable/.lib/libstdc++.so.6
deliverable/.lib/libboost_filesystem.so.1.58.0
deliverable/.lib/libboost_filesystem.so
deliverable/.lib/libfoo.so
deliverable/.lib/libboost_system.so
deliverable/.lib/libgcc_s.so.1
где hello
- исполняемый файл, который я хочу запустить. Однако в окне CentOs появляется следующее сообщение об ошибке:
$ ./hello
$ ./hello: relocation error: ~/deliverable/.lib/libc.so.6: symbol _dl_find_dso_for_object, version GLIBC_PRIVATE not defined in file ld-linux-x86-64.so.2 with link time reference
Как это можно зафиксировать? Я также хотел бы знать, нарушает ли этот шаблон лучшие практики в отношении отгрузки скомпилированного кода между машинами Linux. , ,
Дополнительная информация, если это необходимо:
$ cat Makefile
CXX = g++
CPPFLAGS := -Wall -g -Wfatal-errors -std=c++11 -I./inc -fPIC
DELIVERABLE = $(CURDIR)/deliverable
LIB = $(DELIVERABLE)/.lib
all: $(DELIVERABLE)/hello
$(DELIVERABLE)/hello: main.o $(LIB)/libfoo.so
$(CXX) -L./deliverable/.lib -Wl,--allow-shlib-undefined -Wl,-rpath='$$ORIGIN/.lib' -o $@ $< -lfoo
main.o: main.cc
$(CXX) $(CPPFLAGS) -c $< -o $@
$(LIB)/libfoo.so: foo.o
$(CXX) -L./deliverable/.lib -Wl,--allow-shlib-undefined -Wl,-rpath='$$ORIGIN/.lib' -shared -o $@ $^ -lboost_system -lboost_filesystem
foo.o: foo.cc
$(CXX) $(CPPFLAGS) -c $< -o $@
clean:
rm -f *.o $(LIB)/libfoo.so $(DELIVERABLE)/hello
$ cat main.cc
#include "foo.hh"
int main()
{
hello();
}
$ cat foo.hh
#ifndef FOO_HH
#define FOO_HH
void hello();
#endif
$ cat foo.cc
#include "foo.hh"
#include <boost/filesystem.hpp>
#include <iostream>
void hello()
{
boost::filesystem::path p{__FILE__};
std::cout << "p.parent_path() " << p.parent_path() << '\n';
std::cout << "p.string() " << p.string() << '\n';
std::cout << "__FILE__ " << __FILE__ << '\n';
}
Я также попробовал это на коробке RHEL, которая дала еще худшую ошибку:
$ uname -a
Linux localhost.localdomain 2.6.18-164.6.1.el5 #1 SMP Tue Nov 3 ... EXT 2009 x86_64 x86_64 GNU/Linux
Запуск его на этой машине произошел с:
$./hello
./hello: error while loading shared libraries: ~/deliverable/.lib/libm.so.6: unexpected PLT reloc type 0x25
Я предполагаю, что это типичный случай тонких различий между дистрибутивами Linux:
Известно, что Ubuntu, основанный на Debian и CentOS, который основан на RedHat, использует разные места для хранения системных библиотек и - чтобы ухудшить ситуацию - также используют разные схемы именования.
И даже больше осложнений может возникнуть, если возраст распределений значительно варьируется (новый выпуск Ubuntu против старого CentOS или наоборот).
Вы собрали все свои библиотеки на своей машине Ubuntu. Запуск ldd ~/deliverable/.lib/libc.so.6
покажет вам полный список зависимостей, то есть все зависимости найдены.
Я почти уверен, что запуск этой же команды на вашей машине CentOS покажет вам неполный список (одна или несколько зависимостей не могут быть найдены). Это, скорее всего, связано с различием между дистрибутивами Linux, упомянутыми выше.
С головы до ног я вижу следующие способы решения этой ситуации:
на вашей машине CentOS определите местоположение и имя для распределения, а также имя отсутствующих зависимостей и соедините их с теми же абсолютными путями, которые были показаны ldd
на вашей машине Ubuntu. Это быстрое и грязное решение, которое может или (скорее) может не работать. Я бы посоветовал это сделать.
Скомпилируйте все libs в deliverable/.lib/*
для конкретной целевой платформы и свяжите их соответственно. Это также libstd++
бы необходимость отправить libstd++
поскольку оно будет связано с правильным.
ldd
на CentOS. Все зависимости найдены.
Я подумал, что после того, как в системе установлены дополнительные файлы .so
, вы должны "сказать", что они там?
ldconfig - это команда, о которой я думаю:
ldconfig creates the necessary links and cache (for use by the run-time linker, ld.so) to the most recent shared libraries found in the directories specified on the command line, in the file/etc/ld.so.conf, and in the trusted directories (/usr/lib and/lib). ldconfig checks the header and file names of the libraries it encounters when determining which versions should have their links updated. ldconfig ignores symbolic links when scanning for libraries.
http://linux.about.com/od/commands/l/blcmdl8_ldconfi.htm
strace ./hello
показывает, что strace ./hello
библиотеки.
libfoo
иlibboost_system
для вашего приложения. Посмотрите эту ветку о том, как развернуть пользовательский libc . Мне кажется, ваша проблема в том, что ваш компоновщик и динамический загрузчик не понимают друг друга (ошибки перемещения, ошибки PLT и т. П.) Правильно.libfoo
иlibboost_system
, но затемlibstdc++
и т. Д. Не были найдены на другой машине. (Они были там, но имели неправильные версии.)