You are currently viewing a snapshot of taken on April 21, 2008. Most of this content is highly out of date (some pages haven't been updated since the project began in 1998) and exists for historical purposes only. If there are any pages on this archive site that you think should be added back to, please file a bug.

The Mac Build System

Note: These instructions are for building the now-obsolete CFM build with CodeWarrior. The build instructions for the current Mach-O build are here.


The Mac build system for Mozilla is a set of Perl scripts that drive MacCVS Pro and CodeWarrior via AppleEvents. Unlike the distributed make system on other platforms, all the build logic lives in the mozilla/build/mac/build_scripts directory. The scripts are organized into a series of reusable modules (in the Moz subdirectory), and three driving scripts. Some of the script input comes from data files (MozillaBuildFlags.txt, MozillaCheckoutList.txt), and the rest is in a build-specific Perl module called The long-term goal is to have the scripts be entirely data-driven, and to have as little build-specific logic in perl code as possible.

Driving the build

Note: This instructions assume that you've set MacPerl to run scripts opened from the Finder.

Quick Summary

The first time you run either of the build scripts, you will be prompted to locate the MacCVS Pro session file you wish to check out with, and to locate CodeWarrior (if it is not already running). After the first time, these details are remembered.

  • Debug build

    Double-click on the file mozilla/build/mac/build_scripts/

  • Optimized build

    Double-click on the file mozilla/build/mac/build_scripts/

    If you have less than 128Mb RAM, it is likely that you will run into memory problems doing an optimized build, since the CodeWarrior optimizer is very memory hungry in certain situations.

Both these scripts will do a pull of the tree (either a fresh checkout or update), then run the entire build over the tree. If everything goes well, when the build finishes, you should end up with the Mozilla binary in mozilla:dist:viewer_debug:

If the build stops for some reason, you can restart the build from where it left off by simply running the same script again. The build writes progress to a a file which is read in at the start of a build, allowing it to start where it left off.

To ensure that the build starts from the beginning, trash the file "• Mozilla build progress" at the root level of the tree.

Changing build options

Unlike the old scripts, you should never have to edit files in the tree to change what gets built, or how. The build is configurable via a preferences file that can live in your system preferences folder (system-wide), or at the root of the tree (tree-specific). Each type of build (debug/opt, Mozilla/netscape) has its own preferences file. The first time you run the scripts, a default file will be created for you, which is empty other than some helpful comments.

This preferences file can contain the following kinds of lines. (Lines are not sensitive to how much whitespace appears between words. Trailing comments, preceded by #, are allowed.)

To see the list of available build flags, options, and file paths, see MozillaBuildFlags.txt.

Build options

options  mng                 1      # build mng
options  chrome_files        1      # put files in chrome
options  use_jars            0      # load chrome from files, not jars

Use these flags to turn on or off various build options, like MNG, using files in chrome, LDAP support etc.

Build start

buildfrom   nglayout               # start the build at nglayout

This 'buildfrom' flag is special, and controls where a build will start. In the absence of build progress state, this setting will determine where the build starts. If progress is present, the build will start from the the more advanced of the two settings.

Perl build flags

CLOSE_PROJECTS_FIRST            1              # leave CW projects open until another one is opened (faster)
PROFILE                         1              # set $main::PROFILE, for a profiling build

The build scripts use a number of flags, set as variables in the scope of $main::. For the list of flags used now, see the routine SetupBuildOptions in

Build file locations

filepath   idepath             ::codewarrior.txt
filepath   buildlogfilepath    ":Build Logs:Mozilla build log.txt"  # paths with spaces need quoting

The build uses various files to store state, in the form of paths to the CVS session file, to the CodeWarrior application, and for output log files. You can change the locations of these files here. Paths are relative to the tree root. Paths containing whitespace must be quoted.

Examples of using the build settings

Doing a Carbon build

NB: Note that to do a Carbon build, you'll need to modifiy your build environment according to the instructions on the FizillaCFM page.

To do a Carbon build, put the following in your build prefs file:

options  carbon  1

Don't forget that there are separate build prefs files for the debug and optimized builds.

Doing an optimized build on a low-memory machine

Doing an optimized build can be a challenge, because some of the Mozilla code seems to cause the CodeWarrior optimizer to go pathological, and run out of memory. We have a build option which helps:

options  lowmem  1

This option tunes down the optimization level in a few troublesome files.

Doing a debug and optimized build in the same tree

Here we make use of the fact that there are separate build prefs files for the debug and optimized builds. Start by doing one of the builds, say the debug build. Then, in the optimized build prefs file ("Mozilla opt build prefs") put:

buildfrom config

This causes the build to start at the 'config' stage, which comes just after 'dist'. The DefinesOptions.h header for the opt build is thus created, but we avoid clobbering all the files in dist, so all the library aliases created by the debug build remain.

Doing a static build

Note that the static build is not currently maintained. It probably won't work.

Doing a Mac static build (a build in which all the code which is normally compiled into lots of small shared libraries is build as static libraries, which are finally linked into a few large DLLs) is more complex, because we have to munge lots of CodeWarrior projects to add targets which build static libraries (".o" files). Luckily, this is automated.

First, if you have not done so already, you need to install some extra MacPerl modules. It's a good idea to allocate more memory to MacPerl here (24-26Mb should be fine, if you have virtual memory on). Then, set the following in the build prefs files:

EXPORT_PROJECTS        1    # causes the script to export CW projects to XML, and munge them
USE_XML_PROJECTS       1    # causes the scripts to look for .xml project files, and use them

options static_build   1    # do a static build

The first time you run a build with these settings, the scripts will open each project, and export them to an XML file next to the project. That XML then gets munged, to correct some bad formatting that Pro 5 spits out, and to clone and modify <TARGET> nodes in order to create new project targets, which are set set up as static ".o" targets. Finally, CodeWarrior reads the XML back in to create a new project (named with a leading understcore, like "_layout.mcp"), and builds the new static library targets. Later on in the build, some new projects link all the ".o" files together.

Note that this XML munging only happens once. If both an XML file and project exist in a folder, the scripts compare file modification dates to decide whether to re-munge the project.

Adding new files to the build

Because the Mac build system is different from the other platforms, adding new files or projects can be confusing. Here's a list of the likely changes you'd need to make.

How to add a new project to the build

So you're adding a new module, or perhaps splitting up an existing module, and need to create a new CodeWarrior project and add it to the build. Convention is to put Mac projects in a directory called macbuild at the root of that modules directory hierarchy. Consult a Mac guru for how to create the project, but be careful with the following settings mentioned below.

Mac project files are now checked into the tree in XML format ("gfx.xml"). The build scripts instruct CodeWarrior to convert these to a binary project ("_gfx.mcp") before building, and any time the XML version of the project is updated. If you make a new project, you should check in the XML file, not the ".mcp" file. If you make a change to a project, change the ".mcp" file, use 'Export Project...' on the 'File' menu to export to XML, replacing the existing XML version of the project, and check that in.

IDL Projects

When adding new .idl files to the build, create or edit a MANIFEST_IDL file which aliases those files to dist/idl. Ideally, all IDL projects should find their IDL files in dist:idl, but some are lazy and just look in the tree. The reason to alias all IDL files to dist/idl is that some IDL files include others, and aliassing them all to the same place avoids messing with access paths in the IDL projects.

Add the new MANIFEST_IDL file to the list of manifests in mozilla/build/mac/build_scripts/, in the subroutine BuildClientDist().

IDL projects do both header generation from IDL files, and generation of .xpt files (typelibs), using the XPIDL compiler and linker which are build as part of the Mozilla build process.

Output directory (Headers)
The "headers" target of an IDL project should have the module's folder in dist set as the output directory. E.g. libjar uses dist:libjar. Use a project-relative path, which will look like {Project}::::dist:libjar.
Output directory (.xpt)
The .xpt target should output into the project's folder. The build scripts alias the resulting .xpt file to dist.
xpidl settings (Headers)
Ensure that the linker output field contains {module}.headers. This name must be unique, and is used for header generation dependency tracking.
xpidl settings (.xpt)
Linker output should be {module}.xpt.

To add the IDL project to the Mac build system, edit mozilla/build/mac/build_scripts/, adding a line of perl to build your new project to the subroutine BuildIDLProjects. The second argument to the BuildIDLProject() routine is the name of the xpidl module, which should match the name of the .xpt file.

C/C++ Projects

Most of the C/C++ projects build shared libraries, though some build static libraries. These settings mostly apply to shared library projects.

Prefix files
Prefix files are used for project-specific #defines etc, and are included by the C preprocessor at top of each source file. Debug and non-debug targets should have different prefix files. If you don't have any project- specific settings, use MacSharedPrefix{_debug}.h in mozilla/config/mac. Prefix files use #pragmas to set most warning and compilation options, overriding those in the project settings.
Access paths
Avoid extraneous access paths to folders containing libraries that should be found via aliases in dist. System paths should be just {Compiler}:MSL: and {Compiler}:MacOS:Support:.
Entry points
You should use "__NSInitialize" as the Initialization routine (PPC Linker panel), and "__NSTerminate" as the Termination routine. Leave the Main routine blank. "Generate SYM File" should be on.
Fragment name
If you've cloned an existing project, be sure to give your library a unique fragment name, in the "PPC PEF" prefs panel.

To add the new project to the build, edit mozilla/build/mac/build_scripts/ and add a line to the appropriate subroutine, like:

BuildOneProject(":mozilla:modules:libimg:macbuild:libimg.xml", "libimg$D.shlb", 1, $main::ALIAS_SYM_FILES, 0);

Arguments are:

BuildOneProject(":mozilla:foo:foo.xml",   # path to project (XML version of project)
                "foo$D.shlb",             # target name (= binary name)
                1,                        # whether to create alias of binary in the bin directory
                $main::ALIAS_SYM_FILES,   # whether to alias the .xSYM file
                0);                       # whether this is a component (affects destination dir)

If you have more complex build requirements, look around in the scripts for something similar, and clone it. Seek help if you are confused.

How to add a new MANIFEST file to the build

MANIFEST files are used to copy header files to dist. They have also been used to copy .idl files to dist, and resource files (XUL, GIF etc) to the res directory. They may be variously called MANIFEST, MANIFEST_IDL etc. MANIFEST files contain just a list of files. They may contain relative paths ("res:foo.html") but this is discouraged.

To add one to the build, add a new 'InstallFromManifest' line to mozilla/build/mac/build_scripts/, probably in BuildClientDist(). These lines look like:

InstallFromManifest(":mozilla:include:MANIFEST",    # path to manifest file
                    "$distdirectory:include:");     # destination dir in dist

A similar process is used to install non-chrome resources with a MANIFEST file:

InstallResources(":mozilla:xpfe:browser:src:MANIFEST",  # path to manifest file
                 "$samples_dir");                       # destination dir

Note that InstallResources differs from InstallFromManifest in that it preserves relative paths. So if the MANIFEST file contains foo:bar.gif, a folder called 'foo' will be created in the destination, and bar.gif copied (or aliased) in there.

How to add a new file to the build files are used to list files that go into jar files. They are cross-platform.

To add a new file to the Mac build, add a lines to ProcessJarManifests() in mozilla/build/mac/build_scripts/, like:

CreateJarFromManifest("", $chrome_dir, \%jars);

How to get Mac to pull a new or different CVS module

The list of modules which are pulled lives in a text file, MozillaCheckoutList.txt. Just add a new line to this file. Note that you can specify a date, and/or a tag to pull from here. If you are creating a branch, and want Mac builds on the branch to work, you should edit this file to specify that the tree be pulled from your branch tag.

Having an "environment variable" set a #define

On other platforms, it's common to use environment variables to set up build options. This is emulated on Mac using the build options. The option can be turned on or off in the users' build preferences files, which can cause a #define to be generated in a global header file.

To add such an option-controlled #define, edit MozillaBuildFlags.txt, and add your preprocessor directive after the option setting, like:

ldap            1      MOZ_LDAP_XPCOM

This will generate #define MOZ_LDAP_XPCOM 1 in the generated header DefinesOptions.h, which is included in the global Mac header files. Note that the value of the option in MozillaBuildFlags.txt specifies whether it is on or off by default.

Creating a new build

The build scripts have been factored into reusable modules (in build_scripts/moz) and build-specific files (in build_scripts). If you want to make a totally new build (e.g. to just build NSPR, or for embedding, or whatever), then you should make new versions of the following files:

  • -- driver for an optimized build
  • -- driver for a debug build
  • MozillaBuildFlags.txt -- set of build options
  • -- non-resuable module containing build logic
  • MozillaCheckoutList.txt -- list of modules to pull
  • -- pull-only script

Then edit the new files according to your needs. Since Mozilla is the only build at present, doing this may require some further script refactoring.

Simon Fraser