在 Cmake 中使用 Swig 不正确 link Java

Using Swig in Cmake doesn't link Java properly

我正在尝试 link 一个非常简单的测试 C 库 Java,使用 Swig Cmake(项目需要)。当我 运行 手动操作时一切正常:

$ swig -java AMItest.i
$ gcc -fPIC -c AMItest.c AMItest_wrap.c -I/usr/lib/jvm/java-11-openjdk-amd64/include -I/usr/lib/jvm/java-11-openjdk-amd64/include/linux
$ gcc -shared AMItest.o  AMItest_wrap.o  -W  -o libAMItest_swig.so
$ javac main.java
$ LD_LIBRARY_PATH=. java main

我的cmake:

cmake_minimum_required(VERSION 3.11)
enable_language(C)
project(AMItest)
set(CMAKE_C_FLAGS "-ggdb -O0 -Wall -Wextra -pedantic -std=gnu11 -fdiagnostics-color=always -Wno-unused-function") 
find_package(SWIG REQUIRED COMPONENTS java)
include(${SWIG_USE_FILE})
find_package(JNI REQUIRED)
include_directories(${JNI_INCLUDE_DIRS} .)
swig_add_library(AMItest_swig  LANGUAGE java  SOURCES AMItest.i)
# Optional below
find_package(Java REQUIRED)
add_custom_command(TARGET AMItest_swig COMMAND javac main.java MAIN_DEPENDENCY main.java DEPENDS libAMItest_swig.so BYPRODUCTS main.class)

当我尝试 运行:

$ cmake . &7 make && LD_LIBRARY_PATH=. java main
java: symbol lookup error: libAMItest_swig.so: undefined symbol: AMItest
$ nm libAMItest_swig.so | grep AMItest
                 U AMItest
0000000000003089 T Java_AMItestJNI_AMItest

我的main.java:

public class main {
    public static void main(String argv[]) {
        System.loadLibrary("AMItest_swig"); // File is libAMItest_swig.so
        int size = 11;
        double[] myArray = new double[size];
        System.out.println(AMItest.AMItest(myArray, 10, 20));
        ...
    }
}

最后是我的 AMItest.h(C 代码在这里并不相关):

extern int AMItest(double *Array, int Start, int End);

我很确定它来自编译 C 代码的一些差异,但是使用 make VERBOSE=1 将行与 cc 进行比较不起作用,因为差异太多。我可能需要一些选项或包含一些库。但是哪个以及如何?

像这样将 AMItest.c 添加到 swig_add_library 时:

swig_add_library(AMItest_swig  LANGUAGE java  SOURCES AMItest.i AMItest.c)

以及替换行:

add_custom_command(TARGET AMItest_swig COMMAND javac main.java MAIN_DEPENDENCY main.java DEPENDS libAMItest_swig.so BYPRODUCTS main.class)

与:

include(UseJava)
add_jar(
        Main
        SOURCES main.java
        ENTRY_POINT main
)
add_dependencies(Main AMItest_swig)

那么可以这样调用:

java -jar Main.jar  

并且数字输出正确,这意味着动态 Link 库构建正确。

总结一下:您稍加修改的 CMakeLists.txt 将如下所示:

cmake_minimum_required(VERSION 3.11)
enable_language(C)
project(AMItest)
set(CMAKE_C_FLAGS "-ggdb -O0 -Wall -Wextra -pedantic -std=gnu11 -fdiagnostics-color=always -Wno-unused-function")
find_package(SWIG REQUIRED COMPONENTS java)
include(${SWIG_USE_FILE})
find_package(JNI REQUIRED)
include_directories(${JNI_INCLUDE_DIRS} .)
swig_add_library(AMItest_swig  LANGUAGE java  SOURCES AMItest.i AMItest.c)
# Optional below
find_package(Java REQUIRED)
include(UseJava)
add_jar(
        Main
        SOURCES main.java
        ENTRY_POINT main
)
add_dependencies(Main AMItest_swig)