summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/release/dev/java-updates.rst3
-rw-r--r--Modules/UseJava.cmake157
-rw-r--r--Tests/CMakeLists.txt25
-rw-r--r--Tests/JavaJavah/B.cpp10
-rw-r--r--Tests/JavaJavah/B.java19
-rw-r--r--Tests/JavaJavah/CMakeLists.txt20
-rw-r--r--Tests/JavaJavah/HelloWorld2.java10
7 files changed, 244 insertions, 0 deletions
diff --git a/Help/release/dev/java-updates.rst b/Help/release/dev/java-updates.rst
index b777807..8fd4ed6 100644
--- a/Help/release/dev/java-updates.rst
+++ b/Help/release/dev/java-updates.rst
@@ -11,3 +11,6 @@ java-updates
* The :module:`UseJava` module ``install_jar`` function learned
new ``DESTINATION`` and ``COMPONENT`` options to specify
the corresponding :command:`install` command options.
+
+* The :module:`UseJava` module gained a new ``create_javah``
+ function to create C headers from Java classes.
diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake
index c61591d..dced6ec 100644
--- a/Modules/UseJava.cmake
+++ b/Modules/UseJava.cmake
@@ -309,6 +309,65 @@
#
#
# if you don't set the INSTALLPATH.
+#
+# ::
+#
+# create_javah(TARGET <target>
+# GENERATED_FILES <VAR>
+# CLASSES <class>...
+# [CLASSPATH <classpath>...]
+# [DEPENDS <depend>...]
+# [OUTPUT_NAME <path>|OUTPUT_DIR <path>]
+# )
+#
+# Create C header files from java classes. These files provide the connective glue
+# that allow your Java and C code to interact.
+#
+# There are two main signatures for create_javah. The first signature
+# returns generated files throught variable specified by GENERATED_FILES option:
+#
+# ::
+#
+# Example:
+# Create_javah(GENERATED_FILES files_headers
+# CLASSES org.cmake.HelloWorld
+# CLASSPATH hello.jar
+# )
+#
+#
+#
+# The second signature for create_javah creates a target which encapsulates
+# header files generation.
+#
+# ::
+#
+# Example:
+# Create_javah(TARGET target_headers
+# CLASSES org.cmake.HelloWorld
+# CLASSPATH hello.jar
+# )
+#
+#
+#
+# Both signatures share same options.
+#
+# ``CLASSES <class>...``
+# Specifies Java classes used to generate headers.
+#
+# ``CLASSPATH <classpath>...``
+# Specifies various paths to look up classes. Here .class files, jar files or targets
+# created by command add_jar can be used.
+#
+# ``DEPENDS <depend>...``
+# Targets on which the javah target depends
+#
+# ``OUTPUT_NAME <path>``
+# Concatenates the resulting header files for all the classes listed by option CLASSES
+# into <path>. Same behavior as option '-o' of javah tool.
+#
+# ``OUTPUT_DIR <path>``
+# Sets the directory where the header files will be generated. Same behavior as option
+# '-d' of javah tool. If not specified, ${CMAKE_CURRENT_BINARY_DIR} is used as output directory.
#=============================================================================
# Copyright 2013 OpenGamma Ltd. <graham@opengamma.com>
@@ -1131,3 +1190,101 @@ function(create_javadoc _target)
DESTINATION ${_javadoc_installpath}
)
endfunction()
+
+function (create_javah)
+ cmake_parse_arguments(_create_javah
+ ""
+ "TARGET;GENERATED_FILES;OUTPUT_NAME;OUTPUT_DIR"
+ "CLASSES;CLASSPATH;DEPENDS"
+ ${ARGN})
+
+ # ckeck parameters
+ if (NOT _create_javah_TARGET AND NOT _create_javah_GENERATED_FILES)
+ message (FATAL_ERROR "create_javah: TARGET or GENERATED_FILES must be specified.")
+ endif()
+ if (_create_javah_OUTPUT_NAME AND _create_javah_OUTPUT_DIR)
+ message (FATAL_ERROR "create_javah: OUTPUT_NAME and OUTPUT_DIR are mutually exclusive.")
+ endif()
+
+ if (NOT _create_javah_CLASSES)
+ message (FATAL_ERROR "create_javah: CLASSES is a required parameter.")
+ endif()
+
+ set (_output_files)
+ if (WIN32 AND NOT CYGWIN AND CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
+ set(_classpath_sep ";")
+ else ()
+ set(_classpath_sep ":")
+ endif()
+
+ # handle javah options
+ set (_javah_options)
+
+ if (_create_javah_CLASSPATH)
+ # CLASSPATH can specify directories, jar files or targets created with add_jar command
+ set (_classpath)
+ foreach (_path IN LISTS _create_javah_CLASSPATH)
+ if (TARGET ${_path})
+ get_target_property (_jar_path ${_path} JAR_FILE)
+ if (_jar_path)
+ list (APPEND _classpath "${_jar_path}")
+ list (APPEND _create_javah_DEPENDS "${_path}")
+ else()
+ message(SEND_ERROR "create_javah: CLASSPATH target ${_path} is not a jar.")
+ endif()
+ elseif (EXISTS "${_path}")
+ list (APPEND _classpath "${_path}")
+ if (NOT IS_DIRECTORY "${_path}")
+ list (APPEND _create_javah_DEPENDS "${_path}")
+ endif()
+ else()
+ message(SEND_ERROR "create_javah: CLASSPATH entry ${_path} does not exist.")
+ endif()
+ endforeach()
+ string (REPLACE ";" "${_classpath_sep}" _classpath "${_classpath}")
+ list (APPEND _javah_options -classpath ${_classpath})
+ endif()
+
+ if (_create_javah_OUTPUT_DIR)
+ list (APPEND _javah_options -d "${_create_javah_OUTPUT_DIR}")
+ endif()
+
+ if (_create_javah_OUTPUT_NAME)
+ list (APPEND _javah_options -o "${_create_javah_OUTPUT_NAME}")
+ set (_output_files "${_create_javah_OUTPUT_NAME}")
+
+ get_filename_component (_create_javah_OUTPUT_DIR "${_create_javah_OUTPUT_NAME}" DIRECTORY)
+ get_filename_component (_create_javah_OUTPUT_DIR "${_create_javah_OUTPUT_DIR}" ABSOLUTE)
+ endif()
+
+ if (NOT _create_javah_OUTPUT_DIR)
+ set (_create_javah_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
+ endif()
+
+ if (NOT _create_javah_OUTPUT_NAME)
+ # compute output names
+ foreach (_class IN LISTS _create_javah_CLASSES)
+ string (REPLACE "." "_" _c_header "${_class}")
+ set (_c_header "${_create_javah_OUTPUT_DIR}/${_c_header}.h")
+ list (APPEND _output_files "${_c_header}")
+ endforeach()
+ endif()
+
+ # finalize custom command arguments
+ if (_create_javah_DEPENDS)
+ list (INSERT _create_javah_DEPENDS 0 DEPENDS)
+ endif()
+
+ add_custom_command (OUTPUT ${_output_files}
+ COMMAND "${Java_JAVAH_EXECUTABLE}" ${_javah_options} -jni ${_create_javah_CLASSES}
+ ${_create_javah_DEPENDS}
+ WORKING_DIRECTORY ${_create_javah_OUTPUT_DIR}
+ COMMENT "Building C header files from classes...")
+
+ if (_create_javah_TARGET)
+ add_custom_target (${_create_javah_TARGET} ALL DEPENDS ${_output_files})
+ endif()
+ if (_create_javah_GENERATED_FILES)
+ set (${_create_javah_GENERATED_FILES} ${_output_files} PARENT_SCOPE)
+ endif()
+endfunction()
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 35b29bf..801d7e8 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -3036,6 +3036,31 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
--build-options ${build_options}
--test-command ${JAVA_RUNTIME} -classpath hello2.jar HelloWorld)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJarSourceList")
+
+ # For next test, 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(CMAKE_CONFIGURATION_TYPES)
+ 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()
endif()
endif()
endif()
diff --git a/Tests/JavaJavah/B.cpp b/Tests/JavaJavah/B.cpp
new file mode 100644
index 0000000..2666757
--- /dev/null
+++ b/Tests/JavaJavah/B.cpp
@@ -0,0 +1,10 @@
+
+#include <jni.h>
+#include <stdio.h>
+
+#include "B.h"
+
+JNIEXPORT void JNICALL Java_B_printName(JNIEnv *, jobject)
+{
+ printf("B\n");
+}
diff --git a/Tests/JavaJavah/B.java b/Tests/JavaJavah/B.java
new file mode 100644
index 0000000..d731f39
--- /dev/null
+++ b/Tests/JavaJavah/B.java
@@ -0,0 +1,19 @@
+class B
+{
+ public B()
+ {
+ }
+
+ public native void printName();
+
+ static {
+ try {
+
+ System.loadLibrary("B");
+
+ } catch (UnsatisfiedLinkError e) {
+ System.err.println("Native code library failed to load.\n" + e);
+ System.exit(1);
+ }
+ }
+}
diff --git a/Tests/JavaJavah/CMakeLists.txt b/Tests/JavaJavah/CMakeLists.txt
new file mode 100644
index 0000000..83b0ad0
--- /dev/null
+++ b/Tests/JavaJavah/CMakeLists.txt
@@ -0,0 +1,20 @@
+project(helloJavah 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(hello3 B.java HelloWorld2.java)
+create_javah(TARGET B_javah CLASSES B CLASSPATH hello3)
+
+add_library(B SHARED B.cpp)
+add_dependencies(B B_javah)
+
+target_include_directories(B PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
+ ${JAVA_INCLUDE_PATH}
+ ${JAVA_INCLUDE_PATH2})
diff --git a/Tests/JavaJavah/HelloWorld2.java b/Tests/JavaJavah/HelloWorld2.java
new file mode 100644
index 0000000..faf7277
--- /dev/null
+++ b/Tests/JavaJavah/HelloWorld2.java
@@ -0,0 +1,10 @@
+class HelloWorld2
+{
+ public static void main(String args[])
+ {
+ B b;
+ b = new B();
+ b.printName();
+ System.out.println("Hello World!");
+ }
+}