Skip to content

feat(tools): add build-iiab-rootfs.sh (IIAB-oA rootfs builder)#24

Merged
luisguzman-adfa merged 6 commits into
mainfrom
tools/add-rootfs-builder
Jun 23, 2026
Merged

feat(tools): add build-iiab-rootfs.sh (IIAB-oA rootfs builder)#24
luisguzman-adfa merged 6 commits into
mainfrom
tools/add-rootfs-builder

Conversation

@luisguzman-adfa

Copy link
Copy Markdown
Collaborator

Adds tools/build-iiab-rootfs.sh — builds an IIAB-oA rootfs natively under proot (same libproot + flags as PRootEngine.java), alongside tools/proot-builder.

Highlights:

  • Reads the iiab/iiab commit from the installed /opt/iiab/iiab for the artifact id (provenance).
  • Packages as installed-rootfs/iiab/ — what the app extracts into rootfs/ and detects (fixes the layout mismatch).
  • .meta4 via mkmetalink (bootstraps Go >= 1.25.1), primary + mirror (priority 10/11).
  • --all-arch/--all-tier; --scratch-build (double-gated); native-first with QEMU fallback (--accept-force-emulate-qemu); start-clean + housekeeping; timing.
  • BUILD-ONLY: stages to dist/ + PUBLISH_QUEUE.tsv, never uploads.

Verified: arm64 full builds CLEAN (~30 min); bash -n passes.
Note: tooling-only; skipped by CI once #23 merges. Future: wire into bake-rootfs.yml.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

luisguzman-adfa and others added 4 commits June 23, 2026 04:25
proot repeatedly printed 'please set PROOT_TMP_DIR to a writable location'
during the install. PROOT_TMP_DIR was set INSIDE the 'env -i' guest env to
${PROOT_TMP} (a HOST absolute path) which does not exist inside the rootfs,
so any nested proot the IIAB installer spawns in the guest inherited a
non-writable PROOT_TMP_DIR. Meanwhile the OUTER proot had no PROOT_TMP_DIR
in its host env at all.

Fix:
- Set PROOT_TMP_DIR=${PROOT_TMP} on the HOST side (prefix the outer proot
  command) so the outer proot writes its temp to the writable host dir.
- In the guest env set PROOT_TMP_DIR=/tmp — a guest-valid path bound to
  ${PROOT_TMP} (writable, chmod 1777) — so nested guest proot works and the
  message stops. Also more device-faithful (a guest path, not a host path).
…uilds)

Two fixes needed when BUILDING the rootfs on an SBC (proot on a 64-bit kernel),
which do not arise in the on-device APK build:

1) pid_max: glibc's 32-bit pthread_mutex_t aborts when a process PID > 65535.
   The host PID counter climbs with uptime, so the armeabi-v7a build failed
   intermittently (e.g. RPi5 at pid 114831 -> core dump, rc=134) while passing on
   freshly-booted hosts. For armeabi-v7a on an aarch64 host, cap kernel.pid_max to
   65536 before launching proot and restore it on exit (trap). No effect on arm64.

2) flatten .l2s: proot --link2symlink rewrites hardlinks as ABSOLUTE symlinks to
   .l2s.<name>NNNN files under the build path; they dangle once the rootfs is
   restored at another path on the device (e.g. better_sqlite3.node), breaking the
   dashboard. Materialize every .l2s symlink into a real file before packaging so
   the tarball is relocatable.
@luisguzman-adfa luisguzman-adfa force-pushed the tools/add-rootfs-builder branch from 0ab3b03 to 7127e70 Compare June 23, 2026 04:25
AppDevForAll added 2 commits June 23, 2026 04:30
In --all-arch/--all-tier mode the script re-invokes itself per (arch,tier). It
used "$0", which is just the basename when launched as 'bash build-iiab-rootfs.sh'
(no ./ , not on PATH) -> 'command not found' and every combo failed instantly.
Resolve an absolute SELF once (readlink -f $0) and dispatch with 'bash "$SELF"',
so it works regardless of how it's launched (bash NAME, ./NAME, or abs path).
Emit two members inside the tree: identity (.iiab-rootfs.json, packed first)
and integrity (.iiab-rootfs.integrity.json, packed last, excluded from its own
hash), carrying an iiab-tree-sha256-v1 streaming tree digest. Build self-verifies
the finished artifact before shipping. Lets a manually-imported rootfs (no
sidecar .meta4) detect corruption on its own.

Frozen spec + recipe: docs/ROOTFS_MANIFEST.md
Reference recipe: tools/iiab_tree_hash.py
@luisguzman-adfa luisguzman-adfa merged commit fbd1e41 into main Jun 23, 2026
luisguzman-adfa added a commit that referenced this pull request Jun 23, 2026
…ft + alert)

