[SOLVED] Compiling c natives for JNI centric jar's in linux

I wasn’t sure if I should post this in coding or Linux but chose code since I assume a lot of people who frequent here also know how to compile from source using a make file in Linux.

So after battling with an API that I determined was not complete and would not allow for communicating over bluetooth serial

So after spending 2 days battling with that, I found Bluecove-Bluez which unlike Bluecove-gpl, won’t force me to use the GPL license. Great. Only issue is the available jars are compiled with natives for X86/64. No ARM (I’m building for a Raspberry Pi)

Should be simple, just need to compile on my pi and be done. Only issue is it requires Java D-bus that also, requires natives that are again not compiled for ARM. And Java D-bus? Requires another library that you guessed it, Needs natives compiled for ARM.

Links:
BlueCove 2.1.1
http://snapshot.bluecove.org/distribution/download/2.1.1-SNAPSHOT/2.1.1-SNAPSHOT.62/
Java D-bus
https://dbus.freedesktop.org/releases/dbus-java/
libmatthew
http://www.matthew.ath.cx/projects/java/

So going down the rabbit hole for something that I hoped would be just working with bluetooth, I grabbed the sources and tried to compile libmatthew first.

Going through the instructions, I just need to use the Makefile which I’ll dump here

JAVAC?=javac
JAVADOC?=javadoc
JAR?=jar
JAVAH?=javah
GCJ?=gcj
CC?=gcc
LD?=gcc
JPPFLAGS+=-C -P
CFLAGS+=-Wall -Os -pedantic -Werror
CSTD?=-std=c99
CSHAREFLAG+=-fpic -fno-stack-protector
GCJJNIFLAG=-fjni
JVERCFLAGS+=-source 1.5
JCFLAGS+=
INCLUDES+=-I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux
JAVADOCFLAGS?=-quiet -author -link http://java.sun.com/j2se/1.4.2/docs/api/

LDVER?=$(shell ld -v | cut -d' ' -f1)
UNAME?=$(shell uname -s)

ifeq ($(LDVER),GNU)
LDSHAREFLAGS+=-fpic -shared
else
LDSHAREFLAGS+=-lc
endif

PREFIX?=/usr/local
JARDIR?=$(PREFIX)/share/java
DOCDIR?=$(PREFIX)/share/doc/libmatthew-java/
LIBDIR?=$(PREFIX)/lib/jni

MATTVER=0.8.1
DEBUGVER=1.1
UNIXVER=0.5
CGIVER=0.6
IOVER=0.1
HEXVER=0.2

SRC=$(shell find cx -name '*.java' -and -not -name 'Debug.java')

DEBUG?=disable

.NOPARALLEL:
.NO_PARALLEL:
.NOTPARALLEL:

all: unix-$(UNIXVER).jar cgi-$(CGIVER).jar debug-enable-$(DEBUGVER).jar debug-disable-$(DEBUGVER).jar io-$(IOVER).jar hexdump-$(HEXVER).jar libcgi-java.so libunix-java.so

dist: libmatthew-java-$(MATTVER).tar.gz

classes: .classes 
.classes: $(SRC) 
	mkdir -p classes
	$(MAKE) .$(DEBUG)debug
	$(JAVAC) $(JVERCFLAGS) $(JCFLAGS) -d classes -cp classes $^
	touch .classes
clean:
	rm -rf classes doc
	rm -f .classes .enabledebug .disabledebug *.o *.h *.so *.tar.gz *.jar *.cgi Manifest
	rm -rf libmatthew-java-$(MATTVER)

