3. EDK II 构建系统:Build体系架构、target.txt/tools_def.txt/Conf文件详解、Build命令参数与流程
3.1 构建系统整体架构
EDK II 构建系统(Build System)基于 Makefile 与 Python 混合驱动,核心工具为 Build 命令。其设计目标是将平台固件的编译、链接、封装过程标准化,支持跨架构(IA32/X64/AARCH64/RISCV64)与跨工具链(VS/GCC/ICC/CLANG)开发。
构建系统由三层组成:元数据层(.dsc/.fdf/.dec)、配置层(Conf/)、执行层(Build 命令 + 工具链)。
核心原则: 所有构建规则由
target.txt 与 tools_def.txt 定义,Build 命令解析后生成平台级 Makefile,最终调用本地编译器完成编译。
3.2 Conf 目录与核心配置文件详解
Conf 目录位于 EDK II 工作区根目录(通常为 Conf/),包含三个核心配置文件:target.txt、tools_def.txt、build_rule.txt。这些文件由 edksetup.bat 或 edksetup.sh 初始化生成。
| 配置文件 | 作用 | 典型内容 |
|---|---|---|
| target.txt | 定义构建目标与平台选择 | ACTIVE_PLATFORM、TARGET、TARGET_ARCH、TOOL_CHAIN_TAG |
| tools_def.txt | 定义工具链路径与编译标志 | VS2019x86、GCC5、CLANG38 等工具链定义 |
| build_rule.txt | 定义文件类型到编译规则的映射 | .c → CC、.asm → ASM、.vfr → VFR 编译规则 |
3.3 target.txt 关键参数
target.txt 是构建系统的入口配置文件,Build 命令首先读取此文件。以下为最关键的参数:
- ACTIVE_PLATFORM:指定当前活动的平台描述文件(.dsc)路径,例如
MdeModulePkg/MdeModulePkg.dsc。 - TARGET:构建目标类型,可选
DEBUG、RELEASE、NOOPT。DEBUG 包含调试符号,RELEASE 优化且无调试信息。 - TARGET_ARCH:目标 CPU 架构,支持
IA32、X64、AARCH64、RISCV64等,可指定多个(空格分隔)。 - TOOL_CHAIN_TAG:工具链标签,例如
VS2019x86、GCC5、CLANG38,必须与tools_def.txt中定义一致。 - MAX_CONCURRENT_THREAD_NUMBER:并行编译线程数,默认 0(自动检测 CPU 核心数)。
- BUILD_RULE_CONF:自定义 build_rule.txt 路径,默认使用 Conf/build_rule.txt。
最佳实践: 建议将 ACTIVE_PLATFORM 与 TOOL_CHAIN_TAG 写入 target.txt,避免每次 Build 命令重复输入。对于多架构项目,TARGET_ARCH 可设为
IA32 X64 实现一次构建双架构。
3.4 tools_def.txt 工具链定义
tools_def.txt 包含所有支持的工具链定义,每个工具链由一组 宏变量 描述。变量命名规则为:$(TOOL_CHAIN_TAG)_$(ARCH)_$(TOOL)。
以下为 GCC5 工具链在 X64 架构下的典型定义片段:
# GCC5 工具链定义示例
DEFINE GCC5_X64_PREFIX = gcc
DEFINE GCC5_X64_CC_FLAGS = -c -Os -Wall -Werror -fno-builtin -fshort-wchar -fno-strict-aliasing -m64
DEFINE GCC5_X64_DLINK_FLAGS = -nostdlib -Wl,-q,--gc-sections -m elf_x86_64
DEFINE GCC5_X64_ASM_FLAGS = -c -x assembler -m64
# 工具路径
DEFINE GCC5_X64_CC = $(GCC5_X64_PREFIX)
DEFINE GCC5_X64_DLINK = $(GCC5_X64_PREFIX)-ld
DEFINE GCC5_X64_ASM = $(GCC5_X64_PREFIX)-as
关键宏分类:
- CC_FLAGS:C 编译器标志
- DLINK_FLAGS:链接器标志
- ASM_FLAGS:汇编器标志
- SLINK_FLAGS:静态库归档标志
- VFR_FLAGS:VFR 文件编译标志
注意: 修改 tools_def.txt 后必须重新执行
edksetup 或重启命令行,否则环境变量不会更新。建议不要直接修改原始文件,而是通过 --conf= 参数指定自定义配置目录。
3.5 Build 命令参数详解
Build 命令是 EDK II 构建系统的核心入口,支持丰富的命令行参数。以下为最常用的参数:
| 参数 | 缩写 | 说明 | 示例 |
|---|---|---|---|
--platform |
-p |
指定平台 DSC 文件路径 | -p MdeModulePkg/MdeModulePkg.dsc |
--target |
-t |
构建目标(DEBUG/RELEASE/NOOPT) | -t DEBUG |
--arch |
-a |
目标架构 | -a X64 |
--toolchain |
-T |
工具链标签 | -T GCC5 |
--module |
-m |
仅构建指定模块(.inf) | -m MdeModulePkg/Universal/HelloWorld/HelloWorld.inf |
--buildtarget |
-b |
同 --target,用于指定构建类型 | -b RELEASE |
--conf |
-c |
指定 Conf 目录路径 | -c /path/to/custom/conf |
--clean |
-n |
清理构建输出 | build -n |
--verbose |
-v |
显示详细编译日志 | build -v |
--silent |
-s |
静默模式,仅输出错误 | build -s |
3.6 构建流程详解
Build 命令执行时,遵循以下标准流程:
- 读取配置:解析
target.txt获取平台、架构、工具链等参数。 - 解析元数据:读取
.dsc文件,展开模块列表、库实例、PCD 设置。 - 生成 AutoGen:为每个模块生成
AutoGen.c/AutoGen.h,包含 GUID、PCD、协议等声明。 - 生成 Makefile:根据
build_rule.txt为每个模块生成独立的 Makefile。 - 并行编译:调用本地工具链(CC/ASM/DLINK)编译源文件,生成
.obj/.lib/.efi。 - 固件封装:使用
GenFw、GenFds等工具将模块封装为 FV(Firmware Volume),最终生成FLASH映像。
3.7 构建输出目录结构
构建完成后,输出文件位于 Build/ 目录下,结构如下:
Build/
└── <PlatformName>/
├── DEBUG_<ToolChain>/
│ ├── <Arch>/
│ │ ├── <ModuleName>/
│ │ │ ├── DEBUG/
│ │ │ ├── OUTPUT/
│ │ │ └── Makefile
│ ├── FV/
│ │ ├── Ffs/
│ │ ├── Fv/
│ │ └── <PlatformName>.fd
│ └── <Arch>.map
└── RELEASE_<ToolChain>/
└── ...(同 DEBUG 结构)
- DEBUG/OUTPUT:编译中间文件(.obj、.lib、.efi)
- FV/:固件卷文件,包含 FFS 文件与最终 FLASH 映像
- .map:链接映射文件,用于调试地址解析
3.8 常见构建问题与排查
常见错误 1: "Tool chain not found" — 检查 tools_def.txt 中工具链定义是否正确,以及环境变量 PATH 是否包含编译器路径。
常见错误 2: "Module not found in DSC" — 确认 .dsc 文件中已包含该模块的 INF 路径,或使用
-m 参数时路径正确。
调试技巧: 使用
build -v 查看完整编译命令;使用 build -n 清理后重新构建;使用 build -m <Module.inf> 单独编译特定模块以缩小问题范围。