Native compilation with GCJ!

Started by blue_tomato, June 18, 2005, 04:04:59

Previous topic - Next topic

blue_tomato

I have searched the forums about how to natively compile a LWJGL application with GCJ, but found only outdated references to some old GCJ bugs.

Have anyone successfully used GCJ with LWJGL now?

I believe GCJ compiled native code and JVM would be a perfect bundle with my LWJGL games. Fast, small, stand-alone and FREE (as opposed to the much advertised JET)

So far I have bundled the JRE from Sun with my games, adding an install shield for both JRE and game, but their license forces me to keep all kinds of crap I do not need in the rt.jar, like AWT, JDBC, CORBA etc. So, the download is huge, with maybe 90% being junk that is not needed by the game at all! Bandwidth is expensive, and my users are impatient with too low bandwidth at home, so this is not good at all! :(

My stand-alone GCJ programs are TINY compared to this, and also allows a lot of heavy optimizations not available for the realtime JIT compiler approach. I also like the ability to turn off out-of-bounds checks, that really speeds up my inner loops. Also, I like the added security and ease of deployment an exe file gives me.

I noticed this seems to have been solved with JOGL, but I prefer LWJGL. So, if this is possible please let me know how you did it! :)

Matzon

there has been some work done on this. the latest try hit some small snag, that Elias fixed very shortly after. I am not aware of the current startus beyond that.

elias

According to the latest thread about gcj:

http://lwjgl.org/forum/viewtopic.php?t=1129

it should work. I fixed the problem with AWTGLCanvas (I think  :), but in any case, Display should still work fine.

- elias

blue_tomato

Ok, happy to know this is solved. :)

I am a bit newbie with GCJ though, so do you mind to let me know how to compile up a simple example like

http://java-game-lib.sourceforge.net/wiki/tiki-index.php?page=Lesson+4

In fact, it compiles fine, but the linker complains about undefined references. Do I need some special version of the DLL to link properly?

I get (my test program is called HelloSWT, which launches the Lesson04 example)
C:\java\HelloSWT>gcj --main=HelloSWT -o HelloSWT *.o
HelloSWT.o: In function `ZN8HelloSWTC1Eb':
C:/java/HelloSWT/HelloSWT.java:65: undefined reference to `org::lwjgl::opengl::D
isplay::update()'
HelloSWT.o: In function `ZN8HelloSWT8mainloopEv':
C:/java/HelloSWT/HelloSWT.java:75: undefined reference to `org::lwjgl::input::Ke
yboard::poll()'
C:/java/HelloSWT/HelloSWT.java:76: undefined reference to `org::lwjgl::input::Ke
yboard::isKeyDown(int)'
C:/java/HelloSWT/HelloSWT.java:79: undefined reference to `org::lwjgl::opengl::D
isplay::isCloseRequested()'

.. etc

Do you know how to pass the linking stage successfully?

Thanks :)

elias

I'm on shaky grounds here, but I guess that you're missing the equivalent of -classpath. If you natively compiled lwjgl, can you compile your own stuff with something like gcj -o <app> -llwjgl?

- elias

blue_tomato

Quote from: "elias"I'm on shaky grounds here, but I guess that you're missing the equivalent of -classpath. If you natively compiled lwjgl, can you compile your own stuff with something like gcj -o <app> -llwjgl?

- elias

Not sure if I understand what you mean, but I do add the classpath during compilation.

The compiler is invoked by:

gcj --CLASSPATH=C:\java\lwjgl\jar\lwjgl.jar --no-bounds-check -O3 -c -g -O *.java

This produces the right HelloSWT.o file containing the compiled binary machine code (hopefully also the compiled code from the LWJGL.JAR file?), that is to be wrapped with the bundled Garbage collector etc. by the linker.

The linker is invoked by:

gcj --main=HelloSWT -o HelloSWT *.o

So, the full compile and linking process is as follows:

C:\java\HelloSWT>gcj --CLASSPATH=C:\java\lwjgl\jar\lwjgl.jar --no-bounds-check -
O3 -c -g -O *.java

