CMake JNI 错误

Posted

技术标签:

【中文标题】CMake JNI 错误【英文标题】:CMake JNI error 【发布时间】:2013-09-25 00:35:29 【问题描述】:

我编写了一个绑定 C++ 类,它从 C++ 调用 java。我正在尝试使用 CMake 编译绑定类(因为将使用绑定类的工具使用 CMake)。

但是我收到以下错误:

CMakeFiles/JNIWrapper.dir/JNIWrapper.cpp.o: In function `createVM(JavaVM_**)':
JNIWrapper.cpp:(.text+0x52): undefined reference to `JNI_CreateJavaVM'
collect2: ld returned 1 exit status
make[2]: *** [JNIWrapper] Error 1
make[1]: *** [CMakeFiles/JNIWrapper.dir/all] Error 2
make: *** [all] Error 2

这是我的 CMakeLists.txt:

cmake_minimum_required(VERSION 2.8.6)

project(AProject)

FIND_PACKAGE(JNI REQUIRED)

SET(CMAKE_CXX_FLAGS "$CMAKE_CXX_FLAGS -I/usr/lib/jvm/java-6-openjdk-amd64/include -I/usr/lib/jvm/java-6-openjdk-amd64/include/linux -L/usr/lib/jvm/java-6-openjdk-amd64/jre/lib/amd64/server")

SET(CMAKE_EXE_LINKER_FLAGS "-ljvm")

# add the binary tree directory to the search path for include files
include_directories($CMAKE_CURRENT_SOURCE_DIR)
include_directories($JNI_INCLUDE_DIRS)

# add the executable
add_executable (JNIWrapper JNIWrapper.cpp)

欢迎提出任何建议。

PS:我尝试使用传统方式和编写makefile来编译它。我按照那个例子写了上面的 CMakeLists.txt 脚本。

【问题讨论】:

【参考方案1】:

以下CMakeLists.txt 概述了使用 CMake 构建示例 JNI 项目所需的步骤:

cmake_minimum_required (VERSION 3.0)

find_package(Java REQUIRED)
find_package(JNI REQUIRED)
include(UseJava)

enable_testing()
project (JNIFoo)

# compile JNIFoo.java to class file
set(CMAKE_JAVA_COMPILE_FLAGS "-source" "1.6" "-target" "1.6")
add_jar(JNIFoo JNIFoo.java)
get_target_property(_jarFile JNIFoo JAR_FILE)
get_target_property(_classDir JNIFoo CLASSDIR)

# generate JNIFoo.h stub
set (_stubDir "$CMAKE_CURRENT_BINARY_DIR")
add_custom_command(
    OUTPUT JNIFoo.h
    COMMAND $Java_JAVAH_EXECUTABLE -verbose
        -classpath $_classDir
        -d $_stubDir
        -jni JNIFoo
    DEPENDS JNIFoo
    )

# generate libfoo.jnilib
include_directories($JNI_INCLUDE_DIRS $_classDir $_stubDir)
add_library(foo MODULE foo.c JNIFoo.h)
set_target_properties(foo PROPERTIES SUFFIX ".jnilib")
target_link_libraries(foo $JNI_LIBRARIES)

# add test to run JNIFoo
add_test(NAME TestJNIFoo
    COMMAND $Java_JAVA_EXECUTABLE
    -Djava.library.path=$CMAKE_CURRENT_BINARY_DIR
    -cp $_jarFile JNIFoo)

文件JNIFoo.java 包含一个Java 类,该类将foo.c 中的函数声明为本机方法nativeFoofoo.c 包含方法 nativeFoo 的 C 实现。

CMake 函数 add_jar 将 Java 类编译为 jar 文件,并作为副作用创建一个类文件,该文件需要作为输入传递给 javah C 存根文件生成器可执行文件。使用自定义命令调用javah 以生成存根标头JNIFoo.h 作为输出文件。

由于 Java 在运行时使用 System.loadLibrary 加载 JNI 库,因此必须使用 CMake 命令 add_library 将 JNI 库生成为 MODULE 库。将JNIFoo.h 添加为源文件可确保在编译库之前创建JNIFoo.h。编译后的 JNI 库需要与变量 JNI_LIBRARIES 中包含的 JDK JNI 库链接。 JNI_INCLUDE_DIRS 包含要使用的 JNI 包含目录。

最后,添加了一个测试以使用 JVM 运行 JNIFoo 类。系统属性java.library.path必须设置为包含生成的JNI库libfoo.jnilib的目录。

【讨论】:

这很有用,但没有找到 $JAVA_HOME/include 文件夹而不做: include_directories($JAVA_INCLUDE_PATH $_classDir $_stubDir $ENVJAVA_HOME/include/linux $ ENVJAVA_HOME/include/) 对于 Linux,您可能需要使用 $JAVA_INCLUDE_PATH $JAVA_INCLUDE_PATH2。第二个包含路径是 jni_md.h,它包含在 Linux 中的 jni.h 中 变量JNI_INCLUDE_DIRS 包含用于JNI 编译的所有必要目录。我已经更新了答案。

以上是关于CMake JNI 错误的主要内容,如果未能解决你的问题,请参考以下文章

cmake jni简说

JNI_02用cMake生成JNI

AS2.2使用CMake方式进行JNI/NDK开发

CMake,JNI 提升读取 json 文件 - Android

如何在 cmake 上使用 FIND_JNI

AndroidStudio2.2 cMake方式创建jni工程