[Step] AOSP Build
Overview
HexDroid provides a dedicated aosp step that simplifies the process of building AOSP/Android based projects.
The aosp step can handle the following tasks:
- Syncing AOSP manifest
- Setting up the build environment and lunch configuration(s)
- Running build commands
- Integrating with HexDroid Update Management (OTA) to define and distribute OTA (over-the-air) updates as part of your CI/CD pipeline.
A primary advantage of the aosp step is that it requires no scripting or custom logic.
All configurations are declarative.
This improves clarity, reduces maintenance overhead, and ensures reproducibility.
For example, when multiple build_variant values are defined under a single product_name, HexDroid automatically
expands these into
individual build executions. This expansion is handled internally and does not require additional pipeline logic.
Top Level elements
aosp command has several top level elements:
| Key | Description | Optional |
|---|---|---|
manifest | Performs checkout of aosp tree (repo init/repo sync). | Yes |
lunch | Defines product configurations to build (eng vs userdebug, etc) | Yes |
build | Commands that will be executed for each product configuration | Yes |
release | Creates release, uploads OTA files to HexDroid Update Management | Yes |
artifact | Attaches CI Artifacts (eg. target-files.zip, build logs, etc) | Yes |
steps:
- aosp:
# All elements here are incomplete, shown as example what all top level elements available
manifest:
lunch:
build:
release:
artifact:
Simplified Example
Example of a simple aosp step configuration:
steps:
- aosp:
manifest:
url: https://android.googlesource.com/platform/manifest
revision: main
name: default.xml
lunch:
product_name: aosp_cf_x86_64_phone
build_variant:
- userdebug
- eng
- user
build:
commands:
- m installclean
- m dist
This will be translated into the following steps:
repo init --manifest-url=https://android.googlesource.com/platform/manifest --manifest-branch=main --manifest-name=default.xml
repo sync --verbose
repo manifest --revision-as-HEAD --output-file=aosp_build_manifest_pinned.xml
bash -c set -e
source build/envsetup.sh
lunch aosp_cf_x86_64_phone-userdebug
m installclean
m dist
bash -c set -e
source build/envsetup.sh
lunch aosp_cf_x86_64_phone-eng
m installclean
m dist
bash -c set -e
source build/envsetup.sh
lunch aosp_cf_x86_64_phone-user
m installclean
m dist
manifest
The aosp step provides fine-grained control over the manifest initialization process through three optional phases:
init, sync, and pin.
By default, all three are enabled, ensuring a complete and repeatable setup of the AOSP source tree. However, each can be individually customized or disabled based on the needs of your project.
This allows for more flexible workflows, such as applying specific flags during sync operations.
| Element | Description | Required | Type |
|---|---|---|---|
| url | Manifest URL to checkout. Correspond to --manifest-url= in repo init | Required | String |
| revision | Manifest revision to checkout. Correspond to --manifest-branch= in repo init | Required | String Or Dynamic Lookup |
| name | Manifest file to use. Correspond to --manifest-name= in repo init | Optional | String |
| init | Additional control over repo init command. | Optional | Object |
| sync | Additional control over repo sync command. | Optional | Object |
| pin | Additional control over repo manifest command. | Optional | Object |
manifest.revision (required)
manifest.revision element can be either hardcoded such as:
steps:
- aosp:
manifest:
url: https://android.googlesource.com/platform/manifest
revision: main # points to a specific branch
or manifest.revision can be derived at runtime based on the trigger:
steps:
- aosp:
manifest:
url: https://android.googlesource.com/platform/manifest
revision:
# revision will be derived based on the trigger (e.g. `pull_request` trigger)
# For example, if `pull_request` trigger is set up, and the developer opens the pull request,
# The source branch of `pull_request` will be available here.
from: source_branch
manifest.init (optional)
By default init element will be expanded into:
repo init --manifest-url={url} --manifest-branch={revision} --manifest-name={name}
However, by defining init element you can have extra control such as turn it off, or adding specific flags.
init:
enabled: true # false to disable 'repo init ...', default is true
# List of additional flags to pass to 'repo init'
# Default empty
flags:
- "--depth=1"
manifest.sync (optional)
By default sync element will be expanded into: repo sync
However, by defining sync element you can have extra control such as turn it off, or adding specific flags.
sync:
enabled: true # false to disable 'repo sync', default is true
# List of additional flags to pass to 'repo sync ...'
# Default empty
flags:
- "--current-branch"
manifest.pin (optional)
By default pin element will be expanded into:
repo manifest --revision-as-HEAD --output-file=aosp_build_manifest_pinned.xml.
The AOSP manifest is automatically attached as an SBOM to the release if the release step is configured. This provides a complete record of the exact source code versions used in the build.
However, by defining pin element you can have extra control such as turn it off, or adding specific flags.
pin:
enabled: true # false to disable 'repo manifest ...', default is true
# List of additional flags to pass to 'repo manifest ...'
# Default empty
flags:
- "--verbose"
Example
steps:
- aosp:
manifest:
url: https://android.googlesource.com/platform/manifest
revision: main
name: default.xml
+ init:
+ enabled: true
+ flags:
+ - "--depth=1"
+ sync:
+ enabled: true
+ flags:
+ - "--current-branch"
+ - "--verbose"
+ pin:
+ enabled: true
+ flags:
+ - "--verbose"
lunch
| Element | Required | Type |
|---|---|---|
| product_name | Required | String |
| release_config | Optional | List of Nullable Strings |
| build_variant | Optional | List of Not Null Strings |
The lunch configuration in the aosp step defines the Android build environment, specifying the target product and
the build variants.
lunch:
product_name: aosp_cf_x86_64_phone
build_variant:
- user
- userdebug
- eng
In this case, the build step will be repeated 3 times with the following lunch targets:
aosp_cf_x86_64_phone-user, then aosp_cf_x86_64_phone-userdebug, then aosp_cf_x86_64_phone-eng.
In addition to the basic product_name and build_variant parameters, the release_config option provides
additional flexibility by allowing you to control build-time flags.
release_config identifies certain features and code that are behind feature launch flags and are either enabled or
disabled for a build.
For more on release configurations,
see Set feature flag launch values.
This allows you to verify, for example, in a pull request build job, that you can build all flag variations.
lunch:
product_name: aosp_cf_x86_64_phone
+ release_config:
+ # development release configuration called trunk_staging
+ - trunk_staging
build_variant:
- user
- userdebug
- eng
In this case, the build step will be repeated 3 times with the following lunch targets:
aosp_cf_x86_64_phone-trunk_staging-user, then aosp_cf_x86_64_phone-trunk_staging-userdebug, then
aosp_cf_x86_64_phone-trunk_staging-eng.
To build 'without' feature flag, you can specify an 'empty (aka null)' entry as such:
lunch:
product_name: aosp_cf_x86_64_phone
release_config:
# development release configuration called trunk_staging
- trunk_staging
+ # this will build without feature flags
+ -
build_variant:
- user
- userdebug
- eng
In this case, the build step will be repeated 6 times with the following lunch targets:
aosp_cf_x86_64_phone-trunk_staging-useraosp_cf_x86_64_phone-trunk_staging-userdebugaosp_cf_x86_64_phone-trunk_staging-engaosp_cf_x86_64_phone-useraosp_cf_x86_64_phone-userdebugaosp_cf_x86_64_phone-eng
build
| Element | Required | Type |
|---|---|---|
| commands | Optional (Default is empty) | List of Strings |
| aosp_build_env_setup | Optional (Default is true) | Boolean |
The build section lets you specify the AOSP build commands to execute after the environment is set up (
source build/envsetup.sh and lunch).
Default Behavior
By default, the aosp step handles the environment setup.
You only need to list the make commands (or other shell commands) you want to run within that environment.
build:
commands:
- m installclean
- m dist
Assuming the target is aosp_cf_x86_64_phone-userdebug (defined in the aosp.lunch step), the execution would resemble
this:
bash -c set -e
source build/envsetup.sh
lunch aosp_cf_x86_64_phone-userdebug
# Commands from your build.commands list
m installclean
m dist
Using a Custom Build Script
If you have a custom script that handles both the AOSP environment setup and the build process, you can disable the
step's automatic setup using aosp_build_env_setup: false.
build:
# Disable automatic 'source' and 'lunch'
aosp_build_env_setup: false
commands:
# Your custom script now handles setup and build
- ./my-aosp-build-script.sh
When aosp_build_env_setup is false:
- The
source build/envsetup.shandlunch <target>commands are not executed automatically by the step. - The intended target (e.g.,
aosp_cf_x86_64_phone-userdebug) is passed to your script(s) via the environment variableHEXDROID_CI_AOSP_LUNCH_TARGET. - Your script(s) listed under
commandsare executed sequentially.
The resulting execution for the example above would be:
bash -c set -e
export HEXDROID_CI_AOSP_LUNCH_TARGET=aosp_cf_x86_64_phone-userdebug
./my-aosp-build-script.sh
If you list multiple commands with aosp_build_env_setup: false:
build:
+ aosp_build_env_setup: false
commands:
+ - ./my-aosp-build-script.sh
+ - ./my-aosp-test-script.sh
They will run one after the other, with the environment variable available to both:
bash -c set -e
export HEXDROID_CI_AOSP_LUNCH_TARGET=aosp_cf_x86_64_phone-userdebug
./my-aosp-build-script.sh
./my-aosp-test-script.sh
artifact
The artifact step defined within the aosp step is inlined way to add CI artifacts for each configuration with in
aosp step.
When placed inside the aosp step, the artifact command will automatically execute for each build
variant (e.g., user, userdebug, eng) and configuration you defined.
This provides a convenient shortcut compared to defining multiple top-level artifact steps manually. The functionality remains the same as the standalone artifact step - refer to its documentation for the complete syntax and options.
Artifacts are files or sets of files generated during a pipeline execution that you can save after a job finishes. They allow you to preserve data like build outputs or test results beyond the job's lifespan.
Example:
steps:
- aosp:
manifest:
url: https://android.googlesource.com/platform/manifest
revision: main
name: default.xml
lunch:
product_name: aosp_cf_x86_64_phone
build_variant:
- userdebug
- eng
- user
build:
commands:
- m installclean
- m dist
+ artifact:
+ paths:
+ - out/dist/otatools.zip
+ - out/dist/*-target_files-root.zip
+ - out/dist/*-ota-root.zip
release (OTA)
The release step defined within the aosp step is a simplified way to publish OTA updates for each Android build
configuration.
When placed inside the aosp step, the release process will automatically execute for each build
variant (e.g., user, userdebug, eng) and configuration you defined.
This provides a convenient shortcut compared to defining multiple top-level release steps manually. The functionality remains the same as the standalone release step - refer to its documentation for the complete syntax and options.
The aosp step supports defining and publishing OTA releases through HexDroid Update Management.
You can learn more about HexDroid Release (OTA) management here.
Release step allows you to attach build artifacts, control distribution settings, and define staged rollouts.
Below is a starting template for an AOSP-based project, which will infer the target, resolve version_name and version_code based on AOSP build output artifacts.
steps:
- aosp:
manifest:
url: https://android.googlesource.com/platform/manifest
revision: main
name: default.xml
lunch:
product_name: aosp_cf_x86_64_phone
build_variant:
- userdebug
- eng
- user
build:
commands:
- m installclean
- m dist
+ release:
+ meta:
+ target:
+ type: execs
+ separator: /
+ # Example: generic/vsoc_x86_64/aosp_cf_x86_64_phone/userdebug/test-keys
+ command:
+ - get_build_var PRODUCT_BRAND
+ - get_build_var TARGET_DEVICE
+ - get_build_var TARGET_PRODUCT
+ - get_build_var TARGET_BUILD_VARIANT
+ - get_build_var BUILD_VERSION_TAGS
+ version_code:
+ type: file
+ # Example: 1743844748
+ path: out/build_date.txt
+ version_name:
+ type: file
+ path: out/dist/build.prop
+ # Example: BP1A.250405.007.D1
+ regex: "ro\\.system\\.build\\.id=(.+)"
+ payloads:
+ - file:
+ path: out/target/product/vsoc_x86_64/boot.img
+ type: ota
+ distributed: true
+ rollouts:
+ - rollout:
+ cohort_slug: development
+ action: activate
+ percentage: 100
+ - rollout:
+ cohort_slug: sqa
+ action: activate
+ percentage: 10
If aosp_build_env_setup is set to false in aosp.build, each command (for exec/execs meta-fields) will have
environment variable HEXDROID_CI_AOSP_LUNCH_TARGET set with the intended target (e.g.,
aosp_cf_x86_64_phone-userdebug).