【问题标题】:undefined symbols remain, but shared libraries compile and seem to function properly未定义的符号仍然存在,但共享库可以编译并且似乎可以正常运行
【发布时间】:2020-09-20 12:32:55
【问题描述】:

我的目标是从 SUNDIALS 2.7.0 构建共享库 - 这些是用 C 编写的常微分方程的求解器。

我已经下载了源代码,并按照安装指南进行操作:

  1. 运行 Cmake(带 GUI),检查选项“CVODE”(这是可用的求解器之一 - 我想要的唯一一个),“构建共享库”和“使用通用(std- c) 数学库”并生成 Makefile。
  2. 在 Linux 控制台中运行 make && make install 并生成我的共享库,并且完全没有错误消息。 这是输出:
$ make
Scanning dependencies of target sundials_nvecserial_shared
[  3%] Building C object src/nvec_ser/CMakeFiles/sundials_nvecserial_shared.dir/nvector_serial.c.o
[  7%] Building C object src/nvec_ser/CMakeFiles/sundials_nvecserial_shared.dir/__/sundials/sundials_math.c.o
[ 11%] Linking C shared library libsundials_nvecserial.so
[ 11%] Built target sundials_nvecserial_shared
Scanning dependencies of target sundials_cvode_shared
[ 14%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode.c.o
[ 18%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_io.c.o
[ 22%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_direct.c.o
[ 25%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_band.c.o
[ 29%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_dense.c.o
[ 33%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_diag.c.o
[ 37%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_spils.c.o
[ 40%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_spbcgs.c.o
[ 44%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_spgmr.c.o
[ 48%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_sptfqmr.c.o
[ 51%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_sparse.c.o
[ 55%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_bandpre.c.o
[ 59%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/cvode_bbdpre.c.o
[ 62%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_nvector.c.o
[ 66%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_math.c.o
[ 70%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_direct.c.o
[ 74%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_band.c.o
[ 77%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_dense.c.o
[ 81%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_iterative.c.o
[ 85%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_sparse.c.o
[ 88%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_spbcgs.c.o
[ 92%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_spgmr.c.o
[ 96%] Building C object src/cvode/CMakeFiles/sundials_cvode_shared.dir/__/sundials/sundials_sptfqmr.c.o
[100%] Linking C shared library libsundials_cvode.so
[100%] Built target sundials_cvode_shared
$ sudo make install
[ 11%] Built target sundials_nvecserial_shared
[100%] Built target sundials_cvode_shared
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/include/sundials/sundials_config.h

Install shared components

-- Installing: /usr/local/include/sundials/sundials_band.h
-- Installing: /usr/local/include/sundials/sundials_dense.h
-- Installing: /usr/local/include/sundials/sundials_direct.h
-- Installing: /usr/local/include/sundials/sundials_iterative.h
-- Installing: /usr/local/include/sundials/sundials_math.h
-- Installing: /usr/local/include/sundials/sundials_nvector.h
-- Installing: /usr/local/include/sundials/sundials_fnvector.h
-- Installing: /usr/local/include/sundials/sundials_pcg.h
-- Installing: /usr/local/include/sundials/sundials_sparse.h
-- Installing: /usr/local/include/sundials/sundials_spbcgs.h
-- Installing: /usr/local/include/sundials/sundials_spfgmr.h
-- Installing: /usr/local/include/sundials/sundials_spgmr.h
-- Installing: /usr/local/include/sundials/sundials_sptfqmr.h
-- Installing: /usr/local/include/sundials/sundials_types.h

Install NVECTOR_SERIAL

-- Installing: /usr/local/lib/libsundials_nvecserial.so.2.7.0
-- Installing: /usr/local/lib/libsundials_nvecserial.so.2
-- Installing: /usr/local/lib/libsundials_nvecserial.so
-- Installing: /usr/local/include/nvector/nvector_serial.h

Install CVODE

-- Installing: /usr/local/lib/libsundials_cvode.so.2.9.0
-- Installing: /usr/local/lib/libsundials_cvode.so.2
-- Installing: /usr/local/lib/libsundials_cvode.so
-- Installing: /usr/local/include/cvode/cvode_band.h
-- Installing: /usr/local/include/cvode/cvode_bandpre.h
-- Installing: /usr/local/include/cvode/cvode_bbdpre.h
-- Installing: /usr/local/include/cvode/cvode_dense.h
-- Installing: /usr/local/include/cvode/cvode_diag.h
-- Installing: /usr/local/include/cvode/cvode_direct.h
-- Installing: /usr/local/include/cvode/cvode.h
-- Installing: /usr/local/include/cvode/cvode_sparse.h
-- Installing: /usr/local/include/cvode/cvode_spbcgs.h
-- Installing: /usr/local/include/cvode/cvode_spgmr.h
-- Installing: /usr/local/include/cvode/cvode_spils.h
-- Installing: /usr/local/include/cvode/cvode_sptfqmr.h
-- Installing: /usr/local/include/cvode/cvode_impl.h

这些共享库似乎在我需要它们的项目中正常运行 - 常微分方程正在得到求解,并且输出似乎与独立于这些的其他求解器相同。

但是有一个很大的但是:): 检查生成的共享库中的未定义符号向我展示了标准函数的简短列表 - 以下是共享库的输出:

$ nm -D --undefined-only libsundials_cvode.so.2.9.0
                 w __cxa_finalize
                 U exp
                 U fprintf
                 U fputc
                 U free
                 U fwrite
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U malloc
                 U memset
                 U pow
                 U printf
                 U putchar
                 U realloc
                 U sqrt
                 U __stack_chk_fail
                 U stderr
                 U vsprintf

$ nm -D --undefined-only libsundials_nvecserial.so.2.7.0
                 w __cxa_finalize
                 U exp
                 U free
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 U malloc
                 U pow
                 U printf
                 U putchar
                 U sqrt

打印共享库依赖项给出:

$ ldd -r libsundials_nvecserial.so
    linux-vdso.so.1 (0x00007ffd657a5000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fecd8155000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fecd874c000)
undefined symbol: exp   (./libsundials_nvecserial.so)
undefined symbol: pow   (./libsundials_nvecserial.so)
undefined symbol: sqrt  (./libsundials_nvecserial.so)

$ ldd -r libsundials_cvode.so        linux-vdso.so.1 (0x00007ffe6a1ff000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6cd55ac000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f6cd5bc8000)
undefined symbol: exp   (./libsundials_cvode.so)
undefined symbol: pow   (./libsundials_cvode.so)
undefined symbol: sqrt  (./libsundials_cvode.so)

例如,像 SUNRsqrt 这样的函数是在 sqrt 上定义的,并且在实际数值计算中非常重要——这一事实以及未定义符号的存在让我感到困惑和担心共享库的可靠性。

在生成共享库之前,我已经为环境变量 LD_LIBRARY_PATH 设置了所有适当的路径(顺便说一下,它之前是空的):

$ export LD_LIBRARY_PATH="/usr/lib:/usr/lib/x86_64-linux-gnu:/usr/lib/gcc/x86_64-linux-gnu"
$ echo $LD_LIBRARY_PATH
/usr/lib:/usr/lib/x86_64-linux-gnu:/usr/lib/gcc/x86_64-linux-gnu

例如,C 标准库 libc.so 和 C 数学库 libm.so 存储在 /usr/lib/x86_64-linux- gnu,而 GNU 事务性内存库 libitim.so 存储在 /usr/lib/gcc/x86_64-linux-gnu(虽然是 1.0.其中 0 个也在 /usr/lib/x86_64-linux-gnu)。

操作系统、Cmake、GNU C 编译器和 GNU Make 的版本:

$ lsb_release -d
Description:    Ubuntu 18.04.5 LTS
$ cmake --version
cmake version 3.18.2
$ gcc --version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
$ make --version
GNU Make 4.1

任何评论将不胜感激。

附: 这种情况是完全可重现的,因为它是关于从 SUNDIALS 2.7.0 源代码(direct download link) 生成共享库并检查未定义符号的共享库。

【问题讨论】:

    标签: cmake shared-libraries undefined-symbol c-standard-library sundials


    【解决方案1】:

    您的 ldd 符号未定义,因为 so 文件是在没有 -lm 选项的情况下创建的。但是,只要最终的可执行文件与-lm 选项链接,它就不会成为问题。这是针对与-lm -lrt 链接的test_nvector_serial 之类的测试所做的。

    您可以通过使用make VERBOSE=1 以详细模式运行make 来查看所有这些。 如果您尝试在没有-lm 的情况下生成可执行文件,您将拥有collect2: error: ld returned 1 exit status 和链接器抱怨exp、pow 和sqrt。 如果您在创建so文件时添加-lm(我做到了)。你会看到:

    ldd -r ./src/nvec_ser/libsundials_nvecserial.so
        linux-vdso.so.1 (0x00007ffe1a769000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fe4a5c19000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe4a5828000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fe4a61bd000)
    

    在这种情况下,您可以在不使用-lm 的情况下链接您的测试(如果您愿意,只为自己做一些测试)。

    -lm 编译你的so 文件。您可以在输入正确的文件夹后使用-lm 选项运行命令行来执行此操作(仅用于测试目的)。另一种方法是修改生成so文件的CMakeLists.txt。以libsundials_nvecserial.so 为例,您可以通过在ADD_LIBRARY(sundials_nvecserial_shared SHARED ${nvecserial_SOURCES} ${shared_SOURCES}) 之后添加target_link_libraries(sundials_nvecserial_shared -lm) 来修改sundials-2.7.0/src/nvec_ser/CMakeLists.txt

    对于 LD_LIBRARY_PATH,如果您在标准位置查找,它不一定包含某些内容。链接器也使用 /etc/ld.so.cache 并在默认路径中搜索,除非您使用 -z nodeflib。您可以在https://man7.org/linux/man-pages/man8/ld.so.8.html找到更多详细信息

    对于nm -D。很正常,尝试编译一个hello worldgcc -o exec hello.c你会看到printf是未定义的。查看动态链接,以及用于构建 so 文件的 -rdynamic 选项。

    【讨论】:

    • 您能告诉我在创建 .so 文件时如何添加 '''-lm''' 吗?我尝试添加 CMAKE_C_FLAGS=-lm 或 CMAKE_SHARED_LINKER_FLAGS=-lm (使用 CMake GUI),但这导致在 source/.so 文件之前而不是之后添加 '''-lm''' (我在详细的 make-按照您的建议报告)。它对通过 '''nm -D --undefined-only''' 实用程序找到的其他未定义符号有帮助吗?
    • 我也尝试使用add_library()target_link_directories() 编辑CMakeFile.txt,但从未成功摆脱未定义的符号@yfelion
    • 您提供的详细信息解决了ldd 实用程序输出中未定义符号的问题。上帝保佑你,@yflelion
    猜你喜欢
    • 1970-01-01
    • 2019-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-22
    • 1970-01-01
    相关资源
    最近更新 更多