C:\java\HelloSWT>gcj --main=HelloSWT -o HelloSWT *.o
HelloSWT.o: In function `ZN8HelloSWTC1Eb':
C:/java/HelloSWT/HelloSWT.java:65: undefined reference to `org::lwjgl::opengl::D
isplay::update()'
HelloSWT.o: In function `ZN8HelloSWT8mainloopEv':
C:/java/HelloSWT/HelloSWT.java:75: undefined reference to `org::lwjgl::input::Ke
yboard::poll()'
C:/java/HelloSWT/HelloSWT.java:76: undefined reference to `org::lwjgl::input::Ke
yboard::isKeyDown(int)'
C:/java/HelloSWT/HelloSWT.java:79: undefined reference to `org::lwjgl::opengl::D
isplay::isCloseRequested()'
C:/java/HelloSWT/HelloSWT.java:82: undefined reference to `org::lwjgl::input::Ke
yboard::isKeyDown(int)'
C:/java/HelloSWT/HelloSWT.java:86: undefined reference to `org::lwjgl::input::Ke
yboard::isKeyDown(int)'

...etc

So, all seems fine except the linking process. Seems like it cannot find the right references to the proper methods in the DLL file? Any ideas?

I am lost here, but I guess this should be quite trivial to solve if I just knew how to use GCJ properly... :)

Matzon

think the problem is that lwjgl.jar needs to be compiled at the same time too ?

blue_tomato

Quote from: "Matzon"think the problem is that lwjgl.jar needs to be compiled at the same time too ?

Maybe, I guess it is not smart enough to do that automatically as needed...

I tried

gcj -c lwjgl.jar


which gave

C:\java\HelloSWT>gcj -c lwjgl.jar
org/lwjgl/opengl/AWTGLCanvas.java:0: error: cannot find file for class java.awt.
event.HierarchyListener
org/lwjgl/opengl/AWTGLCanvas.java: In class 'org.lwjgl.opengl.AWTGLCanvas':
org/lwjgl/opengl/AWTGLCanvas.java: In constructor '(java.awt.GraphicsDevice,org.
lwjgl.opengl.PixelFormat,org.lwjgl.opengl.Drawable)':
org/lwjgl/opengl/AWTGLCanvas.java:60: error: cannot find file for class java.awt
.event.HierarchyListener
org/lwjgl/opengl/AWTGLCanvas.java:60: confused by earlier errors, bailing out


Seems to be a problem with AWT dependence now?

blue_tomato

Well, I solved the AWT problem by manually removing all classes that was infected with this problem.

Then I successfully produced the lwjgl.o file, and recompiling the main program now gives

C:\java\HelloSWT>gcj --main=HelloSWT -o HelloSWT *.o
lwjgl.o: In function `ZN3org5lwjgl6openal2AL6createEv':
C:/java/HelloSWT/lwjgl.jar:(.text+0x9bd3): undefined reference to `org::lwjgl::o
penal::AL::nCreate(JArray<java::lang::String*>*)'
C:/java/HelloSWT/lwjgl.jar:(.text+0x9be6): undefined reference to `org::lwjgl::o
penal::AL10::initNativeStubs()'
C:/java/HelloSWT/lwjgl.jar:(.text+0x9beb): undefined reference to `org::lwjgl::o
penal::ALC::initNativeStubs()'
C:/java/HelloSWT/lwjgl.jar:(.text+0x9bf8): undefined reference to `org::lwjgl::o
penal::ALC::alcOpenDevice(java::lang::String*)'
C:/java/HelloSWT/lwjgl.jar:(.text+0x9dcb): undefined reference to `org::lwjgl::o
penal::ALC::alcMakeContextCurrent(long long)'
lwjgl.o: In function `ZN3org5lwjgl6openal2AL7destroyEv':
C:/java/HelloSWT/lwjgl.jar:(.text+0x9e9c): undefined reference to `org::lwjgl::o
penal::ALC::alcDestroyContext(long long)'
C:/java/HelloSWT/lwjgl.jar:(.text+0x9ede): undefined reference to `org::lwjgl::o
penal::ALC::alcCloseDevice(long long)'
C:/java/HelloSWT/lwjgl.jar:(.text+0x9f30): undefined reference to `org::lwjgl::o
penal::AL::resetNativeStubs(java::lang::Class*)'
C:/java/HelloSWT/lwjgl.jar:(.text+0x9f78): undefined reference to `org::lwjgl::o
penal::AL::resetNativeStubs(java::lang::Class*)'
C:/java/HelloSWT/lwjgl.jar:(.text+0x9fb3): undefined reference to `org::lwjgl::o
penal::AL::nDestroy()'
lwjgl.o: In function `ZN3org5lwjgl6openal4AL1017alDopplerVelocityEf':
C:/java/HelloSWT/lwjgl.jar:(.text+0xa169): undefined reference to `org::lwjgl::o
penal::AL10::nalDopplerVelocity(float)'
lwjgl.o: In function `ZN3org5lwjgl6openal4AL1015alDopplerFactorEf':
C:/java/HelloSWT/lwjgl.jar:(.text+0xa193): undefined reference to `org::lwjgl::o

