Zygote
Builder tracknerd

N01 — Build and boot AOSP

Check out AOSP, pick a target, build it and boot it in a virtual device. The guide every other nerd project depends on, and the one that needs the most disk, RAM and patience.

5 minAPI 1–37 · 17verified 2026-10-27

A full AOSP checkout and build is a serious machine operation. Before anything else, be honest about the hardware. The AOSP build documentation states a minimum of 400 GB of free disk space — roughly 250 GB to check out the code and 150 GB to build it — and a minimum of 64 GB of RAM on a 64-bit x86 system.1 That is hundreds of gigabytes and hours of build time on a fast machine, not a coffee-break download. If you do not have that machine, read Building AOSP instead; it explains the pipeline without asking you to run it.

TL;DR#

  • AOSP is many Git repositories described by one manifest. repo is the tool that manages them as a single tree.
  • source build/envsetup.sh then lunch selects a product, a release configuration and a build variant.
  • m builds it. Soong turns the tree into a Ninja graph; Ninja executes it.
  • The build produces images, not a running system. You boot the images in a virtual device.
  • A single-module build is much cheaper than m. Use it while iterating.

What you are building#

A bootable AOSP system image for a virtual target, plus a working adb connection to it. Nothing here is a phone-only skill: the same checkout and the same m command build every later project in this track.

Steps#

  1. Check the host

    The published minimums are 400 GB of free disk and 64 GB of RAM on a 64-bit x86 host. Check both before you start; a build that runs out of either fails in ways that are hard to diagnose.1

    You should seeEnough disk and RAM for one checkout plus one build.
  2. Install repo

    repo is a Python wrapper around Git that reads the AOSP manifest. Install it from your distribution or the AOSP instructions, then put it on PATH. Note that it is a tool for the tree, not part of the build.

    You should see`repo --version` prints a version.
  3. Initialise the tree
    mkdir aosp && cd aosp
    repo init --partial-clone --no-use-superproject -b android-latest-release \
      -u https://android.googlesource.com/platform/manifest

    The branch and the manifest URL define which tree you get. --partial-clone fetches file contents on demand, which makes the first sync smaller but keeps the network in the loop later.

    You should seeA `.repo` directory appears in the new checkout.
  4. Sync
    repo sync -c -j8

    -c restricts to the current branch, and -j8 sets the number of parallel jobs. This is the step people underestimate; it moves a lot of data.

    You should seeA very large download that eventually finishes.
  5. Load the build environment
    source build/envsetup.sh

    This must be sourced, not executed, because it defines shell functions in your current shell. Do it again in every new terminal.

    You should see`lunch` and `m` exist in this shell.
  6. Choose a target
    lunch aosp_cf_x86_64_only_phone-aosp_current-userdebug

    This is the Cuttlefish phone target used in the AOSP build documentation.1 The string has three parts: product, release configuration and build variant, separated by dashes. If you want the plain emulator instead of Cuttlefish, the exact target is listed on the AOSP "Create an AVD" page — check it there rather than guessing, because target names change between releases.

    You should seelunch prints the product, release configuration and variant.
  7. Build
    m

    m builds the default target for the lunch selection. It invokes soong_ui, which reads every Android.bp, resolves the graph, emits Ninja files and runs Ninja. Output lands under out/target/product/, where the system, vendor and boot images are assembled.

    You should seeImage files under `out/target/product/<target>/`.
  8. Boot the target

    For Cuttlefish, use the Cuttlefish launch tooling that matches your AOSP release; the command has changed across releases, so take it from the Cuttlefish documentation rather than from memory. For the emulator, the AOSP page documents building the AVD image and running the emulator command; the exact sequence belongs to that page. Either way, success looks the same: adb devices lists the device and the screen shows a launcher.

    You should seeThe virtual device reaches a home screen and shows in `adb devices`.
  9. Confirm what you booted
    adb shell getprop ro.build.version.sdk
    adb shell getprop ro.build.type

    ro.build.type should say userdebug if you lunched a userdebug variant. If it does not, you booted a different image than you built.

    You should seeProperties that match the target you built.
The whole sequence
mkdir aosp && cd aosp
repo init --partial-clone --no-use-superproject -b android-latest-release -u https://android.googlesource.com/platform/manifest
repo sync -c -j8
source build/envsetup.sh
lunch aosp_cf_x86_64_only_phone-aosp_current-userdebug
m
Example output
Illustrative — no build was executed in this run.

The files you touched#

Once it boots, the tree is readable in the browser as well as on disk. Every path below is open on Android Code Search, which is where you should read it.2 The platform layout — kernel, HAL, native libraries, runtime, framework, system apps — is the subject of the architecture overview.3

  • the Soong build system that reads Android.bp and emits Ninja
  • the legacy Make build and the Kati compatibility layer
  • README.mdthe init language, useful once the build boots
  • init.rcthe platform init.rc, which starts the first services
  • where every later nerd project edits code

If you want to change one of these rather than read it, contributions go through the Android Gerrit, not through a pull request.4

Verification#

A build is not a boot. The build succeeded when the images exist under out/target/product/; the boot succeeded when the device appears in adb devices and reaches a launcher. If the build passes and the boot fails, the problem is usually the target, the virtualisation setup or an incomplete sync — not the source.1

Once it does boot, the boot itself becomes readable: init parses the .rc files in the tree and starts the first services, which is what the next two projects change.5

What can go wrong#

  • You run out of disk. The published minimum is 400 GB for checkout plus build, and build output grows. repo sync failing partway with input/output errors is the usual symptom.
  • The build is OOM-killed. 64 GB of RAM is the stated minimum; less than that will fail with the linker or a compiler killed by the kernel, not with a compiler error.
  • lunch rejects the target. Target names differ between releases. Copy the target from the AOSP page for the branch you synced instead of reusing a string from a blog post.
  • m is not found. You did not source build/envsetup.sh in this shell, or you opened a new terminal.
  • The sync is incomplete. repo sync can stop on a network error and look finished. Re-run it; it is incremental.
  • The device boots but adb sees nothing. That is a host problem (virtualisation, networking or udev), not a build problem.

Sources#

Sources

Every version number, API level, class name and date on this page is traced to one of these. Pages are re-verified against them; last_verified above says when.

  1. docsBuild Androidsource.android.comaccessed 2026-10-27↩
  2. sourceAndroid Code Search (cs.android.com)cs.android.comaccessed 2026-10-27↩
  3. docsAndroid platform architecture (AOSP)source.android.comaccessed 2026-10-27↩
  4. sourceAndroid Gerrit code reviewandroid-review.googlesource.comaccessed 2026-10-27↩
  5. sourcesystem/core/rootdir/init.rcandroid.googlesource.comaccessed 2026-10-27↩