Add BR2_EXTERNAL skeleton

This commit is contained in:
2026-03-27 20:57:59 -03:00
parent 27cfa662a3
commit 162a815132
16 changed files with 632 additions and 0 deletions

356
README.md Normal file
View File

@@ -0,0 +1,356 @@
# br2-external-common
Common Buildroot BR2_EXTERNAL tree for all Raspberry Pi projects. This
repository provides shared board support, packages, rootfs overlays, and
patches that are used across multiple projects.
This repository also pins the upstream Buildroot version as a git submodule,
serving as the single source of truth for which Buildroot release is used. When
a project pulls in this repo, it transitively gets the tested Buildroot version.
## Repository layout
```
br2-external-common/
├── external.desc Buildroot external tree descriptor (name: RPI_COMMON)
├── external.mk Includes all common package .mk files
├── Config.in Top-level Kconfig menu for common packages
├── Makefile Wrapper for standalone build invocations
├── buildroot/ [submodule] Upstream Buildroot, pinned to release tag
├── board/
│ └── raspberrypi/
│ ├── post_build.sh Shared post-build script (rootfs fixups)
│ ├── post_image.sh Shared post-image script (genimage invocation)
│ ├── genimage.cfg SD card partition layout
│ └── overlay/ Shared rootfs overlay (copied into target rootfs)
│ └── etc/
│ └── network/
│ └── interfaces
├── package/
│ ├── my-shared-lib/ Example shared library (CMake package)
│ └── my-common-tool/ Example shared tool (generic package)
├── patches/ Patches to upstream Buildroot packages
└── configs/
└── rpi_common_test_defconfig Minimal defconfig for standalone CI testing
```
## Standalone setup
Use this to develop and test the common tree without any project-specific
additions. This is also what CI should run on every commit to this repo.
### Prerequisites
A Linux host with standard Buildroot dependencies installed. See the Buildroot
manual for the full list. On Debian/Ubuntu:
```sh
sudo apt-get install -y build-essential gcc g++ bash patch gzip bzip2 \
perl tar cpio unzip rsync file bc wget libncurses-dev git
```
### Clone and initialize
```sh
git clone git@github.com:your-org/br2-external-common.git
cd br2-external-common
git submodule update --init
```
This pulls the Buildroot source into `buildroot/` at the pinned release tag.
### Build the test image
The wrapper Makefile handles the Buildroot invocation:
```sh
make defconfig # Loads rpi_common_test_defconfig
make # Builds the full image (takes a while on first run)
```
The SD card image will be at `output/images/sdcard.img`.
### Useful build commands
```sh
make menuconfig # Open Buildroot configuration menu
make savedefconfig # Save current .config back to the test defconfig
make linux-rebuild # Rebuild just the kernel (any Buildroot target works)
make my-shared-lib-rebuild # Rebuild a specific package
make clean # Clean build artifacts
make distclean # Remove the entire output directory
```
You can use a different defconfig by passing DEFCONFIG:
```sh
make defconfig DEFCONFIG=rpi_common_minimal_defconfig
```
## Creating a new project
A project is a separate git repository that uses this common tree as a
submodule. Each project is its own BR2_EXTERNAL and contains only
project-specific packages, overlays, defconfigs, and board overrides.
### Step 1: Create the project repository
```sh
mkdir br2-external-myproject
cd br2-external-myproject
git init
```
### Step 2: Add common as a submodule
```sh
git submodule add git@github.com:your-org/br2-external-common.git common
git submodule update --init --recursive
```
The `--recursive` is important because it also pulls common's own Buildroot
submodule into `common/buildroot/`.
### Step 3: Create the BR2_EXTERNAL descriptor
Create `external.desc` at the project root. The name must be unique across all
external trees and must be a valid C identifier (uppercase, underscores only):
```
name: MY_PROJECT
desc: My project-specific Buildroot configuration
```
### Step 4: Create external.mk
This file includes only the project's own packages. The common packages are
handled by the common tree's own `external.mk` — Buildroot merges them
automatically because both trees are passed as separate BR2_EXTERNAL paths.
```makefile
include $(sort $(wildcard $(BR2_EXTERNAL_MY_PROJECT_PATH)/package/*/*.mk))
```
### Step 5: Create Config.in
Same principle — only source the project's own package configs:
```
menu "My Project packages"
source "$BR2_EXTERNAL_MY_PROJECT_PATH/package/my-app/Config.in"
endmenu
```
### Step 6: Create a project defconfig
Create `configs/rpi_myproject_defconfig`. Start by copying the common test
defconfig and modify it:
```sh
cp common/configs/rpi_common_test_defconfig configs/rpi_myproject_defconfig
```
Edit the defconfig to:
1. Add both overlays (common first, then project-specific):
```
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_RPI_COMMON_PATH)/board/raspberrypi/overlay $(BR2_EXTERNAL_MY_PROJECT_PATH)/overlay"
```
2. Add project-specific packages:
```
BR2_PACKAGE_MY_APP=y
```
The common packages (`BR2_PACKAGE_MY_SHARED_LIB`, etc.) remain as-is.
### Step 7: Create the wrapper Makefile
Create a `Makefile` at the project root:
```makefile
BUILDROOT_DIR := $(CURDIR)/common/buildroot
OUTPUT_DIR := $(CURDIR)/output
BR2_EXTERNAL := $(CURDIR)/common:$(CURDIR)
DEFCONFIG ?= rpi_myproject_defconfig
CONFIG_EXISTS := $(wildcard $(OUTPUT_DIR)/.config)
.PHONY: all defconfig menuconfig savedefconfig clean distclean
all:
ifeq ($(CONFIG_EXISTS),)
@echo "No .config found. Run 'make defconfig' first."
@exit 1
endif
$(MAKE) -C $(BUILDROOT_DIR) BR2_EXTERNAL=$(BR2_EXTERNAL) O=$(OUTPUT_DIR)
defconfig:
$(MAKE) -C $(BUILDROOT_DIR) BR2_EXTERNAL=$(BR2_EXTERNAL) O=$(OUTPUT_DIR) $(DEFCONFIG)
menuconfig:
$(MAKE) -C $(BUILDROOT_DIR) BR2_EXTERNAL=$(BR2_EXTERNAL) O=$(OUTPUT_DIR) menuconfig
savedefconfig:
$(MAKE) -C $(BUILDROOT_DIR) BR2_EXTERNAL=$(BR2_EXTERNAL) O=$(OUTPUT_DIR) savedefconfig \
BR2_DEFCONFIG=$(CURDIR)/configs/$(DEFCONFIG)
clean:
$(MAKE) -C $(BUILDROOT_DIR) BR2_EXTERNAL=$(BR2_EXTERNAL) O=$(OUTPUT_DIR) clean
distclean:
rm -rf $(OUTPUT_DIR)
%:
$(MAKE) -C $(BUILDROOT_DIR) BR2_EXTERNAL=$(BR2_EXTERNAL) O=$(OUTPUT_DIR) $@
```
Note the key difference from the common Makefile:
- `BUILDROOT_DIR` points to `common/buildroot/` (nested submodule)
- `BR2_EXTERNAL` lists both trees, colon-separated: `common:project`
### Step 8: Create supporting directories
```sh
mkdir -p overlay/etc
mkdir -p package
mkdir -p board
mkdir -p configs
echo '/output/' > .gitignore
```
### Step 9: Commit and build
```sh
git add -A
git commit -m "Initial project skeleton"
make defconfig
make
```
### Project directory structure
After following these steps, your project should look like this:
```
br2-external-myproject/
├── external.desc
├── external.mk
├── Config.in
├── Makefile
├── .gitmodules
├── .gitignore
├── common/ [submodule -> br2-external-common]
│ ├── buildroot/ [nested submodule -> upstream Buildroot]
│ ├── board/raspberrypi/
│ ├── package/
│ └── ...
├── configs/
│ └── rpi_myproject_defconfig
├── overlay/ Project-specific rootfs overlay
├── package/ Project-specific packages
│ └── my-app/
└── output/ Build output (gitignored)
```
## Branching strategy
This repository uses long-lived branches to support multiple Buildroot
versions simultaneously, mirroring Buildroot's own LTS release model.
### Branch naming
- `main` — Tracks the latest Buildroot release (currently 2026.02). Active
development of shared packages happens here.
- `YYYY.MM.x` — Maintenance branches for older Buildroot LTS lines (e.g.,
`2023.02.x`). These receive only bug fixes and minor Buildroot bumps within
the same LTS series.
### Creating a maintenance branch
When a project needs to stay on an older Buildroot version:
```sh
# Start from the last commit that used the older Buildroot
git checkout -b 2023.02.x <commit-hash>
# Verify the buildroot submodule points to the right tag
cd buildroot
git log --oneline -1 # Should show 2023.02.x tag
cd ..
git push -u origin 2023.02.x
```
### Bumping a minor Buildroot version on a maintenance branch
For example, upgrading from 2023.02.1 to 2023.02.2:
```sh
git checkout 2023.02.x
cd buildroot
git fetch --tags
git checkout 2023.02.2
cd ..
git add buildroot
git commit -m "buildroot: bump to 2023.02.2"
git push
```
Then in the project that uses this branch:
```sh
cd common
git pull origin 2023.02.x
cd ..
git add common
git commit -m "common: pick up buildroot 2023.02.2"
```
### Backporting shared package fixes
When a bug fix on `main` also applies to a maintenance branch:
```sh
git checkout 2023.02.x
git cherry-pick <commit-hash-from-main>
# Resolve conflicts if the package versions have diverged
# Test with: make defconfig && make
git push
```
### End-of-life
When a legacy project is decommissioned, its maintenance branch can be
archived (renamed to `archive/2023.02.x`) or deleted. No other projects
are affected.
## Adding a new shared package
1. Create a directory under `package/` with the package name.
2. Add a `Config.in` with the Kconfig entry.
3. Add a `.mk` file with the Buildroot package recipe.
4. Source the new `Config.in` in the top-level `Config.in`.
5. Enable the package in `configs/rpi_common_test_defconfig`.
6. Build and verify: `make my-new-package-rebuild`.
See `package/my-shared-lib/` (CMake example) and `package/my-common-tool/`
(generic example) for reference.
## Adding patches to upstream Buildroot packages
Place patch files under `patches/<package-name>/`. Buildroot automatically
applies patches from `BR2_EXTERNAL_RPI_COMMON_PATH/patches/<package-name>/`
during the package build. Patches must follow Buildroot's naming convention:
`NNNN-description.patch` (e.g., `0001-fix-cross-compilation.patch`).