aboutsummaryrefslogtreecommitdiff
path: root/core/release_config.mk
blob: a7b5b3ff381cd16e206952ce3446aef1efe153ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# Copyright (C) 2023 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


# -----------------------------------------------------------------
# Choose the flag files
# -----------------------------------------------------------------
# Release configs are defined in reflease_config_map files, which map
# the short name (e.g. -next) used in lunch to the starlark files
# defining the build flag values.
#
# (If you're thinking about aconfig flags, there is one build flag,
# RELEASE_ACONFIG_VALUE_SETS, that sets which aconfig_value_set
# module to use to set the aconfig flag values.)
#
# The short release config names *can* appear multiple times, to allow
# for AOSP and vendor specific flags under the same name, but the
# individual flag values must appear in exactly one config.  Vendor
# does not override AOSP, or anything like that.  This is because
# vendor code usually includes prebuilts, and having vendor compile
# with different flags from AOSP increases the likelihood of flag
# mismatch.

# Do this first, because we're going to unset TARGET_RELEASE before
# including anyone, so they don't start making conditionals based on it.
# This logic is in make because starlark doesn't understand optional
# vendor files.

# If this is a google source tree, restrict it to only the one file
# which has OWNERS control.  If it isn't let others define their own.
# TODO: Remove wildcard for build/release one when all branch manifests
# have updated.
config_map_files := $(wildcard build/trunk_release/release_config_map.mk) \
    $(wildcard build/release/release_config_map.mk) \
    $(wildcard vendor/google_shared/build/release/release_config_map.mk) \
    $(if $(wildcard vendor/google/release/release_config_map.mk), \
        vendor/google/release/release_config_map.mk, \
        $(sort \
            $(wildcard device/*/release/release_config_map.mk) \
            $(wildcard device/*/*/release/release_config_map.mk) \
            $(wildcard vendor/*/release/release_config_map.mk) \
            $(wildcard vendor/*/*/release/release_config_map.mk) \
        ) \
    )

# PRODUCT_RELEASE_CONFIG_MAPS is set by Soong using an initial run of product
# config to capture only the list of config maps needed by the build.
# Keep them in the order provided, but remove duplicates.
$(foreach map,$(PRODUCT_RELEASE_CONFIG_MAPS), \
    $(if $(filter $(map),$(config_map_files)),,$(eval config_map_files += $(map))) \
)

# Declare an alias release-config
#
# This should be used to declare a release as an alias of another, meaning no
# release config files should be present.
#
# $1 config name
# $2 release config for which it is an alias
define alias-release-config
    $(call _declare-release-config,$(1),,$(2),true)
endef

# Declare or extend a release-config.
#
# The order of processing is:
# 1. Recursively apply any overridden release configs.  Only apply each config
#    the first time we reach it.
# 2. Apply any files for this release config, in the order they were added to
#    the declaration.
#
# Example:
#   With these declarations:
#     $(declare-release-config foo, foo.scl)
#     $(declare-release-config bar, bar.scl, foo)
#     $(declare-release-config baz, baz.scl, bar)
#     $(declare-release-config bif, bif.scl, foo baz)
#     $(declare-release-config bop, bop.scl, bar baz)
#
#   TARGET_RELEASE:
#     - bar will use: foo.scl bar.scl
#     - baz will use: foo.scl bar.scl baz.scl
#     - bif will use: foo.scl bar.scl baz.scl bif.scl
#     - bop will use: foo.scl bar.scl baz.scl bop.scl
#
# $1 config name
# $2 release config files
# $3 overridden release config
define declare-release-config
    $(call _declare-release-config,$(1),$(2),$(3),)
endef

define _declare-release-config
    $(if $(strip $(2)$(3)),,  \
        $(error declare-release-config: config $(strip $(1)) must have release config files, override another release config, or both) \
    )
    $(if $(strip $(4)),$(eval _all_release_configs.$(strip $(1)).ALIAS := true))
    $(eval _all_release_configs := $(sort $(_all_release_configs) $(strip $(1))))
    $(if $(strip $(3)), \
      $(if $(filter $(_all_release_configs), $(strip $(3))),
        $(if $(filter $(_all_release_configs.$(strip $(1)).OVERRIDES),$(strip $(3))),,
          $(eval _all_release_configs.$(strip $(1)).OVERRIDES := $(_all_release_configs.$(strip $(1)).OVERRIDES) $(strip $(3)))), \
        $(error No release config $(strip $(3))) \
      ) \
    )
    $(eval _all_release_configs.$(strip $(1)).DECLARED_IN := $(_included) $(_all_release_configs.$(strip $(1)).DECLARED_IN))
    $(eval _all_release_configs.$(strip $(1)).FILES := $(_all_release_configs.$(strip $(1)).FILES) $(strip $(2)))
endef

# Include the config map files and populate _flag_declaration_files.
# If the file is found more than once, only include it the first time.
_flag_declaration_files :=
_included_config_map_files :=
$(foreach f, $(config_map_files), \
    $(eval FLAG_DECLARATION_FILES:= ) \
    $(if $(filter $(_included_config_map_files),$(f)),,\
        $(eval _included := $(f)) \
        $(eval include $(f)) \
        $(eval _flag_declaration_files += $(FLAG_DECLARATION_FILES)) \
        $(eval _included_config_map_files += $(f)) \
    ) \
)
FLAG_DECLARATION_FILES :=

