Hi from a newbie.
I too have been fighting with how best to develop maven artifacts
containing jni parts. Though I found several useful posts on jni and
maven , e.g.
http://www.tricoder.net/blog/?p=197
http://docs.codehaus.org/display/MAVENUSER/Projects+With+JNI
http://www.humboldt.co.uk/2009/02/wrapping-a-native-library-with-maven.html
in the end I rolled my own solution, something I wanted to avoid. My
goal was to produce usable artifacts that worked across platforms, ie
linux 32 and 64 bit and perhaps windows. Here's some notes on my
experiences over the past 3-4 days. My particular jni effort was to
'Java-ify' an existing C library.
I isolated the Java classes which had native methods into a single Maven
module, so producing a single artifact. I placed the Java sources under
the regular src/main/java. In the pom, I used maven-native-plugin to
invoke javah to produce the headers (jn the default location
target/native/javah). In the same pom, I then used the exec plugin to
invoke make in ./native/${os.name}. Both of these are bound to the
compile phase, so a simple
mvn
will compile Java, run javah, then locate correct Makefile and run it.
I then added makefiles to ./native/Linux and ./native/Windows. In
the Linux makefile, I used VPATH to locate the C sources in
${basedir}/src/main/c. The final .so file (which has no platform/arch
encoded into its name, ie is just libfoo.so) is copied by the make into
${basedir}/target/classes/META-INF/lib, so the package phase will locate
the .so at /META-INF/lib/libfoo.so, from which the nifty
com.wapmx.native loader can unpack it at runtime.
The whole artifact is then named
NAME-${os.arch}-${os.name} and installed and/or deployed. this is sort
of a poor man's AOL (from the nar plugin, which I ended up NOT using).
Then a project/module which depends on this artifact simply uses the
name above. It's a bit crude, but for 2 or 3 platforms maximum, I think
it will be manageable.
Points:
the javah invocation could have been done either from Maven or make. I
chose to to it in Maven, mostly to avoid duplication across many
platform Makefiles.
I use the wapmx artifact to extract the native lib from the jar, better
than requiring LD_LIBRARY_PATH solutions.
My particular jni scenario required that the Java side maintain C
pointers (in both directions). Knowing that these would be 64 bits wide
on 64 bit platforms, I had to use Java longs and jlong in the C code.
Compiling on 32 bit Linux, I then had to add
ifeq ($(shell uname -m),i686)
# want any warning to raise error, but silence any 64/32 bit conversions
CFLAGS += -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast
endif
to the Makefile to silence the compiler's warnings. I always compile
with -Werror (any warning is an error, fail to build)
In the C link phase in my makefiles, I statically linked the C library I
am wrapping, call it W. To do this, I used an explicit file name, eg.
cc -o libfoo.so /path/to/libW.a my1.o my2.o
I tried fancy -Wl,-static and -Wl,-shared linker options but it always
failed to link. I should point out that I had sources to libW, so could
configure/make it as desired.
Then my end user (who is handed just a single jar) does not need any
libW.so at runtime.
Paths I investigated but did not finally use:
having the Java classes containing the native methods (call it A) and
the actual .so (call it B) as separate Maven modules, as explained in
the first url above. Then B depends upon A being built so that javah can
locate .class files, but then how do you run test cases in A, since you
need native code in B.
I did not use maven-nar-plugin, since as suggested, it is really a Maven
solution to wider native development. I had a localised (or so I think)
jni issue.
I used maven-native-plugin over the antrun-plugin, which apparently
would also give access to javah (would this require an extra Ant
build.xml or can this be 'embedded' in the pom???)
Comments, suggestions welcomed
Stuart
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]