6.7 KiB
Agent Guide - Building and Compiling
This document provides the correct procedures for building this RP2350 project. Follow these instructions to avoid common pitfalls.
Build System
This project uses:
- CMake for configuration
- Ninja as the build system (not Make)
- Pico SDK 2.2.0 with the VS Code extension
Initial Setup
The project must be configured with CMake using the Ninja generator before building:
cd /Users/adolforeyna/Projects/pico-bare-metal/Adolfo/basic1
rm -rf build # Clean start
cmake -B build -G Ninja -DPICO_BOARD=adafruit_feather_rp2350
IMPORTANT: Always specify -G Ninja when running cmake. Without it, CMake generates Makefiles which won't work with the ninja command.
Building
Using Ninja Directly
After cmake configuration:
cd /Users/adolforeyna/Projects/pico-bare-metal/Adolfo/basic1/build
ninja
Or from project root:
cd /Users/adolforeyna/Projects/pico-bare-metal/Adolfo/basic1
ninja -C build
Using VS Code Task
The project has a "Compile Project" task that runs:
/Users/adolforeyna/.pico-sdk/ninja/v1.12.1/ninja -C /path/to/build
However, this task will fail if build.ninja doesn't exist. You must run cmake first.
Quick Rebuild
If you only changed source files (not CMakeLists.txt):
cd build
ninja
If you changed CMakeLists.txt or added/removed files:
cd build
cmake -G Ninja ..
ninja
Building for Different Boards
Single Board
# Clean and configure for specific board
rm -rf build
cmake -B build -G Ninja -DPICO_BOARD=pico2
cd build && ninja
Available boards:
adafruit_feather_rp2350(default)pico2pico2_w
All Boards at Once
Use the provided script:
./build_all_boards.sh
This creates:
build_adafruit_feather_rp2350/basic1.uf2→basic1_adafruit_feather_rp2350.uf2build_pico2/basic1.uf2→basic1_pico2.uf2build_pico2_w/basic1.uf2→basic1_pico2_w.uf2
Verifying Build Success
Check for Output Files
ls -lh build/basic1.{uf2,elf,bin}
Successful build produces:
basic1.uf2- Flash file for bootloader (≈150KB)basic1.elf- Executable with debug symbols (≈1.1MB)basic1.bin- Raw binary (≈74KB)basic1.hex- Intel HEX formatbasic1.dis- Disassembly (≈877KB)
Check File Timestamp
stat build/basic1.uf2
Verify the modification time is recent.
Look for Ninja Success Message
Successful build ends with:
[90/90] Linking CXX executable basic1.elf
Failed build shows:
ninja: build stopped: subcommand failed.
Common Issues and Solutions
Issue: "ninja: error: loading 'build.ninja': No such file or directory"
Cause: CMake wasn't run or didn't generate Ninja files
Solution:
cd /Users/adolforeyna/Projects/pico-bare-metal/Adolfo/basic1
cmake -B build -G Ninja -DPICO_BOARD=adafruit_feather_rp2350
Issue: Build directory has Makefiles instead of build.ninja
Cause: CMake was run without -G Ninja
Solution:
rm -rf build
cmake -B build -G Ninja -DPICO_BOARD=adafruit_feather_rp2350
Issue: Compilation errors after adding new files
Cause: CMakeLists.txt not updated or cmake not re-run
Solution:
- Add new files to
CMakeLists.txtin theadd_executable()section - Re-run cmake:
cd build cmake -G Ninja .. ninja
Issue: Changes not reflected in build
Cause: Stale build cache
Solution:
cd build
ninja clean
ninja
Or full rebuild:
rm -rf build
cmake -B build -G Ninja -DPICO_BOARD=adafruit_feather_rp2350
cd build && ninja
Checking for Errors
Compilation Errors
Look for errors in ninja output:
[12/90] Building CXX object CMakeFiles/basic1.dir/basic1.cpp.o
FAILED: CMakeFiles/basic1.dir/basic1.cpp.o
...
error: 'foo' was not declared in this scope
Viewing Recent Build Output
cd build
ninja 2>&1 | tail -50 # Last 50 lines
Viewing Full Build Output
cd build
ninja 2>&1 | tee build.log
Build Output Location
build/
├── basic1.uf2 # Main flash file
├── basic1.elf # Executable with symbols
├── basic1.bin # Raw binary
├── basic1.hex # Intel HEX
├── basic1.dis # Disassembly
├── basic1.elf.map # Memory map
├── build.ninja # Ninja build file (must exist!)
├── CMakeCache.txt # CMake configuration
└── compile_commands.json # For IDE integration
Integration with Tools
VS Code Tasks
The project includes pre-configured tasks in .vscode/tasks.json:
- Compile Project - Runs ninja in build directory
These tasks expect build/build.ninja to exist.
CMake Extension
If using CMake Tools extension:
- Select kit: "Pico ARM GCC"
- Configure with Ninja generator
- Build target: "basic1"
Quick Reference Commands
# Full clean build (default board)
rm -rf build && cmake -B build -G Ninja && ninja -C build
# Full clean build (specific board)
rm -rf build && cmake -B build -G Ninja -DPICO_BOARD=pico2 && ninja -C build
# Incremental build
ninja -C build
# Build all boards
./build_all_boards.sh
# Check build output
ls -lh build/basic1.uf2
# View compile commands
cat build/compile_commands.json | grep -A5 basic1.cpp
Testing Build Success
After building, you can verify the binary contains expected symbols:
arm-none-eabi-nm build/basic1.elf | grep -i main
arm-none-eabi-size build/basic1.elf
Important Notes
- Always use
-G Ninjawhen running cmake - The build directory must be recreated when switching boards
- ninja must be run from the build directory or with
-C build - CMake must be re-run after modifying CMakeLists.txt
- The Pico SDK path is at
~/.pico-sdk/sdk/2.2.0 - The toolchain is at
~/.pico-sdk/toolchain/14_2_Rel1 - Output files are always in the
build/directory (or board-specific build dirs)
When Making Changes
| Change Type | Required Action |
|---|---|
| Source code (.cpp, .c) | ninja -C build |
| Header files (.h) | ninja -C build |
| CMakeLists.txt | cd build && cmake -G Ninja .. && ninja |
| New board | rm -rf build && cmake -B build -G Ninja -DPICO_BOARD=<board> && ninja -C build |
| New files | Update CMakeLists.txt, then re-run cmake |
| board_config.h | ninja -C build |
Flashing
After successful build:
- Manual: Hold BOOTSEL, connect USB, copy
build/basic1.uf2to mounted drive - Script:
./build_and_flash.sh(requires openocd or picotool) - VS Code: Use "Run Project" or "Flash" tasks
Serial Monitor
View serial output:
screen /dev/cu.usbmodem101
Exit: Ctrl-A, then K, then Y
Or use VS Code's serial monitor extension.