TWiki . Sandbox . NativeHowto

How to build a native compiled program that depends on gnu-crypto,swt(,poi) and/or nice with a crossed environment?

You need to keep several issues in mind if you want to do so, even more, if you want to do so with an crossed environment.

Licence issue

Quite a few libraries you depend on, are licenced under the LGPL. Up to a few weeks, I just thought, that a normal LGPL would allow me to use such an library and link against it. That is true, but only for dynamic linking. With a normal LPGL you are not allowed to link your program statically. Some copyright holders still allow you to do so, but you need to read the LICENCEs carefully.

So I assume, that we now use dynamic libraries and we are going to build some.

Different versions

Well, nearly all libraries have interfaces, that change from time to time. So, you cannot plug together two libraries, that interfaces doesn't match.

If you've got quite a few libraries you need to find the best match for all. For me that was to use gcj in version 3.3.1 (mingw-special-version for the crossed version), nice in its latest development version, poi in version 2.0pre3 and swt in version 2.1.1.

Crossed environment

For me windows is the target platform, because many of our customers use that OS, but I'm a linux user, so I wanted to use an cross-compiler. That was not as easy as I first thought, because in the main-trunk of the fsf-gcc sources some patches are not allowed to be applied due to some licence issues. Without some of these patches it is not possible to get Exception Handling working over exe/dll boundaries. So, if only compiling to static binaries, you would be fine with the latest gcc sources, but to get dynamic libraries working properly, you will need the mingw special version (as I used mingw32 as target and windows host emulation; for cygwin something similar might hold). To get proper libraries at all, you will also need a recent binutils package that must be also a special version in a crossed environment (at the moment the linker produces quite huge dll's, but this is only a bug and will be removed in a future version; besides that it works).

Obtain all the sources

You need quite a few sources; which depend on how many of the options you want to build. Let's start with the basic requirement: gcj (as part of the gcc)

What Home Download
binutils-2.14.90 (mingw edition)
gcc-3.3.1 (mingw local patches)
mingw runtime (binary)
mingw Windows-API (binary)
now some optional packages
SWT-2.2.1 (choose 'SWT Binary and Source' for target platform; so it might be:
Jakarta POI-2.0pre3
and NICE

Compile basics

Just to something like follows (pseudo script):

# where are the sources
# where should be everything installed
# target platform
# where to build
# end of configuration section
mkdir -p $BUILD_ROOT
tar xzf $TAR_FILE_DIR/mingw-runtime-3.1.tar.gz
tar xzf $TAR_FILE_DIR/w32api-2.4.tar.gz
Ok, now start building binutils
mkdir binutils-build
tar xzf $TAR_FILE_DIR/binutils-2.14.90-20030807-1-src.tar.gz
cd binutils-build
../binutils-2.14.90-20030807-1/configure --prefix=$DESTINATION --target=$TARGET
make && make install
Now start building gcc (please adjust the configure options as needed, e.g. I only need C,C++ and Java as languages, you might need other too).
# be sure, that new binutils are in path
mkdir gcc-build
tar xjf $TAR_FILE_DIR/gcc-3.3.1.tar.bz2
cd gcc-3.3.1
gzip -d $TAR_FILE_DIR/gcc-3.3.1-20030804-1-src.diff.gz
patch -p1 < $TAR_FILE_DIR/gcc-3.3.1-20030804-1-src.diff
cd ../gcc-build
../gcc-3.3.1/configure --target=mingw32 --prefix=/site.opt/mingw32-cross --without-newlib --enable-shared --enable-libgcj --enable-threads=win32 --enable-languages=c,c++,java --disable-nls --disable-debug --with-gcc --with-gnu-as --with-gnu-ld --without-newlib --disable-win32-registry --enable-libgcj --disable-java-awt --without-x --enable-java-gc=boehm --disable-libgcj-debug --enable-interpreter --enable-hash-synchronization --enable-sjlj-exceptions
make && make install
Ok, now you should have got compiled and installed the most basic requirements in a crossed environment. We will need a shared libgcj.dll and after that we are ready to compile the other libraries.
cd mingw32/libjava
find . -name "*.o" | uniq > objectlist
# now have a sharp look at the objectlist and remove entries that might be the same file,
# but at a different location, e.g. .../.libs/<foo> and .../<foo> is such an candidate.
mingw32-gcj -shared `cat objectlist` -o libgcj.dll -Wl,--out-implib,libgcj.dll.a -Wl,--export-all-symbols -Wl,--enable-runtime-pseudo-reloc -Wl,--allow-multiple-definition
cp libgcj.dll* $DESTINATION/mingw32/lib
Actually I not exactly know, how to work with the generated import lib correctly, but to be sure, that the old static libgcj.a is not used, I rename it to libgcj.b and now you would have to use the importlib, but I will have to ask some other, on how to use that importlib correctly. We will use the dll itself, so it should not matter for the moment.
mv $DESTINATION/mingw32/lib/libgcj.a $DESTINATION/mingw32/lib/libgcj.b
So, we have created a dynamic libgcj.dll. :)

