Friday, August 19, 2005

Building libgcj.dll for MinGW with GCC 4.1

Here's some notes from my experience building libgcj.dll for MinGW using the GCC 4.1 (May 15, 2005 snapshot). This required a good deal of effort for me to figure out since quite a few things have diverged since the last reported sighting I could find of a working libgcj.dll.

Note that this entire process was done using a cross compiler hosted on Linux.

First, it should be noted that I upgraded libtool prior to building the DLL. When I get some time, I'll rebuild it with pristine sources and make sure it works without this step. The basic process to upgrading libtool is:
  • Copy libtool.m4 from a newer libtool distro to the root gcc source directory
  • Run autoconf (version 2.59) followed by automake (version 1.9.3) in the subdirectories that will be built. Do not regenerate the config on the root directory unless if you make special arrangements to regenerate it with autoconf version 2.13.
  • In the libjava target, you will manually have to patch the generated libtool after it gets created. You will need to change the "compiler_c_o" property in the GCJ section to "yes". This is line 7278 of the version of libtool I used. Not doing this will cause problems when the Makefile tries to compile resources. There has got to be a better way to make this work, but I am not terribly familiar with libtool and didn't look into it.
My primary motivation for upgrading libtool was to see if it would just automagically generate the dll for me. Sadly, this didn't work but I think it tried. With that being the case, it is probably ok to skip the libtool upgrade altogether.

I also ran into a problem with the sequence of the build. During the first pass build, the gnu-java-beans.lo file is generated prior to the most of its classfiles being compiled. Because of this, it only contains a handful of classes, which causes a lot of undefined references when building the dll later. I think this is a general problem that just doesn't manifest very often because the java.beans.* API is very rarely used in practice. A work-around is simple enough. After you build it once, just delete the generated gnu-java-beans.lo and rerun make. Since all of the class files are present the output file will be created as expected. You should see that the backing .o file(s) are much larger the second time around.

The next step is to create the actual dll. You should be aware that this is an extremely memory intensive operation. The memory usage of ld tops off at about 630MB on my machine. If you don't have at least this much physical memory available to ld, your machine could thrash for hours.

I used the following script to create the dll:

#!/bin/sh
LIBGCJ_A=libgcj-static.a

mkdir libgcjobjs
cd libgcjobjs
ar x ../$LIBGCJ_A
cd ..

find libgcjobjs -name '*.o' > libgcjobjs.list

i686-pc-mingw32-ld --shared -Bdynamic -e _DllMainCRTStartup@12 -o libgcj.dll --out-implib libgcj.a /.1/home/tlaurenzo/gcc_cross/bin/../lib/gcc/i686-pc-mingw32/4.1.0/../../../../i686-pc-mingw32/lib/dllcrt2.o -L~/gcc_native/i686-pc-mingw32/lib -L/.1/home/tlaurenzo/gcc_cross/bin/../lib/gcc/i686-pc-mingw32/4.1.0 -L/.1/home/tlaurenzo/gcc_cross/bin/../lib/gcc -L/home/tlaurenzo/gcc_cross/lib/gcc/i686-pc-mingw32/4.1.0 -L/.1/home/tlaurenzo/gcc_cross/bin/../lib/gcc/i686-pc-mingw32/4.1.0/../../../../i686-pc-mingw32/lib -L/home/tlaurenzo/gcc_cross/lib/gcc/i686-pc-mingw32/4.1.0/../../../../i686-pc-mingw32/lib --export-all-symbols --enable-runtime-pseudo-reloc --allow-multiple-definition `cat libgcjobjs.list` -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -lm -lgdi32 -lws2_32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt


(This script is just for demonstration purposes. You will obviously need to update all of the paths appropriately)

To build programs that link to the dll, you will need to use some extra switches:

i686-pc-mingw32-gcj --main=Test -L. -o test.exe -Wl,--enable-runtime-pseudo-reloc Test.java


If trying to duplicate this work, note that I am not working on pristine sources. In particular the changes described in the java@gcc.gnu.org mailing list thread entitled "Linker name conflicts due to optimization in gjavah" are critical for this to work.

0 Comments:

Post a Comment

<< Home