Title:      Metrowerks w/ configure HOWTO
Author:     David Elliott
Id:         $Id: configure_howto.txt 33089 2005-03-27 09:28:39Z DE $

=== Introduction to Metrowerks command line tools ===

Since CodeWarrior version 8, Metrowerks has provided command-line compilers
hosted on OS X.  There are three available targets.

1) Mac OS X/PPC
Compiler:   mwcc
Linker:     mwld
-- File formats --
Executable:         Mach-O
Shared Library:     Mach-O (bundle, dylib, etc.)
Static Library:     CodeWarrior
Object:             CodeWarrior

2) Mach-O/PPC
Compiler:   mwccppc
Linker:     mwldppc
-- File formats --
Executable:         Mach-O
Shared Library:     Mach-O (bundle, dylib, etc.)
Static Library:     Archived (ar) Mach-O (.a files)
Object:             Mach-O .o files

3) Mac/PPC
Compiler:   mwpefcc
Linker:     mwpefld
-- File formats --
Executable:         PEF
Shared Library:     PEF ("code fragments")
Static Library:     CodeWarrior
Object:             CodeWarrior

As you can see, only one of these targets produces Mach-O .o files that
normal ar and ranlib could hope to handle.  It's no matter though,
really all that ar and ranlib do is create a static library (.a) from a
collection of .o files.  This can be emulated by a shell script which
calls the appropriate mwld.  I've provided one called mwar which does this.
For ranlib simply use true since mwar does all of the work.

=== Metrowerks Environment Variables ===

In order for any of these programs to work some environment variables
must be set.  The compiler must know where to look for headers (CIncludes).
The linker needs to know where to look for libraries (Libraries) such as
those specified on the commandline with -l as well as crt1.o (or sometimes
mwcrt1.o) for OS X.  The linker also needs to know if any additional
libraries should be linked into executables (LibraryFiles).  Finally,
on OS X the linker needs to know where to look for Frameworks (FrameworkPaths).
These are controlled by the following environment variables:

1) Mac OS X/PPC
CIncludes:          MWCMacOSXPPCIncludes
Libraries:          MWMacOSXPPCLibraries
LibraryFiles:       MWMacOSXPPCLibraryFiles
FrameworkPaths:     MWFrameworkPaths

2) Mach-O/PPC
CIncludes:          MWCMachPPCIncludes
Libraries:          MWMachPPCLibraries
LibraryFiles:       MWMachPPCLibraryFiles
FrameworkPaths:     MWFrameworkPaths

3) Mac/PPC
CIncludes:          MWPEFCIncludes
Libraries:          MWPEFLibraries
LibraryFiles:       MWPEFLibraryFiles
FrameworkPaths:     (N/A)
Notes (mwldppc 3.0.3 build 343):
The environment variables (including MWPEFLibraries) aren't read until after
the command line options have been parsed!  The command line option parser
actually tries to do the linking from within the parser and thus -l options
which don't have a -L specifying where to look for the library do not work.
Yes, this means that MWPEFLibraries is essentially useless AFAICT.

I have provided an example mwvars.sh.  It's what I use with CW 8.3.  YMMV.

=== Compiling wxWidgets targetting Mac OS X with Metrowerks ===

With recent wxWidgets (2.5.5) it is possible to compile using the
Metrowerks tools with minimal effort.  You may use either mwcc/mwld
or mwccppc/mwldppc.  Ideally you will have the tools on your path
on your path as well as the mwar script I've provided.  You will also
have had to source mwvars.sh (either yourself or by sourcing it from
your .profile or .bash_profile).

Before beginning I strongly recommend you write a simple C++ hello world
program.  I recommend #include <iostream> and cout << "Hello World" << endl;.
This will ensure your C++ standard library is working.  Note that
you can compile this using mwcc hello.cpp.  You will find a hello.cpp.o
file as well as an a.out file if the compiler and linker were successful.
Assuming your compiler can produce a.out you're ready to begin.