cgi-$(CGIVER).jar: .classes
	(cd classes; $(JAR) cf ../$@ cx/ath/matthew/cgi/*class)
io-$(IOVER).jar: .classes
	(cd classes; $(JAR) cf ../$@ cx/ath/matthew/io/*class)
unix-$(UNIXVER).jar: .classes
ifeq ($(DEBUG),enable)
	echo "Class-Path: $(JARDIR)/debug-$(DEBUG).jar" > Manifest
else
	echo "Class-Path: " > Manifest
endif
	(cd classes; $(JAR) cfm ../$@ ../Manifest cx/ath/matthew/unix/*class)

hexdump-$(HEXVER).jar: .classes
	(cd classes; $(JAR) cf ../$@ cx/ath/matthew/utils/Hexdump.class)

%.o: %.c %.h
	$(CC) $(CFLAGS) $(CSTD) $(CSHAREFLAG) $(INCLUDES) -c -o $@ $<
lib%.so: %.o
	$(CC) $(LDFLAGS) $(LDSHAREFLAGS) -o $@ $<
headers: .classes
	$(JAVAH) -classpath classes -o $@ cx.ath.matthew.unix.UnixServerSocket cx.ath.matthew.unix.UnixSocket cx.ath.matthew.unix.USInputStream cx.ath.matthew.unix.USOutputStream
	$(JAVAH) -classpath classes -o $@ cx.ath.matthew.cgi.CGI

test.cgi: cgi-$(CGIVER).jar libcgi-java.so
	$(GCJ) $(GCJFLAGS) $(GCJJNIFLAG) -L. -lcgi-java -o test.cgi --main=cx.ath.matthew.cgi.testcgi cgi-$(CGIVER).jar
	
libmatthew-java-$(MATTVER).tar.gz: Makefile cx cgi-java.c unix-java.c README INSTALL COPYING changelog unix-java.h cgi-java.h
	mkdir -p libmatthew-java-$(MATTVER)
	cp -a $^ libmatthew-java-$(MATTVER)
	tar zcf $@ libmatthew-java-$(MATTVER)

debug-enable-$(DEBUGVER).jar: cx/ath/matthew/debug/Debug.jpp
	make .enabledebug
	echo "Class-Path: $(JARDIR)/hexdump.jar" > Manifest
	(cd classes;jar cfm ../$@ ../Manifest cx/ath/matthew/debug/*.class)
debug-disable-$(DEBUGVER).jar: cx/ath/matthew/debug/Debug.jpp
	make .disabledebug
	echo "Class-Path: $(JARDIR)/hexdump.jar" > Manifest
	(cd classes;jar cfm ../$@ ../Manifest cx/ath/matthew/debug/*.class)
.enabledebug: cx/ath/matthew/debug/Debug.jpp 
	mkdir -p classes
	cpp $(PPFLAGS) $(JPPFLAGS) -DDEBUGSETTING=true < cx/ath/matthew/debug/Debug.jpp > cx/ath/matthew/debug/Debug.java
	$(JAVAC) $(JVERCFLAGS) $(JCFLAGS) -cp classes -d classes cx/ath/matthew/debug/Debug.java cx/ath/matthew/utils/Hexdump.java
	rm -f .disabledebug
	touch .enabledebug
.disabledebug: cx/ath/matthew/debug/Debug.jpp 
	mkdir -p classes
	cpp $(PPFLAGS) $(JPPFLAGS) -DDEBUGSETTING=false < cx/ath/matthew/debug/Debug.jpp > cx/ath/matthew/debug/Debug.java
	$(JAVAC) $(JVERCFLAGS) $(JCFLAGS) -cp classes -d classes cx/ath/matthew/debug/Debug.java cx/ath/matthew/utils/Hexdump.java
	rm -f .enabledebug
	touch .disabledebug
cx/ath/matthew/debug/Debug.java: .disabledebug
doc/index.html: 
	$(JAVADOC) $(JAVADOCFLAGS) -d doc/ cx/ath/matthew/debug/Debug.java $(SRC)

doc: doc/index.html

install-doc: doc/index.html
	install -d $(DESTDIR)$(DOCDIR)
	cp -a doc $(DESTDIR)$(DOCDIR)/api

install-native: libcgi-java.so libunix-java.so 
	install -d $(DESTDIR)$(LIBDIR) 
	install libcgi-java.so $(DESTDIR)$(LIBDIR)
	install libunix-java.so $(DESTDIR)$(LIBDIR)

install-jar: unix-$(UNIXVER).jar cgi-$(CGIVER).jar debug-enable-$(DEBUGVER).jar debug-disable-$(DEBUGVER).jar io-$(IOVER).jar hexdump-$(HEXVER).jar
	install -d $(DESTDIR)$(JARDIR)
	install -m 644 debug-enable-$(DEBUGVER).jar $(DESTDIR)$(JARDIR)
	install -m 644 debug-disable-$(DEBUGVER).jar $(DESTDIR)$(JARDIR)
	install -m 644 unix-$(UNIXVER).jar $(DESTDIR)$(JARDIR)
	install -m 644 cgi-$(CGIVER).jar $(DESTDIR)$(JARDIR)
	install -m 644 io-$(IOVER).jar $(DESTDIR)$(JARDIR)
	install -m 644 hexdump-$(HEXVER).jar $(DESTDIR)$(JARDIR)
	ln -sf debug-disable-$(DEBUGVER).jar $(DESTDIR)$(JARDIR)/debug-disable.jar
	ln -sf debug-enable-$(DEBUGVER).jar $(DESTDIR)$(JARDIR)/debug-enable.jar
	ln -sf unix-$(UNIXVER).jar $(DESTDIR)$(JARDIR)/unix.jar
	ln -sf io-$(IOVER).jar $(DESTDIR)$(JARDIR)/io.jar
	ln -sf cgi-$(CGIVER).jar $(DESTDIR)$(JARDIR)/cgi.jar
	ln -sf hexdump-$(HEXVER).jar $(DESTDIR)$(JARDIR)/hexdump.jar

install: install-native install-jar

I type

sudo make install
And I get

cc -Wall -Os -pedantic -Werror -std=c99 -fpic -fno-stack-protector -I/include -I            /include/linux -c -o cgi-java.o cgi-java.c
cgi-java.c:28:17: fatal error: jni.h: No such file or directory
 #include <jni.h>
                 ^
compilation terminated.
Makefile:78: recipe for target 'cgi-java.o' failed
make: *** [cgi-java.o] Error 1

I have openjdk-9-jdk installed and check the install location for jni.h and it’s there.

pi@raspberrypi:/usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/include/jni.h

I’m stuck and don’t know where to go to from here. I just need to get these jars compiled so I can continue on my work (Bluetooth being a pain to work with in itself) but I have hit a roadblock

Fixed, For future reference, JAVA_HOME is deprecated in linux so manually setting the location in the makefile fixed the issue

2 Likes

Since you fixed it, I added [SOLVED] to the title.