十四、buildroot 系统package新增应用 编写规则
4.7.2、编写规则
1、规范概述
Buildroot
像一个「自动化厨房」,每个包是一道菜。如果菜名(包名)、食材位置(路径)、做法(脚本)不统一,厨房会报错。规范是让机器人(Buildroot
脚本)能读懂你的菜谱。
2、命名规则
包目录名(
package/
下的文件夹)小写字母 + 短横线,如
package/my-app
配置项名(
Config.in
里的变量)BR2_PACKAGE_
+ 包目录名大写 + 下划线分隔,如BR2_PACKAGE_MY_APP
,和包目录名严格对应(复制粘贴避免拼写错误).mk
文件中的变量- 包名:
PKG_NAME := my-app
(和目录名一致) - 版本:
PKG_VERSION := 1.0
(语义化版本) - 源文件:
PKG_SOURCE := my_app.tar.gz
(建议和包名相关)
- 包名:
脚本中的路径
禁止硬编码,比如
/home/user/...
,必须使用Buildroot
内置变量:$(TOPDIR)
:Buildroot
根目录(自动识别)$(TARGET_DIR)
:最终生成的根文件系统目录(如/output/target
)$(BUILD_DIR)
:编译中间目录(如/output/build
)
3、文件结构
buildroot/
└─ package/
└─ my-app/ 包目录(和包名一致)
├─ Config.in 菜单配置(必选)
├─ my-app.mk 构建脚本(必选)
└─ my_app.tar.gz 源文件(可选,本地文件)
4、Config.in
编写(让包出现在菜单里)
config BR2_PACKAGE_MY_APP 配置项名(必须和包目录名对应)
bool "My Qt Application" 菜单显示的名称(用户看到的)
help 帮助说明(按 H 键显示)
这是我自己的 应用,安装到 /usr/bin/panorama
依赖:Qt5 库
- 必须有
config
行:否则make menuconfig
找不到你的包 - 不要用中文:菜单显示可能乱码(虽然 Buildroot 支持,但不建议)
5、.mk
文件编写(核心脚本,分 6 步)
下载源文件 → 编译 → 安装
基本信息
PKG_NAME := my-app 包名(和目录名一致)
PKG_VERSION := 1.0 版本号
PKG_LICENSE := MIT 许可证(必填,否则警告)
PKG_LICENSE_FILES := LICENSE 许可证文件(如果有源文件)
源文件位置
本地文件(推荐,避免网络问题):
PKG_SITE := $(TOPDIR)/package/my-app 本地目录
PKG_SOURCE := my_app.tar.gz 源文件名
远程下载(需网络):
PKG_SITE := http://example.com/packages 下载地址
PKG_SOURCE := my-app-$(PKG_VERSION).tar.gz
解压命令
define PKG_EXTRACT_CMDS
# 创建解压目录(Buildroot 自动管理,无需硬编码路径)
mkdir -p $(BUILD_DIR)/my-qt-app-$(PKG_VERSION)
# 复制本地文件到编译目录
cp $(PKG_SITE)/$(PKG_SOURCE) $(BUILD_DIR)/
# 解压(注意 .tar.gz 用 xvzf,.tar.xz 用 xvJf)
tar -xvzf $(BUILD_DIR)/$(PKG_SOURCE) -C $(BUILD_DIR)
endef
编译命令(可选)
如果是预编译好的二进制文件(如果应用已经是可执行文件):
define PKG_BUILD_CMDS
true 跳过编译(写 `true` 避免报错)
endef
如果需要编译(如 C 代码):
define PKG_BUILD_CMDS
$(MAKE) -C $(BUILD_DIR)/my-app-1.0 进入源码目录编译
endef
安装命令
define PKG_INSTALL_TARGET_CMDS
# 创建目标目录(避免因目录不存在报错)
mkdir -p $(TARGET_DIR)/usr/bin
# 安装文件(-D 自动创建路径,-m 755 设置权限)
install -D -m 755 $(BUILD_DIR)/my-qt-app-1.0/panorama $(TARGET_DIR)/usr/bin/panorama
endef
依赖项
PKG_DEPENDS := qt5-base 依赖的包(如你的程序需要 Qt5)
6、package
变量名规范
6.1、基础元数据后缀(必选 / 常用)
后缀名 | 作用描述 | 示例(以 mypackage 为例) |
注意事项 |
---|---|---|---|
_NAME |
包的唯一标识(小写,无空格) | mypackage_NAME := mypackage |
必须与目录名一致(package/mypackage/mypackage.mk ) |
_VERSION |
版本号(遵循语义化或上游格式) | mypackage_VERSION := 1.2.3 |
支持 git describe 等动态版本(需配合 _SITE_METHOD := git ) |
_SITE |
源代码下载地址(HTTP/FTP/Git) | mypackage_SITE := https://example.com |
优先使用官方源,避免第三方镜像 |
_LICENSE |
许可证(SPDX 标识符) | mypackage_LICENSE := GPL-2.0 |
需与 LICENSES 目录下的文本匹配(可选) |
_LIC_FILES_SCAN |
许可证文件路径(相对于解压目录) | mypackage_LIC_FILES_SCAN := */LICENSE |
自动扫描许可证时使用(非必选) |
6.2、源代码处理后缀(核心)
后缀名 | 作用描述 | 示例 | 场景说明 |
---|---|---|---|
_SOURCE |
源代码压缩包名(含扩展名) | mypackage_SOURCE := mypackage-$(mypackage_VERSION).tar.gz |
配合 _SITE 下载,支持 xz , gz , bz2 等格式 |
_EXTRACT_CMDS |
自定义解压命令(覆盖默认行为) | mypackage_EXTRACT_CMDS := tar -C $@ -xzf ... |
处理特殊压缩格式或加密包时使用 |
_SITE_METHOD |
源代码获取方式(url , git , svn , hg ) |
mypackage_SITE_METHOD := git |
Git 需配合 _SITE_URL 和 _SITE_TAG (替代 _VERSION ) |
_PATCH_DIR |
补丁目录(相对于 package/mypackage ) |
mypackage_PATCH_DIR := patches |
补丁命名需遵循 0001-xxx.patch 格式(按顺序应用) |
_NO_EXTRACT |
跳过解压(用于无需解压的包,如脚本) | mypackage_NO_EXTRACT := y |
需配合 _BUILD_IN_SOURCE := y |
6.3、编译与安装后缀(关键)
后缀名 | 作用描述 | 示例 | 经典场景 |
---|---|---|---|
_BUILD_IN_SOURCE |
在解压目录直接编译(而非 build 子目录) |
mypackage_BUILD_IN_SOURCE := y |
适用于 CMake 项目(默认隔离编译) |
_CONFIGURE_CMD |
配置命令(替代默认 ./configure ) |
mypackage_CONFIGURE_CMD := ./autogen.sh |
处理需要预处理的项目(如 autotools) |
_CONFIGURE_ARGS |
配置参数(追加到默认参数) | mypackage_CONFIGURE_ARGS := --prefix=/usr |
覆盖默认安装路径($(STAGING_DIR) ) |
_BUILD_CMD |
编译命令(替代默认 make ) |
mypackage_BUILD_CMD := make -j$(nproc) |
自定义并行编译参数 |
_INSTALL_CMD |
安装命令(替代默认 make install ) |
mypackage_INSTALL_CMD := make DESTDIR=$(TARGET_DIR) install |
明确指定安装目录(避免污染宿主) |
_STRIP_CMD |
二进制瘦身命令(默认自动调用) | mypackage_STRIP_CMD := strip --strip-debug |
针对特殊文件格式(如 WebAssembly) |
6.4、依赖与配置后缀
后缀名 | 作用描述 | 示例 | 注意事项 |
---|---|---|---|
_DEPENDS |
依赖包列表(空格分隔) | mypackage_DEPENDS := host-pkgconfig zlib |
区分 host- (宿主工具)和 target- (目标运行时)依赖 |
_KCONFIG_DEPENDS |
配置菜单依赖(Kconfig 表达式) | mypackage_KCONFIG_DEPENDS := \$(CONFIG_PACKAGE_ZLIB) |
控制包在菜单中的可见性(需与 Config.in 配合) |
_DISABLED |
禁用包(通过配置菜单隐藏) | mypackage_DISABLED := y |
临时禁用,优先级高于 Kconfig 条件 |
_SELECT |
隐式依赖(自动选中其他包) | mypackage_SELECT := packageA packageB |
用于功能捆绑(如 qt5 依赖 qtbase ) |
6.5、高级功能后缀(扩展)
后缀名 | 作用描述 | 示例 | 适用场景 |
---|---|---|---|
_SOVERSION |
共享库版本号(用于动态链接库) | mypackage_SOVERSION := 1 |
需配合 PKG_CONFIG 生成 .pc 文件 |
_TEST_SUITE |
测试套件命令 | mypackage_TEST_SUITE := make check |
仅在 BR2_PACKAGE_mypackage_TEST 启用时执行 |
_AUTORECONF_CMD |
自动生成配置文件(替代 autoreconf ) |
mypackage_AUTORECONF_CMD := autoreconf -fi |
处理老旧 autotools 项目 |
_POST_INSTALL_SCRIPT |
安装后脚本(目标根文件系统) | mypackage_POST_INSTALL_SCRIPT := $(call script,post_install) |
用于创建符号链接、初始化配置等 |
_HOST_BUILD_CMDS |
宿主工具编译命令(区分目标和宿主) | mypackage_HOST_BUILD_CMDS := make -C hosttools |
同时生成宿主工具和目标库的场景(如交叉编译工具) |
6.6、特殊约定后缀(官方保留)
后缀名 | 作用描述 | 示例 | 禁止自定义 |
---|---|---|---|
_PKG_DIR |
包目录路径(自动生成:$(TOPDIR)/package/mypackage ) |
无需手动设置 | 内部使用,禁止修改 |
_TARGET_BIN |
目标二进制文件路径(用于 file 检测) |
mypackage_TARGET_BIN := /usr/bin/mypkg |
配合 TARGET_CROSS 校验架构兼容性 |
_FINGERPRINT |
源代码指纹(校验完整性) | 自动生成(基于 _SOURCE 和 _VERSION ) |
用于增量下载时的哈希校验 |
十四、buildroot 系统package新增应用 编写规则的更多相关文章
- Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理
Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理 1. 回顾 我们知道Android输入系统是Reader线程通过驱动程序得到上报的输入事件,还要经过处理 ...
- centos Linux系统日常管理1 cpuinfo cpu核数 命令 w, vmstat, uptime ,top ,kill ,ps ,free,netstat ,sar, ulimit ,lsof ,pidof 第十四节课
centos Linux系统日常管理1 cpuinfo cpu核数 命令 w, vmstat, uptime ,top ,kill ,ps ,free,netstat ,sar, ulimit ...
- 我是如何一步步编码完成万仓网ERP系统的(十四)库存 3.库存日志
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(十四)——开发环境容器调试小技巧
之前有很多同学提到如何做容器调试,特别是k8s环境下的容器调试,今天就讲讲我是如何调试的.大家都知道在vs自带的创建项目模板里勾选docker即可通过F5启动docker容器调试.但是对于启动在k8s ...
- 代理模式 PROXY Surrogate 结构型 设计模式(十四)
代理模式 PROXY 别名Surrogate 意图 为其他的对象提供一种代理以控制对这个对象的访问. 代理模式含义比较清晰,就是中间人,中介公司,经纪人... 在计算机程序中,代理就表示一个客户端不想 ...
- Flask 教程 第十四章:Ajax
本文翻译自The Flask Mega-Tutorial Part XIV: Ajax 这是Flask Mega-Tutorial系列的第十四部分,我将使用Microsoft翻译服务和少许JavaSc ...
- 【odoo14】第十四章、CMS网站开发
第十四章.CMS网站开发** Odoo有一个功能齐全的内容管理系统(CMS).通过拖放功能,你的最终用户可以在几分钟内设计一个页面,但是在Odoo CMS中开发一个新功能或构建块就不是那么简单了.在本 ...
- 我的MYSQL学习心得(十四) 备份和恢复
我的MYSQL学习心得(十四) 备份和恢复 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) ...
- NeHe OpenGL教程 第二十四课:扩展
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第十四课:图形字体
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
随机推荐
- BUUCTF---佛说:只能四天
题目 尊即寂修我劫修如婆愍闍嚤婆莊愍耨羅嚴是喼婆斯吶眾喼修迦慧迦嚩喼斯願嚤摩隸所迦摩吽即塞願修咒莊波斯訶喃壽祗僧若即亦嘇蜜迦須色喼羅囉咒諦若陀喃慧愍夷羅波若劫蜜斯哆咒塞隸蜜波哆咤慧聞亦吽念彌諸嘚嚴諦咒 ...
- [源码系列:手写spring] IOC第七节:加载xml文件中定义的Bean
目录 主要内容 代码分支 核心代码 BeanDefinitionReader AbstractBeanDefinitionReader XmlBeanDefinitionReader 测试 bean定 ...
- [每日算法] leetcode第3题:无重复字符的最长子串
leetcode第3题入口 题目描述 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: s = "abcabcbb" 输出: 3 解法1: ...
- 「硬核实战」回调函数到底是个啥?一文带你从原理到实战彻底掌握C/C++回调函数
大家好,我是小康. 网上讲回调函数的文章不少,但大多浅尝辄止.缺少系统性,更别提实战场景和踩坑指南了.作为一个在生产环境中与回调函数打了多年交道的开发者,今天我想分享一些真正实用的经验,带你揭开回调函 ...
- nodejs参数的处理与用户的交互
解析脚本参数 作为脚本或者命令行工具,一般都需要支持不同的用户参数.默认参数被保存在process.argv的数组中,如下: [ nodeBinary, script, arg0, arg1, ... ...
- Java提交到MySQL数据库出现中文乱码
1)使用文本或者链接地址写到代码中(不推荐)时,实例如下: jdbc:mysql://localhost:3306/tms?useUnicode=true&characterEncoding= ...
- BI工具革命派vs传统强者:DataFocus.ai与Tableau的终极对决
1. 摘要 DataFocus.ai 作为新一代商业智能工具,强调基于搜索的分析方式,旨在让业务用户能够轻松进行数据探索.该平台集成了数据仓库,并侧重于赋能非技术人员进行自助式分析.其核心理念是通过自 ...
- 关于class类的知识点记录
下方代码,初始化test的一系列参数和对应的值 class SendMsg(object): def __init__(test): test.name = {'Adele baby','beckha ...
- 多模态自动驾驶混合渲染HRMAD:将NeRF和3DGS进行感知验证和端到端AD测试
基于3DGS和NeRF的三维重建技术在过去的一年中取得了快速的进步,动态模型也变得越来越普遍,然而这些模型仅限于处理原始轨迹域内的对象. HRMAD作为一种混合方案,将传统的基于网格的动态三维神经重建 ...
- HTTP表单请求
okHttp 发送表单请求 需要添加依赖 compile group: 'com.squareup.okhttp3', name: 'okhttp', version: '4.9.0' import ...