Update README and add setup scripts

This commit is contained in:
francis.wang
2026-07-15 16:25:38 +08:00
parent 4c86c082a2
commit c748f6060d
3 changed files with 455 additions and 2 deletions
+317
View File
@@ -0,0 +1,317 @@
#!/bin/bash
#
# OpenWrt-Yocto macOS Build Environment Setup
#
# Usage: ./setup-env-macos.sh [command]
#
# Commands:
# setup - Build the Docker image (default)
# shell - Enter the interactive build container
# build - Run bitbake inside the container (requires target, e.g. ./setup-env-macos.sh build openwrt-image-base)
# clean - Remove the Docker image and container
# help - Show this help message
#
# ─── Important Notes ───────────────────────────────────────────────────────
#
# 1. Yocto Project does NOT natively support macOS. This script uses
# Docker to run an Ubuntu container with all required build dependencies.
#
# 2. macOS uses a case-INSENSITIVE filesystem by default. Yocto REQUIRES
# a case-sensitive filesystem. This script will detect this and warn you.
#
# 3. You need at least 50GB of free disk space for a full build.
#
# 4. First-time setup will build a Docker image (~1GB) which may take a few minutes.
#
# ─── Prerequisites ──────────────────────────────────────────────────────────
#
# Install Docker Desktop for Mac: https://docs.docker.com/desktop/setup/mac/
#
# brew install --cask docker (if using Homebrew)
#
# After installation, open Docker Desktop and ensure it's running.
#
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
IMAGE_NAME="openwrt-yocto-builder"
IMAGE_TAG="latest"
CONTAINER_NAME="openwrt-yocto-build"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
print_header() {
echo ""
echo -e "${CYAN}╔══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${CYAN}║ OpenWrt-Yocto macOS Build Environment Setup ║${NC}"
echo -e "${CYAN}╚══════════════════════════════════════════════════════════════╝${NC}"
echo ""
}
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
print_warning() { echo -e "${YELLOW}[WARN]${NC} $1"; }
print_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
print_step() { echo -e "${CYAN}[STEP]${NC} $1"; }
# ─── Prerequisite Checks ────────────────────────────────────────────────────
check_prerequisites() {
print_step "Checking prerequisites..."
# Check Docker
if ! command -v docker &>/dev/null; then
print_error "Docker is not installed."
echo ""
echo " Please install Docker Desktop for Mac:"
echo " https://docs.docker.com/desktop/setup/mac/"
echo ""
echo " Or via Homebrew:"
echo " brew install --cask docker"
echo ""
exit 1
fi
# Check if Docker daemon is running
if ! docker info &>/dev/null; then
print_error "Docker daemon is not running."
echo " Please start Docker Desktop and try again."
exit 1
fi
print_info "Docker is installed and running."
# Check disk space (at least 50GB recommended)
local available_gb
available_gb=$(df -g . | awk 'NR==2 {print $4}')
if [ "$available_gb" -lt 50 ]; then
print_warning "Less than 50GB free disk space detected (${available_gb}GB available)."
echo " Yocto builds require significant disk space. You may run out of space."
echo " Continue anyway? (y/N)"
read -r response
if [[ ! "$response" =~ ^[Yy]$ ]]; then
exit 1
fi
else
print_info "Disk space OK: ${available_gb}GB available."
fi
# Check for case-sensitive filesystem warning
# macOS default APFS is case-insensitive, which breaks Yocto builds
local fs_type
fs_type=$(df -T . | awk 'NR==2 {print $2}')
if [[ "$(uname)" == "Darwin" ]]; then
print_warning "macOS uses a case-insensitive filesystem by default."
echo ""
echo " Yocto Project REQUIRES a case-sensitive filesystem."
echo " The build will happen inside a Docker container (Linux), so this"
echo " is only an issue if you extract source tarballs on macOS directly."
echo " Docker volumes handle case sensitivity correctly."
echo ""
echo " If you encounter 'file not found' errors, ensure all source files"
echo " are downloaded/cached inside the Docker container."
echo ""
fi
}
# ─── Docker Image Management ─────────────────────────────────────────────────
build_image() {
print_step "Building Docker image '${IMAGE_NAME}:${IMAGE_TAG}'..."
# Pass host user's UID/GID so container user matches
docker build \
--build-arg USER_UID="$(id -u)" \
--build-arg USER_GID="$(id -g)" \
-t "${IMAGE_NAME}:${IMAGE_TAG}" \
-f "$SCRIPT_DIR/Dockerfile" \
"$SCRIPT_DIR"
print_info "Docker image built successfully."
}
image_exists() {
docker image inspect "${IMAGE_NAME}:${IMAGE_TAG}" &>/dev/null
}
# ─── Container Management ────────────────────────────────────────────────────
enter_shell() {
print_step "Entering build container..."
# Ensure image exists
if ! image_exists; then
print_info "Docker image not found. Building it first..."
build_image
fi
# Check if container already exists and is running
if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
print_info "Attaching to running container '${CONTAINER_NAME}'..."
docker exec -it "${CONTAINER_NAME}" /bin/bash
return
fi
# Check if container exists but stopped
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
print_info "Starting existing container '${CONTAINER_NAME}'..."
docker start "${CONTAINER_NAME}"
docker exec -it "${CONTAINER_NAME}" /bin/bash
return
fi
# Run a new container
print_info "Creating new container '${CONTAINER_NAME}'..."
docker run -it --rm \
--name "${CONTAINER_NAME}" \
-v "$SCRIPT_DIR:/workspace" \
-v "${HOME}/.gitconfig:/home/builduser/.gitconfig:ro" \
"${IMAGE_NAME}:${IMAGE_TAG}" \
-c "
echo ''
echo '╔═══════════════════════════════════════════════════════╗'
echo '║ OpenWrt-Yocto Docker Build Environment ║'
echo '║ OS: Ubuntu 24.04 ║'
echo '║ Project: /workspace ║'
echo '╚═══════════════════════════════════════════════════════╝'
echo ''
echo 'Quick start:'
echo ' source ./setup-env.sh # Initialize build environment'
echo ' bitbake openwrt-image-base # Build the base image'
echo ''
exec /bin/bash
"
}
run_bitbake() {
local target="$1"
if [ -z "$target" ]; then
print_error "BitBake target is required."
echo " Usage: ./setup-env-macos.sh build <target>"
echo " Example: ./setup-env-macos.sh build openwrt-image-base"
exit 1
fi
print_step "Building target: ${target}"
# Ensure image exists
if ! image_exists; then
print_info "Docker image not found. Building it first..."
build_image
fi
docker run -it --rm \
--name "${CONTAINER_NAME}-builder" \
-v "$SCRIPT_DIR:/workspace" \
"${IMAGE_NAME}:${IMAGE_TAG}" \
-c "
source /workspace/setup-env.sh /workspace/build-x86-openwrt
bitbake ${target}
"
}
clean() {
print_step "Cleaning up Docker resources..."
# Stop and remove container
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
print_info "Removing container '${CONTAINER_NAME}'..."
docker rm -f "${CONTAINER_NAME}" 2>/dev/null || true
fi
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}-builder$"; then
print_info "Removing container '${CONTAINER_NAME}-builder'..."
docker rm -f "${CONTAINER_NAME}-builder" 2>/dev/null || true
fi
# Remove image
if image_exists; then
print_info "Removing image '${IMAGE_NAME}:${IMAGE_TAG}'..."
docker rmi "${IMAGE_NAME}:${IMAGE_TAG}" 2>/dev/null || true
fi
print_info "Cleanup complete."
}
show_help() {
echo ""
echo "OpenWrt-Yocto macOS Build Environment Setup"
echo ""
echo "Usage: ./setup-env-macos.sh [command]"
echo ""
echo "Commands:"
echo " setup Build the Docker image (default action)"
echo " shell Enter the interactive build container"
echo " build TARGET Run bitbake inside the container"
echo " clean Remove Docker image and containers"
echo " help Show this help message"
echo ""
echo "Examples:"
echo " ./setup-env-macos.sh # First-time setup"
echo " ./setup-env-macos.sh shell # Enter build shell"
echo " ./setup-env-macos.sh build openwrt-image-base # Build image"
echo " ./setup-env-macos.sh clean # Cleanup"
echo ""
echo "Quick Start Workflow:"
echo " 1. ./setup-env-macos.sh # Build Docker image"
echo " 2. ./setup-env-macos.sh shell # Enter container"
echo " 3. source ./setup-env.sh # Inside container: init env"
echo " 4. bitbake openwrt-image-base # Inside container: build"
echo ""
}
# ─── Main ────────────────────────────────────────────────────────────────────
main() {
local cmd="${1:-setup}"
case "$cmd" in
setup)
print_header
check_prerequisites
build_image
echo ""
print_info "Setup complete! Next steps:"
echo ""
echo " 1. Enter the build container:"
echo " ./setup-env-macos.sh shell"
echo ""
echo " 2. Inside the container, initialize the build:"
echo " source ./setup-env.sh"
echo ""
echo " 3. Build an image:"
echo " bitbake openwrt-image-base"
echo ""
;;
shell)
print_header
check_prerequisites
enter_shell
;;
build)
print_header
check_prerequisites
run_bitbake "$2"
;;
clean)
print_header
clean
;;
help|--help|-h)
print_header
show_help
;;
*)
print_error "Unknown command: $cmd"
show_help
exit 1
;;
esac
}
main "$@"