# cbuild-ng
**Repository Path**: lengjingzju/cbuild-ng
## Basic Information
- **Project Name**: cbuild-ng
- **Description**: CBuild编译系统,如下特性:
1.任务解析管理器,menuconfig配置,make运行
2.比CMake更快的编译工具,同一Makefile支持Classic/Yocto组合Cross/Native共4种编译;支持指定:O输出,DESTDIR安装,DEPDIR依赖
3.处理软件编译整个过程的脚本:支持网络下载、缓存处理和镜像加速等,支持类似repo作用的代码开发管理和Yocto的发布管理
- **Primary Language**: C
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 14
- **Forks**: 3
- **Created**: 2023-03-11
- **Last Updated**: 2025-12-30
## Categories & Tags
**Categories**: ci
**Tags**: None
## README

# CBuild-ng 编译系统
[English Edition](./README.md)
[CBuild-ng:构建系统的范式转移与价值重构](./notes/cbuild_zh-cn.md)
[IMake:让构建回归Makefile本质,前所未有的简单体验](./notes/imake_zh-cn.md)
[IMake:为Linux原生开发重塑构建系统的清晰与效率](./notes/cmp_cmake_zh-cn.md)
[CPK:一场回归软件本真的打包分发哲学实践](./notes/cpk_zh-cn.md)
[软件框架的十大设计原则](./notes/framework_zh-cn.md)
## 概述
CBuild-ng是一款由中国开发者打造的高性能编译系统,专为嵌入式Linux及复杂软件栈构建而设计。它以轻量级核心(仅7000行代码)、极简设计和灵活兼容为核心理念,融合传统编译与Yocto模式的优势,提供比Buildroot更强大的功能,同时规避Yocto的复杂性。
* 零门槛上手:无需学习新语言,基于Python/Shell/Makefile脚本实现,配置直观(支持类Linux的`menuconfig`),比Buildroot/Yocto更易理解。
* 双模式驱动:
* Classic Build:独立构建模式,依赖隔离清晰,支持缓存加速与跨平台部署。
* Yocto Build:深度封装Yocto,提供 `make` 命令层和图形化配置,简化复杂元数据操作。
* 企业级特性:智能依赖分析、多版本兼容、安全补丁管理,满足工业级开发需求。
CBuild-ng 对比 [CBuild](https://github.com/lengjingzju/cbuild) 最大的区别是 Classic Build 引入了 `WORKDIR` 概念,每个包都在自己的 `WORKDIR` 下的特定目录下准备依赖、编译、安装,包之间的依赖关系和 sysroot 由自动生成的顶层 Makefile 处理。
## 为何选择 CBuild-ng
1️⃣ **极致性能与资源优化**
* 编译速度快:实测300个软件包构建耗时仅5分钟,重编译仅49秒,速度远超Yocto(节省2/3时间)。
* 低资源占用:输出文件系统体积仅为Yocto的1/4(1.8G vs 7.4G),显著降低存储成本。
* 编译缓存机制:支持本地/远程镜像缓存,重复构建直接复用结果,节省90%以上时间。
2️⃣ **零学习曲线的友好设计**
* 无新语言:基于Python/Shell/Makefile,开发者无需学习DSL,开箱即用。
* Kconfig图形化配置:提供类Linux内核的`make menuconfig`界面,依赖关系可视化,配置直观。
* 中文文档支持:项目提供完整中文文档(README_zh-cn.md),降低本土开发者门槛。
3️⃣ **灵活兼容双模式**
* Classic模式:类似Buildroot的独立构建,每个包在独立WORKDIR中处理,依赖隔离清晰。
* Yocto模式:扩展Yocto的元数据层,封装`bitbake`命令,提供菜单配置支持,无缝兼容现有生态。
* 混合编译支持:同一Makefile同时支持交叉编译与本地编译,简化多平台开发流程。
4️⃣ **企业级高级特性**
* 智能依赖管理:自动生成依赖图(支持强弱依赖/冲突检测),一键生成SVG可视化图表。
* 独立软件包分发:类似AppImage的`gen_cpk`工具,自动打包运行时依赖,实现跨系统部署。
* 安全合规支持:自动生成许可证清单(HTML),内置CVE补丁管理,满足企业合规需求。
5️⃣ **开源生态贡献与创新**
* 内核社区认可:项目贡献的Kconfig补丁已合并至Linux 5.19+主线,技术实力获国际认可。
* 全中文技术栈:从文档到社区讨论全面支持中文,降低本土开发者参与门槛。
* 使用方高度评价:某公司在CES2024上称其开发平台为颠覆性创新(Cooper Core即是CBuild,Cbuild-ng比Cbuild更遵循标准,功能更强大)。
* [微信公众号文章](https://mp.weixin.qq.com/s?__biz=MzUxNjUyNjAwNg==&mid=2247485681&idx=1&sn=a40da02663c6d27ea63eb28451095bbf)
* [官网链接](https://www.ambarella.com/cooper/)
## 功能组成
CBuild 编译系统主要由三部分组成: 任务分析处理工具、Makefile 编译模板 (IMake)、网络和缓存处理工具。
* 任务分析处理工具: 分析所有任务并自动生成总配置 Kconfig 和执行脚本 Makefile
* 所有任务由 Python 脚本 `gen_build_chain.py` 分析组装
* 自动收集所有任务的规则和参数,通过 `make menuconfig` 选择是否执行任务和配置任务参数
* 每个任务规则由一条依赖语句声明,支持非常多的依赖规则
* 支持自动生成执行任务的实包和管理任务的虚包的规则
* 支持普通结构(config)、层次结构(menuconfig)、选择结构(choice) 等自动生成
* 支持强依赖(depends on)、弱依赖(if...endif)、条件依赖、强选择(select)、弱选择(imply)、或规则(||) 等自动生成
* 任务是 Makefile 脚本,由 make 执行
* 支持生成任务依赖关系的图片,并有颜色等属性查看任务是否被选中等 `gen_depends_image.sh`
* Makefile 编译模板 (IMake): 比肩 `CMake` `Autotools` `Meson` 等的编译工具,比他们更简洁快速,使用 menuconfig 配置参数,缺点是由于是纯粹 Makefile 实现所以不支持 Windows
* 编译驱动、库、应用的模板,只需填写少数几个变量就可以完成一个超大项目的 Makefile
* 支持编译生成最新的交叉编译工具链 `process_machine.sh` `toolchain/Makefile`
* 一个 Makefile 同时支持 Classic Build 模式和 Yocto Build 方式,同时支持本地编译和交叉编译 `inc.env.mk`
* 一个 Makefile 同时支持生成多个库、可执行文件或驱动
* 支持自动分析头文件作为编译依赖,支持分别指定源文件的 CFLAGS 等
* 支持指定编译输出目录(`make O=xxx`)、安装目录(`make DESTDIR=xxx`)、依赖的 sysroot 目录(`make DEPDIR=xxx`)
* 提供编译静态库、共享库和可执行文件的模板 `inc.app.mk`,支持 C(`*.c`) C++(`*.cc *.cp *.cxx *.cpp *.CPP *.c++ *.C`) 和 汇编(`*.S *.s *.asm`) 混合编译
* 提供编译驱动的模板 `inc.mod.mk`,支持 C(`*.c`) 和 汇编(`*.S`) 混合编译
* 提供符合 [GNUInstallDirs](https://www.gnu.org/prep/standards/html_node/Directory-Variables.html) 标准的安装模板 `inc.ins.mk`
* 提供 Kconfig (menuconfig) 配置参数的模板 `inc.conf.mk`
* 提供调用原始的 `Makefile` `CMake` `Autotools` `Meson` 编译的模板 `inc.rule.mk`
* 网络和缓存等处理工具(Classic Build): 处理包的下载、打补丁、编译、安装、打包,支持源码镜像和缓存镜像
* 提供方便可靠的补丁机制 `exec_patch.sh`
* 提供自动拉取网络包工具,支持从 http(支持 md5)、git(支持 branch tag revision)或 svn(支持 revision) 下载包,支持镜像下载 `fetch_package.sh`
* 提供编译缓存工具,再次编译不需要从代码编译,直接从本地缓存或网络缓存拉取 `process_cache.sh`
* 提供简洁的组装模板,且支持缓存编译 `inc.rule.mk`
* 提供可靠的安装脚本和 sysroot 处理脚本 `process_sysroot.sh`
* 提供丰富的开源软件层,开源包不断增加中
* 提供生成所有包的描述信息的 HTML 文件的脚本 `gen_package_infos.py`
* 提供生成独立包(打包包含系统依赖)的脚本 `gen_cpk_package.py` `gen_cpk_binary.sh`,功能类似 Snap、AppImage或Flatpak
* 测试用例可以查看 [examples_zh-cn.md](./examples/examples_zh-cn.md)
## 性能测试
* 测试场景: 某 SDK 的 300 个包 8 线程本地文件系统编译
| 编译方法 | 首次编译耗时 | 再次编译耗时 | 输出文件系统占用 |
| ----------------------- | ------------ | ------------ | ---------------- |
| CBuild-ng Classic Build | 5m1.790s | 0m49.785s | 1.8G |
| CBuild Classic Build | 5m13.526s | 0m59.156s | 2.7G |
| Yocto Build with cache | 15m42.554s | 3m31.520s | 7.4G+ |
* 测试结果: 对比 Yocto Build,CBuild-ng 的 Classic Build 编译耗时减少 2/3,输出文件系统占用减少 3/4
## 笔记
* 如果对 Shell 语法不了解,可以查看 [Shell 笔记](https://github.com/lengjingzju/notes/blob/master/src/md/programming_shell.md)
* 如果对 GCC 编译选项不了解,可以查看 [GCC 笔记](https://github.com/lengjingzju/notes/blob/master/src/md/gcc_options.md)
* 如果对 Makefile 语法不了解,可以查看 [Makefile 笔记](https://github.com/lengjingzju/notes/blob/master/src/md/programming_makefile.md)
* 如果对 Kconfig 语法不了解,可以查看 [Kconfig 笔记](https://github.com/lengjingzju/notes/blob/master/src/md/programming_kconfig.md)
## 开源贡献
本工程目前已向 Linux 内核社区贡献了2次提交,已合并到 Linux 内核主线
* [kconfig: fix failing to generate auto.conf](https://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git/commit/?h=fixes&id=1b9e740a81f91ae338b29ed70455719804957b80)
```sh
commit 1b9e740a81f91ae338b29ed70455719804957b80
Author: Jing Leng
Date: Fri Feb 11 17:27:36 2022 +0800
kconfig: fix failing to generate auto.conf
When the KCONFIG_AUTOCONFIG is specified (e.g. export \
KCONFIG_AUTOCONFIG=output/config/auto.conf), the directory of
include/config/ will not be created, so kconfig can't create deps
files in it and auto.conf can't be generated.
```
* [kbuild: Fix include path in scripts/Makefile.modpost](https://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild.git/commit/?h=fixes&id=23a0cb8e3225122496bfa79172005c587c2d64bf)
```sh
commit 23a0cb8e3225122496bfa79172005c587c2d64bf
Author: Jing Leng
Date: Tue May 17 18:51:28 2022 +0800
kbuild: Fix include path in scripts/Makefile.modpost
When building an external module, if users don't need to separate the
compilation output and source code, they run the following command:
"make -C $(LINUX_SRC_DIR) M=$(PWD)". At this point, "$(KBUILD_EXTMOD)"
and "$(src)" are the same.
If they need to separate them, they run "make -C $(KERNEL_SRC_DIR)
O=$(KERNEL_OUT_DIR) M=$(OUT_DIR) src=$(PWD)". Before running the
command, they need to copy "Kbuild" or "Makefile" to "$(OUT_DIR)" to
prevent compilation failure.
So the kernel should change the included path to avoid the copy operation.
```
## 总体结构
```
├─Makefile // 顶层 Makefile 入口,驱动整体构建流程
│
└─scripts // 核心脚本目录,包含环境设置、编译及打包等功能
│ build.env // 经典构建(classic build)环境变量配置
│ clean.env // 清理操作环境变量配置
│ yocto.env // Yocto 构建环境变量配置
│
├─bin // 核心可执行脚本目录
│ convert_recipe.py // 将 Yocto recipe 初步转换为调用 inc.rule.mk 的 Makefile 脚本
│ exec_patch.sh // 自动化补丁应用脚本
│ fetch_package.sh // 源码获取脚本,支持 git、svn、http 及镜像下载
│ gen_build_chain.py // 核心依赖分析脚本,根据依赖关系生成顶层 Makefile 与 Kconfig
│ gen_cpk_binary.sh // CPK 打包脚本,生成带自解压头的压缩包
│ gen_cpk_package.py // CPK 包处理脚本,收集运行时依赖并修改 RPATH,实现跨发行版运行
│ gen_depends_image.sh // 生成项目依赖图
│ gen_package_infos.py // 生成软件许可信息文件(HTML/TXT 格式)
│ meson_cross.sh // 处理 Meson 构建系统的交叉编译配置
│ process_cache.sh // 编译缓存管理,支持本地与局域网缓存
│ process_machine.sh // 芯片相关环境变量配置(用户可自定义)
│ process_mirror.py // 国内源码镜像管理与处理
│ process_sysroot.sh // 处理安装文件的复制与系统根目录设置
│ regex_deps.svg // 实依赖规则正则表达式示意图
│ regex_incdeps.svg // 子目录递归依赖规则正则表达式示意图(优化搜索性能)
│ regex_vdeps.svg // 虚依赖规则正则表达式示意图
│
├─core // 构建系统核心 Makefile 模板目录
│ inc.app.mk // 应用程序编译模板
│ inc.conf.mk // Kconfig 配置模板
│ inc.env.mk // 环境设置模板
│ inc.ins.mk // 安装过程模板
│ inc.makes // 聚合模板,便于在非 CBuild-ng 工程中使用核心功能
│ inc.mod.mk // 内核驱动编译模板(支持编译输出与源码分离)
│ inc.rule.mk // 主控构建模板,支持 Autotools/CMake/Meson/Makefile 等多种构建系统
│
├─kconfig // 源自 Linux 6.12 的 Kconfig 系统,无需修改
│
├─meta-cbuild // 供 Yocto 使用 CBuild-ng 的元层(meta-layer)
│
├─progress // 进度条显示模块,属辅助功能非核心代码
│
└─toolchain // 用于构建最新 GCC 交叉编译工具链的脚本
└─ Makefile
```
## 任务分析处理
### 编译架构
* Classic Build 组成:
* 应用和驱动的编译脚本都是由 Makefile + DEPS-statement 组成
* 编译链通过 DEPS-statement 定义的依赖关系组装(包级别的依赖)
* DEPS-statement 基本只需要定义依赖,遵循 CBuild 定义的组装规则
* 脚本分析所有包的 DEPS-statement 自动生成所有包的编译链,所有包都是一个一个单独编译,可以单独进入包下敲 make 编译
* 支持 Kconfig 自己管理或托管,托管的 Kconfig 必需放置和 DEPS-statement 语句文件的同目录,无需手动指定父子包含关系,而是由脚本自动分析组装
* Yocto Build 组成:
* 应用和驱动的编译脚本都是由 Makefile + Recipe 组成
* 编译链通过在 Recipe 中定义的 DEPENDS / RDEPENDS 和扩展的 EXTRADEPS 依赖关系组装(包级别的依赖)
* 自定义包的 Recipe 基本只需要定义依赖,遵循 Yocto 定义的组装规则
* 扩展 Yocto 编译,脚本分析所有包的 Recipe 的文件名和自定义包的 Recipe 的 DEPENDS 变量自动生成所有包的编译链
* 扩展 Yocto 编译,支持弱依赖,可通过 `make menuconfig` 修改 rootfs (增加包、删除包、修改配置等)
### gen_build_chain.py 命令参数
* 调试说明
* gen_build_chain.py 有个 `debug_mode` 变量,设为 True 会打印非常多的调试信息,例如循环依赖,未定义包等
* 命令说明
* 带中括号表示是可选项,否则是必选项
* Classic Build 只需一步自动生成 Kconfig 和 Makefile
* Yocto Build 需要两步分别自动生成 Kconfig 和 Image 配方,会自动分析 `conf/local.conf` `conf/bblayers.conf` 和层下的配方文件和配方附加文件
```sh
# Classic Build
gen_build_chain.py -m MAKEFILE_OUT -k KCONFIG_OUT [-t TARGET_OUT] -d DEP_NAME [-v VIR_NAME] [-c CONF_NAME] -s SEARCH_DIRS [-i IGNORE_DIRS] [-g GO_ON_DIRS] [-l MAX_LAYER_DEPTH] [-w KEYWORDS] [-p PREPEND_FLAG] [-u UNIQUE_PACKAGES]
# Yocto Build Step1
gen_build_chain.py -k KCONFIG_OUT -t TARGET_OUT [-v VIR_NAME] [-c CONF_NAME] [-i IGNORE_DIRS] [-l MAX_LAYER_DEPTH] [-w KEYWORDS] [-p PREPEND_FLAG] [-u USER_METAS]
# Yocto Build Step2
gen_build_chain.py -t TARGET_PATH -c DOT_CONFIG_NAME -o RECIPE_IMAGE_NAME [-p PATCH_PKG_PATH] [-i IGNORE_RECIPES]
```
* Classic Build 命令选项
* `-m `: 指定自动生成的 Makefile 文件路径名
* 可以使用一个顶层 Makefile 包含自动生成的 Makefile,all 目标调用 `make $(ENV_BUILD_JOBS) MAKEFLAGS= all_targets` 多线程编译所有包
* 可以统计各个包的编译时间 `make time_statistics`
* `-k `: 指定自动生成的 Kconfig 文件路径名
* `-t `: 指定自动生成的存储包名、依赖和源码路径列表的文件路径名
* `-d `: 指定要搜索的依赖文件名(含有依赖规则语句),依赖文件中可以包含多条依赖信息,但不建议这么做
* `-c `: 指定要搜索的 Kconfig 配置文件名(含有配置信息)
* 查找和依赖文件同目录的配置文件,优先查找和配置文件名相同后缀的文件名为包名的配置文件,找不到才查找指定配置文件
* `-v `: 指定要搜索的虚拟依赖文件名(含有虚拟依赖规则语句)
* `-s `: 指定搜索的目录文件路径名,多个目录使用冒号隔开
* `-i `: 指定忽略的目录名,不会搜索指定目录名下的依赖文件,多个目录使用冒号隔开
* `-g `: 指定继续搜索的的目录文件路径名,多个目录使用冒号隔开
* 如果在当前目录下搜索到 ``,当前目录不存在 `continue` 文件且 `` 没有指定或当前目录不在它里面,不会再继续搜索当前目录的子目录
* `-l `: 设置 menuconfig 菜单的最大层数,0 表示菜单平铺,1表示2层菜单,...
* `-w `: 设置 menuconfig 菜单的忽略层级名,如果路径中的目录匹配设置值,则这个路径的层数减1,设置的多个目录使用冒号隔开
* `-p `: 设置生成的 Kconfig 中配置项的前缀,如果用户运行 conf / mconf 时设置了无前缀 `CONFIG_=""`,则运行此脚本需要设置此 flag 为 1
* `-u `: 指定唯一包(即此包作为 native 包的依赖时,此包的形式还是不含 native),一般是和 arch 无关的包,多个包名使用冒号隔开
* Yocto Build Step1 命令选项
* `-k `: 指定自动生成的 Kconfig 文件路径名
* `-t `: 指定自动生成的存储包名、依赖和源码路径列表的文件路径名
* `-c `: 指定要搜索的 Kconfig 配置文件名(含有配置信息)
* 优先查找当前目录下的 `配方名.bbconfig` 文件,找不到才在 bbappend 文件中 EXTERNALSRC 变量指定的路径下查找配置文件,优先查找和配置文件名相同后缀的文件名为包名的配置文件,找不到才查找指定配置文件
* `-v `: 指定要搜索的虚拟依赖文件名(含有虚拟依赖规则语句)
* `-i `: 指定忽略的目录名,不会搜索指定目录名下的依赖文件,多个目录使用冒号隔开
* `-l `: 设置 menuconfig 菜单的最大层数,0 表示菜单平铺,1表示2层菜单,...
* `-w `: 设置 menuconfig 菜单的忽略层级名,如果路径中的目录匹配设置值,则这个路径的层数减1,设置的多个目录使用冒号隔开
* `-p `: 设置生成的 Kconfig 中配置项的前缀,如果用户运行 conf / mconf 时设置了无前缀 `CONFIG_=""`,则运行此脚本需要设置此 flag 为 1
* `-u `: 指定用户层,多个层使用冒号隔开。只有用户层的包才会: 分析依赖关系,默认选中,托管 Kconfig,支持 `EXTRADEPS` 特殊依赖和虚拟依赖
* Yocto Build Step2 命令选项
* `-t `: 指定 Step1 自动生成的存储包名、依赖和源码路径列表的文件路径名
* `-c `: 指定配置文件 .config 的路径名
* `-o