118 cedaAddJni
Example:
pythonPackageName = pypizza
cppJniLib = pizza_jni
javaJniJar = PizzaJni
generateJniPythonScript = ${CMAKE_CURRENT_SOURCE_DIR}/generate_pizza_jni_wrappers.py
cppLibs = "MyCompany::Time;MyCompany::Shapes;MyCompany::Pizza"
function(cedaAddJni pythonPackageName cppJniLib javaJniJar generateJniPythonScript cppLibs)
if (BUILD_SHARED_LIBS)
cedaPrepareUseJni()
# Path to witness file which is touched after all the .java and .cpp JNI files have been
# created by the python script
set(generate_jni_files_witness ${CMAKE_CURRENT_BINARY_DIR}/generated_jni_files_witness)
# Paths for where the generated .cpp and .java files will be written
set(cppFolderPath ${CMAKE_CURRENT_BINARY_DIR}/cpp)
set(javaFolderPath ${CMAKE_CURRENT_BINARY_DIR}/java)
# These directories must be created at configure time, because the python script doesn't create them
file(MAKE_DIRECTORY ${cppFolderPath})
file(MAKE_DIRECTORY ${javaFolderPath})
# JniFiles.cmake is a generated file which is checked into the source tree in the repo, and only updated
# when it changes.
#
# It sets the variable 'jniCppFiles' to a list of relative paths of the generated JNI cpp files.
#
# This is done so we have the list of paths to the generated files at configure time, making it possible
# for this CMakeLists.txt file to provide the list of paths to the generated files in the call to
# add_library (see below) for the jni library.
#
# This avoids the need for an ExternalProject
# as discussed here: CMake Compiling Generated Files
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/JniFiles.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/JniFiles.cmake)
else()
message("ERROR : ${CMAKE_CURRENT_SOURCE_DIR}/JniFiles.cmake doesn't exist - run the build to create it then reconfigure")
set(jniCppFiles run-build-and-reconfigure.cpp)
set(jniJavaFiles run-build-and-reconfigure.java)
endif()
# Calculate jnifullPathCppFiles to be a list of full paths to the generated cpp files by prepending
# ${cppFolderPath} to each relative path in ${jniCppFiles}
set(jnifullPathCppFiles "")
foreach(f ${jniCppFiles})
list(APPEND jnifullPathCppFiles ${cppFolderPath}/${f})
endforeach()
set(jnifullPathJavaFiles "")
foreach(f ${jniJavaFiles})
list(APPEND jnifullPathJavaFiles ${javaFolderPath}/${f})
endforeach()
# Without this add_library() may balk at configure time if the generated files don't exist yet
# (since they are only created at build time).
set_source_files_properties(${jnifullPathCppFiles} PROPERTIES GENERATED 1)
set_source_files_properties(${jnifullPathJavaFiles} PROPERTIES GENERATED 1)
if (NOT TARGET ${pythonPackageName})
# When the target platform is for static libraries or it's Android we don't build the python package,
# so declaring a dependency on it with DEPENDS (see add_custom_command below) would produce an error
# when ninja runs (ninja would say there is no rule to build it).
# Instead it is assumed the python package has already been built and installed on the host platform
# so there is no need to declare a dependency on it.
set(pythonPackageName "")
endif()
# Add command to run the python script ${generateJniPythonScript} to generate the JNI files.
add_custom_command(
OUTPUT ${generate_jni_files_witness}
BYPRODUCTS ${jnifullPathCppFiles} ${jnifullPathJavaFiles}
DEPENDS ${generateJniPythonScript} ${pythonPackageName}
COMMENT "Running ${generateJniPythonScript} ${javaFolderPath} ${cppFolderPath}"
COMMAND ${Python_EXECUTABLE} ${generateJniPythonScript} ${javaFolderPath} ${cppFolderPath}
COMMAND ${CMAKE_COMMAND} -DCPP_PATH=${cppFolderPath} -DJAVA_PATH=${javaFolderPath} -DOUPUT_PATH=${CMAKE_CURRENT_SOURCE_DIR}/JniFiles.cmake -P ${Ceda_CMAKE}/GlobJniFiles.cmake
COMMAND ${CMAKE_COMMAND} -E touch ${generate_jni_files_witness})
add_custom_target(GenScriptTarget_${javaJniJar} DEPENDS ${generate_jni_files_witness})
if (TARGET pyceda)
add_dependencies(GenScriptTarget_${javaJniJar} pyceda)
endif()
add_library(${cppJniLib} SHARED ${jnifullPathCppFiles})
cedaAddDependentProject(${cppJniLib})
cedaSetDefaultsForTarget(${cppJniLib})
target_include_directories(${cppJniLib} PRIVATE ${JNI_INCLUDE_DIRS})
target_link_libraries(${cppJniLib} Ceda::cxUtils Ceda::cxObject Ceda::cxPersistStore Ceda::cxJava ${cppLibs})
###################################################################################################
# Create ${javaJniJar}.jar
include(UseJava)
set(CMAKE_JAVA_COMPILE_FLAGS "-source" "1.8" "-target" "1.8")
# This command creates the file ${javaJniJar}.jar.
set(CMAKE_JNI_TARGET TRUE)
add_jar(${javaJniJar} SOURCES ${jnifullPathJavaFiles})
# Make sure the .java files are generated before they are compiled into a jar file
add_dependencies(${javaJniJar} GenScriptTarget_${javaJniJar})
else()
message("Creating JNI bindings unsupported when building static libraries")
endif()
endfunction()