Now that I've got NixOS installed I needed a way to build and make changes to Firefox and Firefox OS. This post goes through the approach I've taken to work on the Firefox codebase. In a later post I'll build on this to do Firefox OS development.

Building Firefox isn't difficult as NixOS has definitions for standard Firefox builds to follow as examples. To build from a local source repository it requires all the pre-requisite packages to be installed. I don't want to pollute my local user environment with all these packages though as I develop on other things which may have version clashes. As an example, Firefox requires autoconf-2.13 whereas other systems I develop with require different verisons.

NixOS (through the Nix package manager) allows setting up build environments that contain specific packages and versions. Switching between these is easy. The file ~/.nixpkgs/config.nix can contain definitions specific for a user. I add the definitions as a packageOverride in this file. The structure of the file looks like:

{ packageOverrides = pkgs : with pkgs; rec { ..new definitions here.. }; }

My definition for a build environment for Firefox is:

firefoxEnv = pkgs.myEnvFun { name = "firefoxEnv"; buildInputs = [ stdenv pkgconfig gtk glib gobjectIntrospection dbus_libs dbus_glib alsaLib gcc xlibs.libXrender xlibs.libX11 xlibs.libXext xlibs.libXft xlibs.libXt ats pango freetype fontconfig gdk_pixbuf cairo python git autoconf213 unzip zip yasm alsaLib dbus_libs which atk gstreamer gst_plugins_base pulseaudio ]; extraCmds = '' export C_INCLUDE_PATH=${dbus_libs}/include/dbus-1.0:${dbus_libs}/lib/dbus-1.0/include export CPLUS_INCLUDE_PATH=${dbus_libs}/include/dbus-1.0:${dbus_libs}/lib/dbus-1.0/include LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:${gcc.gcc}/lib64 for i in $nativeBuildInputs; do LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:\$i/lib done export LD_LIBRARY_PATH export AUTOCONF=autoconf ''; };

The Nix function pkgs.myEnvFun creates a program that can be run by the user to set up the environment such that the listed packages are available. This is done using symlinks and environment variables. The resulting shell can then be used for normal development. By creating special environments for development tasks it becomes possible to build with different versions of packages. For example, replace gcc with gcc46 and the environment will use that C compiler version. Environments for different versions of pango, gstreamer and other libraries can easily be created for testing Firefox builds with those specific versions.

The buildInputs field contains an array of the packages to be avaliable. These are all the pre-requisites as listed in the Mozilla build documentation. This could be modified by adding developer tools to be used (Vim, Emacs, Mercurial, etc) if desired.

When creating definitions that have a build product Nix will arrange the dynamic loader and paths to link to the correct versions of the libraries so that they can be found at runtime. When building an environment we need to change LD_LIBRARY_PATH to include the paths to the libraries for all the packages we are using. This is what the extraCmds section does. It is a shell script that is run to setup additional things for the environment.

The extraCmds in this definition adds to LD_LIBRARY_PATH the lib directory of all the packages in buildInputs . It exports an AUTOCONF environment variable to be the autoconf executable we are using. This variable is used in the Mozilla build system to find autoconf-2.13 . It also adds to the C and C++ include path to find the DBus libraries which are in a nested dbus-1.0 directory.

To build and install this new package use nix-env :

$ nix-env -i env-firefoxEnv

Running the resulting load-env-firefoxEnv command will create a shell environment that can be used to build Firefox:

$ load-env-firefoxEnv ... env-firefoxEnv loaded $ git clone git://github.com/mozilla/gecko-dev ... $ cd gecko-dev $ ./mach build

Exiting the shell will remove access to the pre-requisite libraries and tools needed to build Firefox. This keeps your global user environment free and minimizes the chance of clashes.