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]

Reply via email to