1

を使用してMavenで構成されたJNIプロジェクトがありますnar-maven-plugin。Java と C++ コードの両方がプロジェクトに存在します。メイン コードは適切にコンパイルされるようです (C++ と Java の両方)。問題はテスト コード (JUnit) にあります。

テスト コードは、それ自体がネイティブ メソッドを持つ 1 つの Java クラスを定義しました。対応するネイティブ コードはディレクトリにあります。

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

ビルド メッセージから、このネイティブ テスト コードがコンパイルされたことを示す証拠はなくnm、ビルド プロセスによって作成された DLL をコマンド ラインから実行すると、対応するネイティブ メソッドがまったく表示されません。さらに、テスト コードに意図的に構文エラーを挿入し、コンパイル時にエラーが発生するかどうかを確認するために再コンパイルしました。コードがコンパイルされていないという私の信念と一致して、エラーはありません。

UnsatisfiedLinkErrorそれに応じて、テストが の間に実行されたときに を取得しmvn installます。テストが失敗した時点から、メイン (非テスト) コードのネイティブ メソッドが正しく読み込まれ、リンクされていることがわかります。したがって、特にネイティブ テスト コードのビルドとリンクに関連する問題があると結論付けています。

私は現在、ネイティブ コード用の Eclipse IDE と MinGW コンパイラを使用して Windows 10 を使用しています。

私のPOMの関連セクションは以下のとおりです(初期設定の問題に関連するMinGWコンパイラとnar-maven-pluginを使用したマシン依存の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>
                        </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>

この問題を処理する既知の方法はありますか? (おそらく追加の構成タグ?)

4

1 に答える 1

1

私はこれを機能させましたが、きれいではありませんでした。最後に POM の部分を示しますが、大まかに手順は次のとおりです。

  • メインコードをコンパイルするための質問のようにプロジェクトを設定します
  • <tests>セクションを使用しnar-maven-pluginてネイティブ テスト コードをコンパイルします。これは実際にはネイティブ テスト用の実行可能ファイルを作成するように設定されており、DLL/SO バッキング Java テストを作成しないことに注意してください。
  • <testOptions>実行可能ファイルの代わりに DLL/SO を作成するようにハッキングするようにリンカーに指定します。
  • <testOptions>テスト コードをメイン プロジェクト コードにリンクするようjniにさらにshared指定するstatic
  • テストライブラリをテスト前のパスに移動し、テスト後に削除します

最後の箇条書きをさらに詳しく説明します。テスト コードをコンパイルしてコンパイルしても、Java からロードすることはできません。これはjava.library.path、テストの実行時にテスト ディレクトリが存在しないためです。私が見つけた最善の解決策は、テスト ライブラリを一時的にパス上のディレクトリに移動することでした。構成オプションが簡単に利用できるため、これはパスを変更するよりも簡単に思えました。パス上でライブラリを取得するとSystem.loadLibrary、JUnit テストの実行中に通常どおり使用できます。

上記を実現する拡張POMセグメントは次のとおりです。これは私が質問で持っていたものに基づいていますが、新しい部分では、回答の冒頭で箇条書きを完了する必要があります. テストをサポートする JNI コードはTestWrapper.cpp/src/test/c++. (JNI ソース ファイルの標準的な命名規則ではないことはわかっています。)

: この時点では、このprofilesセクションに示されている Windows 10 マシンでテストするためのリンカー フラグのみを作成しました。同様に、コピー/削除には.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>
于 2017-06-30T22:11:09.123 に答える