错误加载共享库:无法打开共享对象文件::在外部硬件

问题描述 投票:0回答:1

我目前正在开发一个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变量中找到,因此应用程序应该能够找到他们。

c++ gcc makefile shared-libraries ld
1个回答
0
投票

系统正常搜索在一组固定的目录的共享对象。您可以通过定义环境变量LD_LIBRARY_PATH并添加您安装的共享库的目录里解决这个问题。

或者,您可以添加这些库的一些标准库的目录和执行ldconfig -a更新共享库的高速缓存。

ldconfig(8),获取更多信息。

edit

有两种机制加载一个共享对象。

  • 第一个是正常的库加载机制,即指定了具有在开始执行时被加载,并暗示与共享对象链接你的可执行文件。这是你在你的Makefile做什么。您指定的共享可执行文件和ld.so.xxx共享对象(链接到你的应用程序时,你是动态链接的话)加载并遵循所有未解决的标识符,找到他们在虚拟地址空间的地方。该ld.so.xxx对象使用/etc/ld.so.cache文件,这只是一个哈希表提供的目录和共享的可执行文件被加载这种方式。这个文件是由所谓的soname到最后一个版本在文件/etc/ld.so.conf列出的目录列表(共享发现(这是允许不同版本的相同库在同一个系统中共存有用的东西),通常映射索引这是静态的信息,以加速加载库的过程,并在系统的每个引导生成)。如果共享链接时(这种机制不使用ld,但只加载在节目开始时间库)被发现有soname,那么soname搜索在/etc/ld.so.cache发现有可能成为最终文件加载。这个缓存是建立在系统每次开机,所以你不必应付这一点,但只有当你不想重新启动,在安装系统使用一个新的图书馆。需要注意的是共享对象必须给予sonames这个工作是很重要的,而且在文件/etc/ld.so.conf目录列表是用于搜索文件的唯一目录。这意味着,对于一个标准库是可用的,你需要把它放在这个目录中的一个(或目录添加到/etc/ld.so.conf列表),然后执行ldconfig -a重建缓存,让它包括下文件的引用该soname。 另一种方法是添加到搜索列表中的PATH变量的形式放置一个列表。该变量是LD_LIBRARY_PATH所以,如果你有在${HOME}/libs共享对象,您可以将此行添加到您的.profileexport LD_LIBRARY_PATH=${HOME}/libs 要么 setenv LD_LIBRARY_PATH ${HOME}/libs 这允许您的图书馆生活中的标准目录之外,但三思而后行,因为这是一种较有效的方式来加载一个文件(因为它涉及处理目录去寻找最后的共享对象的列表,而此前的做法是直接的,你要求的文件匹配soname要求提供ld.so.xxx,只有一个搜索,只有一步)
  • 二是使用的库函数dlopen(3),让您加载共享对象和内部调用任何事情之前做一些家政服务。在DL库允许你搜索共享可执行符号,然后决定,如果你把它解释为数据或跳转的目标。 dlopen()只是打开并加载到虚拟地址空间的共享对象。它解决的依赖关系(如果要求),并且是更灵活的方式(但它也是不透明的)来加载未知代码执行。这是正常的插件的工作方式。你决定在配置文件中,或什么动态加载,然后加载它。该方案不必事先知道你正在处理什么用的符号表,你可以自由地实现任何你正在加载的模块中想要的。

所有这些方法与ELF二进制文件的工作,让你有很大的自由,但也由很多复杂的。

more...

在我从你的编译看出:

  • 你包括-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帐户的工作,原因是显而易见的:))

期待这一附加意见给予一些光的过程。

© www.soinside.com 2019 - 2024. All rights reserved.