2013-09-25 115 views
3

我寫了一個綁定的C++類,它從C++調用java。我正在嘗試使用CMake來編譯綁定類(因爲將使用綁定類的工具使用CMake)。CMake JNI錯誤

不過,我收到以下錯誤:

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腳本。

回答

13

以下CMakeLists.txt草圖構建一個示例JNI項目通過CMake所需的步驟:

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包含在foo.c聲明的函數作爲一個本地方法nativeFoo的Java類。 foo.c包含方法nativeFoo的C實現。

CMake函數add_jar將Java類編譯爲jar文件,並作爲副作用創建需要作爲輸入傳遞給C++ stub文件生成器可執行文件的類文件。自定義命令用於調用javah以生成存根標頭JNIFoo.h作爲輸出文件。

因爲Java使用System.loadLibrary在運行時加載JNI庫,該庫JNI必須儘可能使用CMake的命令add_library一個MODULE文庫中產生的。作爲源文件添加JNIFoo.h可確保在編譯庫之前創建JNIFoo.h。編譯的JNI庫需要與變量JNI_LIBRARIES中包含的JDK JNI庫鏈接。 JNI_INCLUDE_DIRS包含JNI包含要使用的dirs。

最後,添加一個測試用JVM運行類JNIFoo。系統屬性java.library.path必須設置爲包含生成的JNI庫libfoo.jnilib的目錄。

+0

這很有用,但沒有找到$ JAVA_HOME/include文件夾:include_directories($ {JAVA_INCLUDE_PATH} $ {_ classDir} $ {_ stubDir} $ ENV {JAVA_HOME}/include/linux $ ENV {JAVA_HOME} /包括/) – easytiger

+0

對於Linux,您可能需要使用'$ {JAVA_INCLUDE_PATH} $ {JAVA_INCLUDE_PATH2}'。第二個包含路徑是jni_md.h,它包含在Linux中的jni.h中 –

+0

變量'JNI_INCLUDE_DIRS'包含用於JNI編譯的所有必需目錄。我已經更新了答案。 – sakra