Compare commits

...

100 Commits

Author SHA1 Message Date
5b9f1f2f39 Re-add specific device config 2025-10-23 16:46:16 -04:00
c5bfc7907b Remove specific device config 2025-10-23 16:43:34 -04:00
533b0b5ffc Re-add specific device config 2025-10-23 16:34:37 -04:00
eba54804d3 Blank the seed file 2025-10-23 16:31:34 -04:00
09b62923a8 Re-add specific device config 2025-10-23 16:19:58 -04:00
960755e6a2 Use faster feeds mirror 2025-10-22 21:16:41 -04:00
0fa9b0d85a Streamling config options 2025-10-22 21:02:36 -04:00
4de18e6696 Add optional build clean arg to --source 2025-10-22 20:55:20 -04:00
3772d373bb Tune resource limits 2025-10-22 20:27:21 -04:00
b75597946d Improve worktree detection 2025-10-22 19:35:38 -04:00
018a91e216 Introduce reusable worktrees 2025-10-22 19:31:58 -04:00
0c61a27b06 Reorganize from_source() 2025-10-22 19:25:59 -04:00
675ed5eb39 Abandon upstream seed, untenable 2025-10-22 19:11:51 -04:00
94f60e30b1 Pass BIN_DIR to make and not .config 2025-10-22 15:46:06 -04:00
e8ccb76cc6 Remove more default buildbot configs 2025-10-21 23:58:35 -04:00
4274f876a7 Remove more default buildbot configs 2025-10-21 20:40:19 -04:00
4760c84bff Remove more default buildbot configs 2025-10-21 20:35:38 -04:00
20b3f7f4ec Strip CONFIG_ALL_KMODS 2025-10-21 10:45:18 -04:00
f178e39a28 Use CONFIG_ALL_KMODS=n in global profile 2025-10-20 16:31:48 -04:00
c7b954252d Fetch worktree branch instead of pull 2025-10-19 15:21:53 -04:00
18929109a2 Omit oldconfig step 2025-10-18 21:17:35 -04:00
8d24cb96a9 Switch to canonical make order 2025-10-18 12:27:40 -04:00
9be43af11a Make olddefconfig non-interactive 2025-10-18 11:33:04 -04:00
ce2e85d197 Attempt one step olddefconfig 2025-10-18 11:30:42 -04:00
aeead798c3 Test explicit branch 2025-09-23 16:12:57 -04:00
72355bb65a Use fetch --all to grab wt breanches 2025-09-23 15:37:13 -04:00
3053b24063 Update default release 2025-09-23 15:13:35 -04:00
186fe21d73 Update profiles 2025-09-10 19:29:56 -04:00
d63a909d54 Simplify script dir ID 2025-09-09 16:57:22 -04:00
9128c453f3 Move pfring exclusions to r4s 2025-08-19 16:54:27 -04:00
ffbd193b79 Clarify skipping lock files for --debug 2025-08-19 16:38:03 -04:00
5259c72de4 Exclude pfring kmods 2025-08-18 07:43:09 -04:00
045f43b51f Exclude more pfring packages 2025-08-15 16:53:59 -04:00
89cc3cddeb Exclude problematic packages 2025-08-13 17:34:37 -04:00
cd7449dd7c Re-disable multicore make 2025-08-11 17:44:04 -04:00
2b35e1e017 Re-enable multicore make 2025-08-11 17:10:20 -04:00
983f9ecb04 Exclude libpfring to fix compilation 2025-08-11 15:50:20 -04:00
b5f567ce2b Attempt to mix yes and execute() 2025-08-09 00:01:34 -04:00
a16e713895 Use canonincal method for now 2025-08-08 23:56:28 -04:00
70d24d7fae Replace defconfig with oldconfig 2025-08-08 22:33:30 -04:00
d5069d4c40 Add golang dependency 2025-08-08 22:24:39 -04:00
718b29cfe8 Try to omit oldconfig 2025-08-08 22:22:35 -04:00
e3ce0b6e57 Make oldconfig to prevent upstream clobbers 2025-08-08 20:50:07 -04:00
3ba76a4e8d Add early debugging 2025-08-08 19:48:53 -04:00
4f1f145a10 Fix comments 2025-08-08 14:33:50 -04:00
2123205ca0 Reformat profiles 2025-08-08 14:30:31 -04:00
e510f8ccb6 Don't build unecessary kmods 2025-08-08 14:20:50 -04:00
da398172e8 Workaround libpfring issue #26569 2025-08-06 21:10:36 -04:00
12067ac09b Disable cherrypicks by default since branch-specific 2025-08-06 21:06:25 -04:00
cf2c35b114 Specify fork with cherrypick 2025-08-06 21:01:08 -04:00
5629472aa3 Support cherrypicks 2025-08-06 20:55:59 -04:00
a7a85ee67a Use --detached worktrees 2025-08-05 14:14:16 -04:00
4890aa192d Cleanup some comments 2025-07-29 17:40:02 -04:00
819ff0add0 Update README 2025-07-29 02:13:55 -04:00
149da1be87 Update README 2025-07-29 02:12:03 -04:00
6f1bc4dd00 SHow more commit info 2025-07-29 02:01:52 -04:00
5d434f031d Remove extraneous normalize_and_ref output 2025-07-29 01:58:37 -04:00
25b5623a65 Add temp debug 2025-07-29 01:56:19 -04:00
20477c21ab Add temp debug 2025-07-29 01:54:34 -04:00
8ed85fff2b Add temp debug 2025-07-29 01:52:51 -04:00
ab8f58ca92 Add temp debug 2025-07-29 01:52:36 -04:00
20e11b7419 Add temp debug 2025-07-29 01:49:03 -04:00
11c28c7ab3 Add temp debug 2025-07-29 01:47:28 -04:00
908664b185 Resimplify worktrees 2025-07-29 01:43:53 -04:00
40ce9940ae Debug commit print 2025-07-29 01:15:10 -04:00
64ffeeca17 Fix git object 2025-07-29 01:06:01 -04:00
0106ac7eff Use full name for branch ref 2025-07-29 00:44:49 -04:00
86f5bf7e3f Skip fetch 2025-07-29 00:32:38 -04:00
a18d467c4f Hacky way to show latest commit 2025-07-29 00:25:06 -04:00
3a659b4798 Fix clashing worktrees 2025-07-29 00:05:26 -04:00
7f996e7724 Silence commond debug warning 2025-07-28 23:51:44 -04:00
3688539a90 Return early and add debug output for dependencies 2025-07-28 23:48:14 -04:00
c28d7683d8 Make BUILD_DIR worktree_dir 2025-07-28 23:44:19 -04:00
a5b559c59c Fix parsing in normalize_and_ref() 2025-07-28 23:29:46 -04:00
d22d21148c Implement per-profile modes 2025-07-28 23:24:16 -04:00
2b4dac7ef3 Hide openwrt src dir 2025-07-28 21:38:09 -04:00
498f8a7333 Use a global release object 2025-07-28 21:36:01 -04:00
d28f2e8c31 Only fetch if not checked out 2025-07-28 19:03:17 -04:00
ca3f1e82ed Use git fetch for branches 2025-07-28 19:00:44 -04:00
4b66de068b Refactor worktree code 2025-07-28 18:31:20 -04:00
1e88f1b912 Revert to serial debug 2025-07-28 17:45:51 -04:00
cbe7e0468d Use multicore debug 2025-07-28 01:02:49 -04:00
a664b70cf4 Update README 2025-07-28 00:36:14 -04:00
b5199d5682 Remove index update 2025-07-28 00:29:33 -04:00
35ec2993cc Remove worktree dir before add 2025-07-27 22:53:32 -04:00
e4838f361e Cleanup dependency arrays 2025-07-27 22:46:40 -04:00
f32b8c84b0 Update dependencies 2025-07-27 22:39:31 -04:00
f34953b3cc Fix for missing worktree metadata 2025-07-27 22:22:55 -04:00
e91394ee00 Add --depends to README 2025-07-27 21:29:26 -04:00
a40ac543e9 Use default CFLAGS 2025-07-27 00:05:03 -04:00
06a3209046 Use CFLAGS in make 2025-07-26 21:39:58 -04:00
5ef6d2dc0f Use CFLAGS var 2025-07-26 19:39:53 -04:00
36c0786255 Use -std=c17 for gcc15 2025-07-26 00:43:03 -04:00
25e66b3d19 Update openwrt default to 24.10.2 2025-07-25 19:25:30 -04:00
aa24a58aae Roll verbose into debug 2025-04-22 20:13:12 -04:00
7298fca349 User serial compilation for --debug 2025-04-22 16:58:06 -04:00
7191e10f91 Use n-1 cores 2025-04-22 16:55:43 -04:00
e80dddf9a7 Update default release 2025-04-21 16:48:51 -04:00
481e2e2277 Update print_help() 2025-02-22 17:21:03 -05:00
de84a404f0 Update default release 2025-02-22 17:06:32 -05:00
4 changed files with 423 additions and 344 deletions

