Search code examples
javacmakejava-native-interface

UseJava in CMake to GENERATE_NATIVE_HEADERS


CMake seems to be really cool. Just the other day, I found out I can use it to compile Java sources into jars. There also is an option to GENERATE_NATIVE_HEADERS. However, it just does not generate headers for me. The resulting Makefile invokes javac without -h someplace. Any hints what I might be missing? This is what I have so far:

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
find_package(Java 11 REQUIRED)
find_package(Java COMPONENTS Development)
find_package(JNI REQUIRED)
include(UseJava)
add_jar(SomeJava 
    SomeJava.java
    ENTRY_POINT SomeJava
    GENERATE_NATIVE_HEADERS SomeJava-native
)
add_library(native SHARED
    native.c
)
target_include_directories(native PRIVATE
    ${JNI_INCLUDE_DIRS}
)

native.c

#include "SomeJava.h"
JNIEXPORT void JNICALL Java_SomeJava_printHelloWorld(JNIEnv * env, jclass cls) {
    printf("Native Hello World!\n");
}

SomeJava.java

public class SomeJava {
    public static void main(String[] args) {
        printHelloWorld();
    }
    static {
        System.loadLibrary("native");
    }
    public static native void printHelloWorld();
}

If I invoke javac manually to generate SomeJava.h, it works just fine.


Solution

  • Per the examples in the documentation, it appears you may want to link to your produced INTERFACE target named SomeJava-native:

    The produced target for native headers can then be used to compile C/C++ sources with the target_link_libraries() command.

    Currently, your code doesn't appear to use this target, so you can add this to the end of your CMake file:

    target_link_libraries(native PRIVATE SomeJava-native)
    

    Also, be sure your CMake version is 3.11 or greater, as the GENERATE_NATIVE_HEADERS feature was not available in earlier versions.