Linux 上的共享库不包含对其依赖项之一的引用
Shared library on Linux does not contain reference to one of its dependencies
(这个问题涉及 Java JNI,但我不认为问题实际上出在 JNI 或 Java)
我正在执行这条命令:
cc -shared -fpic -L. -lcpdf -I$JAVA_HOME/include I$JAVA_HOME/include/linux jcpdfwrapper.c -o libjcpdf.so
也就是说我正在构建共享库 libjcpdf.so
,它需要 libcpdf.so
的函数,所以应该依赖它。
在 Windows (MinGW) 和 MacOS 上,新的共享库 (jcpdf) 清楚地链接到给定的共享库 (cpdf):
WINDOWS:
$ ldd jcpdf.dll
ntdll.dll => /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffe875f0000)
KERNEL32.DLL => /cygdrive/c/WINDOWS/System32/KERNEL32.DLL (0x7ffe86400000)
KERNELBASE.dll => /cygdrive/c/WINDOWS/System32/KERNELBASE.dll (0x7ffe851f0000)
msvcrt.dll => /cygdrive/c/WINDOWS/System32/msvcrt.dll (0x7ffe87120000)
libcpdf.dll => /home/JohnWhitington/jcpdf/libcpdf.dll (0x3743f0000)
WS2_32.dll => /cygdrive/c/WINDOWS/System32/WS2_32.dll (0x7ffe870b0000)
RPCRT4.dll => /cygdrive/c/WINDOWS/System32/RPCRT4.dll (0x7ffe87480000)
VERSION.dll => /cygdrive/c/WINDOWS/SYSTEM32/VERSION.dll (0x7ffe7d270000)
OS X:
$ otool -L libjcpdf.dylib
libjcpdf.dylib:
libjcpdf.dylib (compatibility version 0.0.0, current version 0.0.0)
libcpdf.so (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.100.3)
但是,在 Linux 上,我们在 libjcpdf.so 中没有对 libcpdf.so 的引用:
$ ldd libjcpdf.so
linux-vds0,30,1 => (60x00007fc40b13000)
libc.so,6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc1fb2af000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe1fba8f000)
所以发生的事情是,虽然从主 Java 程序 System.LoadLibrary("jcpdf")
成功,但任何使用该库的尝试都会给出:
java: symbol lookup error: /home/john/jcpdf/libjcpdf.so: undefined symbol: cpdf_startup
整个程序在 MacOS 和 Windows 上运行良好。
如何告诉 cc
让 libjcpdf.so
实际上依赖于 libcpdf.so
?
您的 cc
版本(或它使用的 link 编辑器)似乎默认为 -Wl,--as-neeeded
。在这种情况下,命令行顺序很重要。如果 -lcpdf
先出现,则还没有对其符号的引用,因此不会创建依赖关系。 -l
参数应该放在最后:
cc -shared -fpic -I$JAVA_HOME/include I$JAVA_HOME/include/linux jcpdfwrapper.c -o libjcpdf.so -L. -lcpdf
(这个问题涉及 Java JNI,但我不认为问题实际上出在 JNI 或 Java)
我正在执行这条命令:
cc -shared -fpic -L. -lcpdf -I$JAVA_HOME/include I$JAVA_HOME/include/linux jcpdfwrapper.c -o libjcpdf.so
也就是说我正在构建共享库 libjcpdf.so
,它需要 libcpdf.so
的函数,所以应该依赖它。
在 Windows (MinGW) 和 MacOS 上,新的共享库 (jcpdf) 清楚地链接到给定的共享库 (cpdf):
WINDOWS:
$ ldd jcpdf.dll
ntdll.dll => /cygdrive/c/WINDOWS/SYSTEM32/ntdll.dll (0x7ffe875f0000)
KERNEL32.DLL => /cygdrive/c/WINDOWS/System32/KERNEL32.DLL (0x7ffe86400000)
KERNELBASE.dll => /cygdrive/c/WINDOWS/System32/KERNELBASE.dll (0x7ffe851f0000)
msvcrt.dll => /cygdrive/c/WINDOWS/System32/msvcrt.dll (0x7ffe87120000)
libcpdf.dll => /home/JohnWhitington/jcpdf/libcpdf.dll (0x3743f0000)
WS2_32.dll => /cygdrive/c/WINDOWS/System32/WS2_32.dll (0x7ffe870b0000)
RPCRT4.dll => /cygdrive/c/WINDOWS/System32/RPCRT4.dll (0x7ffe87480000)
VERSION.dll => /cygdrive/c/WINDOWS/SYSTEM32/VERSION.dll (0x7ffe7d270000)
OS X:
$ otool -L libjcpdf.dylib
libjcpdf.dylib:
libjcpdf.dylib (compatibility version 0.0.0, current version 0.0.0)
libcpdf.so (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.100.3)
但是,在 Linux 上,我们在 libjcpdf.so 中没有对 libcpdf.so 的引用:
$ ldd libjcpdf.so
linux-vds0,30,1 => (60x00007fc40b13000)
libc.so,6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc1fb2af000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe1fba8f000)
所以发生的事情是,虽然从主 Java 程序 System.LoadLibrary("jcpdf")
成功,但任何使用该库的尝试都会给出:
java: symbol lookup error: /home/john/jcpdf/libjcpdf.so: undefined symbol: cpdf_startup
整个程序在 MacOS 和 Windows 上运行良好。
如何告诉 cc
让 libjcpdf.so
实际上依赖于 libcpdf.so
?
您的 cc
版本(或它使用的 link 编辑器)似乎默认为 -Wl,--as-neeeded
。在这种情况下,命令行顺序很重要。如果 -lcpdf
先出现,则还没有对其符号的引用,因此不会创建依赖关系。 -l
参数应该放在最后:
cc -shared -fpic -I$JAVA_HOME/include I$JAVA_HOME/include/linux jcpdfwrapper.c -o libjcpdf.so -L. -lcpdf