Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1136147
  • 博文数量: 276
  • 博客积分: 8317
  • 博客等级: 少将
  • 技术积分: 2329
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-12 08:17
个人简介

http://ads.buzzcity.net/adpage.php?partnerid=40096

文章分类

全部博文(276)

文章存档

2013年(1)

2012年(38)

2011年(102)

2010年(85)

2009年(45)

2008年(5)

分类: LINUX

2010-11-30 13:42:43

Intro

This guide should be a place that developers can go for information about getting started with Chromium OS.  The target audience of this guide is anyone who would like to obtain, build, or contribute to Chromium OS.  This guide doesn't go into detail about everything, but attempts to give people a broad overview of common tasks.

Guiding principles of this document:
  • You should be updating this document to fix it as necessary.  If something looks wrong but you don't know the right answer, at least put a red TODO saying that it looks wrong.  If you see a red TODO and know the right answer, fix it!
  • Only people with @chromium.org accounts can change the page.  Everyone else should please post to the Chromium OS dev group.
  • If possible, information should be placed directly in this page (it's OK if it grows big) and this should be the main place for general "getting started" information.  Other pages should link back to this page.  Where that's not possible, we should try to only point to small discreet chunks of information on other pages.  Why?  Following a web of links is very confusing for a new person, who really needs a linear flow.
  • Where possible, this page should describe a single way of doing things.  Where options are given, it should be clear why someone following the instructions would pick one or the other.  Where there is disagreement, an alternate option can be listed as a SIDE NOTE.

Audience of this document

This document is intended for consumption by anyone working on Chromium OS.  This could be a new developer who is simply interested in the project and wants to see what the fuss is about or a developer who has been working with Chromium OS for a long time.

Due to the fact that a large number of the people working on Chromium OS work at Google, there may occasionally be a reference or two in this document that is only relevant to engineers at Google.  These references should be kept at a minimum, since Chromium OS is an open source project and we want to be as open as possible.

Note: When you produce a Chromium OS image, you need to fulfill the various attribution requirements of the third party licenses. Currently, the images generated by a build don't automatically do this for you. You'll need to modify .


Getting started with Chromium OS development

Prerequisites
You need to have Linux to develop for Chromium OS.  Specifically, the supported environment is:
  • Linux (version 10.04 - Lucid) - Most developers working on Chromium OS are using Lucid (the LTS version of Ubuntu) and will not be updating to 10.10.  It is possible that things will work if you're running a different Linux distribution, but you will probably find life easier if you're on Lucid.
  • A 64-bit system for performing the build (we hope to support 32-bit at some point).
  • An account with sudo access (root access is needed to run the chroot command and modify the mount table).  NOTE: You shouldn't run any of the commands here as root--the commands themselves will run sudo to get root access when needed.
  • If you are building the Chromium browser from source, you might look at the .


Install depot_tools

To get started, you'll need to follow the instructions at install depot_tools.  This is required so that you can use the 'repo' command to get/sync the source code.


Install git

You will also need to install the git revision control system.  On Ubuntu, the magic incantation to do this is:

sudo aptitude install git gitk git-gui

This also installs git's graphical front end (git gui) and revision history browser (gitk).


Preparations if you are committer

If you are new to Chromium OS, you are NOT a committer.  You should skip this section.  Feel free to revisit if/when you .

Creating your ssh key

Committers will access the git repositories through an ssh connection.  That means we need to setup a ssh key.  Create a key using ssh-keygen. You will be asked for a password. Please provide one in order to protect your key.  Don't worry, with the keychain program (see below) you won't need to enter this password very often.

ssh-keygen -t rsa -f ~/.ssh/chromium

Submit your public key to the gitmaster

You'll need to give the public key that was generated (in ~/.ssh/chromium.pub) to the Chromium OS gitmaster and wait until it is accepted.  Whoever approved you as a committer should have given you instructions on how to do this.  They are purposely not listed here to avoid lots of spamming of the gitmaster.

Automate usage of your key with keychain

We want you to protect your chromium ssh key with a password, but you don't want to type that password all the time.  Enter the keychain command.  

On Ubuntu, install it with this command (assumes apt is configured with universe):
sudo aptitude install keychain

Then, you use it by adding this to the end of your ~/.bashrc file:
eval `keychain --eval ~/.ssh/chromium`

You should also run the above keychain command yourself now so that your current terminal will have access.

SIDE NOTE: The keychain command is really just a wrapper around ssh-agent.  You could use ssh-agent directly, but it's more complicated and thus doesn't belong in these instructions.  If someone is passionate about ssh-agent, feel free to make a sub-page about how to use ssh-agent instead of keychain.

FAQ: People wonder why we tell you to password protect your key, then turn around and tell you how to avoid entering the password.  The thing to note is that keychain only keeps the "decrypted" version of your ssh key in RAM (hopefully in protected memory).  This is more secure, since someone who has physical access to your machine can access the disk without your password (by rebooting from a CD-based Linux distribution), but cannot access the RAM so easily.

Setup your ssh config

The last step in the preparations for committers is to make sure that you have the following bit of text in your ~/.ssh/config file:

Host gitrw.chromium.org
  Port 9222
  User git
  IdentityFile %d/.ssh/chromium


# The remaining lines are optimizations for faster sync times. They # are not strictly necessary # NOTE: You should _NOT_ have ControlMaster and ControlPath lines # here. The repo tool handles setting up ControlMaster and # ControlPath and if you have something here it could potentially # conflict with repo's configuration.
# Turn off negotiations that don't make sense for sync connections
GSSAPIAuthentication no GSSAPIKeyExchange no PasswordAuthentication no RSAAuthentication yes   ForwardX11 no
ForwardX11Trusted no ForwardAgent no HostbasedAuthentication no RhostsRSAAuthentication no Protocol 2 # Prefer faster ciphers and MACs. Ciphers arcfour256,aes128-ctr,aes192-ctr,aes256-ctr MACs umac-64@openssh.com,hmac-md5,hmac-sha1



Decide where your source will live

There are always questions about where to place source code on your file system.  The author of this document places his source in ${HOME}/chromiumos, and this seems fairly common among Chromium OS developers.  I would suggest placing your source there, and all commands in this document assume that.  If you feel strongly, feel free to put your own source elsewhere.

IMPORTANT NOTE: If your home directory is on a NFS (as is true for engineers at Google), you must place your code somewhere else.  Not only is it a bad idea to build directly from NFS for performance reasons, but it won't actually work (the build uses sudo and root doesn't have access to your NFS mount).  Wherever you place your source, you can still make a symbolic link to it from your home directory (this is suggested), like this:

