A compiler contributed to xtc that integrates Java with C. Both language and compiler are described in an OOPSLA '07 paper by Martin Hirzel and Robert Grimm.

### Prerequisites

You need Java 1.5, gcc, and the usual GNU tooling (in particular, gcc and make). We have tested Jeannie under Mac OS X with HotSpot, and under Linux and Cygwin with IBM Java.

### Environment variables

JAVA_DEV_ROOT | set this such that $JAVA_DEV_ROOT/xtc is the top-level xtc directory
PATH_SEP | ':' for MacOS or Linux, or ';' for Cygwin
CLASSPATH | $JAVA_DEV_ROOT/classes$PATH_SEP$JAVA_DEV_ROOT/bin/junit.jar$PATH_SEP$JAVA_DEV_ROOT/bin/antlr.jar
JAVA_HOME | set this such that $JAVA_HOME/bin/java is the Java virtual machine
CPATH | should include the directory that contains jni.h, which is most likely $JAVA_HOME/include
PATH | should include $JAVA_HOME/bin
OSTYPE | should be either cygwin, or have linux or darwin as a substring

### Testing using the Makefile

Try the following:

    make -C $JAVA_DEV_ROOT/fonda/jeannie_testsuite test_000

If all goes well, that should produce the output:

    ==== integration test_000 ====
    Processing tmp/000sugared/Main.jni ...
    diff tmp/000mangled/output.txt tmp/000sugared/output.txt

What happened is that the Makefile compiled and ran the same test written in Jeannie (fonda/jeannie_testsuite/input/000sugared_Main.jni) and in JNI (fonda/jeannie_testsuite/input/000mangled_Main.{c,java}), and compared the output.

You can also run all included integration tests in batch mode:

    make -C $JAVA_DEV_ROOT/fonda/jeannie_testsuite test

To find out the individual compilation steps, uncomment the following line in the Makefile:

    # export VERBOSE_MAKE=true

### Compiling your own programs

The easiest way is to follow the existing examples and use the existing Makefiles. But if you prefer to compile by hand, the following example compiles and runs foo/Bar.jni

- Run Jeannie preprocessor to inject "#include <jni.h>" at the start of the file.

      java -ea xtc.lang.jeannie.PreJeannieParser foo/Main.jni > foo/Main.jni.pp

- Run C prepreocessor to resolve #includes, #ifdefs, and macros.

      # Mac OS:
      cc -DSPECIALIZE_RELPROD -DSPECIALIZE_AND -DSPECIALIZE_OR -DSMALL_NODES -U__BLOCKS__ -fomit-frame-pointer -fno-common -I/System/Library/Frameworks/JavaVM.framework/Headers -E -x c foo/Bar.jni.pp > foo/Bar.jni.i
      # Linux:
      gcc -E -x c foo/Bar.jni.pp > foo/Bar.jni.i
      # Cygwin:
      gcc -mno-cygwin -I$JAVA_HOME/include -E -x c foo/Bar.jni.pp > foo/Bar.jni.i

- Run Jeannie compiler.

      # Mac OS or Linux:
      java -ea -DJNICALL='' xtc.lang.jeannie.Jeannie -analyze -translate -in foo foo/Bar.jni.i
      # Cygwin:
      java -ea -DJNICALL='__attribute__((__stdcall__))' xtc.lang.jeannie.Jeannie -analyze -translate -in foo foo/Bar.jni.i

- Compile resulting C code into a shared object file (dynamically linked libary):

      # Mac OS:
      cc -DSPECIALIZE_RELPROD -DSPECIALIZE_AND -DSPECIALIZE_OR -DSMALL_NODES -U__BLOCKS__ -fomit-frame-pointer -fno-common -I/System/Library/Frameworks/JavaVM.framework/Headers -dynamiclib -framework JavaVM -o foo/libBar.jnilib foo/Bar.i
      # Linux:
      gcc -shared -o foo/libBar.so foo/Bar.i
      # Cygwin:
      gcc -mno-cygwin -I$JAVA_HOME/include -Wl,--add-stdcall-alias -shared -o foo/Bar.dll foo/Bar.i

- Compile resulting Java code into class files (bytecode):

      javac -sourcepath foo -d foo foo/Bar.java

- Tell the dynamic linker where to find the shared object file.

      export PATH=foo:"$PATH"
      export LD_LIBRARY_PATH=foo:"$LD_LIBRARY_PATH"

- Run the code with a Java virtual machine.

      java -cp foo -Djava.library.path=foo Bar