- Shell 72.5%
- Dockerfile 27.5%
Squashed 2 commits: BaseOS build environment for the BraX3 (MT6835) Move project paths to Brax3_BaseOs namespace |
||
|---|---|---|
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| build.sh | ||
| docker-compose.yml | ||
| docker-entrypoint.sh | ||
| Dockerfile | ||
| LICENSE | ||
| README.md | ||
| sync.sh | ||
BaseOS build environment
Build tooling for BaseOS on the BraX3 (MediaTek MT6835 / Dimensity 6300),
tree baseos-1.0 (AOSP android-16.0.0_r4), by Brax Technologies PBC.
Two supported paths, both running the same build.sh:
| Path | Use when |
|---|---|
Docker — docker compose up |
CI, or a host whose distribution is not a supported AOSP host |
Host — ./build.sh |
the host already has the dependencies |
New to this project? Start with the manifest repository, which explains the tree itself.
Contents
- Quick start
- Requirements
- 1. Get the source
- 2a. Build with Docker
- 2b. Build on the host
- Configuration
- Output
- Signing
- Troubleshooting
- Licensing
Branch note. This is the
baseos-1.0builder. Theandroid-14branch of this repository holds a different, incompatible builder for the MediaTek ALPS tree (alps/+vendor_t/,kernel-5.15,pri_build_project), pinned to Ubuntu 20.04 for ALPS prebuilt host tools. Neither works on the other's tree.
Quick start
mkdir Brax3_BaseOs && cd Brax3_BaseOs
git clone https://review.os-source.co/Brax3_BaseOs/build docker
./docker/sync.sh
cd docker
cp .env.example .env
sed -i "s|^BSP_DIR=.*|BSP_DIR=$(cd .. && pwd)|; \
s|^BUILD_UID=.*|BUILD_UID=$(id -u)|; \
s|^BUILD_GID=.*|BUILD_GID=$(id -g)|" .env
docker compose up -d --build
docker logs -f baseos_build_brax3
Requirements
Hardware — 16+ cores and 64 GB RAM recommended; roughly 250 GB free for
out/ on top of ~120 GB of source. An SSD makes a large difference.
Software — Docker for the container path, or a
supported AOSP 16 host (Ubuntu 22.04+ / Debian 12+) for the host path. Both need
git, git-lfs and the repo tool.
1. Get the source
mkdir -p ~/bin && export PATH=~/bin:$PATH
curl -fsSL https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
mkdir Brax3_BaseOs && cd Brax3_BaseOs
git clone https://review.os-source.co/Brax3_BaseOs/build docker
./docker/sync.sh
sync.sh runs repo init, repo sync, and the Git LFS resolve step.
Do not run
repoor the build as root. A root-owned tree cannot afterwards be synced or built by a normal user. Both scripts refuse to start as root; see Troubleshooting if you need to override that in CI.
Git LFS is mandatory
repo sync fetches git objects but never runs the Git LFS smudge filter, so
LFS-backed files land as ~130-byte pointer stubs. The WebView prebuilts
(external/chromium-webview/prebuilt/{arm,arm64,x86,x86_64}/webview.apk) are
LFS-backed. Left unresolved, the build compiles for ~1h45m and then fails at
86%:
external/chromium-webview/prebuilt/arm64/webview.apk: error: failed opening zip: Invalid file.
sync.sh handles this and verifies the result. To repair an existing tree:
./docker/sync.sh --lfs-only
# equivalently:
repo forall -c 'git lfs ls-files -n >/dev/null 2>&1 && git lfs pull'
A healthy arm64 APK is ~247 MB and reports Android package (APK); a stub is
ASCII text beginning version https://git-lfs.github.com/spec/v1. build.sh
refuses to start while any stub remains, so this fails in seconds rather than
hours.
2a. Build with Docker
cd docker
cp .env.example .env
sed -i "s|^BSP_DIR=.*|BSP_DIR=$(cd .. && pwd)|; \
s|^BUILD_UID=.*|BUILD_UID=$(id -u)|; \
s|^BUILD_GID=.*|BUILD_GID=$(id -g)|" .env
docker compose up -d --build
docker logs -f baseos_build_brax3
The container runs as your uid:gid, and the tree is mounted at the same
absolute path it has on the host. AOSP embeds absolute paths in out/ and in
ccache entries, so this is what lets you alternate between the Docker and host
paths without invalidating everything.
2b. Build on the host
cd Brax3_BaseOs
./docker/build.sh
Same script, same defaults, same build.log. The AOSP toolchain is hermetic —
clang, the JDK and python all come from prebuilts/ — so a current Ubuntu or
Debian with git-lfs installed is generally enough.
Configuration
Both paths read the same variables, via .env for Docker or the environment for
the host path:
| Variable | Default | Meaning |
|---|---|---|
BSP_DIR |
tree containing the script | Source root |
LUNCH_PRODUCT |
baseos_brax3 |
Product |
LUNCH_RELEASE |
bp4a |
Release config |
BUILD_VARIANT |
userdebug |
user / userdebug / eng |
BUILD_TARGET |
droid |
Make goals |
BUILD_THREADS |
nproc |
Parallelism |
CCACHE_DIR |
$BSP_DIR/.ccache |
ccache location |
Build the flashable set instead of a plain droid:
BUILD_TARGET="superimage otapackage updatepackage target-files-package" ./docker/build.sh
Output
Artifacts land in out/target/product/brax3/:
| Artifact | Goal | Notes |
|---|---|---|
Partition images (system, vendor, boot, …) |
droid |
|
super.img |
superimage |
All dynamic partitions |
baseos_brax3-img.zip |
updatepackage |
fastboot update <zip> |
baseos_brax3-ota.zip |
otapackage |
A/B OTA, recovery sideload |
baseos_brax3-target_files.zip |
target-files-package |
Signing, incremental OTAs |
Flash with:
fastboot update out/target/product/brax3/baseos_brax3-img.zip
SP Flash Tool packages cannot be produced from this tree. The scatter file,
MTK_AllInOne_DA.binandpreloaderare MediaTek artifacts carried by the ALPS BSP and are not present here. Take those three from an existing BraX3 factory image and combine them with the images built here.
Signing
Builds from this tree are signed with the AOSP testkey and are
engineering-only. A testkey-signed build must not be distributed to users:
the corresponding private key is public, so anyone can sign an update that such
a device would accept.
For a release build, run sign_target_files_apks against the target-files zip
with your own production keys, and keep those keys outside the source tree —
never in a device or vendor repository, whose history is permanent and easily
published by accident.
Troubleshooting
ERROR: refusing to build as root
Intended. Build as a normal user; for Docker, set BUILD_UID / BUILD_GID in
.env.
If your CI runner genuinely executes as uid 0, set ALLOW_ROOT_BUILD=1 and the
guard downgrades to a warning:
ALLOW_ROOT_BUILD=1 # in .env, or exported for ./build.sh
Know what that opts you into: out/, .ccache and any .repo metadata the run
touches become root-owned, so a non-root user cannot subsequently sync or build
that tree without sudo chown -R. Keep the tree consistently root-owned or
consistently not — mixing the two is what breaks.
ERROR: ... is an unresolved Git LFS pointer
Run ./docker/sync.sh --lfs-only.
ERROR: <dir> is not writable
The container uid does not match the tree owner. Compare BUILD_UID /
BUILD_GID against stat -c '%u:%g' $BSP_DIR. If the tree was ever synced as
root:
sudo chown -R "$(id -u):$(id -g)" "$BSP_DIR"
Connection refused on port 29418 during sync
Gerrit restarted. sync.sh passes --retry-fetches=3; re-run it.
Everything rebuilds after switching between Docker and host
BSP_DIR does not match the path the previous build used. Both paths must see
the tree at the same absolute location.
Licensing
Apache License 2.0 — see LICENSE.
The tree this builds contains GPL-2.0 components, chiefly the Linux kernel and the out-of-tree kernel modules; their corresponding source is published. See the manifest repository.
© Brax Technologies PBC.