ldd 说编译成功完成后找不到库

Posted

技术标签:

【中文标题】ldd 说编译成功完成后找不到库【英文标题】:ldd says library isn't found by compile completes successfully 【发布时间】:2013-05-02 18:51:45 【问题描述】:

我正在尝试编译项目。它编译成功。我的make 命令以0 的状态码退出,并且没有显示任何错误。

但是,该项目无法运行,当我运行 ldd -d <file> 时,它显示我有两个未找到的库。

>ldd -d output_file.so
    linux-gate.so.1 =>  (0xf77e0000)
    libvstdlib_srv.so => not found
    libtier0_srv.so => not found
    libm.so.6 => /lib/libm.so.6 (0xf7760000)
    libdl.so.2 => /lib/libdl.so.2 (0xf775b000)
    libc.so.6 => /lib/libc.so.6 (0xf75a9000)
    /lib/ld-linux.so.2 (0x46e4a000)
undefined symbol: pfVectorNormalize     (output_file.so)
undefined symbol: _Z12VectorAnglesRK6VectorR6QAngle     (output_file.so)
undefined symbol: pfSqrt       (output_file.so)
undefined symbol: __cxa_guard_acquire   (output_file.so)
undefined symbol: __cxa_guard_release   (output_file.so)
undefined symbol: _Z6ConMsgPKcz (output_file.so)
undefined symbol: Warning      (output_file.so)
undefined symbol: __dynamic_cast        (output_file.so)
undefined symbol: _Z11ConColorMsgRK5ColorPKcz   (output_file.so)
undefined symbol: Error (output_file.so)
undefined symbol: AssertValidStringPtr  (output_file.so)
undefined symbol: _AssertValidWritePtr  (output_file.so)
undefined symbol: _AssertValidReadPtr   (output_file.so)
undefined symbol: _ZTVN10__cxxabiv121__vmi_class_type_infoE     (output_file.so)
undefined symbol: _ZTVN10__cxxabiv120__si_class_type_infoE      (output_file.so)
undefined symbol: _ZTVN10__cxxabiv117__class_type_infoE (output_file.so)
undefined symbol: __gxx_personality_v0  (output_file.so)

这两个库被设置为指向文件实际位置的符号链接:

...
lrwxrwxrwx 1 Andy Andy    62 May  2 12:30 libtier0_srv.so -> /home/dev/sdks/hl2sdk-ob-valve/lib/linux/libtier0_srv.so
lrwxrwxrwx 1 Andy Andy    64 May  2 12:30 libvstdlib_srv.so -> /home/dev/sdks/hl2sdk-ob-valve/lib/linux/libvstdlib_srv.so
-rw-r--r-- 1 Andy Andy  5444 May  2 11:53 Makefile
...

正在运行的gcc 命令是

gcc -I/home/dev/sdks/hl2sdk-ob-valve/public/game/server -I. -I.. -ICEntity -Isdk -I/home/dev/project1/hl2sdk-ob-valve/public -I/home/dev/sdks/hl2sdk-ob-valve/public/engine -I/home/dev/sdks/hl2sdk-ob-valve/public/tier0 -I/home/dev/sdks/hl2sdk-ob-valve/public/tier1 -I/home/dev/sdks/hl2sdk-ob-valve/public/mathlib -I/home/dev/project1/mmsource-central/core -I/home/dev/project1/mmsource-central/core/sourcehook -I/home/dev/project1/sourcemod-central/public -I/home/dev/project1/sourcemod-central/public/sourcepawn -I/home/dev/project1/sourcemod-central/core project1_output/sdk/smsdk_ext.o project1_output/extension.o project1_output/CTrackingProjectile.o project1_output/CSentryRocket.o project1_output/CProjectileRocket.o project1_output/CProjectileArrow.o project1_output/CProjectileFlare.o project1_output/CProjectilePipe.o project1_output/CProjectileSyringe.o project1_output/CEntity/CEntity.o project1_output/CEntity/CEntityManager.o project1_output/CEntity/CPlayer.o /home/dev/project1/hl2sdk-ob-valve/lib/linux/tier1_i486.a libvstdlib_srv.so libtier0_srv.so -m32 -lm -ldl -static-libgcc -shared -o project1_output/output_file.so

