Add BR2_EXTERNAL skeleton
This commit is contained in:
356
README.md
Normal file
356
README.md
Normal 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`).
|
||||
Reference in New Issue
Block a user