前一篇 介绍了如何执行构建命令。这篇看配置怎样被选中和加载。

一、构建目标与配置加载

1.1 T:选择构建目标

要知道本次构建用了哪套配置,可以先查构建命令传入了哪些变量、Makefile 怎样使用它们。

这份 SDK 用 T 选择构建目标,顶层 Makefile 根据T的值,拼出配置文件路径。传入 T=best1306p,选中的就是 config/best1306p/target.mk:

正文配图 图 1:顶层 Makefile 根据 T 拼出配置路径

默认的构建输出目录如下:

正文配图 图 2:顶层 Makefile 中的输出目录设置与目标检查

Makefile 还会检查这个文件是否存在。不存在时,会报 Invalid target。

修改配置前先看构建命令里的 T,再去找对应目录,避免改了另一套配置。

1.2 CHIP:指定芯片平台

选出产品配置后,还需要指定它使用的芯片平台。

CHIP ?= best1306p

这里用的也是 best1306p 作为默认值。

两个变量的用途分别是:

  • T:选择哪套产品或构建配置。
  • CHIP:指定这套配置使用的芯片平台。

这次两者恰好都叫 best1306p。换成产品目标时,它们可能不同。

1.3 配置文件的加载顺序

配置拆在多个文件中时,Make 可以用 include 读入其他文件。因此,查配置除了找赋值,还要沿着 include 看它们的加载顺序。

这份工程的顶层 Makefile 先读入下面两个文件:

正文配图 图 3:先读取目标配置,再读取公共配置

srctree 表示源码根目录。这里先读取 target.mk,再读取 common.mk。

target.mk 里面还有其他 include。Make 读到这里,会先处理被包含的文件,再回来接着读后面的配置。

这个构建目标的配置加载顺序是:

%%{init: {"flowchart": {"htmlLabels": true, "wrappingWidth": 1000, "rankSpacing": 30}, "themeVariables": {"lineColor": "#71829a"}}}%%
flowchart LR
    A["顶层 Makefile"]
    B["target.mk"]
    C["按顺序读入专项配置"]
    D["custom.mk"]
    E["common.mk"]
    A --> B --> C --> D
    A --> E
    class A,B,C,D blue;
    class E green;
    classDef blue fill:#e8f2ff,stroke:#7ba4d8,color:#23456b,stroke-width:1.5px;
    classDef green fill:#e7f4ec,stroke:#78aa8b,color:#24563a,stroke-width:1.5px;
    classDef amber fill:#fff3df,stroke:#d5a25b,color:#72501e,stroke-width:1.5px;

正文配图 图 4:target.mk 中专项配置与 custom.mk 的加载顺序

图里的专项配置大多按 CHIP 选择路径,custom.mk 则按 T。其他产品目标可能有不同写法,需要看对应的 target.mk。

还有一个容易漏掉的位置:custom.mk 后面仍然会读取 common.mk。查变量最终值时,不能看到 custom.mk 就停下,还要看公共配置有没有继续赋值或处理。

《系统总览(01)》讲过按条件加载 ANC 配置 :变量要在判断之前设置。后面改值,前面的 ifeq 不会重新执行。查配置时,除了看值,还得看赋值位置。

二、配置变量的覆盖规则

配置按顺序读入,同一个变量也可能被设置多次。多音量表这个开关就是一个例子。

2.1 默认配置与产品定制

target.mk 中有:

正文配图 图 5:target.mk 将多音量表的默认值设为 0

后面加载的 custom.mk 中又有:

正文配图 图 6:custom.mk 将多音量表设为 1

在没有外部传入该变量的情况下,前面的 ?= 0 先提供默认值,后面的普通赋值再将它设为 1。

只查 target.mk 的话,容易误以为这个开关是关闭的。

2.2 命令行变量的优先级

如果执行:

make T=best1306p CODEC_DAC_MULTI_VOLUME_TABLE=0 -j

这时,即使 custom.mk 里写了 = 1,命令行传入的 0 也会保留下来。

普通的 =、:= 都不能覆盖命令行传入的同名变量的值;如果需要强覆盖,需要在赋值前面加 override,这样也会覆盖命令行传入的值。

碰到同名变量,可以依次查:

  1. 构建命令是否指定同名变量的值。
  2. 文件中有哪些有效赋值,使用什么赋值方式、按什么顺序加载。
  3. 文件是否使用 override强覆盖,以及变量在哪里被判断或使用。

上一篇:编译配置(01):编译命令与构建脚本

下一篇:编译配置(03):Make 变量怎样变成 C 宏