gpt4 book ai didi

java - 未使用 `nar-maven-plugin` 编译的 JUnit 测试的 native 代码

转载 作者:行者123 更新时间:2023-11-30 05:11:52 26 4
gpt4 key购买 nike

我有一个使用 nar-maven-plugin 配置了 Maven 的 JNI 项目。 Java 和 C++ 代码都驻留在项目中。主要代码显然编译正确(C++ 和 Java)。问题出在测试代码 (JUnit) 上。

测试代码定义了一个本身具有 native 方法的 Java 类。相应的 native 代码驻留在目录中

<project root>
+- src
+- test
+- c++

构建消息中没有证据表明此 native 测试代码曾经被编译过,当我从命令行运行 nm 时,相应的 native 方法根本没有出现构建过程。另外,我故意在测试代码中加入一个语法错误,然后重新编译,看看是否会出现编译时错误。没有错误,这与我认为代码永远不会编译的信念一致。

相应地,当测试在 mvn install 期间运行时,我得到一个 UnsatisfiedLinkError。请注意,我可以从测试失败的那一点看出主要(非测试)代码的 native 方法已正确加载和链接。因此,我得出结论,存在一些与 native 测试代码的构建和链接相关的问题。

我目前在 Windows 10 上使用 Eclipse IDE 和 MinGW 编译器编译 native 代码。

我的 POM 的相关部分如下(根据我在 Avoiding machine-dependent POM with MinGW compiler and nar-maven-plugin 上与早期配置问题相关的回答略作更新):

<profiles>
<profile>
<id>Windows-MinGW</id>
<activation>
<os>
<family>Windows</family>
</os>
</activation>
<build>
<plugins>
<plugin>
<groupId>com.github.maven-nar</groupId>
<artifactId>nar-maven-plugin</artifactId>
<version>3.5.1</version>
<extensions>true</extensions>
<configuration>
<cpp>
<options>
<option>-std=c++1y</option>
</options>
</cpp>

<linker>
<name>g++</name>
<options>
<option>-Wl,--kill-at</option>
</options>
</linker>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>

<build>
<defaultGoal>integration-test</defaultGoal>

<plugins>
<plugin>
<groupId>com.github.maven-nar</groupId>
<artifactId>nar-maven-plugin</artifactId>
<version>3.5.1</version>
<extensions>true</extensions>
<configuration>
<cpp>
<defines>
<define>EXPORT_DLL</define>
</defines>
</cpp>
<libraries>
<library>
<type>jni</type>
<narSystemPackage>com.mycompany.sandbox</narSystemPackage>
</library>
</libraries>
</configuration>
</plugin>
</plugins>

</build>

有没有已知的方法来处理这个问题? (也许额外的配置标签?)

最佳答案

我让它工作了,但它并不漂亮。我将在最后给出 POM 部分,但大体上,这些是步骤:

  • 按照编译主代码的问题设置项目
  • 使用<tests>关于 nar-maven-plugin 的部分编译 native 测试代码,注意这实际上是为 native 测试创建可执行文件而不是创建 DLL/SO 支持 Java 测试
  • 指定 <testOptions>链接器将其破解成 DLL/SO 而不是可执行文件
  • 进一步说明 <testOptions>让您的测试代码链接到主项目代码,因为当您选择 jni 时不会自动支持它(而不是 sharedstatic )库类型
  • 将测试库移动到测试前路径,测试后删除

更详细地扩展最后一个项目符号:即使您获得要编译的测试代码,您也无法从 Java 加载它,因为测试目录不在 java.library.path 上。当测试运行时!我能找到的最佳解决方案是将测试库临时移动到路径上的目录中。由于配置选项很容易获得,这似乎比更改路径更容易。前提是拿到路径上的库,那么就可以用System.loadLibrary了在 JUnit 测试执行期间像往常一样。

现在这里是完成上述任务的扩展 POM 段。这是基于我在问题中的内容,但是新的部分需要完成答案开头的项目符号。请注意,支持测试的 JNI 代码位于文件 TestWrapper.cpp 中。在 /src/test/c++ . (我知道这不是 JNI 源文件的标准命名约定。)

注意:此时我只计算出用于在我的 Windows 10 机器上进行测试的链接器标志,它代表 profiles部分。同样,复制/删除具有 .dll明确扩展,这将需要进行调整。 (但是,请进一步注意,即使您获得了一个 .dll 文件,当插件创建它时,它也会有一个 .exe 扩展名!)此时我的 POM 对于其他机器/架构来说无疑是坏的,但是有一个让他们从这里开始工作的清晰路径,因此似乎值得按原样发布答案。

<profiles>
<profile>
<id>Windows-MinGW</id>
<activation>
<os>
<family>Windows</family>
</os>
</activation>
<build>
<plugins>
<plugin>
<groupId>com.github.maven-nar</groupId>
<artifactId>nar-maven-plugin</artifactId>
<version>3.5.1</version>
<extensions>true</extensions>
<configuration>
<cpp>
<options>
<option>-std=c++1y</option>
</options>
</cpp>
<linker>
<name>g++</name>
<options>
<option>-Wl,--kill-at</option>
</options>
<testOptions>
<!-- Put the -shared flag onto the linker - That will force a DLL instead of an EXE -->
<testOption>-shared</testOption>
<!-- We cannot easily link to the *library* that was created for the main project but we can get the compiled object files with the following option -->
<testOption>${project.build.directory}/nar/obj/${nar.aol}/*.o</testOption>
</testOptions>
</linker>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>

<build>
<defaultGoal>integration-test</defaultGoal>

<plugins>
<plugin>
<groupId>com.github.maven-nar</groupId>
<artifactId>nar-maven-plugin</artifactId>
<version>3.5.1</version>
<extensions>true</extensions>
<configuration>
<cpp>
<defines>
<define>EXPORT_DLL</define>
</defines>
</cpp>
<libraries>
<library>
<type>jni</type>
<narSystemPackage>com.mycompany.mypackage</narSystemPackage>
</library>
</libraries>
<tests>
<test>
<name>TestWrapper</name>
<run>false</run>
</test>
</tests>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>copy-test-lib-to-path</id>
<phase>pre-integration-test</phase>
<configuration>
<target>
<copy file="${project.build.directory}/test-nar/bin/${nar.aol}/TestWrapper.exe" tofile="${project.build.directory}/nar/${project.artifactId}-${project.version}-${nar.aol}-jni/lib/${nar.aol}/jni/TestWrapper.dll"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>delete-test-lib-from-deployment</id>
<phase>post-integration-test</phase>
<configuration>
<target>
<delete file="${project.build.directory}/nar/${project.artifactId}-${project.version}-${nar.aol}-jni/lib/${nar.aol}/jni/TestWrapper.dll"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>

</plugins>

关于java - 未使用 `nar-maven-plugin` 编译的 JUnit 测试的 native 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44850793/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com