# Verify that all inherited/overridden release configs are declared.
$(foreach config,$(_all_release_configs),\
  $(foreach r,$(all_release_configs.$(r).OVERRIDES),\
    $(if $(strip $(_all_release_configs.$(r).FILES)$(_all_release_configs.$(r).OVERRIDES)),,\
    $(error Release config $(config) [declared in: $(_all_release_configs.$(r).DECLARED_IN)] inherits from non-existent $(r).)\
)))
# Verify that alias configs do not have config files.
$(foreach r,$(_all_release_configs),\
  $(if $(_all_release_configs.$(r).ALIAS),$(if $(_all_release_configs.$(r).FILES),\
    $(error Alias release config "$(r)" may not specify release config files $(_all_release_configs.$(r).FILES))\
)))

ifeq ($(TARGET_RELEASE),)
    # We allow some internal paths to explicitly set TARGET_RELEASE to the
    # empty string.  For the most part, 'make' treats unset and empty string as
    # the same.  But the following line differentiates, and will only assign
    # if the variable was completely unset.
    TARGET_RELEASE ?= was_unset
    ifeq ($(TARGET_RELEASE),was_unset)
        $(error No release config set for target; please set TARGET_RELEASE, or if building on the command line use 'lunch <target>-<release>-<build_type>', where release is one of: $(_all_release_configs))
    endif
    # Instead of leaving this string empty, we want to default to a valid
    # setting.  Full builds coming through this path is a bug, but in case
    # of such a bug, we want to at least get consistent, valid results.
    TARGET_RELEASE = trunk_staging
endif

# During pass 1 of product config, using a non-existent release config is not an error.
# We can safely assume that we are doing pass 1 if DUMP_MANY_VARS=="PRODUCT_RELEASE_CONFIG_MAPS".
ifneq (PRODUCT_RELEASE_CONFIG_MAPS,$(DUMP_MANY_VARS))
    ifeq ($(filter $(_all_release_configs), $(TARGET_RELEASE)),)
        $(error No release config found for TARGET_RELEASE: $(TARGET_RELEASE). Available releases are: $(_all_release_configs))
    endif
endif

# Choose flag files
# Don't sort this, use it in the order they gave us.
# Do allow duplicate entries, retaining only the first usage.
flag_value_files :=

# Apply overrides recursively
#
# $1 release config that we override
applied_releases :=
define _apply-release-config-overrides
$(foreach r,$(1), \
  $(if $(filter $(r),$(applied_releases)),, \
    $(foreach o,$(_all_release_configs.$(r).OVERRIDES),$(call _apply-release-config-overrides,$(o)))\
    $(eval applied_releases += $(r))\
    $(foreach f,$(_all_release_configs.$(r).FILES), \
      $(if $(filter $(f),$(flag_value_files)),,$(eval flag_value_files += $(f)))\
    )\
  )\
)
endef
$(call _apply-release-config-overrides,$(TARGET_RELEASE))
# Unset variables so they can't use them
define declare-release-config
$(error declare-release-config can only be called from inside release_config_map.mk files)
endef
define _apply-release-config-overrides
$(error invalid use of apply-release-config-overrides)
endef

# TODO: Remove this check after enough people have sourced lunch that we don't
# need to worry about it trying to do get_build_vars TARGET_RELEASE. Maybe after ~9/2023
ifneq ($(CALLED_FROM_SETUP),true)
define TARGET_RELEASE
$(error TARGET_RELEASE may not be accessed directly. Use individual flags.)
endef
else
TARGET_RELEASE:=
endif
.KATI_READONLY := TARGET_RELEASE

$(foreach config, $(_all_release_configs), \
    $(eval _all_release_configs.$(config).DECLARED_IN:= ) \
    $(eval _all_release_configs.$(config).FILES:= ) \
)
_all_release_configs:=
config_map_files:=
applied_releases:=


# -----------------------------------------------------------------
# Flag declarations and values
# -----------------------------------------------------------------
# This part is in starlark.  We generate a root starlark file that loads
# all of the flags declaration files that we found, and the flag_value_files
# that we chose from the config map above.  Then we run that, and load the
# results of that into the make environment.

# _flag_declaration_files is the combined list of FLAG_DECLARATION_FILES set by
# release_config_map.mk files above.

# Because starlark can't find files with $(wildcard), write an entrypoint starlark script that
# contains the result of the above wildcards for the starlark code to use.
filename_to_starlark=$(subst /,_,$(subst .,_,$(1)))
_c:=load("//build/make/core/release_config.scl", "release_config")
_c+=$(newline)def add(d, k, v):
_c+=$(newline)$(space)d = dict(d)
_c+=$(newline)$(space)d[k] = v
_c+=$(newline)$(space)return d
_c+=$(foreach f,$(_flag_declaration_files),$(newline)load("$(f)", flags_$(call filename_to_starlark,$(f)) = "flags"))
_c+=$(newline)all_flags = [] $(foreach f,$(_flag_declaration_files),+ [add(x, "declared_in", "$(f)") for x in flags_$(call filename_to_starlark,$(f))])
_c+=$(foreach f,$(flag_value_files),$(newline)load("//$(f)", values_$(call filename_to_starlark,$(f)) = "values"))
_c+=$(newline)all_values = [] $(foreach f,$(flag_value_files),+ [add(x, "set_in", "$(f)") for x in values_$(call filename_to_starlark,$(f))])
_c+=$(newline)variables_to_export_to_make = release_config(all_flags, all_values)
$(file >$(OUT_DIR)/release_config_entrypoint.scl,$(_c))
_c:=
filename_to_starlark:=

# Exclude the entrypoint file as a dependency (by passing it as the 2nd argument) so that we don't
# rerun kati every build. Kati will replay the $(file) command that generates it every build,
# updating its timestamp.
#
# We also need to pass --allow_external_entrypoint to rbcrun in case the OUT_DIR is set to something
# outside of the source tree.
$(call run-starlark,$(OUT_DIR)/release_config_entrypoint.scl,$(OUT_DIR)/release_config_entrypoint.scl,--allow_external_entrypoint)