Now you are ready with the most needed things to create shared dll's and shared executables.

Compile first HelloWorld

Take the following file src/test.nice

package test;
void main(String[] args) {
  System.out.println("Hello, World");
and let it compile
nicec --sourcepath src --destination targets test -o test
That will create a test.jar that is an executable jar archive. This file you can now compile to a native executable through gcj
mingw32-gcj --shared -o libhello.dll test.jar -Wl,--out-implib,libhello.dll.a -Wl,--enable-runtime-pseudo-reloc
mingw32-gcj -o hello.exe -L. -lhello -lgcj -Wl,--enable-runtime-pseudo-reloc
Quite easy, isn't it.

Compile runtime nice classes as dll

As we have seen in the last example, the runtime nice classes are included in the hello.dll. That is not usefull and it is even not permitted for LGPL libraries, to included such libraries to your libraries without making your libraries also an LGPL library.

So, we should create a seperate nice.dll as follows. Take the test.jar from the last example and do as follows:

jar xf test.jar
jar cf nice.jar gnu nice
mingw32-gcj --shared -o libnice.dll nice.jar -Wl,--out-implib,libnice.dll.a -Wl,--enable-runtime-pseudo-reloc
Then you can create the executable hello.exe also as follows:
mingw32-gcj --classpath=nice.jar -o hello.exe test/*.class -L. -lnice -lgcj

Compile gnu-crypto as dll

Follow the gnu-crypto INSTALL document and make a gcj-friendly gnu-crypto package. Then simply take the created jars javax-crypto.jar and gnu-crypto.jar and create two dll's:

mingw32-gcj --shared -o libjavax-crypto.dll javax-crypto.jar -Wl,--out-implib,libjavax-crypto.dll.a -Wl,--enable-runtime-pseudo-reloc
mingw32-gcj --shared --classpath=javax-crypto.jar -o libgnu-crypto.dll gnu-crypto.jar -Wl,--out-implib,libgnu-crypto.dll.a -Wl,--enable-runtime-pseudo-reloc

Compile POI-hssf as dll

Well, actually I didn't want the hole POI package but only the hssf part (that needs no other libraries). So you can simply go to the poi src and compile all dependent classes for the hssf package as follows:

cd poi-2.0-pre3/src/java
mkdir ../targets
javac -d ../targets org/apache/poi/hssf/usermodel/
Now we should have all classes needed for the HSSF part of POI in the targets directory. We could now jar all these classes up and then again create a dll from it, but now we use the old style:
cd ../targets
CLASSES=`find . -name "*.class"`
for i in $CLASSES ; do \
mingw32-gcj -c -o `echo $i | sed -e 's/\.class/\.o/'` $i --classpath . \
mingw32-gcj --shared -o libpoi-hssf.dll `find org -name "*.o"` -lgcj -Wl,--out-implib,libpoi-hssf.dll.a -Wl,--enable-runtime-pseudo-reloc

Compile SWT as dll

Well, that might be a bit tricky on the first view, but it is also quite easy:

cd .../swt-windows-src
mingw32-gcj -c --resource=org/eclipse/swt/internal/ -o SWTMessages.o org/eclipse/swt/internal/
echo <<"EOF" >
package org.eclipse.swt.internal.image;
public class SWTImageLoaders
        GIFFileFormat x = new GIFFileFormat();
        PNGFileFormat y = new PNGFileFormat();
        JPEGFileFormat z = new JPEGFileFormat();
        WinBMPFileFormat q = new WinBMPFileFormat();
        WinICOFileFormat p = new WinICOFileFormat();
mingw32-gcj -c -o SWTImageLoaders.o
mingw32-gcj -fjni --shared -o libswt.dll `find . -name "*.o"` -lgcj -Wl,--out-implib,libswt.dll.a -Wl,--enable-runtime-pseudo-reloc -lswt-win32-2135 -L.


I hope, that this howto is a good starting point to get you started with the most common libraries (that I needed for some of my applications) and gcj in a crossed environment. It should now be easy for you to compile other libraries with the same strategies. Don't upset on some hickups, just have a sharp look at the error messages and you most commonly will find a way out. Have fun with your cross compiler toolchain, Christian

-- ChristianS - 04 Oct 2003

----- Revision r1.2 - 04 Oct 2003 - 15:01 GMT - ChristianS
Copyright © 1999-2003 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback.