我目前正在开发一个C ++应用程序,这将参考多个*。所以库,对于不同的机器各自含有代码 - 写入C.我也有从自定义空间实用程序,其中(顾名思义)一个共享对象包含代码包含为应用程序(用C ++编写,如本申请的其余部分)有用的基本工具。
目前,utilities.so是由应用程序引用唯一的(自定义)库。该应用程序编译和链接就好了,但是执行它在目标硬件上显示以下错误:bin/updater_v4test: error while loading shared libraries: ../../../bin/device_modules/utilities.so.1.0.0: cannot open shared object file: No such file or directory
当调用LDD在所述申请中,下面的输出被示出:../../../bin/device_modules/utilities.so.1.0.0 => not found
我写了一个脚本(化妆时退出没有错误)收集所有SO和推动他们对目标硬件上的/ lib /目录下;这意味着在应用程序的每个成功的版本(无论是部分或全部),更新后的文件推到正确的目录在目标硬件上。
在试图模仿其他图书馆我已经用(如zlib的),我试图创建一个符号链接库文件,没有运气(utilities.so.1.0.0是符号链接,utilities.so是实际所以)。 utilities.so.1.0.0 --> utilities.so
目前我在一个损失,我不能在试图弄清楚这一点,我自己浪费更多的时间。
下面是从公用事业Makefile文件的摘录:
include ../../common/user.mk
LIB_DIR=../../../libs/lib/powerpc-linux-gnu
CFLAGS=-Wall -ggdb -I../../libs/include -I../../common -lpthread -lddc -std=c++0x -I../../libs/include/zlib
LDFLAGS=../../libs/lib/powerpc-linux-gnu/libcurl.so.4 ../../libs/include/minizip/.libs/libminizip.so.1.0.0 \
-L ../../libs/lib \
-L ../../libs/lib/powerpc-linux-gnu \
-Wl,-rpath-link,../../libs/lib/powerpc-linux-gnu \
-lrt -lddc -lpthread -shared
BIN_DIR=../bin
CANONICAL_BIN_DIR := $(shell readlink -f $(BIN_DIR))
CANONICAL_CUR_DIR := $(shell readlink -f "./")
COMP_OBJECTS := $(wildcard *.cpp)
OBJECTS := $(patsubst %.cpp,%.o,$(wildcard *.cpp))
all: objects utilities.so
-cp --parents utilities.so $(GLOBAL_BIN_LIB)
-ln -s utilities.so utilities.so.1.0.0
-mv utilities.so.1.0.0 $(GLOBAL_BIN_LIB)
# -cp --parents *.h $(GLOBAL_HEADER_DIR)
-rm -f utilities.so
-rm -f *.o
for header in $(wildcard *.h); do \
echo $$header; \
ln -s $(CANONICAL_CUR_DIR)/$$header $(GLOBAL_HEADER_DIR)/$$header; \
done;
@printf "########## BUILT $^ ##########\n\n"
utilities.so: $(OBJECTS)
${CXX} $^ -o $@ ${LDFLAGS}
objects: $(COMP_OBJECTS)
${CXX} -c $^ ${CFLAGS}
而现在从应用Makefile文件的摘录。在这里,我加入到连接器参数库的引用,头文件都从一个目录包含英寸
include ../../../common/user.mk
LIB_DIR=../../../libs/lib/powerpc-linux-gnu
CFLAGS=-Wall -ggdb -I../../../libs/include -I${COMMON_DIR} -lpthread -lddc -std=c++0x -I../../../libs/include/zlib -I${HEADER_DIR}
LDFLAGS=../../../libs/lib/powerpc-linux-gnu/libcurl.so.4 ../../../libs/include/minizip/.libs/libminizip.so.1.0.0 ../../../bin/device_modules/utilities.so.1.0.0 \
-L ../../../libs/lib \
-L ../../../libs/lib/powerpc-linux-gnu \
-Wl,-rpath-link,../../../libs/lib/powerpc-linux-gnu \
-lrt -lddc -lpthread -L ${SO_DIR}
BIN_DIR=../bin
CANONICAL_BIN_DIR := $(shell readlink -f $(BIN_DIR))
CANONICAL_CUR_DIR := $(shell readlink -f "./")
all: test_update.bin
-cp --parents test_update.bin $(BIN_DIR)
-ln -s $(CANONICAL_BIN_DIR)/test_update.bin $(GLOBAL_BIN_APP)/test_update.bin
-rm -f *.bin
@printf "########## BUILT $^ ##########\n\n"
test_update.bin: main.o updaterdelegate.o commonfunctions.o tinyxml.o
${CXX} $^ -o $@ ${LDFLAGS}
####################
# Required Files #
####################
main.o: Main.cpp
${CXX} -c $^ -o $@ ${CFLAGS}
updaterdelegate.o: UpdaterDelegate.cpp
${CXX} -c $^ -o $@ ${CFLAGS}
commonfunctions.o: $(shell python -c "import os.path; print os.path.relpath('${IMPL_CMN_FUNC}'.replace('\"', ''), '${CANONICAL_CUR_DIR}'.replace('\"', ''))")
${CXX} -c $^ -o $@ ${CFLAGS}
tinyxml.o: $(shell python -c "import os.path; print os.path.relpath('${IMPL_TXML}'.replace('\"', ''), '${CANONICAL_CUR_DIR}'.replace('\"', ''))")
${CXX} -c $^ -o $@ ${CFLAGS}
####################
# /Required Files #
####################
只是为了控释片和shiggles,我将添加utilities.so和应用程序的生成输出。
utilities.so:
(清洁略)
=============== CLEAN COMPLETE... BUILDING... ===============
make: Entering directory `~/_workspace/upv4/common/utils'
powerpc-linux-gnu-g++ -c ArgumentHandling.cpp Extensions.cpp Logging.cpp -Wall -ggdb -I../../libs/include -I../../common -lpthread -lddc -std=c++0x -I../../libs/include/zlib
ArgumentHandling.cpp: In member function ‘void Utilities::ArgumentHandler::freeMemory()’:
ArgumentHandling.cpp:136: warning: deleting ‘void*’ is undefined
powerpc-linux-gnu-g++ ArgumentHandling.o Extensions.o Logging.o -o utilities.so ../../libs/lib/powerpc-linux-gnu/libcurl.so.4 ../../libs/include/minizip/.libs/libminizip.so.1.0.0 -L ../../libs/lib -L ../../libs/lib/powerpc-linux-gnu -Wl,-rpath-link,../../libs/lib/powerpc-linux-gnu -lrt -lddc -lpthread -shared
cp --parents utilities.so """~/_workspace/upv4""/bin/device_modules"
ln -s utilities.so utilities.so.1.0.0
mv utilities.so.1.0.0 """~/_workspace/upv4""/bin/device_modules"
rm -f utilities.so
rm -f *.o
for header in ArgumentHandling.h Enumerations.h Extensions.h Logging.h; do \
echo $header; \
ln -s ~/_workspace/upv4/common/utils/$header """"~/_workspace/upv4""/bin/device_modules"/headers"/$header; \
done;
ArgumentHandling.h
Enumerations.h
Extensions.h
Logging.h
########## BUILT objects utilities.so ##########
make: Leaving directory `~/_workspace/upv4/common/utils'
=============== BUILD COMPLETE... PARSING... ===============
========== Warnings ==========
Total: 1
ArgumentHandling.cpp:136: warning: deleting ‘void*’ is undefined
========== Errors ==========
Total: 0
test_update.bin:
(清洁略)
=============== CLEAN COMPLETE... BUILDING... ===============
make: Entering directory `~/_workspace/_workspace/upv4/test/app/src'
powerpc-linux-gnu-g++ -c Main.cpp -o main.o -Wall -ggdb -I../../../libs/include -I"""~/_workspace/_workspace/upv4""/common" -lpthread -lddc -std=c++0x -I../../../libs/include/zlib -I"""""~/_workspace/_workspace/upv4""/bin/device_modules"/headers""
powerpc-linux-gnu-g++ -c UpdaterDelegate.cpp -o updaterdelegate.o -Wall -ggdb -I../../../libs/include -I"""~/_workspace/_workspace/upv4""/common" -lpthread -lddc -std=c++0x -I../../../libs/include/zlib -I"""""~/_workspace/_workspace/upv4""/bin/device_modules"/headers""
powerpc-linux-gnu-g++ -c ../../../common/commonFunctions.cpp -o commonfunctions.o -Wall -ggdb -I../../../libs/include -I"""~/_workspace/_workspace/upv4""/common" -lpthread -lddc -std=c++0x -I../../../libs/include/zlib -I"""""~/_workspace/_workspace/upv4""/bin/device_modules"/headers""
powerpc-linux-gnu-g++ -c ../../../common/xmlreader/tinyxml2.cpp -o tinyxml.o -Wall -ggdb -I../../../libs/include -I"""~/_workspace/_workspace/upv4""/common" -lpthread -lddc -std=c++0x -I../../../libs/include/zlib -I"""""~/_workspace/_workspace/upv4""/bin/device_modules"/headers""
powerpc-linux-gnu-g++ main.o updaterdelegate.o commonfunctions.o tinyxml.o -o test_update.bin ../../../libs/lib/powerpc-linux-gnu/libcurl.so.4 ../../../libs/include/minizip/.libs/libminizip.so.1.0.0 ../../../bin/device_modules/utilities.so.1.0.0 -L ../../../libs/lib -L ../../../libs/lib/powerpc-linux-gnu -Wl,-rpath-link,../../../libs/lib/powerpc-linux-gnu -lrt -lddc -lpthread -L """"~/_workspace/_workspace/upv4""/bin/device_modules""
cp --parents test_update.bin ../bin
ln -s ~/_workspace/_workspace/upv4/test/app/bin/test_update.bin """~/_workspace/_workspace/upv4""/bin"/test_update.bin
ln: failed to create symbolic link `~/_workspace/_workspace/upv4/bin/test_update.bin': File exists
make: [all] Error 1 (ignored)
rm -f *.bin
########## BUILT test_update.bin ##########
make: Leaving directory `~/_workspace/_workspace/upv4/test/app/src'
=============== BUILD COMPLETE... PARSING... ===============
========== Warnings ==========
Total: 0
========== Errors ==========
Total: 0
构建脚本是自定义的,我建我自己摆脱整个化妆输出的自己时,我并不需要它,并将其解析出所有的错误和警告。由于这个问题,我已经重新打开化妆输出。
我错过了什么编译时/库的链接,或应用程序的链接过程中的一些问题呢?我倾向于说该库的编译/链接过程中它是 - 虽然我不知道究竟是怎么了?你,因为一切都被编译和链接就好了。为什么应用程序寻找它不可能有一个路径的.so文件?
我还相信,在.so文件与$ PATH变量中找到,因此应用程序应该能够找到他们。
系统正常搜索在一组固定的目录的共享对象。您可以通过定义环境变量LD_LIBRARY_PATH
并添加您安装的共享库的目录里解决这个问题。
或者,您可以添加这些库的一些标准库的目录和执行ldconfig -a
更新共享库的高速缓存。
见ldconfig(8)
,获取更多信息。
有两种机制加载一个共享对象。
Makefile
做什么。您指定的共享可执行文件和ld.so.xxx
共享对象(链接到你的应用程序时,你是动态链接的话)加载并遵循所有未解决的标识符,找到他们在虚拟地址空间的地方。该ld.so.xxx
对象使用/etc/ld.so.cache
文件,这只是一个哈希表提供的目录和共享的可执行文件被加载这种方式。这个文件是由所谓的soname
到最后一个版本在文件/etc/ld.so.conf
列出的目录列表(共享发现(这是允许不同版本的相同库在同一个系统中共存有用的东西),通常映射索引这是静态的信息,以加速加载库的过程,并在系统的每个引导生成)。如果共享链接时(这种机制不使用ld
,但只加载在节目开始时间库)被发现有soname
,那么soname
搜索在/etc/ld.so.cache
发现有可能成为最终文件加载。这个缓存是建立在系统每次开机,所以你不必应付这一点,但只有当你不想重新启动,在安装系统使用一个新的图书馆。需要注意的是共享对象必须给予soname
s这个工作是很重要的,而且在文件/etc/ld.so.conf
目录列表是用于搜索文件的唯一目录。这意味着,对于一个标准库是可用的,你需要把它放在这个目录中的一个(或目录添加到/etc/ld.so.conf
列表),然后执行ldconfig -a
重建缓存,让它包括下文件的引用该soname
。
另一种方法是添加到搜索列表中的PATH变量的形式放置一个列表。该变量是LD_LIBRARY_PATH
所以,如果你有在${HOME}/libs
共享对象,您可以将此行添加到您的.profile
:
export LD_LIBRARY_PATH=${HOME}/libs
要么
setenv LD_LIBRARY_PATH ${HOME}/libs
这允许您的图书馆生活中的标准目录之外,但三思而后行,因为这是一种较有效的方式来加载一个文件(因为它涉及处理目录去寻找最后的共享对象的列表,而此前的做法是直接的,你要求的文件匹配soname
要求提供ld.so.xxx
,只有一个搜索,只有一步)dlopen(3)
,让您加载共享对象和内部调用任何事情之前做一些家政服务。在DL库允许你搜索共享可执行符号,然后决定,如果你把它解释为数据或跳转的目标。 dlopen()
只是打开并加载到虚拟地址空间的共享对象。它解决的依赖关系(如果要求),并且是更灵活的方式(但它也是不透明的)来加载未知代码执行。这是正常的插件的工作方式。你决定在配置文件中,或什么动态加载,然后加载它。该方案不必事先知道你正在处理什么用的符号表,你可以自由地实现任何你正在加载的模块中想要的。所有这些方法与ELF二进制文件的工作,让你有很大的自由,但也由很多复杂的。
在我从你的编译看出:
-l
在编译命令只,如果您链接一个可执行的库时,才需要,不要把库中的编译阶段。lib<name>.so
(结尾没有版本信息),所以这意味着你通常会发现三个名字对于一个标准库(让我用数学库-lm
为一个例子):
/usr/lib/libm.so.3.2.8#这是与库内容的ELF文件。 /usr/lib/libm.so.3 - > libm.so.3.2.8#这是SONAME用于创建库。 /usr/lib/libm.so - > libm.so.3#这是实际的文件中的LD(1),使用时-lm方案的搜索。这些链接必须创建,因为系统一般不会。这是共享库的安装过程的一部分。该soname
链接可以有不同的版本库,并检测它们中的哪一个会在运行时使用(全部都必须是兼容的,所以你可以互换,当你做出一个不兼容的修改,那么你必须改变的soname,所以系统没有得到装载混淆)
重要的是要知道,ld(1)
程序只选择一个库,如果它被称为lib<name>.so
,没有版本信息是非常重要的。事实上,lib<name>.so
编译器首先searchs,然后lib<name>.a
,然后抱怨。
它是把-L
地方搜索将在链结参数使用这些目录中的任何-l
选项前的库非常重要。
你只需要运行ldconfig -a
,如果你不打算使用LD_LIBRARY_PATH
机制在系统目录中安装库。 (该机制不为root帐户的工作,原因是显而易见的:))
期待这一附加意见给予一些光的过程。