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
中的函数声明为本机方法nativeFoo
。 foo.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 错误的主要内容,如果未能解决你的问题,请参考以下文章