ldd说编译完成后找不到库

时间:2013-05-02 18:51:46

标签: c++ gcc makefile

我正在尝试编译项目。它编译成功。我的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++不是我选择的语言,我对Makefiles有足够的了解是危险的,但并不是真的要解决任何问题,所以如果这还不够,我会道歉。我可以根据需要提供更多。

4 个答案:

答案 0 :(得分:13)

我偶然发现了这个问题,遇到了同样的问题,但却有了不同的解决方案。

使用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

答案 1 :(得分:6)

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

答案 2 :(得分:2)

如@ diverscuba23所述,您需要将库所在的路径添加到LD_LIBRARY_PATH。一个简单而非永久的方法是在运行程序时指定它:

LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./yourProgram

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

更一般地说:

LD_LIBRARY_PATH=<PATH_TO_YOUR_LIBRARY>:$LD_LIBRARY_PATH ./yourProgram

答案 3 :(得分:0)

您的输出文件是* .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 ++中,包含的含义不同于其他语言:use / require / import / include
----声明符号,类型和参数列表;但不执行
-I提供* .h,*。hh,*。hpp的路径;是声明符号的文本文件
-L提供查找库的路径(以及用于链接exec的静态库)
-l链接包含实现的库
-rpath为lib提供运行时路径以链接到exec并将其编译为exec
----这将绑定应用程序及其库位置(例如,在应用程序位于bin中时,示例-rpath ../ lib)