As per usual, I recommend building outside the source tree.
From the source tree (workingDirectory$ is the prompt)

wxWidgets$ mkdir ../BUILD_MACd_CW8
wxWidgets$ cd ../BUILD_MACd_CW8
BUILD_MACd_CW8$ ../wxWidgets/configure --enable-debug --disable-shared CC=mwcc CXX=mwcc LD=mwld AR=mwar RANLIB=true
[ configure hopefully succeeds ]
BUILD_MACd_CW8$ make
[ make hopefully succeeds ]
BUILD_MACd_CW8$ make -C samples/minimal
[ minimal make succeeds ]
BUILD_MACd_CW8$ ./samples/minimal/minimal.app/Contents/MacOS/minimal
[ minimal runs and your prompt will return when you Quit the app ]

The important options are CC=mwcc CXX=mwcc LD=mwld AR=mwar RANLIB=true
Right now you also need --disable-shared.  Eventually I hope to add the
ability to created shared libraries.

If you wish to use the Mach-O compilers instead of the Mac OS X compilers
then use CC=mwccppc CXX=mwccppc LD=mwldppc.  You don't need a special
AR or RANLIB with this compiler.

At the moment, precompiled headers aren't supported though you don't need
to pass --disable-precomp-headers since the Makefiles know they can't do PCH.
I hope to add this soon.

As you can see, this is not wildly different from compiling using any
other compiler (for instance GCC).  The same files that would be compiled
by gcc are now compiled by mwcc.  The same files that would be linked
by the combination of ar and ranlib are now linked using the mwar shell
script that calls mwld to do the work and using true in place of ranlib.
The same files that would be linked using ld (i.e. the executable sample)
are linked using mwld.


=== Compiling wxWidgets targetting Mac OS (Carbon) with Metrowerks ===

Compiling for Mac OS PEF Carbon is not really more or less difficult
than compiling for OS X.  However, there is still some work left to do.

In particular, the -lCarbonLib and -lQuickTimeLib options to the linker don't
work because of the aforementioned bug in mwpefld. To fix this you can add
-L/path/to/Universal/Libraries/StubLibraries to LDFLAGS.  Unfortunately
because autoconf (2.59) doesn't always use eval appropriately you cannot
have spaces in the path.  What I recommend is to make a symlink from
/Applications/Metrowerks CodeWarrior 8.0/Metrowerks CodeWarrior/MacOS Support to some path which can be accessed without using spaces.
Something like this:
~$ ln -snf "/Applications/Metrowerks CodeWarrior 8.0/Metrowerks CodeWarrior/MacOS Support" MW_MacOS

There is also a problem with the samples Makefiles.  Currently they clear
the resource fork of the executable rather than append to it.  This
can be remedied by adding the -a option to Rez before making in that
sample's directory.  I hope to fix this soon.

Assuming you work around these it's pretty straightforward:

wxWidgets$ mkdir ../BUILD_MACCARBONd_CW8
wxWidgets$ cd ../BUILD_MACCARBONd_CW8
BUILD_MACCARBONd_CW8$ ../wxWidgets/configure --host=powerpc-apple-macos --enable-debug --disable-shared CC=mwpefcc CXX=mwpefcc LD=mwpefld AR=mwpefar RANLIB=true LDFLAGS=-L/Users/yourname/MW_MacOS/Universal/Libraries/StubLibraries
[ configure hopefully succeeds ]
BUILD_MACd_CW8$ make
[ make hopefully succeeds ]
BUILD_MACd_CW8$ make -C samples/minimal
[ minimal make succeeds ]
BUILD_MACd_CW8$ /System/Library/Frameworks/Carbon.framework/Versions/A/Support/LaunchCFMApp ./samples/minimal/minimal
[ minimal runs and your prompt will return when you Quit the app ]

