Gaia build system primer

This article explains how Gaia's build system works, including the makefile, the build process, environment variables, and potential customizations.

Most of the meaningful work for the build steps are performed by the scripts that live inside the build/ subdirectory of Gaia, which are executed using make, node.js and XPCShell (also known as JS Shell), a runtime environment from XULRunner. The Gaia build system contains many helper tools to help install, test, localization, and package webapps onto a real device. It also allows developers to customize Gaia by for example changing default wallpaper, ringtones, apps and settings.

Note: XPCShell is similar to node.js but with the added capability to run some Mozilla-flavored javascript. It allows Gaia build scripts to run inside a Firefox extension.

The Makefile

The Makefile consists of a bunch of goals. This section explains the most useful ones.


This goal will push all the apps for Gaia to your device. If you want to only push a specific app, you can use the APP flag as follows:

APP=calendar make install-gaia

This directory must exist inside one of the Gaia apps directories (e.g., apps).


This works the same as install-gaia but starts by purging and then sets up permission defaults after installing all of the apps. The apps will be in /data/local like in the engineering builds. This will also push test and debugging applications.

Be careful: Using the APP environment variable with reset-gaia appears to work, but it will put your phone in an unusable state (which is recoverable by running this goal again without the APP variable). So don't do that.


Same as reset-gaia but source code will be optimized. This goal basically allows you to emulate user builds. This will also push the same set of apps that are installed in user builds.

Be careful: Using the APP environment variable with production appears to work, but it will put your phone in an unusable state (which is recoverable by running this goal again without the APP variable). So don't do that.

reference workloads

These goals push variously sized workloads to the device, helping us with debugging and fixing the performance and scalability issues we might have. These goals accept the APP environment variable, or an APPS environment variable that should contain the app names separated by a space, e.g.,

APP=sms make reference-workload-light
APPS="sms communications/contacts" make reference-workload-heavy

Note: For more information, read Hacking Gaia: Reference workloads.

Environment variables

Some environment variables let you control some aspects of the build and installation on the device, for example:


This enables parallel build in order to take advantage of multicore CPU and speed up building time. Default value is 0.

Be careful: Parallel build is an experimental feature that can be unstable.


This triggers an optimization pass on the JavaScript files. This is automatically set when running make production. This can be used for install-gaia or reset-gaia too.


This is basically an alias for make production.


This lets you generate a debug profile to use with Gaia unit tests or when developing your Firefox OS app in Firefox. You must delete the existing profile directory before trying to generate a new one.


This disables screen lock on the device.


This variable lets you build specific device from different 'app.list'. All 'app.list' files are located under /build/config/$(GAIA_DEVICE_TYPE)/  folders.

GAIA_DEVICE_TYPE default value is phone.

Note: for more details and more options, consult our Hacking Gaia make options guide.

Build process

Here is a sequence diagram for building gaia:

pre-app.js, app.js & post-app.js will be executed by Makefile and mostly build tasks have been done in xpcshell scripts, Makefile is used for detecting OS and downloading b2g-desktop and we plan to migrate more tasks from Makefile to xpcshell scripts.

you may have question for why we have pre-app, app and post-app, that just because we are moving dependencies from Makefile to xpcshell script, so we created pre-app.js and post-app.js on bug 1021051 for moving mostly dependencies to xpcshell scripts, and at the end, app.js, pre-app.js and post-app.js will be merged on bug 1053703.

we have three kinds of directory for gaia build system:

  1. source directories: apps, dev_apps, shared directories
  2. stage directory: build_stage
  3. profile directories: profile, profile-debug or profile-test directories

our goal is never generate files to source directories, unfortunately we still have some modules to generate files into source directories, but we plan to fix these issues. here is a table to show which modules generate files to source, stage or profile directories.

Here is the build process when make is executed in the gaia directory, rules will be executed in order:

  1. b2g_sdk: b2g-desktop is used to run the xpcshell scripts in GAIA_DIR/build/.
  2. svoperapps: Download apps and generate configuration files for apps installation per provider of mobile telephony and country
  3. webapp-manifests: Generate webapps metadata for build process
  4. keyboard-layouts: Generate the default keyboard layout config
  5. settings.json (settings.js): This JavaScript generates the default settings for Firefox OS, which are read by Gaia.
  6. webapp-shared: Pick files which are used in each app from shared directory to build_stage directory.
  7. preferences: Generates default preferences for Firefox OS; it will generate the user.js file and put it onto the device, where it is read by Gecko. Note that the values might be changed with different environment variables such as DEBUG=1.
  8. app.js: Makefiles in the app directory: These are executed if they exist. For each app, if there is no app Makefile the Gaia Makefile will copy the app directory to the build_stage, and execute [app-directory]/build/build.js if it exists. See Build script for apps for more details.
  9. test-agent-bootstrap & test-agent-config: setup test-agent includes two make rules, test-agent-config & test-agent-bootstrap-apps, which are used to setup test environments for each app.
  10. webapp-optimize: This script contains various optimization procedures including JavaScript minification, concatenation of localization resource files into to JSON files, and generation of HTML files for the default language if necessary.
  11. webapp-zip: This compresses each app to a separate zip file and puts them into the profile/ directory.
  12. optimize-clean: optimize-clean cleans the HTML files for the default language.
  13. contacts: Copies the preloaded contact file to your profile, if it exists in GAIA_DISTRIBUTION_DIR.
  14. extensions: Copies the extensions in GAIA_DIR/tools/extensions to your profile directory; different configuration setups allow you to specify copying different extensions.
  15. installed-extensions.json (additional-extensions.js): Finally, this script downloads certain additional extensions to your profile directory.

Build Script for apps

By default, app build script [app directory]/build/build.js will be executed by app.js if it exists. if $APP/build/build.js does not exist, app.js will copy app into build_stage.

files in app directory should be copied into build_stage directory by app build script becuase app.js will not copy them if app build script exists. for example, calendar app has build/build.js and utils.copyToStage() should be called in build.js for calendar app.

build script for apps can require all build modules in $GAIA_DIR/build especially utils module which is a very useful module for building apps, you can use require('utils') to get the module.

Customizing the preferences

If you find that you have a set of custom preferences you need to set each time you flash your device, you can create a file called custom-prefs.js inside the build/config directory and store them in there. This keeps them from being overwritten and out of source control.

Here are some useful preferences:

// this enables marionette which lets you run performance tests
// see
user_pref("marionette.defaultPrefs.enabled", true);

// this sets the port for remote debugging your application on the device
user_pref("devtools.debugger.remote-port", 60000);

// this enables the remote debugger
user_pref("devtools.debugger.remote-enabled", true);

// this outputs debug information about the Radio Interface Layer in logcat
user_pref("ril.debugging.enabled", true);

This file is read each time you generate a profile. The safest way to be sure that everything is generated is to delete your profile first:

rm -rf profile && make profile

Then you can safely use the install-gaia goal.


The device remains black after a flash

This can sometimes happen if you flash the device while it is idle. To remedy this just restart B2G by using the following command from the command line:

adb shell stop b2g && adb shell start b2g


Document Tags and Contributors

Last updated by: RickyChien,
Hide Sidebar