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). Runnix-shellfirst, then invoke the scripts — they do not self-re-enter the env anymore. Don't rely onnix-shell --run(the shellHook doesexec android-env); don't run two nix-shells at once (nix store deadlock). - TWRP sources:
repo initof omnitwrp-5.1(platform_manifest_twrp_omni) +local_manifests/twrp.xmlcopied into.repo/local_manifests/beforerepo sync -c -j$(nproc), thenapply_patches patches/twrpandapply_patches patches/kernel. - LOS sources:
repo initof cm-14.1 (LineageOS/android) +local_manifests/rubenslte.xmlcopied in beforerepo sync -c -j$(nproc), thenapply_patches patches/kernelandapply_patches patches/los. Sync wipes in-tree edits;apply_patchesis idempotent so re-applying each full build is harmless. - Patches:
common.sh::apply_patchesdry-runs each patch withLC_ALL=Cfirst. An already-applied patch makes GNU patch (2.8, from the nix env) reportReversed (or previously applied) patch detectedon 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 declaresprebuilts/gcc/linux-x86/arm/arm-eabi-4.8at the default revisionrefs/tags/android-5.1.1_r28(aosp remote). It lands atprebuilts/gcc/linux-x86/arm/arm-eabi-4.8and is put onPATH(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/fromprebuilts/sdk/tools/jacks/withcp -n. - Kernel: built from source via the omni/lineage kernel build rules. The
variant defconfig (
msm8926-sec_rubenslte_defconfig) enables onlyCONFIG_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.mkdrops tzdata + f2fs tools and compresses with LZMA. Result: 10,479,632 B, 19-language TWRP. - SEANDROIDENFORCE:
build_los.shappends 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_ARGSstay recursive (=, expanded afterPRODUCT_OUT/KERNEL_OUTexist) — never:=.mkbootimg.mk: the dt.img rule depends onINSTALLED_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 LOSrootdir/etc/fstab.qcomis 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 theirCONFIG_MACH_RUBENSLTE_*enabled. - SEANDROIDENFORCE trailer +
--dtare required for Samsung bootloaders (append_seandroidenforceappends it to LOS boot.img). - LOS is Jack-only and the ROM is bare (no GApps,
/dataext4). - Kernel fixes go in
patches/kernel/and must apply in bothtwrp-build/andlos-build/.
Gotchas
- The env deliberately has no 64-bit host gcc: PATH
gccis the genuine 32-bitpkgsi686Linux.gcc9frommultiPkgs, because omni/TWRP host tools are compiled as obj32 (-m32) and only work against a real 32-bit compiler. AddinggcctotargetPkgsregresses the TWRP build with the classicgnu/stubs-32.h: No such file or directory(x86_64 nixpkgs gcc has no 32-bit multilib headers). - repo launcher warning: the nix-provided
gitRepolauncher 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 ininit/init_rubenslte.cppcome from the matisse/millet cm-14.1 trees. They build and boot (per the platform), but re-verify against stock rubenslte/system/etcbefore trusting camera/audio/wifi calibration; onlyrootdir/etc/fstab.qcomis rubens-extracted (partition map from stock recovery.fstab). repo syncwipes 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): giteatwrp_device_samsung_rubenslte+android_kernel_samsung_rubenslte(bothmain). 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 (defaultr28), 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 brokenchromium-webview_prebuilt_*repos and adds the intact AOSP copy instead:external/chromium-webview(platform/external/chromium-webviewonnougat-mr1.2-release, via the primary manifest'saospremote).
- gitea device/vendor/kernel (
Troubleshooting (most likely first)
repo syncfailsremote <name> already exists with different attributes— a local-manifest<remote>redeclares a remote the primary manifest already defines with different attributes (onlyaospshares the primary's remote name; as long as no local<remote name="aosp">is added it resolves fromdefault.xml). The primaryaospremote has absolute fetch, unlikegithub(fetch=".."), which is why that one gets a locallosremote alias instead.- adb
CANNOT LINK ... libc.so—/systemisn't mounted in recovery; normal. Mount System in TWRP. make: ... [/dt.img] Błąd 255— the recursive-variable /INSTALLED_KERNEL_TARGETinvariant 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/fromlos-build/prebuilts/sdk/tools/jacks/(cp -n jack-*.jar jill-*.jar). - Bacon JVM SIGSEGV in libconscrypt (
signapk.jar,pc=0x300) — the fulljdk8's GTK/GNOME startup stack loads OpenSSL 3 into global symbol scope and interposes AOSP hostlibconscrypt_openjdk_jni.so's embedded BoringSSL. Fixed byjdk8_headlessinshell.nix(no desktop stack). If it ever returns, checkLD_DEBUG=libson a signapk run foropenssl-3.0.9loads and confirmshell.nixstill usesjdk8_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.