【发布时间】:2016-10-15 18:47:53
【问题描述】:
我对 NDK + Gradle + CMake 集成还很陌生,我试图理解为什么链接不会按预期导出符号。
我有一个由CMakeLists.txt 构建的静态库,它不是主要的CMakeLists.txt。
脚本执行以下操作:
# main CMakeLists.txt
add_subdirectory(${LIBS}/foo libs}
add_library(native SHARED native.cpp)
# omitting standard android libraries
target_link_libraries(native foo ${android-lib} ${log-lib})
而CMakeLists.txt 内${libs}/foo 如下:
# misc configuration of ${SRC}
add_library(foo STATIC ${SRC})
脚本运行良好,它能够链接libnative.so,并且我能够找到生成的libfoo.a。一切似乎都很好。
然后我尝试在 foo 库中的 foo.cpp 中定义一个本地方法:
extern "C" JNIEXPORT void JNICALL Java_com_mypackage_Controls_onTap(JNIEnv*, jobject, int x, int y) {
// log something
}
但我无法调用 foo 库中定义的本机方法。我在运行时收到UnsatisfiedLinkError。相反,如果我将方法移动(直接通过复制和粘贴)到 native.cpp,那么一切都会正常。
所以基本上:
- Java -> native.cpp 中的方法有效
- Java -> native.cpp 中的方法 -> foo 库中定义的方法 有效
-
Java -> foo 库中的方法 不起作用 (
UnsatisfiedLinkError)
我尝试使用nm 检查导出的函数,看起来foo.a 正确导出了本机函数,我可以看到
00011060 T Java_com_mypackage_Controls_onTap
但是这个条目从libnative.so 中消失了。相反,如果我直接在 native.cpp 中定义该方法,那么我也可以在 libnative.so 上使用 nm 正确地看到它。
此外,从native.cpp 调用foo 库中的任何方法都按预期工作,因此库是有效静态链接的。
我无法理解这背后的原因,方法应该没问题,可见性应该是正确的,正如JNIEXPORT 宏指定的那样,所以我真的在黑暗中摸索(并且 Gradle 不提供任何输出编译阶段,所以我无法理解发生了什么,但 build.ninja 文件似乎是正确的)
【问题讨论】:
-
您是否尝试添加
set( CMAKE_VERBOSE_MAKEFILE on )?从您的解释中很难判断出了什么问题 - 要么是从 libnative.so 中删除了符号,要么完全跳过了链接 libfoo.a。 -
@AlexCohn 的 libfoo.a 链接不会被跳过,因为我能够从 libnative 调用 libfoo 的方法并且它可以正确链接和工作。似乎该符号已被剥离或没有从外部明显导出,但我试图强制 -fvisibility=default 没有任何成功。不幸的是,使用的生成器不是make,所以没有makefile。我可以看到调用命令,它似乎是正确的。 so 是通过喜欢 native.o 和 libfoo.a 生成的。我真的没有线索..
标签: android c++ android-ndk linker cmake