#!/bin/bash # Automatically prepare OpenWRT build environment. # - Clone or update repository # - Support selecting release/beta/snapshot versions # - Normalize helper checkout into openwrt/helper # - Update and install feeds # - Prepare .config for build set -e umask 022 REPO_URL="https://github.com/openwrt/openwrt.git" SCRIPT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)/$(basename "${BASH_SOURCE[0]}")" SCRIPT_DIR="$(dirname "$SCRIPT_PATH")" WORK_ROOT="" HELPER_DIR="" echo "========================================" echo " OpenWRT Build Environment Setup Script" echo "========================================" # --- Helpers --- is_openwrt_repo() { local dir="$1" [ -f "$dir/feeds.conf.default" ] && [ -f "$dir/Makefile" ] && git -C "$dir" rev-parse --is-inside-work-tree >/dev/null 2>&1 } is_helper_checkout() { local dir="$1" [ -f "$dir/prepare-openwrt.sh" ] && [ -f "$dir/prepare-openwrt-env.sh" ] && [ -f "$dir/add-external-repos.sh" ] } has_remote_branch() { local branch="$1" git show-ref --verify --quiet "refs/remotes/origin/$branch" } has_tag() { local tag="$1" git rev-parse --verify "refs/tags/$tag" >/dev/null 2>&1 } ensure_helper_target_available() { local target_helper="$1" local source_dir="$2" local existing_path="" local source_path="" if [ ! -e "$target_helper" ]; then return fi existing_path="$(cd "$target_helper" && pwd -P)" source_path="$(cd "$source_dir" && pwd -P)" if [ "$existing_path" = "$source_path" ]; then return fi echo "[ERROR] Helper destination already exists at '$target_helper'." echo "[ERROR] Refusing to overwrite a different helper checkout." exit 1 } ensure_target_root_ready() { local target_root="$1" local first_entry="" if [ ! -e "$target_root" ]; then return fi if [ ! -d "$target_root" ]; then echo "[ERROR] Target OpenWrt root '$target_root' exists but is not a directory." exit 1 fi if is_openwrt_repo "$target_root"; then return fi first_entry="$(find "$target_root" -mindepth 1 -maxdepth 1 ! -name helper -print -quit 2>/dev/null || true)" if [ -z "$first_entry" ]; then return fi echo "[ERROR] Target OpenWrt root '$target_root' already contains unexpected files." echo "[ERROR] Refusing to merge the helper checkout into a non-OpenWrt directory." exit 1 } normalize_structure() { local source_dir="$SCRIPT_DIR" local source_name local parent_dir local target_root local target_helper local temp_dir source_name="$(basename "$source_dir")" parent_dir="$(dirname "$source_dir")" if [ "$source_name" = "helper" ] && [ "$(basename "$parent_dir")" = "openwrt" ]; then WORK_ROOT="$parent_dir" HELPER_DIR="$source_dir" cd "$WORK_ROOT" echo "[INFO] Reusing existing normalized layout at '$WORK_ROOT'." return fi if is_openwrt_repo "$source_dir"; then WORK_ROOT="$source_dir" HELPER_DIR="$source_dir/helper" cd "$WORK_ROOT" echo "[INFO] Script is already running from an OpenWrt source root at '$WORK_ROOT'." echo "[INFO] Skipping relocation to avoid moving an existing OpenWrt tree." return fi if ! is_helper_checkout "$source_dir"; then echo "[ERROR] '$source_dir' does not look like a helper checkout." echo "[ERROR] Refusing to relocate an unexpected directory." exit 1 fi target_root="$parent_dir/openwrt" target_helper="$target_root/helper" if [ "$source_dir" != "$target_root" ]; then ensure_target_root_ready "$target_root" fi ensure_helper_target_available "$target_helper" "$source_dir" if [ "$source_dir" = "$target_root" ]; then echo "[INFO] Helper checkout already uses the target root name. Normalizing in place." temp_dir="$parent_dir/.openwrt-helper-relocate-$$" if [ -e "$temp_dir" ]; then echo "[ERROR] Temporary relocation path already exists: '$temp_dir'." exit 1 fi cd "$parent_dir" mv "$source_dir" "$temp_dir" mkdir -p "$target_root" mv "$temp_dir" "$target_helper" else echo "[INFO] Relocating helper checkout to '$target_helper'." mkdir -p "$target_root" cd "$parent_dir" mv "$source_dir" "$target_helper" fi WORK_ROOT="$target_root" HELPER_DIR="$target_helper" cd "$WORK_ROOT" echo "[INFO] OpenWrt source root: '$WORK_ROOT'." echo "[INFO] Helper checkout: '$HELPER_DIR'." } ensure_origin_remote() { local current_url="" if git remote get-url origin >/dev/null 2>&1; then current_url="$(git remote get-url origin)" if [ "$current_url" != "$REPO_URL" ]; then echo "[INFO] Updating git remote 'origin' to '$REPO_URL'." git remote set-url origin "$REPO_URL" fi else git remote add origin "$REPO_URL" fi } prepare_openwrt_repo() { cd "$WORK_ROOT" if is_openwrt_repo "$WORK_ROOT"; then echo "[INFO] Existing OpenWrt repository detected at '$WORK_ROOT'. Updating refs..." ensure_origin_remote git fetch --tags origin return fi if [ -e "$WORK_ROOT/.git" ]; then echo "[ERROR] '$WORK_ROOT' already contains a Git repository that does not look like OpenWrt." exit 1 fi if [ -f "$WORK_ROOT/feeds.conf.default" ] || [ -f "$WORK_ROOT/Makefile" ] || [ -d "$WORK_ROOT/package" ]; then echo "[ERROR] '$WORK_ROOT' contains files that look like an incomplete OpenWrt tree." echo "[ERROR] Refusing to initialize over an unexpected directory state." exit 1 fi echo "[INFO] Initializing OpenWrt repository in '$WORK_ROOT'..." git init . ensure_origin_remote git fetch --tags origin } checkout_or_update_branch() { local branch="$1" if [ ! "$(git rev-parse --abbrev-ref HEAD 2>/dev/null)" = "$branch" ]; then if git show-ref --verify --quiet "refs/heads/$branch"; then git checkout "$branch" else git checkout -b "$branch" --track "origin/$branch" fi fi git pull --ff-only origin "$branch" } # --- Function: choose version --- choose_version() { echo echo "Select OpenWRT version type:" echo " 1) Stable release (e.g., 24.10.4)" echo " 2) Beta (e.g., 24.10-SNAPSHOT or openwrt-24.10)" echo " 3) Latest snapshot (master branch)" echo -n "Enter choice [1-3, default=1]: " read -r choice case "$choice" in 2) echo -n "Enter beta version (e.g. 24.10 or openwrt-24.10): " read -r VERSION SELECTED_TYPE="beta" ;; 3) SELECTED_TYPE="snapshot" VERSION="master" ;; *) echo -n "Enter stable version number (e.g. 24.10.4, default: latest): " read -r VERSION SELECTED_TYPE="stable" ;; esac } # --- Start --- normalize_structure choose_version prepare_openwrt_repo pushd "$WORK_ROOT" >/dev/null # --- Version selection logic --- if [ "$SELECTED_TYPE" == "snapshot" ]; then echo "[INFO] Checking out latest master (snapshot)..." if has_remote_branch "master"; then checkout_or_update_branch "master" else echo "[ERROR] Remote branch 'master' not found." exit 1 fi elif [ "$SELECTED_TYPE" == "beta" ]; then local_branch="" local_tag="" if [[ "$VERSION" == openwrt-* ]]; then local_branch="$VERSION" local_tag="v${VERSION#openwrt-}-SNAPSHOT" elif [[ "$VERSION" == v*-SNAPSHOT ]]; then local_tag="$VERSION" local_branch="openwrt-${VERSION#v}" local_branch="${local_branch%-SNAPSHOT}" else local_branch="openwrt-${VERSION}" local_tag="v${VERSION}-SNAPSHOT" fi if has_remote_branch "$local_branch"; then echo "[INFO] Checking out beta branch '$local_branch'..." checkout_or_update_branch "$local_branch" elif has_tag "$local_tag"; then echo "[INFO] Checking out beta tag '$local_tag'..." git checkout "$local_tag" else echo "[ERROR] Beta branch or tag not found for version '$VERSION'." exit 1 fi else # Stable version if [ -z "$VERSION" ]; then LATEST_TAG=$(git tag -l "v*" | sort -V | tail -n 1) if [ -z "$LATEST_TAG" ]; then echo "[ERROR] No stable tags found in remote repository." exit 1 fi echo "[INFO] No version specified, using latest stable tag: $LATEST_TAG" VERSION="$LATEST_TAG" else if [[ "$VERSION" != v* ]]; then VERSION="v${VERSION}" fi fi if has_tag "$VERSION"; then git checkout "$VERSION" else echo "[ERROR] Version tag '$VERSION' not found." exit 1 fi fi # --- Update feeds --- echo "[INFO] Updating and installing all feeds..." ./scripts/feeds update -a ./scripts/feeds install -a # --- Run defconfig --- echo "[INFO] Running make defconfig..." make defconfig CURRENT_VERSION=$(git describe --tags 2>/dev/null || git rev-parse --abbrev-ref HEAD) popd >/dev/null echo echo "========================================" echo "✅ OpenWRT source is ready." echo " Version: $CURRENT_VERSION" echo " Root: $WORK_ROOT" echo "========================================" echo echo "👉 Next steps:" echo " cd $WORK_ROOT" echo " make menuconfig" echo " make -j\$(nproc) download world" echo