Buildroot: package và BR2_EXTERNAL¶
Trang này trình bày cách đưa phần mềm và tùy biến của dự án vào Buildroot, theo thứ tự: cấu trúc một package, file Config.in, file .mk với các package infrastructure, file .hash, patch, hook, cơ chế BR2_EXTERNAL, và một ví dụ hoàn chỉnh chạy trên QEMU. Khái niệm chung, thư mục output/ và các lệnh build được trình bày ở trang Buildroot.
Nội dung đối chiếu với Buildroot manual của bản LTS 2026.02 (source tag 2026.02.3).
Cấu trúc một package¶
Mỗi package là một thư mục trong package/ (hoặc trong package/ của một br2-external tree), tên thư mục là tên package viết thường:
| File | Bắt buộc | Vai trò |
|---|---|---|
Config.in |
Có, với package cho target | Khai báo option BR2_PACKAGE_<PKG> và các sub-option trong menuconfig |
Config.in.host |
Chỉ với host package xuất hiện trong menu | Khai báo option BR2_PACKAGE_HOST_<PKG> |
<pkg>.mk |
Có | Phiên bản, nguồn tải, license, dependency và cách build |
<pkg>.hash |
Có, trừ khi không thể kiểm tra hash (ví dụ source local) | Hash của file tải về và của file license |
*.patch |
Không | Patch áp vào source sau khi giải nén, theo thứ tự tên file |
| File khác | Không | Script init, file cấu hình mẫu, dùng trong .mk qua $(<PKG>_PKGDIR) |
Mọi biến trong .mk có tiền tố là tên package viết hoa, dấu - đổi thành _. Ví dụ package my-app dùng tiền tố MY_APP_.
Với package có sẵn trong Buildroot, Config.in của package phải được thêm vào package/Config.in ở đúng nhóm menu. Với package trong br2-external, thêm vào Config.in ở gốc tree (xem BR2_EXTERNAL).
File Config.in¶
Config.in dùng cú pháp Kconfig, giống Linux kernel:
config BR2_PACKAGE_LIBFOO
bool "libfoo"
depends on BR2_TOOLCHAIN_HAS_THREADS
select BR2_PACKAGE_ZLIB
help
Thư viện ví dụ.
https://example.org/libfoo
if BR2_PACKAGE_LIBFOO
config BR2_PACKAGE_LIBFOO_TOOLS
bool "install tools"
help
Cài thêm các công cụ dòng lệnh của libfoo.
endif
comment "libfoo needs a toolchain w/ threads"
depends on !BR2_TOOLCHAIN_HAS_THREADS
Quy ước của Buildroot:
bool,helpvà các thuộc tính thụt một tab. Nội dung help thụt một tab và hai dấu cách, kết thúc bằng URL upstream sau một dòng trống.- Thứ tự thuộc tính: kiểu và prompt,
default,depends ontheo target,depends ontheo toolchain,depends ontheo package khác,select, rồihelp. - Dùng
selectcho thư viện mà package cần,depends oncho yêu cầu về toolchain hoặc kiến trúc. Khi dùngdepends on, thêm mộtcommentđể menuconfig hiện lý do package bị ẩn.
Sub-option đặt trong khối if BR2_PACKAGE_<PKG> ... endif để chỉ hiện khi package được chọn.
File .mk và package infrastructure¶
File .mk gồm phần metadata (phiên bản, nguồn, license, dependency) và một dòng $(eval $(<infra>-package)) ở cuối. Infrastructure sinh ra toàn bộ rule cho các bước source, extract, patch, configure, build, install. Với build system phổ biến, infrastructure đã biết cách gọi, nên .mk chỉ cần metadata và option.
| Infrastructure | Dùng cho | Option thường dùng |
|---|---|---|
generic-package |
Makefile viết tay, script | <PKG>_BUILD_CMDS, <PKG>_INSTALL_TARGET_CMDS |
autotools-package |
./configure && make |
<PKG>_CONF_OPTS, <PKG>_AUTORECONF = YES |
cmake-package |
CMake | <PKG>_CONF_OPTS (truyền -D...) |
meson-package |
Meson | <PKG>_CONF_OPTS |
python-package |
setuptools, pep517 | <PKG>_SETUP_TYPE |
golang-package, cargo-package |
Go, Rust | Vendoring dependency khi tải source |
kernel-module |
Module kernel ngoài cây | Đi kèm $(eval $(generic-package)) |
kconfig-package |
Package cấu hình bằng Kconfig (BusyBox, U-Boot) | Sinh các target <pkg>-menuconfig, <pkg>-update-config |
Thay -package bằng host-<infra>-package (ví dụ host-generic-package) để build cùng package cho máy build, cài vào output/host/. Package cho máy build có tên với tiền tố host- trong danh sách dependency.
Metadata chung¶
| Biến | Ý nghĩa |
|---|---|
<PKG>_VERSION |
Phiên bản, hoặc tag/commit khi tải từ git |
<PKG>_SOURCE |
Tên file tarball, mặc định <pkg>-$(<PKG>_VERSION).tar.gz |
<PKG>_SITE |
URL thư mục chứa tarball, URL repository, hoặc đường dẫn local |
<PKG>_SITE_METHOD |
wget, git, svn, file (tarball local), local (thư mục source local), ... Thường tự suy ra từ SITE |
<PKG>_LICENSE, <PKG>_LICENSE_FILES |
License theo mã SPDX và file chứa nội dung license, dùng cho make legal-info |
<PKG>_DEPENDENCIES |
Package phải build và cài xong trước khi package này configure |
<PKG>_INSTALL_STAGING |
YES để cài vào staging/, cần cho thư viện. Mặc định NO |
<PKG>_INSTALL_TARGET |
NO để không cài vào target/, ví dụ thư viện tĩnh. Mặc định YES |
Ví dụ generic-package¶
################################################################################
#
# libfoo
#
################################################################################
LIBFOO_VERSION = 1.0
LIBFOO_SOURCE = libfoo-$(LIBFOO_VERSION).tar.gz
LIBFOO_SITE = http://www.foosoftware.org/download
LIBFOO_LICENSE = GPL-3.0+
LIBFOO_LICENSE_FILES = COPYING
LIBFOO_INSTALL_STAGING = YES
LIBFOO_DEPENDENCIES = host-libaaa libbbb
define LIBFOO_BUILD_CMDS
$(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D) all
endef
define LIBFOO_INSTALL_STAGING_CMDS
$(INSTALL) -D -m 0644 $(@D)/foo.h $(STAGING_DIR)/usr/include/foo.h
$(INSTALL) -D -m 0755 $(@D)/libfoo.so* $(STAGING_DIR)/usr/lib
endef
define LIBFOO_INSTALL_TARGET_CMDS
$(INSTALL) -D -m 0755 $(@D)/libfoo.so* $(TARGET_DIR)/usr/lib
endef
$(eval $(generic-package))
Ví dụ rút gọn từ tutorial generic-package trong manual. Các biến Buildroot cung cấp trong lệnh:
$(@D): thư mục source đã giải nén,output/build/libfoo-1.0/.$(TARGET_CONFIGURE_OPTS): các biếnCC,CFLAGS,LDFLAGS, ... trỏ vào cross toolchain.$(STAGING_DIR),$(TARGET_DIR),$(HOST_DIR): các thư mục cài đặt.
Với generic-package, phải tự viết các khối _BUILD_CMDS và _INSTALL_*_CMDS. Với các infrastructure khác, các khối này đã có sẵn và chỉ viết lại khi cần thay đổi hành vi mặc định.
Ví dụ cmake-package¶
LIBFOO_VERSION = 1.0
LIBFOO_SOURCE = libfoo-$(LIBFOO_VERSION).tar.gz
LIBFOO_SITE = http://www.foosoftware.org/download
LIBFOO_INSTALL_STAGING = YES
LIBFOO_INSTALL_TARGET = NO
LIBFOO_CONF_OPTS = -DBUILD_DEMOS=ON
LIBFOO_DEPENDENCIES = libglib2 host-pkgconf
$(eval $(cmake-package))
Infrastructure tự sinh toolchain file cho CMake và gọi cmake, make, make install với DESTDIR phù hợp. Vì vậy CMakeLists.txt không nên hard-code compiler hay sysroot, xem CMake.
File .hash¶
File <pkg>.hash chứa hash của tarball và của file license. Mỗi dòng gồm ba trường cách nhau bằng hai dấu cách: loại hash, giá trị hash, tên file.
# Lấy từ trang release của upstream
sha256 0a1b...e9f libfoo-1.0.tar.gz
# Tự tính
sha256 5c3d...a07 COPYING
- Loại hash:
md5,sha1,sha224,sha256,sha384,sha512. Nếu upstream không công bố hash hoặc chỉ cómd5, tự tính ít nhất một hash mạnh (nên dùngsha256) và ghi chú ở dòng comment phía trên. - Hash của file license giúp phát hiện license thay đổi khi nâng phiên bản. Hash này được kiểm tra khi chạy
make legal-info. - Với package tải từ git, Buildroot tạo tarball từ repository với hậu tố định dạng
-git4, ví dụmyapp-v1.2.0-git4.tar.gz. Hash trong file.hashlà hash của tarball này.
Package dùng SITE_METHOD = local không có tarball nên không cần file hash. Mặc định Buildroot bỏ qua kiểm tra hash với package dùng phiên bản tùy chỉnh (ví dụ kernel với BR2_LINUX_KERNEL_CUSTOM_VERSION). Khi bật BR2_DOWNLOAD_FORCE_CHECK_HASHES, mọi file tải về đều phải có ít nhất một hash hợp lệ.
Patch¶
Patch của package được áp sau bước extract, theo hai nguồn:
- Các file
*.patchtrong thư mục package, theo thứ tự tên file. Nên đặt tên dạng0001-mo-ta.patch. - Thư mục khai báo trong
BR2_GLOBAL_PATCH_DIR. Với mỗi thư mục, Buildroot tìm<dir>/<pkg>/<version>/, nếu không có thì<dir>/<pkg>/. Nếu có fileseries, thứ tự áp patch theo file đó.
BR2_GLOBAL_PATCH_DIR là cách khuyến nghị để thêm patch riêng của dự án cho bất kỳ package nào, kể cả kernel và U-Boot, mà không sửa thư mục package của Buildroot. Package dùng SITE_METHOD = local hoặc <PKG>_OVERRIDE_SRCDIR không được áp patch.
Hook¶
Hook cho phép chèn lệnh vào trước hoặc sau một bước mà không viết lại cả bước đó. Mỗi bước có cặp biến <PKG>_PRE_<BƯỚC>_HOOKS và <PKG>_POST_<BƯỚC>_HOOKS, với bước là DOWNLOAD, EXTRACT, RSYNC, PATCH, CONFIGURE, BUILD, INSTALL_STAGING, INSTALL_TARGET, INSTALL_IMAGES. Riêng host package dùng INSTALL thay cho INSTALL_STAGING và INSTALL_TARGET
define LIBFOO_REMOVE_DOC
rm -rf $(TARGET_DIR)/usr/share/doc/libfoo
endef
LIBFOO_POST_INSTALL_TARGET_HOOKS += LIBFOO_REMOVE_DOC
Một số biến tích hợp hệ thống không cần khai báo hook:
| Biến | Tác dụng |
|---|---|
<PKG>_INSTALL_INIT_SYSV |
Cài script init khi dùng BusyBox init hoặc SysV init |
<PKG>_INSTALL_INIT_SYSTEMD |
Cài unit file khi dùng systemd |
<PKG>_USERS |
Tạo user cho daemon, cùng cú pháp với users table |
<PKG>_PERMISSIONS |
Đặt owner và quyền cho file, cùng cú pháp với device table |
Cơ chế BR2_EXTERNAL¶
Phần tùy biến của dự án (package riêng, defconfig, kernel config, overlay, patch, script) có thể đặt ở hai nơi: sửa trực tiếp trong cây Buildroot và quản lý bằng nhánh git, hoặc đặt trong một thư mục riêng gọi là br2-external tree. Cách thứ hai giữ nguyên cây Buildroot, nên nâng phiên bản Buildroot chỉ cần đổi tag.
Cấu trúc br2-external tree¶
Ba file bắt buộc, có thể để rỗng:
| File | Nội dung |
|---|---|
external.desc |
name: (bắt buộc, chỉ gồm [A-Za-z0-9_]) và desc: (mô tả ngắn) |
Config.in |
source các Config.in của package, option riêng của dự án. Hiện trong menu External options |
external.mk |
include các file .mk của package, target make riêng |
Các thư mục tùy chọn:
| Thư mục | Vai trò |
|---|---|
configs/ |
Defconfig của dự án, hiện trong make list-defconfigs dưới nhãn External configs. Defconfig trùng tên với Buildroot thì bản trong br2-external được dùng |
package/ |
Package riêng, cùng cấu trúc với package của Buildroot |
board/ |
Nội dung tự do: kernel config, overlay, script post-build và post-image |
patches/ |
Dùng làm BR2_GLOBAL_PATCH_DIR |
provides/ |
Thêm lựa chọn cho các mục có nhiều implementation: toolchain, init system, skeleton, jpeg, openssl |
linux/ |
Linux kernel extension bổ sung |
Từ name: trong external.desc, Buildroot sinh biến BR2_EXTERNAL_<NAME>_PATH chứa đường dẫn tuyệt đối của tree. Biến này dùng được trong Kconfig, trong Makefile, trong defconfig và trong các script post-build, post-image. Mọi đường dẫn tới file của dự án nên viết qua biến này để tree đặt ở đâu cũng được.
Sử dụng¶
Giá trị BR2_EXTERNAL được lưu vào file .br2-external.mk trong thư mục output, nên các lệnh make sau không cần truyền lại. Dùng nhiều tree bằng danh sách cách nhau bởi dấu cách, bỏ tree bằng BR2_EXTERNAL= (rỗng). Đường dẫn tương đối được tính từ thư mục gốc của Buildroot, không phải thư mục output.
Cách tổ chức repository thường gặp là một repository dự án chứa br2-external tree và Buildroot dưới dạng git submodule, cố định ở một tag LTS. Defconfig, kernel config, overlay và patch đều nằm trong repository dự án.
Ví dụ hoàn chỉnh trên QEMU¶
Ví dụ tạo một br2-external tree tên VUX gồm package hello (C, Makefile viết tay, source nằm ngay trong tree) và một defconfig dựa trên qemu_aarch64_virt_defconfig ở trang Buildroot, có thêm rootfs overlay.
Chưa chạy thử
Ví dụ được viết theo manual và đối chiếu với file trong source Buildroot 2026.02.3, nhưng chưa được build và chạy thử trong môi trường viết trang.
br2-ext/
├── external.desc
├── Config.in
├── external.mk
├── configs/
│ └── vux_qemu_aarch64_defconfig
├── board/
│ └── vux-qemu/
│ └── rootfs-overlay/
│ └── etc/
│ └── motd
└── package/
└── hello/
├── Config.in
├── hello.mk
└── src/
├── Makefile
└── hello.c
File của tree¶
external.desc:
Config.in:
external.mk:
Package hello¶
package/hello/Config.in:
config BR2_PACKAGE_HELLO
bool "hello"
help
Chương trình hello world ví dụ, build bằng Makefile viết tay.
package/hello/hello.mk:
################################################################################
#
# hello
#
################################################################################
HELLO_VERSION = 1.0
HELLO_SITE = $(BR2_EXTERNAL_VUX_PATH)/package/hello/src
HELLO_SITE_METHOD = local
HELLO_LICENSE = MIT
define HELLO_BUILD_CMDS
$(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D)
endef
define HELLO_INSTALL_TARGET_CMDS
$(INSTALL) -D -m 0755 $(@D)/hello $(TARGET_DIR)/usr/bin/hello
endef
$(eval $(generic-package))
package/hello/src/hello.c:
package/hello/src/Makefile dùng CC, CFLAGS, LDFLAGS do $(TARGET_CONFIGURE_OPTS) truyền vào, nên không cần biết cross compiler là gì:
Với SITE_METHOD = local, Buildroot copy thư mục src/ vào output/build/hello-1.0/ bằng rsync thay vì tải tarball. Cách này phù hợp với code nằm cùng repository dự án. Source ở repository riêng thì dùng SITE_METHOD = git kèm file .hash.
Defconfig và overlay¶
configs/vux_qemu_aarch64_defconfig lấy lại các dòng của qemu_aarch64_virt_defconfig, bỏ phần build QEMU và post-image script, thêm overlay và package hello:
BR2_aarch64=y
BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_6_18=y
BR2_SYSTEM_DHCP="eth0"
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VUX_PATH)/board/vux-qemu/rootfs-overlay"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.18.7"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
BR2_TARGET_ROOTFS_EXT2=y
BR2_TARGET_ROOTFS_EXT2_4=y
# BR2_TARGET_ROOTFS_TAR is not set
BR2_PACKAGE_HELLO=y
Đường dẫn kernel config board/qemu/... là đường dẫn tương đối tính từ gốc Buildroot, dùng lại config của board QEMU. Trong dự án thực tế, copy file này vào board/vux-qemu/ của tree và trỏ qua $(BR2_EXTERNAL_VUX_PATH).
board/vux-qemu/rootfs-overlay/etc/motd:
Build và chạy¶
cd buildroot
make BR2_EXTERNAL=../br2-ext O=../output-vux vux_qemu_aarch64_defconfig
cd ../output-vux
make
Defconfig không build QEMU nên dùng QEMU của máy build (gói qemu-system-arm trên Debian/Ubuntu):
qemu-system-aarch64 -M virt -cpu cortex-a53 -nographic -smp 1 \
-kernel images/Image \
-append "rootwait root=/dev/vda console=ttyAMA0" \
-netdev user,id=eth0 -device virtio-net-device,netdev=eth0 \
-drive file=images/rootfs.ext4,if=none,format=raw,id=hd0 \
-device virtio-blk-device,drive=hd0
Sau khi đăng nhập root, nội dung /etc/motd hiện ra và lệnh hello in Hello from Buildroot.
Vòng lặp sửa code của package hello:
hello-rebuild rsync lại source, build và cài lại vào target/; all tạo lại rootfs.ext4. Sửa .mk hoặc Config.in của package thì dùng make hello-dirclean all. Sau khi chỉnh cấu hình bằng make menuconfig, lưu lại vào tree bằng:
Kiểm tra package¶
| Công cụ | Tác dụng |
|---|---|
utils/check-package |
Kiểm tra coding style của Config.in, .mk, .hash, patch. Với br2-external dùng check-package -b <đường dẫn>/*. Cần shellcheck, flake8, python-magic |
utils/test-pkg |
Build package với nhiều toolchain dựng sẵn (glibc, musl, uClibc-ng, nhiều kiến trúc) để phát hiện lỗi phụ thuộc toolchain. Đầu vào là một đoạn cấu hình, ví dụ ./utils/test-pkg -c libfoo.config -p libfoo |
make <pkg>-show-info |
In metadata của package dạng JSON |
make legal-info |
Kiểm tra license và hash của file license |
Liên quan¶
- Buildroot: tổng quan, thư mục output, các lệnh build và phát triển.
- Yocto: recipe và layer, khái niệm tương ứng với package và br2-external.
- CMake và Makefile (Programming): build system mà các package infrastructure gọi tới.
- Gói mã nguồn mở: đánh giá và tích hợp gói mã nguồn mở vào image.
Tài liệu tham khảo¶
- The Buildroot user manual. Các mục dùng trong trang: Adding new packages to Buildroot (package directory, Config files, The .hash file, generic-package, cmake-package, kernel-module, hooks), Keeping customizations outside of Buildroot, Adding project-specific patches and hashes, Tips and tricks (check-package, test-pkg), Migrating from older Buildroot versions (định dạng tarball
-git4). - Source Buildroot, tag
2026.02.3: gitlab.com/buildroot.org/buildroot, mirror github.com/buildroot/buildroot. Các fileconfigs/qemu_aarch64_virt_defconfig,board/qemu/aarch64-virt/readme.txt,package/pkg-download.mk. - Bootlin: Embedded Linux system development with Buildroot, slide và lab của khóa đào tạo.