具体来说,我正在为应用程序使用cblas
。我创建了一个使用foo.so
作为子例程的cblas
,然后我dlopen('foo.so', RTLD_LAZY)
。
这是我用来编译的标志(删除了一些-I
标志):
g++-8 -std=c++17 -shared -O3 -xc++
-ffast-math -fPIC -fopenmp -lcblas - -o /mnt/xxx/python/test.so
这是我在dlopen()
上遇到的错误:
test.so: undefined symbol: cblas_dgemm
在这里我们看到cblas_dgemm
中包含了.so
。
root@cd872c4b85ff:/mnt/xxx/python# objdump -TC test.so | grep cblas
0000000000000000 D *UND* 0000000000000000 cblas_ddot
0000000000000000 D *UND* 0000000000000000 cblas_dsyrk
0000000000000000 D *UND* 0000000000000000 cblas_dgemm
0000000000000000 D *UND* 0000000000000000 cblas_dgemv
但是在ldd
中,它没有作为依赖项列出。
root@cd872c4b85ff:/mnt/xxx/python# ldd test.so
linux-vdso.so.1 (0x00007ffdbb3c4000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f43f23a7000)
libgomp.so.1 => /usr/lib/x86_64-linux-gnu/libgomp.so.1 (0x00007f43f2177000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f43f1f5f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f43f1b6e000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f43f17d0000)
/lib64/ld-linux-x86-64.so.2 (0x0000562eb733a000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f43f15cc000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f43f13ab000)
我进行了一次测试编译,结果表明已成功找到-lcblas
:
g++-8 -lcblas -Wl,--verbose | grep blas
attempt to open /usr/lib/gcc/x86_64-linux-gnu/8/libcblas.so failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/8/libcblas.a failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcblas.so succeeded
-lcblas (/usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/libcblas.so)
/usr/lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
重要的一点是,如果我将环境变量设置为LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libcblas.so
,则可执行文件将正确运行。但是,这显然不是使可执行文件正常工作的正确方法。 -Wl,rpath=
也不是正确的方式,因为cblas将驻留在不同的目录中(即,在OS X上它位于/usr/lib/libcblas.so
中,而在ubuntu中它位于/usr/lib/x86_64-linux-gnu/libcblas.so
中,我猜测将会有更多无法预测的位置。
可能是什么原因?我没有正确链接吗?动态链接器是否由于某种原因找不到符号?
由于部分信息已被删除,请让我知道是否需要任何信息,并将其添加到上面的信息中。谢谢。
编辑:符号确实存在于libcblas.so
中:
root@3841c2760800:/usr/lib/x86_64-linux-gnu# nm -D libcblas.so | grep cblas_ddot
000000000000a0a0 T cblas_ddot
root@3841c2760800:/usr/lib/x86_64-linux-gnu# nm -D libcblas.so | grep cblas_dgemm
0000000000005790 T cblas_dgemm
root@3841c2760800:/usr/lib/x86_64-linux-gnu# nm -D libcblas.so | grep cblas_dgemv
00000000000077f0 T cblas_dgemv
root@3841c2760800:/usr/lib/x86_64-linux-gnu# nm -D libcblas.so | grep cblas_dsyrk
00000000000065f0 T cblas_dsyrk
编辑:
我相信依赖图看起来像:
main --(dlopens)--> test.so
--(includes)--> header-only linear algebra library
--(calls cblas subroutine)--> /usr/lib/x86.../libcblas.so
答案 0 :(得分:0)
所以-这是因为我的链接的顺序。我要做的是将C ++文件(或字符串)流式传输到此g ++编译过程中。要进行流式传输,可以这样做:
ifelse
g++ ... -xc++ - ...
告诉-xc++
它正在接收c ++文件(必须),而g++
是文件字符串的占位符。在我的汇编中,我有:
-
这意味着它实际上未正确链接(linker_flags必须在文件名之后)。
我知道排序很重要,但是在这种情况下,当我在文件中流式传输时,我忘记了这一原理,这就是为什么未定义符号的原因。