Skip to content

Setup Build Server

This guide gets a shared Linux machine ready to build Android Automotive images for the NXP i.MX8 QuadMax MEK.

This machine is treated as a build server, not the day-to-day development workstation.

Use the build server to:

  1. Store the large NXP source tree and release bundles.
  2. Build Android images and related artifacts.
  3. Publish those artifacts somewhere the team can retrieve them.

Use your laptop to:

  1. Flash hardware with adb, fastboot, or uuu as needed.
  2. Deploy app changes.
  3. Capture logs and debug the target device.

This guide focuses on the build-server side:

  1. Prepare the host machine.
  2. Copy the shared justfile onto the server.
  3. Download the NXP release package.
  4. Sync and build the source tree.
  5. Store the resulting artifacts in a predictable shared location.

This workflow assumes a dedicated build server with:

  • Ubuntu 24.04
  • 4 CPU cores
  • 32 GB RAM
  • 32 GB or more of swap configured
  • 450 GB of free disk space before the source bundle is extracted
  • Docker installed and usable by the build users

Make sure you have access to:

  • The NXP Android Automotive BSP for your target release
  • Credentials or portal access required to download NXP release artifacts
  • A shared location or convention for publishing completed build outputs

Install the tools required to run the shared build workflow:

Terminal window
sudo apt update
sudo apt install -y \
git \
curl \
unzip \
just

Install Docker separately using the official Install Docker Engine on Ubuntu instructions.

Add your user to the Docker group if needed:

Terminal window
sudo usermod -aG docker "$USER"
newgrp docker

Android Automotive builds can exhaust memory during Soong bootstrap even when the main build runs with -j2. On a 32 GB build server, configure at least 32 GB of swap before running the first full build.

One straightforward Ubuntu setup is a swapfile:

Terminal window
sudo fallocate -l 32G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Verify that swap is active:

Terminal window
swapon --show
free -h

If this machine is shared or you continue to see build processes get killed, raise the swap size further or move the build to a host with more RAM.

Terminal window
sudo groupadd --system android-build
sudo usermod -aG android-build "$USER"
sudo mkdir -p /srv/android-automotive
sudo chgrp -R android-build /srv/android-automotive
sudo chmod -R 2775 /srv/android-automotive
cd /srv/android-automotive

Add any future build-server users to the android-build group as well so they can work in the shared workspace.

This directory will hold downloaded release archives, the extracted source tree, and generated build artifacts.

After running sudo usermod -aG android-build "$USER", start a fresh shell in the new group before continuing. The simplest option is:

Terminal window
newgrp android-build

Before moving on, verify that this shell can write to the shared workspace:

Terminal window
touch /srv/android-automotive/test.txt
rm /srv/android-automotive/test.txt

If touch fails, run newgrp android-build again and repeat the check before running any just recipes inside /srv/android-automotive.

This repo includes a dedicated build-server justfile here.

Run these recipes from the repo root on your laptop to copy the build-server recipes, shared timing helper, and MRS build-image definition onto the build server:

Terminal window
just push-build-server-file user@host docs/public/build-server/justfile
just push-build-server-file user@host docs/public/build-server/build-time.sh
just push-build-server-file user@host docs/public/build-server/Dockerfile.android-build

Those recipes copy all three files into /srv/android-automotive/ on the build server.

The intended usage on the build server is:

Terminal window
cd /srv/android-automotive
just

This will list the available build server recipes.

From /srv/android-automotive, run the remaining one-time setup recipe:

Terminal window
cd /srv/android-automotive
just install-repo

Download the Android Automotive release package from the NXP Android Automotive software page

Then click the Downloads button.

Find 16.0.0_1.1.0_ANDROID_Automotive_SOURCE, click the Download button, and follow the short form until you have downloaded the .tar.gz file.

You can also download the matching Documentation package and any release notes you want to keep with the build, but the source package above is the key artifact for the build server workflow.

Run this recipe from the repo root on your laptop to copy the source bundle onto the build server:

Terminal window
just push-build-server-file user@host /path/to/imx-automotive-16.0.0_1.1.0.tar.gz

After copying the source bundle to the build server, your workspace should look like this:

/srv/android-automotive/
├── justfile
└── imx-automotive-16.0.0_1.1.0.tar.gz

Then extract it on the build server:

Terminal window
cd /srv/android-automotive
just extract-bsp

After extraction, you should have a source tree at:

/srv/android-automotive/imx-automotive-16.0.0_1.1.0

Verify the extracted source directory:

Terminal window
ls -lah /srv/android-automotive/imx-automotive-16.0.0_1.1.0

Configure Git identity for the build user:

Terminal window
git config --global user.name "Your Name"
git config --global user.email "you@example.com"

Then source the setup script included in the release:

Terminal window
cd /srv/android-automotive/imx-automotive-16.0.0_1.1.0
source ./imx_android_setup.sh

This step will take a long time because it performs the initial source fetch and repository setup. Expect it to take at least an hour.

After it completes, the Android source tree used for the build will be under:

/srv/android-automotive/imx-automotive-16.0.0_1.1.0/android_build

This repo includes OS customizations under os/. Push them to the build server before building:

Terminal window
just push-build-server-file user@host manifests/mrs-platform.xml
just push-os-customizations user@host

