From b62a86bdc7bdf2f837248e6bf95a965b28bc554b Mon Sep 17 00:00:00 2001 From: Mohamed Salem Date: Mon, 13 Apr 2026 04:06:15 +0200 Subject: [PATCH] Move build.sh and flash.sh to repo root as shared scripts build.sh runs inside Docker (mounted at /scripts/build.sh via docker-compose volume). flash.sh runs on the host and takes the project name as an argument, auto-detecting the .uf2 file. Usage: cd color_switcher && docker compose run --rm pico-build bash /scripts/build.sh cd .. && ./flash.sh color_switcher --- README.md | 10 ++-- build.sh | 22 +++++++ color_switcher/build.sh | 25 -------- .../cmake/cmake_config/mcu_config.cmake | 2 +- color_switcher/docker-compose.yml | 1 + color_switcher/flash.sh | 46 -------------- flash.sh | 60 +++++++++++++++++++ 7 files changed, 90 insertions(+), 76 deletions(-) create mode 100755 build.sh delete mode 100755 color_switcher/build.sh delete mode 100755 color_switcher/flash.sh create mode 100755 flash.sh diff --git a/README.md b/README.md index 2eb5035..7aaeaa1 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,9 @@ Each project is independent. To work on one, `cd` into its folder: ```bash cd color_switcher/ -docker compose build # first time only -docker compose run --rm pico-build bash build.sh # compile -./flash.sh # flash (hold BOOTSEL + plug in) +docker compose build # first time only +docker compose run --rm pico-build bash /scripts/build.sh # compile +cd .. && ./flash.sh color_switcher # flash (hold BOOTSEL + plug in) ``` See each project's own `README.md` for project-specific instructions. @@ -68,8 +68,10 @@ pico/ │ ├── src/ # project-specific components (APP_CLSW, SYS_ECU) │ ├── Dockerfile # containerized ARM cross-compilation │ ├── docker-compose.yml -│ ├── build.sh / flash.sh +│ └── docker-compose.yml │ └── CLAUDE.md / README.md +├── build.sh # shared build script (runs inside Docker) +├── flash.sh # shared flash script (runs on host macOS) ├── .gitmodules ├── CLAUDE.md └── README.md # this file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..020bd7c --- /dev/null +++ b/build.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# ============================================================================ +# build.sh — Build Pico firmware for a given project +# ============================================================================ +# Runs inside Docker. CMake source directory is the project's cmake/ folder. +# Build artifacts (including the .uf2) land in the project's build/ folder. +# +# Usage (from inside Docker container): +# bash /scripts/build.sh +# +# The script auto-detects the project directory from the Docker working +# directory (/project), so no arguments are needed. +# ============================================================================ + +set -e + +# Configure: cmake/ holds the CMakeLists.txt, build/ holds the output +cmake -S cmake -B build + +# Compile using all available CPU cores +cmake --build build -j"$(nproc)" \ No newline at end of file diff --git a/color_switcher/build.sh b/color_switcher/build.sh deleted file mode 100755 index 3c803b9..0000000 --- a/color_switcher/build.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -# Build script for the Pico firmware. -# Creates an out-of-source build directory to keep generated files -# separate from the project source code. -# -# Directory layout expected at project root: -# cmake/ - all build-system files (CMakeLists.txt + cmake_config/) -# src/ - application source code -# build/ - created by this script, holds all CMake/Make output -# -# Using -S and -B lets us point CMake at the cmake/ source folder while -# keeping the build artifacts in a sibling build/ folder at the project root. - -# Fail fast on any error so a broken configure step doesn't silently lead -# to a confusing make error further down. -set -e - -# Configure the build: tell CMake the source directory is cmake/ and the -# binary (build) directory is build/. CMake will create build/ if needed. -cmake -S cmake -B build - -# Compile everything using all available CPU cores. The final output is a -# .uf2 file in build/ that can be dragged onto the Pico's USB mass storage. -cmake --build build -j"$(nproc)" diff --git a/color_switcher/cmake/cmake_config/mcu_config.cmake b/color_switcher/cmake/cmake_config/mcu_config.cmake index 936670e..b4ca273 100644 --- a/color_switcher/cmake/cmake_config/mcu_config.cmake +++ b/color_switcher/cmake/cmake_config/mcu_config.cmake @@ -97,7 +97,7 @@ function(mcu_link_target target) # When running inside Docker, the target will fail with a clear error # from flash.sh ("not found" or "/Volumes/RPI-RP2 not accessible"). add_custom_target(flash - COMMAND bash ${PROJECT_ROOT_DIR}/flash.sh + COMMAND bash ${PROJECT_ROOT_DIR}/../flash.sh ${PROJECT_NAME} DEPENDS ${target} WORKING_DIRECTORY ${PROJECT_ROOT_DIR} COMMENT "Flashing firmware to Pico via USB mass storage" diff --git a/color_switcher/docker-compose.yml b/color_switcher/docker-compose.yml index 25ccb62..d135a8e 100644 --- a/color_switcher/docker-compose.yml +++ b/color_switcher/docker-compose.yml @@ -28,6 +28,7 @@ services: volumes: - .:/project - ../common:/common + - ../build.sh:/scripts/build.sh # Keep the container alive indefinitely. We intentionally do NOT run the # build on startup - `sleep infinity` lets the container stay up so it can diff --git a/color_switcher/flash.sh b/color_switcher/flash.sh deleted file mode 100755 index d16ef8a..0000000 --- a/color_switcher/flash.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash - -# ============================================================================ -# flash.sh - Flash firmware to the Raspberry Pi Pico -# ============================================================================ -# This script MUST run on the host macOS (not inside Docker) because it -# needs access to /Volumes/RPI-RP2, the USB mass storage mount point that -# appears when the Pico is held in BOOTSEL mode during power-on. -# -# Usage: -# 1. Hold BOOTSEL on the Pico and plug it into USB -# 2. Run: ./flash.sh -# -# Or chain with a build: -# docker compose run --rm pico-build bash build.sh && ./flash.sh -# ============================================================================ - -PICO_MOUNT="/Volumes/RPI-RP2" -UF2_FILE="build/Color_Switcher_PICO.uf2" - -# Verify the firmware file exists before waiting for the Pico -if [ ! -f "$UF2_FILE" ]; then - echo "Error: $UF2_FILE not found. Run the build first:" - echo " docker compose run --rm pico-build bash build.sh" - exit 1 -fi - -# Wait for the Pico to appear in BOOTSEL mode -echo "Waiting for Pico in BOOTSEL mode ($PICO_MOUNT)..." -echo " -> Hold BOOTSEL and plug in the Pico via USB" -while [ ! -d "$PICO_MOUNT" ]; do - sleep 0.5 -done - -# Copy the firmware to the Pico's USB mass storage -echo "Pico detected. Copying $UF2_FILE..." -cp "$UF2_FILE" "$PICO_MOUNT/" - -# Wait for the Pico to unmount (it reboots automatically after receiving the .uf2) -echo "Waiting for Pico to reboot..." -while [ -d "$PICO_MOUNT" ]; do - sleep 0.5 -done - -echo "Done! Pico rebooted with new firmware." -echo " -> Open a serial monitor: screen /dev/tty.usbmodem* 115200" \ No newline at end of file diff --git a/flash.sh b/flash.sh new file mode 100755 index 0000000..46b15c6 --- /dev/null +++ b/flash.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +# ============================================================================ +# flash.sh — Flash Pico firmware for a given project +# ============================================================================ +# Runs on the HOST macOS (not inside Docker) because it needs access to +# /Volumes/RPI-RP2, the USB mass storage mount that appears when the Pico +# is held in BOOTSEL mode. +# +# Usage: +# ./flash.sh +# +# Example: +# ./flash.sh color_switcher +# +# The script finds the .uf2 file in the project's build/ directory +# automatically — no hardcoded firmware name needed. +# ============================================================================ + +set -e + +# --- Validate arguments --- +PROJECT="${1:?Usage: ./flash.sh (e.g., ./flash.sh color_switcher)}" + +# Resolve paths relative to this script's location (the repo root) +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +BUILD_DIR="$SCRIPT_DIR/$PROJECT/build" +PICO_MOUNT="/Volumes/RPI-RP2" + +# --- Find the .uf2 file --- +UF2_FILE=$(find "$BUILD_DIR" -maxdepth 1 -name "*.uf2" 2>/dev/null | head -1) + +if [ -z "$UF2_FILE" ]; then + echo "Error: No .uf2 file found in $BUILD_DIR" + echo " Run the build first:" + echo " cd $PROJECT && docker compose run --rm pico-build bash /scripts/build.sh" + exit 1 +fi + +echo "Firmware: $UF2_FILE" + +# --- Wait for the Pico in BOOTSEL mode --- +echo "Waiting for Pico in BOOTSEL mode ($PICO_MOUNT)..." +echo " -> Hold BOOTSEL and plug in the Pico via USB" +while [ ! -d "$PICO_MOUNT" ]; do + sleep 0.5 +done + +# --- Copy the firmware --- +echo "Pico detected. Copying $(basename "$UF2_FILE")..." +cp "$UF2_FILE" "$PICO_MOUNT/" + +# --- Wait for reboot --- +echo "Waiting for Pico to reboot..." +while [ -d "$PICO_MOUNT" ]; do + sleep 0.5 +done + +echo "Done! Pico rebooted with new firmware." +echo " -> Open a serial monitor: screen /dev/tty.usbmodem* 115200" \ No newline at end of file