1717# - Supports JSON package manifest for additional package installation
1818# (via apt or local .deb) inside the rootfs.
1919# - Supports injecting custom apt sources from the package manifest.
20- # - Injects custom kernel and firmware .deb packages.
20+ # - Optionally injects custom kernel and firmware .deb packages.
21+ # - Supports installing local .deb packages (--local-debs) with full dependency resolution
22+ # via a temporary local APT repository built inside the rootfs.
2123# - Installs user-specified packages from seed and/or overlay manifest.
2224# - Dynamically deduces and generates base and custom package manifests.
2325# - Configures GRUB bootloader, hostname, DNS, and other system settings.
2729# ./build-rootfs.sh \
2830# --product-conf qcom-product.conf \
2931# --seed seed_file \
30- # --kernel-package kernel.deb \
32+ # [ --kernel-package kernel.deb] \
3133# [--firmware firmware.deb] \
3234# [--overlay package-manifest.json] \
33- # [--variant desktop]
35+ # [--variant desktop] \
36+ # [--local-debs pkg-a.deb] \
37+ # [--local-debs debs/]
3438#
3539# ARGUMENTS:
3640# --product-conf <qcom-product.conf> Required. Product configuration file.
3741# --seed <seed_file> Required. Seed file: one package per line (# comments allowed).
38- # --kernel-package <kernel.deb> Required . Custom kernel package.
42+ # --kernel-package <kernel.deb> Optional . Custom kernel package.
3943# --firmware <firmware.deb> Optional. Custom firmware package.
4044# --overlay <package-manifest.json> Optional. JSON manifest specifying extra packages/apt sources.
4145# --variant <variant_name> Optional. System variant (default: desktop).
46+ # --local-debs <path> Optional. A .deb file OR a directory of .deb files to install
47+ # via a local APT repo (repeatable). May be specified multiple
48+ # times. Inter-package dependencies are resolved automatically
49+ # via a temporary local APT repository built inside the rootfs.
50+ # Installed after manifest packages (--overlay).
51+ # Examples:
52+ # --local-debs mypkg.deb
53+ # --local-debs debs/
4254#
4355# OUTPUT:
4456# rootfs.img Flashable ext4 rootfs image.
@@ -69,21 +81,26 @@ MANIFEST="" # internal name retained (overlay JSON)
6981KERNEL_DEB=" "
7082FIRMWARE_DEB=" "
7183VARIANT_INPUT=" " # New variable to hold the variant argument
84+ LOCAL_DEBS=() # Array of local .deb file paths (--local-debs, repeatable)
7285USE_CONF=0
7386USE_MANIFEST=0
7487TARGET=" "
7588
7689print_usage () {
7790 echo " Usage:"
78- echo " $0 --product-conf <qcom-product.conf> --seed <seed_file> --kernel-package <kernel.deb> [--firmware <firmware.deb>] [--overlay <package-manifest.json>] [--variant <variant>]"
91+ echo " $0 --product-conf <qcom-product.conf> --seed <seed_file> [ --kernel-package <kernel.deb>] [--firmware <firmware.deb>] [--overlay <package-manifest.json>] [--variant <variant>] [--local-debs <pkg.deb>] ... "
7992 echo
8093 echo " Arguments:"
8194 echo " --product-conf Required. qcom-product.conf"
8295 echo " --seed Required. Seed file (one package per line; supports # comments)"
83- echo " --kernel-package Required . Kernel .deb"
96+ echo " --kernel-package Optional . Kernel .deb"
8497 echo " --firmware Optional. Firmware .deb"
8598 echo " --overlay Optional. package-manifest.json (same schema as current manifest)"
8699 echo " --variant Optional. System variant (default: desktop)"
100+ echo " --local-debs Optional. A .deb file OR a directory of .deb files to install via a"
101+ echo " local APT repo (repeatable). Specify once per path. Dependencies"
102+ echo " between packages are resolved automatically. Installed after manifest."
103+ echo " Examples: --local-debs mypkg.deb --local-debs debs/"
87104}
88105
89106# Parse named options
@@ -102,6 +119,8 @@ while [[ $# -gt 0 ]]; do
102119 MANIFEST=" ${2-} " ; shift 2 ;;
103120 --variant)
104121 VARIANT_INPUT=" ${2-} " ; shift 2 ;;
122+ --local-debs)
123+ if [[ -n " ${2-} " ]]; then LOCAL_DEBS+=(" ${2-} " ); fi ; shift 2 ;;
105124 -h|--help)
106125 print_usage
107126 exit 0
@@ -115,7 +134,7 @@ while [[ $# -gt 0 ]]; do
115134done
116135
117136# Validate required args
118- if [[ -z " ${CONF} " || -z " ${SEED} " || -z " ${KERNEL_DEB} " ]]; then
137+ if [[ -z " ${CONF} " || -z " ${SEED} " ]]; then
119138 echo " [ERROR] Missing required argument(s)."
120139 print_usage
121140 exit 1
129148
130149[[ -f " $CONF " ]] || { echo " [ERROR] Config file not found: $CONF " ; exit 1; }
131150[[ -f " $SEED " ]] || { echo " [ERROR] Seed file not found: $SEED " ; exit 1; }
132- [[ -f " $KERNEL_DEB " ]] || { echo " [ERROR] Kernel package not found: $KERNEL_DEB " ; exit 1; }
151+ if [[ -n " $KERNEL_DEB " ]]; then
152+ [[ -f " $KERNEL_DEB " ]] || { echo " [ERROR] Kernel package not found: $KERNEL_DEB " ; exit 1; }
153+ fi
133154if [[ -n " $FIRMWARE_DEB " ]]; then
134155 [[ -f " $FIRMWARE_DEB " ]] || { echo " [ERROR] Firmware package not found: $FIRMWARE_DEB " ; exit 1; }
135156fi
136157if [[ " $USE_MANIFEST " -eq 1 && -n " $MANIFEST " ]]; then
137158 [[ -f " $MANIFEST " ]] || { echo " [ERROR] Manifest/overlay file not found: $MANIFEST " ; exit 1; }
138159fi
160+ for _deb in " ${LOCAL_DEBS[@]} " ; do
161+ if [[ -d " $_deb " ]]; then
162+ : # directory — may contain zero or more .deb files; handled gracefully at copy time
163+ elif [[ -f " $_deb " ]]; then
164+ : # valid .deb file path
165+ else
166+ echo " [ERROR] --local-debs path not found (not a file or directory): $_deb "
167+ exit 1
168+ fi
169+ done
139170
140171WORKDIR=$( pwd)
141172MNT_DIR=" $WORKDIR /mnt"
391422# Step 4: Inject Kernel, Firmware, and Working resolv.conf
392423# ==============================================================================
393424echo " [INFO] Copying kernel and firmware packages into rootfs..."
394- cp " $KERNEL_DEB " " $ROOTFS_DIR /"
425+ if [[ -n " $KERNEL_DEB " ]]; then
426+ cp " $KERNEL_DEB " " $ROOTFS_DIR /"
427+ fi
395428if [[ -n " $FIRMWARE_DEB " ]]; then
396429 cp " $FIRMWARE_DEB " " $ROOTFS_DIR /"
397430fi
@@ -463,6 +496,27 @@ apt install -y ${APT_INSTALL_LIST[@]}
463496EOF
464497chmod +x " $ROOTFS_DIR /install_manifest_pkgs.sh"
465498
499+ # ==============================================================================
500+ # Step 6.5: Copy local .deb packages into rootfs (if provided)
501+ # ==============================================================================
502+ if [[ ${# LOCAL_DEBS[@]} -gt 0 ]]; then
503+ echo " [INFO] Copying local .deb packages into rootfs for local APT repository..."
504+ mkdir -p " $ROOTFS_DIR /opt/local-debs"
505+ for _deb in " ${LOCAL_DEBS[@]} " ; do
506+ if [[ -d " $_deb " ]]; then
507+ echo " [INFO] -> directory: $_deb "
508+ for _f in " $_deb " /* .deb; do
509+ [[ -f " $_f " ]] || continue # skip if glob matched nothing (empty dir)
510+ echo " [INFO] $( basename " $_f " ) "
511+ cp " $_f " " $ROOTFS_DIR /opt/local-debs/"
512+ done
513+ else
514+ echo " [INFO] -> $( basename " $_deb " ) "
515+ cp " $_deb " " $ROOTFS_DIR /opt/local-debs/"
516+ fi
517+ done
518+ fi
519+
466520# ==============================================================================
467521# Step 7: Bind Mount System Directories for chroot
468522# ==============================================================================
@@ -516,6 +570,13 @@ else
516570 CMD_FW_INSTALL=" echo '[CHROOT] Skipping firmware installation.'"
517571fi
518572
573+ CMD_KERNEL_INSTALL=" "
574+ if [[ -n " $KERNEL_DEB " ]]; then
575+ CMD_KERNEL_INSTALL=" yes \"\" | dpkg -i /$( basename " $KERNEL_DEB " ) "
576+ else
577+ CMD_KERNEL_INSTALL=" echo '[CHROOT] Skipping kernel installation (no kernel package provided).'"
578+ fi
579+
519580echo " [INFO] Entering chroot to install packages and configure GRUB..."
520581env DISTRO=" $DISTRO " CODENAME=" $CODENAME " VARIANT=" $VARIANT " \
521582 chroot " $ROOTFS_DIR " /bin/bash -c "
@@ -562,7 +623,7 @@ dpkg-query -W -f='\${Package} \${Version}\n' > /tmp/\${CODENAME}_base.manifest
562623
563624echo '[CHROOT] Installing custom firmware and kernel...'
564625$CMD_FW_INSTALL
565- yes \"\" | dpkg -i / $( basename " $KERNEL_DEB " )
626+ $CMD_KERNEL_INSTALL
566627
567628# Run update-grub explicitly: the zz-update-grub hook skips it in a chroot
568629# because systemd is not running (/run/systemd/system absent).
@@ -575,6 +636,23 @@ usermod -aG sudo qcom
575636echo '[CHROOT] Installing manifest packages (if any)...'
576637/install_manifest_pkgs.sh || true
577638
639+ echo '[CHROOT] Installing local .deb packages via local APT repository (if any)...'
640+ if ls /opt/local-debs/*.deb >/dev/null 2>&1; then
641+ echo '[CHROOT] Setting up local .deb APT repository...'
642+ apt-get install -y --no-install-recommends dpkg-dev
643+ cd /opt/local-debs
644+ dpkg-scanpackages . /dev/null > Packages
645+ cd /
646+ echo 'deb [trusted=yes] file:///opt/local-debs ./' > /etc/apt/sources.list.d/local-debs.list
647+ apt-get update
648+ LOCAL_PKG_NAMES=\$ (for deb in /opt/local-debs/*.deb; do dpkg-deb --field \"\$ deb\" Package; done | tr '\n' ' ')
649+ echo \" [CHROOT] Installing local packages: \$ LOCAL_PKG_NAMES\"
650+ apt-get install -y \$ LOCAL_PKG_NAMES
651+ echo '[CHROOT] Local .deb packages installed successfully.'
652+ else
653+ echo '[CHROOT] No local .deb packages found; skipping.'
654+ fi
655+
578656echo '[CHROOT] Capturing post-install package list...'
579657dpkg-query -W -f='\$ {Package} \$ {Version}\n' > /tmp/\$ {CODENAME}_post.manifest
580658
0 commit comments