【问题标题】:libpthread.so.0: error adding symbols: DSO missing from command linelibpthread.so.0:添加符号时出错:命令行中缺少 DSO
【发布时间】:2013-11-22 23:51:11
【问题描述】:

我在编译openvswitch-1.5.0时遇到如下编译错误:

 gcc -Wstrict-prototypes -Wall -Wno-sign-compare -Wpointer-arith
     -Wdeclaration-after-statement -Wformat-security -Wswitch-enum -Wunused-parameter -Wstrict-aliasing -Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-field-initializers -Wno-override-init  -g -O2 -export-dynamic ***-lpthread***  -o utilities/ovs-dpctl utilities/ovs-dpctl.o lib/libopenvswitch.a
 /home/jyyoo/src/dpdk/build/lib/librte_eal.a
 /home/jyyoo/src/dpdk/build/lib/libethdev.a
 /home/jyyoo/src/dpdk/build/lib/librte_cmdline.a
 /home/jyyoo/src/dpdk/build/lib/librte_hash.a
 /home/jyyoo/src/dpdk/build/lib/librte_lpm.a
 /home/jyyoo/src/dpdk/build/lib/librte_mbuf.a
 /home/jyyoo/src/dpdk/build/lib/librte_ring.a
 /home/jyyoo/src/dpdk/build/lib/librte_mempool.a
 /home/jyyoo/src/dpdk/build/lib/librte_malloc.a -lrt -lm 
     /usr/bin/ld: /home/jyyoo/src/dpdk/build/lib/librte_eal.a(eal.o): undefined reference
     to symbol 'pthread_create@@GLIBC_2.2.5'
     /lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from 
     command line

如果我尝试查看libpthread 的符号,它看起来不错。

$ readelf -s /lib/x86_64-linux-gnu/libpthread.so.0 | grep pthread_create
   199: 0000000000008220  2814 FUNC    GLOBAL DEFAULT   13 pthread_create@@GLIBC_2.2.5
   173: 0000000000008220  2814 FUNC    LOCAL  DEFAULT   13 __pthread_create_2_1
   462: 0000000000008220  2814 FUNC    GLOBAL DEFAULT   13 pthread_create@@GLIBC_2.2

您能给出任何提示或指点吗?

【问题讨论】:

标签: gcc compiler-errors linker undefined-reference


【解决方案1】:

您应该在命令行正在编译的目标文件之后提及该库:

 gcc -Wstrict-prototypes -Wall -Wno-sign-compare -Wpointer-arith -Wdeclaration-after-statement -Wformat-security -Wswitch-enum -Wunused-parameter -Wstrict-aliasing -Wbad-function-cast -Wcast-align -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-field-initializers -Wno-override-init \
     -g -O2 -export-dynamic -o utilities/ovs-dpctl utilities/ovs-dpctl.o \
     lib/libopenvswitch.a \
     /home/jyyoo/src/dpdk/build/lib/librte_eal.a /home/jyyoo/src/dpdk/build/lib/libethdev.a /home/jyyoo/src/dpdk/build/lib/librte_cmdline.a /home/jyyoo/src/dpdk/build/lib/librte_hash.a /home/jyyoo/src/dpdk/build/lib/librte_lpm.a /home/jyyoo/src/dpdk/build/lib/librte_mbuf.a /home/jyyoo/src/dpdk/build/lib/librte_ring.a /home/jyyoo/src/dpdk/build/lib/librte_mempool.a /home/jyyoo/src/dpdk/build/lib/librte_malloc.a \
     -lrt -lm -lpthread 

说明:链接取决于模块的顺序。首先请求符号,然后从包含它们的库中链接。所以你必须指定首先使用库的模块,然后是它们之后的库。像这样:

gcc x.o y.o z.o -la -lb -lc

此外,如果存在循环依赖,您应该在命令行上多次指定同一个库。所以如果libb 需要来自libc 的符号,而libc 需要来自libb 的符号,命令行应该是:

gcc x.o y.o z.o -la -lb -lc -lb

【讨论】:

  • 我认为你可以为循环依赖做-Wl,--start-group -la -lb- -lc -Wl,--end-group
  • 请注意,这也适用于源文件——它们应该列在库之前。您可以认为生成的目标文件代替命令行中的源文件,并应用与上述相同的顺序。
【解决方案2】:

错误信息取决于发行版/编译器版本:

Ubuntu 俏皮:

/usr/bin/ld: /mnt/root/ffmpeg-2.1.1//libavformat/libavformat.a(http.o): undefined reference to symbol 'inflateInit2_'
/lib/x86_64-linux-gnu/libz.so.1: error adding symbols: DSO missing from command line

Ubuntu Raring:(更多信息)

/usr/bin/ld: note: 'uncompress' is defined in DSO /lib/x86_64-linux-gnu/libz.so.1 so try adding it to the linker command line

解决方案:在链接阶段,您可能在编译步骤中缺少库。就我而言,我在 makefile / GCC 标志中添加了“-lz”。

背景: DSO 是动态共享对象或共享库。

【讨论】:

  • 我使用此解决方案构建了另一个项目,该项目通过将 -lz 添加到 LDFLAGS 来给出相同的错误,并且效果很好。谢谢!
  • 错误仍然存​​在:/usr/bin/ld: gaSim.o: undefined reference to symbol 'pthread_create@@GLIBC_2.1' /lib/i386-linux-gnu/libpthread.so .0:添加符号时出错:命令行中缺少 DSO
  • 部分解决了添加“-lpthread”的问题,但现在它向我显示:gaSim.c:(.text+0x11d6): undefined reference to `glewInit'
  • @Aerox:对于glewInit,你需要-lGLEW
【解决方案3】:

背景

当链接器通过正常搜索找不到所需符号但该符号在直接指定的动态库的依赖项之一中可用时,将显示DSO missing from command line 消息。

过去,链接器认为指定语言的依赖项中的符号可用。但是在后来的一些版本中,这种情况发生了变化,现在链接器对可用的内容进行了更严格的查看。因此,该消息旨在帮助实现这一转变。

怎么办?

如果您是软件的维护者

您应该通过确保在链接器命令行上直接指定满足所需符号所需的所有库来解决此问题。还要记住,顺序通常很重要。

如果您只是想编译软件

作为一种解决方法,可以使用选项-Wl,--copy-dt-needed-entries 切换回更宽松的可用符号视图。

将其注入构建的常用方法是在运行 configure 之前导出 LDFLAGS 或类似这样:

export LDFLAGS="-Wl,--copy-dt-needed-entries"

有时将LDFLAGS="-Wl,--copy-dt-needed-entries" 直接传递给make 也可能有效。

【讨论】:

  • gcc 版本 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1) 无法识别此标志。
  • 这不是 gcc 选项,因此要么您缺少 -Wl, 位,要么您的链接器不支持此选项。你用的是什么链接器?这个答案假定经典的 binutils 链接器(ld.bfd)。 binutils 黄金链接器(ld.gold)将--copy-dt-needed-entries 记录为“不支持”。因此,如果您将其(或任何其他不支持此选项的链接器)作为默认设置,您可能需要遵循维护者部分或切换到经典 ld 进行链接。我认为您可以为此使用-fuse-ld=ld.bfd
【解决方案4】:

我发现了另一个案例,因此我认为你们都错了。

这就是我所拥有的:

/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: eggtrayicon.o: undefined reference to symbol 'XFlush'
/usr/lib64/libX11.so.6: error adding symbols: DSO missing from command line

问题在于命令行不包含-lX11 - 尽管应该将 libX11.so 作为依赖项添加,因为参数中还有 GTK 和 GNOME 库。

所以,对我来说,唯一的解释是这条消息可能是为了帮助您,但它没有正确地做到这一点。这可能很简单:提供符号的库没有添加到命令行。

请注意关于 POSIX 链接的三个重要规则:

  • 动态库已定义依赖项,因此只能以任何顺序提供顶级依赖项中的库(尽管在静态库之后)
  • 静态库只有未定义的符号 - 您可以了解它们的依赖关系并在命令行中提供所有这些符号
  • 静态库中的顺序始终是:请求者优先提供者后接。否则你会得到未定义的符号消息,就像你忘记将库添加到命令行时一样
  • 当您使用-l<name> 指定库时,您永远不知道它是使用lib<name>.so 还是lib<name>.a。动态库是首选,如果找到的话,静态库只能由编译器选项强制执行——仅此而已。而你有没有上述问题,就看你是静态库还是动态库了
  • 嗯,有时动态库中可能缺少依赖项:D

【讨论】:

  • 它不仅旨在帮助您,而且链接器需要它来解析有问题的名称。该错误是完全有效的。如果编译器决定让它通过,你只会得到一个段错误来访问二进制运行时中不存在的东西。
  • 补充一下,有可能在不同的平台上,源码编译的不一样;在一个系统上链接的内容可能不会在另一个系统上链接。通常情况并非如此,但这是 100% 合理的。
  • 问题不在于它无效,而在于它对找出问题的原因并没有太大帮助。
【解决方案5】:

我也遇到了同样的问题。我不知道为什么,我只是在编译器中添加了-lpthread 选项,一切正常。

旧:

$ g++ -rdynamic -m64 -fPIE -pie  -o /tmp/node/out/Release/mksnapshot ...*.o *.a -ldl -lrt

出现以下错误。如果我将-lpthread 选项附加到上面的命令,那么OK。

/usr/bin/ld: /tmp/node/out/Release/obj.host/v8_libbase/deps/v8/src/base/platform/condition-variable.o: undefined reference to symbol 'pthread_condattr_setclock@@GLIBC_2.3.3'
//lib/x86_64-linux-gnu/libpthread.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status

【讨论】:

  • 这对我有用;我必须在执行链接的 makefile 中的 g++ 命令中添加第二个“冗余”-lpthread。 (它已经在 makefile 的 LIBS 列表中出现过一次。)我还在 makefile 的 LDFLAGS 定义中添加了“-L /lib/x86_64-linux-gnu”。
【解决方案6】:

我发现我有同样的错误。我正在用 lapack 和 blas 编译代码。当我切换调用这两个库的顺序时,错误就消失了。

“LAPACK_LIB = -llapack -lblas”在哪里工作 “LAPACK_LIB = -lblas -llapack”给出了上述错误。

【讨论】:

  • 我在 cmake 定义的项目中收到此错误...那么 Cmake 中是否存在导致链接器顺序错误的错误?
  • 回复@peterkarasev:尝试使用find_package(Threads)target_link_libraries( ... ${CMAKE_THREAD_LIBS_INIT})
【解决方案7】:

我发现有时链接器抱怨的库不是导致问题的库。可能有一种聪明的方法可以找出问题所在,但这就是我所做的:

  • 注释掉链接命令中的所有链接库。
  • 清除所有 .o、.so 等文件(通常 make clean 就足够了,但您可能需要运行递归 find + rm 或类似的东西)。
  • 取消注释链接命令中的库,一次一个,并根据需要重新排列顺序。

@peter karasev:我在 CentOS7 上的 gcc 4.8.2 cmake 项目中遇到了同样的问题。 “target_link_libraries”部分中库的顺序很重要。我猜 cmake 只是将列表按原样传递给链接器,即它不会尝试找出正确的顺序。这是合理的 - 当您考虑它时,cmake 在链接成功完成之前无法知道正确的顺序是什么。

【讨论】:

    【解决方案8】:

    如果你使用 CMake,有一些方法可以解决它:

    方案一:最优雅的一种

    add_executable(...)
    target_include_directories(...)
    target_link_libraries(target_name pthread)
    

    解决方案 2: 使用 CMake find_package

    find_package(Threads REQUIRED) # this will generate the flag for CMAKE_THREAD_LIBS_INIT
    
    add_executable(...)
    target_include_directories(...)
    target_link_libraries(target_name ${CMAKE_THREAD_LIBS_INIT})
    

    解决方案 3: 更改 CMake 标志

    # e.g. with C++ 17, change to other version if you need
    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -pthread")
    

    【讨论】:

      【解决方案9】:

      请加:CFLAGS="-lrt"LDFLAGS="-lrt"

      【讨论】:

        【解决方案10】:

        在处理使用数学函数的代码时,您还应该链接它们。 在我的情况下,我在编译时提供了以下内容,这对我有用。

        mpicc -o testname testname.c -lm
        

        【讨论】:

          【解决方案11】:

          当我使用distcc 制作我的 c++ 项目时,我也遇到了同样的问题; 最后我用export CXX="distcc g++"解决了这个问题。

          【讨论】:

            【解决方案12】:

            尝试在 Makefile 的库列表末尾添加-pthread

            它对我有用。

            【讨论】:

              【解决方案13】:

              如果您使用 cmake 并使用 pthreads,请尝试添加以下行

              find_package(Threads)
              target_link_libraries(${CMAKE_THREAD_LIBS_INIT})
              

              【讨论】:

                【解决方案14】:

                我在安装 HPCC 基准测试(包括 HPL 和其他一些基准测试)时也发生了同样的事情。我在构建脚本的编译器标志中添加了-lm,然后编译成功。

                【讨论】:

                • 这既不能回答这个特定问题,也不能为一系列类似问题提供一般答案。这是对另一个问题的高度本地化的答案。
                【解决方案15】:

                如果使用g++,请确保您没有运行gcc

                【讨论】:

                • 为什么?你能详细说明一下吗?
                • @IvanIvković 好吧,gcc 是 C 编译器,g++ 是 C++ 编译器。虽然 C++ 可以编译 C,但 gcc 不能编译 C++。
                【解决方案16】:

                改为使用 g++ 编译。它在我从 gcc 切换到 g++ 的情况下有效。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2015-09-18
                  • 2018-02-12
                  • 2015-11-02
                  • 1970-01-01
                  • 2017-05-13
                  • 2020-01-12
                  • 1970-01-01
                  • 2021-10-07
                  相关资源
                  最近更新 更多