Compare commits
12 Commits
896c60691e
...
2d83b552c7
| Author | SHA1 | Date | |
|---|---|---|---|
| 2d83b552c7 | |||
| ec8fb8f960 | |||
| 2ce592b693 | |||
| 4d70450fe8 | |||
| 2245e7feef | |||
| f5f32ed8d4 | |||
| 0485481023 | |||
| dea1912670 | |||
| e402c76da1 | |||
| 75aee07a26 | |||
| c508654e79 | |||
| b9701e3ab6 |
29
README.md
29
README.md
@@ -41,12 +41,37 @@ See `profiles` for example device profile definitions. Multiple `--profile` can
|
||||
|
||||
The default build mode is `imagebuilder` unless `--mode=source` is passed. Default profile modes can be set individually in `profiles`.
|
||||
|
||||
`--mode=imagebuilder` inherits `CONFIG_TARGET_ROOTFS_PARTSIZE=`, but all other kconfigs only work in `--mode=source`.
|
||||
|
||||
Profile keys:
|
||||
|
||||
| Key | Required | Description |
|
||||
|---|---|---|
|
||||
| `mode` | No | Build mode for this profile: `imagebuilder` or `source`. CLI `--mode` overrides profile value. |
|
||||
| `device` | Yes | OpenWrt device/profile id used by build commands (for example `friendlyarm_nanopi-r4s`). |
|
||||
| `target` | Yes | OpenWrt target/subtarget (for example `rockchip/armv8`, `x86/64`). |
|
||||
| `filesystem` | No | Root filesystem type (`squashfs`, `ext4`, etc). Defaults to `squashfs`. |
|
||||
| `packages` | No | Space-separated package list. Prefix with `-` to remove a package in Image Builder or source config generation. |
|
||||
| `kconfigs` | No | Space-separated Kconfig symbols. In `imagebuilder` mode only `CONFIG_TARGET_ROOTFS_PARTSIZE=<MB>` is used (mapped to `ROOTFS_PARTSIZE`). In `source` mode all entries are written to `.config` seed. |
|
||||
| `files` | No | Host directory containing custom overlay files. In `imagebuilder` mode this is passed as `FILES=<dir>`. In `source` mode contents are synced into `<build dir>/files/` before build. Defaults to `<buildroot>/src/files`. |
|
||||
| `cherrypicks` | No | Space-separated entries in `URL@branch:commit` form. Each commit is fetched and cherry-picked in `source` mode. |
|
||||
| `branches` | No | Space-separated `URL@branch` entries to merge into the source worktree in `source` mode. |
|
||||
| `release` | No | Default release/ref for the profile (for example `snapshot`, `25.12.3`). CLI `--release` overrides it. |
|
||||
| `clean` | No | Optional source cleanup step (`clean`, `targetclean`, `dirclean`, `distclean`). CLI `--clean` overrides it. |
|
||||
| `repo` | No | Extra Image Builder repository line appended to `repositories.conf` before build. |
|
||||
|
||||
Notes:
|
||||
|
||||
* The profile file uses associative arrays (`declare -Ag name=( [key]="value" ... )`).
|
||||
* `packages`, `kconfigs`, `cherrypicks`, and `branches` are parsed as scalar whitespace-separated strings.
|
||||
* If a profile-specific `files` path is configured, it must exist.
|
||||
|
||||
## Examples
|
||||
|
||||
* `openwrtbuilder -p r4s -p ax6000`
|
||||
* `openwrtbuilder -p r4s -r snapshot --debug`
|
||||
* `openwrtbuilder -p ax6000 -r 23.05.5 --mode source --debug`
|
||||
* `openwrtbuilder -p rpi4 -r 23.05.5 --flash /dev/sdX`
|
||||
* `openwrtbuilder -p ax6000 -r 25.12.3 --mode source --debug`
|
||||
* `openwrtbuilder -p rpi4 -r 25.12.3 --flash /dev/sdX`
|
||||
* `openwrtbuilder -p linksys -r snapshot --ssh-upgrade root@192.168.1.1`
|
||||
|
||||
## Additional Info
|
||||
|
||||
123
openwrtbuilder
123
openwrtbuilder
@@ -1,25 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build and deploy OpenWRT images using shell-style device profiles, via source code or the official Image Builder.
|
||||
# Copyright 2022-25 Bryan C. Roessler
|
||||
# Copyright 2022-26 Bryan C. Roessler
|
||||
# Apache 2.0 License
|
||||
# See README and ./profiles for device configuration
|
||||
|
||||
# Set default release
|
||||
: "${DEFAULT_RELEASE:=${RELEASE:="24.10.5"}}"
|
||||
: "${DEFAULT_RELEASE:=${RELEASE:="25.12.3"}}" # do find all replace
|
||||
|
||||
# @internal
|
||||
print_help() {
|
||||
usage() {
|
||||
debug "${FUNCNAME[0]}"
|
||||
|
||||
cat <<-'EOF'
|
||||
Build and deploy OpenWRT images using convenient profiles.
|
||||
|
||||
USAGE:
|
||||
openwrtbuilder [OPTION [VALUE]]... -p PROFILE [-p PROFILE]...
|
||||
openwrtbuilder [OPTIONS] [-p PROFILE]...
|
||||
|
||||
OPTIONS
|
||||
--profile,-p PROFILE
|
||||
--release,-r,--version,-v RELEASE ("snapshot", "24.10.5")
|
||||
--release,-r,--version,-v RELEASE ("snapshot", "25.12.3")
|
||||
Default: From profile or hardcoded RELEASE
|
||||
--buildroot,-b PATH
|
||||
Default: location of openwrtbuilder script
|
||||
@@ -44,8 +44,8 @@ print_help() {
|
||||
|
||||
EXAMPLES
|
||||
openwrtbuilder -p r4s -r snapshot
|
||||
openwrtbuilder -p ax6000 -r 23.05.0-rc3 --source --debug
|
||||
openwrtbuilder -p rpi4 -r 24.10.0 --flash /dev/sdX
|
||||
openwrtbuilder -p ax6000 -r 23.05.0-rc3 --mode source --debug
|
||||
openwrtbuilder -p rpi4 -r 25.12.3 --flash /dev/sdX
|
||||
openwrtbuilder -p linksys -r snapshot --ssh-upgrade root@192.168.1.1
|
||||
EOF
|
||||
}
|
||||
@@ -66,7 +66,7 @@ init() {
|
||||
else
|
||||
echo "/etc/os-release not found"
|
||||
echo "Your OS is unsupported"
|
||||
print_help
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -149,14 +149,14 @@ parse_input() {
|
||||
--depends) FORCE_DEPENDS=1 ;;
|
||||
--yes|-y) YES=1 ;;
|
||||
--debug|-d) echo "Debugging on"; DEBUG=1 ;;
|
||||
--help|-h) print_help; exit 0 ;;
|
||||
--help|-h) usage; exit 0 ;;
|
||||
--) shift; break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
else
|
||||
echo "Incorrect options provided"
|
||||
print_help; exit 1
|
||||
usage; exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ install_dependencies() {
|
||||
lock_file="$BUILD_ROOT/.dependencies_imagebuilder.lock"
|
||||
fi
|
||||
|
||||
[[ -f $lock_file ]] && debug "$lock_file lock file exists but skipping for --debug" && return 0
|
||||
[[ -f $lock_file ]] && debug "$lock_file lock file exists, skipping dependency install" && return 0
|
||||
|
||||
if [[ "$mode" == "source" ]]; then
|
||||
# For building from source code see:
|
||||
@@ -403,31 +403,51 @@ ssh_backup() {
|
||||
[[ -d "$FILES_DIR" ]] || execute mkdir -p "$FILES_DIR"
|
||||
|
||||
# Make backup archive on remote
|
||||
if ! execute "ssh -t $SSH_BACKUP_PATH sysupgrade -b /tmp/$backup_fname"; then
|
||||
if ! execute ssh -t "$SSH_BACKUP_PATH" sysupgrade -b "/tmp/$backup_fname"; then
|
||||
echo "SSH backup failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Move backup archive locally
|
||||
if ! execute "rsync -avz --remove-source-files $SSH_BACKUP_PATH:/tmp/$backup_fname $BUILD_DIR/"; then
|
||||
if ! execute rsync -avz --remove-source-files "$SSH_BACKUP_PATH:/tmp/$backup_fname" "$BUILD_DIR/"; then
|
||||
echo "Could not copy SSH backup"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract backup archive
|
||||
if ! execute "tar -C $FILES_DIR -xzf $BUILD_DIR/$backup_fname"; then
|
||||
if ! execute tar -C "$FILES_DIR" -xzf "$BUILD_DIR/$backup_fname"; then
|
||||
echo "Could not extract SSH backup"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
execute "rm $BUILD_DIR/$backup_fname"
|
||||
execute rm "$BUILD_DIR/$backup_fname"
|
||||
}
|
||||
|
||||
make_images() {
|
||||
debug "${FUNCNAME[0]}"
|
||||
local -a make_opts
|
||||
local -a make_opts; ((DEBUG)) && make_opts+=("V=sc")
|
||||
local rootfs_partsize
|
||||
|
||||
# Image Builder accepts ROOTFS_PARTSIZE, not CONFIG_TARGET_ROOTFS_PARTSIZE.
|
||||
# Parse profile KCONFIGS (scalar string) and extract only this value.
|
||||
for kconfig in $KCONFIGS; do
|
||||
case "$kconfig" in
|
||||
CONFIG_TARGET_ROOTFS_PARTSIZE=*) rootfs_partsize="${kconfig#*=}" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
local -a make_cmd=(make "${make_opts[@]}" image
|
||||
BIN_DIR="$BIN_DIR"
|
||||
PROFILE="$DEVICE"
|
||||
PACKAGES="$PACKAGES"
|
||||
FILES="$FILES_DIR"
|
||||
--directory="$BUILD_DIR"
|
||||
--jobs="$JOBS")
|
||||
|
||||
[[ -n "$rootfs_partsize" ]] && make_cmd+=("ROOTFS_PARTSIZE=$rootfs_partsize")
|
||||
|
||||
# Reuse the existing output
|
||||
# TODO Disable for now since it was causing issues
|
||||
# if [[ -d "$BIN_DIR" ]]; then
|
||||
# if ask_ok "$BIN_DIR exists. Rebuild?"; then
|
||||
# execute rm -rf "$BIN_DIR"
|
||||
@@ -436,21 +456,10 @@ make_images() {
|
||||
# fi
|
||||
# fi
|
||||
|
||||
((DEBUG)) && make_opts+=("V=sc")
|
||||
|
||||
debug make "${make_opts[@]}" image BIN_DIR="$BIN_DIR" \
|
||||
PROFILE="$DEVICE" PACKAGES="$PACKAGES" \
|
||||
FILES="$FILES_DIR" --directory="$BUILD_DIR" \
|
||||
--jobs="$JOBS"
|
||||
|
||||
make "${make_opts[@]}" image \
|
||||
BIN_DIR="$BIN_DIR" \
|
||||
PROFILE="$DEVICE" \
|
||||
PACKAGES="$PACKAGES" \
|
||||
FILES="$FILES_DIR" \
|
||||
--directory="$BUILD_DIR" \
|
||||
--jobs="$JOBS" \
|
||||
> "$BUILD_DIR/make.log"
|
||||
# Debug manually so we can log output
|
||||
debug "${make_cmd[*]}"
|
||||
"${make_cmd[@]}" 2>&1 | tee "$BUILD_DIR/make.log"
|
||||
return "${PIPESTATUS[0]}" # bash-specific way to return exit code of piped command
|
||||
}
|
||||
|
||||
flash_images() {
|
||||
@@ -458,9 +467,8 @@ flash_images() {
|
||||
local img_gz="$1"
|
||||
local dev="$2"
|
||||
local img="${img_gz%.gz}"
|
||||
local partitions
|
||||
|
||||
if [[ ! -e "$dev" ]]; then
|
||||
if [[ ! -b "$dev" ]]; then
|
||||
echo "The device specified by --flash could not be found"
|
||||
return 1
|
||||
fi
|
||||
@@ -468,13 +476,13 @@ flash_images() {
|
||||
[[ -f $img_gz ]] || { echo "$img_gz does not exist"; return 1; }
|
||||
|
||||
execute gunzip -qfk "$img_gz"
|
||||
|
||||
echo "Unmounting target device $dev partitions"
|
||||
partitions=("$dev"?*)
|
||||
execute sudo umount "${partitions[@]}"
|
||||
[[ -f "$img" ]] || { echo "Extracted image '$img' is missing"; return 1; }
|
||||
|
||||
if execute sudo dd if="$img" of="$dev" bs=2M conv=fsync; then
|
||||
sync
|
||||
if command -v partprobe &>/dev/null; then
|
||||
execute sudo partprobe "$dev" || debug "partprobe failed for $dev"
|
||||
fi
|
||||
echo "Image flashed successfully!"
|
||||
else
|
||||
echo "dd failed!"
|
||||
@@ -504,15 +512,14 @@ ssh_upgrade() {
|
||||
}
|
||||
|
||||
# @description Builds OpenWRT from source code using the the default buildbot as base
|
||||
# This enables the use of kernel config options in profiles
|
||||
from_source() {
|
||||
debug "${FUNCNAME[0]}"
|
||||
local src_url="https://github.com/openwrt/openwrt.git"
|
||||
local seed_file="$BUILD_DIR/.config"
|
||||
local worktree_meta="$SRC_DIR/.git/worktrees/source-$REF"
|
||||
local pkg config commit description
|
||||
local pkg kconfig commit description
|
||||
local -a make_opts
|
||||
local -a config_opts=(
|
||||
local -a kconfigs=(
|
||||
"CONFIG_TARGET_${TARGET%%/*}=y"
|
||||
"CONFIG_TARGET_${TARGET//\//_}=y"
|
||||
"CONFIG_TARGET_PROFILE=DEVICE_$DEVICE"
|
||||
@@ -667,25 +674,33 @@ from_source() {
|
||||
./scripts/feeds update -a -f &&
|
||||
./scripts/feeds install -a -f
|
||||
|
||||
# Apply custom files overlay for source builds.
|
||||
execute rm -rf "$BUILD_DIR/files"
|
||||
if [[ -d "$FILES_DIR" ]]; then
|
||||
execute mkdir -p "$BUILD_DIR/files"
|
||||
execute rsync -a "$FILES_DIR/" "$BUILD_DIR/files/"
|
||||
fi
|
||||
|
||||
# Add custom packages
|
||||
for pkg in $PACKAGES; do
|
||||
if [[ $pkg == -* ]]; then
|
||||
config_opts+=("CONFIG_PACKAGE_${pkg#-}=n") # remove package
|
||||
kconfigs+=("CONFIG_PACKAGE_${pkg#-}=n") # remove package
|
||||
else
|
||||
config_opts+=("CONFIG_PACKAGE_$pkg=y") # add package
|
||||
kconfigs+=("CONFIG_PACKAGE_$pkg=y") # add package
|
||||
fi
|
||||
done
|
||||
|
||||
# Add profile config options
|
||||
for config in $CONFIGS; do
|
||||
config_opts+=("$config")
|
||||
# Add profile kconfig options
|
||||
# $KCONFIGS is a scalar, use a loop to split and avoid SC2068
|
||||
for kconfig in $KCONFIGS; do
|
||||
kconfigs+=("$kconfig")
|
||||
done
|
||||
|
||||
# Reset and write options to config seed file
|
||||
[[ -f $seed_file ]] && execute rm -f "$seed_file"
|
||||
for config in "${config_opts[@]}"; do
|
||||
debug "Writing $config to $seed_file"
|
||||
echo "$config" >> "$seed_file"
|
||||
for kconfig in "${kconfigs[@]}"; do
|
||||
debug "Writing $kconfig to $seed_file"
|
||||
echo "$kconfig" >> "$seed_file"
|
||||
done
|
||||
|
||||
# Expand seed into full config
|
||||
@@ -766,7 +781,6 @@ main() {
|
||||
|
||||
# Fallback to SCRIPT_DIR if BUILD_ROOT has not been set
|
||||
declare -g BUILD_ROOT="${BUILD_ROOT:=$SCRIPT_DIR}"
|
||||
declare -g FILES_DIR="${FILES_DIR:=$BUILD_ROOT/src/files}"
|
||||
declare -g BACKUP_DIR="$SCRIPT_DIR/backups"
|
||||
|
||||
# This could be dangerous
|
||||
@@ -813,7 +827,16 @@ main() {
|
||||
declare -g PACKAGES="${P_ARR[packages]:-}" # scalar
|
||||
declare -g CHERRYPICKS="${P_ARR[cherrypicks]:-}" # scalar
|
||||
declare -g BRANCHES="${P_ARR[branches]:-}" # scalar
|
||||
declare -g CONFIGS="${P_ARR[configs]:-}" # scalar
|
||||
declare -g KCONFIGS="${P_ARR[kconfigs]:-}" # scalar
|
||||
declare -g FILES_DIR="${P_ARR[files]:-$BUILD_ROOT/src/files}"
|
||||
|
||||
if [[ ! -d "$FILES_DIR" ]]; then
|
||||
if [[ -v P_ARR[files] ]]; then
|
||||
echo "Profile '$PROFILE' files directory does not exist: $FILES_DIR"
|
||||
return 1
|
||||
fi
|
||||
execute mkdir -p "$FILES_DIR"
|
||||
fi
|
||||
|
||||
install_dependencies "$MODE"
|
||||
|
||||
|
||||
23
profiles
23
profiles
@@ -2,7 +2,7 @@
|
||||
# Device profiles for openwrtbuilder
|
||||
# shellcheck disable=SC2034
|
||||
|
||||
DEFAULT_RELEASE="25.12.0-rc4" # overrides default release in openwrtbuilder
|
||||
DEFAULT_RELEASE="25.12.3" # overrides default release in openwrtbuilder
|
||||
|
||||
# Default packages (precede with "-" to exclude)
|
||||
default_packages=(
|
||||
@@ -13,7 +13,7 @@ default_packages=(
|
||||
)
|
||||
|
||||
# Default kernel configs
|
||||
default_configs=(
|
||||
default_kconfigs=(
|
||||
)
|
||||
|
||||
# Current devices
|
||||
@@ -24,14 +24,13 @@ declare -Ag r4s=(
|
||||
[filesystem]="ext4"
|
||||
[packages]="${default_packages[*]} \
|
||||
adblock luci-app-adblock \
|
||||
irqbalance luci-app-irqbalance \
|
||||
luci-app-sqm \
|
||||
collectd-mod-df usbutils kmod-usb-storage kmod-usb-storage-uas \
|
||||
kmod-fs-btrfs btrfs-progs block-mount smcroute avahi-daemon \
|
||||
ethtool ca-bundle tailscale"
|
||||
[configs]="${default_configs[*]} \
|
||||
CONFIG_KERNEL_BTRFS_FS_POSIX_ACL=y CONFIG_BTRFS_PROGS_ZSTD=y \
|
||||
CONFIG_TARGET_ROOTFS_PARTSIZE=512 CONFIG_TARGET_KERNEL_PARTSIZE=32"
|
||||
[files]="/mnt/backup"
|
||||
[kconfigs]="${default_kconfigs[*]} \
|
||||
CONFIG_TARGET_ROOTFS_PARTSIZE=512 CONFIG_TARGET_KERNEL_PARTSIZE=32 \
|
||||
CONFIG_KERNEL_BTRFS_FS_POSIX_ACL=y CONFIG_BTRFS_PROGS_ZSTD=y"
|
||||
# For 24.10 branch (Linux 6.6)
|
||||
# [cherrypicks]="https://github.com/wurzerj/openwrt.git:59d6e31 \
|
||||
# https://github.com/wurzerj/openwrt.git:bb251b8" # fix inconsistent reboot
|
||||
@@ -46,7 +45,7 @@ declare -Ag ax6000=(
|
||||
tailscale"
|
||||
)
|
||||
|
||||
declare -Ag ax6000_uboot=(
|
||||
declare -Ag ax6000_uboot_ap=(
|
||||
[mode]="imagebuilder"
|
||||
[device]="xiaomi_redmi-router-ax6000-ubootmod"
|
||||
[target]="mediatek/filogic"
|
||||
@@ -66,10 +65,9 @@ declare -Ag n5100=(
|
||||
btrfs-progs block-mount cryptsetup kmod-crypto-xts smcroute \
|
||||
avahi-daemon ethtool ca-bundle smartmontools intel-microcode \
|
||||
lm-sensors samba4-server luci-app-samba4 tailscale shadow-useradd"
|
||||
[configs]="${default_configs[*]} \
|
||||
[kconfigs]="${default_kconfigs[*]} \
|
||||
CONFIG_KERNEL_BTRFS_FS_POSIX_ACL=y CONFIG_BTRFS_PROGS_ZSTD=y \
|
||||
CONFIG_TARGET_ROOTFS_PARTSIZE=512 CONFIG_TARGET_KERNEL_PARTSIZE=32"
|
||||
# [files]="/mnt/backup"
|
||||
)
|
||||
|
||||
declare -Ag w1700k=(
|
||||
@@ -97,7 +95,7 @@ declare -Ag w1700k=(
|
||||
# https://github.com/OpenWRT-fanboy/OpenW1700k.git@lumos:9841a707a577385498591bcfb56b836176325c2f \
|
||||
# https://github.com/OpenWRT-fanboy/OpenW1700k.git@lumos:8446ec6431a3247683a27070d3c69f2789b52c70 \
|
||||
# https://github.com/OpenWRT-fanboy/OpenW1700k.git@lumos:05380e2ef5fb96c171da23453ba32aa349a4b126"
|
||||
[branches]="https://github.com/OpenWRT-fanboy/OpenW1700k.git@minimal"
|
||||
# [branches]="https://github.com/OpenWRT-fanboy/OpenW1700k.git@minimal"
|
||||
)
|
||||
|
||||
declare -Ag w1700k_ap=(
|
||||
@@ -108,10 +106,9 @@ declare -Ag w1700k_ap=(
|
||||
[release]="snapshot"
|
||||
[packages]="${default_packages[*]} \
|
||||
-dnsmasq -odhcpd-ipv6only -nftables -firewall4 \
|
||||
irqblance luci-app-irqbalance \
|
||||
wpad-openssl libiwinfo-data tailscale bridger switch smp_util \
|
||||
kmod-crypto-hw-eip93"
|
||||
[branches]="https://github.com/OpenWRT-fanboy/OpenW1700k.git@minimal"
|
||||
# [branches]="https://github.com/OpenWRT-fanboy/OpenW1700k.git@minimal"
|
||||
)
|
||||
|
||||
declare -Ag rpi4=(
|
||||
|
||||
Reference in New Issue
Block a user