Using GCJ to compile Jung (Java Universal Network and Graph ... thing)

Dan Bolser dmb@mrc-dunn.cam.ac.uk
Mon Nov 29 22:54:00 GMT 2004


Here I my story... 

Way back when I wanted to start a project on Savannah to do a very simple
task using very complex software. I needed to use Savannah so that I could
get collaboration from a particular developer, so OK, I (tried to)  
register the project.

For the curious the software I wanted to use is here...

http://comas.soi.city.ac.uk/prova/

Naturally enough, registering a reasonablly complex java project on
Savannah was not a walk in the park - I had my first experience with GCJ
and a rude awakening to SUN. 

The first thing I needed to do was upgrade my GCC and learn some java (I
know very little java). Back then (RH9) I was installing RPMs and solving
deps. by hand, and as the network of deps. spread, somewhere I got lost,
and ended up with a broken RH9.

Now I am FC2, and very hapily using YUM to keep track of all those deps.

Time had passed (banging my head against first the FC2 and nvidia problem,
and then the USB problem) - and I had forgotten all about my original aim
of registering a project, however, I had been left with a machine with no
SUN, and a lurking feeling that it should stay that way.

I really need to be doing other things... 

One of those things is an analysis of a biological protein interaction
network. I decided to use JUNG to get some measures for my proteins, and I
decided to use this as an opportunity to learn about GCJ.

http://jung.sourceforge.net/


The biggest problem I found in learning GCJ was that information is geared
towards telling someone who is already familiar with GCC how to use it. I
am barly familiar with Java, and didn't really knwo what was going on.

I tried to make some crib notes as I went along, as I couldn't find any
gcj HOWTO. These are surly improvable, but free to use... here they are 
unedited...


__BEGIN__

First, adjust your verion of gcc if you have a newer install (gcj is
constantly under development, so new features of the java language will be
incorperated all the time).
 
# Location of gcc install dir
# (set with --prefix during compile)
GCC-VERSION=/usr/share/gcc-4.0

export PATH=$GCC-VERSION/bin/:$PATH
export LD_LIBRARY_PATH=$GCC-VERSION/lib:$LD_LIBRARY_PATH
 
That is all you need to do to make use of a certain gcc version.
 
 
Using gcj to compile a very simple java program...
 
Usually one file = one class, and the class name is the same as the file
name. For example className.java
 
gcj --main=className className.java -o myProg
 
It's that simple!

For example ...

public class FirstSample
{
   public static void main(String[] args)
   {
      System.out.println("Hello World!");
   }
}

gcj --main=FirstSample FirstSample.java -o myProg_FirstSample

Then ...

./myProg_FirstSample
Hello World!

To 'link' .jar or .zip files you must fist compile them into an object
file (later we link up the object files into the executable file). To do
that use the following ...

