Compare commits

..

1 Commits

Author SHA1 Message Date
251b54937b Use --detached worktrees 2025-08-05 14:13:27 -04:00
3 changed files with 236 additions and 507 deletions

View File

@@ -12,12 +12,10 @@ Build and deploy OpenWRT images using shell-style device profiles, via source co
--profile,-p PROFILE
--release,-r,--version,-v RELEASE ("snapshot", "22.03.3")
--buildroot,-b PATH (Default: script directory)
--cpus,-c NUM
Default: # of host CPUS minus 1
--mode,-m imagebuilder|source
Default: imagebuilder
--clean clean|targetclean|dirclean|distclean
Optional clean step for source mode
--source
Build image from source code, not from Image Builder
Allows make config options to be passed in profile
Uses git worktree for multi-profile deduplication
--ssh-upgrade HOST
Example: root@192.168.1.1
--ssh-backup SSH_PATH
@@ -39,39 +37,14 @@ Build and deploy OpenWRT images using shell-style device profiles, via source co
See `profiles` for example device profile definitions. Multiple `--profile` can be passed at once.
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.4`). 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.
The default build mode is `imagebuilder` unless `--source` is passed. Default profile modes can be set individually in `profiles`.
## Examples
* `openwrtbuilder -p r4s -p ax6000`
* `openwrtbuilder -p r4s -r snapshot --debug`
* `openwrtbuilder -p ax6000 -r 25.12.4 --mode source --debug`
* `openwrtbuilder -p rpi4 -r 25.12.4 --flash /dev/sdX`
* `openwrtbuilder -p ax6000 -r 23.05.5 --source --debug`
* `openwrtbuilder -p rpi4 -r 23.05.5 --flash /dev/sdX`
* `openwrtbuilder -p linksys -r snapshot --ssh-upgrade root@192.168.1.1`
## Additional Info

View File

@@ -1,55 +1,49 @@
#!/usr/bin/env bash
# Build and deploy OpenWRT images using shell-style device profiles, via source code or the official Image Builder.
# Copyright 2022-26 Bryan C. Roessler
# Build and deploy OpenWRT images using shell-style device profiles, via source code or the official Image Builder.# Copyright 2022-25 Bryan C. Roessler
# Apache 2.0 License
# See README and ./profiles for device configuration
# See README and profiles for device configuration
# Set default release
: "${DEFAULT_RELEASE:=${RELEASE:="25.12.4"}}" # do find all replace
: "${RELEASE:="24.10.2"}"
# @internal
usage() {
print_help() {
debug "${FUNCNAME[0]}"
cat <<-'EOF'
Build and deploy OpenWRT images using convenient profiles.
USAGE:
openwrtbuilder [OPTIONS] [-p PROFILE]...
openwrtbuilder [OPTION [VALUE]]... -p PROFILE [-p PROFILE]...
OPTIONS
--profile,-p PROFILE
--release,-r,--version,-v RELEASE ("snapshot", "25.12.4")
Default: From profile or hardcoded RELEASE
--release,-r,--version,-v RELEASE ("snapshot", "22.03.5")
--buildroot,-b PATH
Default: location of openwrtbuilder script
--cpus,-c NUM
Default: # of host CPUS minus 1
--mode,-m imagebuilder|source
Default: imagebuilder
--clean clean|targetclean|dirclean|distclean
Optional clean step for source mode
--source
Build image from source, not from Image Builder
Allows make config options to be passed in profile
Uses git worktree for multi-profile deduplication
--ssh-upgrade HOST
Examples: root@192.168.1.1, root@router.lan
--ssh-backup SSH_PATH
Enabled by default for --ssh-upgrade
--flash,-f DEVICE
Example: /dev/sdX
--mirror PREFIX
Mirror prefix for feeds (default: github.com/openwrt)
--dl-timeout SECONDS
Per-file max download time for source builds (default: 300)
--reset
Cleanup all source and output files
--depends
Force dependency installation
--yes,-y
Assume yes for all questions (non-interactive)
Assume yes for all questions (automatic mode)
--debug,-d
--help,-h
EXAMPLES
openwrtbuilder -p r4s -r snapshot
openwrtbuilder -p ax6000 -r 23.05.0-rc3 --mode source --debug
openwrtbuilder -p rpi4 -r 25.12.4 --flash /dev/sdX
openwrtbuilder -p ax6000 -r 23.05.0-rc3 --source --debug
openwrtbuilder -p rpi4 -r 24.10.0 --flash /dev/sdX
openwrtbuilder -p linksys -r snapshot --ssh-upgrade root@192.168.1.1
EOF
}
@@ -63,14 +57,14 @@ init() {
# Save the script directory
# https://stackoverflow.com/a/4774063
SCRIPT_DIR=$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")
SCRIPT_DIR="$(cd -- "$(dirname "$0")" >/dev/null 2>&1 || exit $? ; pwd -P)"
if [[ -e "/etc/os-release" ]]; then
source "/etc/os-release"
else
echo "/etc/os-release not found"
echo "Your OS is unsupported"
usage
print_help
exit 1
fi
@@ -131,38 +125,34 @@ init() {
parse_input() {
debug "${FUNCNAME[0]}" "$*"
declare -ga PROFILES
declare -gi RESET=0 YES=0 DEBUG=0 FORCE_DEPENDS=0 CPUS=0
declare -g USER_RELEASE SSH_UPGRADE_PATH SSH_BACKUP_PATH FLASH_DEV USER_MODE USER_CLEAN USER_MIRROR USER_DL_TIMEOUT
local long_opts='release:,version:,profile:,buildroot:,cpus:,mode:,clean:,mirror:,dl-timeout:'
declare -gi RESET=0 FROM_SOURCE=0 YES=0 DEBUG=0 FORCE_DEPENDS=0
declare -g USER_RELEASE SSH_UPGRADE_PATH SSH_BACKUP_PATH FLASH_DEV
local long_opts='release:,version:,profile:,buildroot:,source,'
long_opts+='ssh-upgrade:,ssh-backup:,flash:,reset,depends,yes,debug,help'
if _input=$(getopt -o +r:v:p:b:m:c:f:ydh -l $long_opts -- "$@"); then
if _input=$(getopt -o +r:v:p:b:sf:ydh -l $long_opts -- "$@"); then
eval set -- "$_input"
while true; do
case "$1" in
--release|-r|--version|-v) shift; USER_RELEASE="$1" ;;
--profile|-p) shift; PROFILES+=("$1") ;;
--buildroot|-b) shift; BUILD_ROOT="$1" ;;
--mode|-m) shift; USER_MODE="$1" ;;
--clean) shift; USER_CLEAN="$1" ;;
--cpus|-c) shift; CPUS="$1" ;;
--source|-s) FROM_SOURCE=1 ;;
--ssh-upgrade) shift; SSH_UPGRADE_PATH="$1" ;;
--ssh-backup) shift; SSH_BACKUP_PATH="$1" ;;
--flash|-f) shift; FLASH_DEV="$1" ;;
--mirror) shift; USER_MIRROR="$1" ;;
--dl-timeout) shift; USER_DL_TIMEOUT="$1" ;;
--reset) RESET=1 ;;
--depends) FORCE_DEPENDS=1 ;;
--yes|-y) YES=1 ;;
--debug|-d) echo "Debugging on"; DEBUG=1 ;;
--help|-h) usage; exit 0 ;;
--help|-h) print_help; exit 0 ;;
--) shift; break ;;
esac
shift
done
else
echo "Incorrect options provided"
usage; exit 1
print_help; exit 1
fi
}
@@ -178,10 +168,10 @@ install_dependencies() {
if [[ "$mode" == "source" ]]; then
lock_file="$BUILD_ROOT/.dependencies_source.lock"
elif [[ "$mode" == "imagebuilder" ]]; then
lock_file="$BUILD_ROOT/.dependencies_imagebuilder.lock"
lock_file="$BUILD_ROOT/.dependencies_ib.lock"
fi
[[ -f $lock_file ]] && debug "$lock_file lock file exists, skipping dependency install" && return 0
[[ -f $lock_file ]] && debug "$lock_file lock file exists" && return 0
if [[ "$mode" == "source" ]]; then
# For building from source code see:
@@ -195,7 +185,6 @@ install_dependencies() {
gcc
gcc-c++
git
golang
llvm15-libs # for qosify
make
ncurses-devel
@@ -214,7 +203,6 @@ install_dependencies() {
python3-devel
python3-pyelftools
python3-setuptools
quilt
rsync
swig
tar
@@ -233,12 +221,10 @@ install_dependencies() {
gcc-multilib
gettext
git
golang
liblzma-dev
libncurses5-dev
libssl-dev
python3-distutils
quilt
rsync
patch
unzip
@@ -263,7 +249,6 @@ install_dependencies() {
gcc
gettext
git
golang
grep
groff
gzip
@@ -278,7 +263,6 @@ install_dependencies() {
patch
pkgconf
python
quilt
rsync
sed
texinfo
@@ -409,52 +393,31 @@ 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; ((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"
ROOTFS_FILESYSTEM="$FILESYSTEM"
FILES="$FILES_DIR"
--directory="$BUILD_DIR"
--jobs="$JOBS")
[[ -n "$rootfs_partsize" ]] && make_cmd+=("ROOTFS_PARTSIZE=$rootfs_partsize")
local -a make_opts
# 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"
@@ -463,10 +426,21 @@ make_images() {
# fi
# fi
# 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
((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="$(($(nproc) - 1))"
make "${make_opts[@]}" image \
BIN_DIR="$BIN_DIR" \
PROFILE="$DEVICE" \
PACKAGES="$PACKAGES" \
FILES="$FILES_DIR" \
--directory="$BUILD_DIR" \
--jobs="$(($(nproc) - 1))" \
> "$BUILD_DIR/make.log"
}
flash_images() {
@@ -474,8 +448,9 @@ flash_images() {
local img_gz="$1"
local dev="$2"
local img="${img_gz%.gz}"
local partitions
if [[ ! -b "$dev" ]]; then
if [[ ! -e "$dev" ]]; then
echo "The device specified by --flash could not be found"
return 1
fi
@@ -483,13 +458,13 @@ flash_images() {
[[ -f $img_gz ]] || { echo "$img_gz does not exist"; return 1; }
execute gunzip -qfk "$img_gz"
[[ -f "$img" ]] || { echo "Extracted image '$img' is missing"; return 1; }
echo "Unmounting target device $dev partitions"
partitions=("$dev"?*)
execute sudo umount "${partitions[@]}"
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!"
@@ -519,63 +494,24 @@ 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
# @arg $1 string .config seed URL
# @arg $2 string Profile name
# @arg $3 string Worktree ref (commit-ish or branch name)
from_source() {
debug "${FUNCNAME[0]}"
debug "${FUNCNAME[0]}" "$*"
local seed_url="$1"
local profile="$2"
local ref="$3"
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 kconfig commit description rootfs_kconfig
local -a make_opts
local worktree_meta="$SRC_DIR/.git/worktrees/source-$ref"
local pkg config commit seed_file description
local -a make_opts config_opts
echo "Building from source is under development"
# Convert filesystem to corresponding KCONFIG value
case "${FILESYSTEM,,}" in
squashfs) rootfs_kconfig="SQUASHFS" ;;
ext4|ext4fs) rootfs_kconfig="EXT4FS" ;;
ubifs) rootfs_kconfig="UBIFS" ;;
erofs) rootfs_kconfig="EROFS" ;;
jffs2) rootfs_kconfig="JFFS2" ;;
all) rootfs_kconfig="all";;
*) echo "Error: unsupported filesystem '$FILESYSTEM' for source mode"; return 1 ;;
esac
# Default KCONFIG options for all profiles (can be overridden by profile-specific KCONFIGS)
local -a kconfigs=(
"CONFIG_TARGET_${TARGET%%/*}=y"
"CONFIG_TARGET_${TARGET//\//_}=y"
"CONFIG_TARGET_PROFILE=DEVICE_$DEVICE"
"CONFIG_TARGET_${TARGET//\//_}_DEVICE_$DEVICE=y"
"CONFIG_TARGET_ROOTFS_SQUASHFS=n"
"CONFIG_TARGET_ROOTFS_EXT4FS=n"
"CONFIG_TARGET_ROOTFS_UBIFS=n"
"CONFIG_TARGET_ROOTFS_EROFS=n"
"CONFIG_TARGET_ROOTFS_JFFS2=n"
"CONFIG_TARGET_MULTI_PROFILE=n"
"CONFIG_BUILDBOT=n"
"CONFIG_ALL_KMODS=n"
"CONFIG_ALL_NONSHARED=n"
"CONFIG_DEVEL=n"
"CONFIG_COLLECT_KERNEL_DEBUG=n"
"CONFIG_SDK=n"
"CONFIG_SDK_LLVM_BPF=n"
"CONFIG_IB=n"
"CONFIG_MAKE_TOOLCHAIN=n"
"CONFIG_TARGET_PER_DEVICE_ROOTFS=n"
)
# Add KCONFIG for selected filesystem(s)
if [[ $rootfs_kconfig == "all" ]]; then
kconfigs+=("CONFIG_TARGET_ROOTFS_SQUASHFS=y"
"CONFIG_TARGET_ROOTFS_EXT4FS=y"
"CONFIG_TARGET_ROOTFS_UBIFS=y"
"CONFIG_TARGET_ROOTFS_EROFS=y"
"CONFIG_TARGET_ROOTFS_JFFS2=y")
else
kconfigs+=("CONFIG_TARGET_ROOTFS_${rootfs_kconfig}=y")
fi
# Remove all build directories and worktrees if --reset
# Remove all build directories and worktrees
if ((RESET)); then
if [[ -d "$BUILD_DIR" || -d "$worktree_meta" ]]; then
execute git -C "$SRC_DIR" worktree remove --force --force "$BUILD_DIR"
@@ -585,101 +521,24 @@ from_source() {
[[ -d "$BUILD_DIR" ]] && execute rm -rf "$BUILD_DIR"
fi
# Fetch or clone source repo (no local merges)
# Pull or clone source repo
if [[ -d "$SRC_DIR" ]]; then
execute git -C "$SRC_DIR" fetch origin --tags --prune
execute git -C "$SRC_DIR" pull
else
execute mkdir -p "$SRC_DIR"
execute git clone "$src_url" "$SRC_DIR"
fi
# Reuse worktree if present; otherwise create it (support branches and tags)
if git -C "$BUILD_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
execute git -C "$BUILD_DIR" fetch origin --tags --prune
execute git -C "$BUILD_DIR" reset --hard "origin/$REF" || \
execute git -C "$BUILD_DIR" reset --hard "$REF" || \
execute git -C "$BUILD_DIR" checkout --detach "$REF"
else
# Remove existing build dir and add new worktree
if [[ -d "$BUILD_DIR" ]]; then
execute rm -rf "$BUILD_DIR"
fi
execute git -C "$SRC_DIR" worktree prune --verbose
# Prefer local tag/branch if present, otherwise use remote-tracking branch
if ! execute git -C "$SRC_DIR" worktree add --detach "$BUILD_DIR" "$REF"; then
execute git -C "$SRC_DIR" worktree add --detach "$BUILD_DIR" "origin/$REF"
fi
fi
# Add cherrypicks
for cherrypick in $CHERRYPICKS; do
url_branch="${cherrypick%:*}"
commit="${cherrypick##*:}"
branch=""
url="$url_branch"
if [[ "$url_branch" == *"@"* ]]; then
url="${url_branch%@*}"
branch="${url_branch#*@}"
fi
remote="${url%.git}"
remote="${remote##*/}"
remote=${remote//[^A-Za-z0-9._-]/_}
[[ -z $remote ]] && remote="cherry"
if ! git -C "$BUILD_DIR" remote | grep -q "^$remote$"; then
execute git -C "$BUILD_DIR" remote add "$remote" "$url"
else
execute git -C "$BUILD_DIR" remote set-url "$remote" "$url"
fi
if [[ -n $branch ]]; then
execute git -C "$BUILD_DIR" fetch "$remote" "$branch"
else
execute git -C "$BUILD_DIR" fetch "$remote"
fi
# Verify commit exists before attempting cherry-pick
if ! git -C "$BUILD_DIR" cat-file -e "$commit^{commit}" 2>/dev/null; then
debug "Commit $commit not found after fetching from $remote; skipping"
continue
fi
execute git -C "$BUILD_DIR" merge-base --is-ancestor "$commit" HEAD ||
execute git -C "$BUILD_DIR" cherry-pick "$commit"
done
# Merge entire branches
for branch in $BRANCHES; do
url_branch="$branch"
branch=""
url="$url_branch"
if [[ "$url_branch" == *"@"* ]]; then
url="${url_branch%@*}"
branch="${url_branch#*@}"
fi
remote="${url%.git}"
remote="${remote##*/}"
remote=${remote//[^A-Za-z0-9._-]/_}
[[ -z $remote ]] && remote="merge"
if ! git -C "$BUILD_DIR" remote | grep -q "^$remote$"; then
execute git -C "$BUILD_DIR" remote add "$remote" "$url"
else
execute git -C "$BUILD_DIR" remote set-url "$remote" "$url"
fi
if [[ -n $branch ]]; then
execute git -C "$BUILD_DIR" fetch "$remote" "$branch"
echo "Merging $remote/$branch into $(git -C "$BUILD_DIR" rev-parse --abbrev-ref HEAD)"
execute git -C "$BUILD_DIR" merge --allow-unrelated-histories -m "Merge $remote/$branch" "$remote/$branch" || \
{ debug "Merge conflict or failed for $remote/$branch"; return 1; }
else
debug "Cannot merge: no branch specified in entry '$branch'"
continue
fi
done
execute git -C "$SRC_DIR" worktree add --detached "$BUILD_DIR" "$ref"
# Print commit info
commit=$(git -C "$BUILD_DIR" rev-parse HEAD)
description=$(git -C "$BUILD_DIR" describe --always --dirty)
description=$(git -C "$BUILD_DIR" describe)
echo "Current commit hash: $commit"
echo "Git worktree description: $description"
@@ -691,74 +550,86 @@ from_source() {
# Begin OpenWRT build process
((DEBUG)) && make_opts+=("V=sc")
# Cleanup build environment: heavy clean only when --reset was used earlier
# Cleanup build environment
execute make "${make_opts[@]}" "-j1" distclean
# make clean # compiled output
# make targetclean # compiled output, toolchain
# make dirclean # compiled output, toolchain, build tools
# make distclean # compiled output, toolchain, build tools, .config, feeds, .ccache
if [[ -n $CLEAN ]]; then
execute make "${make_opts[@]}" "-j1" "$CLEAN"
else
debug "Skipping cleanup step"
fi
# Use a custom (faster) mirror
local mirror_prefix="${USER_MIRROR:-github.com/openwrt}"
execute sed -i -E "s;git.openwrt.org/(feed|project);${mirror_prefix};" feeds.conf.default
# execute sed -i -E 's;git.openwrt.org/(feed|project);github.com/openwrt;' feeds.conf.default
# Update package feed
./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
# Grab the release seed config
if ! execute "$DL_TOOL" "-o" "$seed_file" "$seed_url"; then
echo "Could not obtain $seed_file from $seed_url"
return 1
fi
# Set compilation output dir
config_opts+=("CONFIG_BINARY_FOLDER=\"$BIN_DIR\"")
# Add custom packages
for pkg in $PACKAGES; do
if [[ $pkg == -* ]]; then
kconfigs+=("CONFIG_PACKAGE_${pkg#-}=n") # remove package
config_opts+=("CONFIG_PACKAGE_${pkg#-}=n") # remove package
else
kconfigs+=("CONFIG_PACKAGE_$pkg=y") # add package
config_opts+=("CONFIG_PACKAGE_$pkg=y") # add package
fi
done
# Add profile kconfig options
# $KCONFIGS is a scalar, use a loop to split and avoid SC2068
for kconfig in $KCONFIGS; do
kconfigs+=("$kconfig")
# Add config options from profile
for config in ${P_ARR[config]}; do
config_opts+=("$config")
done
# Reset and write options to config seed file
[[ -f $seed_file ]] && execute rm -f "$seed_file"
for kconfig in "${kconfigs[@]}"; do
debug "Writing $kconfig to $seed_file"
echo "$kconfig" >> "$seed_file"
# Only compile selected fs
execute sed -i '/CONFIG_TARGET_ROOTFS_/d' "$seed_file"
config_opts+=("CONFIG_TARGET_PER_DEVICE_ROOTFS=n")
if [[ $FILESYSTEM == "squashfs" ]]; then
config_opts+=("CONFIG_TARGET_ROOTFS_EXT4FS=n")
config_opts+=("CONFIG_TARGET_ROOTFS_SQUASHFS=y")
elif [[ $FILESYSTEM == "ext4" ]]; then
config_opts+=("CONFIG_TARGET_ROOTFS_SQUASHFS=n")
config_opts+=("CONFIG_TARGET_ROOTFS_EXT4FS=y")
fi
# Only compile selected target image
execute sed -i '/CONFIG_TARGET_DEVICE_/d' "$seed_file"
config_opts+=("CONFIG_TARGET_MULTI_PROFILE=n")
config_opts+=("CONFIG_TARGET_PROFILE=DEVICE_$DEVICE")
config_opts+=("CONFIG_TARGET_${TARGET//\//_}_DEVICE_$DEVICE=y")
config_opts+=("CONFIG_SDK=n")
config_opts+=("CONFIG_SDK_LLVM_BPF=n")
config_opts+=("CONFIG_IB=n")
config_opts+=("CONFIG_MAKE_TOOLCHAIN=n")
# Write options to config seed file
for config in "${config_opts[@]}"; do
debug "Writing $config to $seed_file"
echo "$config" >> "$seed_file"
done
# Expand seed into full config
# Serial make prep is more reliable
execute make "${make_opts[@]}" "-j1" defconfig
execute make "${make_opts[@]}" "-j1" download
# Run serial make download for better reliability
# CURL_EXTRA_ARGS is picked up by OpenWRT's scripts/download.pl
CURL_EXTRA_ARGS="--max-time ${USER_DL_TIMEOUT:-300}" execute make "${make_opts[@]}" "-j1" download
# (Optional) Disable multicore make world
# ((DEBUG)) && make_opts+=("-j1") || make_opts+=("-j$JOBS)")
make_opts+=("-j$JOBS")
# make_opts+=("-j$(($(nproc)-1))")
((DEBUG)) && make_opts+=("-j1") || make_opts+=("-j$(($(nproc)-1))")
# Make image
if ! ionice -c2 -n7 nice -n19 make "${make_opts[@]}" BIN_DIR="$BIN_DIR" world 2>&1 | tee "$BUILD_DIR/make.log"; then
echo "Error: make failed (see $BUILD_DIR/make.log)"
if ! execute ionice -c 3 chrt --idle 0 nice -n19 make "${make_opts[@]}" world; then
echo "Error: make failed"
return 1
fi
execute popd || return 1
# Symlink output images to root of BIN_DIR (match Image Builder behavior)
# Symlink output images to root of BIN_DIR (match Image Builder)
shopt -s nullglob
for image in "$BIN_DIR/targets/${TARGET}/"*.{img,img.gz,ubi}; do
execute ln -fs "$image" "$BIN_DIR/${image##*/}"
@@ -768,6 +639,32 @@ from_source() {
return 0
}
# @description Backs up a file to a chosen directory using its timestamp
# @arg $1 string File to backup
# @arg $2 string Directory to backup to
backup() {
debug "${FUNCNAME[0]}" "$*"
local file="$1" dir="$2"
local creation_date base_name backup_file
[[ -f $file ]] || return 1
[[ -d $dir ]] || execute mkdir -p "$dir" || { debug "Failed to create directory: $dir"; return 1; }
if creation_date=$(stat -c %w "$file" 2>/dev/null || stat -c %y "$file" 2>/dev/null) && \
[[ $creation_date != "-" && -n $creation_date ]] && \
creation_date=$(date -d "$creation_date" +%y%m%d%H%M 2>/dev/null); then
debug "Creation date: $creation_date"
else
creation_date="unknown"
debug "Unable to determine creation date, using 'unknown'"
fi
base_name="${file##*/}"
backup_file="$dir/$creation_date-$base_name"
[[ -f $backup_file ]] || execute cp --archive "$file" "$backup_file"
}
# @section Helper functions
# @internal
debug() { ((DEBUG)) && echo "Debug: $*"; }
@@ -818,6 +715,7 @@ 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
@@ -841,101 +739,73 @@ main() {
# Remove dependency lock files for --depends
if ((FORCE_DEPENDS)); then
[[ -f "$BUILD_ROOT/.dependencies_source.lock" ]] && rm -f "$BUILD_ROOT/.dependencies_source.lock"
[[ -f "$BUILD_ROOT/.dependencies_imagebuilder.lock" ]] && rm -f "$BUILD_ROOT/.dependencies_imagebuilder.lock"
[[ -f "$BUILD_ROOT/.dependencies_ib.lock" ]] && rm -f "$BUILD_ROOT/.dependencies_ib.lock"
fi
# Run selected profiles
for PROFILE in "${PROFILES[@]}"; do
debug "Running profile: $PROFILE"
for profile in "${PROFILES[@]}"; do
debug "Running profile: $profile"
if [[ ! ${!PROFILE@a} = A ]]; then
echo "Profile '$PROFILE' does not exist"
if [[ ! ${!profile@a} = A ]]; then
echo "Profile '$profile' does not exist"
return 1
fi
# Store profile in P_ARR nameref and set global profile vars
local -n P_ARR="$PROFILE"
declare -g REPO="${P_ARR[repo]:-}"
declare -g FILESYSTEM="${P_ARR[filesystem]:-squashfs}"
# Store profile in P_ARR nameref
local -n P_ARR="$profile"
local mode="${P_ARR[mode]:="imagebuilder"}"
((FROM_SOURCE)) && mode="source" # allow cli override
install_dependencies "$mode"
local repo="${P_ARR[repo]:-}"
declare -g FILESYSTEM="${P_ARR[filesystem]:="squashfs"}"
declare -g TARGET="${P_ARR[target]}"
declare -g DEVICE="${P_ARR[device]}"
declare -g MODE="${USER_MODE:-${P_ARR[mode]:-imagebuilder}}"
declare -g CLEAN="${USER_CLEAN:-${P_ARR[clean]:-}}"
declare -g PACKAGES="${P_ARR[packages]:-}" # scalar
declare -g CHERRYPICKS="${P_ARR[cherrypicks]:-}" # scalar
declare -g BRANCHES="${P_ARR[branches]:-}" # scalar
declare -g KCONFIGS="${P_ARR[kconfigs]:-}" # scalar
declare -g FILES_DIR="${P_ARR[files]:-$BUILD_ROOT/src/files}"
declare -g PACKAGES="${P_ARR[packages]:-}"
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
# pull in USER_RELEASE from args or profile default
local raw_release="${USER_RELEASE:=${P_ARR[release]:=$RELEASE}}"
install_dependencies "$MODE"
# Set number of parallel jobs for make and imagebuilder
declare -gi JOBS
if ((CPUS)); then
JOBS="$CPUS" # user overide (--cpus)
else
JOBS=$(nproc || echo 4) # fallback to quad-core if nproc fails
((JOBS > 1)) && JOBS=$((JOBS - 1)) # leave one CPU free
fi
# Normalize RELEASE and set REF committish
local raw_release="${USER_RELEASE:=${P_ARR[release]:=$DEFAULT_RELEASE}}"
declare -g RELEASE REF
read -r RELEASE REF < <(normalize_and_ref "$raw_release" "$MODE")
# single call to normalize+ref
read -r release ref < <(normalize_and_ref "$raw_release" "$mode")
declare -g SRC_DIR="$BUILD_ROOT/src/.openwrt"
declare -g BUILD_DIR="$BUILD_ROOT/src/$PROFILE/$REF-$MODE"
declare -g BIN_DIR="$BUILD_ROOT/bin/$PROFILE/$REF-$MODE"
declare -g BUILD_DIR="$BUILD_ROOT/src/$profile/$mode-$ref"
declare -g BIN_DIR="$BUILD_ROOT/bin/$profile/$mode-$ref"
if [[ "$RELEASE" == "snapshot" ]]; then
if [[ "$release" == "snapshot" ]]; then
local url_prefix="https://downloads.openwrt.org/snapshots/targets/$TARGET"
local url_filename="openwrt-imagebuilder-${TARGET//\//-}.Linux-x86_64.tar.zst"
local img_fname="openwrt-${TARGET//\//-}-$DEVICE-$FILESYSTEM"
else
local url_prefix="https://downloads.openwrt.org/releases/$RELEASE/targets/$TARGET"
local url_filename="openwrt-imagebuilder-$RELEASE-${TARGET//\//-}.Linux-x86_64.tar.zst"
local img_fname="openwrt-$RELEASE-${TARGET//\//-}-$DEVICE-$FILESYSTEM"
local url_prefix="https://downloads.openwrt.org/releases/$release/targets/$TARGET"
local url_filename="openwrt-imagebuilder-$release-${TARGET//\//-}.Linux-x86_64.tar.zst"
local img_fname="openwrt-$release-${TARGET//\//-}-$DEVICE-$FILESYSTEM"
fi
local imagebuilder_url="$url_prefix/$url_filename"
local imagebuilder_file="$BUILD_DIR/$url_filename"
local imagebuilder_sha256_url="$url_prefix/sha256sums"
local imagebuilder_sha256_file="$BUILD_DIR/sha256sums"
local ib_url="$url_prefix/$url_filename"
local ib_file="$BUILD_DIR/$url_filename"
local ib_sha256_url="$url_prefix/sha256sums"
local ib_sha256_file="$BUILD_DIR/sha256sums"
local seed_url="$url_prefix/config.buildinfo"
if [[ "$MODE" == "source" ]]; then
if [[ "$mode" == "source" ]]; then
declare -g SYSUPGRADEIMGGZ="$BIN_DIR/targets/$TARGET/$img_fname-sysupgrade.img.gz"
else
declare -g SYSUPGRADEIMGGZ="$BUILD_DIR/$img_fname-sysupgrade.img.gz"
fi
# Backup existing output directory
if [[ -d "$BIN_DIR" ]]; then
local timestamp
timestamp=$(date +%y%m%d%H%M)
execute mkdir -p "$BACKUP_DIR/$PROFILE/$REF-$MODE-$timestamp"
execute rsync -a --delete --exclude 'packages/' "$BIN_DIR/" "$BACKUP_DIR/$PROFILE/$REF-$MODE-$timestamp/"
fi
backup "$SYSUPGRADEIMGGZ" "$BACKUP_DIR/$profile/$mode-$ref"
if [[ "$MODE" == "source" ]]; then
from_source || return $?
elif [[ "$MODE" == "imagebuilder" ]]; then
if [[ "$mode" == "source" ]]; then
from_source "$seed_url" "$profile" "$ref" || return $?
elif [[ "$mode" == "imagebuilder" ]]; then
[[ -d $BUILD_DIR ]] || mkdir -p "$BUILD_DIR"
get_imagebuilder "$imagebuilder_url" "$imagebuilder_file" "$imagebuilder_sha256_url" "$imagebuilder_sha256_file" &&
verify "$imagebuilder_file" "$imagebuilder_sha256_file" &&
extract "$imagebuilder_file" "$BUILD_DIR" || return $?
# Add external repositories for the Image Builder build
if [[ -n $REPO ]]; then
if ! grep -q "$REPO" "$BUILD_DIR/repositories.conf"; then
echo "$REPO" >> "$BUILD_DIR/repositories.conf"
get_imagebuilder "$ib_url" "$ib_file" "$ib_sha256_url" "$ib_sha256_file" &&
verify "$ib_file" "$ib_sha256_file" &&
extract "$ib_file" "$BUILD_DIR" || return $?
if [[ -v $repo ]]; then
if ! grep -q "$repo" "$BUILD_DIR/repositories.conf"; then
echo "$repo" >> "$BUILD_DIR/repositories.conf"
fi
sed -i '/option check_signature/d' "$BUILD_DIR/repositories.conf"
fi
@@ -946,7 +816,7 @@ main() {
local -a outfiles=("$BIN_DIR"/*.img.gz "$BIN_DIR"/*.img)
shopt -u nullglob
for outfile in "${outfiles[@]}"; do
verify "$outfile" "$imagebuilder_sha256_file" || return 1
verify "$outfile" "$ib_sha256_file" || return 1
done
fi
#copyFiles
@@ -958,9 +828,5 @@ main() {
done
}
# Roughly turn debugging on for pre-init
# Reset and reparse in parse_input() with getopt
[[ " $* " =~ ( --debug | -d ) ]] && DEBUG=1
main "$@"
exit

192
profiles
View File

@@ -1,161 +1,67 @@
#!/usr/bin/env bash
# Device profiles for openwrtbuilder
# shellcheck disable=SC2034
# Device profiles for openwrtbuilder
DEFAULT_RELEASE="25.12.4" # overrides default release in openwrtbuilder
# Default packages (precede with "-" to exclude)
default_packages=(
ca-bundle base-files apk-mbedtls libustream-mbedtls openssh-sftp-server dropbear
fstools libc libgcc logd mtd netifd
nano vim htop diffutils tar iperf3 zsh rsync tcpdump ethtool
odhcp6c ppp ppp-mod-pppoe procd-ujail
uboot-envtools uci uclient-fetch urandom-seed urngd
luci luci-ssl luci-app-statistics luci-app-filemanager luci-app-attendedsysupgrade
lm-sensors collectd-mod-sensors collectd-mod-thermal collectd-mod-conntrack collectd-mod-cpu
tailscale
)
default_router=("${default_packages[@]}"
dnsmasq odhcpd-ipv6only nftables firewall4
luci-proto-wireguard luci-app-sqm luci-app-watchcat
adblock luci-app-adblock
kmod-nft-offload
)
default_ap=("${default_packages[@]}"
-dnsmasq -odhcpd-ipv6only -nftables -firewall4
-kmod-nft-offload
)
# Default kernel configs
default_kconfigs=(
)
# Default packages
default_packages="luci luci-ssl luci-proto-wireguard luci-app-statistics \
collectd-mod-sensors collectd-mod-thermal collectd-mod-conntrack \
collectd-mod-cpu nano htop diffutils tar iperf3 zsh rsync \
openssh-sftp-server"
# Current devices
# Nanopi R4S router w/ btrfs
declare -Ag router=(
declare -Ag r4s=(
[mode]="source"
[device]="friendlyarm_nanopi-r4s"
[target]="rockchip/armv8"
[filesystem]="ext4"
[packages]="${default_router[*]} \
kmod-r8169 \
[packages]="$default_packages luci-app-ddns luci-app-sqm irqbalance \
collectd-mod-df usbutils kmod-usb-storage kmod-usb-storage-uas \
kmod-fs-btrfs btrfs-progs block-mount \
smcroute avahi-daemon"
[kconfigs]="${default_kconfigs[*]} \
kmod-fs-btrfs btrfs-progs block-mount smcroute avahi-daemon \
curl ethtool ca-bundle tailscale"
[config]="CONFIG_KERNEL_BTRFS_FS_POSIX_ACL=y CONFIG_BTRFS_PROGS_ZSTD=y \
CONFIG_TARGET_ROOTFS_PARTSIZE=512 CONFIG_TARGET_KERNEL_PARTSIZE=32 \
CONFIG_KERNEL_BTRFS_FS_POSIX_ACL=y CONFIG_BTRFS_PROGS_ZSTD=y"
CONFIG_BUILDBOT=n"
[files]="/mnt/backup"
)
# Redmi AX6000 router w/ stock layout in full router mode
declare -Ag abby_router=(
declare -Ag ax6000=(
[mode]="imagebuilder"
[device]="xiaomi_redmi-router-ax6000-stock"
[target]="mediatek/filogic"
[release]="snapshot"
[filesystem]="squashfs"
[packages]="${default_router[*]} \
wpad-basic-mbedtls \
kmod-leds-ws2812b kmod-mt7915e \
kmod-mt7986-firmware mt7986-wo-firmware"
[packages]="$default_packages -dnsmasq -odhcpd-ipv6only -nftables -firewall4 tailscale"
)
declare -Ag ax6000_uboot_ap=(
declare -Ag ax6000_uboot=(
[mode]="imagebuilder"
[device]="xiaomi_redmi-router-ax6000-ubootmod"
[target]="mediatek/filogic"
[release]="snapshot"
[filesystem]="squashfs"
[packages]="${default_ap[*]} \
wpad-basic-mbedtls \
kmod-leds-ws2812b kmod-mt7915e \
kmod-mt7986-firmware mt7986-wo-firmware"
[packages]="$default_packages -dnsmasq -odhcpd-ipv6only -nftables -firewall4"
)
# Testing
declare -Ag w1700k_ap=(
[mode]="source"
[device]="gemtek_w1700k-ubi"
[target]="airoha/an7581"
declare -Ag n5100=(
[device]="generic"
[target]="x86/64"
[filesystem]="squashfs"
[release]="snapshot"
[packages]="${default_ap[*]} \
wpad-basic-mbedtls libiwinfo-data \
kmod-gpio-button-hotplug kmod-leds-gpio \
airoha-en7581-npu-firmware airoha-en7581-mt7996-npu-firmware \
kmod-i2c-an7581 kmod-hwmon-nct7802 kmod-mt7996-firmware kmod-phy-rtl8261n \
fitblk"
)
declare -Ag w1700k_ap_fanboy=(
[mode]="source"
[device]="gemtek_w1700k-ubi"
[target]="airoha/an7581"
[filesystem]="squashfs"
[release]="snapshot"
[packages]="${default_ap[*]} \
wpad-basic-mbedtls libiwinfo-data \
kmod-gpio-button-hotplug kmod-leds-gpio \
airoha-en7581-npu-firmware airoha-en7581-mt7996-npu-firmware \
kmod-i2c-an7581 kmod-hwmon-nct7802 kmod-mt7996-firmware kmod-phy-rtl8261n \
fitblk"
[branches]="https://github.com/OpenWRT-fanboy/OpenW1700k.git@ubi2"
)
declare -Ag w1700k=(
[mode]="source"
[device]="gemtek_w1700k-ubi"
[target]="airoha/an7581"
[filesystem]="squashfs"
[release]="snapshot"
[packages]="${default_router[*]} \
wpad-basic-mbedtls libiwinfo-data \
kmod-gpio-button-hotplug kmod-leds-gpio \
airoha-en7581-npu-firmware airoha-en7581-mt7996-npu-firmware \
kmod-i2c-an7581 kmod-hwmon-nct7802 kmod-mt7996-firmware kmod-phy-rtl8261n \
fitblk"
# tools: m4: update to 1.4.21 (fixes GCC15/C23 _Generic build failure)
# [cherrypicks]="https://github.com/openwrt/openwrt@main:ce9a0ff3fb88d037080aaf95af92ac5da4fcfdba"
)
# Deprecated: Last working profile for w1700k with stock (non-ubi) partitions
declare -Ag w1700k_fanboy=(
[mode]="source"
[device]="gemtek_w1700k-ubi"
[target]="airoha/an7581"
[filesystem]="squashfs"
[release]="snapshot"
[packages]="${default_router[*]} \
wpad-basic-mbedtls libiwinfo-data \
kmod-gpio-button-hotplug kmod-leds-gpio \
airoha-en7581-npu-firmware airoha-en7581-mt7996-npu-firmware \
kmod-i2c-an7581 kmod-hwmon-nct7802 kmod-mt7996-firmware kmod-phy-rtl8261n \
fitblk"
# [cherrypicks]="\
# https://github.com/OpenWRT-fanboy/OpenW1700k.git@lumos:8d449e968cfaa774ab7a219b3a5ab4251b2f9352 \
# https://github.com/OpenWRT-fanboy/OpenW1700k.git@lumos:3033241393ef6eb562539c6a3ccb9d3cf1a25d05 \
# https://github.com/OpenWRT-fanboy/OpenW1700k.git@lumos:79a21e0986a9efe6de3a07394a71ac15a2107b16 \
# https://github.com/OpenWRT-fanboy/OpenW1700k.git@lumos:2f8a1cbf901df0d325dfe112fdfe8013a72c8305 \
# https://github.com/OpenWRT-fanboy/OpenW1700k.git@lumos:71b09bc5852797cdbf7cb3b56a7d8fcd9d4ca9db \
# https://github.com/OpenWRT-fanboy/OpenW1700k.git@lumos:fe0135f0b7037a9cc1985d5937dd24cb99bfccb1 \
# https://github.com/OpenWRT-fanboy/OpenW1700k.git@lumos:cdb937180fb971fe702078f0e0fef63f2fcce337 \
# https://github.com/OpenWRT-fanboy/OpenW1700k.git@lumos:6dc847c802b9dc597fc2c64711ca85499f128d1d \
# https://github.com/OpenWRT-fanboy/OpenW1700k.git@lumos:b6e6cf911915dd987eecde908a2013419565cff4 \
# https://github.com/OpenWRT-fanboy/OpenW1700k.git@lumos:708089948949e66f5234249fc631e0453b58942e \
# 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"
[packages]="$default_packages luci-app-ddns irqbalance collectd-mod-df \
usbutils kmod-usb-storage kmod-usb-storage-uas kmod-fs-btrfs \
btrfs-progs block-mount cryptsetup kmod-crypto-xts smcroute \
avahi-daemon curl ethtool ca-bundle smartmontools intel-microcode \
lm-sensors samba4-server luci-app-samba4 tailscale shadow-useradd"
[config]="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 rpi4=(
[device]="rpi-4"
[target]="bcm27xx/bcm2711"
[filesystem]="ext4"
[packages]="${default_router[*]} \
luci-app-pbr -dnsmasq dnsmasq-full \
kmod-usb-net-asix-ax88179 kmod-usb-net-rtl8152"
[packages]="$default_packages kmod-usb-net-asix-ax88179 kmod-usb-net-rtl8152 \
luci-app-upnp luci-app-pbr -dnsmasq dnsmasq-full luci-app-ddns luci-app-sqm"
)
declare -Ag r4s_stock=(
@@ -165,34 +71,19 @@ declare -Ag r4s_stock=(
[release]="snapshot"
)
# Retired devices
declare -Ag n5100=(
[device]="generic"
[target]="x86/64"
[filesystem]="squashfs"
[packages]="${default_router[*]} \
irqbalance collectd-mod-df \
usbutils kmod-usb-storage kmod-usb-storage-uas kmod-fs-btrfs \
btrfs-progs block-mount cryptsetup kmod-crypto-xts smcroute \
avahi-daemon smartmontools intel-microcode \
samba4-server luci-app-samba4 shadow-useradd"
[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"
)
declare -Ag totolink=(
[device]="totolink_x5000r"
[target]="ramips/mt7621"
[filesystem]="squashfs"
[packages]="${default_ap[*]}"
[packages]="$default_packages -dnsmasq -odhcpd-ipv6only -nftables -firewall4 \
-kmod-nft-offload collectd-mod-iwinfo"
)
declare -Ag archer=(
[device]="tplink_archer-c7-v2"
[target]="ath79/generic"
[filesystem]="squashfs"
[packages]="${default_ap[*]} \
[packages]="$default_packages -dnsmasq -odhcpd -iptables \
-ath10k-firmware-qca988x-ct ath10k-firmware-qca988x-ct-full-htt"
)
@@ -200,24 +91,23 @@ declare -Ag linksys=(
[device]="linksys_ea8300"
[target]="ipq40xx/generic"
[filesystem]="squashfs"
[packages]="${default_ap[*]}"
[packages]="$default_packages -dnsmasq -odhcpd -iptables"
)
declare -Ag r2s=(
[device]="friendlyarm_nanopi-r2s"
[target]="rockchip/armv8"
[filesystem]="ext4"
[packages]="${default_router[*]} \
kmod-usb-net-rtl8152 \
luci-app-upnp luci-app-pbr -dnsmasq dnsmasq-full smcroute"
[packages]="$default_packages luci-app-upnp luci-app-pbr -dnsmasq dnsmasq-full \
luci-app-ddns luci-app-sqm luci-app-statistics collectd-mod-sensors \
collectd-mod-thermal collectd-mod-conntrack smcroute curl ethtool"
)
declare -Ag r2s_tr=(
[device]="friendlyarm_nanopi-r2s"
[target]="rockchip/armv8"
[filesystem]="ext4"
[packages]="${default_router[*]} \
kmod-usb-net-rtl8152 \
luci-app-upnp luci-app-pbr -dnsmasq dnsmasq-full \
travelmate"
[packages]="$default_packages luci-app-upnp luci-app-pbr luci-app-ddns \
luci-app-statistics collectd-mod-sensors collectd-mod-thermal \
collectd-mod-conntrack curl ethtool travelmate"
)