prepare-openwrt-env.sh - Dispatch on the package manager instead of guessing from the distro version: apt, dnf/yum, pacman, zypper and apk are all supported. - Probe every package against the running release and skip the ones that no longer exist. Previously a single dropped package (on Ubuntu 26.04 arm64, gcc-multilib-s390x-linux-gnu) failed the whole apt command and set -e aborted the script, so nothing was installed at all. - Align the package lists with the official build system guide, adding libelf-dev, python3-dev, bc, xsltproc, zstd, u-boot-tools and others. - Make Go opt-in via --with-go rather than forced on arm64. - Add -y/--yes, -n/--dry-run and -h/--help; allow running as root. prepare-openwrt.sh - Split read-only discovery from mutation. Versions are resolved over git ls-remote before anything is moved, so aborting at the prompt leaves the helper checkout untouched. - Resume an interrupted first run instead of failing forever: a root with .git but no source tree was previously unrecoverable without a manual rm -rf. Also restore the worktree when HEAD already points at the target ref, where checkout is a no-op. - Detect the relocated layout by content rather than directory name, so renaming the root no longer triggers a second, nested relocation. - Replace the staged in-place relocation with a resumable content move, removing the window that could strand the checkout in a hidden dir. - Filter release candidates before sorting; sort -V orders v25.12.0-rc1 after v25.12.0, so the newest stable tag could be an rc. - Follow upstream: snapshots use main (master as fallback) and the dead -SNAPSHOT tag lookup is gone. - Use a partial clone (--filter=blob:none) by default. - Guard version switches on a dirty tree and back up .config first. - Add /helper/ to .git/info/exclude and warn that git clean -xdff still deletes it, since -x bypasses ignore rules by design. - Leave a symlink at the old checkout path so shells and editors whose working directory still points there keep working. - Add --stable/--branch/--snapshot plus -y, -n, --force, --full-clone, --allow-rc, --root, --skip-feeds, --skip-defconfig, --repo-url and --no-compat-link. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
OpenWrt Build Helper Scripts
Overview
This repository contains shell scripts that streamline preparing, configuring, and building OpenWrt from source on Debian/Ubuntu systems (x86_64 and ARM64). It also includes convenience utilities to manage package selections, fetch device config.buildinfo, apply a DAHDI driver patch, and add external LuCI packages.
What’s included
- prepare-openwrt-env.sh
- Installs the build dependencies listed by the official OpenWrt build system guide.
- Supports apt (Debian/Ubuntu/Mint), dnf/yum (Fedora/RHEL/Rocky/Alma), pacman (Arch/Manjaro), zypper (openSUSE) and apk (Alpine).
- Probes each package against the running release and skips the ones that no longer exist, so a renamed or dropped package cannot abort the whole install.
- Handles x86_64 and ARM64 differences (native vs. cross multilib).
- Options:
-y/--yes(no prompt),-n/--dry-run(only print),--with-go(also install the Go toolchain).
- prepare-openwrt.sh
- Clones or updates the OpenWrt source repo in the top-level
openwrt/root. - Lets you select a stable tag, a release branch, or the snapshot (
main) interactively, or non-interactively via flags. - Uses the script location as the source of truth, so running it from another current working directory is supported.
- On first run from a helper checkout, relocates that checkout to
openwrt/helper/and leaves a symlink behind at the old path. - Prints a plan and asks for confirmation; nothing on disk is touched before you confirm.
- Uses a partial clone (
--filter=blob:none) by default, so the first fetch is far smaller than full history. - Resumes automatically if a previous run was interrupted.
- Updates feeds and runs make defconfig.
- Options:
--stable [<ver>],--branch <name>,--snapshot,-y/--yes,-n/--dry-run,-f/--force,--full-clone,--allow-rc,--root <dir>,--skip-feeds,--skip-defconfig,--repo-url <url>,--no-compat-link,-h/--help.
- Clones or updates the OpenWrt source repo in the top-level
- add-external-repos.sh
- Clones or updates additional package repositories into package/.
- Currently includes luci-app-netspeedtest and luci-app-easytier (adjust REPOS as needed).
- download-config.sh
- Downloads config.buildinfo for a selected device based on your checked-out OpenWrt version (stable or snapshot).
- Writes .config and runs make defconfig.
- Prints firmware URL and a Firmware Selector link for reference.
- add-openwrt-packages.sh
- Enables packages listed in a text file by appending CONFIG_PACKAGE_=y to .config (without removing existing settings).
- Verifies presence in package/ or feeds/ and reports missing ones, then runs make defconfig.
- update-go-path.sh
- Detects the latest Go installation under /usr/lib/go-* and sets CONFIG_GOLANG_EXTERNAL_BOOTSTRAP_ROOT in .config.
- apply-dahdi-patches.sh
- Writes a DAHDI driver patch into package/feeds/telephony/dahdi-linux/patches/300-fix-dahdi-max-attempts.patch.
- Fixes MAX macro naming collisions in multiple DAHDI modules for OpenWrt 24.10.4 builds.
System requirements
- OS: Debian/Ubuntu, Fedora/RHEL, Arch, openSUSE or Alpine (the other scripts are developed and tested on Debian/Ubuntu)
- Architectures: x86_64/amd64 and aarch64/arm64
- Tools: git, wget, curl, bash
- Internet access for feeds and package downloads
- Optional: Go (required by some OpenWrt packages; install it with
./prepare-openwrt-env.sh --with-go; configurable via update-go-path.sh) - Note: with the default partial clone, switching to another tag or branch later fetches missing blobs on demand and therefore needs network access
Quick start
- Prepare the host machine
- Run: ./prepare-openwrt-env.sh
- This installs compilers, headers, Python tooling, and other build prerequisites.
- Preview without touching the system: ./prepare-openwrt-env.sh -n
- Get OpenWrt sources
- Run: ./prepare-openwrt.sh
- Choose a stable tag, a release branch, or the snapshot.
- Non-interactive: ./prepare-openwrt.sh --stable 25.12.5 -y
- Preview only, changes nothing: ./prepare-openwrt.sh --stable -n
- The script:
- Reuses or creates the top-level OpenWrt root at
./openwrt. - Moves this helper checkout to
./openwrt/helperon first run. - Updates/install feeds and runs make defconfig.
- Reuses or creates the top-level OpenWrt root at
- Add optional external packages
- From the OpenWrt root:
- ./helper/add-external-repos.sh
- This pulls extra LuCI packages into package/.
- Import a device config.buildinfo (optional but convenient)
- From the OpenWrt root:
- ./helper/download-config.sh
- Pick a device, and the script writes .config and runs make defconfig.
- Enable additional packages from a list (optional)
- Create a file packages.txt containing package names (whitespace or newlines).
- From the OpenWrt root:
- ./helper/add-openwrt-packages.sh packages.txt
- Configure Go bootstrap path (if needed)
- From the OpenWrt root:
- ./helper/update-go-path.sh
- This sets CONFIG_GOLANG_EXTERNAL_BOOTSTRAP_ROOT to the latest /usr/lib/go-X.XX/ found.
- You can override it manually in .config if necessary.
- Apply DAHDI patch (only if you build telephony/dahdi-linux)
- Ensure telephony feed is installed:
- ./scripts/feeds update telephony
- ./scripts/feeds install -a
- Then run:
- ./helper/config_24.10.4/apply-dahdi-patches.sh
- Build the package:
- make package/feeds/telephony/dahdi-linux/{clean,prepare} V=s
- make package/feeds/telephony/dahdi-linux/compile V=s
- Build OpenWrt
- Common commands:
- make menuconfig
- make -j$(nproc) download world
- Artifacts will be in bin/ after the build completes.
Script usage notes and tips
- Run locations:
prepare-openwrt.sh: resolves paths from the script location, not your current shell directory.prepare-openwrt-env.sh: can be run before the first normalization from the fresh helper checkout.- All other helper scripts: run them from inside the OpenWrt source root as
./helper/...unless otherwise indicated.
- Feeds:
- If a package can’t be found, ensure feeds are updated/installed:
- ./scripts/feeds update -a && ./scripts/feeds install -a
- If a package can’t be found, ensure feeds are updated/installed:
- Go toolchain:
- On x86_64, Go is optional unless your selection pulls packages needing Go (e.g., firewall4 in some versions). If needed:
- sudo apt install golang -y
- Then use update-go-path.sh to set .config automatically.
- On x86_64, Go is optional unless your selection pulls packages needing Go (e.g., firewall4 in some versions). If needed:
- ARM64 multilib:
- The script installs cross multilib packages for better compatibility, but not all targets need them. If apt errors on specific multilib packages, remove or adjust as appropriate for your environment.
Troubleshooting
- Telephony feed not found when applying DAHDI patch:
- Run feeds update/install for telephony as shown above.
- Version detection in download-config.sh:
- If you’re on a branch like openwrt-24.10, the script will try to find the latest v24.10.x tag automatically. Otherwise it prompts for a version (e.g., 24.10.4 or SNAPSHOT).
- Missing packages in add-openwrt-packages.sh:
- Ensure the corresponding feed is enabled in feeds.conf.default and run feeds update/install.
- Permission errors:
- Scripts use umask 022 and do not require root except when installing apt packages.
- Clean up and rebuild a package:
- make package//{clean,compile} V=s
- Full rebuild:
- make clean; make -j$(nproc) download world
Directory behavior
- If you start from a freshly cloned helper checkout at
<parent>/<origin_folder>,prepare-openwrt.shwill:- Reuse or create
<parent>/openwrt/as the OpenWrt source root. - Move the entire helper checkout, including its
.git, to<parent>/openwrt/helper/. - Initialize or update the OpenWrt source tree directly in
<parent>/openwrt/. - Leave a symlink at the original checkout path pointing to
<parent>/openwrt/helper/, so shells, editors and agent sessions whose working directory is still the old path keep working. Disable with--no-compat-link.
- Reuse or create
- If you later rerun
prepare-openwrt.sh— fromopenwrt/helper/or through the symlink at the old path — it reuses the parentopenwrt/directory and does not move anything again. - The already-relocated layout is detected by content (the OpenWrt tree or its
originremote), not by directory name, so renamingopenwrt/to something else does not trigger a second relocation. - If a run is interrupted after the repository was created but before the source tree was checked out, the next run detects that state, reports
resuming it, and completes. No manual cleanup is needed. - If the script is already located in a real OpenWrt source root, it treats that directory as the source root and does not relocate it just because the directory name is
openwrt. - Use
--root <dir>to point at a different OpenWrt root in any ambiguous situation.
Known hazard: git clean -xdff
helper/ lives inside the OpenWrt Git worktree but is not tracked by it. The script
adds /helper/ to openwrt/.git/info/exclude, which keeps git status clean and stops
git add -A from staging it — but that does not protect it from git clean -xdff:
-x deliberately includes ignored files and -ff removes Git's refusal to recurse into
a nested repository. Running git clean -xdff in the OpenWrt root will delete the helper
checkout including its .git. Use this instead:
git clean -xdf -e /helper
Security and safety
- Scripts use set -euo pipefail to stop on errors.
- prepare-openwrt.sh backs up
.configto.config.<previous-ref>.bakbefore switching versions, and refuses to switch a tree with modified tracked files unless you pass --force. - They modify .config and write under package/ and feeds/ inside your OpenWrt tree.
- Backup your .config if you need a known baseline.
License and authorship
- Scripts authored by Zhe Yuan with help from ChatGPT.
- License: MIT (unless you choose a different license; update this line accordingly).