find ./* -name *.java > files

gcc -C @files

jar -cf myJar.jar `find ./* -name *.class`

gcc -c myJar.jar -o myJar.o

This first compiles (-C) the .java files found (using find) into 'native'
.class files. Add a --classpath predicate here if you need to bring in
classes which your .java files depend on (i.e. if you import them). Then
we make a .jar archive (simply a set of .class files), then compile (-c)
the archive into an object file. You can then use this in the following
way (to build an execuable)...

gcj --main=test test.java myJar.o -o myProg_test

Use the same classpath here as you did above.


A simpler way (more java like) to do somthing similar is the following...

gcj -C test.java --classpath myJar.jar

Then...

gij --classpath myJar.jar:. test

__END__


Then I set about trying to implement my own instructions. I got most of
these details from pinskia (as I remember) on the #gcc irc channel, and he
pointed me at the #gcj irc channel, which proved to be invaluable.

The first thing I tried to do was build an executable from a test app (I
had previously used with SUN Java and JUNG). I had changed some stuff and
was trying to compile it, I needed the jung.jar in my --classpath. When my
app compiled finally I got tons of warnings - I was doing something like

gcj -c test.java -o test --classpath=jung.jar

The warnings were all about jung namespace thingies in my /tmp

So I tried to make the jung.o to link against during compile, that was a
can of worms.

I found the 'find ./* -name *.java > files; gcj -C @names' trick after
thrashing around for a bit (almost literally) - I didn't really know what
I was doing, then I found I needed 

gcj -C @names --classpath for the various clases needed by jung. I didn't
realize that some .zip distributions need to be unzipped before you find
the .jar inside!

The line looked like this...

gcj -C @files --classpath=/usr/share/java/colt.jar:/usr/share/java/commons-collections-3.1.jar:/usr/share/java/xmlParserAPIs.jar:/usr/share/java/junit.jar

See http://jung.sourceforge.net/download.html for a list of deps.

So now I came across (again) the String.split() problem in gcc-3.3 or
whatever ships with FC2 + up2date (I had fixed this in my own code, but
didn't feel like fixing it in Jung). The nice people in the IRC suggested
GCC-4.0, so I jumped in

./compile --prefix=${HOME}/gcc-4.0

And set paths as above.

First I  warmed up by compiling colt into myColt.jar
  
Aside, colt compiled quite easily with the same @files trick, except for
one thing, utf.

I got round this problem rather elequently with the following...

fixTheFucker.sh
#!/bin/sh
 
echo "Fixing $1"
 
mv $1 $1.whatThe
grep "^Copyright" -v $1.whatThe > $1
rm $1.whatThe


They like to say (C) properly in the colt sources!

I was building the jar like this... 

jar -cf myColt.jar `find ./* -name *.class` 

after building all the .java files in the src/ directory of the colt
distribution.

Oh, I just remebered, colt defines the same classes multiple times in
different locations... 

These cause problems and are under

src/jal/generic/{object|numeric|string}/*

Similar but different classes

Solution: rm jal/generic/  -rf 

Then I had problems with something like
./edu/oswego/cs/dl/util/concurrent/misc/SynchronizationTimer.java
./edu/oswego/cs/dl/util/concurrent/misc/SwingWorker.java

So I canned them. Then it compiled.


Also someting like gcj -c colt.zip -o colt.o works (does something). I was
trying crazy things.

At this point I didn't know what gij was or what it was for.

So I boldy jump into jung and keep tyring 

gcj -C @files --classpath=/usr/share/java/myColt.jar:/usr/share/java/commons-collections-3.1.jar:/usr/share/java/xmlParserAPIs.jar:/usr/share/java/junit.jar


Biggest problem was the nested class hierarch bug not resolving
properly, (inherited inner classes)

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18131

and being supplied with the wrong colt package on the cern website!


With help I made all the calles to inherited inner classes explicit
(thanks to mjw).


These issues I sent to the jung mailing list

http://sourceforge.net/mailarchive/forum.php?thread_id=6047661&forum_id=34661
http://sourceforge.net/mailarchive/forum.php?thread_id=6046149&forum_id=34661
http://sourceforge.net/mailarchive/forum.php?thread_id=6049768&forum_id=34661


The jung source wasn't compile friendly, and I had to drop some junk they
were developing.

Finally the only class that wouldn't compile was PluggableRenderer
http://jung.sourceforge.net/doc/api/edu/uci/ics/jung/visualization/PluggableRenderer.html

so I binned it (and the test examples that use it).

It compiled and I built the jar as before.


So now I was ready to try the following...

gcj -c myJung.jar -o myJung.o
gcj -c junit.jar -o junit.o 
gcj -c commons-collections-3.1.jar -o commons-collections-3.1.o 
gcj -c myColt.jar -o myColt.o 
gcc -c xmlParserAPIs.jar -o xmlParserAPIs.o 

gcj --main=test test.java ../jung/myJung.o ../junit.o ../colt/src/myColt.o
../commons-collections-3.1.o ../xmlParserAPIs.o -o well
--classpath=/usr/share/java/myJung.jar


Which turned my 50 or so lines into a mammoth 13M seg-fault machine!

I was confused.



Then the gij penny dropped...

gcj -C test.java --classpath=/usr/share/java/myJung.jar 
gij --classpath /usr/share/java/myJung.jar:/usr/share/java/commons-collections-3.1.jar:. test 

(that last line was picky!)

A little more debugging (runtime errors) and I was set :)


Again, I cannot stress how much help the IRC gave me (all of you!). For
every line of code above I must have put 50 into xchat.

It has been really fun doing this - native sentement of joy, I thank
you for this thing! (A cat-power lyric).

All the best,

Dan, AKA faceface








More information about the Java mailing list