Update README and add setup scripts
This commit is contained in:
+72
@@ -0,0 +1,72 @@
|
|||||||
|
# Dockerfile for OpenWrt-Yocto Build Environment
|
||||||
|
#
|
||||||
|
# Yocto Project does NOT natively support macOS.
|
||||||
|
# This Dockerfile provides an Ubuntu-based container with all
|
||||||
|
# required build dependencies for Yocto/OpenEmbedded builds.
|
||||||
|
#
|
||||||
|
# Based on Yocto Project Scarthgap (5.0) system requirements:
|
||||||
|
# https://docs.yoctoproject.org/ref-manual/system-requirements.html
|
||||||
|
|
||||||
|
FROM ubuntu:24.04
|
||||||
|
|
||||||
|
# Prevent interactive prompts during package installation
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
# Install all required Yocto build host packages (from poky/documentation/poky.yaml.in)
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
build-essential \
|
||||||
|
chrpath \
|
||||||
|
cpio \
|
||||||
|
debianutils \
|
||||||
|
diffstat \
|
||||||
|
file \
|
||||||
|
gawk \
|
||||||
|
gcc \
|
||||||
|
git \
|
||||||
|
iputils-ping \
|
||||||
|
libacl1 \
|
||||||
|
liblz4-tool \
|
||||||
|
locales \
|
||||||
|
python3 \
|
||||||
|
python3-git \
|
||||||
|
python3-jinja2 \
|
||||||
|
python3-pexpect \
|
||||||
|
python3-pip \
|
||||||
|
python3-subunit \
|
||||||
|
socat \
|
||||||
|
texinfo \
|
||||||
|
unzip \
|
||||||
|
wget \
|
||||||
|
xz-utils \
|
||||||
|
zstd \
|
||||||
|
# Additional useful tools
|
||||||
|
sudo \
|
||||||
|
vim \
|
||||||
|
nano \
|
||||||
|
less \
|
||||||
|
bash-completion \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Set up locale (required by Yocto)
|
||||||
|
RUN locale-gen en_US.UTF-8 && update-locale LANG=en_US.UTF-8
|
||||||
|
ENV LANG=en_US.UTF-8
|
||||||
|
ENV LC_ALL=en_US.UTF-8
|
||||||
|
|
||||||
|
# Create a non-root user to match macOS host user (builds should not run as root)
|
||||||
|
ARG USER_UID=1000
|
||||||
|
ARG USER_GID=1000
|
||||||
|
RUN groupadd -g ${USER_GID} builduser && \
|
||||||
|
useradd -m -u ${USER_UID} -g builduser -s /bin/bash builduser && \
|
||||||
|
echo "builduser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
|
||||||
|
|
||||||
|
# Create working directory
|
||||||
|
RUN mkdir -p /workspace && chown builduser:builduser /workspace
|
||||||
|
|
||||||
|
# Switch to non-root user
|
||||||
|
USER builduser
|
||||||
|
WORKDIR /workspace
|
||||||
|
|
||||||
|
# Set Git safe directory (since the mounted volume may have different ownership)
|
||||||
|
RUN git config --global --add safe.directory /workspace
|
||||||
|
|
||||||
|
ENTRYPOINT ["/bin/bash"]
|
||||||
@@ -6,7 +6,9 @@
|
|||||||
|
|
||||||
```
|
```
|
||||||
03-openwrt-yocto/
|
03-openwrt-yocto/
|
||||||
├── setup-env.sh # 一键初始化脚本
|
├── setup-env.sh # Linux 环境初始化脚本
|
||||||
|
├── setup-env-macos.sh # macOS Docker 编译环境脚本
|
||||||
|
├── Dockerfile # Yocto 编译容器镜像定义
|
||||||
├── poky/ # Yocto 核心框架 (BitBake + OE-Core)
|
├── poky/ # Yocto 核心框架 (BitBake + OE-Core)
|
||||||
│ ├── bitbake/ # BitBake 构建引擎
|
│ ├── bitbake/ # BitBake 构建引擎
|
||||||
│ ├── meta/ # OpenEmbedded-Core 基础层
|
│ ├── meta/ # OpenEmbedded-Core 基础层
|
||||||
@@ -48,7 +50,7 @@ source ./setup-env.sh
|
|||||||
|
|
||||||
> 所有操作均为幂等:重复执行不会产生重复配置。
|
> 所有操作均为幂等:重复执行不会产生重复配置。
|
||||||
|
|
||||||
### 2. 构建镜像
|
### 2. 构建镜像 (Linux)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 最小化 CLI 系统(无 Web 界面)
|
# 最小化 CLI 系统(无 Web 界面)
|
||||||
@@ -144,3 +146,65 @@ packagegroup-openwrt-full (继承 base)
|
|||||||
- Yocto 版本: Scarthgap (5.0) / Nanbield (4.3)
|
- Yocto 版本: Scarthgap (5.0) / Nanbield (4.3)
|
||||||
- 已验证目标: qemux86-64
|
- 已验证目标: qemux86-64
|
||||||
- Linux 内核: 6.6 (yocto-standard)
|
- Linux 内核: 6.6 (yocto-standard)
|
||||||
|
- **macOS**: 通过 Docker 容器支持(详见下方 macOS 编译章节)
|
||||||
|
|
||||||
|
## macOS 编译 (Docker)
|
||||||
|
|
||||||
|
> **Yocto Project 不支持在 macOS 上原生编译。** 官方推荐的跨平台方案是通过 Docker 容器运行 Linux 编译环境。
|
||||||
|
|
||||||
|
#### 前置条件
|
||||||
|
|
||||||
|
1. 安装 [Docker Desktop for Mac](https://docs.docker.com/desktop/setup/mac/)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew install --cask docker
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 启动 Docker Desktop 并确保 Docker 守护进程在运行。
|
||||||
|
|
||||||
|
3. 确保至少有 **50GB** 可用磁盘空间。
|
||||||
|
|
||||||
|
#### 初始化 macOS 编译环境
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/03-openwrt-yocto
|
||||||
|
|
||||||
|
# 首次运行:构建 Docker 镜像(约需数分钟)
|
||||||
|
./setup-env-macos.sh
|
||||||
|
|
||||||
|
# 进入编译容器
|
||||||
|
./setup-env-macos.sh shell
|
||||||
|
```
|
||||||
|
|
||||||
|
进入容器后,在容器内初始化 Yocto 环境并编译:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 在 Docker 容器内执行:
|
||||||
|
source ./setup-env.sh # 初始化 BitBake 环境
|
||||||
|
bitbake openwrt-image-base # 编译镜像
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 一键编译
|
||||||
|
|
||||||
|
也可以直接从 macOS 宿主机发起编译:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./setup-env-macos.sh build openwrt-image-base
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 可用命令
|
||||||
|
|
||||||
|
| 命令 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| `./setup-env-macos.sh` | 构建 Docker 镜像(首次必需) |
|
||||||
|
| `./setup-env-macos.sh shell` | 进入交互式编译容器 |
|
||||||
|
| `./setup-env-macos.sh build <target>` | 在容器中执行 bitbake 编译 |
|
||||||
|
| `./setup-env-macos.sh clean` | 清理 Docker 镜像和容器 |
|
||||||
|
| `./setup-env-macos.sh help` | 查看帮助 |
|
||||||
|
|
||||||
|
#### 技术说明
|
||||||
|
|
||||||
|
- Docker 镜像基于 **Ubuntu 24.04**(Yocto Scarthgap 官方支持的发行版)
|
||||||
|
- 编译产物位于宿主机的 `build-x86-openwrt/tmp/deploy/images/` 目录
|
||||||
|
- 容器与宿主机共享项目目录,修改即时生效
|
||||||
|
- 容器内的用户 UID/GID 与宿主机用户一致,避免文件权限问题
|
||||||
|
|||||||
Executable
+317
@@ -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 "$@"
|
||||||
Reference in New Issue
Block a user