Compare commits
1 Commits
master
...
251b54937b
| Author | SHA1 | Date | |
|---|---|---|---|
| 251b54937b |
14
README.md
14
README.md
@@ -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,13 +37,13 @@ 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`.
|
||||
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 23.05.5 --mode source --debug`
|
||||
* `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`
|
||||
|
||||
|
||||
366
openwrtbuilder
366
openwrtbuilder
@@ -1,11 +1,10 @@
|
||||
#!/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
|
||||
# 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:="24.10.5"}}"
|
||||
: "${RELEASE:="24.10.2"}"
|
||||
|
||||
# @internal
|
||||
print_help() {
|
||||
@@ -19,26 +18,25 @@ print_help() {
|
||||
|
||||
OPTIONS
|
||||
--profile,-p PROFILE
|
||||
--release,-r,--version,-v RELEASE ("snapshot", "24.10.5")
|
||||
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
|
||||
--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
|
||||
|
||||
@@ -59,7 +57,7 @@ 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"
|
||||
@@ -127,21 +125,19 @@ 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
|
||||
local long_opts='release:,version:,profile:,buildroot:,cpus:,mode:,clean:'
|
||||
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" ;;
|
||||
@@ -172,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 but skipping for --debug" && return 0
|
||||
[[ -f $lock_file ]] && debug "$lock_file lock file exists" && return 0
|
||||
|
||||
if [[ "$mode" == "source" ]]; then
|
||||
# For building from source code see:
|
||||
@@ -189,7 +185,6 @@ install_dependencies() {
|
||||
gcc
|
||||
gcc-c++
|
||||
git
|
||||
golang
|
||||
llvm15-libs # for qosify
|
||||
make
|
||||
ncurses-devel
|
||||
@@ -208,7 +203,6 @@ install_dependencies() {
|
||||
python3-devel
|
||||
python3-pyelftools
|
||||
python3-setuptools
|
||||
quilt
|
||||
rsync
|
||||
swig
|
||||
tar
|
||||
@@ -227,12 +221,10 @@ install_dependencies() {
|
||||
gcc-multilib
|
||||
gettext
|
||||
git
|
||||
golang
|
||||
liblzma-dev
|
||||
libncurses5-dev
|
||||
libssl-dev
|
||||
python3-distutils
|
||||
quilt
|
||||
rsync
|
||||
patch
|
||||
unzip
|
||||
@@ -257,7 +249,6 @@ install_dependencies() {
|
||||
gcc
|
||||
gettext
|
||||
git
|
||||
golang
|
||||
grep
|
||||
groff
|
||||
gzip
|
||||
@@ -272,7 +263,6 @@ install_dependencies() {
|
||||
patch
|
||||
pkgconf
|
||||
python
|
||||
quilt
|
||||
rsync
|
||||
sed
|
||||
texinfo
|
||||
@@ -441,7 +431,7 @@ make_images() {
|
||||
debug make "${make_opts[@]}" image BIN_DIR="$BIN_DIR" \
|
||||
PROFILE="$DEVICE" PACKAGES="$PACKAGES" \
|
||||
FILES="$FILES_DIR" --directory="$BUILD_DIR" \
|
||||
--jobs="$JOBS"
|
||||
--jobs="$(($(nproc) - 1))"
|
||||
|
||||
make "${make_opts[@]}" image \
|
||||
BIN_DIR="$BIN_DIR" \
|
||||
@@ -449,7 +439,7 @@ make_images() {
|
||||
PACKAGES="$PACKAGES" \
|
||||
FILES="$FILES_DIR" \
|
||||
--directory="$BUILD_DIR" \
|
||||
--jobs="$JOBS" \
|
||||
--jobs="$(($(nproc) - 1))" \
|
||||
> "$BUILD_DIR/make.log"
|
||||
}
|
||||
|
||||
@@ -505,35 +495,23 @@ 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 config commit description
|
||||
local -a make_opts
|
||||
local -a config_opts=(
|
||||
"CONFIG_TARGET_${TARGET%%/*}=y"
|
||||
"CONFIG_TARGET_${TARGET//\//_}=y"
|
||||
"CONFIG_TARGET_PROFILE=DEVICE_$DEVICE"
|
||||
"CONFIG_TARGET_${TARGET//\//_}_DEVICE_$DEVICE=y"
|
||||
"CONFIG_TARGET_ROOTFS_${FILESYSTEM^^}=y"
|
||||
"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"
|
||||
)
|
||||
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"
|
||||
|
||||
# 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"
|
||||
@@ -543,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
|
||||
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
|
||||
# Remove existing build dir and add new worktree
|
||||
if [[ -d "$BUILD_DIR" ]]; then
|
||||
execute rm -rf "$BUILD_DIR"
|
||||
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 prune --verbose
|
||||
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"
|
||||
|
||||
@@ -649,24 +550,29 @@ 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
|
||||
execute sed -i -E 's;git.openwrt.org/(feed|project);github.com/openwrt;' 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
|
||||
|
||||
# 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
|
||||
@@ -676,37 +582,54 @@ from_source() {
|
||||
fi
|
||||
done
|
||||
|
||||
# Add profile config options
|
||||
for config in $CONFIGS; do
|
||||
# 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"
|
||||
# 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
|
||||
|
||||
# Run serial make download for better reliability
|
||||
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 ! execute ionice -c2 -n7 nice -n19 make "${make_opts[@]}" BIN_DIR="$BIN_DIR" world; then
|
||||
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##*/}"
|
||||
@@ -716,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: $*"; }
|
||||
@@ -790,92 +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]:-}"
|
||||
# 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 CONFIGS="${P_ARR[configs]:-}" # scalar
|
||||
declare -g PACKAGES="${P_ARR[packages]:-}"
|
||||
|
||||
install_dependencies "$MODE"
|
||||
# pull in USER_RELEASE from args or profile default
|
||||
local raw_release="${USER_RELEASE:=${P_ARR[release]:=$RELEASE}}"
|
||||
|
||||
# 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
|
||||
@@ -886,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
|
||||
@@ -898,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
|
||||
|
||||
111
profiles
111
profiles
@@ -1,20 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
# Device profiles for openwrtbuilder
|
||||
# shellcheck disable=SC2034
|
||||
# Device profiles for openwrtbuilder
|
||||
|
||||
DEFAULT_RELEASE="25.12.0-rc4" # overrides default release in openwrtbuilder
|
||||
|
||||
# Default packages (precede with "-" to exclude)
|
||||
default_packages=(
|
||||
ca-bundle nano vim htop diffutils tar iperf3 zsh rsync tcpdump ethtool
|
||||
openssh-sftp-server
|
||||
luci luci-ssl luci-proto-wireguard luci-app-statistics luci-app-filemanager
|
||||
collectd-mod-sensors collectd-mod-thermal collectd-mod-conntrack collectd-mod-cpu
|
||||
)
|
||||
|
||||
# Default kernel configs
|
||||
default_configs=(
|
||||
)
|
||||
# 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
|
||||
declare -Ag r4s=(
|
||||
@@ -22,28 +14,23 @@ declare -Ag r4s=(
|
||||
[device]="friendlyarm_nanopi-r4s"
|
||||
[target]="rockchip/armv8"
|
||||
[filesystem]="ext4"
|
||||
[packages]="${default_packages[*]} \
|
||||
adblock luci-app-adblock \
|
||||
irqbalance luci-app-irqbalance \
|
||||
[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 \
|
||||
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"
|
||||
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_BUILDBOT=n"
|
||||
[files]="/mnt/backup"
|
||||
# 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
|
||||
)
|
||||
|
||||
declare -Ag ax6000=(
|
||||
[mode]="imagebuilder"
|
||||
[device]="xiaomi_redmi-router-ax6000-stock"
|
||||
[target]="mediatek/filogic"
|
||||
[release]="snapshot"
|
||||
[filesystem]="squashfs"
|
||||
[packages]="${default_packages[*]} \
|
||||
tailscale"
|
||||
[packages]="$default_packages -dnsmasq -odhcpd-ipv6only -nftables -firewall4 tailscale"
|
||||
)
|
||||
|
||||
declare -Ag ax6000_uboot=(
|
||||
@@ -52,75 +39,29 @@ declare -Ag ax6000_uboot=(
|
||||
[target]="mediatek/filogic"
|
||||
[release]="snapshot"
|
||||
[filesystem]="squashfs"
|
||||
[packages]="${default_packages[*]} \
|
||||
-dnsmasq -odhcpd-ipv6only -nftables -firewall4"
|
||||
[packages]="$default_packages -dnsmasq -odhcpd-ipv6only -nftables -firewall4"
|
||||
)
|
||||
|
||||
declare -Ag n5100=(
|
||||
[device]="generic"
|
||||
[target]="x86/64"
|
||||
[filesystem]="squashfs"
|
||||
[packages]="${default_packages[*]} \
|
||||
luci-app-ddns irqbalance collectd-mod-df \
|
||||
[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 ethtool ca-bundle smartmontools intel-microcode \
|
||||
avahi-daemon curl ethtool ca-bundle smartmontools intel-microcode \
|
||||
lm-sensors samba4-server luci-app-samba4 tailscale shadow-useradd"
|
||||
[configs]="${default_configs[*]} \
|
||||
CONFIG_KERNEL_BTRFS_FS_POSIX_ACL=y CONFIG_BTRFS_PROGS_ZSTD=y \
|
||||
[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 w1700k=(
|
||||
[mode]="source"
|
||||
[device]="gemtek_w1700k"
|
||||
[target]="airoha/an7581"
|
||||
[filesystem]="squashfs"
|
||||
[release]="snapshot"
|
||||
[packages]="${default_packages[*]} \
|
||||
luci-app-sqm \
|
||||
smcroute avahi-daemon \
|
||||
lm-sensors samba4-server luci-app-samba4 shadow-useradd \
|
||||
ca-bundle tailscale"
|
||||
# [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"
|
||||
)
|
||||
|
||||
declare -Ag w1700k_ap=(
|
||||
[mode]="source"
|
||||
[device]="gemtek_w1700k"
|
||||
[target]="airoha/an7581"
|
||||
[filesystem]="squashfs"
|
||||
[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"
|
||||
)
|
||||
|
||||
declare -Ag rpi4=(
|
||||
[device]="rpi-4"
|
||||
[target]="bcm27xx/bcm2711"
|
||||
[filesystem]="ext4"
|
||||
[packages]="${default_packages[*]} \
|
||||
luci-app-upnp luci-app-pbr -dnsmasq dnsmasq-full luci-app-ddns luci-app-sqm \
|
||||
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=(
|
||||
@@ -134,8 +75,7 @@ declare -Ag totolink=(
|
||||
[device]="totolink_x5000r"
|
||||
[target]="ramips/mt7621"
|
||||
[filesystem]="squashfs"
|
||||
[packages]="${default_packages[*]} \
|
||||
-dnsmasq -odhcpd-ipv6only -nftables -firewall4 \
|
||||
[packages]="$default_packages -dnsmasq -odhcpd-ipv6only -nftables -firewall4 \
|
||||
-kmod-nft-offload collectd-mod-iwinfo"
|
||||
)
|
||||
|
||||
@@ -143,7 +83,7 @@ declare -Ag archer=(
|
||||
[device]="tplink_archer-c7-v2"
|
||||
[target]="ath79/generic"
|
||||
[filesystem]="squashfs"
|
||||
[packages]="${default_packages[*]} -dnsmasq -odhcpd -iptables \
|
||||
[packages]="$default_packages -dnsmasq -odhcpd -iptables \
|
||||
-ath10k-firmware-qca988x-ct ath10k-firmware-qca988x-ct-full-htt"
|
||||
)
|
||||
|
||||
@@ -151,16 +91,14 @@ declare -Ag linksys=(
|
||||
[device]="linksys_ea8300"
|
||||
[target]="ipq40xx/generic"
|
||||
[filesystem]="squashfs"
|
||||
[packages]="${default_packages[*]} \
|
||||
-dnsmasq -odhcpd -iptables"
|
||||
[packages]="$default_packages -dnsmasq -odhcpd -iptables"
|
||||
)
|
||||
|
||||
declare -Ag r2s=(
|
||||
[device]="friendlyarm_nanopi-r2s"
|
||||
[target]="rockchip/armv8"
|
||||
[filesystem]="ext4"
|
||||
[packages]="${default_packages[*]} \
|
||||
luci-app-upnp luci-app-pbr -dnsmasq dnsmasq-full \
|
||||
[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"
|
||||
)
|
||||
@@ -169,8 +107,7 @@ declare -Ag r2s_tr=(
|
||||
[device]="friendlyarm_nanopi-r2s"
|
||||
[target]="rockchip/armv8"
|
||||
[filesystem]="ext4"
|
||||
[packages]="${default_packages[*]} \
|
||||
luci-app-upnp luci-app-pbr luci-app-ddns \
|
||||
[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"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user