2012-05-25 18 views
31

¿Qué es una buena manera de integrar las diversas tareas de HAT en bibliotecas nativas (por ejemplo, los de JOGL, LWGL, o JCuda? Específicamente,La integración de las bibliotecas del sistema nativos con SBT

  1. ¿Hay una manera recomendada de incluir una biblioteca nativa en la tarea run una discusión sobre la lista de distribución SBT sugiere estas posibilidades:?

    La última tiene la ventaja de que run no necesita tenedor, pero tiene la desventaja de que la configuración debe realizarse fuera de SBT.

  2. ¿Puedo incluir automáticamente bibliotecas nativas en el proyecto Eclipse generado por el plugin sbteclipse? Es posible rewrite the .project file in a post-processing step. ¿Hay código de ejemplo? ¿Hay una mejor manera?

  3. pueden las bibliotecas nativas se incluirán en el tarro ejecutable que se genera por un plugin como sbt-assembly, sbt-onejar o sbt-proguard?

Supongo que no hay una configuración SBT directa para bibliotecas nativas. Si algo así existiera, ¿podrían las tareas anteriores manejar bibliotecas nativas de forma transparente?

Respuesta

28

De la investigación que he hecho en el pasado, sólo hay dos maneras de obtener bibliotecas nativas cargadas: La modificación de java.library.path y utilizando System.loadLibrary (me siento como la mayoría de la gente hace esto), o utilizando System.load con una ruta absoluta.

Como has mencionado, jugar con java.library.path puede ser molesto en términos de configuración de SBT y Eclipse, y no creo que sea posible hacerlo automáticamente para un archivo ejecutable.

De modo que deja System.load. En términos de escribir sus propias bibliotecas nativas, lo que puede hacer es:

  • Crear una tarea SBT que recopila sus fuentes nativas (con javah y gcc), dando como resultado la toma .so archivos y los archivos .so que depende on, los pone en un jar (como recursos) en el directorio de destino y agrega la ruta al jar al unmanagedJars in Compile.
  • Cree un método Scala para cargar una biblioteca. En lugar de llamar al System.loadLibrary, usará Class.getResourceAsStream para leer la biblioteca, File.createTempFile para escribirla en algún lugar del sistema de archivos, y System.load para cargarla en la JVM.
  • Ahora, en lugar de llamar al System.loadLibrary como lo haría antes, llame al MyClasspathJniLoader.loadLibrary.

Eso funcionará con SBT run, Eclipse y archivos ejecutables sin configuración adicional (aunque no sé cómo Proguard sabe qué recursos incluir).

Ahora, en cuanto a las bibliotecas nativas de terceros que ya se han escrito, algunas de ellas como jblas ya usan este enfoque de "jar gordo". Si esperan que configures java.library.path y luego llamen al System.loadLibrary cuando lo deseen, tendrás que hacer algo de magia para que funcione.

No he probado esto, pero esta solución podría funcionar:

  • uso una tarea similar SBT para poner todas las bibliotecas en su ruta nativa en un frasco como recursos, y poner el frasco en el clsaspath.
  • Cree un método Scala que tome una función y una lista de nombres de biblioteca, cree un directorio temporal, lea esas bibliotecas de los recursos del jar en archivos en el directorio temporal, agregue el directorio temporal al java.library.path, llame a la función de pasado, y finalmente revierte el java.library.path a lo que era antes.
  • La primera vez que llame a la biblioteca nativa (cuando presumiblemente se inicializará estáticamente y realizará la llamada System.loadLibrary), ajuste esa llamada en particular en su método con la lista de bibliotecas que cargará. De esta forma, cuando llame al System.loadLibrary, todas sus bibliotecas estarán en java.library.path y se cargarán correctamente.

Obviamente, esto es molesto ya que se debe inicializar manualmente la biblioteca de terceros antes de usarlo, pero parece más factible para envolver todos los puntos de inicialización (sus principales funciones y las inicializaciones de prueba) que lo hace para obtener toda de sus herramientas para establecer java.library.path correctamente. Y puede ser aún más fácil que eso si ya tiene su propia capa de abstracción sobre la biblioteca de terceros, por lo que solo hay un punto de inicialización que debe ajustar.

Si eso parece una solución realista, puedo agregar más detalles sobre la tarea SBT o los métodos de envoltura de Scala si está confundido.

0

En Osx, si tiene problemas para cargar libs nativos en /lib/*.jnilib durante sbt test.

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

Usted puede utilizar el siguiente código en lugar de System.loadLibrary("jniortools").

new File("lib").listFiles().map(_.getAbsolutePath).filter(_.endsWith("jniortools.jnilib")).foreach(System.load) 
0

Hay una manera simple.

Supongamos que las bibliotecas nativas almacenan en lib_extra directorio

  1. añadir JNA a libraryDependencies:

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

  2. agrega este código a la compilación.SBT:

    unmanagedResourceDirectories en Compilar + = baseDirectory.value/"lib_extra"

    includeFilter en (Compilar, unmanagedResourceDirectories): = ".dll, .so"

Cuestiones relacionadas