No description
  • Shell 72.5%
  • Dockerfile 27.5%
Find a file
Brax Technologies 939720dc34 BaseOS build environment for the BraX3 (MT6835)
Squashed 2 commits:
  BaseOS build environment for the BraX3 (MT6835)
  Move project paths to Brax3_BaseOs namespace
2026-08-19 14:55:48 +03:00
.env.example BaseOS build environment for the BraX3 (MT6835) 2026-08-19 14:55:48 +03:00
.gitattributes BaseOS build environment for the BraX3 (MT6835) 2026-08-19 14:55:48 +03:00
.gitignore BaseOS build environment for the BraX3 (MT6835) 2026-08-19 14:55:48 +03:00
build.sh BaseOS build environment for the BraX3 (MT6835) 2026-08-19 14:55:48 +03:00
docker-compose.yml BaseOS build environment for the BraX3 (MT6835) 2026-08-19 14:55:48 +03:00
docker-entrypoint.sh BaseOS build environment for the BraX3 (MT6835) 2026-08-19 14:55:48 +03:00
Dockerfile BaseOS build environment for the BraX3 (MT6835) 2026-08-19 14:55:48 +03:00
LICENSE BaseOS build environment for the BraX3 (MT6835) 2026-08-19 14:55:48 +03:00
README.md BaseOS build environment for the BraX3 (MT6835) 2026-08-19 14:55:48 +03:00
sync.sh BaseOS build environment for the BraX3 (MT6835) 2026-08-19 14:55:48 +03:00

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
Dockerdocker 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

Branch note. This is the baseos-1.0 builder. The android-14 branch 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.

SoftwareDocker 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 repo or 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.bin and preloader are 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.