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,最终调用本地编译器完成编译。
EDK II 构建系统三层架构 EDK II 构建系统三层架构 元数据层(Meta-Data Layer) .dsc(平台描述) .fdf(固件描述) .dec(包声明) 定义模块列表、PCD、库实例 定义固件卷、FDF布局 声明 GUID、协议、PPI、PCD 配置层(Configuration Layer) target.txt tools_def.txt build_rule.txt 定义目标架构、工具链、编译选项 执行层(Execution Layer) Build 命令 Makefile 生成 本地编译器/链接器 解析配置 → 生成 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 命令执行时,遵循以下标准流程:

  1. 读取配置:解析 target.txt 获取平台、架构、工具链等参数。
  2. 解析元数据:读取 .dsc 文件,展开模块列表、库实例、PCD 设置。
  3. 生成 AutoGen:为每个模块生成 AutoGen.c / AutoGen.h,包含 GUID、PCD、协议等声明。
  4. 生成 Makefile:根据 build_rule.txt 为每个模块生成独立的 Makefile。
  5. 并行编译:调用本地工具链(CC/ASM/DLINK)编译源文件,生成 .obj / .lib / .efi。
  6. 固件封装:使用 GenFw、GenFds 等工具将模块封装为 FV(Firmware Volume),最终生成 FLASH 映像。
Build 命令执行流程 Build 命令执行流程 1. 读取 target.txt 配置 2. 解析 .dsc / .dec / .fdf 3. 生成 AutoGen.c / AutoGen.h 4. 生成模块级 Makefile 5. 并行编译(CC/ASM/DLINK) 6. 固件封装 → 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> 单独编译特定模块以缩小问题范围。

3.9 本章小结