java - Maven y la biblioteca JOGL?
maven-2 build-process (7)
Aquí, como referencia, es la parte de mi archivo Ant build.xml que descarga y descomprime la biblioteca JOGL (2.0 beta 10).
<target name="libraries" depends="libraries.jogl" />
<target name="libraries.jogl.check">
<condition property="libraries.jogl.exists">
<available file="lib/jogl" />
</condition>
</target>
<target name="libraries.jogl" depends="libraries.jogl.check" unless="libraries.jogl.exists">
<condition property="joglostype" value="windows-i586">
<and>
<os family="windows" />
<or>
<os arch="i386" />
<os arch="x86" />
</or>
</and>
</condition>
<condition property="joglostype" value="windows-amd64">
<and>
<os family="windows" />
<os arch="amd64" />
</and>
</condition>
<condition property="joglostype" value="linux-i586">
<and>
<os name="Linux" />
<or>
<os arch="i386" />
<os arch="x86" />
</or>
</and>
</condition>
<condition property="joglostype" value="linux-amd64">
<and>
<os name="Linux" />
<or>
<os arch="AMD64" />
<os arch="x86_64" />
</or>
</and>
</condition>
<echo>Detected operating system: ${joglostype}</echo>
<echo>(if invalid OS, update ant build file)</echo>
<mkdir dir="lib" />
<get src="http://download.java.net/media/jogl/builds/archive/jsr-231-2.0-beta10/jogl-2.0-${joglostype}.zip" dest="lib/jogl.zip" usetimestamp="true" />
<mkdir dir="lib/jogl" />
<unzip src="lib/jogl.zip" dest="lib/jogl">
<patternset>
<include name="**/gluegen-rt.jar" />
<include name="**/jogl.all.jar" />
<include name="**/nativewindow.all.jar" />
<include name="**/newt.all.jar" />
<include name="**/*.so" />
<include name="**/*.dll" />
</patternset>
<mapper type="flatten" />
</unzip>
</target>
He estado estudiando Maven en mi tiempo libre en los últimos días, pero parece que no puedo imaginar cómo organizar un proyecto para que se utilicen las bibliotecas JOGL. Preferiría preferir lo siguiente:
- Descargue automáticamente, si es necesario, el archivo zip JOGL específico del sistema operativo desde here (contiene 4 archivos jar y algunos archivos de biblioteca nativos (.so / .dll)); o depende de un proyecto Maven que es un contenedor de uno de los archivos.
- Descomprime ese archivo zip apropiadamente, para que:
- los archivos jar se agregan a la ruta de clase y se implementan según sea necesario, y
- los archivos de la biblioteca nativa se agregan al archivo jar final (¿esto les permitiría usarlos automáticamente, o necesitaría algo más involucrado?)
Creo que parte de mi problema es que no entiendo completamente el uso de JOGL, dónde colocar las bibliotecas nativas cuando ejecuto el código, etc. Necesito volver a lo básico y escribir un mundo de JOGL hello, compilarlo desde la línea de comando y ejecutarlo desde la línea de comando para ver exactamente lo que requiere en cuanto a la ubicación del directorio de las bibliotecas nativas; Puedo hacer eso ahora, en realidad.
Con el artículo 1, he encontrado algunas características específicas del sistema operativo; Los perfiles de Maven se pueden activar en función de las propiedades del sistema, que incluyen el sistema operativo. Entonces podría activar un perfil de Windows que tiene una dependencia de la biblioteca JOGL específica de Windows, lo mismo para Linux, y ambos tienen un alter ego de 64 bits. (Documentos oficiales de activación / documentos no oficiales )
Intenté crear un repositorio Maven basado en un archivo jar JOGL y luego agregar el proyecto JOGL jar como una dependencia de mi proyecto; la dependencia se descarga, pero no se usa. No tengo idea de dónde va el archivo jar o cómo usarlo, descomprimirlo, etc. Aquí está el comando que utilicé.
Entonces, en resumen: JOGL consta de cuatro archivos .jar y algunas bibliotecas nativas. ¿Cómo puedo integrar esos archivos en mi proyecto Maven para poder escribir una aplicación JOGL con Maven manejando mi proceso de compilación? Además, ¿cómo puedo usar un conjunto diferente de archivos dependiendo del sistema operativo, porque por supuesto las bibliotecas nativas e incluso los archivos .jar difieren entre Windows, Linux y Mac?
Cuando se trata de JNI y Maven, Projects with JNI es la referencia con la que se debe comenzar. Cubre mucho más que su problema actual (que es "solo" usar una biblioteca que se basa en JNI y bibliotecas nativas) pero, bueno, el que puede hacer más puede hacer menos.
Si lo lees detenidamente, verás que una solución para usar las bibliotecas JNI es agruparlas en archivos JAR específicos de la arquitectura para que puedas confiar en ellos como cualquier otra dependencia desde el punto de vista de Maven. Así es como se empaqueta JOGL versión 1.1.1 en http://download.java.net/maven/2/net/java/dev/jogl/ , hay un artefacto JAR con las clases Java y varios artefactos JAR específicos de la arquitectura con las bibliotecas nativas
Biblioteca JNI archivada dentro del contenedor
La solución que terminé usando fue almacenar la biblioteca jni compilada en el contenedor junto con los archivos de clase.
Esto significa compilación cruzada para todas las arquitecturas posibles, o más simplemente, tener un contenedor diferente para cada arquitectura. Este último encaja bastante bien con nuestra configuración, donde casi todas nuestras máquinas son Linux-i386, con un puñado de cajas win32.
Lamentablemente,
System.load()
no puede hacer frente a la carga de bibliotecas desde un contenedor, por lo que necesitaremos un cargador personalizado que extraiga la biblioteca en un archivo temporal en tiempo de ejecución; esto es obviamente alcanzable, sin embargo.
Luego, como se explicó, la idea es usar un cargador de biblioteca personalizado para cargar la biblioteca nativa. La buena noticia es que dicho cargador está "provisto" como se explica a continuación.
Cargador de la biblioteca
Ahora tenemos nuestra biblioteca JNI en la ruta de clase, por lo que necesitamos una forma de cargarla. Creé un proyecto separado que extraería bibliotecas JNI de la ruta de clase, y luego las cargaría. Encuéntrelo en http://opensource.mxtelecom.com/maven/repo/com/wapmx/native/mx-native-loader/1.2/ . Esto se agrega como una dependencia al pom, obviamente.
Para usarlo, llame a
com.wapmx.nativeutils.jniloader.NativeLoader.loadLibrary(libname)
. Hay más información en el javadoc paraNativeLoader
.Por lo general, prefiero envolver dichos elementos en un bloque try / catch, de la siguiente manera:
public class Sqrt { static { try { NativeLoader.loadLibrary("sqrt"); } catch (Throwable e) { e.printStackTrace(); System.exit(1); } } /* ... class body ... */ }
Ahora deberíamos estar en el punto donde nuestras pruebas junit funcionan desde maven; ¡una prueba de mvn debería funcionar! También debería funcionar bien desde un IDE.
Ahora, para responder sus preguntas, cómo:
Descargue automáticamente, si es necesario, el archivo zip JOGL específico del sistema operativo desde aquí (contiene 4 archivos jar y algunos archivos de biblioteca nativos (.so / .dll)); o depende de un proyecto Maven que es un contenedor de uno de los archivos.
Lamentablemente, JOGL 2.0 jar no está disponible en el repositorio de Maven de java.net, por lo que tendrás que lidiar con eso y ponerlos a disposición en un repositorio privado o instalarlos manualmente en el repositorio local de cada desarrollador. Para hacerlo, use mvn install:install-file
como se documenta en la Guía para instalar mvn deploy:deploy-file
terceros (y no mvn deploy:deploy-file
como lo hizo, este objetivo se usa para instalar artefactos en un repositorio remoto).
Personalmente, descargaría JOGL 2.0 ZIP de here me proporcionó, lo empaqueté como lo hicieron con JOGL 1.1.1 (un Java JAR y varios JAR específicos para bibliotecas nativas) e instalaré los JAR en cada repositorio local por el momento. Luego, declare una dependencia estándar en el artefacto Java y, de hecho, use profiles para la dependencia específica de la arquitectura. Algo como esto:
<project>
...
<dependencies>
<dependency>
<groupId>net.java.dev.jogl</groupId>
<artifactId>jogl</artifactId>
<version>2.0-beta10</version>
</dependency>
...
</dependencies>
...
<profiles>
<profile>
<id>linux-i586</id>
<activation>
<os>
<arch>i386</arch>
<family>unix</family>
<name>linux</name>
</os>
</activation>
<dependencies>
<dependency>
<groupId>net.java.dev.jogl.jogl-linux-i586</groupId>
<artifactId>jogl-linux-i586</artifactId>
<version>2.0-beta10</version>
</dependency>
</dependencies>
</profile>
...
</profiles>
...
</project>
No olvide agregar el repositorio requerido para el cargador de biblioteca personalizado y la dependencia:
<project>
<repositories>
<repository>
<id>opensource.mxtelecom.com</id>
<url>http://opensource.mxtelecom.com/maven/repo</url>
</repository>
...
<repositories>
...
<dependencies>
<dependency>
<groupId>com.wapmx.native</groupId>
<artifactId>mx-native-loader</artifactId>
<version>1.2</version>
</dependency>
...
</dependencies>
...
</project>
En cuanto a la segunda parte de tu pregunta:
Descomprime ese archivo zip apropiadamente, para que (...)
Como expliqué, en realidad no dependerá de los archivos ZIP sino de los JAR y no necesitará descomprimirlos ni durante el desarrollo ni para distribuir su proyecto. Para la distribución, solo deberá crear un jar que incluya las dependencias. Esto se puede hacer con el complemento maven-assembly-plugin. Vea esta respuesta, por ejemplo, para más detalles sobre esto.
Hay un repositorio maven para JOGL 2.0 aquí: jogamp.org/deployment/maven
Yo uso SBT para construir mis proyectos. La resolución que necesita agregar a build.sbt
:
resolvers += MavenRepository("jogamp", "http://jogamp.org/deployment/maven")
Y la dependencia, por ejemplo, para la base jogl library:
libraryDependencies += "org.jogamp.jogl" % "jogl-all" % "2.0-rc9"
En los archivos maven xml esto sería algo así como (de acuerdo con this ):
<settings>
<profiles>
<profile>
<id>jogamp</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>jogamp-remote</id>
<name>jogamp test mirror</name>
<url>http://www.jogamp.org/deployment/maven/</url>
<layout>default</layout>
</repository>
</repositories>
</profile>
</profiles>
</settings>
Con la dependencia declarada como:
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all</artifactId>
<version>2.0-rc9</version>
</dependency>
Para descargar automáticamente el jar nativo correcto, en sbt hago algo como:
sys.props("os.name") match {
case "Linux" => "org.jogamp.jogl" % "jogl-all-natives-linux-i586" % "2.0-rc9"
... etc. ...
Jogamp ahora contiene soporte para Maven, para los componentes jogl (el soporte joc y joal está disponible). A partir de 2.0-rc11, los paquetes se envían a Maven Central.
Solo pon esto en tu pom:
<dependencies>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt-main</artifactId>
<version>2.0-rc11</version>
</dependency>
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all-main</artifactId>
<version>2.0-rc11</version>
</dependency>
</dependencies>
Maven extraerá todas las dependencias la próxima vez que intente construir el proyecto.
No conozco la biblioteca JOGL pero tengo experiencia con Java3d, que tiene los mismos problemas de instalación / construcción. Hay dos formas de lograr esto:
decirles a los desarrolladores que instalen JOGL sin ayuda, luego trate las librerías JOGL como dependencias del sistema como lo hacemos con Java3d
<dependency> <groupId>javax.java3d</groupId> <artifactId>j3dcore</artifactId> <version>1.5.1</version> <scope>system</scope> <systemPath>${java.home}/lib/ext/j3dcore.jar</systemPath> </dependency>
coloque todas las jarras y bibliotecas dependientes del sistema en el repositorio propio y cree poms adecuados para ellas
Si desea automatizar con Maven la instalación de JOGL, puede intentar usar maven-antrun-plugin o crear su propio plugin Maven que maneje la instalación (un buen ejemplo es Cargo que descarga servidores y descomprime).
Considero usar la primera opción: decirles a los desarrolladores que instalen JOGL. En nuestro caso, la aplicación Java3d es distribuida por Java WebStart, por lo que para ellos la instalación de Java3d está totalmente automatizada por WebStart.
No hay una manera fácil de lograr esto con. Intente si puede configurar maven-assembly-plugin para construir un jar ejecutable y empaquetar los archivos correctos con su código. No puede usar la administración de dependencia maven para lograr esto porque necesita los contenidos ZIP, no el ZIP en sí. Podrías probar el maven-antrun-plugin .
este script descargará una versión de una URL e instalará en un repositorio local (nombrado). https://gist.github.com/1624599
ejemplo de uso: ./install_jogl_maven http://jogamp.org/deployment/v2.0-rc5 path_to_local_repo 2.0-rc5