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

时间:2013-01-26 23:54:41

标签: java cmake swig

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

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

# 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)

example.c

int foo() {
  return 0;
}

example.i

%module example

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

我正在使用:

  • cmake version 2.8.10.2
  • Java版“1.6.0_37”
  • SWIG版本2.0.9
  • Mac OS X Darwin内核版本12.2.0

2 个答案:

答案 0 :(得分:8)

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

我目前的方法区分构建系统生成时间构建时间。而不是使用通配符(在Windows上似乎不适用于add_jar)。我使用add_custom_command()生成一个JAR,其中包含 build-time 生成的java类。我在构建系统生成时间知道此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 Events以构建 Native.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")

如果您为项目使用不同的文件夹(例如在一个子目录中使用native,在另一个子目录中使用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})

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

问候蒂姆

答案 1 :(得分:0)

您可以尝试使用文件全局:

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