1
.gitignore vendored
View File

@@ -1,6 +1,7 @@
src/
bin/
.vscode/
*.code-workspace
backups/
.dependencies_source
.dependencies_ib

View File

@@ -1,10 +1,10 @@
# openwrtbuilder
Sanely build and deploy OpenWRT images using the Image Builder or from source code.
Build and deploy OpenWRT images using shell-style device profiles, via source code or the official Image Builder.
## Usage
`openwrtbuilder [--option [VALUE]]... -p PROFILE [-p PROFILE]...`
`openwrtbuilder [OPTION [VALUE]]... -p PROFILE [-p PROFILE]...`
## Options
@@ -13,8 +13,9 @@ Sanely build and deploy OpenWRT images using the Image Builder or from source co
--release,-r,--version,-v RELEASE ("snapshot", "22.03.3")
--buildroot,-b PATH (Default: script directory)
--source
Build image from source, not from Image Builder
Allows make config options to be passed in profile
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
@@ -24,6 +25,8 @@ Sanely build and deploy OpenWRT images using the Image Builder or from source co
--reset
Cleanup all source and output files
Can be combined with -p to reset a specific profile
--depends
Force dependency installation
--yes,-y
Assume yes for all questions (automatic mode)
--debug,-d
@@ -32,15 +35,22 @@ Sanely build and deploy OpenWRT images using the Image Builder or from source co
## Profiles
See `./profiles` for example device profile definitions.
See `profiles` for example device profile definitions. Multiple `--profile` can be passed at once.
The default build mode is `imagebuilder` unless `--source` is passed. Default profile modes can be set individually in `profiles`.
## Examples
* `./openwrtbuilder -p r4s -r snapshot --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`
* `openwrtbuilder -p r4s -p ax6000`
* `openwrtbuilder -p r4s -r snapshot --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`
## Additional Info
Did you find `openwrtbuilder` useful? [Buy me a coffee!](https://paypal.me/bryanroessler)
Find `openwrtbuilder` useful? [Paypal me a coffee!](https://paypal.me/bryanroessler)
[↓ ↓ ↓ Bitcoin ↓ ↓ ↓](bitcoin:bc1q7wy0kszjavgcrvkxdg7mf3s6rh506rasnhfa4a)
[![Bitcoin](https://repos.bryanroessler.com/files/bc1q7wy0kszjavgcrvkxdg7mf3s6rh506rasnhfa4a.png)](bitcoin:bc1q7wy0kszjavgcrvkxdg7mf3s6rh506rasnhfa4a)

View File

@@ -1,18 +1,18 @@
#!/usr/bin/env bash
# Builds and deploys OpenWRT images
# Copyright 2022-24 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.md and ./profiles for device configuration
# See README and ./profiles for device configuration
# Set default release
: "${RELEASE:="24.10.0-rc5"}"
: "${RELEASE:="24.10.4"}"
# @internal
print_help() {
debug "${FUNCNAME[0]}"
cat <<-'EOF'
Build and deploy OpenWRT images
Build and deploy OpenWRT images using convenient profiles.
USAGE:
openwrtbuilder [OPTION [VALUE]]... -p PROFILE [-p PROFILE]...
@@ -22,28 +22,28 @@ print_help() {
--release,-r,--version,-v RELEASE ("snapshot", "22.03.5")
--buildroot,-b PATH
Default: location of openwrtbuilder script
--source
--source[=CLEAN]
Build image from source, not from Image Builder
Optional CLEAN runs the given clean mode before building
(clean|targetclean|dirclean|distclean)
--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 (automatic mode)
--verbose
Make make or imagebuilder noisier
--debug,-d
--help,-h
EXAMPLES
./openwrtbuilder -p r4s -r snapshot
./openwrtbuilder -p ax6000 -r 23.05.0-rc3 --source --debug
./openwrtbuilder -p rpi4 -r 22.03.3 --flash /dev/sdX
./openwrtbuilder -p linksys -r snapshot --ssh-upgrade root@192.168.1.1
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 linksys -r snapshot --ssh-upgrade root@192.168.1.1
EOF
}
@@ -56,7 +56,7 @@ init() {
# Save the script directory
# https://stackoverflow.com/a/4774063
SCRIPT_DIR="$(cd -- "$(dirname "$0")" >/dev/null 2>&1 || exit $? ; pwd -P)"
SCRIPT_DIR=$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")
if [[ -e "/etc/os-release" ]]; then
source "/etc/os-release"
@@ -124,10 +124,10 @@ init() {
parse_input() {
debug "${FUNCNAME[0]}" "$*"
declare -ga PROFILES
declare -g RESET=0 FROM_SOURCE=0 YES=0 VERBOSE=0 DEBUG=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,yes,verbose,debug,help'
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 SOURCE_CLEAN
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:sf:ydh -l $long_opts -- "$@"); then
eval set -- "$_input"
@@ -136,13 +136,18 @@ parse_input() {
--release|-r|--version|-v) shift; USER_RELEASE="$1" ;;
--profile|-p) shift; PROFILES+=("$1") ;;
--buildroot|-b) shift; BUILD_ROOT="$1" ;;
--source|-s) FROM_SOURCE=1 ;;
--source|-s) FROM_SOURCE=1
case "$1" in
-*|"") ;; # if empty
*) SOURCE_CLEAN="$1"; shift ;;
esac
;;
--ssh-upgrade) shift; SSH_UPGRADE_PATH="$1" ;;
--ssh-backup) shift; SSH_BACKUP_PATH="$1" ;;
--flash|-f) shift; FLASH_DEV="$1" ;;
--reset) RESET=1 ;;
--depends) FORCE_DEPENDS=1 ;;
--yes|-y) YES=1 ;;
--verbose) VERBOSE=1 ;;
--debug|-d) echo "Debugging on"; DEBUG=1 ;;
--help|-h) print_help; exit 0 ;;
--) shift; break ;;
@@ -156,163 +161,214 @@ parse_input() {
}
# @description Install build dependencies on major distros
# @arg $1 string Build mode ("source" or "imagebuilder")
install_dependencies() {
debug "${FUNCNAME[0]}"
local mode="$1"
local -a pkg_list
local lock_file
if ((FROM_SOURCE)); then
lock_file="$BUILD_ROOT/.dependencies_source"
else
lock_file="$BUILD_ROOT/.dependencies_ib"
# Set appropriate lock file based on mode
if [[ "$mode" == "source" ]]; then
lock_file="$BUILD_ROOT/.dependencies_source.lock"
elif [[ "$mode" == "imagebuilder" ]]; then
lock_file="$BUILD_ROOT/.dependencies_ib.lock"
fi
if [[ ! -f $lock_file ]]; then
if ((FROM_SOURCE)); then
# For building from source code
# https://openwrt.org/docs/guide-developer/toolchain/install-buildsystem
case "$ID" in
fedora|centos)
pkg_list+=(
bash-completion
bzip2
gcc
gcc-c++
git
make
ncurses-devel
patch
rsync
tar
unzip
wget
which
diffutils
python3
python3-devel
python3-setuptools
python3-pyelftools
perl-base
perl-Data-Dumper
perl-File-Compare
perl-File-Copy
perl-FindBin
perl-IPC-Cmd
perl-Thread-Queue
perl-Time-Piece
perl-JSON-PP
swig
clang # for qosify
llvm15-libs
patch)
;;
debian|ubuntu)
pkg_list+=(
build-essential
clang
flex
g++
gawk
gcc-multilib
gettext
git
libncurses5-dev
libssl-dev
python3-distutils
rsync
unzip
zlib1g-dev
file
wget
patch)
;;
arch)
pkg_list+=(
base-devel
autoconf
automake
bash
binutils
bison
bzip2
clang
fakeroot
file
findutils
flex
gawk
gcc
gettext
git
grep
groff
gzip
libelf
libtool
libxslt
m4
make
ncurses
openssl
patch
pkgconf
python
rsync
sed
texinfo
time
unzip
util-linux
wget
which
zlib
patch)
;;
*)
debug "Skipping dependency install, your OS is unsupported"
return 1
;;
esac
else
# For Imagebuilder
case "$ID" in
fedora|centos)
pkg_list+=(
@c-development
@development-tools
@development-libs
perl-FindBin
zlib-static
elfutils-libelf-devel
gawk
unzip
file
wget
python3
axel
perl-IPC-Cmd
zstd) ;;
debian|ubuntu)
pkg_list+=(
build-essential
libncurses5-dev
libncursesw5-dev
zlib1g-dev
gawk
git
gettext
libssl-dev
xsltproc
wget
unzip
python
axel
zstd) ;;
*) debug "Unsupported OS for automatic dependency install"; return 1 ;;
esac
fi
[[ -f $lock_file ]] && debug "$lock_file lock file exists but skipping for --debug" && return 0
pkg_install "${pkg_list[@]}" && echo "${pkg_list[@]}" > "$lock_file"
if [[ "$mode" == "source" ]]; then
# For building from source code see:
# https://openwrt.org/docs/guide-developer/toolchain/install-buildsystem
case "$ID" in
fedora|centos)
pkg_list+=(
bzip2
clang # for qosify
diffutils
gcc
gcc-c++
git
golang
llvm15-libs # for qosify
make
ncurses-devel
patch
perl
perl-Data-Dumper
perl-File-Compare
perl-File-Copy
perl-FindBin
perl-IPC-Cmd
perl-JSON-PP
perl-Thread-Queue
perl-Time-Piece
perl-base
python3
python3-devel
python3-pyelftools
python3-setuptools
quilt
rsync
swig
tar
unzip
wget
which
) ;;
debian|ubuntu)
pkg_list+=(
build-essential
clang
file
flex
g++
gawk
gcc-multilib
gettext
git
golang
liblzma-dev
libncurses5-dev
libssl-dev
python3-distutils
quilt
rsync
patch
unzip
wget
zlib1g-dev
) ;;
arch)
pkg_list+=(
autoconf
automake
base-devel
bash
binutils
bison
bzip2
clang
fakeroot
file
findutils
flex
gawk
gcc
gettext
git
golang
grep
groff
gzip
libelf
libtool
libxslt
m4
make
ncurses
net-snmp
openssl
patch
pkgconf
python
quilt
rsync
sed
texinfo
time
unzip
util-linux
wget
which
xz
zlib
) ;;
*) debug "Unsupported OS, skipping dependency install"; return 1 ;;
esac
elif [[ "$mode" == "imagebuilder" ]]; then
# For Imagebuilder
case "$ID" in
fedora|centos)
pkg_list+=(
@c-development
@development-tools
@development-libs
perl-FindBin
zlib-static
elfutils-libelf-devel
gawk
unzip
file
wget
python3
axel
perl-IPC-Cmd
zstd) ;;
debian|ubuntu)
pkg_list+=(
build-essential
libncurses5-dev
libncursesw5-dev
zlib1g-dev
gawk
git
gettext
libssl-dev
xsltproc
wget
unzip
python
axel
zstd) ;;
*) debug "Unsupported OS, skipping dependency install"; return 1 ;;
esac
fi
pkg_install "${pkg_list[@]}" && echo "${pkg_list[@]}" > "$lock_file"
}
# @description Normalize release and set worktree reference
# @arg $1 string Raw release input
# @arg $2 string Build mode ("source" or "imagebuilder")
# @returns string Normalized release and reference
normalize_and_ref() {
local input="$1" mode="$2"
local rel ref branch tag
case "$input" in
snapshot|latest|main|master)
rel="snapshot"
ref="main"
;;
v[0-9][0-9].[0-9][0-9].*|[0-9][0-9].[0-9][0-9].*)
# strip optional leading “v”
rel="${input#v}"
if [[ "$mode" == "source" ]]; then
branch="openwrt-${rel%.*}"
tag="v$rel"
if ask_ok "Use branch $branch HEAD (y) or tag $tag (n)?"; then
ref="$branch"
else
ref="$tag"
fi
else
ref="$rel"
fi
;;
*)
if [[ "$mode" == "source" ]]; then
# arbitrary commit-ish allowed
rel="$input"
ref="$input"
else
echo "Error: invalid release '$input'" >&2
exit 1
fi
;;
esac
printf '%s %s' "$rel" "$ref"
}
# @description Acquires the OpenWRT Image Builder
@@ -337,17 +393,6 @@ get_imagebuilder() {
done
}
add_repos() {
debug "${FUNCNAME[0]}"
if [[ -v P_ARR[repo] ]]; then
if ! grep -q "${P_ARR[repo]}" "$BUILD_DIR/repositories.conf"; then
echo "${P_ARR[repo]}" >> "$BUILD_DIR/repositories.conf"
fi
sed -i '/option check_signature/d' "$BUILD_DIR/repositories.conf"
fi
}
ssh_backup() {
debug "${FUNCNAME[0]}"
local date hostname backup_fname
@@ -391,7 +436,7 @@ make_images() {
# fi
# fi
((VERBOSE)) && make_opts+=("V=s")
((DEBUG)) && make_opts+=("V=sc")
debug make "${make_opts[@]}" image BIN_DIR="$BIN_DIR" \
PROFILE="$DEVICE" PACKAGES="$PACKAGES" \
@@ -461,87 +506,115 @@ 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]}" "$*"
local seed_url="$1"
local profile="$2"
local ref="$3"
local src_url="https://github.com/openwrt/openwrt.git"
local seed_file="$WORKTREE_DIR/.config"
local pkg config commit seed_file wt_commit description
local -a make_opts config_opts
local seed_file="$BUILD_DIR/.config"
local worktree_meta="$SRC_DIR/.git/worktrees/source-$ref"
local pkg config commit seed_file 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"
)
echo "Building from source is under development"
# Update source code
if [[ ! -d "$SRC_DIR" ]]; then
# Remove all build directories and worktrees if --reset
if ((RESET)); then
if [[ -d "$BUILD_DIR" || -d "$worktree_meta" ]]; then
execute git -C "$SRC_DIR" worktree remove --force --force "$BUILD_DIR"
[[ -d "$BUILD_DIR" ]] && execute rm -rf "$BUILD_DIR"
[[ -d "$worktree_meta" ]] && execute rm -rf "$worktree_meta"
fi
[[ -d "$BUILD_DIR" ]] && execute rm -rf "$BUILD_DIR"
fi
# Fetch or clone source repo (no local merges)
if [[ -d "$SRC_DIR" ]]; then
execute git -C "$SRC_DIR" fetch origin --tags --prune
else
execute mkdir -p "$SRC_DIR"
execute git clone "$src_url" "$SRC_DIR"
fi
git -C "$SRC_DIR" pull
# Generate commitish for git worktree
case "$RELEASE" in
snapshot) wt_commit="origin/main" ;;
[0-9][0-9].[0-9][0-9].*)
local branch="openwrt-${RELEASE%.*}"
local tag="v$RELEASE"
if ask_ok "Use $branch branch HEAD (y, recommended) or $tag tag (n)?"; then
wt_commit="origin/$branch"
else
wt_commit="$tag"
fi
;;
*)
debug "Passing '$RELEASE' commit-ish to git worktree"
wt_commit="$RELEASE"
;;
esac
# TODO There's a bug in the make clean functions that seem to invoke a full make
if [[ -d "$WORKTREE_DIR" ]]; then
execute git -C "$WORKTREE_DIR" checkout "$wt_commit"
execute git -C "$WORKTREE_DIR" pull
# 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 add --force --detach "$WORKTREE_DIR" "$wt_commit"
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
# To workaround bug, don't use make *clean, blow it away and start fresh
# [[ -d "$WORKTREE_DIR" ]] && execute rm -rf "$WORKTREE_DIR"
# execute git -C "$SRC_DIR" worktree add --force --detach "$WORKTREE_DIR" "$wt_commit"
# Print commit information
commit=$(git -C "$WORKTREE_DIR" rev-parse HEAD)
description=$(git -C "$WORKTREE_DIR" describe)
# Add cherrypick commits if specified in profile (skip if already included)
for entry in ${P_ARR[cherrypicks]}; do
remote="${entry%%:*}"
commit="${entry##*:}"
if ! git -C "$BUILD_DIR" remote | grep -q "^$remote$"; then
execute git -C "$BUILD_DIR" remote add "$remote" "https://github.com/$remote/openwrt.git"
fi
execute git -C "$BUILD_DIR" fetch "$remote"
execute git -C "$BUILD_DIR" merge-base --is-ancestor "$commit" HEAD ||
execute git -C "$BUILD_DIR" cherry-pick "$commit"
done
# Print commit info
commit=$(git -C "$BUILD_DIR" rev-parse HEAD)
description=$(git -C "$BUILD_DIR" describe --always --dirty)
echo "Current commit hash: $commit"
echo "Git worktree description: $description"
((DEBUG)) && git --no-pager -C "$WORKTREE_DIR" log -1
((DEBUG)) && git --no-pager -C "$BUILD_DIR" log -1
# Enter worktree
execute pushd "$WORKTREE_DIR" || return 1
execute pushd "$BUILD_DIR" || return 1
# Cleanup build environment
((VERBOSE)) && make_opts+=("V=s")
execute make "${make_opts[@]}" "-j1" distclean
# Begin OpenWRT build process
((DEBUG)) && make_opts+=("V=sc")
# Cleanup build environment: heavy clean only when --reset was used earlier
# 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 $SOURCE_CLEAN ]]; then
execute make "${make_opts[@]}" "-j1" "$SOURCE_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
# Update package feed
./scripts/feeds update -i -f &&
./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
@@ -551,53 +624,37 @@ from_source() {
fi
done
# Add config options from profile
# Add profile config options
for config in ${P_ARR[config]}; do
config_opts+=("$config")
done
# 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
# 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"
done
# Make prep
# Expand seed into full config
execute make "${make_opts[@]}" "-j1" defconfig
# Run serial make download for better reliability
execute make "${make_opts[@]}" "-j1" download
# ((DEBUG)) && make_opts+=("-j1") || make_opts+=("-j$(($(nproc)+1))")
make_opts+=("-j$(($(nproc)+1))")
# (Optional) Disable multicore make world
# ((DEBUG)) && make_opts+=("-j1") || make_opts+=("-j$(($(nproc)-2))")
make_opts+=("-j$(($(nproc)-2))")
# Make image
if ! execute ionice -c 3 chrt --idle 0 nice -n19 make "${make_opts[@]}" world; then
if ! execute ionice -c2 -n7 nice -n19 make "${make_opts[@]}" BIN_DIR="$BIN_DIR" world; then
echo "Error: make failed"
return 1
fi
execute popd || return 1
# Symlink output images to root of BIN_DIR (match Image Builder)
# Symlink output images to root of BIN_DIR (match Image Builder behavior)
shopt -s nullglob
for image in "$BIN_DIR/targets/${TARGET}/"*.{img,img.gz,ubi}; do
execute ln -fs "$image" "$BIN_DIR/${image##*/}"
@@ -615,7 +672,7 @@ backup() {
local file="$1" dir="$2"
local creation_date base_name backup_file
[[ -f $file ]] || { debug "File not found: $file"; return 1; }
[[ -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) && \
@@ -704,8 +761,13 @@ main() {
exit $?
fi
install_dependencies
# 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_ib.lock" ]] && rm -f "$BUILD_ROOT/.dependencies_ib.lock"
fi
# Run selected profiles
for profile in "${PROFILES[@]}"; do
debug "Running profile: $profile"
@@ -715,40 +777,34 @@ main() {
fi
# Store profile in P_ARR nameref
declare -gn P_ARR="$profile"
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 PACKAGES="${P_ARR[packages]:-}"
declare -g RELEASE="${USER_RELEASE:=${P_ARR[release]:=$RELEASE}}"
# normalize RELEASE
case "$RELEASE" in
snapshot|latest|main|master) RELEASE="snapshot" ;;
v[0-9][0-9].[0-9][0-9].*) RELEASE="${RELEASE#v}" ;;
[0-9][0-9].[0-9][0-9].*) ;;
*)
if ! ((FROM_SOURCE)); then
echo "Error: Invalid release version format"
echo "Use semantic version, tag, or 'snapshot'"
exit 1
fi
;;
esac
# pull in USER_RELEASE from args or profile default
local raw_release="${USER_RELEASE:=${P_ARR[release]:=$RELEASE}}"
declare -g SRC_DIR="$BUILD_ROOT/src/openwrt"
declare -g WORKTREE_DIR="$BUILD_ROOT/src/$profile/$RELEASE-src"
declare -g BUILD_DIR="$BUILD_ROOT/src/$profile/$RELEASE"
declare -g BIN_DIR="$BUILD_ROOT/bin/$profile/$RELEASE"
# single call to normalize+ref
read -r release ref < <(normalize_and_ref "$raw_release" "$mode")
if [[ "$RELEASE" == "snapshot" ]]; then
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"
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 ib_url="$url_prefix/$url_filename"
@@ -757,39 +813,27 @@ main() {
local ib_sha256_file="$BUILD_DIR/sha256sums"
local seed_url="$url_prefix/config.buildinfo"
if ((FROM_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 "$SYSUPGRADEIMGGZ" "$BACKUP_DIR/$profile/$RELEASE"
backup "$SYSUPGRADEIMGGZ" "$BACKUP_DIR/$profile/$ref-$mode"
if ((RESET)); then
if ((FROM_SOURCE)); then
[[ -d $WORKTREE_DIR ]] && ask_ok "Remove $WORKTREE_DIR?"
execute git worktree remove --force "$WORKTREE_DIR"
execute rm -rf "$WORKTREE_DIR"
elif [[ -d $BUILD_DIR ]] && ask_ok "Remove $BUILD_DIR?"; then
execute rm -rf "$BUILD_DIR"
fi
fi
if ((DEBUG)); then
echo "Profile settings:"
for x in "${!P_ARR[@]}"; do printf "%s=%s\n" "$x" "${P_ARR[$x]}"; done
echo "Environment variables:"
declare -p
fi
if ((FROM_SOURCE)); then
from_source "$seed_url" || return $?
else
if [[ "$mode" == "source" ]]; then
from_source "$seed_url" "$profile" "$ref" || return $?
elif [[ "$mode" == "imagebuilder" ]]; then
[[ -d $BUILD_DIR ]] || mkdir -p "$BUILD_DIR"
get_imagebuilder "$ib_url" "$ib_file" "$ib_sha256_url" "$ib_sha256_file" &&
verify "$ib_file" "$ib_sha256_file" &&
extract "$ib_file" "$BUILD_DIR" || return $?
add_repos
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
make_images
# Verify output image for stock builds (in testing)
if [[ ! -v P_ARR[packages] || -z ${P_ARR[packages]} ]]; then
@@ -809,5 +853,9 @@ main() {
done
}
# Roughly turn debugging on for pre-init
# Reset and reparse in parse_input() with getopt
[[ " $* " =~ ( --debug | -d ) ]] && DEBUG=1
main "$@"
exit

View File

@@ -1,64 +1,80 @@
#!/usr/bin/env bash
# shellcheck disable=SC2034
# Device profiles for openwrtbuilder
# shellcheck disable=SC2034
# 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"
# Default (but optional) packages (precede with "-" to exclude)
default_packages=(nano htop diffutils tar iperf3 zsh rsync curl tcpdump
openssh-sftp-server luci luci-ssl luci-proto-wireguard luci-app-statistics
collectd-mod-sensors collectd-mod-thermal collectd-mod-conntrack collectd-mod-cpu
)
# Default (but optional) kernel configs
default_configs=(
)
# Current devices
declare -Ag r4s=(
[mode]="source"
[device]="friendlyarm_nanopi-r4s"
[target]="rockchip/armv8"
[filesystem]="ext4"
[packages]="$default_packages luci-app-ddns luci-app-sqm irqbalance \
[packages]="${default_packages[*]} \
luci-app-ddns luci-app-sqm \
adblock luci-app-adblock \
collectd-mod-df usbutils kmod-usb-storage kmod-usb-storage-uas \
kmod-fs-btrfs btrfs-progs block-mount smcroute avahi-daemon \
curl ethtool ca-bundle"
[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"
ethtool ca-bundle tailscale"
[config]="${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"
# For 24.10 branch (Linux 6.6)
# [cherrypicks]="wurzerj:59d6e31 wurzerj: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 -dnsmasq -odhcpd-ipv6only -nftables -firewall4"
[packages]="${default_packages[*]} \
-dnsmasq -odhcpd-ipv6only -nftables -firewall4 tailscale"
)
declare -Ag ax6000_uboot=(
[mode]="imagebuilder"
[device]="xiaomi_redmi-router-ax6000-ubootmod"
[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 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]="${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"
# [files]="/mnt/backup"
)
declare -Ag rpi4=(
[device]="rpi-4"
[target]="bcm27xx/bcm2711"
[filesystem]="ext4"
[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"
[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"
)
declare -Ag r4s_stock=(
@@ -72,7 +88,8 @@ 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"
)
@@ -80,7 +97,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"
)
@@ -88,14 +105,16 @@ 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"
)
@@ -104,7 +123,8 @@ 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"
)