Builds on the import/restore validation: now reads the build's identity manifest
`installed-rootfs/iiab/.iiab-rootfs.json` (canonical contract:
docs/ROOTFS_MANIFEST.md), which the rootfs builder (PR #24) emits as the first
tar member.

- New deploy/data/RootfsManifest: a dependency-free reader that parses only the
  first few 512-byte tar headers (the identity member is packed first) to get
  {kind, arch} — no reliance on libtar `--occurrence`, fast (a few KB).
- RootfsArchiveValidator: when the manifest is present it authoritatively gates
  `kind` (must be "iiab-rootfs") and `arch` (must equal this app's ABI); the ELF
  probe is skipped. When absent it returns OK_NO_MANIFEST and falls back to the
  existing ELF/structure heuristic.
- Soft phase (this version): a missing manifest does NOT block — import shows a
  non-blocking "manifest not found" warning and proceeds; a later version will
  validate silently / then strictly. Wrong kind/arch is still hard-blocked.
- New string install_warn_manifest_missing (en + es).

Next (separate PR): the integrity check (iiab-tree-sha256-v1 -> Result.CORRUPT,
a Java ustar/pax reader mirroring tools/iiab_tree_hash.py) and the in-app
backup-writer emitting both members.
luisguzman-adfa added a commit that referenced this pull request Jun 23, 2026
…ft + alert)

Builds on the import/restore validation: now reads the build's identity manifest
`installed-rootfs/iiab/.iiab-rootfs.json` (canonical contract:
docs/ROOTFS_MANIFEST.md), which the rootfs builder (PR #24) emits as the first
tar member.

- New deploy/data/RootfsManifest: a dependency-free reader that parses only the
  first few 512-byte tar headers (the identity member is packed first) to get
  {kind, arch} — no reliance on libtar `--occurrence`, fast (a few KB).
- RootfsArchiveValidator: when the manifest is present it authoritatively gates
  `kind` (must be "iiab-rootfs") and `arch` (must equal this app's ABI); the ELF
  probe is skipped. When absent it returns OK_NO_MANIFEST and falls back to the
  existing ELF/structure heuristic.
- Soft phase (this version): a missing manifest does NOT block — import shows a
  non-blocking "manifest not found" warning and proceeds; a later version will
  validate silently / then strictly. Wrong kind/arch is still hard-blocked.
- New string install_warn_manifest_missing (en + es).

Next (separate PR): the integrity check (iiab-tree-sha256-v1 -> Result.CORRUPT,
a Java ustar/pax reader mirroring tools/iiab_tree_hash.py) and the in-app
backup-writer emitting both members.
luisguzman-adfa added a commit that referenced this pull request Jun 23, 2026
…ft + alert)

Builds on the import/restore validation: now reads the build's identity manifest
`installed-rootfs/iiab/.iiab-rootfs.json` (canonical contract:
docs/ROOTFS_MANIFEST.md), which the rootfs builder (PR #24) emits as the first
tar member.

- New deploy/data/RootfsManifest: a dependency-free reader that parses only the
  first few 512-byte tar headers (the identity member is packed first) to get
  {kind, arch} — no reliance on libtar `--occurrence`, fast (a few KB).
- RootfsArchiveValidator: when the manifest is present it authoritatively gates
  `kind` (must be "iiab-rootfs") and `arch` (must equal this app's ABI); the ELF
  probe is skipped. When absent it returns OK_NO_MANIFEST and falls back to the
  existing ELF/structure heuristic.
- Soft phase (this version): a missing manifest does NOT block — import shows a
  non-blocking "manifest not found" warning and proceeds; a later version will
  validate silently / then strictly. Wrong kind/arch is still hard-blocked.
- New string install_warn_manifest_missing (en + es).

Next (separate PR): the integrity check (iiab-tree-sha256-v1 -> Result.CORRUPT,
a Java ustar/pax reader mirroring tools/iiab_tree_hash.py) and the in-app
backup-writer emitting both members.
luisguzman-adfa added a commit that referenced this pull request Jun 24, 2026
…ft + alert)

Builds on the import/restore validation: now reads the build's identity manifest
`installed-rootfs/iiab/.iiab-rootfs.json` (canonical contract:
docs/ROOTFS_MANIFEST.md), which the rootfs builder (PR #24) emits as the first
tar member.

- New deploy/data/RootfsManifest: a dependency-free reader that parses only the
  first few 512-byte tar headers (the identity member is packed first) to get
  {kind, arch} — no reliance on libtar `--occurrence`, fast (a few KB).
- RootfsArchiveValidator: when the manifest is present it authoritatively gates
  `kind` (must be "iiab-rootfs") and `arch` (must equal this app's ABI); the ELF
  probe is skipped. When absent it returns OK_NO_MANIFEST and falls back to the
  existing ELF/structure heuristic.
- Soft phase (this version): a missing manifest does NOT block — import shows a
  non-blocking "manifest not found" warning and proceeds; a later version will
  validate silently / then strictly. Wrong kind/arch is still hard-blocked.
- New string install_warn_manifest_missing (en + es).

Next (separate PR): the integrity check (iiab-tree-sha256-v1 -> Result.CORRUPT,
a Java ustar/pax reader mirroring tools/iiab_tree_hash.py) and the in-app
backup-writer emitting both members.
@luisguzman-adfa luisguzman-adfa deleted the tools/add-rootfs-builder branch June 24, 2026 02:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant