Building Chromium for Chromium OS (simple chrome)

This workflow allows you to quickly build/deploy Chromium for any Chromium OS device, without a Chromium OS checkout, and without a Chromium OS chroot.

At its core is the chrome-sdk shell which sets up the shell environment, and fetches the necessary SDK components (CrOS toolchain, sysroot, etc.).

Typography conventions

Color Paths, files, and commands:
green text on your build machine, outside the chroot
purple text inside the chrome-sdk shell on your build machine
Note: This is not the same thing as the cros-sdk chroot.
crimson text on your Chromium OS device

Checkout Chromium

First off make sure all preconditions are met:

  1. You have a local copy of the Chromium source code.
  2. You have a local copy of depot_tools.

Secondly, think about whether you need access to Google APIs from the executable you are building.  If the answer is yes, you will need to have your keys (see http://www.chromium.org/developers/how-tos/api-keys) either in your include.gypi, or in a file in your home directory called ".googleapikeys".

Run `cros chrome-sdk`

Run this from within your Chromium checkout (not the Chromium OS chroot):

NOTE: When prompted for a project ID, enter 134157665460 as your project ID (this is the Chrome OS project ID).

gclient sync -n -R

# Note: Replace $BOARD with a Chromium OS board name

cros chrome-sdk --board=$BOARD

cros chrome-sdk may ask you to set up gsutil access by providing you with a link. Follow the link, and grab the authentication token. Then paste the token into the prompt. (If you are a Googler, use your @google.com account)

cros chrome-sdk will fetch the latest Chrome OS SDK for building Chrome, and put you in a shell (with a yellow command prompt).  chrome-sdk will also automatically install and start the Goma server, with the active server port stored in the $SDK_GOMA_PORT environment variable.

The necessary environment variables needed to build Chrome (i.e., GYP_DEFINES, GYP_GENERATORS, etc.) are set up for you, and the contents of ~/.chromite/chrome_sdk.bashrc (which you can use to set a custom environment) will be sourced. If you use a ~/.gyp/include.gyp file to customize your builds outside of this workflow, note that it will override GYP_DEFINES, which may cause issues (see http://crbug.com/411469). You can work around this by setting the GYP_CONFIG_DIR environment variable to point to a different directory in chrome_sdk.bashrc.

Tip: cros chrome-sdk will set up the environment to build external Chromium by default. To build the official Chrome, run with the --internal flag.

Note1: There are no public builders yet for non-generic boards, so you'll have to use the generic or create your own local build. Star http://crbug.com/360342 for updates.

Using a custom Chromium OS build from your Chromium OS chroot (optional)

If you are making changes to Chromium OS and have a Chromium OS build inside a chroot that you want to build against, run cros chrome-sdk with the --chroot option.

cros chrome-sdk --board=$BOARD --chroot=/path/to/chroot

Build Chromium

cros chrome-sdk defaults to setting Ninja as the GYP_GENERATOR. From inside the chrome-sdk shell, run the following commands, where %CHROME_DIR% is the path to your Chromium checkout:

unset PKG_CONFIG_PATH
cd %CHROME_DIR%/src
./build/install-build-deps.sh # Append --arm for arm targets (e.g., $BOARD=daisy)
# Optionally edit GYP_DEFINES here to remove debugging symbols - see tip, below
gclient runhooks
ninja -C out_${SDK_BOARD}/Release -j500 chrome chrome_sandbox nacl_helper

Congratulations, you've now built Chromium for Chromium OS!

Once you've built Chromium the first time, you can build incrementally just using ninja. Here's an example:

ninja -C out_${SDK_BOARD}/Release -j500 chrome

Tip: The default extensions will be installed by the test image you use below.

Tip: The default GYP_DEFINES specifies "release_extra_cflags=-g", which gives you debugging symbols, but then the symbols are stripped by default before deploying to the device! This just slows down your build. If you don't need debugging symbols at all, you can make your compile and link a lot faster by removing this. Try running this before gclient runhooks:

export GYP_DEFINES=${GYP_DEFINES//release_extra_cflags=-g/}

Set up the Chromium OS device

Before you can deploy your build of Chromium to the device, it needs to have a test image loaded on it.

Create a bootable USB stick

You will need a 4GiB USB stick (you can get one at the ChromeStop where you picked up your Chromebook). Run cros flash from your current checkout and tell it to download & install the right test image.

Here, replace $BOARD with and <version> with the right values. Both can be seen in your SDK prompt (e.g. (sdk lumpy R27-3789.0.0) is the lumpy board using version R27-3789.0.0).

cros flash usb:// xbuddy://remote/$BOARD/<version>/test

See the Cros Flash page for more details.

Download a test image manually

Easiest way to get a test image is to let cros flash download it for you. However, if you want to download one manually, you can use the URL (where $BOARD and <version> are replaced same as above):
https://storage.cloud.google.com/chromeos-image-archive/$BOARD-release/<version>/chromiumos_test_image.tar.xz

After you download the compressed tarball containing the test image (it should have "test" somewhere in the file name), extract the image by running:

tar xf <path_to_file>

Put your Chrome OS device in dev mode

Follow the device-specific instructions to put your device into dev mode and enable booting from USB.

Install the test image onto your device

Now that you are in dev mode and have enabled booting from USB, plug the USB stick into the machine and reboot.  At the dev-mode warning screen, press Ctrl-U to boot from the USB.  Once you've booted from the USB, login as a guest user and press Ctrl-Alt-T to get a terminal and run (password is "test0000"):

shell
sudo /usr/sbin/chromeos-install

IMPORTANT NOTE: Installing Chromium OS onto your hard disk will WIPE YOUR HARD DISK CLEAN.

Connect device to corp network

To do this you will need a USB-to-ethernet dongle (you can find these at the techstop).

Deploying Chrome to the device

To deploy the build to a device, you will need direct ssh access to it from your computer. The scripts below handle everything else.

Checking the IP address

  1. Click the status area in the lower-right corner
  2. Click the network icon
  3. Click the circled i symbol in the lower-right corner
  4. A small window pops up that shows the IP address
This also works both before and after login. Another option is to run 'ifconfig' from the shell (Ctrl-Alt-t -> shell) after guest login.

Using deploy_chrome

Just type deploy_chrome from with your chrome-sdk shell. It will use rsync to incrementally deploy to the device.

Specify the build output directory to deploy from using --build-dir, and the IP address of the target device (which must be ssh-able as user 'root') using --to, where %CHROME_DIR% is the path to your Chrome checkout:

cd %CHROME_DIR%/src
deploy_chrome --build-dir=out_${SDK_BOARD}/Release --to=172.11.11.11

Tip: deploy_chrome lives under $CHROME_DIR/src/third_party/chromite/bin. You can run deploy_chrome outside of a chrome-sdk shell as well.

Tip: Specify the --target-dir flag to deploy to a custom location on the target device.

Debugging

Logfiles

Other than the normal system output in /var/log/messages, you can find the output of Chrome itself in /var/log/ui/ui.LATEST. This is where vmodule output and such ends up.

Commandline Flags and Envvars

If you want to tweak the command line of Chrome or its environment, you have to do this on the device itself.

R37 (and newer)

Edit the /etc/chrome_dev.conf file. Instructions on using it are in the file itself.

R36 (and older)

Edit the /sbin/session_manager_setup.sh script. If you go to the end, you'll see where Chrome is invoked and where you can tweak the flags/env.

Debug build

A debug build of Chrome will include useful tools like DCHECK()s and debug logs (DVLOG(), etc.). To build a debug version of Chrome, pass Debug instead of Release to ninja:

ninja -C out_${SDK_BOARD}/Debug -j500 chrome chrome_sandbox nacl_helper

Remote GDB

On the target machine, open up a port for the gdb server to listen on, and attach the gdb server to the running chrome process.  

sudo /sbin/iptables -A INPUT -p tcp --dport 1234 -j ACCEPT
sudo gdbserver --attach :1234 $(pgrep chrome -P $(pgrep session_manager))

On your host machine (inside the chrome-sdk shell), run gdb and start the Python interpreter:

cd %CHROME_DIR%/src
gdb out_${BOARD}/Release/chrome
Reading symbols from /usr/local/google2/chromium2/src/out_link/Release/chrome...
(gdb) pi 
>>>

Note: These instructions are for targeting an x86_64 device.  For now, to target an ARM device, you need to run the cross-compiled gdb from within a chroot.

Then from within the Python interpreter, run these commands:

import os
sysroot = os.environ['SYSROOT']
gdb.execute('set sysroot %s' % sysroot)
gdb.execute('set solib-absolute-prefix %s' % sysroot)
gdb.execute('set debug-file-directory %s/usr/lib/debug' % sysroot)
gdb.execute('target remote 12.34.56.78:1234')

If you wish, after you connect, you can Ctrl-D out of the Python shell.

Extra debugging instructions are located at http://www.chromium.org/chromium-os/how-tos-and-troubleshooting/debugging-tips.

Additional instructions

Updating the version of the Chrome OS SDK

When you invoke cros chrome-sdk, the script fetches the version of the SDK that corresponds to your Chrome checkout.  To update the SDK, sync your Chrome checkout and re-run cros chrome-sdk.

IMPORTANT NOTE: Every time that you update Chrome or the Chrome OS SDK, it is possible that Chrome may start depending on new features from a new Chrome OS image. This can cause unexpected problems, so it is important to update your image regularlyThe instructions for updating your Chrome OS image are in Step 4.

Specifying the version of the Chrome OS SDK to use

You can specify a version of Chrome OS to build against. This is handy for tracking down when a particular bug was introduced.

cros chrome-sdk --board=$BOARD --version=3680.0.0

Once you are finished testing the old version of the chrome-sdk, you can always start a new shell with the latest version again. Here's an example:

cros chrome-sdk --board=$BOARD

Updating Chrome

Tip: If you update Chrome inside the chrome-sdk, it will automatically run ./build/gyp-chromium for you inside the chrome-sdk shell.  Note that you may then be using an SDK that is out of date with the current Chrome.  See the section on 'Updating the version of the Chrome OS SDK' above.

git rebase-update
gclient sync

Using clang

Run cros chrome-sdk with the --clang flag.  Clang doesn't work with Ninja right now, so you'll also need to pass in --make.

cros chrome-sdk --board=$BOARD --clang --make

Then run these commands to build with make, where %CHROME_DIR% is the path to your Chrome checkout:

cd %CHROME_DIR%/src
./build/gyp_chromium
make -j1000 chrome chrome_sandbox nacl_helper

Note that  Make files are spread through the source tree, and not concentrated in the out_$BOARD directory, so you can only have one Make config running at a time.

Updating Deployed Files

Since the gyp files don't define which targets get installed, that information is maintained in the chromite repo as part of Chromium OS. That repo is also integrated into the Chromium source tree via the DEPS file.

In order to add/remove a file from the installed list:

  1. Go into the chromite directory and modify lib/chrome_util.py
    1. Look for the _COPY_PATHS list
    2. Add your new file with optional=True
  2. Commit your change locally using git
  3. Upload your change to gerrit
    1. git push origin master:refs/for/master
  4. Get it reviewed by someone on the Chromium OS build team (e-mail chromium-os-dev@ if you can't find anyone)
  5. Merge the change into Chromium OS via gerrit
  6. Update the DEPS file in Chromium to use the new chromite sha1
  7. Check in the Chromium change like normal
  8. Once everything has settled, then go back and remove the optional=True from the file list
    1. Unless the file is actually optional, then keep it
Comments