31

さまざまなSBTタスクをネイティブライブラリ(たとえば、JOGLLWGL、またはJCudaからのもの)と統合するための良い方法は何ですか?具体的には、

  1. runタスクにネイティブライブラリを含めるための推奨される方法はありますか?SBTメーリングリストでの議論は、これらの可能性を示唆しています。

    最後の1つには、フォークする必要がないという利点がrunありますが、構成をSBTの外部で行う必要があるという欠点があります。

  2. sbteclipseプラグインによって生成されたEclipseプロジェクトにネイティブライブラリを自動的に含めることはできますか?後処理ステップでファイル書き換えることができます。.projectサンプルコードはありますか?もっと良い方法はありますか?

  3. ネイティブライブラリは、sbt-assemblysbt-onejarsbt -proguardなどのプラグインによって生成される実行可能なJarに含めることができますか?

ネイティブライブラリには直接のSBT設定はないと思います。そのようなものが存在する場合、上記のタスクはネイティブライブラリを透過的に処理できますか?

4

3 に答える 3

30

私が過去に行った調査によると、ネイティブライブラリをロードする方法は2つしかありません。変更java.library.pathして使用する方法System.loadLibrary(ほとんどの人がこれを行うように感じます)、またはSystem.load絶対パスで使用する方法です。

ご存知のように、SBTとEclipseの構成に関しては、いじりjava.library.pathが煩わしい場合があり、実行可能jarに対して自動的に行うことはできないと思います。

だからそれは去るSystem.load。独自のネイティブライブラリを作成するという点で、できることは次のとおりです。

  • javahネイティブソース(およびを使用gcc)をコンパイルし、結果の.soファイルとそれに依存する.soファイルを取得し、それらをターゲットディレクトリのjarに(リソースとして)配置し、jarへのパスを追加するSBTタスクを作成します。にunmanagedJars in Compile
  • ライブラリをロードするためのScalaメソッドを作成します。を呼び出す代わりに、ライブラリを読み取り、ファイルシステムのどこかに書き込み、JVMにロードするためにSystem.loadLibrary使用します。Class.getResourceAsStreamFile.createTempFileSystem.load
  • System.loadLibraryこれで、以前のように呼び出す代わりに、を呼び出しますMyClasspathJniLoader.loadLibrary

これは、追加の構成なしでSBT実行、Eclipse、および実行可能jarで機能します(ただし、proguardがどのリソースを含めるかをどのように認識しているかはわかりません)。

すでに作成されているサードパーティのネイティブライブラリに関しては、jblasのような一部のライブラリはすでにこの「ファットジャー」アプローチを使用しています。彼らがあなたがセットアップすることを期待し、そして彼らがそれを感じたときに彼らがjava.library.path電話をするならば、あなたはそれを機能させるためにいくつかの魔法をする必要があるでしょう。System.loadLibrary

私はこれを試していませんが、この解決策はうまくいくかもしれません:

  • 同様のSBTタスクを使用して、ネイティブパス上のすべてのライブラリをリソースとしてjarに配置し、そのjarをclsaspathに配置します。
  • 関数とライブラリ名のリストを受け取り、一時ディレクトリを作成し、それらのライブラリをjarのリソースから一時ディレクトリ内のファイルに読み取り、一時ディレクトリをに追加しjava.library.path、渡された関数を呼び出し、最後に元に戻すScalaメソッドを作成します。java.library.path以前の状態に戻ります。
  • ネイティブライブラリを初めて呼び出すとき(おそらく静的に初期化してSystem.loadLibrary呼び出しを行うとき)、ロードするライブラリのリストを使用して、メソッド内の特定の呼び出しをラップします。そうすれば、を呼び出すとSystem.loadLibrary、すべてのライブラリがオンにjava.library.pathなり、正常にロードされます。

java.library.pathサードパーティのライブラリを使用する前に手動で初期化する必要があるため、これは明らかに面倒ですが、すべてのツールを正しく設定するよりも、すべての初期化ポイント(メイン関数とテストの初期化)をラップする方が現実的です。。また、サードパーティのライブラリの上に独自の抽象化レイヤーがある場合は、それよりもさらに簡単な場合があります。そのため、ラップする必要のある初期化ポイントは実際には1つだけです。

それが現実的な解決策のように思われる場合は、混乱している場合は、SBTタスクまたはScalaラッパーメソッドに関する詳細を追加できます。

于 2012-05-27T19:32:10.507 に答える
0

Osxで、/lib/*.jnilib中にネイティブライブラリをロードする際に問題が発生した場合sbt test

[error] java.lang.UnsatisfiedLinkError: Fatal execution error, caused by no jniortools in java.library.path

の代わりに次のコードを使用できますSystem.loadLibrary("jniortools")

new File("lib").listFiles().map(_.getAbsolutePath).filter(_.endsWith("jniortools.jnilib")).foreach(System.load)
于 2016-07-29T09:13:24.233 に答える
0

簡単な方法があります。

lib_extraディレクトリに保存されているネイティブライブラリを想定します

  1. libraryDependenciesにjnaを追加します。

    libraryDependencies ++ = Seq( "net.java.dev.jna"% "jna-platform"% "4.1.0")

  2. 次のコードをbuild.sbtに追加します。

    コンパイル中のunmanagedResourceDirectories+= baseDirectory.value / "lib_extra"

    includeFilter in(Compile、unmanagedResourceDirectories):= " .dll、 .so"

于 2016-11-29T08:12:34.143 に答える