The first command copies the pinned MRS platform manifest to /srv/android-automotive/. The final command copies only the os/ tree. The MRS-owned mrs_mek_8q, neuralplex, and mrs_cuttlefish products include the appropriate shared MRS OS layer directly.

Run a full source synchronization after initially providing the manifest or when deliberately refreshing the complete NXP/AOSP checkout:

Terminal window
cd /srv/android-automotive
just sync-source

Both synchronization modes install the current manifest first. Full sync-source synchronizes the complete Repo checkout and does not copy local OS customizations. Routine builds run sync-os automatically; it synchronizes only the four manifest-pinned MRS platform projects and copies os/ to device/mrs/. This avoids scanning every repository in the otherwise fixed NXP release tree before each build.

The first synchronization of an existing NXP checkout may require Repo to replace the Git metadata associated with the four downstream project paths. Preserve or verify any local work in those projects, then run this one-time migration from the Android source tree:

Terminal window
repo sync --detach --fail-fast --force-sync \
packages/apps/Car/Launcher \
system/core \
hardware/interfaces \
device/google/cuttlefish

Neither routine sync-os nor full sync-source runs use --force-sync.

If you have not pushed these customizations yet, the MRS-owned products are not available to lunch, so the build fails instead of silently producing a stock NXP image.

First, you need to build the Docker image used for containerized Android Automotive builds. The recipe builds NXP’s Dockerfile unchanged as android-build-nxp, then creates the android-build image from the MRS-owned Dockerfile.android-build. The derived layer installs zip, which AOSP/Soong requires but the NXP image omits. This build takes around 20 minutes.

Terminal window
cd /srv/android-automotive
just build-container

Start the Android Automotive build from /srv/android-automotive:

Terminal window
cd /srv/android-automotive
just build mek_8q

To build Cuttlefish images instead, pass the cuttlefish target:

Terminal window
cd /srv/android-automotive
just build cuttlefish

To build NeuralPlex images, pass the neuralplex target:

Terminal window
cd /srv/android-automotive
just build neuralplex

This recipe starts the build in the background. It does not require you to keep the SSH session open while the build runs.

It also writes a build-time.txt file next to the published artifacts in /srv/android-automotive/releases/imx-automotive-16.0.0_1.1.0/, so the start time, end time, elapsed seconds, and exit status travel with the build output.

The build workflow handles:

  • building the NXP base image without modifying its Dockerfile
  • adding MRS-owned build dependencies in the derived android-build image
  • starting a detached container with that android_build tree mounted at /work/android_src
  • running the selected target lunch, such as mrs_mek_8q-nxp_stable-userdebug, neuralplex-nxp_stable-userdebug, or mrs_cuttlefish-bp2a-eng
  • running the target build command
  • publishing the finished artifacts into /srv/android-automotive/releases/imx-automotive-16.0.0_1.1.0/<target>/

just build-release uses /srv/android-automotive/imx-automotive-16.0.0_1.1.0/android_build/out-release instead of the default out/ tree so it does not reuse or clobber the eng build state.

To check whether the detached container is still running, use docker ps. To inspect the latest build output, use docker logs -f android-automotive-build.

When the build completes, the output images should be under:

/srv/android-automotive/imx-automotive-16.0.0_1.1.0/android_build/out/target/product/mek_8q

When just build finishes successfully, it publishes the release artifacts directly into:

/srv/android-automotive/releases/imx-automotive-16.0.0_1.1.0/<target>

The build timing summary lives alongside those files as /srv/android-automotive/releases/imx-automotive-16.0.0_1.1.0/<target>/build-time.txt.

The directory should be shaped roughly like this:

/srv/android-automotive/releases/imx-automotive-16.0.0_1.1.0/
└── mek_8q/
├── boot.img
├── boot-imx.img
├── init_boot.img
├── vendor_boot.img
├── vendor_boot-debug.img
├── super.img
├── super_empty.img
├── partition-table.img
├── partition-table-13GB.img
├── partition-table-dual.img
├── partition-table-13GB-dual.img
├── dtbo.img
├── dtbo-*.img
├── vbmeta.img
├── vbmeta-*.img
├── u-boot-imx8qm-mek-uuu.imx
└── uuu_imx_android_flash.sh

A Cuttlefish build publishes the host package and image zip under:

/srv/android-automotive/releases/imx-automotive-16.0.0_1.1.0/
└── cuttlefish/
├── build-time.txt
├── cvd-host_package.tar.gz
└── mrs_cuttlefish-img-*.zip

These files are copied from:

  • /srv/android-automotive/imx-automotive-16.0.0_1.1.0/android_build/out/target/product/mek_8q
  • /srv/android-automotive/imx-automotive-16.0.0_1.1.0/android_build/out-release/target/product/mek_8q

If you are iterating on a single system module, see Module-only rebuilds for the app-specific build and adb update flow.

To remove build outputs from the source tree:

Terminal window
cd /srv/android-automotive
just clean-build

To remove published artifacts:

Terminal window
cd /srv/android-automotive
just clean-artifacts

If setup or builds stall, check these first:

  • Not enough free disk space
  • Build host runs out of memory
  • Wrong NXP release bundle or manifest for the target image
  • Workspace created inside one user’s home directory
  • Build tools installed in user-local paths instead of shared system paths
  • Build server does not have the current docs/public/build-server/justfile
  • Docker permissions not configured for the build users

After the build server is producing published images, continue with: