Files
builders_rubenslte/AGENTS.md
T

11 KiB

AGENTS.md — builders_rubenslte

Build drivers + docs for TWRP recovery (recovery.img) and a LineageOS 14.1 ROM for the Samsung Tab Active SM-T365 (rubenslte, Qualcomm MSM8926 / msm8226, Linux kernel 3.4).

Layout

build_twrp.sh       TWRP  -> recovery.img   (omni twrp-5.1)
build_los.sh        LOS   -> boot.img / lineage_rubenslte-*.zip (cm-14.1, Jack)
common.sh           shared: apply_patches (idempotent patch application)
shell.nix           nix-shell FHS env for both builds (nixpkgs 22.11 pinned)
patches/{twrp,kernel,los}   post-sync fixes; kernel/ is shared by both builds
local_manifests/    rubenslte.xml (LOS overlay) + twrp.xml (TWRP overlay)
twrp-build/  los-build/  .ccache/  .jack-repository/   (gitignored workspaces)

Repos

Everything rubenslte lives on gitea, fetched anonymously over https: https://git.cfpi-fpsi.eu/rubenslte.

  • twrp_device_samsung_rubenslte — TWRP device tree, self-contained (own BoardConfig.mk / mkbootimg.mk / dtbtool, no platform imports).
  • android_kernel_samsung_rubenslte — stock msm8226 kernel, built from source, shared by both builds.
  • android_device_samsung_rubenslte — LOS device tree; inherits the shared msm8226-common / qcom-common platform layers (cm-14.1). rubenslte is its own device family, so the former millet-common family layer is gone and the family bits are owned in-tree (rootdir/, init/, liblights/, libshims/, keylayout/, audio/, wifi/).
  • android_vendor_samsung_rubenslte — LOS proprietary blobs.

android_device_samsung_msm8226-common lives on gitea too (cm-14.1) — a mirror of the maintainer fork that produced the matisse family (LineageOS org has no cm-14.1 for it). The two qcom-common platform layers come straight from LineageOS (device/samsung/qcom-common, device/qcom/common, both cm-14.1).

Commands

Both scripts are console-style with getopts; the only flag is -h (usage). Every build runs a full repo sync first, so in-tree edits are always wiped and re-patched — there is no skip-sync mode.

./build_twrp.sh -h            # usage
./build_twrp.sh build         # full build -> recovery.img at repo root
./build_twrp.sh clean         # remove twrp-build/out and recovery.img
./build_twrp.sh prune         # remove all of twrp-build and recovery.img

./build_los.sh bootimage      # build boot.img (kernel + dt.img + ramdisk, fast gate)
./build_los.sh bacon          # full build -> lineage_rubenslte-*.zip
./build_los.sh clean          # mka clean
./build_los.sh prune          # remove all of los-build

Cheap checks without nix: bash -n common.sh build_twrp.sh build_los.sh. Patch check: patch -p1 --dry-run -d <workspace> < patches/<dir>/<file>. Flashing / boot keys: README.md.

How the builds work

  • Env: everything runs inside the nix-shell FHS env (shell.nix). Run nix-shell first, then invoke the scripts — they do not self-re-enter the env anymore. Don't rely on nix-shell --run (the shellHook does exec android-env); don't run two nix-shells at once (nix store deadlock).
  • TWRP sources: repo init of omni twrp-5.1 (platform_manifest_twrp_omni) + local_manifests/twrp.xml copied into .repo/local_manifests/ before repo sync -c -j$(nproc), then apply_patches patches/twrp and apply_patches patches/kernel.
  • LOS sources: repo init of cm-14.1 (LineageOS/android) + local_manifests/rubenslte.xml copied in before repo sync -c -j$(nproc), then apply_patches patches/kernel and apply_patches patches/los. Sync wipes in-tree edits; apply_patches is idempotent so re-applying each full build is harmless.
  • Patches: common.sh::apply_patches dry-runs each patch with LC_ALL=C first. An already-applied patch makes GNU patch (2.8, from the nix env) report Reversed (or previously applied) patch detected on the forward dry run — that output, not the exit code, is what skips it. Warnings print the patch log but don't abort the build.
  • Toolchain (TWRP): arm-eabi-4.8 (gcc 4.8, matches stock) is checked out by repo sync — the omni twrp-5.1 manifest already declares prebuilts/gcc/linux-x86/arm/arm-eabi-4.8 at the default revision refs/tags/android-5.1.1_r28 (aosp remote). It lands at prebuilts/gcc/linux-x86/arm/arm-eabi-4.8 and is put on PATH (the sync fetches it). LOS uses the tree's own prebuilts.
  • Compiler (LOS): Jack only, in-process (JACK_SERVER=false JACK_NO_SERVER=1); the jack/jill jars are seeded into .jack-repository/ from prebuilts/sdk/tools/jacks/ with cp -n.
  • Kernel: built from source via the omni/lineage kernel build rules. The variant defconfig (msm8926-sec_rubenslte_defconfig) enables only CONFIG_MACH_RUBENSLTE_OPEN (EUR); dtbTool packs dt.img for the bootloader.
  • Recovery ramdisk: the stock minigzip ramdisk overflows the 10,485,248 B partition, so mkbootimg.mk drops tzdata + f2fs tools and compresses with LZMA. Result: 10,479,632 B, 19-language TWRP.
  • SEANDROIDENFORCE: build_los.sh appends the trailer to the LOS boot.img (append_seandroidenforce) — required by Samsung bootloaders.

Artifacts: recovery.img (repo root; build_twrp.sh checks it against RECOVERY_BUDGET=10485248 and errors if it exceeds the partition) and los-build/out/target/product/rubenslte/lineage_rubenslte-*.zip.