我的问题是: 1.)为什么即使它们是符号链接的,也找不到这两个库? 2.) 未定义的符号是mathlib 包的一部分,该包包含在gcc 命令中。 -I/home/dev/sdks/hl2sdk-ob-valve/public/mathlib 尽管包含在内,为什么这些是未定义的?

c++ 不是我选择的语言,我对 Makefile 有足够的了解是危险的,但并不能真正解决任何问题,所以如果信息不足,我深表歉意。我可以根据需要提供更多。

【问题讨论】:

【参考方案1】:

我只是偶然发现了这一点,遇到了同样的问题,但解决方案不同。

使用 LD_LIBRARY_PATH 实际上会起作用。如果它是用于您自己在构建环境中的测试,那很好,但除了这种情况外,您应该尽量避免它。这是一篇比我了解更多的人的文章,为什么 LD_LIBRARY_PATH 不好:

http://xahlee.info/UnixResource_dir/_/ldpath.html

发生的事情是,从设置 LD_LIBRARY_PATH 的事实也可以看出,在运行时,您的程序找不到共享库libtier0_srv.so。您应该将目录添加到运行时库搜索路径,而不是为所有程序全局设置变量以首先查看/home/dev/sdks/hl2sdk-ob-valve/lib/linux/。你通过传递选项来做到这一点

-rpath /home/dev/sdks/hl2sdk-ob-valve/lib/linux/

ld,链接器。您可以使用您发布的gcc 命令执行此操作,方法是添加选项

-Wl,-rpath,/home/dev/sdks/hl2sdk-ob-valve/lib/linux/,

告诉gcc 将上面的选项传递给ld

【讨论】:

是的,这比设置环境变量的“大锤”方法要好。【参考方案2】:

库文件是共享对象,这意味着它们直到运行时才会被解析。为了让 ldd 找到它们(假设 Linux 或其他 Unix 变体),您需要将库的路径添加到您的 LD_LIBRARY_PATH (还有另一个路径 env 可以使用,但我现在想不起来)然后ldd 应该能够找到该库。

【讨论】:

【参考方案3】:

正如@diverscuba23 提到的,您需要将您的库所在的路径添加到您的LD_LIBRARY_PATH。一种简单且非永久性的方法是在运行程序时指定它,如下所示:

LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./yourProgram

在这种情况下,库需要位于运行程序的同一目录中。

更笼统地说:

LD_LIBRARY_PATH=<PATH_TO_YOUR_LIBRARY>:$LD_LIBRARY_PATH ./yourProgram

【讨论】:

【参考方案4】:

您的输出文件是*.so,一个共享对象库文件;来自另一个共享库的符号被引用但不被导入(静态链接)。 -- 使用 nm 查看符号(已定义或未定义) ldd 将搜索 ldconfig 系统缓存并且 /etc/ld.so.conf 通知搜索位置 -- 您可以使用此功能添加库路径(例如:/opt/valve/lib)以与所有用户共享 -- 您的编译命令包括您的主目录中的共享库档案。 ---- ldd 不会正常搜索主目录,使用 LD_LIBRARY_PATH ------ 但您必须列出目录的完整路径 你说你“包含”了 mathlib,我认为这是 -I (对于头文件) -- 但库目录是 -L $MY_PATH/mathlib/lib 和 -l vstdlib_srv 链接它 ----您包含库而不是链接它 -- 在 C/C++ 中,include 的含义与其他语言不同:use/require/import/include ---- 这声明了符号、类型和参数列表;但不是实施 -I 提供*.h、*.hh、*.hpp 的路径;这是声明符号的文本文件 -L 提供查找库的路径(以及链接 exec 的静态库) -l 链接包含实现的库 -rpath 为库提供运行时路径以链接到 exec 并将其编译到 exec ---- 这将绑定应用程序及其库位置(例如 -rpath ../lib,当应用程序在 bin 中时)

【讨论】:

以上是关于ldd 说编译成功完成后找不到库的主要内容,如果未能解决你的问题,请参考以下文章

编译成功后找不到openni2库

使用外部库找不到入口点错误

Mac安装Scrapy教程及安装成功后找不到Scrapy解决

jar打包完成后提示找不到主类,高手看一下哪一步有问题?

Ionic 2:更新到 RC.0 后找不到名称“Promise”

Pyinstaller - 编译应用程序后找不到 libmagic