Skip to content

Instantly share code, notes, and snippets.

@themagicalmammal
Last active February 23, 2026 12:02
Show Gist options
  • Select an option

  • Save themagicalmammal/3fd4e91a0063241f330f2ff402d2ea83 to your computer and use it in GitHub Desktop.

Select an option

Save themagicalmammal/3fd4e91a0063241f330f2ff402d2ea83 to your computer and use it in GitHub Desktop.

Building LineageOS from Source

A Precise, Beginner-Friendly Reference for LineageOS 23.1 and LineageOS based ROMs

Target Device: OnePlus 7 · Codename: guacamoleb · SoC: Snapdragon 855 (SM8150)


Before You Begin

What You're Actually Doing

Android is built from a massive collection of git repositories — thousands of them — managed by a tool called repo. You'll pull all that source code to your machine, drop in device-specific code (device tree, kernel, vendor blobs), then compile the entire OS from scratch. The result is a flashable .zip image.

This takes real hardware. Don't attempt it on anything under-spec'd.

System Requirements

Resource Minimum Recommended
OS Ubuntu 20.04 LTS Ubuntu 22.04 LTS
CPU 8-core 16-core or more
RAM 16 GB 32 GB+
Disk (SSD strongly preferred) 300 GB free 500 GB+ free
Internet Stable broadband High-speed (initial sync is ~80–100 GB)

Why SSD? Android builds perform thousands of small file reads and writes. A spinning hard drive will make your build take 3–5× longer and risks timeouts during repo sync.

Conventions Used Here

  • ~/android — your source tree root (all ROM source lives here)
  • ~/bin — where standalone tools like repo are stored
  • CODENAME — always refers to guacamoleb in this guide
  • Commands are meant to be run as your regular user unless sudo is explicitly shown

Step 1 — Install Build Dependencies

Android's build system expects a specific set of tools to be present. Install them all at once.

sudo apt update && sudo apt upgrade -y
sudo apt install -y \
  git git-core gnupg flex bison \
  build-essential zip curl rsync \
  zlib1g-dev gcc-multilib g++-multilib \
  libc6-dev-i386 libncurses-dev libncurses5-dev libncursesw5-dev \
  lib32z1 lib32stdc++6 libssl-dev liblz4-tool \
  bc libxml2-utils xsltproc unzip fontconfig \
  python3 python3-pip python3-venv python-is-python3 \
  ccache lzop schedtool openssl \
  clang lld lldb axel jq \
  android-sdk-libsparse-utils

Akhil Narang's setup script handles additional environment configuration that the above misses. Run it:

cd ~/
git clone https://github.com/akhilnarang/scripts
cd scripts
./setup/android_build_env.sh

Install Java 17

LineageOS 23.1 (and anything based on it) requires exactly OpenJDK 17. Other versions will cause build failures.

sudo apt install -y openjdk-17-jdk

Add Java to your environment permanently by appending to ~/.profile:

echo 'export JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64"' >> ~/.profile
echo 'export PATH="$JAVA_HOME/bin:$PATH"' >> ~/.profile
source ~/.profile

Verify the correct version is active:

java -version
# Expected output: openjdk version "17.x.x" ...

If you see a different version, you may have multiple JDKs installed. Set the correct one with sudo update-alternatives --config java.


Step 2 — Create Your Working Directories

mkdir -p ~/bin
mkdir -p ~/android

~/bin is where the repo binary lives. ~/android is your source root — everything lives under here. Keep both paths consistent; the rest of this guide assumes them.


Step 3 — Install the repo Tool

repo is a Python wrapper around git that manages the hundreds of individual repositories that make up Android. Google hosts the canonical version.

curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo

Make sure ~/bin is in your PATH. Add this to ~/.profile if it isn't already:

echo 'export PATH="$HOME/bin:$PATH"' >> ~/.profile
source ~/.profile

Confirm it's working:

repo --version

Step 4 — Configure Git Identity

repo communicates with remote git servers and requires you to have a name and email set. These don't need to match any real account — they're just used for commit metadata.

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

Step 5 — Initialize and Sync the Source Tree

Navigate into your working directory and initialize the repo manifest. This tells repo which project to pull and from which branch.

cd ~/android
repo init -u https://github.com/LineageOS/android.git -b lineage-23.1 --git-lfs

