写点什么

CBuild-ng: 让 Linux 根文件系统和复杂应用构建前所未有的简单

作者:lengjingzju
  • 2025-09-09
    广东
  • 本文字数:12880 字

    阅读完需:约 42 分钟

CBuild-ng: 让Linux根文件系统和复杂应用构建前所未有的简单

项目地址


  • github: https://github.com/lengjingzju/cbuild-ng

  • gitee: https://gitee.com/lengjingzju/cbuild-ng


行业使用


  • 某美股半导体上市公司基于前一代 CBuild 定制的 SDK,同时支持经典编译和 Yocto 编译,初次移植周期由大于 1 年变为 3 个月,增加新系列芯片周期少于 1 个月。

  • 在信创背景下,CBuild-ng 通过源码下载加速(国内镜像、局域网镜像、本地缓存)和编译缓冲镜像(局域网镜像、本地缓存),高效地支持了隔离网环境下的构建。


本文由三部分组成,分别介绍 CBuild-ng 整体情况、IMake 的使用、CPK 的使用。

【一】CBuild-ng:构建系统的范式转移与价值重构

序言

在软件工程的演进历程中,构建系统长期面临着一个根本性困境:开发者必须在自由与秩序、灵活性与效率、生态广度与开发体验之间做出艰难抉择。Yocto 与 Buildroot 作为传统范式的两极代表,分别体现了"无限可能性伴随复杂性"与"有限简单性牺牲扩展性"的二元对立,这种对立本质上延续了工业时代"集中控制"与"标准化生产"的思维模式。


CBuild-ng 的诞生标志着这一时代的终结。它并非对现有范式的简单改进,而是一次彻底的范式革命(Paradigm Revolution),通过架构哲学、交互哲学、生态哲学和工程哲学的四重创新,实现了对传统二元对立的根本性超越与重构。

一、架构哲学:从"单体巨构"到"联邦式微内核"

传统构建系统的核心困境根植于"全局耦合"的架构范式。组件间依赖关系呈现网状纠缠,状态修改会产生不可预知的涟漪效应,系统复杂性随规模增长呈指数级攀升,维护成本急剧增加。


CBuild-ng 提出的联邦式微内核架构对此进行了深度重构:


  • 隔离性容器架构:每个软件包在独立的 workdir 环境中构建,可配置隔离的构建上下文,实现依赖的物理隔离和环境纯净性

  • 智能协调机制:依赖解析与状态协调由统一的智能元系统进行管理,形成清晰的层次化架构

  • 契约化接口规范:包间通过明确定义的接口进行协作,彻底杜绝隐式耦合


这种"分而治之"的工程哲学将复杂性进行了有效的封装和模块化:包的内部复杂性被隔离,包间的复杂性被抽象和自动化,最终实现了前所未有的架构清晰度、可维护性与可扩展性,使大规模系统构建从经验艺术走向工程科学。

CBuild-ng 的模块联邦

CBuild-ng 最具突破性的创新在于对应用构建范式的重新定义。传统构建工具(Autotools / CMake / Meson)采用的"内部编译依赖"模式,导致模块边界模糊、依赖关系复杂、维护成本随规模急剧增长。


CBuild-ng 建立的"模块联邦"新范式具有以下特征:


  • 组件原子化设计:每个功能模块都是独立的软件包,具备自主版本生命周期,可脱离 CBuild-ng 独立使用

  • 依赖同级化管理:包间通过明确定义的接口协作,形成去中心化的网络拓扑结构

  • 物理隔离性保障:应用不再是一个巨型单体仓库,而是由多个微包联邦组成的有机整体


这种范式使按需组装系统成为现实:开发者可以像搭积木一样,从组件仓库中挑选所需模块,快速组装出定制化系统,不仅显著降低了维护难度,更实现了真正的软件复用。

二、交互哲学:从"过程指令"到"意图声明"

传统构建模式要求开发者成为"编译过程的描述者",必须深入理解构建机制的每一个细节。这种"编写指令"的范式迫使开发者从"架构师"降级为"装配工",将创造性智力消耗在实现细节中。


CBuild-ng 的工程实践实现了根本性转变:


  • 声明式编程范式:开发者只需声明构建目标(源文件、依赖项、编译参数等)而非具体过程

  • 意图抽象机制:系统接收高级意图后自动生成最优构建流程,将开发者从过程性思维解放到定义性思维


这种转变大幅降低了认知负荷,使开发者能够将创造力集中于架构与设计本身,实现了开发效率的显著提升。

IMake 的模板工具

CBuild-ng 使用 IMake(Include Makefile / I have the Makefile )而不是发明新的描述语言降低编译的难度。