mkdir -p /usr/local/path/to/source/chromiumos
ln -s /usr/local/path/to/source/chromiumos ${HOME}/chromiumos

...otherwise, you should make the directory like this:

mkdir -p ${HOME}/chromiumos

SIDE NOTE: There were some suggestions about putting the source in ${HOME}/trunk (and the instructions suggested this for a while).  Having the source in ${HOME}/trunk allows you to have some sloppiness later (you can enter the same commands inside the build chroot and outside).  That may be convenient, but is dangerous because it might lead to you submitting a change to a build script that works on your machine, but doesn't work on someone else's machine (who doesn't have the code in ${HOME}/trunk).


Get the source

Chromium OS uses  to sync down the sources.  For those not familiar with repo, it is effectively a wrapper for the  that helps deal with a large number of git repositories.  You already installed repo when you installed depot_tools above.

If you are not a committer (probably true if you're new to the project -- see above), enter these commands:

cd ${HOME}/chromiumos
repo init -u
repo sync

If you are a committer, your commands are:

cd ${HOME}/chromiumos
repo init -u ssh://git@gitrw.chromium.org:9222/manifest
repo sync

SIDE NOTE: Some people advocate that you should tell the repo command to use the minilayout by appending -m minilayout.xml to the repo init line above.  It is the author's advice that you not do this.  It makes grepping for source code very difficult (though it does optimize your repo sync a bit).

SIDE NOTEIf you want to build on a branch pass the branch name to repo init (e.g: repo init -u [-m minilayout.xml] -b 0.9.94.T)


Create a chroot

To make sure that everyone uses the exact same tools and environment to build Chromium OS, all building is done inside a .  This chroot is its own little world: it contains its own compiler, its own tools (its own copy of bash, it's own copy of sudo, ...).  Now that we've synced down the sources, we need to create this chroot.  Assuming you're already in ${HOME}/chromiumos (or wherever your source lives), the commands to setup the chroot are:

cd src/scripts
./make_chroot --replace

SIDE NOTE: You shouldn't have to create the chroot very often.  Most developers create it once and never touch it again unless someone explicitly sends out an email telling them to recreate their chroot.  Since this is very disruptive to developers, it doesn't happen very often.

SIDE NOTE: The --replace flag above will actually delete any old chroot that might have been present and re-create a new one.  If you don't pass in --replace, the make_chroot command will attempt to "fixup" your existing chroot.  I've heard this is not particularly well tested at the moment, so you probably shouldn't do it unless someone tells you to.


Enter the chroot

Most of the commands that Chromium OS developers use on a day-to-day basis (including the commands to build a Chromium OS image) expect to be run from within the chroot.  You can enter the chroot by using one of the commands in the src/scripts directory:

./enter_chroot.sh

This will probably prompt you for your password for the sudo command (entering the chroot requires root privileges), then print out a bunch of messages.  Once it is done, that terminal is in the chroot and you'll be in the ~/trunk/src/scripts directory (where most build commands live).

You should note that this src/scripts directory is the same src/scripts directory as you were in before you entered the chroot, even though it looks like a different location.  That's because when you enter the chroot, the "~/trunk" directory in the chroot is mounted such that it points to the main Chromium OS directory.  This means that changes that you make to the source code outside of the chroot immediately take effect inside the chroot.


IMPORTANT NOTE: In this document, commands that are intended to be entered inside the chroot and paths that refer to paths inside the chroot will be colored purple.

IMPORTANT NOTE: If you need to delete your chroot later, make sure to use ./make_chroot --delete to do it properly.  Using rm -rf could end up deleting your source tree.

SIDE NOTE: Some commands can be run from outside the chroot, even if they expect to be run inside the chroot.  These commands are smart enough to enter the chroot for the duration of the command. 
SIDE NOTE: If you need to share lots of files inside and outside chroot (for example, settings for your favorite editor / tools, or files downloaded by browser outside chroot, ...), read the Tips and Tricks for more information.


Choose what board you want to build for

When you build Chromium OS, you will produce an disk image (usually just called an "image") that is appropriate for copying directly onto the boot disk of the computer you'd like to run Chromium OS.  Depending on the specifics of the computer you're going to run Chromium OS on, you may want different things on that disk image.  For instance, if your computer has an ARM processor, you'll want to make sure that everything on the disk is compatible with ARM.  Similarly, if your computer has some specialized hardware, you'll need to include driver software for that hardware.

Different classes of computers are referred to by Chromium OS as different target "boards".  The following are some example boards:
  • x86-generic - A good place to get started if you're running Chromium OS on a computer with a x86-compatible CPU.
  • arm-generic - A good place to get started if you're running Chromium OS on a computer with a ARM CPU.
  • x86-pineview - A reference x86 computer produced by Intel.  TODO: insert quick description of what's unique here.
  • tegra2 - A reference ARM computer produced by Nvidia.  TODO: insert quick description of what's unique here.
You will need to choose a board for your first build.  Don't worry too much--you can always build for another board later.  If you want a list of known boards, you can look in ~/trunk/src/overlays:

You will need to to specify the name of the board to various steps in the build process.  To facilitate this process, it can be helpful to keep the name of the board in a shell variable.  This is not strictly necessary, but makes it so that you can simply copy and paste the commands below into your terminal program.  ...so enter the following inside your chroot (note: change x86-generic to whatever board you want to build for):

BOARD=x86-generic


Initialize the build for a board

To start building for a given board, you will want to issue the following command inside your chroot (you should be in the ~/trunk/src/scripts directory):

./setup_board --board=${BOARD} --force

This will setup the board target with a default sysroot of /build/${BOARD}.


SIDE NOTE: If you pass the "--default" flag to setup_board, it will place the board name in the file ~/trunk/src/scripts/.default_board (it does the same as echo ${BOARD} > ~/trunk/src/scripts/.default_board).  This will make it so that you don't need to specify a --board argument to all future commands.  We don't do that in these instructions so that you can explicitly see what commands are actually board-specific.

SIDE NOTE: If you don't pass --force into this command and you've already setup/built for this board previously, it will fail.  You can only setup a board that does not yet exist.  The --force flag will delete the /build/${BOARD} directory and setup a new board.  Like enter_chroot.sh, most people only re-run setup_board when told to (AKA they don't re-run it even after a repo sync).

SIDE NOTE: You can delete the board sysroot at any time with: sudo rm -rf /build/${BOARD}


Set the chronos user password

On a Chromium OS computer, you can get command line access (and root access through the sudo command) by logging in with the shared user account: chronos.  You should set a password for this user by entering this command from inside the ~/trunk/src/scripts directory:

./set_shared_user_password.sh

You will be prompted for a password, which will be stored (in encrypted form) in the "shared_user_password.txt" file in your src/scripts directory.  

SIDE NOTE: Remember that the "src/scripts" directory is the same physical directory both inside and outside the chroot (not colored purple here to emphasize that).  That means that, even if you completely recreate your chroot, you don't have to run this command again.  The only time you'd ever need to run it again is if you sync down fresh source code.

SIDE NOTE: If you don't set a shared user password, the password for the chronos account may end up being any number of things depending on some complicated (and constantly evolving) formula that includes whether you build a developer image, whether you boot into developer mode, and the current state of the scripts.  The password might be empty, or a well-known string, or it might be impossible to login with chronos.  I strongly suggest you just set a shared user password.  TODO: put a link to some place with more info about this.


Enable a local user account (optional)

The local user account allows login with no password even if you can not connect to the Internet. If you are customizing Chromium OS and having trouble logging in due to your customizations, it may be handy to be able to bypass authentication and log yourself in as a test user. This is disabled by default for security reasons, but if you want to enable it for a backdoor user USERNAME, enter the following from inside the ~/trunk/src/scripts directory:

./enable_localaccount.sh USERNAME

SIDE NOTE: The author of this page has been developing for Chromium OS for quite a while and never needed to enter this command.  TODO: Can this be moved elsewhere?


Build the packages for your board

To build up all of the packages for your board, you can run the following command (which is fairly slow) from inside the ~/trunk/src/scripts directory:

./build_packages --board=${BOARD} --oldchromebinary

This step is the rough equivalent of make all in a standard Makefile system.  This command is supposed to handle incremental builds, so you will want to run it whenever you change something and need it rebuilt (or after you run repo sync).

Normally, build_packages will build the stable version of a package (i.e. from committed git sources) unless you are working on a package (with cros_workon).  If you are working on a package, build_packages will build using your local sources.  See below for information about cros_workon.


SIDE NOTE: The --oldchromebinary flag is not strictly necessary but will make your build faster in some rare instances (when the Chrome/Chromium browser has recently been revved) at the cost of a slightly older version of Chrome/Chromium.  This may become the default in the future.

SIDE NOTE: Even though there are some flags that can optimize your build (like --nowithdev, --nowithautotest, etc), you shouldn't use them (even if you don't plan on building a developer / test image).  There are some that can cause some hard-to-debug differences if you use one of these options.


Build a disk image for your board

Once the build_packages step is done, you're ready to make an image by running this command from inside the ~/trunk/src/scripts directory:

./build_image --board=${BOARD} --withdev --noenable_rootfs_verification

This will create an image with developer tools that allows you to freely modify the root file system.  The image produced won't be a secure version of Chromium OS, but will give you fairly liberal access.  If you would like a more secure, locked-down version of Chromium OS, you should leave off the --withdev and --noenable_rootfs_verification options.

The image produced by build_image will be located in ~/trunk/src/build/images/${BOARD}/versionNum/ (where versionNum will actually be a version number).  The most recent image produced for a given board will be symlinked to ~/trunk/src/build/images/${BOARD}/latest.

IMPORTANT NOTE: It's up to you to delete old builds that you don't need.  Every time you run build_image, it will create a files that take up over 4GB of space (!).


Looking at your disk image (optional)

If you want, you can look at the rootfs of the disk image that you just created by using this set of commands:

cd ~/trunk/src/build/images/${BOARD}/latest
./unpack_partitions.sh chromiumos_image.bin
mkdir -p rootfs
sudo mount -o loop part_3 rootfs

This will do a loopback mount of the rootfs from your image to the location ~/trunk/src/build/images/${BOARD}/latest/rootfs in your chroot.

If you built an x86 Chromium OS image, you can probably even try chrooting into the image.  This is a little hacky (the Chromium OS rootfs isn't really designed to be a chroot for your host machine), but it seems to work pretty well.  Don't forget to exit this chroot when you're done.

sudo chroot ~/trunk/src/build/images/${BOARD}/latest/rootfs

Don't forget to umount the root filesystem when you're done:

sudo umount ~/trunk/src/build/images/${BOARD}/latest/rootfs 

If you don't want to unpack the partitions (which takes up extra disk space), you can also mount directly without unpacking:

cd ~/trunk/src/build/images/${BOARD}/latest
ROOTA_START=`grep 'ROOT-A' unpack_partitions.sh | awk '{print $2;}'`
mkdir -p rootfs
sudo mount -o loop,offset=$((512 * ${ROOTA_START})) chromiumos_image.bin rootfs

Again, don't forget to unmount when you're done:

sudo umount ~/trunk/src/build/images/${BOARD}/latest/rootfs 

TODO: I think most/all of the above is handled in src/scripts/mount_gpt_image.sh.  Rewrite the above using that script.


Getting your image onto a USB key

You can boot Chromium OS either from real hardware, or from a virtual machine.  If you'd like to boot real hardware with your image, the easiest way is to put it on a USB flash drive.  The first step is to insert a USB flash disk (a 4GB or bigger) into your computer.  This disk will be completely erased, so make sure it doesn't have anything important on it.  Wait ~10 seconds for it to register, then type the following command from in the ~/trunk/src/scripts directory:

./image_to_usb.sh --board=${BOARD}

...since we didn't pass a --to parameter, the image_to_usb.sh command will list all USB disks that it could find.  If yours isn't listed, wait a few seconds and try the command again.  Once you've found your USB disk (mine usually to show up as /dev/sdc), you're ready to re-enter the command with a --to parameter (you should replace ${MY_USB_KEY_LOCATION} with the one for your disk, like /dev/sdc):

./image_to_usb.sh --board=${BOARD} --to=${MY_USB_KEY_LOCATION}

When the image_to_usb.sh command finishes, you can simply unplug your USB key and it's ready to go.

IMPORTANT NOTE: Remember, running this command will completely replace the contents of your USB disk.  Make sure there wasn't anything important on it.

SIDE NOTE: By default, image_to_usb.sh will use the latest image for the given board.  If you want to specify a different image, you can specify it with --from.

SIDE NOTE: If you're interested in creating a test image (used for allowing Chromium OS to talk to autotest), see the Running Tests section.


Booting from your USB key

If you're on an x86-based PC/notebook, you should simply be able to configure your computer's BIOS to boot from your USB key.  After you've done this, just plug your newly minted USB key in, reboot, and you're booting into Chromium OS.  Your Chromium OS image may not have all the drivers to run all of the peripherals on your PC, but it should at least boot.

For specific information about what works on various different machines, see the Developer Hardware page.


Getting to a command prompt on Chromium OS

Since you set the shared user password (with set_shared_user_password.sh) when you built your image, you have the ability to login with the chronos user.  After your computer has booted to the Chromium OS login screen, you can get a text-based login prompt by pressing [ Ctrl ] [ Alt ] [ F2 ] on your keyboard.  Then, login with the chronos user and enter the password you set earlier.

Because you built an image with developer tools, you also have an alternate way to get a terminal prompt.  I'll mention this as well, since the alternate shell is a little nicer (in the very least, it keeps your screen from dimming on you), even if it is a little harder to get to.  To use this alternate way:
  1. Go through the standard Chromium OS login screen (you'll need to setup a network, etc) and get to the web browser.  It's OK if you login as guest.
  2. Press [ Ctrl ] [ Alt ] [ T ] to get the crosh shell.
  3. Use the shell command to get the shell prompt.  NOTE: you don't need to enter the chronos password here, though you will still need the password if you want to use the sudo command.

Installing your Chromium OS image to your hard disk

Once you've booted from your USB key and got to the command prompt, you can install your Chromium OS image to the hard disk on your computer.  You can do that with the command:

/usr/sbin/chromeos-install

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


Building an image to run in a virtual machine

Many times it is easier to simply run Chromium OS in a virtual machine like kvm.  You can to adapt the previously built Chromium OS image so that usable by kvm (which uses qemu images) by entering this command from the ~/trunk/src/scripts directory:

./image_to_vm.sh --board=${BOARD}

This will create the file ~/trunk/src/build/images/${BOARD}/latest/chromiumos_qemu_image.bin.

SIDE NOTE: If you want to adapt the image for other virtual machines, see the --format=vmware and --format=virtualbox options.  

SIDE NOTE: You can specify source/destination paths with the --from and --to parameters.

SIDE NOTE: If you're interested in creating a test image (used for allowing Chromium OS to talk to autotest), see the Running Tests section.


Building Chromium browser from source

TODO: validate that these instructions are still correct

The  page might be useful to look at here?

The chromeos-base/chromeos-chrome ebuilds contain a step for verifying that the libcros API is still compatible with the revision of Chromium being built.  In order for the ebuild to find the header files you'll need to "work on" the chromeos-chrome/libcros package.  Do the following from within the ~/trunk/src/scripts directory:

# You only need to do this once!
./cros_workon start chromeos-base/libcros
repo sync

# If you want to always build from source you can export the variables:
export CHROME_ORIGIN=LOCAL_SOURCE
export FEATURES="-usersandbox"
export USE="-build_tests"
./build_packages

# If you want to only emerge the browser:
USE="-build_tests" FEATURES="-usersandbox" CHROME_ORIGIN=LOCAL_SOURCE emerge-${BOARD} chromeos-base/chromeos-chrome

Additional instructions on building Chromium from source can be found in the instructions on 
.



Using devserver

Auto-update from devserver

TODO: this is a first cut describing what works for me.

When you build a Chromium OS image it will be configured with the name of the build machine as the source for updates. The developer server (devserver) can be configured to provide a simple update service for any machines that have your image installed on them. When you build a new image, rather than messing about with USB keys you can update over the network (provided the device running Chromium OS can access your build machine over the network). Start the devserver inside the chroot telling it to act as an update server:

./start_devserver --board=${BOARD} --client_prefix ChromeOSUpdateEngine 

Now on the Chromium OS device select "About" under the wrench menu and click the button to check for updates, this could take some time. You should see lots of output from the devserver as it generates and provides the update and the Chromium OS device will indicate progress and eventually ask for a restart.

Use gmerge to install or update individual packages from devserver

TODO: merge with this: 

TODO: document this.  Remember to note that your image must have --noenable_rootfs_verification for gmerge to work (right?).



Making changes

Now that you've got everything built, you're ready to start making some changes.  Depending on what you're going to be changing, there are some special instructions you'll want to follow.


Making changes to a package whose source is in our tree

If you'd like to make changes to a Chromium OS package whose source is in our tree, this is the workflow to look at.  Specifically, this is a package where:
  • The ebuild for the package lives in the src/third_party/chromiumos-overlay or src/overlays/overlay-${BOARD} directories.
  • There is an ebuild for the package that ends with 9999.ebuild.
  • The ebuild inherits from the cros-workon class.
  • The ebuild has a KEYWORD in the ebuild containing this architecture name (like "x86").
You can see a list of all of these packages by running this from inside the ~/trunk/src/scripts directory:

./cros_workon --board=${BOARD} list --all 

Run cros_workon start

The first thing you'll want to do is to mark the package as active, like this (replacing ${PACKAGE_NAME} with your package name, like chromeos-wm):

./cros_workon --board=${BOARD} start ${PACKAGE_NAME}

This will:
  • Indicate that we'd like to build the 9999 version of the ebuild instead of the stable, committed version.
  • Indicate that we'd like to build from source every time.
  • If you specified that you wanted the minilayout when you did your repo init, this will add a clause to your .repo/local_manifest.xml to tell repo to sync down the source code for this package next time you do a repo sync.

repo sync

After you've run cros_workon, you'll want to sync down sources.  This is critical if you're using the minilayout, but is probably a good idea in any case to make sure that you're working with the latest code (it'll help avoid merge conflicts later).  You'll want to run this from outside the chroot, anywhere under your ~/chromiumos directory:

repo sync

TODO: The old instructions had this warning in them:

if you run repo sync inside your chroot ensure your email is configured right in git (git config -l). If your local commit email differs from your git config email address or if your git config email address is unset a "repo sync" will discard your local commits. The make_chroot / enter_chroot commands have been enhanced to copy your global git config into the chroot, so this should just work.

...someone who knows better should figure out if this warning is still relevant and update this section.

Figure out where the ebuild / source code for the project is

It can be a little tricky to figure out where the source code and ebuild for your project is.  Luckily, some magic portage commands can come to the rescue.

To find out where the ebuild lives:

equery-${BOARD} which ${PACKAGE_NAME}

...for PACKAGE_NAME=chromeos-wm, that gave me:
    /home/.../trunk/src/third_party/chromiumos-overlay/chromeos-base/chromeos-wm/chromeos-wm-9999.ebuild

NOTE: If I ran that same commands without doing a cros_workon first, you can see the difference:
    /home/.../trunk/src/third_party/chromiumos-overlay/chromeos-base/chromeos-wm/chromeos-wm-0.0.1-r134.ebuild


To find out where the source code lives (and what git repo it's under):

ebuild-${BOARD} `equery-${BOARD} which ${PACKAGE_NAME}` info

Again trying with PACKAGE_NAME=chromeos-wm, I saw this:
    CROS_WORKON_SRCDIR="/home/.../trunk/src/platform/window_manager"
    CROS_WORKON_PROJECT="window_manager"


SIDE NOTE: This little shell script can be interesting / useful if you want to see info about all packages (it's a little slow, though):

ALL_PACKAGES=`./cros_workon --board=${BOARD} list --all`
for package in ${ALL_PACKAGES}; do
  ebuildPath=`equery-${BOARD} which ${package}`
  eval `ebuild-${BOARD} "${ebuildPath}" info`
  echo "${package} - $CROS_WORKON_PROJECT - $CROS_WORKON_SRCDIR"
done

Create a branch for your changes

Since Chromium OS uses repo/git and git-cl, you should always create a local branch whenever you make a change.  You can run the command to do this from outside the chroot (anywhere under your ~/chromiumos directory) or from within the chroot.  In the command, you'll want to replace ${CROS_WORKON_PROJECT} with the project name you found in the previous step and replace ${BRANCH_NAME} with a name that is meaningful to you and describes this change (nobody else will see this name):

repo start ${BRANCH_NAME} ${CROS_WORKON_PROJECT}

The branch created will be based on the remote branch.  If you've made any other local changes, they will not be present in this branch.

Make your changes

You should be able to make your changes to the source code now.  To incrementally compile your changes, use 

./bin/cros_workon_make --board=${BOARD} ${PACKAGE_NAME}

This will build your package inside your source directory.  Change a single file, and it will rebuild only that file and re-link.  If your package contains test binaries, using

./bin/cros_workon_make --board=${BOARD} ${PACKAGE_NAME} --tests

will build and run those binaries as well.  Call cros_workon_make --help to see other options that are supported.

TODO: Describe the ideal workflow here.  Talk about devserver / gmerge?

Set your editor

Many of the commands below (the git and git cl ones) will open up an editor.  You probably will want to do one of these three commands (depending on your favorite editor).  

If you're not a *nix expert, nano is a reasonable editor:

export EDITOR='nano'

If you love vi:

export EDITOR='vi'

If you love emacs (and don't want an XWindow to open up every time you do something):

export EDITOR='emacs -nw'

You should probably add one of those lines to your .bashrc (or similar file) too.

Submit changes locally

When your changes look good, you should commit them to your local branch using git.  Full documentation of how to use git is a bit beyond this guide, but you might be able to commit them by running something like this command from the project directory:

git commit -a

...the git commit command will bring up a text editor.  You should describe your change, save, and exit the editor.  Note that the description is only for your own use.  When you upload your changes for code review, the git-cl command will grab all of your previous descriptions, but you will have a chance to edit them.

Upload your changes and get a code review (committers only)

Once your changes are committed locally, you'll want to upload your change using git-cl.  The git-cl command is very un-git-like.  It takes all of the changes in your local branch, munges them into one patch, then uploads that to the code review server.  You should run the command from outside the chroot, from within a directory that's part of the project you're working on:

git cl upload

The git cl upload command will bring up a text editor.  What you write here is important, since it will get sent to the code review server.  The first line should be a short description of your change.  Later lines can contain more descriptions.  The text editor will also be populated with BUG= and TEST= lines.  

For BUG=, you should put something that looks like: BUG=bug-tracker:number.  If this change is related to more than one tracker issue, you can list them all separated with commas.  You can get a tracker name by looking in the upper-left corner in the tracker page.

For TEST=, you should describe what you did to test the change.

Here's what a sample would look like:

# Enter a description of the change.
# This will displayed on the codereview site.
# The first line will also be used as the subject of the review.
Here's a SHORT, one-line summary of my change.

And here is more details
...this can be as long as I want.

BUG=chromium-os:99999, chromium:88888
TEST=Ran all the white box tests

Save the file and exit the editor.  This will upload the changes and print out a URL for the code review.  Go to that URL (log in with your chromium.org account, which you might want to do in an "incognito window" in Chrome) and use the "Publish+Mail Comments" to mail it to your reviewers.

You will likely get comments from reviewers on what you need to change before submitting.  You should make these changes, submit them locally, then re-upload your changes for code review.  Note that git-cl stores the code review "issue number" as meta data on your git branch.  That means that each git branch is associated with one and only one code review.  If you do a second git cl upload on your branch, it will amend your previous code review, not start another one.

Eventually, all your reviewers will be fat and happy and will tell you LGTM (looks good to me).

Push your change

Once you've iterated a few times and your code reviewers are happy (you get Looks Good To Me from all of them), you can push your change to live with:

git cl push

You probably want to do a repo sync before the git cl push to make sure that nothing is broken.  This could cause a merge conflict.  TODO: Some short desc of how to deal with merge conflicts?


SIDE NOTE: If you want to start on another (unrelated) change while waiting for your review to happen, you can repo start another branch, then later come back to this branch by doing git checkout ${BRANCH_NAME} from within a directory associated with this project.

SIDE NOTE: Now that you've pushed, if (for some reason) you wanted to re-use your same branch for another code review, you could clear your code review with git cl issue 0.

Submitting changes (non-committers)

If you're not a committer, I believe that the process is to submit a patch to the the Chromium OS dev group.  

TODO: put instructions for generating this patch.  You might want to see git-format-patch?

Cleaning up after you're done with your change

Once you're done with your change, you're ready to clean up.  The most important thing to do is to tell cros_workon that you're done by running this from inside the ~/trunk/src/scripts directory:

./cros_workon --board=${BOARD} stop ${PACKAGE_NAME}

...this will tell cros_workon to stop forcing the -9999.ebuild and to stop forcing a build from source every time.


You can also delete the branch that repo created.  There are a number of ways to do that, but one of the ways is:

repo abandon ${BRANCH_NAME} ${CROS_WORKON_PROJECT}


SIDE NOTE: If you don't specify a project name with the repo abandon command, it will throw out any local changes across all projects.  You might also want to look at git branch -D or repo prune.

SIDE NOTE: If you were running with the minilayout, doing a cros_workon stop won't remove your source code.  It will continue to stay on your hard disk and get synced down.

Making sure your change didn't break things

After you commit, make sure you didn't break the build by checking the .


Making changes to something other than a package whose source is in our tree

If you want to make to changes to something other than the source code of a package, you can still follow most of the instructions above (in the Making changes to a package whose source is in our tree section).  However, simply skip the cros_workon steps.  Specifically, note that you still need the repo start step.

Things that fall into this category:
  • Build scripts (pretty much anything in src/scripts)
  • Changes to ebuild files themselves (like the ones under src/third_party/chromiumos-overlay)
  • Anything else?

Making changes to the way that the chroot is constructed

This section is currently a placeholder, waiting for someone to fill it in.  However, a few notes:
  • Many of the commands that take a --board=${BOARD} parameter can also be passed a --host parameters.  That will make the commands affect the host (AKA the chroot) rather than the board.
    • Most notably, cros_workon --host will say that you want to build a package used in the chroot from source.
  • If you modify the make_chroot script, remember that most developers won't get your change for a long time.  People tend to build their chroot once, then never again.  I believe that we're moving away from having the make_chroot script do much.


Building an individual package

TODO: Document this better..., and add the new cros_workon_make

Note: To build an individual package use emerge-${BOARD}. For example, if you want to build dash to test on your device:

emerge-${BOARD} dash


Working on a branch

It is required you have different checkouts (yes new chroots in a completely new directory) for every branch you are working on.  This is to ensure all the prebuilts work automatically for you. You have to pass the -b option to repo during init and you will follow exactly the same workflow as above. (i.e cros_workon + repo start etc)

$ mkdir cros_0.9.110.B/ && cd cros_0.9.110.B/
$ repo init -u  -b  [-m minilayout.xml]
$ #...follow steps above to edit/modify files i.e repo sync, cros_work start, repo start etc. 
$ git cherry-pick -x   #To pull in changes that exist on another branch (TIP: git has all the objects from all branches)
$ git log # to verify the SHA1 exists on the branch. 
$ git cl upload  #A new issue will be created for this branch commit
$ git cl push    # Make sure you have tested on your new branch - just cherry-picking doesn't guarantee it will build on the new branch

If you are a GIT Jedi master and a Portage black belt you can leverage the fact that all the branches checkouts actually checkout all the git objects, and the rest you can figure out :)


Troubleshooting

My build is failing, what's the problem?

It's possible that your build is broken because of transient failures introduced when a dependency is in-flight while its dependent is built.   These often manifest as missing files or configuration information.  Try re-running the build.

If re-running doesn't help, t to see if the problem exists there as well.


How do I fix network problems in the chroot?

TODO: This troubleshooting tip was from the old instructions.  Is it still relevant?

When running emerge inside the chroot it will use wget to fetch packages.  This wget process is run as the portage user, and if that user is unable to talk on the network it will be unable to resolve hostnames, among other things.  This can happen if the machine is using a local firewall service such as UncomplicatedFireWall (ufw package on Ubuntu) that limits network traffic to a specific set of users.

This can be verified by looking at the output of iptables, for example with ufw:

$ sudo iptables -L ufw-after-output | grep owner
ACCEPT     all  --  anywhere             anywhere            owner UID match root
ACCEPT     all  --  anywhere             anywhere            owner UID match yourname

One way to get around this is to add the portage user to the list of allowed users.  First, create the user on the build machine:

sudo useradd -d /var/tmp/portage -N -s /bin/false portage

Then add it to the list of allowed users in /etc/ufw/after.rules and /etc/ufw/after6.rules:

# allow outbound connections by portage user for building chromiumos
-A ufw-after-output -m owner --uid-owner portage -j ACCEPT

And restart the firewall:

sudo restart ufw



Running Tests

Many of the automated tests that are part of the Chromium OS project run using the autotest framework.  TODO: more details.  In order to run the autotests on your Chromium OS machine (or virtual machine), you must use an image that has been modified for test.  


Getting an image that has been modified for test

The easiest way to get an image that has been modified for testing is to add the --test_image flag to either image_to_vm.sh or image_to_usb.sh, like:

./image_to_usb.sh --board=${BOARD} --test_image --to=${MY_USB_KEY_LOCATION}

...or...

./image_to_vm.sh --board=${BOARD} --test_image 

Adding the --test_image flag will cause the image_to_xxx commands to make a copy of your chromiumos_image.bin file called chromiumos_test_image.bin (if that file doesn't already exist) and then modify that image for test and use the test image as the source of the command.  


SIDE NOTE: TODO: Is this still needed?  I don't think so now that the default stateful size is 2G.  When creating an VM image for testing purposes, it is highly recommended that you expand its stateful partition with the --statefulfs_size parameter. Otherwise, certain autotest scenarios will run out of stateful partition disk space since its default size on ChromeOS image files is equal to rootfs size of 2G.

SIDE NOTE: If the directory already has a file called chromiumos_test_image.bin, it will be reused.  That means that calling both image_to_usb.sh and image_to_vm.sh doesn't waste time by creating the test image twice.

SIDE NOTE: If you are so inclined, you can call the mod_image_for_test.sh script directly.  That will cause the script, by default, to modify your existing chromiumos_image.bin for test.  I don't see a lot of good reason to do this, unless you are low on disk space and know that you won't ever need the non-modified image.


Creating a new test

TODO: Validate that these instructions are still right.  They were copied from an old instructions page.

To create a new test, the following steps have to be taken.

  1. Create the source inside git repository R
  2. Find out which ebuild builds test from repository R, if R is a new repository, create a new ebuild for it (see below).
  3. Edit the ebuild, and add tests_${testname} into the IUSE_TESTS variable. Prefix your test with a + if you want it to be enabled by default.
  4. Recompile (see modifying a test), make sure it runs, commit, etc.
To create a new ebuild, you need to utilize the autotest eclass, which wraps all the necessary steps to compile your tests. A new ebuild may have to be created if a new repository with tests is being started. Please refer to existing ebuilds for details.

If you create a new ebuild for test X, you will need to run cros_workon start X.  Mysterious failures mode will occur otherwise.


Seeing which tests are implemented by an ebuild

TODO: Validate that these instructions are still right.  They were copied from an old instructions page.

Run this command and look at the "USE=" output.  The command tells emerge to "pretend" to build the tests and print out verbose output.  You'll want to replace ${EBUILD_NAME} with the name of an ebuild containing tests (see just below), like autotest-tests:

emerge-${BOARD} -pv ${EBUILD_NAME}

As far as I know, the only ebuilds containing tests are:
  • chromeos-base/autotest-tests - the default set of tests, that did not fall anywhere else
  • chromeos-base/chromeos-chrome - chrome tests; the tests that are part of chrome


More testing tips

At the moment, I'd read the Running Smoke Suite On a VM Image page for more info about tests.  It actually contains the most up-to-date info about autotests.  TODO: It would be nice if some of that information migrated here?


Tips and Tricks

This section is a bit free form.  People can put their own favorite tips and tricks here.

Looking for a text editor, but don't have the dev image?

Try running qemacs.  The qemacs editor is available, even on release images (though to get to the shell, remember that you need to be in developer mode).  Yes, it's not vi.  Yes, it's not nano.  ...but at least it's something.  Some future version of Chromium OS may include vi (maybe even instead of qemacs) through busybox.

Quick reference for those not used to emacs:
  • Ctrl-S: search for text
  • Ctrl-X, Ctrl-S: save the file
  • Ctrl-X, Ctrl-C: quit qemacs


Wish you had more commands available to you on the device?

If you're using the shell in a Chromium OS device (requires developer mode, or a system where you've set a custom chronos password), you may find that you're missing commands you wish you had.  Try putting busybox on a USB key or an SD Card.  I formatted by USB key with ext3 and named it utils (and that is assumed in these instructions) using the Disk Utility that comes with Ubuntu (go to the System menu at the top of the screen, then Administration).  Since busybox is built as part of a normal build (it's used in the factory image), you can copy it to your USB key like this (run from outside the chroot):

sudo chown root.root /media/utils
sudo chmod o+rx /media/utils
sudo cp ~/chromiumos/chroot/build/${BOARD}/bin/busybox /media/utils/
sudo chmod o+rx /media/utils/busybox

Then, you can go crazy and add symlinks for whatever your favorite busybox commands are:

for cmd in less vi zip zcat; do
  sudo ln -s busybox /media/utils/$cmd
done

Finally, unmount your USB key:

sudo umount /media/utils

...and plug it into your Chromium OS device.  Make sure that the browser has started (AKA you're not still on the login screen) so that Chromium OS will mount your usb key to /media/utils.  You can get access to your commands with:

sudo mount -o remount,exec /media/utils
export PATH="$PATH:/media/utils"

If you want a list of all of the commands that busybox supports, you can just run busybox to get a list.  If you want to run a busybox command without making a symlink, just type busybox first.  Like: busybox netstat.


How do I set up git bash completion on Ubuntu?

Add the following lines to your ~/.bashrc:

if [ -f /etc/bash_completion ]; then
 . /etc/bash_completion
fi


How do I set up repo bash completion on Ubuntu?

Copy the attached bash_completion file under your home directory (e.g., under ~/etc) and add the following line to your ~/.bashrc:

[ -f "$HOME/etc/bash_completion" ] && . "$HOME/etc/bash_completion"


How do I modify my prompt to tell me which branch I'm in?

Add the following to your ~/.bash_profile

export PS1='\h:\W$(__git_ps1 "(%s)") \u\$ '


How do I configure repo to sync private repositories?

Create a file called .repo/local_manifest.xml and add your private project into it. 

  
           fetch  = "ssh://gitrw.chromium.org"
           review = "" />

  
           name   = "nameofgitrepo"
           remote = "private" />

If you want to pull in from a different git server you will need to add a different remote for the project. Please type repo manifest -o tmp.xml to dump your current manifest to see an example. More documentation on the manifest file format is available on the .


How do I find a list of branches that I've created with repo?

See the repo branches command.


How do I share files for inside and outside chroot?

TODO: This tip is a draft because is not committed yet.
enter_chroot command supports mounting additional folders into your chroot environment.
You can create a .local_mounts file in src/scripts listing all folders (outside chroot) that you'd like to access inside chroot, for example:

# source(path outside chroot) destination(path inside chroot)
/usr/share/vim/google
/home/YOURID/Downloads /Downloads

Each line of .local_mounts refer to a mount command. If there is only one path name, it will be used as both source and destination. If there are two folder names listed in one line, the first is considered as the path INSIDE chroot and the second should be the path OUTSIDE chroot.

Note: For security and safety concern, all folders mounted by.local_mounts are read-only, and both the folders (inside and outside chroot) must already exist before calling enter_chroot.

How do I split my change into two (or any number of) separate changelists for upload?

Usually when submitting your changes into a revision control system, it is considered best practice to break your submissions into the smallest possible logical chunks and then submit one changelist per chunk.  Each chunk should work fine without future chunks, but may depend on previous chunks.  For instance, you may be able to submit your change to add a new API in a separate changelist from your change that uses the API.

This has several advantages:
  • It documents which parts of your change are related to what goal.
  • It makes it easy for someone to revert part of your change without reverting the whole thing (if there are problems).
  • It makes it easy for someone to cherry-pick your changes later.
Note that most developers will still develop their entire change at once, then only break things apart during submission.


It turns out that repo and git-cl are not really optimized for this workflow.  Why?
  • The git-cl command always munges all of the changes in your branch into one big changelist.  It does not easily allow you to create multiple changelists from a branch.
  • The repo command always creates branches from the mainline (AKA the remote master).  This makes it impossible to use repo to create branches that depend on one another.
...but, luckily, you can work around that by using git directly.

TODO: This is probably not the perfectly ideal way to do things, but will work.  Can someone optimize?

TODO: I haven't actually tested all of these steps.  They are based on an email plus my (poor) understanding of git.  Can someone test, then remove this TODO?

Do all your work in one big branch

I'll assume that you initially did all of your work in one big branch.  AKA, you started the branch like this:

repo start ${BRANCH_NAME} ${CROS_WORKON_PROJECT}

...and then made a bunch of changes.

Create a new branch for your first submission

To keep things simple, we're going to leave our first branch alone and create new branches for our submission.  We'd like to eventually get to a structure that looks like this (if we wanted to do N separate uploads, each of which was dependent on the previous ones):

master
  \_____${BRANCH_NAME}_A
          \_______________${BRANCH_NAME}_B

...so the first step is to create "${BRANCH_NAME}_A".  We can use repo start to do this one.  Remember, that I'm assuming ${CROS_WORKON_PROJECT} is the name of your project.

repo start ${BRANCH_NAME}_A ${CROS_WORKON_PROJECT}

The rest of the instructions are going to assume that you've changed into the directory that your project lives.  If you want to use repo to help you find it, you can do:

cd `repo forall ${CROS_WORKON_PROJECT} -c 'pwd'`

Get the relevant changes into branch A

There are probably better ways to this this, but one way to get the changes from your big branch into branch A is to use git cherry-pick.  First, use git log to figure out what changes you want:

git log ${BRANCH_NAME}

For instance, in my example, I see this (using --format=short):

commit d7b250822f98bda19f62072555beb66602bed29d
Author: Me

    Change 4

commit 0c577cee881471d6509c91eba8eeeb0c8bec1551
Author: Me

    Change 3

commit 0a7285d2d09159e540fb89f086f58a457b5f583f
Author: Me

    Change 2

commit dd1ee8d9a9d3148cf4403c339ab18f094304d2fa
Author: Me

    Change 1

Now, use git cherry-pick to pick the changes you want.  ...so if I wanted change #1 and #3, I could do:

git cherry-pick dd1ee8d9a9d3148cf4403c339ab18f094304d2fa
git cherry-pick 0c577cee881471d6509c91eba8eeeb0c8bec1551 

Create branch B

Now, you'll want to create branch B as a subbranch of branch A.  You can do that like:

git branch ${BRANCH_NAME}_B ${BRANCH_NAME}_A
git checkout ${BRANCH_NAME}_B

Get the relevant changes into branch B

We'll use the same cherry-picking technique to get things into branch B.  Let's imagine that I want change #2 and #4:

git cherry-pick 0a7285d2d09159e540fb89f086f58a457b5f583f
git cherry-pick d7b250822f98bda19f62072555beb66602bed29d 

Double-check that you've got everything

At this point, your branch B should have everything that was in the original branch.  There's a git diff command you can do to verify that:

git diff ${BRANCH_NAME}..${BRANCH_NAME}_B

Upload for code review

To upload the first part for code review, just do:

git checkout ${BRANCH_NAME}_A
git cl upload

To upload the second part for code review, just do:

git checkout ${BRANCH_NAME}_B
git cl upload ${BRANCH_NAME}_A  # sends diff from ${BRANCH_NAME}_A to ${BRANCH_NAME}_B

It is very important in this case that you mention in your second upload that this change depends on the first one.  You should actually include the URL pointing to the first code review in the changelist comments of the second change.  If you don't do this, your reviewers will be very confused.  Even better is if you can actually wait to start the code review for branch B until after the code for branch A has been committed.

Make changes, re-upload

To upload additional changes to branch A (the first changelist), you can do:

git checkout ${BRANCH_NAME}_A

# ... make changes ...

git cl upload
git checkout ${BRANCH_NAME}_B
git rebase ${BRANCH_NAME}_A     # Incorporate branch A's changes into branch B

To upload additional changes to branch B, you can do:

git checkout ${BRANCH_NAME}_B

# ... make changes ...

git cl upload ${BRANCH_NAME}_A  # sends diff from ${BRANCH_NAME}_A to ${BRANCH_NAME}_B

Push

When you're ready to push branch A, it's pretty easy:

git checkout ${BRANCH_NAME}_A
git cl push

To push branch B (which you can't do until after you've pushed branch A), you need to rebase it to master.  TODO: Can someone confirm that this is the right set of steps for Chromium OS?

git checkout cros/master
git pull
git checkout ${BRANCH_NAME}_B
git rebase --onto cros/master ${BRANCH_NAME}_A
git cl push


Other notes

Developer mode

Sometimes in this document, we talk about "developer mode".  It can be confusing about what developer mode is, since some instructions talk about developer mode being entered by running with an image that was built "--withdev" and others talk about switching your hardware to "developer mode".  It turns out that, for most things, the two actions both enable the same set of things (like the shell command in crosh).  Thus, we refer to either as being in "developer mode".


To get into details, putting your hardware into developer mode will make:

/bin/cros_boot_mode

...print developer.  It will also make the file /mnt/stateful_partition/.developer_mode appear.

Building with --withdev will create a file called /root/.dev_mode (in addition to adding a whole bunch of useful developer tools to your stateful partition).  The presence of the /root/.dev_mode file will enable developer mode and also prevent wiping of the stateful partition when you switch your hardware between developer mode and release mode.



More reading

You've now got the basics setup, but you've still got lots to learn.  

Here are some links to other chromium.org pages that might be helpful:
Here are some links to external sites that might be helpful:
  • The Gentoo Development Guide might be useful for (TODO: short description)
  • might be useful for (TODO: short description)
  •  might be useful for (TODO: short description)
  • The Gentoo Wiki on Cross-Compiling might be useful for (TODO: short description)
  •  might be useful for (TODO: short description)
  • The  might help you if you're curious about repo.  Or, you can go straight to the .
  • The repo-discuss group might be a good place to talk about repo.

阅读(14761) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~