MacOS-target gcj: create Mactel+PPC binaries from OS X, Linux and Cygwin

These instructions tell you how to build a cross compiler targeting Mac OS X (Intel and PPC) from any of three host platforms: Mac OS X, Linux, and Cygwin. The instructions use the provided tarball

Instructions

1. Gathering MacOS Headers and Libraries

In order to build the cross compiler, you need a few headers and libraries which ship with Mac OS X. The redistributability of these files is uncertain, so they are not included as part of the package.

To gather up these headers and libraries, you'll need to unpack the tarball on a Mac and type

make usr.tgz

This will gather the required headers and libraries and pack them up in usr.tgz. Copy this file to your build machine; from this point forward you don't need the Mac anymore. The list of files to gather is in usr.list.

2. Preparing your build machine

If your host is cygwin, use Cygwin's setup.exe to install the following packages:

svn
zip
unzip
patchutils
flex
bison
bzip2
curl
texinfo
libgmp-devel
libmpfr-devel
jikes

Yes, you actually need the last package (jikes); it's used in the gcj build process to bootstrap ecj.

3. Building the Cross Compiler

Now, just type

make Test arch=ppc
make Test arch=i386

Each command sets up the cross compiler to target Mac OS on a specific cpu (ppc or i386). If you type make Test without an arch line, it will build both cross-compilers and use lipo to merge the two binaries into a “fat” (“universal”) binary.

4. Compiling your own binaries

You'll need to compile and link the provided eprintf.cc into your programs. This provides an implementation of the following function, which libgcc apparently depends on:

extern "C" void
  __eprintf (const char *string, const char *expression,
             unsigned int line, const char *filename);

How does it work?

In case you're curious, when you type the commands above, the included Makefile will:

* Acquire odcctools, the OpenDarwin version of cctools. The cctools suite is the Darwin equivalent of binutils (the actual GNU binutils only has partial support for Darwin).

  • The odcctools-patch is applied ot the sources; this fixes a few small Darwin-specific portions of the cctools source code so it will build under Cygwin:

    diff -BNubr odcctools/ar/archive.c odcctools/ar/archive.c
    --- odcctools/ar/archive.c      2006-12-13 22:10:42.000000000 -0800
    +++ odcctools/ar/archive.c      2006-12-13 21:38:33.000000000 -0800
    @@ -83,12 +83,13 @@
     
     #include "archive.h"
     #include "extern.h"
    +#include 
     
     typedef struct ar_hdr HDR;
     static char hb[sizeof(HDR) + 1];       /* real header */
     
     int archive_opened_for_writing = 0;
    -
    +#define DEFFILEMODE 0666
     int
     open_archive(mode)
            int mode;
    diff -BNubr odcctools/misc/libtool.c odcctools/misc/libtool.c
    --- odcctools/misc/libtool.c    2006-12-13 22:10:43.000000000 -0800
    +++ odcctools/misc/libtool.c    2006-12-13 21:53:40.000000000 -0800
    @@ -2246,7 +2246,7 @@
               (int)sizeof(toc_ar_hdr.ar_date),
                   (long int)stat_buf.st_mtime + 5);
            for(i = 0; i < narchs; i++){
    -           if(lseek(fd, time_offsets[i], L_SET) == -1){
    +           if(lseek(fd, time_offsets[i], SEEK_SET) == -1){
                    system_error("can't lseek in output file: %s", output);
                    return;
                }
    --- odcctools/misc/libtool.c    2006-04-13 06:44:46.000000000 -0700
    +++ odcctools/misc/libtool.c    2006-12-20 15:39:44.000000000 -0800
    @@ -2209,7 +2209,7 @@
             * of the unlink() is ignored).
             */
            (void)unlink(output);
    -       if((fd = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1){
    +       if((fd = open(output, O_WRONLY | O_CREAT, 0666)) == -1){
                system_error("can't create output file: %s", output);
                return;
            }

  • odcctools is compiled and installed locally using the $(target)-$(toolname) convention that GCC expects.

* Check out gcc from the FSF subversion repository, configure it, and build it. In particular,

  • The -dylib_file argument is added to libgcj.specs to let it know that libmathCommon.dylib is somewhere other than /usr/lib/system.

  • The libSystemStubs.dylib library is linked in to gcj-compiled binaries by default.

  • The enable-static-builds patch tells gcj to use normal C++ .ctors to register Java classes, rather than the proprietary .jcr section, which currently does not work correctly on Darwin.

    Index: gcc/config/i386/darwin.h
    ===================================================================
    --- gcc/config/i386/darwin.h    (revision 120174)
    +++ gcc/config/i386/darwin.h    (working copy)
    @@ -51,6 +51,8 @@
         }                                           \
       while (0)
     
    +#define TARGET_USE_JCR_SECTION 0
    +
     #undef PTRDIFF_TYPE
     #define PTRDIFF_TYPE (TARGET_64BIT ? "long int" : "int")

  • The enable-static-builds patch also tells libtool to limit its command lines to no more than 2048 characters (a Win32 limitation).

    Index: ltconfig
    ===================================================================
    --- ltconfig    (revision 120174)
    +++ ltconfig    (working copy)
    @@ -217,7 +217,7 @@
     ac_ext=c
     libext=a
     cache_file=
    -max_cmd_len=
    +max_cmd_len=2048
     
     ## Dependencies to place before and after the object being linked:
     predep_objects=
    @@ -2376,7 +2376,7 @@
     pic_mode=$pic_mode
     
     # What is the maximum length of a command?
    -max_cmd_len=$max_cmd_len
    +max_cmd_len=2048
     
     # Does compiler simultaneously support -c and -o options?
     compiler_c_o=$compiler_c_o