资讯动态

OpenSSL Unified Scheme 构建系统设计解析:build.info、%unified_info 与构建模板

发布时间:2026/10/15 9:55:07 来源:尧图企业网站定制
固件操作系统【免费下载链接】CloverBootloaderBootloader for macOS, Windows and Linux in UEFI and in legacy mode项目地址https://gitcode.com/gh_mirrors/cl/CloverBootloader点击查看免费下载导读OpenSSL 的源码树中分散着数十个build.info文件它们共同驱动着Configure脚本、%unified_info信息数据库以及各平台的构建文件模板Makefile / MMS / NMake 等这套机制被称为Unified Scheme统一构建方案。本文以仓库内 Configurations/README-design.md 这一设计文档为骨架结合当前仓库中的真实build.info文件与构建模板源码系统讲解 Unified Scheme 的三大组成build.info声明语法、%unified_info数据结构、构建文件模板的规则生成函数。读完本文你将能够读懂 OpenSSL 任意子目录下的build.info内容理解Configure如何将分散的声明聚合为一张统一的依赖/源文件信息表并明白unix-Makefile.tmpl等模板如何最终产出可执行的构建规则。一、Unified Scheme 的整体架构数据如何流动Unified Scheme 的核心思想是把构建什么与怎么构建彻底分离。整个构建系统的数据流动分为三个环节build.info文件遍布源码树的声明文件只存放构建某个目标最少需要什么信息例如产物名程序、库、模块、脚本以及对应的源文件、依赖、包含目录、宏定义。%unified_info数据库Configure脚本Configure读取并消化所有build.info将分散的声明聚合成一张哈希表%unified_info该表最终以 Perl 数据的形式序列化写入构建树顶部的configdata.pm文件见 Configure 与 Configure。构建树可能与源码树是同一个目录也可能分离。构建文件模板文档所描述的驱动模板在仓库中对应 common0.tmpl它遍历%unified_info中的全部信息并调用平台模板如 Unix 的 unix-Makefile.tmpl、Windows 的 windows-makefile.tmpl、VMS 的 descrip.mms.tmpl中定义的一组规则生成函数产出最终的构建文件Makefile 等。build.info源码树各处 │ Configure 消化、聚合 ▼ %unified_infoconfigdata.pm │ common0.tmpl 驱动 ▼ 平台模板函数generatesrc / src2obj / obj2lib / obj2shlib / obj2dso / obj2bin / in2script ▼ 最终构建文件Makefile / MMS / NMake …从源码结构看common0.tmpl 正是文档中反复提到的驱动模板的实际实现它开篇就从%unified_info{sources}、%unified_info{shared_sources}、%unified_info{depends}中提取可能被生成的文件再对照%unified_info{generate}过滤出真正需要执行生成规则的目标集合。二、build.info最小信息声明语法2.1 声明变量总览build.info只声明最终产物与源文件两类信息刻意回避中间文件如.o目标文件与平台相关的扩展名如.so、.a、.exe这些均由Configure与平台模板推断。用于声明产物的变量带_NO_INST后缀的变体表示构建但不安装变量用途不安装变体PROGRAMS声明要构建的可执行程序PROGRAMS_NO_INSTLIBS声明要构建的常规库LIBS_NO_INSTMODULES声明要构建的模块如可动态加载的引擎MODULES_NO_INSTSCRIPTS声明要构建的脚本SCRIPTS_NO_INST用于描述如何从源产出目标的索引变量以产物文件为索引键值为对应内容索引变量含义SOURCE[file]生成file所需的源文件列表DEPEND[file]file的额外依赖产物间依赖如程序依赖库、目标文件依赖头文件INCLUDE[file]构建file时使用的包含目录列表DEFINE[file]构建file时需要定义的 C 宏-D参数GENERATE[file]用某条命令/脚本生成file的规则文档特别强调两条约定DEPEND是唯一允许提及目标文件.o的位置如DEPEND[cversion.o]buildinf.hSOURCE的索引键只能是最终产物库、程序、模块其值只能是源文件可以是生成出来的源文件。2.2 文档的虚构示例五段 build.info 的拼图文档用一个缩小版 OpenSSL作为示例程序apps/openssl、库libssl与libcrypto、模块engines/ossltest。各目录的build.info如下# 顶层 build.info LIBSlibcrypto libssl INCLUDE[libcrypto]include INCLUDE[libssl]include DEPEND[libssl]libcrypto# apps/build.info PROGRAMSopenssl SOURCE[openssl]openssl.c INCLUDE[openssl].. ../include DEPEND[openssl]../libssl# crypto/build.info LIBS../libcrypto SOURCE[../libcrypto]aes.c evp.c cversion.c DEPEND[cversion.o]buildinf.h GENERATE[buildinf.h]../util/mkbuildinf.pl $(CC) $(CFLAGS) $(PLATFORM) DEPEND[buildinf.h]../Makefile DEPEND[../util/mkbuildinf.pl]../util/Foo.pm# ssl/build.info LIBS../libssl SOURCE[../libssl]tls.c# engines/build.info MODULESdasync SOURCE[dasync]e_dasync.c DEPEND[dasync]../libcrypto INCLUDE[dasync]../include MODULES_NO_INSTossltest SOURCE[ossltest]e_ossltest.c DEPEND[ossltest]../libcrypto.a INCLUDE[ossltest]../include关键约定build.info中出现的所有路径均相对于该文件所在目录如apps/build.info中的..指向仓库根目录产物不带扩展名ossltest通过DEPEND[ossltest]../libcrypto.a显式链接静态库并通过MODULES_NO_INST声明仅用于内部测试、不安装。2.3 真实仓库中的 build.info 实例当前仓库的顶层 build.info 与该设计一脉相承并展示了文档未展开的高级语法SUBDIRScrypto ssl apps util tools fuzz providers doc IF[{- !$disabled{tests} -}] SUBDIRStest ENDIF LIBSlibcrypto libssl INCLUDE[libcrypto]. include INCLUDE[libssl]. include DEPEND[libssl]libcrypto # 空索引表示这些依赖在任何其他内容之前无条件构建 DEPEND[]include/openssl/asn1.h include/openssl/bio.h ... GENERATE[include/openssl/asn1.h]include/openssl/asn1.h.in GENERATE[include/openssl/configuration.h]{skip}include/openssl/configuration.h.in ...其中IF[{- !$disabled{...} -}] ... ENDIF是条件块由Configure根据用户禁用项求值$变量可在块内定义与复用GENERATE[...]{skip}是带属性的生成声明。crypto/build.infocrypto/build.info中还能看到文档虚构示例的原型——真实的buildinf.h生成规则与 CPUID 汇编文件生成规则DEPEND[info.o]buildinf.h DEPEND[cversion.o]buildinf.h GENERATE[buildinf.h]../util/mkbuildinf.pl $(CC) $(LIB_CFLAGS) $(CPPFLAGS_Q) $(PLATFORM) GENERATE[x86cpuid.S]x86cpuid.pl DEPEND[x86cpuid.s]perlasm/x86asm.pl2.4 Configure 的无条件信任策略文档明确Configure处理build.info时几乎不做校验将其内容视为事实。当构建树与源码树分离时它假定所有构建产物落在构建目录、所有源码位于源码树若某源文件在源码树找不到如示例中的crypto/buildinf.h则假定它是生成文件、位于构建树。这与 common0.tmpl 中从各表提取候选源文件、再对照generate表过滤的逻辑相互印证。三、%unified_info聚合后的信息数据库Configure将全部build.info的内容消化后存入%unified_info包含以下索引本节即文档核心内容索引类型内容dependshashfile [ dependency ... ]由DEPEND直接推断moduleslist由MODULES直接推断generatehashfile [ generator ... ]由GENERATE直接推断includeshashfile [ include ... ]由INCLUDE直接推断installhashtype [ file ... ]类型为programs、libraries、modules、scripts列出应安装的文件librarieslist由LIBS直接推断programslist由PROGRAMS直接推断scriptslist由SCRIPTS直接推断sourceshashfile [ sourcefile ... ]由SOURCE间接推断——目标文件以源文件为值同时目标文件又作为程序/库的源文件shared_sourceshash结构同sources仅用于构建共享库的目标文件3.1 文档示例五个 build.info 聚合后的 %unified_info将上一节虚构示例聚合后得到的数据库节选our %unified_info ( depends { apps/openssl [ libssl ], crypto/buildinf.h [ Makefile ], crypto/cversion.o [ crypto/buildinf.h ], engines/dasync [ libcrypto ], engines/ossltest [ libcrypto.a ], libssl [ libcrypto ], util/mkbuildinf.pl [ util/Foo.pm ], }, modules [ engines/dasync, engines/ossltest ], generate { crypto/buildinf.h [ util/mkbuildinf.pl, \$(CC), \$(CFLAGS)\, \$(PLATFORM)\ ], }, includes { apps/openssl [ ., include ], libcrypto [ include ], libssl [ include ], util/mkbuildinf.pl [ util ], }, install { modules [ engines/dasync ], libraries [ libcrypto, libssl ], programs [ apps/openssl ], }, libraries [ libcrypto, libssl ], programs [ apps/openssl ], sources { apps/openssl [ apps/openssl.o ], apps/openssl.o [ apps/openssl.c ], crypto/aes.o [ crypto/aes.c ], crypto/cversion.o [ crypto/cversion.c ], crypto/evp.o [ crypto/evp.c ], engines/dasync [ engines/e_dasync.o ], engines/e_dasync.o [ engines/e_dasync.c ], engines/ossltest [ engines/e_ossltest.o ], engines/e_ossltest.o [ engines/e_ossltest.c ], libcrypto [ crypto/aes.c, crypto/cversion.c, crypto/evp.c ], libssl [ ssl/tls.c ], ssl/tls.o [ ssl/tls.c ], }, );注意两处细节install表只含dasync不含ossltest因为后者声明为MODULES_NO_INSTsources表是间接的它同时记录目标文件由哪些源文件产出与产物由哪些目标文件/源文件组成两层关系使下游模板可以递归展开整个构建依赖图。文档最后点出该表的本质它隐含了一个递归构建次序——要构建所有程序必须构建apps/openssl而构建它又需要apps/openssl.o与libssl构建libssl需要ssl/tls.o与libcrypto构建libcrypto又需要它的全部目标文件……common.tmpl正是利用这张表把完整规则集自动铺开。3.2 真实仓库中的实现佐证Configure 源码中my %unified_info ();Configure即为该数据库的声明后续代码将DEPEND写入$unified_info{depends}、将SOURCE推断为$unified_info{sources}区分目标文件与产物两层、将GENERATE写入$unified_info{generate}、将INCLUDE按源码树包含目录/构建树包含目录拆分为$unified_info{includes}-{...}-{source|build}等Configure。最终该哈希表随configdata.pm一起输出用户可用perl configdata.pm --dump查看见 Configure 的注释说明。四、构建文件模板规则生成函数4.1 模板的构成构建文件模板 平台构建文件如 Unix 的 Makefile 语法 内嵌的 Perl 代码片段。Perl 片段负责生成所有与配置相关的数据与规则其核心是一组规则生成函数。文档列出并详细解释了七个主要函数参数均以key value方式传入函数职责关键参数generatesrc生成由输入产出源文件的构建规则src待生成文件、generator生成命令首项为输入文件、generator_incs/generator_deps生成器自身的包含目录/依赖、incs/deps中间调用$(CC)时的包含目录/依赖、intentlibs/dso/binsrc2obj由源文件及相关数据产出目标文件的规则obj目标文件以.o结尾函数负责按平台改写、srcs源文件列表首项与目标文件直接对应、deps、incs、intentlib/dso/binobj2lib由目标文件产出静态库Unix 语义libfoo.alib不带扩展名的库名函数负责补全、objslibobj2shlib兼容旧接口期望从静态库构建共享库——现已弃用静态库与共享库不再共享目标文件强行构建会失败用法同obj2shlibobj2shlib由对应目标文件产出共享库Unix 语义libfoo.soshlib共享库名不带扩展名、lib静态基础库名不带扩展名Windows 上可能用于导入库等支持文件、objs、deps其他库不带扩展名obj2dso由目标文件产出可运行时加载的动态共享对象插件lib、objs、depsobj2bin由目标文件产出可执行文件bin不带扩展名函数负责补全、objs、deps链接的库不带扩展名in2script由输入产出脚本文件script、sources文档对obj2shlib有两条特别说明仅当需要构建共享库时才会被调用它必须把.o扩展名转换为平台合适的扩展名。4.2 驱动模板如何调用这些函数文档给出的调用示例构建libcrypto时common.tmpl依次产生obj2shlib(shlib libcrypto, objs [ crypto/aes.o, crypto/evp.o, crypto/cversion.o ], deps [ ]); obj2lib(lib libcrypto, objs [ crypto/aes.o, crypto/evp.o, crypto/cversion.o ]); src2obj(obj crypto/aes.o, srcs [ crypto/aes.c ], deps [ ], incs [ include ], intent lib); src2obj(obj crypto/cversion.o, srcs [ crypto/cversion.c ], deps [ crypto/buildinf.h ], incs [ include ], intent lib); generatesrc(src crypto/buildinf.h, generator [ util/mkbuildinf.pl, \$(CC), $(CFLAGS)\, \$(PLATFORM)\ ], generator_incs [ util ], generator_deps [ util/Foo.pm ], incs [ ], deps [ ], intent lib);这些函数返回的字符串最终被拼接、写入生成的构建文件。可以看到crypto/buildinf.h必须先于crypto/cversion.o生成后者deps引用了它这正是%unified_info中依赖关系被模板翻译为 Makefile 依赖规则的体现。4.3 真实仓库中的模板实现三个平台模板都完整实现了文档描述的接口可直接对照阅读unix-Makefile.tmplgeneratesrc第 1511 行、src2obj第 1635 行、obj2shlib第 1713 行、obj2dso第 1837 行、obj2lib第 1880 行、obj2bin第 1898 行、in2script第 1943 行windows-makefile.tmpl同名函数自第 712 行起descrip.mms.tmplVMS 平台版本自第 940 行起。以 unix-Makefile.tmpl 的obj2lib实现为例可以看到文档语义被翻译为真实 Makefile 规则的过程sub obj2lib { my %args _; my $lib platform-staticlib($args{lib}); # 补全静态库扩展名 .a my objs map { platform-obj($_) } {$args{objs}}; # 目标文件扩展名平台化 ... return EOF; $lib: $deps \$(RM) $lib $fill_lib # 分组执行 \$(AR) \$(ARFLAGS) $lib ... \$(RANLIB) \$\ || echo Never mind. EOF }platform-staticlib/platform-obj由 Configurations/platform 目录下的平台模块提供负责补全扩展名这一文档反复强调的职责。五、阅读 build.info 与调试构建的实用要点结合本文内容在实际阅读或调试 OpenSSL 构建时可关注以下切入点从顶层 build.info 入手它声明了SUBDIRScrypto ssl apps util tools fuzz providers doc未禁用测试时追加test未弃用 3.0 接口时追加engines以及libcrypto/libssl两个核心库与全局INCLUDE。用perl configdata.pm --dump查看聚合结果该文件位于构建树顶部可能即源码树根--dump可输出%unified_info等配置数据Configure。对照条件块求值IF[{- !$disabled{asm} $config{processor} ne 386 -}]这类条件见 crypto/build.info由Configure求值后决定包含哪些源文件例如仅在未禁用汇编时才把x86cpuid.S等 CPUID 汇编源加入libcrypto。区分生成文件与源码凡是GENERATE[...]声明过的文件如buildinf.h、各*cpuid.S都是构建时由 Perl 脚本util/mkbuildinf.pl、x86cpuid.pl等现场生成的不要在源码树中寻找它们的实体。结语OpenSSL Unified Scheme 通过build.info声明、%unified_info聚合、模板函数渲染三层分工把多平台构建规则从海量平台细节中解放出来任何新增程序、库、模块或脚本只需在对应目录的build.info中追加几行声明其余扩展名推断、依赖排序、安装清单、共享库与静态库的差异全部交由Configure与平台模板自动完成。本文所引设计文档位于 Configurations/README-design.md配套的真实声明文件与模板实现可在 build.info、crypto/build.info、common0.tmpl 与 unix-Makefile.tmpl 中继续深入研读。赞分享固件操作系统【免费下载链接】CloverBootloaderBootloader for macOS, Windows and Linux in UEFI and in legacy mode项目地址https://gitcode.com/gh_mirrors/cl/CloverBootloader点击查看免费下载相关推荐CloverBootloader 内置 OpenSSL 构建系统解析Configure 目标平台配置、build.info 与 unified 构建体系CloverBootloader 内置 OpenSSL 构建系统解析Configure 目标平台配置、build.info 与 unified 构建体系 Op固件操作系统OpenSSL 构建配置体系详解Configurations 目录中的目标配置、build.info 与 unified 构建系统OpenSSL 构建配置体系详解Configurations 目录中的目标配置、build.info 与 unified 构建系统 在 OpenSSL 中密码学网络安全通信FiraCode构建系统设计可维护的构建系统架构FiraCode构建系统设计可维护的构建系统架构 引言 你是否曾为复杂的字体项目构建流程感到困扰编译命令冗长、依赖关系混乱、跨平台兼容性问题频发本文将深入开发工具上一篇agent-core LLM 协议收敛把多厂商模型接入统一到 OpenAI 兼容与 Anthropic 两套协议下一篇FEALPy用 Python 手写有限元全流程的仿真引擎创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