etc...

Well, no closer to solution, now I just get problems linking lwjgl instead of problems linking my own program... So much hassle, I have no idea now... :/

AndersD

If I remember correctly, gcj compiles java-native bindings as their own "special jni" by default - you probably need to specify -fjni (?)

EDIT: And as I've noticed you're trying this on windows - you should be aware that gcj can only link statically on windows (IIRC again ;). IMO: Basically the attitude among a lot of the developers on gcj  @ gnu mailing list is quite "anti-windowz" :P (not saying they're impolite if you ask any windows specific questions - just that they not really care about the windows implementation).

blue_tomato

Quote from: "AndersD"If I remember correctly, gcj compiles java-native bindings as their own "special jni" by default - you probably need to specify -fjni (?)

EDIT: And as I've noticed you're trying this on windows - you should be aware that gcj can only link statically on windows (IIRC again ;). IMO: Basically the attitude among a lot of the developers on gcj  @ gnu mailing list is quite "anti-windowz" :P (not saying they're impolite if you ask any windows specific questions - just that they not really care about the windows implementation).

Tried -fjni during linking, no luck.. :(

But, the MinGW team successfully added SWT to GCJ, so it should be possible to add LWJGL the same way...

Unfortunately my own JNI, GCJ and C++ skills are just very basic, I do not see any way out of this mess. Too bad, it would really be great to make this work.

Quite amazing something this simple is that hard... Sigh..

And about anti-windows fanatics, I do not dare to tread in their murky lairs, if you leave them alone with their Linux coding they harm noone... :)

blue_tomato

Woah, made it work now! :D

The trick was to add -fjni to all stages, not only during linking...

The compressed stand-alone distributable is now only 2mb, which is really great!

Now my only concern is about the AWT related methods I removed, but hopefully they are not really doing anything useful.

I suggest all AWT dependence is removed from LWJGL, having no AWT was in fact one of its greatest benefits earlier...

princec

They can be easily removed if you don't want to use them. Really we should supply them as a separate jar.

Cas :)

AndersD

Have you tried compiling lwjgl as a shared dll? Just curious if it will work :)

blue_tomato

Quote from: "AndersD"Have you tried compiling lwjgl as a shared dll? Just curious if it will work :)

Nope, did not try that. But it is a much better idea to use Proguard to link it all together before compiling, then all unused methods and classes are removed. I lost one megabyte of junk from the compressed distributable file this way! :)

My compressed stand-alone distributable is now only slightly over 1mb! It contains everything needed to run a simple openGL based animation, and consists only of one native EXE file and the lwjgl DLL file!

At least, I THINK it contains everything... Hard to know as the team behind GCJ does a fine job in NOT telling whether you need to bundle any DLLs with your GCJ compiled application or not. And after installing MinGV my system is polluted with all kinds of runtime DLLs so I do not know if it works in a clean system or not.

Give it a try if you want, I have put an example here:

http://www.ninjasoftware.com/download/standalone_test.rar

Please let me know if it works on your system, or wheter I need more DLLs with it...

Thanks! :)