问题描述
我的目标是从SUNDIALS 2.7.0构建共享库-这些是用C编写的常微分方程的求解器。
我已经下载了源代码,并遵循了安装指南:
- 运行Cmake(带有GUI),选中选项“ CVODE” (这是可用的求解器之一,这是我想要的唯一解决方案),“构建共享库”和“使用通用(std- c)数学库”并生成了Makefile。
- 在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 )。
OS,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
任何评论将不胜感激。
P.S。 这种情况是完全可重现的,因为这完全是关于从SUNDIALS 2.7.0源(direct download link)生成共享库并检查未定义符号上的共享库。
解决方法
您使用ldd定义了未定义的符号,因为这样创建的文件没有使用-lm
选项。但是,只要将最终可执行文件与-lm
选项链接在一起,就不会有问题。对于与test_nvector_serial
链接的-lm -lrt
之类的测试,就是这样做的。
您可以通过使用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
,您可以通过在sundials-2.7.0/src/nvec_ser/CMakeLists.txt
之后添加target_link_libraries(sundials_nvecserial_shared -lm)
来修改ADD_LIBRARY(sundials_nvecserial_shared SHARED ${nvecserial_SOURCES} ${shared_SOURCES})
。
对于LD_LIBRARY_PATH,如果在标准位置查看,则不必包含某些内容。除非您使用-z nodeflib
,否则链接程序还将使用/etc/ld.so.cache并也在默认路径中进行搜索。您可以在https://man7.org/linux/man-pages/man8/ld.so.8.html
对于nm -D。正常,尝试编译一个hello world gcc -o exec hello.c
,您会发现printf是未定义的。看一下动态链接,以及用于构建so文件的-rdynamic
选项。