We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 198

Summary: Some Mac build TODOs...
Product: SDL Reporter: Ryan C. Gordon <icculus>
Component: buildAssignee: Ryan C. Gordon <icculus>
Status: RESOLVED FIXED QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2 CC: max
Version: HG 1.2   
Hardware: PowerPC   
OS: Mac OS X (All)   

Description Ryan C. Gordon 2006-04-13 10:55:37 UTC
I figured I'd put down some notes on how to build a Universal binary from the configure script, or at least what it would need to do.

Ideally, we need the Makefile to build each file twice on the Mac: once with gcc-3.3 for PowerPC, and once with gcc-4.0 for x86, and then use "lipo" to glue them into one object file.

so you end up with something like this:

gcc-3.3 -o myfile-ppc.o -arch ppc $OTHER_COMPILER_FLAGS myfile.c
gcc-4.0 -o myfile-x86.o -arch i386 $OTHER_COMPILER_FLAGS myfile.c
lipo -create -o myfile.o myfile-ppc.o myfile-x86.o
rm -f myfile-ppc.o myfile-x86.o

This could either be a special make rule for Mac OS X, or perhaps a shell script that wraps the compiler ("export CC=maccompile.sh" or something)

Also, I think we can keep 10.2.8 compatibility on the PowerPC side (and 10.4 on the x86 side, which won't always be the latest version), if we do some tapdancing with command lines. This _should_ fix the issues with the Quicktime SDK forcing 10.4 as a baseline.

On PowerPC:

CFLAGS := -arch ppc -F/Developer/SDKs/MacOSX10.2.8.sdk/System/Library/Frameworks -I/Developer/SDKs/MacOSX10.2.8.sdk/Developer/Headers/FlatCarbon -DMAC_OS_X_VERSION_MIN_REQUIRED=1020 -I/Developer/SDKs/MacOSX10.2.8.sdk/usr/include/gcc/darwin/3.3 -I/Developer/SDKs/MacOSX10.2.8.sdk/usr/include/gcc/darwin/3.3/c++ -I/Developer/SDKs/MacOSX10.2.8.sdk/usr/include/gcc/darwin/3.3/c++/ppc-darwin -isystem /Developer/SDKs/MacOSX10.2.8.sdk/usr/include

LDFLAGS := -arch ppc -mmacosx-version-min=10.2 -L/Developer/SDKs/MacOSX10.2.8.sdk/usr/lib/gcc/darwin/3.3 -F/Developer/SDKs/MacOSX10.2.8.sdk/System/Library/Frameworks -Wl,-syslibroot,/Developer/SDKs/MacOSX10.2.8.sdk


On Intel:

CFLAGS := -arch i386 -mmacosx-version-min=10.4 -DMAC_OS_X_VERSION_MIN_REQUIRED=1040 -isysroot /Developer/SDKs/MacOSX10.4u.sdk

LDFLAGS := -arch i386 -mmacosx-version-min=10.4 -L/Developer/SDKs/MacOSX10.4u.sdk/usr/lib/gcc/i686-apple-darwin8/4.0.0
-Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk


The '-F' command line is an Apple GCC thing: it tells it where to look for headers in frameworks. The rest is tapdancing to make sure all system headers use the ones from the 10.2.8 SDK, which can be installed from XCode's installer (but is not installed by default). gcc4 added the isysroot option, which cleans things up a lot.

These instructions can build on either a PowerPC or Intel Mac. The build system may need to be 10.4 or later.

--ryan.
Comment 1 Sam Lantinga 2006-04-13 11:05:08 UTC
If you have merged ppc and x86 objects, how do you use separate LDFLAGS?
Comment 2 Sam Lantinga 2006-04-13 11:15:35 UTC
If you show me how to build a fat .dylib, I'll see if I can integrate it into the SDL build system...
Comment 3 Ryan C. Gordon 2006-04-13 11:17:08 UTC
Whoops, I changed direction in mid-post and forgot to correct that.

"lipo" should be used on the final binaries. So you compile and link them seperately, then merge them.

Something I've been doing in Makefiles recently looks like this:

# set up OBJS, PPC vs X86 compiler defines, etc up here.

# make the objects to build into two seperate copies in different places...
X86OBJS := $(foreach f,$(OBJS),$(BINDIR)/x86/$(f))
PPCOBJS := $(foreach f,$(OBJS),$(BINDIR)/ppc/$(f))

# Build with gcc4,x86,10.4.0 options in the "x86" dir
$(BINDIR)/x86/%.o : %.c
	$(X86CC) -o $@ $(CFLAGS) $(X86CFLAGS) $<

# Build with gcc3,ppc,10.2.8 options in the "ppc" dir
$(BINDIR)/ppc/%.o : %.c
	$(PPCCC) -o $@ $(CFLAGS) $(PPCCFLAGS) $<

# Link x86 objects into something like SDL-x86.dylib
$(X86EXE) : $(X86OBJS)
	$(X86LD) -o $@ $(LDFLAGS) $(X86LDFLAGS) $^

# Link ppc objects into something like SDL-ppc.dylib
$(PPCEXE) : $(PPCOBJS)
	$(PPCLD) -o $@ $(LDFLAGS) $(PPCLDFLAGS) $^

# merge SDL-ppc.dylib and SDL-x86.dylib into SDL.dylib
$(EXE) : $(X86EXE) $(PPCEXE)
	lipo -create -o $@ $^

--ryan.
Comment 4 Sam Lantinga 2006-04-14 01:44:02 UTC
Ryan, I added build-scripts/fatbuild.sh to CVS.
It's completely untested, could you check it out?
Comment 5 Max Horn 2006-04-15 08:11:44 UTC
FYI, the Apple porting guides at <http://developer.apple.com/documentation/Porting/Conceptual/PortingUnix/compiling/chapter_4_section_3.html> suggests

CFLAGS="-isysroot /Developer/SDKs/MacOSX10.4u.sdk -arch i386 -arch ppc"
LDFLAGS="-Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk -arch ppc -arch i386"

But I am not sure whether -isysroot is available in gcc 3.3, probably not... Nor do I know whether one can use this to build binaries that work on 10.3 / 10.2, this'll require some experimenting.

Another potentially interesting read:
<http://perldoc.perl.org/perlmacosx.html>


Comment 6 Sam Lantinga 2006-04-16 13:56:04 UTC
So, has anyone tried the script?
Comment 7 Max Horn 2006-04-16 14:06:07 UTC
I'll give it a try now (though I have no intel machin myself). BTW it's missing the executable bit.
Comment 8 Sam Lantinga 2006-04-17 01:07:39 UTC
I fixed a couple things, go ahead an try it again...
Comment 9 Max Horn 2006-04-17 02:41:55 UTC
It fails to compile the PPC version over here, because it mixes files from my regular /usr/include and from /Developer/SDKs/MacOSX10.2.8.sdk/

I really think using the options listed in the links I provided is necessary. Even then, when using GCC 4.0, I am not sure if the resulting binaries will actually work on 10.2/10.3...

Anyway, -nostdinc, -isysroot seem like the way to go...
Comment 10 Ryan C. Gordon 2006-04-17 14:00:35 UTC
There is no -isysroot in gcc 3.3, only gcc4, which means you have to surrender 10.2 (and 10.3?) support on PowerPC to use it.

-isystem puts that path at the start of the include directory list, so it should never favor /usr/include if it has the same file in the -isystem path.

Of course, it's probably worth noting that this will silently ignore the -isystem path if it doesn't exist...which it won't, if the 10.2.8 SDK isn't installed when installing XCode (and it isn't, by default).

Are we having fun yet?   :)

--ryan.

Comment 11 Sam Lantinga 2006-04-17 22:30:01 UTC
What should the fat dylib be called?

$ ls -d */build/.libs/*.dylib
ppc/build/.libs/libSDL-1.2.0.7.3.dylib  x86/build/.libs/libSDL-1.2.0.7.3.dylib
ppc/build/.libs/libSDL-1.2.0.dylib      x86/build/.libs/libSDL-1.2.0.dylib
ppc/build/.libs/libSDL.dylib            x86/build/.libs/libSDL.dylib      

$ find ppc x86 -type f -name "*.dylib"
ppc/build/.libs/libSDL-1.2.0.7.3.dylib
x86/build/.libs/libSDL-1.2.0.7.3.dylib

Does the libSDL.a also need to be built as a stub for dynamic linking, or is that a static library?
Comment 12 Ryan C. Gordon 2006-04-18 13:51:59 UTC
The final files should be called what they are normally called (I think it's libSDL-1.2.0.7.3.dylib and the rest are symlinks to it)...the one file will have both ppc and x86 code, and the OS and tools will pick the right half for what they need.

libSDLmain.a needs the same treatment: build both x86 and ppc, merge them with lipo, and then the linker will choose the right piece depending on what it's linking it to.

We only need them seperate when first compiling, but once everything is built, it should exist on the system as it always would: it will just contain both architectures.

I'm not sure I'm answering your question properly.

--ryan.

Comment 13 Sam Lantinga 2006-04-18 23:51:24 UTC
Yep, that was exactly what I needed.  I think this is pretty much wrapped up.