Invariants — do not "simplify"

  • BoardConfig.mk: INSTALLED_DTIMAGE_TARGET + BOARD_MKBOOTIMG_ARGS stay recursive (=, expanded after PRODUCT_OUT/KERNEL_OUT exist) — never :=.
  • mkbootimg.mk: the dt.img rule depends on INSTALLED_KERNEL_TARGET; the ramdisk must stay LZMA + trimmed or the image overflows the partition.
  • F2FS is off (no kernel driver): never re-add TARGET_USERIMAGES_USE_F2FS. The LOS rootdir/etc/fstab.qcom is EXT4-only and TWRP's mkbootimg strips f2fs tools from the ramdisk.
  • dt.img is EUR-only (CONFIG_MACH_RUBENSLTE_OPEN); other variants (T365Y/T365M) need their CONFIG_MACH_RUBENSLTE_* enabled.
  • SEANDROIDENFORCE trailer + --dt are required for Samsung bootloaders (append_seandroidenforce appends it to LOS boot.img).
  • LOS is Jack-only and the ROM is bare (no GApps, /data ext4).
  • Kernel fixes go in patches/kernel/ and must apply in both twrp-build/ and los-build/.

Gotchas

  • The env deliberately has no 64-bit host gcc: PATH gcc is the genuine 32-bit pkgsi686Linux.gcc9 from multiPkgs, because omni/TWRP host tools are compiled as obj32 (-m32) and only work against a real 32-bit compiler. Adding gcc to targetPkgs regresses the TWRP build with the classic gnu/stubs-32.h: No such file or directory (x86_64 nixpkgs gcc has no 32-bit multilib headers).
  • repo launcher warning: the nix-provided gitRepo launcher is read-only and warns that it can't auto-update to a newer repo version — harmless.
  • Don't switch LOS off Jack or re-enable the Jack server (host TLS breaks the server path and aborts the build).
  • LOS family bits in the device tree are ported Samsung msm8926-tablet baselines, not device-extracted data: audio/mixer_paths.xml, wifi/WCNSS_*, keylayout/*, and the bootloader-match table in init/init_rubenslte.cpp come from the matisse/millet cm-14.1 trees. They build and boot (per the platform), but re-verify against stock rubenslte /system/etc before trusting camera/audio/wifi calibration; only rootdir/etc/fstab.qcom is rubens-extracted (partition map from stock recovery.fstab).
  • repo sync wipes in-tree edits — expected. Prefer editing the device repos, not patching; patches are only for upstream 5.1/14.1 sources that can't live in the device tree.
  • Commit style: short lowercase-imperative subject, no body. Stage with git add -A (images and workspaces are gitignored).

Why local_manifests

repo auto-imports every .xml in .repo/local_manifests/ on top of the primary manifest, so both builds get their rubenslte bits without forking the whole manifest. (repo reads the copy the build script drops into twrp-build/ / los-build/.repo/local_manifests/ — edit the source files, every build re-copies them.)

  • twrp.xml (TWRP): gitea twrp_device_samsung_rubenslte + android_kernel_samsung_rubenslte (both main). The omni twrp-5.1 manifest has no rubenslte entries, hence the overlay; the arm-eabi-4.8 toolchain is already in the primary manifest (default r28), so no override is needed.
  • rubenslte.xml (LOS): the cm-14.1 manifest is LineageOS's shared project list — no rubenslte entries, no gitea remote, and it pins chromium-webview prebuilts that fail to clone from GitHub (repos packed over GitHub's object limits). The overlay adds:
    • gitea device/vendor/kernel (main)
    • device/samsung/msm8226-common (gitea, cm-14.1) + the two qcom-common layers (LineageOS, cm-14.1)
    • <remove-project>s the four broken chromium-webview_prebuilt_* repos and adds the intact AOSP copy instead: external/chromium-webview (platform/external/chromium-webview on nougat-mr1.2-release, via the primary manifest's aosp remote).

Troubleshooting (most likely first)

  • repo sync fails remote <name> already exists with different attributes — a local-manifest <remote> redeclares a remote the primary manifest already defines with different attributes (only aosp shares the primary's remote name; as long as no local <remote name="aosp"> is added it resolves from default.xml). The primary aosp remote has absolute fetch, unlike github (fetch=".."), which is why that one gets a local los remote alias instead.
  • adb CANNOT LINK ... libc.so — /system isn't mounted in recovery; normal. Mount System in TWRP.
  • make: ... [/dt.img] Błąd 255 — the recursive-variable / INSTALLED_KERNEL_TARGET invariant broke; restore per above.
  • Recovery image won't fit — ramdisk isn't LZMA/trimmed; check mkbootimg.mk.
  • f2fs tools reappear in the ramdisk — stale out/target/product/rubenslte/root/sbin/ from a past build; delete + root.ts.
  • Jack jar "not readable" — re-seed .jack-repository/ from los-build/prebuilts/sdk/tools/jacks/ (cp -n jack-*.jar jill-*.jar).
  • Bacon JVM SIGSEGV in libconscrypt (signapk.jar, pc=0x300) — the full jdk8's GTK/GNOME startup stack loads OpenSSL 3 into global symbol scope and interposes AOSP host libconscrypt_openjdk_jni.so's embedded BoringSSL. Fixed by jdk8_headless in shell.nix (no desktop stack). If it ever returns, check LD_DEBUG=libs on a signapk run for openssl-3.0.9 loads and confirm shell.nix still uses jdk8_headless.

Device: SM-T365, MSM8926, Adreno 305, 1.5 GB/16 GB, recovery partition 10,485,248 B; similar devices: milletlte, matisselte, motorola_thea.

For depth: patches/README.md, twrp_device_samsung_rubenslte/README.md, local_manifests/rubenslte.xml.