在生成目录之外运行程序时无法加载动态库

时间:2019-01-05 02:36:54

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

我有以下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。确实,当我make program 如果没有-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 。 如果我尝试从其他任何目录中用program 编译时运行-Wl, -R libdivsufsort-master/build/lib/,它将无法运行,并终止于 上述错误消息。

如何更改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来生成指向program的绝对路径 目录,在某些系统上不支持。另外两个 行产生绝对路径,与二进制文件的位置无关- 它只需要保留在构建目录中,如果构建就可以再次编译 目录移动。重要的是,program现在可以从 构建目录。

1 个答案:

答案 0 :(得分:0)

您需要将$ORIGIN-Wl,-R一起使用,以在相对路径中找到该库:

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