【问题标题】:JNI Cross Compiled from OS-X to Windows Fails with "Can't find dependent libraries"从 OS-X 到 Windows 的 JNI 交叉编译失败并显示“找不到依赖库”
【发布时间】:2020-09-01 10:49:48
【问题描述】:

我有一个在 Apple OS-X 上构建并为 Windows 10 交叉编译的 Java JNI 程序。

在 OS-X 上构建和运行良好。 Windows 64 位交叉编译完成,没有错误,但生成的程序无法在 Windows 10 下运行并给出错误:

Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\Michael\Documents\JNIExample\MyLib.dll: Can't find dependent libraries

在我添加对 C++ new 运算符的引用时发生错误。当它被删除时,“找不到依赖库”消失并且应用程序运行。该程序曾经使用这些工具和操作系统的早期版本运行过。

我的猜测是我在 x86_64-w64-mingw32-gcc 中遗漏了一些重要的东西,包括新运算符所需的静态绑定库。有人可以帮忙吗?

用于构建项目的命令在 bash shell 脚本文件中:doit.sh

#!/bin/bash

    echo "=== Building on OS-X ==="

    export JAVA_HOME="`/usr/libexec/java_home -v '14*'`"
    
    # Clean up
    rm -rf bin/*.class MyLib/*.o *.dll *.jnilib *.jar
    
    # Compile Java and generate JNI header file
    mkdir -p bin
    javac -d bin -h MyLib -sourcepath src src/*.java

    # Create the JAR file, main entry point in class MyLib
    jar cfe Test.jar MyLib -C bin .
    
    # Build the C++ shared library
    gcc -c -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/darwin" MyLib/MyLib.cpp -o MyLib/MyLib.mac.o
    g++ -dynamiclib -o libMyLib.jnilib MyLib/*.mac.o
    
    echo "=== Running on OS-X ==="
    java -jar Test.jar

    echo "=== Building on OS-X ==="
    
    # Cross compile for the Windows shared library
    /usr/local/bin/x86_64-w64-mingw32-gcc -D __LP64__ -c -I$JAVA_HOME/include -I$JAVA_HOME/include/darwin MyLib/MyLib.cpp -o MyLib/MyLib.win.o
    /usr/local/bin/x86_64-w64-mingw32-g++ -shared -static-libgcc -static-libstdc++ -o MyLib.dll MyLib/*.win.o

我的目标是使用 jlink 和 jpackage 制作应用程序的 Windows 和 Mac 分发版,以便最终将所有库都包含在我的最终分发版中。

工具版本
| Tool                       | Version |
|-------------------------|----------------------|
| MacBook Pro | OS-X Catalina 10.15.6 |
| x86_64-w64-mingw32-gcc/g++ | 9.3.0 (GCC) (download with brew install mingw-w64) |
| gcc/g++                    | Apple clang version 12.0.0 (clang-1200.0.31.1) |
| java                       | java version "14.0.1" 2020-04-14 |
x86_64-w64-mingw32-gcc -v 输出
michaelellis$ /usr/local/bin/x86_64-w64-mingw32-gcc -v
Using built-in specs.
COLLECT_GCC=/usr/local/bin/x86_64-w64-mingw32-gcc
COLLECT_LTO_WRAPPER=/usr/local/Cellar/mingw-w64/7.0.0_2/toolchain-x86_64/libexec/gcc/x86_64-w64-mingw32/9.3.0/lto-wrapper
Target: x86_64-w64-mingw32
Configured with: ../configure --target=x86_64-w64-mingw32 --with-sysroot=/usr/local/Cellar/mingw-w64/7.0.0_2/toolchain-x86_64 --prefix=/usr/local/Cellar/mingw-w64/7.0.0_2/toolchain-x86_64 --with-bugurl=https://github.com/Homebrew/homebrew-core/issues --enable-languages=c,c++,fortran --with-ld=/usr/local/Cellar/mingw-w64/7.0.0_2/toolchain-x86_64/bin/x86_64-w64-mingw32-ld --with-as=/usr/local/Cellar/mingw-w64/7.0.0_2/toolchain-x86_64/bin/x86_64-w64-mingw32-as --with-gmp=/usr/local/opt/gmp --with-mpfr=/usr/local/opt/mpfr --with-mpc=/usr/local/opt/libmpc --with-isl=/usr/local/opt/isl --disable-multilib --enable-threads=posix
Thread model: posix
gcc version 9.3.0 (GCC) 

完整的 SSCCE 可在公共 git 上获取:https://gitlab.com/Michael51773/jniexample

【问题讨论】:

  • 不要使用gcc编译C++代码,使用g++。
  • 谢谢@Botje,但这似乎没什么区别。
  • 您可能还应该包含 windows JNI 标头而不是 macOS 标头,但我怀疑这会有所作为。
  • Mac开发平台只有一个{JAVA_HOME}/include/darwin,没有Windows版本。如果在 Windows 平台上构建,您必须使用 {JAVA_HOME}/include/win32,每个版本仅存在于您正在开发的平台的 JVM 安装中。
  • @Botje 从本质上讲,我通过构建一个使用共享库的 C++ 应用程序实现了您的建议,并看到它也失败了,但对于缺少哪些库提供了更多信息! (见下面的答案)。无论如何,感谢您的贡献。

标签: java-native-interface mingw cross-compiling


【解决方案1】:

对此进行调查的下一步是创建一个使用可共享库的简单 C++ 独立命令行应用程序。

这在 OS-X 上正确构建和运行,但是在将交叉编译的产品部署到 Windows 平台时,它无法执行,将以下库列为缺失:

  • libstc++-6.dll
  • libwinpthread-1.dll
  • libgcc_s_seh

将这些文件从 mingw 发行版 /usr/local/Cellar/mingw-w64/7.0.0_2/toolchain-x86_64/x86_64-w64-mingw32/.. 复制到与 Windows 平台上的应用程序相同的目录中解决了问题!

在我看来,mingcw g++ -static-libgcc -static-libstdc++ 可能不像以前那样工作了!

【讨论】:

  • 很好的调查!
猜你喜欢
  • 1970-01-01
  • 2012-08-06
  • 2018-03-24
  • 1970-01-01
  • 2020-04-10
  • 1970-01-01
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多