将add_jar与 Swig 生成的 Java 绑定一起使用的正确方法是什么?

2022-09-03 15:38:46

我正在使用Swig为C库生成Java绑定。构建系统是用CMake编写的,以实现平台中立性。我希望生成一个包含Java绑定的JAR文件(即由Swig创建的.java文件编译而产生的.class文件)。我正在尝试使用Cmake命令来执行编译并生成JAR文件。add_jar()

我的问题是Swig在构建时生成一组Java文件,但在执行cmake时需要一个源文件列表。我目前正在使用UNIX通配符(从字面上传递到javac命令行)来解决这个问题。add_jar()

# How do I avoid the shell wildcard?
add_jar(ExampleJNI ${CMAKE_SWIG_OUTDIR}/*.java)

有没有更好的方法?

我在下面包括一个完整的示例(由三个文件组成),以说明我的方法。如果您想自己尝试,请将这三个文件放在一个目录中,然后调用 。cmake . ; make VERBOSE=1

CMakeLists.txt

cmake_minimum_required (VERSION 2.8)
find_package(Swig REQUIRED)
find_package(Java REQUIRED)
find_package(JNI REQUIRED)
include(UseJava)
include(UseSWIG)

project (Example)

add_library (Example example.c)

set(CMAKE_SWIG_FLAGS -package org.mycompany)
set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/src/main/java/org/mycompany)

swig_add_module(ExampleSWIG java example.i)
include_directories(${JNI_INCLUDE_DIRS})

swig_link_libraries(ExampleSWIG Example)

# How do I avoid the wildcard?
add_jar(ExampleJNI ${CMAKE_SWIG_OUTDIR}/*.java)

add_dependencies(ExampleJNI ExampleSWIG)

例子.c

int foo() {
  return 0;
}

例子.i

%module example

%inline %{
    extern int    foo();
%}

我正在使用:

  • 版本 2.8.10.2
  • Java 版本“1.6.0_37”
  • SWIG 版本 2.0.9
  • Mac OS X 达尔文内核版本 12.2.0

答案 1

这篇文章很旧,但我今天遇到了同样的问题,并找到了一个很好的解决方案。

我目前的方法区分构建系统生成时间和构建时间。而不是使用通配符(似乎不适用于windows上的add_jar)。我使用add_custom_command()构建时使用生成的java类生成JAR。我在构建系统生成时就知道这个JAR的名称。所以我可以使用这个名字作为add_jar()函数INCLUDE_JAR参数。我将包含 SWIG 生成的 java 文件的 JAR 称为 Native.jar

下面是如何实现 CMake + Java + SWIG 的示例

首先,我们需要找到必要的软件包:

FIND_PACKAGE(SWIG REQUIRED)
FIND_PACKAGE(JNI REQUIRED)
FIND_PACKAGE(Java REQUIRED)
INCLUDE(UseSWIG)
INCLUDE(UseJava)

然后,我们需要定义 SWIG 模块:

SET(CMAKE_SWIG_OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/java")
SET_PROPERTY(SOURCE "native-interface.i" PROPERTY CPLUSPLUS ON)
SWIG_ADD_MODULE(Native java "native-interface.i" 
    "algorithm.hpp"
    "algorithm-listener.hpp"
    "simple-methods.hpp" "simple-methods.cpp"
    )
TARGET_INCLUDE_DIRECTORIES(Native
    PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
    PRIVATE ${JAVA_INCLUDE_PATH}
    PRIVATE ${JAVA_INCLUDE_PATH2})

如您所见,我使用java子目录来存储java文件。我还将为类文件添加一个子目录,然后注册POST_BUILD事件以构建本机.jar

FILE(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/classes")
ADD_CUSTOM_COMMAND(TARGET Native POST_BUILD
    COMMAND "${Java_JAVAC_EXECUTABLE}" -d classes java/*.java
    COMMAND "${Java_JAR_EXECUTABLE}" -cfM Native.jar -C classes .
    )
# Store Path to native JAR in variable:
SET(NATIVE_JAR "${CMAKE_CURRENT_BINARY_DIR}/Native.jar")

在下一步中,我们将使用add_jar()函数生成一个java项目:

ADD_JAR(ConsoleApp 
    SOURCES "NativeInvoker.java"
    INCLUDE_JARS ${NATIVE_JAR})
SET(CMAKE_JAVA_COMPILE_FLAGS "-source" "1.8" "-target" "1.8")

如果你为项目使用不同的文件夹(比如在一个子目录中有本机,在另一个子目录中有java的东西)。您必须将 Native.dll复制到与 Java 应用程序相同的文件夹中,或者确保 Java 可以找到它。要在CMake中执行此操作,您可以再次使用add_custom_command()。

ADD_CUSTOM_COMMAND(TARGET ConsoleApp POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:Native> ${CMAKE_CURRENT_BINARY_DIR})

希望这对你们很多人都有帮助。

问候蒂姆


答案 2

您可以尝试使用文件通配:

FILE(GLOB SWIG_JAVA_FILES ${CMAKE_SWIG_OUTDIR}/*.java)
add_jar(ExampleJNI ${SWIG_JAVA_FILES})

推荐