Open-source project
MisterZtr/LineageOS_gsi avatar
MisterZtr/LineageOS_gsi

LineageOS_gsi: assembling a Treble-Droid system image from patches

Script and patches for building Treble-Droid based LineageOS GSI

560 stars59 forksShellLicense varies

At a glance

What is it?
MisterZtr/LineageOS_gsi is a shell script and a patch set for building an unofficial LineageOS 23.2 generic system image on Treble enabled devices. It wraps the standard Android source workflow, layers patches on top, and leaves the heavy lifting of Treble support to the wider community.
Who is it for?
This project suits a developer who already has an Android source tree in mind, a Treble enabled phone and patience for a multi hour compile, and it does not suit someone looking for a downloadable custom ROM or a supported daily driver.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 152 days ago.
What is it written in?
Mainly Shell, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A patch set rather than a prebuilt ROM

The repository is not a distribution channel. Its description is short and precise: script and patches for building Treble-Droid based LineageOS GSI. The top level of the project contains only a documentation file, a Russian translation of it, and a patches directory. There is no image to download, no updater zip, and no automated release pipeline that produces a flashable file for the end user.

What it is instead is the missing layer between the official LineageOS source tree and a device that boots a generic system image. Generic system images work only on devices that ship a Treble launchable partition, and getting one to run on a specific phone usually means patching the build configuration, the device overlay and assorted framework details. Those patches live in the patches directory of this repository, and a single script applies them.

The consequence for an adopter is important. You are not consuming a finished artifact, you are consuming a build recipe that has to be combined with the upstream LineageOS tree at the right moment. The version branch is lineage-23.2, which matches the LineageOS 23.2 release series, and the project describes the result as an unofficial build. The README also carries a Russian version, README-RU.md, which suggests the maintainer expects a mixed international audience.

Because the repository holds patches and one script, everything interesting about it lives in how those patches interact with upstream. That is where the risk sits, and it is where this review concentrates.

The local manifest is what pulls Treble dependencies in

The build starts from a plain LineageOS source checkout, which the build guide sets up with the standard repo tool. First you create a working directory and enter it.

bash
mkdir LineageOS
cd LineageOS

Then repo is pointed at the LineageOS source repository on the 23.2 branch, with Git LFS enabled.

bash
repo init -u https://github.com/LineageOS/android.git -b lineage-23.2 --git-lfs

The second ingredient is a second repository. The project guide describes this step as cloning the manifest that adds the necessary dependencies for a GSI, and it targets the maintainer's own treble_manifest repository, placed into the .repo/local_manifests directory on the lineage-23.2 branch. That location matters. repo reads every manifest it finds there, so dropping a file into .repo/local_manifests is the supported way to inject extra projects and remotes into an existing checkout without editing the upstream manifest.

In other words, the GSI support is not carried by this repository's patches alone. Part of it arrives as additional source projects declared in a companion manifest, and the two have to be kept in step. Anyone who wants to see the exact list of added dependencies should read treble_manifest directly, because the build guide does not enumerate it.

The build guide also expects you to already know Git and repo, and it points at a wiki page on how to build a GSI for the general procedure. Those prerequisites are stated rather than taught, which is a fair signal about the audience: people comfortable in a large source tree already.

Syncing first, patching second

Once the manifest is in place, the source is brought down with a forced, parallel sync.

bash
repo sync --force-sync --optimized-fetch --no-tags --no-clone-bundle --prune -j4

The flags are worth reading rather than copying blindly. A forced sync discards local modifications to tracked projects, which matters here because the patch step comes afterwards and the two orders conflict if you mix them up. No tags and no clone bundle trim the download, and a pruned sync removes projects that are no longer referenced. The parallelism is set to four, a deliberately modest number.

After the sync, the patches are applied. The guide gives one command for this, and it expects to be run from the parent of the LineageOS directory, since the path it invokes starts with the LineageOS_gsi directory name.

bash
bash LineageOS_gsi/patches/apply-patches.sh .

The trailing dot is the target directory for the patch application, and the script name says what it does. There is no per patch selection and no interactive mode described.

The order is therefore fixed and worth internalising. Sync first, patch second, and never re sync without expecting to re apply. The forced sync in the command above is also why the workflow is safe to repeat after a failure in the patch stage: you throw away the tree state, resync, and apply the patch set again from a known clean point.

The troubleshooting note is one line long: if you hit conflicts while applying the patches, apply the patch manually. That is an honest admission that conflict resolution is a manual, per patch task, and it is the first thing a new user is most likely to encounter when upstream sources have moved on.

Building the image, with ccache carrying the rebuild cost

Compilation requires Java 17 as the default, according to the build guide, which links to an Arch Linux page on managing installed Java environments. That step matters for a specific reason: the build guide notes that treble_app is now used from the compiled version, so a missing or mismatched JDK produces a failure rather than a warning in an unrelated part of the tree.

For repeated builds the build guide suggests ccache settings, and it is specific about where to put them.

bash
export USE_CCACHE=1
export CCACHE_COMPRESS=1
export CCACHE_MAXSIZE=50G # 50 GB

These lines are meant for your shell profile, so they persist across sessions. The effect of the first two is to turn ccache on and to compress what it stores, and the third caps the cache at 50 GB. A 50 GB ceiling on a cache is a deliberate trade, since a full ccache stops accepting new entries and the benefit of caching goes away exactly when a large rebuild is under way. The comment on that line is worth keeping in mind when the disk fills.

The build itself is the familiar Android sequence. The environment script is sourced, the ccache is sized and reset to zero file size limit, a breakfast target is chosen, and the system image is made with one job per logical core.

bash
. build/envsetup.sh
ccache -M 50G -F 0
breakfast lineage_arm64_bvNE-bp4a-userdebug
make systemimage -j$(nproc --all)

The product name encodes the configuration. The lineage_arm64 part is the architecture, the middle token is the variant, bp4a is the board generation, and userdebug is the build type. Each of the four target names in the build guide differs only in that middle token, which is where the real choices live.

erofs, ext4, GApps and vanilla are four separate builds

The build guide lists four build targets, and the differences are the whole decision. Two are VANILLA builds with erofs and with ext4, and two are GAPPS builds with the same filesystem split. The VANILLA erofs target is lineage_arm64_bvNE-bp4a-userdebug, the VANILLA ext4 target is lineage_arm64_bvN4-bp4a-userdebug, the GAPPS erofs target is lineage_arm64_bgNE-bp4a-userdebug, and the GAPPS ext4 target is lineage_arm64_bgN4-bp4a-userdebug. Each one is followed by the same make systemimage line with parallelism from nproc.

Two axes, then. The g in bgNE and bgN4 marks the GApps flavour, which ships Google applications, and the absence of it marks the vanilla flavour without them. The E in the erofs names and the 4 in the ext4 names select the image filesystem. erofs is the newer read only filesystem used for system partitions, while ext4 is the older writable one.

The ext4 build is the safer first attempt on a device you care about, because it is what most existing recovery tooling and GSI flashing instructions expect. The erofs build is worth trying once you have a working flow, since it is the direction the Android project has been moving for system images.

The GApps choice is more consequential than the filesystem one. A vanilla image gives you no Play services, so apps that depend on them will not run, which is fine for a minimal, de-Googled device and useless for most daily use. Choosing a GApps build also means accepting a bundle of third party applications whose licences and update behaviour are outside the scope of this repository.

The bp4a suffix deserves a note as well. It identifies a specific board generation, so if your phone is not on that generation, the build you get is not a guaranteed match, and the build guide does not document how the suffix is chosen for other boards.

Compressing the system image with 7-zip

After the build, the build guide covers compression and points at 7-zip for a fast and safe way to do it. The output location named in the instructions is the product directory, and the command is a straight archive of the system image.

bash
cd out/target/product/tdgsi_arm64_ab
7z a system.img.xz "system.img"

The product directory name tdgsi_arm64_ab is another fixed string in the workflow, and the archive is created alongside the image it compresses. This is the point where the project hands off to the flashing step, and the flashing step itself lives outside this repository.

Two observations. First, this only compresses the system image. A GSI also involves boot, vendor and other partitions, and the build guide does not describe producing or packaging them, so anyone planning to flash needs to work that out separately. Second, the build guide recommends 7-zip specifically and links to an Arch User Repository package, so the workflow is written from an Arch Linux workstation, which is also the platform referenced for the Java 17 setup guidance.

The project is therefore a source building recipe with an Arch Linux flavour of tooling, aimed at someone who can already handle repo, manifests and patch conflicts.

What breaks, and when this is the wrong tool

The most likely failure is patch conflict. The documentation treats it as a known case rather than a solved problem, and the fix is manual application, patch by patch, against a source tree that has moved since the patch was written. The default branch is lineage-23.2 and the last push was on 2026-05-24, with tagged releases v2026.05.24-lineage23.2, v2026.05.07-lineage23.2 and v2026.05.04-lineage23.2. Upstream LineageOS sources on a branch do not stand still, and a patch set from May applied to a tree that has been rebased since then is exactly where a conflict shows up.

The second failure mode is hardware mismatch. A GSI only runs on a device that provides a Treble launchable system image partition, and the bp4a board generation embedded in the target names is a fixed assumption, not a runtime detection.

The third is resource cost. A full Android system image build, a multi gigabyte source download, and a ccache sized at 50 GB are all non trivial on a laptop. The parallelism of the sync is set to four in the given command, which is a reminder of the scale involved.

There is also a licensing gap worth stating plainly. The repository's license field is listed as unknown, while the software it patches and assembles is LineageOS, which carries its own licensing terms. Patches distributed without a clear license grant give you weaker rights to modify and redistribute the result than you would expect, and the credits section, which lists the LineageOS team, Phhusson, AndyYan, Ponces, Peter Cai, Iceows, ChonDoit, Nazim N, Ahnet, mytja, cawilliamson and Doze-off, shows how much of the underlying work belongs to other people.

This is the wrong tool if you want a supported phone, a daily driver with warranty, or an image you can install without a toolchain. It is the right tool if you want a Treble phone running LineageOS 23.2 with your own build configuration, and you are prepared to resolve patch conflicts when the sources shift.

Editorial conclusion

This project suits a developer who already has an Android source tree in mind, a Treble enabled phone and patience for a multi hour compile, and it does not suit someone looking for a downloadable custom ROM or a supported daily driver. Before you start, confirm that your device ships with a Treble launchable system image partition, read the patch conflict notes, and check that the patch set still applies cleanly to the current lineage-23.2 sources, since the last push was on 2026-05-24 and the branch is expected to move.

Frequently asked questions

What is MisterZtr/LineageOS_gsi?

It is a set of patches and an apply script for building an unofficial LineageOS 23.2 generic system image for Treble enabled devices. The repository holds a README, a Russian translation of it, and a patches directory.

How do I build the LineageOS GSI from this repository?

You run repo init against the LineageOS tree on lineage-23.2 with --git-lfs, clone the maintainer's treble_manifest into .repo/local_manifests, run a forced repo sync, then apply the patches with the apply-patches.sh script before building the system image.

What is the difference between the erofs, ext4, GApps and vanilla builds?

Two independent choices are encoded in the target names. The g in bgNE and bgN4 marks a GApps build with Google applications, the E suffix marks an erofs system image, and the 4 suffix marks an ext4 one.

What should I do if the patches fail to apply?

The README states that you should apply the patch manually when you face conflicts. The last push was on 2026-05-24, so conflicts are likely if the lineage-23.2 sources have changed since then.

Which devices can run a system image built from this project?

Only devices that provide a Treble launchable system image partition, since the project targets Treble-Droid based hardware. The build targets also hardcode the bp4a board generation.

Official sources

  1. Issues
  2. MisterZtr/LineageOS_gsi on GitHub
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/misterztr-lineageos-gsi.svg)](https://hysenlabs.com/projects/misterztr-lineageos-gsi)

Was this useful?