【问题标题】:Native code for JUnit tests not compiled with `nar-maven-plugin`未使用 `nar-maven-plugin` 编译的 JUnit 测试的本机代码
【发布时间】:2017-07-01 06:11:09
【问题描述】:

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

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

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

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

相应地,当测试在mvn install 期间运行时,我得到一个UnsatisfiedLinkError。请注意,我可以从测试失败的那一点看出,主(非测试)代码的本机方法已正确加载和链接。因此,我得出结论,具体而言,与原生测试代码的构建和链接有关。

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

我的 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>

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

【问题讨论】:

    标签: java c++ maven java-native-interface maven-nar-plugin


    【解决方案1】:

    我得到了这个工作,但它并不漂亮。我将在最后给出 POM 部分,但总的来说,这些是步骤:

    • 在编译主代码的问题中设置项目
    • 使用nar-maven-plugin 上的&lt;tests&gt; 部分来编译本机测试代码,注意这实际上是为了为本机测试创建可执行文件而不是创建DLL/SO 支持Java 测试
    • &lt;testOptions&gt; 指定给链接器以将其破解为生成 DLL/SO 而不是可执行文件
    • 进一步指定 &lt;testOptions&gt; 以使您的测试代码链接到主项目代码,因为当您选择 jni(而不是 sharedstatic)库类型时,不会自动支持此功能
    • 将测试库移动到测试前的路径,测试后删除

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

    现在这里是完成上述操作的扩展 POM 段。这是基于我在问题中的内容,但是对于新作品,需要在答案的开头完成项目符号。请注意,支持该测试的 JNI 代码位于 /src/test/c++ 中的文件 TestWrapper.cpp 中。 (我知道这不是 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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-30
      • 2019-10-08
      • 2022-01-14
      • 1970-01-01
      • 2015-08-01
      相关资源
      最近更新 更多