统一的多范式构建框架


  • 多目标协同支持:单个 Makefile 支持生成多个库、可执行文件或驱动模块

  • 混合语言编译能力:无缝支持 C、C++、汇编等语言的混合编译

  • 智能依赖分析:自动头文件依赖追踪,支持源文件级细粒度控制

  • 灵活目录架构:支持输出目录(O=)、安装目录(DESTDIR=)、依赖目录(DEPDIR=)的灵活配置


丰富高效的 Makefile 模板


  • 环境配置模板(inc.env.mk):实现编译输出目录、依赖目录、安装目录、编译器和编译参数等的配置

  • 应用开发模板(inc.app.mk):提供静态库、共享库和可执行文件的完整解决方案

  • 内核驱动模板(inc.mod.mk):实现驱动代码输出与源码分离的创新架构

  • 标准化安装模板(inc.ins.mk):完全遵循 GNUInstallDirs 标准规范

  • 配置管理模板(inc.conf.mk):提供统一的 Kconfig(menuconfig)配置界面

三、生态哲学:从"范式锁定"到"自由统合"

技术选型的最大成本往往是"范式锁定"——选择简单意味着放弃生态,选择生态则必须接受复杂性。这种锁定效应导致项目初期选择焦虑和后期迁移成本高昂。


CBuild-ng 的双模式驱动架构提出了创新性解决方案:


  • 经典构建模式(Classic Mode):高度优化的独立构建系统,提供超越 Buildroot 的简单性与性能

  • Yocto 封装模式(Yocto Mode):对 Yocto 生态的无损封装与透明代理,保持完全兼容性


这种设计首次实现了在统一框架下的范式自由切换,开发者可根据项目阶段需求选择最优路径,从根本上消除了技术选型的锁定成本。


  • 传统项目支持:Classic 模式实现现有项目(Autotools、CMake、Meson、传统 Makefile 等)的直接嵌入和统一管理,优化的配置和编译管线

  • 统一接口层:Yocto 模式提供和 Classic 模式一致的配置接口、开发体验和工具链管理,实现高效的资源配置和编译优化

四、工程哲学:对"熵增"的系统性对抗

CBuild-ng 的核心价值体现在对软件熵增的系统性对抗和对软件复杂性的系统性治理:


  • 性能突破:通过现代化缓存和并行策略,实现构建速度的数量级提升

  • 资源优化:对输出体积的极致优化直接转化为硬件成本节约

  • 网络赋能:原生支持分布式架构,使隔离网络环境开发成为可能

  • 质量保障:内置企业级功能,包括许可证合规、依赖可视化等


这些特性使其从辅助工具演进为核心竞争力放大器,直接贡献于产品的质量、成本和交付效率。

缓存加速创新

CBuild-ng 在软件供应链管理方面实现了突破性创新:


多级镜像体系


  • 国内镜像网络:可集成主流开源镜像源,优化国内访问体验

  • 企业私有镜像:支持内网镜像服务,满足隔离环境需求

  • 智能路由选择:自动选择最优下载源,保证获取效率


分布式缓存生态


  • 本地缓存加速:基于内容哈希的精准验证机制

  • 团队协作支持:支持局域网缓存共享,提升协作效率

  • 云端同步能力:构建结果分布式同步,实现"一次构建,多处使用"

应用分发创新

CBuild-ng 引入了全新的应用分发范式:


独立应用格式


  • 自包含部署:将应用及其依赖打包为独立单元(cpk 格式即压缩包头部增加安装脚本)

  • 跨环境兼容:通过路径隔离实现环境适应性(修改 RPATH 和 ld.so 路径而不是导出环境变量运行)


性能表现


  • 离线部署:完整支持断网环境下的应用分发

  • 构建效率:大规模项目构建时间优化至分钟级

  • 资源利用:输出体积显著优化,存储成本大幅降低

  • 缓存效能:高缓存命中率,二次构建近乎瞬时完成


质量体系


  • 依赖管理:完整的依赖关系可视化与分析工具

  • 跨平台支持:支持多种 Linux 架构/发行版(Debian 系/RedHat 系/Arch 系)的统一构建

  • 安全合规:自动生成许可证清单和合规性报告

五、实践验证:工业级的可靠性证明

CBuild-ng 的技术实力已获得产业实践验证:


头部企业采用


  • 高度认可:某企业在 CES2024 上介绍他的核心基于 CBuild 定制的 SDK 开发平台为颠覆式创新

  • 生产环境验证:在多个关键领域大规模部署应用,一套构建系统支持多个系列几十款芯片和上百个方案

  • 性能指标达成:实现大规模项目的高效编译和部署