Unlike the OS X case not many people compile wxMac Carbon PEF using configure.
From time to time there may be minor problems.  Please report these using
the sourceforge bug tracker.

=== Other Metrowerks notes ===
--- Object file extension ---
By default, the mw compilers when used with the -c option will append .o
to the source filename (following symlinks even).  This is in contrast to
normal compilers which replace the files extension with .o.  To get the
normal behavior you must add -ext o to the compiler options.  The wxWidgets
configure script does this and the macros to check for this are part of
Bakefile (bakefile.sourceforge.net).

--- Static library extension ---
The CodeWarrior IDE typically uses the .lib extension for CodeWarrior static
libraries and .a for Mach-O static libraries (ar/ranlib archives).  The
wxWidgets makefiles always use .a.  This isn't really a problem just be
aware that the .a files aren't really ar/ranlib archives and aren't useable
by anything other than CodeWarrior itself.

--- IDE ---
As far as I know it should be possible to use libraries created by
the command line tools from the IDE.  For instance, you could compile
wxWidgets using this method but continue to use the IDE for your application.
Personally, I prefer sticking with the command line so I haven't tried this.

--- OS X SDKs ---
Before CodeWarrior 9.3 the usage of SDKs (those in /Developer/SDKs) is
impossible.  You might think that it would work simply be prefacing any
/System or /usr paths with the SDK path when setting the environment variables.
Unfortunately, the libraries and frameworks inside these SDKs contain absolute
paths to libraries and frameworks which they depend on.  Thus, the linker
attempts to load the non-SDK version to satisfy the dependency.

To ensure an app will work correctly on previous versions of the OS you
can use Apple's availability macros.

--- CodeWarrior 8.3 and Panther ---
CodeWarrior 8.3 has some problems running on Panther.  When using the IDE
version it is typical to change the OS X directory to the 10.2 SDK.
Unfortunately, this is impossible with the command line compiler due to
the aforementioned bug.  Thus, the only solution is to allow CodeWarrior
8.3 to work with Panther's headers.  Fortunately, this isn't as hard
as some people (particularly those at Metrowerks) would make you think.

First of all, there are issues with Apple's headers declaring conflicting
types.  Particularly with respect to wchar_t.  Now, I'm sure you're
aware of the "(wchar_t Support fix)" directory.  What you need to do
is create another one called "(wchar_t Support Panther fix)" using the 
provided machine/ansi.h file which contains some minor changes from
the Metrowerks version.

Secondly, there is an issue with crt1.o.  Apple's position is that
/usr/lib/crt1.o is intended to be used only with Apple's GCC.
Metrowerks does provide an mwcrt1.o and when you're using the IDE you
can perfectly well use it instead of Apple's crt1.o.  Unfortunately,
when you are using mwld it has crt1.o hardcoded.  Very fortunately, it
has only the filename encoded and it searches the libraries path!
What I do is symlink "Mac OS X Support/Libraries/Startup/mwcrt1.o" to
crt1.o in the same directory.

--- MSL on OS X ---
In mwvar.sh for the Mac OS X/PPC toolchain I've used MSL C++ with the
BSD CRT.  To do this I used the .a files.  Earlier I used the .lib files
but these also require the MSL C .lib.  AFAIK using this would cause
the MSL CRT to be used and I think I don't want that unless I'm using
the MSL CRT headers.  It did work although I never tested it with
anything too complex.  I suspect it would have failed although I'm
wondering how it works with the CW projects because I think they do
link with the MSL_C libs.  This is probably very wrong.

If you do decide to use the MSL_C libs you'll need to add
"MSL/MSL_C/MSL_MacOS/Src/console_OS_X.c".  Unfortunately,
mwld is a linker and doesn't understand C source code.  Thus you must
compile this file and use the compiled version.

What I did was simply run mwcc -c console_OS_X.c to generate a
console_OS_X.c.o object file.  This file must be in MWMacOSXPPCLibraryFiles.