What is --git-lfs? Git LFS (Large File Storage) is used for large binary files like prebuilts. This flag ensures they're fetched correctly. If your system doesn't have git-lfs installed, run sudo apt install git-lfs first.

Now sync the source. This downloads everything — expect it to take 1–4 hours depending on your connection:

repo sync -c -j$(nproc --all) --force-sync --no-clone-bundle --no-tags

Flag breakdown:

Flag Effect
-c Only sync the currently checked-out branch, not all branches
-j$(nproc --all) Use all available CPU threads for parallel downloads
--force-sync Overwrites local changes if repos are out of sync
--no-clone-bundle Skips bundle files, which can cause sync failures
--no-tags Doesn't download git tags — saves time and space

If the sync fails partway through (common on slower connections), just re-run the same command. It will resume where it left off.


Step 6 — Clone Device-Specific Repositories

The ROM source you just synced is device-agnostic. To build for a specific phone, you need to add hardware-specific code. All of these repositories are cloned inside your ~/android source root into specific paths — the build system expects them at exact locations.

cd ~/android

Device Trees

These contain build configuration, BoardConfig, and makefile rules specific to your device.

# Device-specific tree for the OnePlus 7 (guacamoleb)
git clone https://github.com/LineageOS/android_device_oneplus_guacamoleb \
  -b lineage-23.1 device/oneplus/guacamoleb

# Common tree shared by all OnePlus SM8150 devices
git clone https://github.com/LineageOS/android_device_oneplus_sm8150-common \
  -b lineage-23.1 device/oneplus/sm8150-common

Kernel Source

The Linux kernel for the Snapdragon 855 (SM8150) platform. This is compiled from source during the build — no prebuilt kernel is used.

git clone https://github.com/LineageOS/android_kernel_oneplus_sm8150 \
  -b lineage-23.1 kernel/oneplus/sm8150

Vendor Blobs

These are proprietary binaries — Wi-Fi firmware, camera HAL, DSP blobs, etc. — that cannot be open-sourced. They're provided by TheMuppets, who extract them from official OEM firmware.

# Device-specific vendor blobs
git clone https://github.com/TheMuppets/proprietary_vendor_oneplus_guacamoleb \
  -b lineage-23.1 vendor/oneplus/guacamoleb

# Platform-level vendor blobs shared across SM8150 devices
git clone https://github.com/TheMuppets/proprietary_vendor_oneplus_sm8150-common \
  -b lineage-23.1 vendor/oneplus/sm8150-common

Hardware Abstraction Layer (HAL)

OnePlus devices use a shared hardware module for display, touch, and other subsystems not covered by the common Qualcomm HAL.

git clone https://github.com/LineageOS/android_hardware_oplus \
  -b lineage-23.1 hardware/oplus

Step 7 — Set Up ccache

ccache is a compiler cache. On your second and subsequent builds, it can cut build time by 50–70% by reusing previously compiled objects. Set it up before your first build so it starts warming on the very first run.

export USE_CCACHE=1
export CCACHE_EXEC=/usr/bin/ccache
ccache -M 50G

To make these persistent across terminal sessions, add them to ~/.profile:

echo 'export USE_CCACHE=1' >> ~/.profile
echo 'export CCACHE_EXEC=/usr/bin/ccache' >> ~/.profile
source ~/.profile

50 GB is a reasonable cache size for a single device. If you're building for multiple devices, consider increasing it to 100 GB. ccache uses space lazily — it won't allocate 50 GB immediately, only as the cache fills.

Check your cache statistics at any time:

ccache -s

Step 8 — Build the ROM

First Build

cd ~/android
source build/envsetup.sh
breakfast guacamoleb
croot
brunch guacamoleb | tee log.txt

What each command does:

Command Purpose
source build/envsetup.sh Loads Android build functions (lunch, brunch, croot, etc.) into your shell
breakfast guacamoleb Configures the build environment for your specific device (calls lunch under the hood)
croot Changes directory to the root of your source tree — important if you've navigated elsewhere
brunch guacamoleb Runs the full build: compiles everything and assembles the flashable zip
` tee log.txt`

Your first build will take anywhere from 1 to 5 hours depending on your hardware. This is normal.

Subsequent Builds

After the first build, you don't need to set ccache again:

source build/envsetup.sh
breakfast guacamoleb
croot
brunch guacamoleb | tee log.txt

With a warm ccache, subsequent builds typically complete in 20–60 minutes.