特殊企业实践


  • 隔离网络方案:为敏感行业提供完整离线构建能力

  • 团队协作支持:支持大规模团队的并行开发流程

  • 混合部署能力:实现本地与云端构建的无缝衔接

  • 复杂应用编译:为复杂应用的编译调试提供强力支持(Buildroot/Yocto 不具备这种能力)

结论:工程实践的新范式

CBuild-ng 的价值超越传统"构建工具"的范畴,它基于成熟的 Makefile/Bash/Python 技术栈,通过工程整合创新,重新定义了系统构建的实践范式:不仅证明了"强大即复杂,简单即有限"的传统假设不再成立,更通过卓越的架构设计实现了能力与易用性的完美统一。


更重要的是,CBuild-ng 代表了一种经过实践检验的工程哲学——将人的智力集中于创造性工作,而将复杂性交由系统智能管理。作为经过工业实践检验的成熟解决方案,CBuild-ng 不仅提供了技术上的领先优势,更为企业级软件开发提供了完整的价值链条:从代码编写到构建测试,从依赖管理到分发部署,每一个环节都体现了对开发者体验和生产效率的深度优化。



【二】IMake:让构建回归 Makefile 本质,前所未有的简单体验

现代构建系统的困境与 IMake 的诞生

在当今软件开发领域,构建系统已成为项目成功的关键因素。从经典的 Makefile 到现代的 Autotools、CMake 和 Meson,开发者们一直在寻找更高效、更灵活的构建工具。然而,这些工具往往伴随着陡峭的学习曲线和复杂的配置语法:


  • Autotools 需要编写复杂的 configure.ac 和 Makefile.am 文件,使用 M4 宏语言,配置过程繁琐

  • CMake 虽然功能强大,但需要学习专属的 CMakeLists.txt 语法,生成的 Makefile 难以理解和调试

  • Meson 作为后起之秀,设计理念先进但仍需学习新的配置语言


这些工具在追求功能强大的同时,却远离了构建系统的本质——简单、直观和可控。正是在这样的背景下,IMake(Include Makefile)应运而生,它让构建回归 Makefile 的本质,同时提供了现代构建系统的高级特性。

IMake 核心优势:简单而不失强大

IMake(Include Makefile)是一套基于纯 Makefile 实现的构建模板系统,它通过模块化的设计理念,将复杂的构建逻辑封装为可重用的模板。只需包含相应的模板文件并设置少量变量,您就能轻松完成从简单应用到复杂系统的构建配置。

核心优势

  • 极简配置:告别复杂的 configure.ac、CMakeLists.txt、meson.build,只需定义几个变量即可完成编译

  • 原生 Makefile 体验:完全基于 Makefile,无需学习新语法,现有知识完全适用

  • menuconfig 图形化配置:提供熟悉的 Kconfig 界面,轻松管理构建选项

  • 多功能支持:同时支持本地编译和交叉编译、经典编译和 Yocto 编译,静态库、动态库、可执行文件、内核模块一网打尽

  • 工具链配置:支持 GCC 和 Clang,轻松切换编译环境

  • 智能依赖处理:自动分析头文件依赖,探测环境配置自动重新编译,确保正确的构建顺序

  • 编译选项预置:预置常用的可选编译选项:优化等级、安全增强、安全调试(sanitizer)、静态分析(analyzer)、性能分析(gprof)

  • 符合标准规范:符合通用的 O 指定编译输出(编译输出与源码分离),DESTDIR 指定安装位置(安装目录符合 GNUInstallDirs 标准),自定义 DEPDIR 指定依赖根目录

优势对比

与其他构建系统相比,IMake 具有独特优势:


适用场景与目标用户

理想应用场景

  1. 嵌入式 Linux 开发:交叉编译支持完善,配置简单

  2. 系统级软件开发:内核模块支持良好,符合 Linux 标准

  3. 开源库开发:符合 GNU 标准,易于其他项目集成

  4. 大型项目构建:模块化设计,支持组件化开发,menuconfig 图形配置更直观

目标用户群体

  • 追求构建系统简单性和透明度的开发者

  • 主要工作在 Linux 环境的软件工程师

  • 对 Autotools/CMake/Meson 复杂性感到沮丧的开发者

  • 希望深度控制构建过程的资深程序员

编译模板功能特性详解

IMake 可脱离 CBuild-ng 独立使用,建议用户使用模板 inc.makes 并设置 INC_MAKES 启用相应的模板


  • inc.makes 默认只启用 inc.env.mk 和 inc.ins.mk

  • INC_MAKES 的值可以是 disenv conf app mod disins 的组合

  • disenv: 不启用 inc.env.mk

  • conf : 启用 inc.conf.mk

  • app : 启用 inc.app.mk

  • mod : 启用 inc.mod.mk

  • disins: 不启用 inc.ins.mk


