15 August 2005

Perserverance: 1 Static Linking: 0

Finally! I've figured out how to make dynamic linking of module files work with bigloo on Mac OS X! Details follow (though I should warn you that this is a total hack right now).

There are two steps involved: 1. Alter the bigloo compilation process so it builds the proper dynamic libraries and 2. Make sure that the executable bigloo is linked against the dynamic libraries, and not the static ones.

#1: The way I know to do #1 is to edit Makefile.config after running ./configure [whatever-options-you-want]. Scroll through Makefile.config and change the following options:

LD
LD=ld
LDFLAGS
LDFLAGS=-dylib -single_module
LDLIBS
-lc -lSystem.B -ldylib1.o -lm -lc -lgcc
SHAREDSUFFIX
SHAREDSUFFIX=dylib
Now issue the command
make
The make process will halt with an error! That's OK. Re-edit the Makefile.config file by changing the LDLIBS variable to LDLIBS=-lbigloogc-2.7a -lc -lSystem.B -ldylib1.o -lm -lc -lgcc (you should alter the "-2.7a" to whatever version of bigloo you're compiling). The compile should now finish. You will have both libbigloo***-***.a and libbigloo***-***.dylib in the lib subdirectory.

#2: Though it seems like you should be able to ensure that the bigloo executable is linked against the dynamic libs by using the --sharedcompiler=yes flag to the configure script, this doesn't work. However, the fix is easy enough: edit the dboot target of the file comptime/Makefile. There will be a section looks something like

doboot: $(O_OBJECTS)
 if [ "$(SHRD_COMP)" = "yes" -a -f $(BOOTLIBDIR)/lib$(LIBRARYNAME)_s$(VERSION)$(SHAREDSUFFIX) ]; then            gc=-lbigloogc-$(RELEASE);            if [ "$(GCCUSTOM)" = "no" ]; then       gc=-lgc;            fi;     $(CC) $(EXTRA_LD_OPT) $(CFLAGS) -o $(BIGLOO_DEST) $(O_OBJECTS) -L $(BOOTLIBDIR) -lbigloo_s-$(RELEASE) $$gc $(EXTRALIBS);  else            gc=$(BOOTLIBDIR)/libbigloogc-$(RELEASE).a;            if [ "$(GCCUSTOM)" = "no" ]; then               gc=-lgc;            fi;     $(CC) $(EXTRA_LD_OPT) $(CFLAGS) -o $(BIGLOO_DEST) $(O_OBJECTS) $(BOOTLIBDIR)/libbigloo_s-$(RELEASE).a $$gc $(EXTRALIBS);  fi
 -$(STRIP) $(BIGLOO_DEST)$(EXE_SUFFIX)
 @ echo "$(BIGLOO_DEST)$(EXE_SUFFIX) done..."
you want to make it look like:
doboot: $(O_OBJECTS)
 if [ "$(SHRD_COMP)" = "yes" -a -f $(BOOTLIBDIR)/lib$(LIBRARYNAME)_s$(VERSION)$(SHAREDSUFFIX) ]; then            gc=-lbigloogc-$(RELEASE);            if [ "$(GCCUSTOM)" = "no" ]; then       gc=-lgc;            fi;     $(CC) $(EXTRA_LD_OPT) $(CFLAGS) -o $(BIGLOO_DEST) $(O_OBJECTS) /tmp/bigloo2.7a/lib/2.7a/libbigloo_s-2.7a.dylib /tmp/bigloo2.7a/lib/2.7a/libbigloogc-2.7a.dylib  else            gc=$(BOOTLIBDIR)/libbigloogc-$(RELEASE).a;            if [ "$(GCCUSTOM)" = "no" ]; then               gc=-lgc;            fi;     $(CC) $(EXTRA_LD_OPT) $(CFLAGS) -o $(BIGLOO_DEST) $(O_OBJECTS) $(BOOTLIBDIR)/libbigloo_s-$(RELEASE).a $$gc $(EXTRALIBS);  fi
 -$(STRIP) $(BIGLOO_DEST)$(EXE_SUFFIX)
 @ echo "$(BIGLOO_DEST)$(EXE_SUFFIX) done..."
(The difference is that we have explicitly included the libbigloo_s-2.7a.dylib and the libbigloogc-2.7a.dylib libraries on the $(CC) command line---including the full paths!) Now delete the old executable at bin/bigloo (relative to the unpacked bigloo directory) and re-make. Check with otool -L bin/bigloo to make sure that the bigloo executable really links against the dynamic libraries. The output of my otool looks like
SYDNEYPACIFIC-THREE-FORTY-ONE:/tmp/bigloo2.7a farr$ otool -L bin/bigloo
bin/bigloo:
        /tmp/bigloo2.7a/lib/2.7a/libbigloo_s-2.7a.dylib (compatibility version 0.0.0, current version 0.0.0)
        /tmp/bigloo2.7a/lib/2.7a/libbigloogc-2.7a.dylib (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 71.1.3)

Now, to make a loadable bundle, issue the following command (this example comes from the Bigloo manual, section 13.1 under the dynamic-load procedure documentation):

MACOSX_DEPLOYMENT_TARGET=10.3 gcc -bundle -undefined dynamic_lookup -o mod.bundle mod1.o mod2.o
This command replaces the ld -G -o lib.so mod1.o mod2.o command from the manual. You can now load the bundle with
(dynamic-load "mod.bundle")
from the REPL. You need the MACOSX_DEPLOYMENT_TARGET=10.3 so that it doesn't complain about the -undefined dynamic_lookup option; if you don't have 10.3, you can probably get away with -undefined suppress, but I haven't tried it.

Footnotes

1: I think it would be really neat if someone found a way to make all of this ad-hoc makefile-modifying happen automatically as part of the Bigloo build process on Mac OS X. I think it'll take someone more knowledgeable about the internals of the build process, but I may have a look at it later.

2:What happened here is that libbigloo requires the garbage collection library, so we have to include it in the LDLIBS variable. We can't put it in there at the beginning because the GC library doesn't exist yet, so we have to wait for the build to fail and then put it in. This is necessary because Mac OS X makes a distinction between dynamic libraries (which are treated like ELF static libraries for link purposes, but like ELF shared (or dynamic) libraries for loading at runtime) and loadable bundles (which are treated like ELF shared libraries all the time). In English: you have to have all the symbols for a .dylib at link time, though the libraries which contain them won't be loaded until run time, while you don't need the symbols for a .bundle until you use them at runtime.

3:And I don't understand why---the command that make issues has -lbigloogc-2.7a -lbigloo_s-2.7a and my documentation tells me that linking against the dynamic library version is the default in OS X, so I really don't understand what's going on here.

4: But very kludgy.

No comments: