第 1 步:BoardConfig.mk 设置 Make 变量
bash
# device/rockchip/rk3576/BoardConfig.mk
BOARD_PRESSURE_SENSOR_SUPPORT := true
这就是一个普通的 Make 变量,没什么特别的。
第 2 步:sensors.mk 把 Make 变量注册到 Soong 命名空间 # device/rockchip/common/modules/sensors.mk
bash
$(call soong_config_set,sensor_rockchip,pressure,$(BOARD_PRESSURE_SENSOR_SUPPORT))
soong_config_set 的定义在 build/make/core/config.mk:309:
define soong_config_set
$(call soong_config_define_internal,$1,$2) \
$(eval SOONG_CONFIG_$(strip $1)_$(strip $2):=$3)
endef
执行后,实际效果是创建了两个 Make 变量:
bash
SOONG_CONFIG_NAMESPACES += sensor_rockchip
SOONG_CONFIG_sensor_rockchip += pressure
SOONG_CONFIG_sensor_rockchip_pressure := true # ← 值在这里!
第 3 步:soong_config.mk 把这些变量写进 JSON 文件
这是最关键的桥梁!在 build/make/core/soong_config.mk:269-275:
bash
$(call add_json_map, VendorVars)
$(foreach namespace,$(sort $(SOONG_CONFIG_NAMESPACES)),\
$(call add_json_map, $(namespace))\
$(foreach key,$(sort $(SOONG_CONFIG_$(namespace))),\
$(call add_json_str,$(key),$(subst ",\",$(SOONG_CONFIG_$(namespace)_$(key)))))\
$(call end_json_map))
$(call end_json_map)
翻译成人话:遍历所有 SOONG_CONFIG_NAMESPACES,把每个命名空间下的变量和值,写成 JSON。
最终生成的 out/soong/soong.variables 文件里会有:
javascript
{
"VendorVars": {
"sensor_rockchip": {
"pressure": "true",
"gravity": "true",
"compass": "false",
"light": "true"
}
}
}
这就是桥梁!Make 把值写进 JSON,Soong 从 JSON 读出来。
第 4 步:Soong (Go 代码) 读取 JSON
在 build/soong/android/variable.go:435 定义了结构体:
bash
type productVariables struct {
// ...
VendorVars map[string]map[string]string `json:",omitempty"`
// ...
}
Soong 启动时解析 soong.variables JSON 文件,VendorVars 字段就自动拿到了所有命名空间的值。
然后在 config.go:1574:
cpp
func (c *config) VendorConfig(name string) VendorConfig {
return soongconfig.Config(c.productVariables.VendorVars[name])
}
传入命名空间名 "sensor_rockchip",就能拿到 {"pressure": "true", ...}。
第 5 步:Soong 根据 Android.bp 的声明决定加什么 cflags
在 build/soong/android/soongconfig/modules.go 的 boolVariable.PropertiesToApply 方法(第 741-755 行):
java
func (b boolVariable) PropertiesToApply(config SoongConfig, values reflect.Value) (interface{}, error) {
if config.Bool(b.variable) { // ← 读取 pressure 的值,"true" → true
values = removeDefault(values)
return values.Interface(), nil // ← 返回 pressure=true 对应的 cflags
}
// 否则返回 conditions_default 对应的 cflags
v := values.Elem().Elem()
if f := conditionsDefaultField(v); f.IsValid() {
return f.Interface(), nil
}
return nil, nil
}
然后 Soong 把返回的 cflags 合并到编译参数里,最终等价于:
bash
clang -DPRESSURE_SENSOR_SUPPORT=1 ...
一图总结
┌──────────────────────────────────────────────────────────┐
│ ① BoardConfig.mk │
│ BOARD_PRESSURE_SENSOR_SUPPORT := true │
└─────────────────────┬────────────────────────────────────┘
│ Make 变量赋值
▼
┌──────────────────────────────────────────────────────────┐
│ ② sensors.mk │
│ $(call soong_config_set,sensor_rockchip,pressure,true) │
│ ↓ 产生: │
│ SOONG_CONFIG_sensor_rockchip_pressure := true │
└─────────────────────┬────────────────────────────────────┘
│ Make 变量
▼
┌──────────────────────────────────────────────────────────┐
│ ③ soong_config.mk (桥梁!) │
│ 遍历 SOONG_CONFIG_NAMESPACES,写 JSON: │
│ ↓ │
│ out/soong/soong.variables: │
│ { "VendorVars": { "sensor_rockchip": { "pressure":"true"}}}│
└─────────────────────┬────────────────────────────────────┘
│ JSON 文件(磁盘)
▼
┌──────────────────────────────────────────────────────────┐
│ ④ Soong (Go) │
│ 解析 soong.variables → productVariables.VendorVars │
│ config.VendorConfig("sensor_rockchip") → {"pressure":"true"}│
└─────────────────────┬────────────────────────────────────┘
│ Go 代码中的 map
▼
┌──────────────────────────────────────────────────────────┐
│ ⑤ Android.bp 匹配 │
│ soong_config_variables.pressure = true │
│ → 选择 cflags: "-DPRESSURE_SENSOR_SUPPORT=1" │
│ → 编译时: clang -DPRESSURE_SENSOR_SUPPORT=1 │
└─────────────────────┬────────────────────────────────────┘
│ C 宏
▼
┌──────────────────────────────────────────────────────────┐
│ ⑥ Sensors.h (C++ 代码) │
│ #if PRESSURE_SENSOR_SUPPORT ← 1,生效! │
│ AddSensor<PressureSensor>(); │
│ #endif │
└──────────────────────────────────────────────────────────┘
核心就一句话:soong_config.mk 第 269-275 行把 Make 变量写进 soong.variables JSON 文件,Soong 从这个 JSON
读出来,然后匹配 Android.bp 里的 soong_config_variables 决定加什么 cflags。