Finding Your Output

The built ROM will be in:

~/android/out/target/product/guacamoleb/

Look for a file named something like lineage-*.zip. That's your flashable image.


Step 9 — Keeping Your Tree Updated

To pull in the latest upstream changes from LineageOS:

cd ~/android
repo sync -c -j$(nproc --all) --force-sync --no-clone-bundle --no-tags

After syncing, you'll usually want to do a dirty build rather than a full clean build:

source build/envsetup.sh
breakfast guacamoleb
croot
make installclean
brunch guacamoleb | tee log.txt

Only run make clobber if you suspect something is fundamentally broken, or after major tree-level changes (like a branch switch or major component update). A full clean build throws away all cached work.


Cleaning Reference

Command What it removes When to use it
make installclean Installed files only; keeps compiled objects After most updates — faster rebuild
make clobber Everything in out/ After major changes, branch switches, or mysterious failures
ccache -C All ccache entries Only if you suspect cache corruption

Troubleshooting

Out of Memory During Build

Android build jobs run in parallel and can exhaust RAM. Add a swap file:

sudo fallocate -l 32G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

To make it permanent across reboots, add this line to /etc/fstab:

/swapfile none swap sw 0 0

You can also reduce parallelism. By default brunch uses all cores. Override it:

make -j4 bacon

repo sync Fails

Network interruptions are common during a large sync. Simply re-run the sync command — it picks up where it left off. If a specific repository is consistently failing, try with fewer threads:

repo sync -c -j4 --force-sync --no-clone-bundle --no-tags

Wrong Java Version

The build will fail with cryptic errors if the JDK isn't 17. Check what's active:

java -version
update-java-alternatives --list

Switch if needed:

sudo update-alternatives --config java
# Select the entry for java-17-openjdk

Missing python Binary

Some build scripts call python (Python 2 style). The python-is-python3 package you installed handles this, but verify:

python --version
# Should report Python 3.x.x

Build Fails with Ninja Error

Look at the last few lines of log.txt — Ninja errors typically point to the real failure above them. Search for FAILED: in the log:

grep -n "FAILED:" log.txt | tail -20

Then look at the lines around the first FAILED: entry for the actual error.

Device Not Found by adb / fastboot

adb devices
fastboot devices

If nothing shows:

  • Ensure USB Debugging is enabled on the phone (Settings → Developer Options → USB Debugging)
  • Accept the RSA key prompt on your phone if one appears
  • Try a different cable (use a data cable, not a charge-only cable)
  • Try a different USB port (USB 2.0 ports can sometimes work better than USB 3.0 for older devices)
  • Run lsusb to confirm the OS sees the device at all

Understanding the Repository Structure

After everything is in place, your source tree should look roughly like this:

~/android/
├── art/                    # Android Runtime (ART)
├── bionic/                 # C library, math, and dynamic linker
├── build/                  # Build system (Soong, Make)
├── device/
│   └── oneplus/
│       ├── guacamoleb/     # Device tree (your clone)
│       └── sm8150-common/  # Platform-common device tree (your clone)
├── frameworks/             # Android framework (Java APIs)
├── hardware/
│   └── oplus/              # Hardware abstraction (your clone)
├── kernel/
│   └── oneplus/
│       └── sm8150/         # Kernel source (your clone)
├── out/                    # Build output (generated during build)
├── packages/               # System apps
├── vendor/
│   └── oneplus/
│       ├── guacamoleb/     # Device vendor blobs (your clone)
│       └── sm8150-common/  # Platform vendor blobs (your clone)
└── ...

The build system ingests all of this and produces a single flashable image. The device tree is the glue that tells the build system which kernel, which blobs, and which feature flags to use.


Tips for Long-Term Maintenance

  • Use repo sync regularly. LineageOS is actively developed. Weekly syncs keep you current.
  • Don't edit files in the source tree directly unless you intend to maintain a patch. Changes will be overwritten on the next sync. Use proper Android patch management (topic branches + repo upload) if you want to contribute upstream.
  • Monitor your disk. The out/ directory grows with every build. make clobber reclaims it when needed.
  • Save your log.txt files. When asking for help in forums or Telegram groups, a build log is essential context. The LineageOS Telegram and XDA thread for guacamoleb are good resources.
  • Check the LineageOS wiki for guacamoleb — device-specific guidance there applies here too.

Credits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment