Introduction
This project aim to explain how you build a Java 1.8 native (for win32-x86-64, linux-x86-64 and darwin) maven multiple package using mvn
and few POM.xml.
e.g. You have a cross platform C++ library and a JNI wrapper on it thanks to SWIG.
Then you want to provide a cross-platform Maven package to consume it in a Maven project...
Table of Content
Requirement
You'll need a "Java SDK >= 1.8" and "Maven >= 3.6".
Directory Layout
The project layout is as follow:
-
CMakeLists.txt Top-level for CMake based build.
-
cmake Subsidiary CMake files.
-
ci Root directory for continuous integration.
-
Foo Root directory for
Foo
library.- CMakeLists.txt for
Foo
. - include public folder.
- java
- CMakeLists.txt for
Foo
Java. - foo.i SWIG Java wrapper.
- CMakeLists.txt for
- src private folder.
- CMakeLists.txt for
-
java Root directory for Java template files
- base.i Generic SWIG stuff (e.g. fixing int64 java typemaps).
- pom-native.xml.in POM template to build the native project.
- Loader.java Unpack and load the correct native libraries.
- pom-local.xml.in POM template to build the "pure" Java project.
- Test.java Test source code to verify the Java wrapper is working.
- pom-test.xml.in POM template to build the test project.
Build Process
To Create a native dependent package we will split it in two parts:
- A bunch of
org.mizux.javanative:javanative-{platform}
maven packages for each supported platform targeted and containing the native libraries. - A generic maven package
org.mizux.javanative:javanative-java
depending on each native packages and containing the Java code.
platform
names come from the JNA project (Java Native Access) which will be use to find at runtime on which platform the code is currently running.
Local Package
The pipeline for linux-x86-64
should be as follow:
note: The pipeline will be similar for darwin
and win32-x86-64
architecture, don't hesitate to look at the CI log!
Building local native Package
disclaimer: In this git repository, we use CMake
and SWIG
.
Thus we have the C++ shared library libFoo.so
and the SWIG generated Java wrapper Foo.java
.
note: For a C++ CMake cross-platform project sample, take a look at Mizux/cmake-cpp.
note: For a C++/Swig CMake cross-platform project sample, take a look at Mizux/cmake-swig.
So first let's create the local org.mizux.javanative:javanative-{platform}.jar
maven package.
Here some dev-note concerning this POM.xml
.
- This package is a native package only containing native libraries.
Then you can generate the package and install it locally using:
mvn package
mvn install
note: this will automatically trigger the mvn compile
phase.
If everything good the package (located in <buildir>/java/org.mizux.javanative-<platform>/target/
) should have this layout:
{...}/target/javanative-<platform>-1.0.jar:
\- <platform>
\-libFoo.so.1.0
\-libjnijavanative.so
...
note: <platform>
could be linux-x86-64
, darwin
or win32-x86-64
.
tips: since maven package are just zip archive you can use unzip -l <package>.jar
to study their layout.
Building local Package
So now, let's create the local org.mizux.javanative:javanative-java.jar
maven package which will depend on our previous native package.
Here some dev-note concerning this POM.xml
.
- Add runtime dependency on each native package(s) availabe:
<dependency> <groupId>org.mizux.javanative</groupId> <artifactId>javanative-linux-x86-64</artifactId> <version>[1.0,)</version> <type>jar</type> <scope>runtime</scope> </dependency>
- Add dependency to jna so we can find at runtime the current
<platform>
:
<dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna-platform</artifactId> <version>5.5.0</version> </dependency>
- Add dependency to jna so we can find at runtime the current
Then you can generate the package using:
mvn package
mvn install
If everything good the package (located in <buildir>/java/org.mizux.javanative/target/
) should have this layout:
{...}/target/javanative-java-1.0.jar:
\- org/
\- mizux/
\- javanative/
\- Loader$PathConsumer.class
\- Loader$1.class
\- Loader.class
\- foo/
\- GlobalsJNI.class
\- StringJaggedArray.class
\- IntPair.class
\- StringVector.class
\- Foo.class
\- PairVector.class
\- PairJaggedArray.class
\- Globals.class
...
Testing local Package
We can test everything is working by using the org.mizux.javanative.test:javanative-test
project.
First you can build it using:
cmake --build build
note: javanative-test
depends on javanative-java
which is locally installed in the local maven cache (~/.m2/repository/org/mizux/javanative/...
).
Then you can run it using:
cmake --build build --target test
or manually using:
cd <builddir>/java/org.mizux.javanative.test
mvn exec:java -Dexec.mainClass="org.mizux.javanative.Test"
Appendices
Few links on the subject...
Resources
- POM.xml reference
- Maven Central POM requirement
- Javadoc Plugin
- Java Source Plugin
- Java Native Access Project
Misc
Image has been generated using plantuml:
plantuml -Tsvg doc/{file}.dot
So you can find the dot source files in doc.
License
Apache 2. See the LICENSE file for details.
Disclaimer
This is not an official Google product, it is just code that happens to be owned by Google.