【发布时间】:2015-06-14 23:56:10
【问题描述】:
我正在尝试编译一个非常基本的程序并在多个操作系统上运行。该程序只是尝试使用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
【问题讨论】:
-
是否有理由将 libc、libstdc++、libm、libgcc 等添加到可交付成果目录中?据我所知,您的应用程序只需要
libfoo和libboost_system。请参阅此thread about how to deploy a custom libc。在我看来,您的问题是您的链接器和动态加载器无法正确理解彼此(重定位错误、PLT 错误等)。 -
我只部署了
libfoo和libboost_system,然后在另一台机器上没有找到libstdc++等。 (他们在那里,但版本错误。) -
啊,好吧。如果您没有部署额外的库,您是否也可以发布您收到的错误消息
-
@Nick 如果您决定真正部署包括 libc 在内的所有共享库依赖项,您还必须指定一个自定义加载程序。见this thread。为了让应用程序在史前遗留系统上运行,我尝试过一次......