diff options
-rw-r--r-- | Help/release/dev/UseJava-add_jar-native-headers.rst | 9 | ||||
-rw-r--r-- | Modules/UseJava.cmake | 74 | ||||
-rw-r--r-- | Tests/CMakeLists.txt | 54 | ||||
-rw-r--r-- | Tests/JavaNativeHeaders/CMakeLists.txt | 18 | ||||
-rw-r--r-- | Tests/JavaNativeHeaders/D.cpp | 10 | ||||
-rw-r--r-- | Tests/JavaNativeHeaders/D.java | 19 | ||||
-rw-r--r-- | Tests/JavaNativeHeaders/E.cpp | 10 | ||||
-rw-r--r-- | Tests/JavaNativeHeaders/E.java | 19 | ||||
-rw-r--r-- | Tests/JavaNativeHeaders/HelloWorld3.java | 15 |
9 files changed, 211 insertions, 17 deletions
diff --git a/Help/release/dev/UseJava-add_jar-native-headers.rst b/Help/release/dev/UseJava-add_jar-native-headers.rst new file mode 100644 index 0000000000..0370a672f1 --- /dev/null +++ b/Help/release/dev/UseJava-add_jar-native-headers.rst @@ -0,0 +1,9 @@ +UseJava-add_jar-native-headers +------------------------------ + +* | The command add_jar from :module:`UseJava` module learns how to generate native + headers files using option -h of javac tool. + | This capability requires, at least, version 1.8 of Javac tool. + | Command create_javah will no longer be supported due to the + `suppression of javah tool <http://openjdk.java.net/jeps/313>`_ in the version 1.10 + of the JDK, so ``add_jar(GENERATE_NATIVE_HEADERS)`` must be used instead. diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake index b5fc23629e..939bd7be79 100644 --- a/Modules/UseJava.cmake +++ b/Modules/UseJava.cmake @@ -20,6 +20,7 @@ # [VERSION version] # [OUTPUT_NAME name] # [OUTPUT_DIR dir] +# [GENERATE_NATIVE_HEADERS target [DESTINATION dir]] # ) # # This command creates a <target_name>.jar. It compiles the given @@ -35,6 +36,14 @@ # The default OUTPUT_DIR can also be changed by setting the variable # CMAKE_JAVA_TARGET_OUTPUT_DIR. # +# Optionaly, using option GENERATE_NATIVE_HEADERS, native header files can be generated +# for methods declared as native. These files provide the connective glue that allow your +# Java and C code to interact. An INTERFACE target will be created for an easy usage +# of generated files. Sub-option DESTINATION can be used to specify output directory for +# generated header files. +# +# GENERATE_NATIVE_HEADERS option requires, at least, version 1.8 of the JDK. +# # Additional instructions: # # :: @@ -168,6 +177,22 @@ # # # +# :: +# +# For an optimum usage of option GENERATE_NATIVE_HEADERS, it is recommended to +# include module JNI before any call to add_jar. The produced target for native +# headers can then be used to compile C/C++ sources with command +# target_link_libraries. +# +# +# :: +# +# find_package(JNI) +# add_jar(foo foo.java GENERATE_NATIVE_HEADERS foo-native) +# add_library(bar bar.cpp) +# target_link_libraries(bar PRIVATE foo-native) +# +# # Target Properties: # # :: @@ -359,6 +384,10 @@ # Create C header files from java classes. These files provide the connective glue # that allow your Java and C code to interact. # +# This command will no longer be supported starting with version 1.10 of the JDK due +# to the `suppression of javah tool <http://openjdk.java.net/jeps/313>`_. +# Command ``add_jar(GENERATE_NATIVE_HEADERS)`` must be used instead. +# # There are two main signatures for create_javah. The first signature # returns generated files through variable specified by GENERATED_FILES option: # @@ -448,7 +477,7 @@ function(add_jar _TARGET_NAME) cmake_parse_arguments(_add_jar "" "VERSION;OUTPUT_DIR;OUTPUT_NAME;ENTRY_POINT;MANIFEST" - "SOURCES;INCLUDE_JARS" + "SOURCES;INCLUDE_JARS;GENERATE_NATIVE_HEADERS" ${ARGN} ) @@ -494,6 +523,31 @@ function(add_jar _TARGET_NAME) get_filename_component (_MANIFEST_VALUE "${_add_jar_MANIFEST}" ABSOLUTE) endif () + unset (_GENERATE_NATIVE_HEADERS) + if (_add_jar_GENERATE_NATIVE_HEADERS) + # Raise an error if JDK version is less than 1.8 because javac -h is not supported + # by earlier versions. + if ("${Java_VERSION}" VERSION_LESS 1.8) + message (FATAL_ERROR "ADD_JAR: GENERATE_NATIVE_HEADERS is not supported with this version of Java.") + endif() + cmake_parse_arguments (_add_jar_GENERATE_NATIVE_HEADERS "" "DESTINATION" "" ${_add_jar_GENERATE_NATIVE_HEADERS}) + if (NOT _add_jar_GENERATE_NATIVE_HEADERS_UNPARSED_ARGUMENTS) + message (FATAL_ERROR "ADD_JAR: GENERATE_NATIVE_HEADERS: missing required argument.") + endif() + list (LENGTH _add_jar_GENERATE_NATIVE_HEADERS_UNPARSED_ARGUMENTS length) + if (length GREATER 1) + list (REMOVE_AT _add_jar_GENERATE_NATIVE_HEADERS_UNPARSED_ARGUMENTS 0) + message (FATAL_ERROR "ADD_JAR: GENERATE_NATIVE_HEADERS: ${_add_jar_GENERATE_NATIVE_HEADERS_UNPARSED_ARGUMENTS}: unexpected argument(s).") + endif() + if (NOT _add_jar_GENERATE_NATIVE_HEADERS_DESTINATION) + set (_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_TARGET_NAME}.dir/native_headers") + endif() + + set (_GENERATE_NATIVE_HEADERS_TARGET ${_add_jar_GENERATE_NATIVE_HEADERS_UNPARSED_ARGUMENTS}) + set (_GENERATE_NATIVE_HEADERS_OUTPUT_DIR "${_add_jar_GENERATE_NATIVE_HEADERS_DESTINATION}") + set (_GENERATE_NATIVE_HEADERS -h "${_GENERATE_NATIVE_HEADERS_OUTPUT_DIR}") + endif() + if (LIBRARY_OUTPUT_PATH) set(CMAKE_JAVA_LIBRARY_OUTPUT_PATH ${LIBRARY_OUTPUT_PATH}) else () @@ -625,6 +679,7 @@ function(add_jar _TARGET_NAME) ${CMAKE_JAVA_COMPILE_FLAGS} -classpath "${CMAKE_JAVA_INCLUDE_PATH_FINAL}" -d ${CMAKE_JAVA_CLASS_OUTPUT_PATH} + ${_GENERATE_NATIVE_HEADERS} ${_JAVA_SOURCES_FILELISTS} COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_JAVA_CLASS_OUTPUT_PATH}/java_compiled_${_TARGET_NAME} DEPENDS ${_JAVA_COMPILE_FILES} ${_JAVA_COMPILE_FILELISTS} ${_JAVA_COMPILE_DEPENDS} @@ -735,6 +790,17 @@ function(add_jar _TARGET_NAME) ${CMAKE_JAVA_CLASS_OUTPUT_PATH} ) + if (_GENERATE_NATIVE_HEADERS) + # create an INTERFACE library encapsulating include directory for generated headers + add_library (${_GENERATE_NATIVE_HEADERS_TARGET} INTERFACE) + target_include_directories (${_GENERATE_NATIVE_HEADERS_TARGET} INTERFACE + "${_GENERATE_NATIVE_HEADERS_OUTPUT_DIR}" + ${JNI_INCLUDE_DIRS}) + # this INTERFACE library depends on jar generation + add_dependencies (${_GENERATE_NATIVE_HEADERS_TARGET} ${_TARGET_NAME}) + + set_property (DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${_GENERATE_NATIVE_HEADERS_OUTPUT_DIR}") + endif() endfunction() function(INSTALL_JAR _TARGET_NAME) @@ -1246,6 +1312,12 @@ function(create_javadoc _target) endfunction() function (create_javah) + if ("${Java_VERSION}" VERSION_GREATER_EQUAL 1.10) + message (FATAL_ERROR "create_javah: not supported with this Java version. Use add_jar(GENERATE_NATIVE_HEADERS) instead.") + elseif ("${Java_VERSION}" VERSION_GREATER_EQUAL 1.8) + message (DEPRECATION "create_javah: this command will no longer be supported starting with version 1.10 of JDK. Update your project by using command add_jar(GENERATE_NATIVE_HEADERS) instead.") + endif() + cmake_parse_arguments(_create_javah "" "TARGET;GENERATED_FILES;OUTPUT_NAME;OUTPUT_DIR" diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index fb7313f936..506e995a72 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -3195,29 +3195,51 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release --test-command ${JAVA_RUNTIME} -classpath hello3.jar HelloWorld) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJarSourceListAndOutput") - # For next test, java tool must have same architecture as toolchain + # For next tests, java tool must have same architecture as toolchain math(EXPR _object_mode "${CMAKE_SIZEOF_VOID_P} * 8") execute_process( COMMAND "${Java_JAVA_EXECUTABLE}" -d${_object_mode} -version OUTPUT_QUIET ERROR_QUIET RESULT_VARIABLE _result ) if(_result EQUAL 0) - if(_isMultiConfig) - set (JAVAH_LIBRARY_PATH ${CMake_BINARY_DIR}/Tests/JavaJavah/$<CONFIGURATION>) - else() - set (JAVAH_LIBRARY_PATH ${CMake_BINARY_DIR}/Tests/JavaJavah) + ## next test is valid only if Java version is less than 1.10 + if ("${Java_VERSION}" VERSION_LESS 1.10) + if(_isMultiConfig) + set (JAVAH_LIBRARY_PATH ${CMake_BINARY_DIR}/Tests/JavaJavah/$<CONFIGURATION>) + else() + set (JAVAH_LIBRARY_PATH ${CMake_BINARY_DIR}/Tests/JavaJavah) + endif() + add_test(NAME Java.Javah COMMAND ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/JavaJavah" + "${CMake_BINARY_DIR}/Tests/JavaJavah" + ${build_generator_args} + --build-project helloJavah + --build-two-config + --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJavah/" + --build-options ${build_options} + --test-command ${JAVA_RUNTIME} -Djava.library.path=${JAVAH_LIBRARY_PATH} -classpath hello3.jar HelloWorld2) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJavah") + endif() + ## next test is valid only if Java is, at least, version 1.8 + if (NOT "${Java_VERSION}" VERSION_LESS 1.8) + if(_isMultiConfig) + set (JAVANATIVEHEADERS_LIBRARY_PATH ${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/$<CONFIGURATION>) + else() + set (JAVANATIVEHEADERS_LIBRARY_PATH ${CMake_BINARY_DIR}/Tests/JavaNativeHeaders) + endif() + add_test(NAME Java.NativeHeaders COMMAND ${CMAKE_CTEST_COMMAND} + --build-and-test + "${CMake_SOURCE_DIR}/Tests/JavaNativeHeaders" + "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders" + ${build_generator_args} + --build-project helloJavaNativeHeaders + --build-two-config + --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/" + --build-options ${build_options} + --test-command ${JAVA_RUNTIME} -Djava.library.path=${JAVANATIVEHEADERS_LIBRARY_PATH} -classpath hello4.jar HelloWorld3) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders") endif() - add_test(NAME Java.Javah COMMAND ${CMAKE_CTEST_COMMAND} - --build-and-test - "${CMake_SOURCE_DIR}/Tests/JavaJavah" - "${CMake_BINARY_DIR}/Tests/JavaJavah" - ${build_generator_args} - --build-project helloJavah - --build-two-config - --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJavah/" - --build-options ${build_options} - --test-command ${JAVA_RUNTIME} -Djava.library.path=${JAVAH_LIBRARY_PATH} -classpath hello3.jar HelloWorld2) - list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJavah") endif() endif() endif() diff --git a/Tests/JavaNativeHeaders/CMakeLists.txt b/Tests/JavaNativeHeaders/CMakeLists.txt new file mode 100644 index 0000000000..7dc267942c --- /dev/null +++ b/Tests/JavaNativeHeaders/CMakeLists.txt @@ -0,0 +1,18 @@ +project(helloJavaNativeHeaders Java CXX) + +cmake_minimum_required (VERSION 2.6) +set(CMAKE_VERBOSE_MAKEFILE 1) + +find_package(Java COMPONENTS Development) +include (UseJava) + +# JNI support +find_package(JNI) + +add_jar(B1 D.java GENERATE_NATIVE_HEADERS D1-native) +add_jar(E1 E.java GENERATE_NATIVE_HEADERS E1-native) + +add_jar(hello4 HelloWorld3.java) + +add_library(D SHARED D.cpp E.cpp) +target_link_libraries (D PRIVATE D1-native E1-native) diff --git a/Tests/JavaNativeHeaders/D.cpp b/Tests/JavaNativeHeaders/D.cpp new file mode 100644 index 0000000000..2a90a080cb --- /dev/null +++ b/Tests/JavaNativeHeaders/D.cpp @@ -0,0 +1,10 @@ + +#include <jni.h> +#include <stdio.h> + +#include "D.h" + +JNIEXPORT void JNICALL Java_D_printName(JNIEnv*, jobject) +{ + printf("D\n"); +} diff --git a/Tests/JavaNativeHeaders/D.java b/Tests/JavaNativeHeaders/D.java new file mode 100644 index 0000000000..449c0df2de --- /dev/null +++ b/Tests/JavaNativeHeaders/D.java @@ -0,0 +1,19 @@ +class D +{ + public D() + { + } + + public native void printName(); + + static { + try { + + System.loadLibrary("D"); + + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load.\n" + e); + System.exit(1); + } + } +} diff --git a/Tests/JavaNativeHeaders/E.cpp b/Tests/JavaNativeHeaders/E.cpp new file mode 100644 index 0000000000..fb98946db1 --- /dev/null +++ b/Tests/JavaNativeHeaders/E.cpp @@ -0,0 +1,10 @@ + +#include <jni.h> +#include <stdio.h> + +#include "E.h" + +JNIEXPORT void JNICALL Java_E_printName(JNIEnv*, jobject) +{ + printf("E\n"); +} diff --git a/Tests/JavaNativeHeaders/E.java b/Tests/JavaNativeHeaders/E.java new file mode 100644 index 0000000000..30fd95aef6 --- /dev/null +++ b/Tests/JavaNativeHeaders/E.java @@ -0,0 +1,19 @@ +class E +{ + public E() + { + } + + public native void printName(); + + static { + try { + + System.loadLibrary("D"); + + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load.\n" + e); + System.exit(1); + } + } +} diff --git a/Tests/JavaNativeHeaders/HelloWorld3.java b/Tests/JavaNativeHeaders/HelloWorld3.java new file mode 100644 index 0000000000..77f1fedd92 --- /dev/null +++ b/Tests/JavaNativeHeaders/HelloWorld3.java @@ -0,0 +1,15 @@ +class HelloWorld3 +{ + public static void main(String args[]) + { + D d; + d = new D(); + d.printName(); + + E e; + e = new E(); + e.printName(); + + System.out.println("Hello World!"); + } +} |