模板详细说明参考 编译模板

使用示例

实际工程使用


纯头文件应用工程

  • 纯头文件工程只有安装

  • 头文件是安装在 include 的 PACKAGE_NAME 子目录下,防止大工程头文件重名


PACKAGE_NAME    = xxx
INSTALL_HEADERS:= $(wildcard src/*.h)
.PHONY: all clean installall: @echo "Build $(PACKAGE_NAME) Done!"
include inc.makes
clean: @echo "Clean $(PACKAGE_NAME) Done."
install: install_hdrs @echo "Install $(PACKAGE_NAME) to $(INS_PREFIX) Done."
复制代码

单库应用工程

  • 指定生成的静态库 LIBA_NAME 和动态库 LIBSO_NAME

  • 从指定文件 VERSION_FILE 的指定版本宏 VERSION_NAME 自动提取版本,生成的动态库为 libxxx.so.x.y.z



PACKAGE_NAME = xxx
VERSION_FILE := xxx.hppVERSION_NAME := XXX_VERSION
LIBA_NAME := libxxx.aLIBSO_NAME := libxxx.soCPFLAGS += -I./src
INSTALL_HEADERS:= $(wildcard src/*.hpp)
.PHONY: all clean installall: @echo "Build $(PACKAGE_NAME) Done!"
INC_MAKES := appinclude inc.makes
all: $(LIB_TARGETS)
clean: clean_objs @rm -f $(LIB_TARGETS) @echo "Clean $(PACKAGE_NAME) Done."
install: install_hdrs install_libs @echo "Install $(PACKAGE_NAME) to $(INS_PREFIX) Done."
复制代码

多库和可执行文件混合应用工程

  • SEARCH_HDRS 指定头文件搜索的子路径,这样源代码可以写成 #include "aaa.h" 而不是 #include "mmm/aaa.h"

  • object_byte_size/frame_byte_size 是指定最大对象和函数帧大小,大于该值时有编译警告,用于调试过大的局部变量,不是必需

  • 可选 ENV_BUILD_TYPE 指定优化等级,release 是 -O3,不指定时是 -O2

  • set_flags 是设置单个文件的编译标志,参考内核编译指定单文件的编译编译标志设置,而 CPFLAGS 是全局的



PACKAGE_NAME = xxxSEARCH_HDRS := mmm nnn
INSTALL_HEADERS:= $(wildcard src/*.hpp)
CPFLAGS += -Isrc -Wno-unused-parameter
.PHONY: all clean installall: @echo "Build $(PACKAGE_NAME) Done!"
INC_MAKES := appobject_byte_size= 65536frame_byte_size = 16384ENV_BUILD_TYPE := releaseinclude inc.makes
staticlib := libxxx.asharedlib := libxxx.so $(call get_version,src/xxx.hpp,JXXX_VERSION, )libsrcs := $(wildcard src/*.cpp)$(call set_flags,CFLAGS,src/xxx_message.cpp,-Wno-missing-field-initializers)LLIBS := $(addprefix -l,jcore ljson g711 g722 bcg729 opus fdk-aac)$(eval $(call add-liba-build,$(staticlib),$(libsrcs)))$(eval $(call add-libso-build,$(sharedlib),$(libsrcs),$(LLIBS)))
server_srcs := test/xxx_server.cppserver_libs := $(addprefix -l,jcore ljson $(PACKAGE_NAME))$(eval $(call add-bin-build,xxx_server,$(server_srcs),$(server_libs),,$(OBJ_PREFIX)/lib$(PACKAGE_NAME).so))
client_srcs := test/xxx_client.cppclient_libs := $(LLIBS) -l$(PACKAGE_NAME)$(eval $(call add-bin-build,xxx_client,$(client_srcs),$(client_libs),,$(OBJ_PREFIX)/lib$(PACKAGE_NAME).so))
all: $(BIN_TARGETS) $(LIB_TARGETS)
clean: clean_objs @rm -f $(LIB_TARGETS) $(BIN_TARGETS) @echo "Clean $(PACKAGE_NAME) Done."
install: install_hdrs install_libs install_bins @echo "Install $(PACKAGE_NAME) to $(INS_PREFIX) Done."
复制代码

单驱动工程

ifneq ($(KERNELRELEASE),)MOD_NAME = xxx
INC_MAKES := modinclude $(src)/inc.makes
else
PACKAGE_NAME = xxxSEARCH_HDRS = mmm nnn
all: modules
clean: modules_clean
install: modules_install
INC_MAKES := modinclude inc.makesendif
复制代码

单驱动含测试程序工程

  • 通过 KERNELRELEASE 宏区分是 Kbuild 编译部分和应用编译部分


ifneq ($(KERNELRELEASE),)MOD_NAME       := xxxSRCS           := $(wildcard $(src)/src/*.c)
INC_MAKES := modinclude $(src)/inc.makesccflags-y += -I$(src)/src
else
PACKAGE_NAME = xxxCPFLAGS += -IsrcINSTALL_HEADERS:= src/xxx.h
all: modules
clean: modules_clean
install: modules_install
INC_MAKES := app modinclude inc.makes
$(eval $(call add-bin-build,xxx_test,test/xxx_test.c))
all: $(BIN_TARGETS)
clean: clean_objs @rm -f $(BIN_TARGETS) @echo "Clean $(PACKAGE_NAME) Done."
install: install_bins install_hdrs @echo "Install $(PACKAGE_NAME) to $(INS_PREFIX) Done."
endif
复制代码

结语:回归本质,简化构建

IMake 的出现是对当前复杂构建系统生态的一次重要反思。它证明了一个观点:强大的功能不一定需要复杂的配置,简单的设计也可以应对复杂的构建需求。


探索 IMake,体验构建系统的简单之美! 如果您正在寻找一个既强大又简单的构建解决方案,IMake 值得您的尝试。



【三】CPK:一场回归软件本真的打包分发哲学实践

在 Linux 复杂的分发生态中,我们是否已经忘记了软件的纯粹形态?当容器、沙箱和守护进程成为标配,CPK 以其极简、透明和自由的哲学,发起了另一场值得深思的技术实践。

引言:迷失在“进步”中的软件本真

Linux 世界从不缺少创新,尤其是在应用分发领域。我们从deb/rpm走向了 Snap、Flatpak 和 AppImage,每一次进化都试图解决依赖、隔离和跨平台兼容性问题。然而,在这些解决方案不断叠加抽象层的同时,我们也悄然失去了什么:系统的简洁性、对软件行为的完全可知性、以及无需中间人介入的直接控制权。


我们似乎在用一种复杂性去替代另一种复杂性。有没有一种方式,能够让我们回归到软件最本真的状态——一份完整、自包含、可在任何地方直接运行的数字产物


开源构建系统 CBuild-ng 给出的答案是:CPK (CBuild/Compressed Package)。它不仅是一种技术格式,更是一场关乎极简(Simplicity)、主权(Sovereignty)与自由(Mobility) 的哲学实践。

一、极简(Simplicity)——剥离一切非必要复杂性

CPK 的设计哲学根植于 Unix 的经典信条:KISS (Keep It Simple, Stupid)。它坚信,真正的通用性应建立在系统最坚实、最普遍的基础上,而非另一套复杂的中间件之上。


CPK 是什么?


  • 它是一个自解压的 Shell 脚本,后面紧跟着一个标准的 tar 归档包

  • 它的全部依赖,仅仅是 Python、sh、file、tar、gcc、readelf、patchelf。这几个工具存在于任何一台 Linux 机器上(patchelf 需要单独静态编译),无需安装任何额外的框架或守护进程(如 snapd 或 flatpak)。


这种极简到极致的设计,带来了无与伦比的透明性。用户可以用文本编辑器直接查看 CPK 包的安装逻辑,用tar命令解压并审计其内容。没有黑盒子,没有隐藏的魔法,一切行为都是可知、可预测、可审计的。CPK 用最原始的工具,解决了最现代的问题,完成了一次对过度工程化的优雅否定。

二、主权(Sovereignty)——将控制权彻底归还

CPK 蕴含着一种强烈的主张:它要求将软件的完整主权归还给创造者和使用者。


  • 对开发者而言,CPK 赋予了「交付确定性」的能力。

  • 开发者可以自由选用任何现代工具链(如 AlmaLinux 10 的最新 glibc),将应用与其全部依赖(直至最底层的 C 库)一同封存,形成一个冻结的、已知良好的运行环境。从此,他可以庄严地向用户宣告:“这就是我的作品及其全部所需,它在此环境中完美运行。” 这彻底终结了“依赖地狱”和“在我机器上是好的”这一古老困境。

  • 对用户而言,CPK 意味着「完全的控制权和透明度」。

  • 一个.cpk文件无需 root 权限即可安装于用户目录(~/.cpk/),不会向系统深处散落文件。用户可以审视安装脚本,可以自由剖析包内内容,可以决定何时运行与更新。没有强制的后台服务,没有不经同意的自动升级。CPK 在开发者与用户之间,建立了一种基于透明和尊重的信任关系。

三、自由(Mobility)——构建可自由迁徙的数字生命体

CPK 的终极理想,是让 Linux 应用成为一个真正可自由迁徙的数字生命体,获得跨越发行版鸿沟的能力。


其核心技术在于:它不仅携带用户态依赖,更自带最底层的 C 库(如 glibc)和解释器(ld.so),并通过修改二进制文件的解释器路径(Interpreter),使其形成一个完美的内部闭环。这使得一个在最新发行版上构建的应用,可以在任何旧版主机上完整“复活”


它实现了应用与环境的标准脱钩,赋予了应用跨越发行版自由迁徙的能力,这正是 Linux 世界长期以来所追寻的“一次构建,到处运行”的优雅实现。CPK 让应用摆脱了系统的束缚,成为了一个真正独立、可迁移的数字实体。

四、横向审视——CPK 在生态中的独特定位

CPK 的设计哲学与主流方案有显著区别,它并非要取代所有现有方案,而是在 “极致简化”、“可控性”“跨发行版部署” 之间找到了一个独特的平衡点。


以下是从多个维度的详细对比:



CPK 的独特定位:


  1. 面向开发者和专业用户:CPK 的透明性(可查看脚本)、可控性(自己处理依赖)和极简依赖,使其特别适合开发者分发复杂工具链、内部工具、CI/CD 构建产物,以及专业用户部署特定版本的商业软件。

  2. 嵌入式与边缘计算:在资源受限或需要高度定制化的环境中,CPK 的低开销无需常驻守护进程的特点是一个巨大优势。它允许将复杂的运行时环境可靠地分发到任何 Linux 设备上。

  3. 追求简单和透明的哲学:CPK 不相信“魔法”。它用最基础的组件构建了一套解决方案,所有步骤都是可审计、可调试的(无沙箱、无强制商店)。这与 Snap/Flatpak 引入的相对复杂的守护进程和框架形成鲜明对比。

五、实战——感受 CPK 的优雅体验

基于 CBuild-ng 集成的 CPK 打包示例

make xxx-cpk 命令即可自动编译软件并生成 cpk 包,ELFs copied from system: 清晰的显示了从系统复制的哪些包


lengjing@lengjing:~/data/cbuild-ng$ source scripts/build.env host genericlengjing@lengjing:~/data/cbuild-ng$ make loadconfiglengjing@lengjing:~/data/cbuild-ng$ make tcpdump-cpkMatch patchelf-native Cache.Build patchelf-native Done.Match patchelf Cache.Build patchelf Done.log path is /home/lengjing/data/cbuild-ng/output/x86_64-host/config/log/2025-09-04--08-15-58.068091488/[100%]                                                  [  2/  2] tcpdump----------------------------------------    libpcap    tcpdump----------------------------------------Generate /home/lengjing/data/cbuild-ng/output/x86_64-host/packages/tcpdump/usr/share/license/index.txt OK.Generate /home/lengjing/data/cbuild-ng/output/x86_64-host/packages/tcpdump/usr/share/license/index.html OK.Note: tcpdump.dot tcpdump.svg and tcpdump.png are generated in the /home/lengjing/data/cbuild-ng/output/x86_64-host/packages/tcpdump/usr/share/license folder.Interpreter path       : /home/lengjing/data/cbuild-ng/output/x86_64-host/packages/tcpdump/syslib/ld-linux-x86-64.so.2ELFs with interpreter  : [('/home/lengjing/data/cbuild-ng/output/x86_64-host/packages/tcpdump/usr/bin', ['tcpdump']), ('/home/lengjing/data/cbuild-ng/output/x86_64-host/packages/tcpdump/syslib', ['libc-2.31.so', 'libpthread-2.31.so'])]ELFs with rpath        : [('/home/lengjing/data/cbuild-ng/output/x86_64-host/packages/tcpdump/usr/bin', ['tcpdump']), ('/home/lengjing/data/cbuild-ng/output/x86_64-host/packages/tcpdump/usr/lib', ['libpcap.so.1.10.5']), ('/home/lengjing/data/cbuild-ng/output/x86_64-host/packages/tcpdump/syslib', ['libcrypto.so.1.1', 'libc-2.31.so', 'libdl-2.31.so', 'libpthread-2.31.so'])]ELFs copied from system: ['libcrypto.so.1.1', 'libc.so.6', 'ld-linux-x86-64.so.2']CPK SUCCESS: /home/lengjing/data/cbuild-ng/output/x86_64-host/packages/tcpdumpCPK is packed to /home/lengjing/data/cbuild-ng/output/x86_64-host/packages/tcpdump.cpk
复制代码

CPK 打包命令和原理

%-cpk:  @$(MAKE) $(MFLAG) CONFIG_PATCHELF_NATIVE=y patchelf-native  @$(MAKE) $(MFLAG) CONFIG_PATCHELF=y patchelf  @$(MAKE) $(MFLAG) $(patsubst %-cpk,%-pkg,$@)  @PATH=$(ENV_NATIVE_ROOT)/objects/patchelf/image/usr/bin:$(PATH) \    python3 $(ENV_TOOL_DIR)/gen_cpk_package.py -r $(ENV_CROSS_ROOT)/packages/$(patsubst %-cpk,%,$@) \    -i include:share:etc:srv:com:var:run $(if $(PKG_EOS),-o $(PKG_EOS)) \    -c $(ENV_BUILD_TOOL)gcc -t $(ENV_BUILD_TOOL)readelf $(if $(CPK_EXTRA_PATH),-e $(CPK_EXTRA_PATH))  @cp -fp $(ENV_CROSS_ROOT)/objects/patchelf/image/usr/bin/patchelf $(ENV_CROSS_ROOT)/packages/$(patsubst %-cpk,%,$@)ifneq ($(PKG_EOS),y)  @cp -fp $(ENV_TOOL_DIR)/gen_cpk_package.py $(ENV_CROSS_ROOT)/packages/$(patsubst %-cpk,%,$@)  @ush=$(ENV_CROSS_ROOT)/packages/$(patsubst %-cpk,%,$@)/update.sh && \    echo '#!/bin/sh' > $${ush} && \    echo 'curdir=$$(dirname $$(realpath $$0))' >> $${ush} && \    echo 'PATH=$$curdir:$$PATH python3 $$curdir/gen_cpk_package.py -r $$curdir -i include:share:etc:srv:com:var:run' >> $${ush} && \    chmod +x $${ush}endif  @bash $(ENV_TOOL_DIR)/gen_cpk_binary.sh pack $(ENV_CROSS_ROOT)/packages/$(patsubst %-cpk,%,$@)
复制代码


上述代码为顶层 Makefile CPK 打包的命令,主要使用 gen_cpk_package.pygen_cpk_binary.sh 脚本完成处理,用户也可以独立使用这两个脚本,脱离 CBuild-ng 单独打包


  • 静态编译patchelf特别提醒,发行版本的 patchelf 可能有问题,请选用合适的 patchelf

  • 运行gen_cpk_package.py脚本完成处理(-h 得到命令帮助)

  • 分析 -r 指定的打包目录下的动态链接的可执行程序和动态库

  • 使用 file 命令得到文件属性,再使用 -t 指定的 readelf 分析依赖的动态库

  • 使用 -c 指定的 gcc 从他的搜寻目录找到依赖的动态库(不在打包目录下)复制到 syslib 目录

  • 使用 patchelf 修改 rpath 和 interpreter 指向打包目录的文件

  • 运行gen_cpk_binary.sh脚本将压缩打包目录并把压缩包追加到本脚本后面成为单文件

安装 CPK 包的示例

下面是 AlmaLinux10 下编译的 CPK 在 ubuntu20.04 下运行的例子,成功演示了:一个在 AlmaLinux 10(基于较新的 glibc 2.41)上编译的 tcpdump 及其所有复杂依赖,可以无缝地在 Ubuntu 20.04(基于较旧的 glibc 2.31)上运行。并且请看usr/share/license 目录,index.html/index.txt 提供了许可列表,图片可查看依赖关系,这是企业合规的特性。


lengjing@lengjing:~/Downloads$ ./tcpdump.cpkPlease set the installation directory (/home/lengjing/.cpk/tcpdump):Delete the original app [/home/lengjing/.cpk/tcpdump] first? (y or n): y-e Your choice is yInterpreter path       : /home/lengjing/.cpk/tcpdump/syslib/ld-linux-x86-64.so.2ELFs with interpreter  : [('/home/lengjing/.cpk/tcpdump/syslib', ['libc.so.6']), ('/home/lengjing/.cpk/tcpdump/usr/bin', ['tcpdump']), ('/home/lengjing/.cpk/tcpdump/syslib', [])]ELFs with rpath        : [('/home/lengjing/.cpk/tcpdump/syslib', ['libc.so.6', 'libz.so.1.3.1.zlib-ng', 'libcrypto.so.3.2.4']), ('/home/lengjing/.cpk/tcpdump/usr/bin', ['tcpdump']), ('/home/lengjing/.cpk/tcpdump/usr/lib', ['libpcap.so.1.10.5']), ('/home/lengjing/.cpk/tcpdump/syslib', [])]ELFs copied from system: []CPK SUCCESS: /home/lengjing/.cpk/tcpdump-e Successfully installed to /home/lengjing/.cpk/tcpdumplengjing@lengjing:~/Downloads$ cd /home/lengjing/.cpk/tcpdumplengjing@lengjing:~/.cpk/tcpdump$ tree.├── gen_cpk_package.py├── patchelf├── syslib│     ├── ld-linux-x86-64.so.2│     ├── libcrypto.so.3 -> libcrypto.so.3.2.4│     ├── libcrypto.so.3.2.4│     ├── libc.so.6│     ├── libz.so.1 -> libz.so.1.3.1.zlib-ng│     └── libz.so.1.3.1.zlib-ng├── update.sh└── usr    ├── bin    │     ├── pcap-config    │     ├── tcpdump    │     └── tcpdump.4.99.5 -> tcpdump    ├── lib    │     ├── libpcap.so -> libpcap.so.1    │     ├── libpcap.so.1 -> libpcap.so.1.10.5    │     └── libpcap.so.1.10.5    └── share        └── license            ├── common            │     └── MIT-LENGJING            │         └── LICENSE            ├── index.html            ├── index.txt            ├── libpcap            │     └── LICENSE            ├── spdx-licenses.html            ├── tcpdump            │     └── LICENSE            ├── tcpdump.dot            ├── tcpdump.png            └── tcpdump.svg
10 directories, 24 fileslengjing@lengjing:~/.cpk/tcpdump$ file usr/bin/tcpdumpusr/bin/tcpdump: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /home/lengjing/.cpk/tcpdump/syslib/ld-linux-x86-64.so.2, BuildID[sha1]=ccfe1b6660bd62cd643fe2746464872074e651ee, for GNU/Linux 3.2.0, not strippedlengjing@lengjing:~/.cpk/tcpdump$ ./syslib/libc.so.6GNU C Library (GNU libc) stable release version 2.41.Copyright (C) 2025 Free Software Foundation, Inc.This is free software; see the source for copying conditions.There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR APARTICULAR PURPOSE.Compiled by GNU CC version 15.1.1 20250521 (Red Hat 15.1.1-2).libc ABIs: UNIQUE IFUNC ABSOLUTEMinimum supported kernel: 3.2.0For bug reporting instructions, please see:<https://www.gnu.org/software/libc/bugs.html>.lengjing@lengjing:~/.cpk/tcpdump$ /usr/lib/x86_64-linux-gnu/libc.so.6GNU C Library (Ubuntu GLIBC 2.31-0ubuntu9.18) stable release version 2.31.Copyright (C) 2020 Free Software Foundation, Inc.This is free software; see the source for copying conditions.There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR APARTICULAR PURPOSE.Compiled by GNU CC version 9.4.0.libc ABIs: UNIQUE IFUNC ABSOLUTEFor bug reporting instructions, please see:<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.lengjing@lengjing:~/.cpk/tcpdump$ ./usr/bin/tcpdump -htcpdump version 4.99.5libpcap version 1.10.5 (with TPACKET_V3)OpenSSL 3.2.4 11 Feb 202564-bit build, 64-bit time_tUsage: tcpdump [-AbdDefhHIJKlLnNOpqStuUvxX#] [ -B size ] [ -c count ] [--count] [ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ] [ -i interface ] [ --immediate-mode ] [ -j tstamptype ] [ -M secret ] [ --number ] [ --print ] [ -Q in|out|inout ] [ -r file ] [ -s snaplen ] [ -T type ] [ --version ] [ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ] [ --time-stamp-precision precision ] [ --micro ] [ --nano ] [ -z postrotate-command ] [ -Z user ] [ expression ]
复制代码

结语:一种选择,一种态度

在技术选择上,没有唯一的真理。Snap/Flatpak 致力于构建一个安全可控的软件生态,其价值毋庸置疑。


而 CPK,则是为另一群人准备的:他们是极简主义的信徒,是掌控感的追求者,是希望软件保持纯粹形态的理想主义者。CPK 是他们表达技术态度的一种方式——选择简单而非复杂,选择透明而非遮蔽,选择自由而非约束。


CPK 无意取代 Snap、Flatpak 或 AppImage。它们服务于不同的愿景:Snap/Flatpak 致力于构建一个安全、可控、便于管理的软件生态;AppImage 追求极致的单一文件便携性。


CPK,不仅仅是一种格式,更是一场回归软件本真的哲学实践。它用优雅的技术和最小的开销,精准地解决了特定场景下的痛点,体现了“简单即是美”的工程哲学。


发布于: 刚刚阅读数: 2
用户头像

lengjingzju

关注

还未添加个人签名 2025-09-05 加入

挑战高性能、高可用软件和框架的开发者。代表作: 1. 嵌入式SDK和大型应用软件构建框架CBuild-ng 2. 高性能多功能json和number双模引擎LJSON

评论

发布
暂无评论
CBuild-ng: 让Linux根文件系统和复杂应用构建前所未有的简单_开源_lengjingzju_InfoQ写作社区