Получение исполняемых файлов для запуска на нескольких ОС Linux:

1

Я пытаюсь получить очень базовую программу, скомпилированную и запущенную на нескольких ОС. Программа просто пытается напечатать это имя файла для потока, используя 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
  • 0
    Есть ли причина, по которой вы также включили libc, libstdc ++, libm, libgcc и т. Д. В каталог результатов? Насколько я понимаю, вам нужны только libfoo и libboost_system для вашего приложения. Посмотрите эту ветку о том, как развернуть пользовательский libc . Мне кажется, ваша проблема в том, что ваш компоновщик и динамический загрузчик не понимают друг друга (ошибки перемещения, ошибки PLT и т. П.) Правильно.
  • 0
    Я развернул только libfoo и libboost_system , но затем libstdc++ и т. Д. Не были найдены на другой машине. (Они были там, но имели неправильные версии.)
Показать ещё 13 комментариев
Теги:
centos

2 ответа

0

Я предполагаю, что это типичный случай тонких различий между дистрибутивами Linux:

Известно, что Ubuntu, основанный на Debian и CentOS, который основан на RedHat, использует разные места для хранения системных библиотек и - чтобы ухудшить ситуацию - также используют разные схемы именования.

И даже больше осложнений может возникнуть, если возраст распределений значительно варьируется (новый выпуск Ubuntu против старого CentOS или наоборот).

Вы собрали все свои библиотеки на своей машине Ubuntu. Запуск ldd ~/deliverable/.lib/libc.so.6 покажет вам полный список зависимостей, то есть все зависимости найдены.

Я почти уверен, что запуск этой же команды на вашей машине CentOS покажет вам неполный список (одна или несколько зависимостей не могут быть найдены). Это, скорее всего, связано с различием между дистрибутивами Linux, упомянутыми выше.

С головы до ног я вижу следующие способы решения этой ситуации:

  1. на вашей машине CentOS определите местоположение и имя для распределения, а также имя отсутствующих зависимостей и соедините их с теми же абсолютными путями, которые были показаны ldd на вашей машине Ubuntu. Это быстрое и грязное решение, которое может или (скорее) может не работать. Я бы посоветовал это сделать.

  2. Скомпилируйте все libs в deliverable/.lib/* для конкретной целевой платформы и свяжите их соответственно. Это также libstd++ бы необходимость отправить libstd++ поскольку оно будет связано с правильным.

  • 0
    Просто запустил ldd на CentOS. Все зависимости найдены.
  • 0
    @nils Это всегда одна и та же платформа, то есть x64. Как / почему вы по-другому компилируете для CentOS или Ubuntu?
Показать ещё 3 комментария
0

Я подумал, что после того, как в системе установлены дополнительные файлы .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

  • 1
    Об этом заботится использование переменной $ ORIGIN. Кроме того, strace ./hello показывает, что strace ./hello библиотеки.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню