【问题标题】:Dynamic library cannot load when running program outside build directory在构建目录之外运行程序时无法加载动态库
【发布时间】:2019-01-05 02:36:53
【问题描述】:

我有以下 Makefile:

OBJ=main.o other.o other1.o other2.o
LINKDIVSUF=-L libdivsufsort-master/build/lib/ -ldivsufsort64 -Wl,-R libdivsufsort-master/build/lib/  
INCDIVSUF=-I libdivsufsort-master/build/include -ldivsufsort64                                       
EXE=program                                                                                             
COMPFLAGS=-MMD -fopenmp -std=c++17 -O3                                                   
CXX=g++                                                                                              

$(EXE):$(OBJ)                                                                                        
  $(CXX) $(COMPFLAGS) $(OBJ) -o $(EXE) $(LINKDIVSUF) -lz -lboost_regex -lboost_program_options       

%.o: %.cpp                                                                                           
  $(CXX) $(COMPFLAGS) $(INCDIVSUF) -c $<                                                             
-include $(OBJ:.o=.d)                                                                                      

program 链接到动态库 libdivsufsort64.so.3,该动态库位于构建目录 ./libdivsufsort-master/build/lib/。 使用-Wl,-R libdivsufsort-master/build/lib/ 是为了避免必须将absolute/path/to/libdivsufsort-master/build/lib/ 连接到LD_LIBRARY_PATH 才能运行program。确实,当我makeprogram 如果没有-Wl, -R libdivsufsort-master/build/lib/,并且没有设置LD_LIBRARY_PATH 并随后运行program,我会收到以下错误消息:

./program: error while loading shared libraries: libdivsufsort64.so.3: cannot open shared object file: No such file or directory 

使用-Wl, -R libdivsufsort-master/build/lib/program 运行成功,LD_LIBRARY_PATH 没有改变,但仅当 我从构建它的同一目录运行program 。 如果我在使用 -Wl, -R libdivsufsort-master/build/lib/ 从任何其他目录编译时尝试运行 program ,它将无法运行, 以 上述错误信息。

如何更改 g++ 编译选项(或编译时的其他任何内容)以启用 program 运行 任何目录,同时避免需要更改LD_LIBRARY_PATH?我发现的唯一“解决方案”是将libdivsufsort-master/build/lib/ 连接到LD_LIBRARY_PATH。通过这样做,我可以从任何地方运行program 目录,因此无需使用Wl,-R libdivsufsort-master/build/lib/ 进行编译,但是,这当然需要program 的用户手动设置他们的LD_LIBRARY_PATH,这是我特别想避免的。

解决方案 阅读这篇that discusses the use of relative or absolute paths with -R (-rpath) 的帖子我想出了这个解决方案。

添加以下行,使得 Makefile 现在是:

libdivsufsort_lib = $(addprefix $(shell pwd), /libdivsufsort-master/build/lib/)        
libdivsufsort_include = $(addprefix $(shell pwd), /libdivsufsort-master/build/include/)
OBJ=main.o other.o other1.o other2.o
LINKDIVSUF=-L libdivsufsort-master/build/lib/ -ldivsufsort64 -Wl,-R libdivsufsort-master/build/lib/  
INCDIVSUF=-I libdivsufsort-master/build/include -ldivsufsort64                                       
EXE=program                                                                                             
COMPFLAGS=-MMD -fopenmp -std=c++17 -O3                                                   
CXX=g++                                                                                              

$(EXE):$(OBJ)                                                                                        
  $(CXX) $(COMPFLAGS) $(OBJ) -o $(EXE) $(LINKDIVSUF) -lz -lboost_regex -lboost_program_options       

%.o: %.cpp                                                                                           
  $(CXX) $(COMPFLAGS) $(INCDIVSUF) -c $<                                                             
-include $(OBJ:.o=.d)    

这避免了使用$ORIGIN 来生成programs 的绝对路径 目录,某些系统不支持该目录。两个额外的 无论二进制文件的位置如何,行都会产生绝对路径 - 它只需要保存在构建目录中并在构建时再次编译 目录移动。重要的是,现在可以从外部调用program 构建目录。

【问题讨论】:

    标签: makefile compilation linker g++ dynamic-linking


    【解决方案1】:

    您需要使用$ORIGIN-Wl,-R 在相对路径中定位库:

    LINKDIVSUF = ... -Wl,-R,'$ORIGIN/libdivsufsort-master/build/lib'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-21
      • 1970-01-01
      • 2011-09-15
      • 1970-01-01
      • 2011-09-09
      相关资源
      最近更新 更多