blob: 5fa60124eaed89e4aa9b5bb2153688d59d6ae937 [file] [log] [blame]
Colin Cross9d34f352019-11-22 16:03:51 -08001// Copyright 2019 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package android
16
17// This file provides module types that implement wrapper module types that add conditionals on
18// Soong config variables.
19
20import (
21 "fmt"
22 "path/filepath"
Paul Duffine8b47682023-01-09 15:42:57 +000023 "reflect"
Colin Cross9d34f352019-11-22 16:03:51 -080024 "strings"
Paul Duffine8b47682023-01-09 15:42:57 +000025 "sync"
Colin Cross9d34f352019-11-22 16:03:51 -080026 "text/scanner"
27
28 "github.com/google/blueprint"
29 "github.com/google/blueprint/parser"
30 "github.com/google/blueprint/proptools"
31
32 "android/soong/android/soongconfig"
33)
34
35func init() {
Paul Duffin32299982023-01-09 14:02:06 +000036 RegisterSoongConfigModuleBuildComponents(InitRegistrationContext)
Colin Cross9d34f352019-11-22 16:03:51 -080037}
38
Paul Duffin32299982023-01-09 14:02:06 +000039func RegisterSoongConfigModuleBuildComponents(ctx RegistrationContext) {
40 ctx.RegisterModuleType("soong_config_module_type_import", SoongConfigModuleTypeImportFactory)
41 ctx.RegisterModuleType("soong_config_module_type", SoongConfigModuleTypeFactory)
42 ctx.RegisterModuleType("soong_config_string_variable", SoongConfigStringVariableDummyFactory)
43 ctx.RegisterModuleType("soong_config_bool_variable", SoongConfigBoolVariableDummyFactory)
44}
45
46var PrepareForTestWithSoongConfigModuleBuildComponents = FixtureRegisterWithContext(RegisterSoongConfigModuleBuildComponents)
47
Colin Cross9d34f352019-11-22 16:03:51 -080048type soongConfigModuleTypeImport struct {
49 ModuleBase
50 properties soongConfigModuleTypeImportProperties
51}
52
53type soongConfigModuleTypeImportProperties struct {
54 From string
55 Module_types []string
56}
57
58// soong_config_module_type_import imports module types with conditionals on Soong config
59// variables from another Android.bp file. The imported module type will exist for all
60// modules after the import in the Android.bp file.
61//
Liz Kammer432bd592020-12-16 12:42:02 -080062// Each soong_config_variable supports an additional value `conditions_default`. The properties
63// specified in `conditions_default` will only be used under the following conditions:
64// bool variable: the variable is unspecified or not set to a true value
65// value variable: the variable is unspecified
66// string variable: the variable is unspecified or the variable is set to a string unused in the
67// given module. For example, string variable `test` takes values: "a" and "b",
68// if the module contains a property `a` and `conditions_default`, when test=b,
69// the properties under `conditions_default` will be used. To specify that no
70// properties should be amended for `b`, you can set `b: {},`.
71//
Colin Cross9d34f352019-11-22 16:03:51 -080072// For example, an Android.bp file could have:
73//
74// soong_config_module_type_import {
Bill Peckhamc93258b2020-02-04 13:17:24 -080075// from: "device/acme/Android.bp",
Colin Cross9d34f352019-11-22 16:03:51 -080076// module_types: ["acme_cc_defaults"],
77// }
78//
79// acme_cc_defaults {
80// name: "acme_defaults",
81// cflags: ["-DGENERIC"],
82// soong_config_variables: {
83// board: {
84// soc_a: {
85// cflags: ["-DSOC_A"],
86// },
87// soc_b: {
88// cflags: ["-DSOC_B"],
89// },
Liz Kammer432bd592020-12-16 12:42:02 -080090// conditions_default: {
91// cflags: ["-DSOC_DEFAULT"],
92// },
Colin Cross9d34f352019-11-22 16:03:51 -080093// },
94// feature: {
95// cflags: ["-DFEATURE"],
Liz Kammer432bd592020-12-16 12:42:02 -080096// conditions_default: {
97// cflags: ["-DFEATURE_DEFAULT"],
98// },
Colin Cross9d34f352019-11-22 16:03:51 -080099// },
Dan Willemsenb0935db2020-03-23 19:42:18 -0700100// width: {
101// cflags: ["-DWIDTH=%s"],
Liz Kammer432bd592020-12-16 12:42:02 -0800102// conditions_default: {
103// cflags: ["-DWIDTH=DEFAULT"],
104// },
Dan Willemsenb0935db2020-03-23 19:42:18 -0700105// },
Colin Cross9d34f352019-11-22 16:03:51 -0800106// },
107// }
108//
109// cc_library {
110// name: "libacme_foo",
111// defaults: ["acme_defaults"],
112// srcs: ["*.cpp"],
113// }
114//
115// And device/acme/Android.bp could have:
116//
117// soong_config_module_type {
118// name: "acme_cc_defaults",
119// module_type: "cc_defaults",
120// config_namespace: "acme",
Dan Willemsen2b8b89c2020-03-23 19:39:34 -0700121// variables: ["board"],
122// bool_variables: ["feature"],
Dan Willemsenb0935db2020-03-23 19:42:18 -0700123// value_variables: ["width"],
Colin Cross9d34f352019-11-22 16:03:51 -0800124// properties: ["cflags", "srcs"],
125// }
126//
127// soong_config_string_variable {
128// name: "board",
Liz Kammer432bd592020-12-16 12:42:02 -0800129// values: ["soc_a", "soc_b", "soc_c"],
Colin Cross9d34f352019-11-22 16:03:51 -0800130// }
131//
Colin Cross9d34f352019-11-22 16:03:51 -0800132// If an acme BoardConfig.mk file contained:
Sasha Smundak18fd0992021-08-24 14:05:19 -0700133// $(call add_sonng_config_namespace, acme)
134// $(call add_soong_config_var_value, acme, board, soc_a)
135// $(call add_soong_config_var_value, acme, feature, true)
136// $(call add_soong_config_var_value, acme, width, 200)
Colin Cross9d34f352019-11-22 16:03:51 -0800137//
Dan Willemsenb0935db2020-03-23 19:42:18 -0700138// Then libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE -DWIDTH=200".
Liz Kammer432bd592020-12-16 12:42:02 -0800139//
140// Alternatively, if acme BoardConfig.mk file contained:
141//
142// SOONG_CONFIG_NAMESPACES += acme
143// SOONG_CONFIG_acme += \
144// board \
145// feature \
146//
147// SOONG_CONFIG_acme_feature := false
148//
149// Then libacme_foo would build with cflags:
150// "-DGENERIC -DSOC_DEFAULT -DFEATURE_DEFAULT -DSIZE=DEFAULT".
151//
152// Similarly, if acme BoardConfig.mk file contained:
153//
154// SOONG_CONFIG_NAMESPACES += acme
155// SOONG_CONFIG_acme += \
156// board \
157// feature \
158//
159// SOONG_CONFIG_acme_board := soc_c
160//
161// Then libacme_foo would build with cflags:
162// "-DGENERIC -DSOC_DEFAULT -DFEATURE_DEFAULT -DSIZE=DEFAULT".
163
Jingwen Chena47f28d2021-11-02 16:43:57 +0000164func SoongConfigModuleTypeImportFactory() Module {
Colin Cross9d34f352019-11-22 16:03:51 -0800165 module := &soongConfigModuleTypeImport{}
166
167 module.AddProperties(&module.properties)
168 AddLoadHook(module, func(ctx LoadHookContext) {
169 importModuleTypes(ctx, module.properties.From, module.properties.Module_types...)
170 })
171
172 initAndroidModuleBase(module)
173 return module
174}
175
176func (m *soongConfigModuleTypeImport) Name() string {
Sasha Smundak116ec922020-03-10 16:10:06 -0700177 // The generated name is non-deterministic, but it does not
178 // matter because this module does not emit any rules.
179 return soongconfig.CanonicalizeToProperty(m.properties.From) +
180 "soong_config_module_type_import_" + fmt.Sprintf("%p", m)
Colin Cross9d34f352019-11-22 16:03:51 -0800181}
182
Colin Crossa6389e92022-06-22 16:44:07 -0700183func (*soongConfigModuleTypeImport) Namespaceless() {}
Colin Cross9d34f352019-11-22 16:03:51 -0800184func (*soongConfigModuleTypeImport) GenerateAndroidBuildActions(ModuleContext) {}
185
186// Create dummy modules for soong_config_module_type and soong_config_*_variable
187
188type soongConfigModuleTypeModule struct {
189 ModuleBase
Jingwen Chena47f28d2021-11-02 16:43:57 +0000190 BazelModuleBase
Colin Cross9d34f352019-11-22 16:03:51 -0800191 properties soongconfig.ModuleTypeProperties
192}
193
194// soong_config_module_type defines module types with conditionals on Soong config
Bill Peckhamc93258b2020-02-04 13:17:24 -0800195// variables. The new module type will exist for all modules after the definition
196// in an Android.bp file, and can be imported into other Android.bp files using
197// soong_config_module_type_import.
Colin Cross9d34f352019-11-22 16:03:51 -0800198//
Liz Kammer432bd592020-12-16 12:42:02 -0800199// Each soong_config_variable supports an additional value `conditions_default`. The properties
200// specified in `conditions_default` will only be used under the following conditions:
Colin Crossd079e0b2022-08-16 10:27:33 -0700201//
202// bool variable: the variable is unspecified or not set to a true value
203// value variable: the variable is unspecified
204// string variable: the variable is unspecified or the variable is set to a string unused in the
205// given module. For example, string variable `test` takes values: "a" and "b",
206// if the module contains a property `a` and `conditions_default`, when test=b,
207// the properties under `conditions_default` will be used. To specify that no
208// properties should be amended for `b`, you can set `b: {},`.
Liz Kammer432bd592020-12-16 12:42:02 -0800209//
Colin Cross9d34f352019-11-22 16:03:51 -0800210// For example, an Android.bp file could have:
211//
Colin Crossd079e0b2022-08-16 10:27:33 -0700212// soong_config_module_type {
213// name: "acme_cc_defaults",
214// module_type: "cc_defaults",
215// config_namespace: "acme",
216// variables: ["board"],
217// bool_variables: ["feature"],
218// value_variables: ["width"],
219// properties: ["cflags", "srcs"],
220// }
Colin Cross9d34f352019-11-22 16:03:51 -0800221//
Colin Crossd079e0b2022-08-16 10:27:33 -0700222// soong_config_string_variable {
223// name: "board",
224// values: ["soc_a", "soc_b"],
225// }
Colin Cross9d34f352019-11-22 16:03:51 -0800226//
Colin Crossd079e0b2022-08-16 10:27:33 -0700227// acme_cc_defaults {
228// name: "acme_defaults",
229// cflags: ["-DGENERIC"],
230// soong_config_variables: {
231// board: {
232// soc_a: {
233// cflags: ["-DSOC_A"],
234// },
235// soc_b: {
236// cflags: ["-DSOC_B"],
237// },
238// conditions_default: {
239// cflags: ["-DSOC_DEFAULT"],
240// },
241// },
242// feature: {
243// cflags: ["-DFEATURE"],
244// conditions_default: {
245// cflags: ["-DFEATURE_DEFAULT"],
246// },
247// },
248// width: {
249// cflags: ["-DWIDTH=%s"],
250// conditions_default: {
251// cflags: ["-DWIDTH=DEFAULT"],
252// },
253// },
254// },
255// }
Colin Cross9d34f352019-11-22 16:03:51 -0800256//
Colin Crossd079e0b2022-08-16 10:27:33 -0700257// cc_library {
258// name: "libacme_foo",
259// defaults: ["acme_defaults"],
260// srcs: ["*.cpp"],
261// }
Colin Cross9d34f352019-11-22 16:03:51 -0800262//
Colin Cross9d34f352019-11-22 16:03:51 -0800263// If an acme BoardConfig.mk file contained:
264//
Colin Crossd079e0b2022-08-16 10:27:33 -0700265// SOONG_CONFIG_NAMESPACES += acme
266// SOONG_CONFIG_acme += \
267// board \
268// feature \
Colin Cross9d34f352019-11-22 16:03:51 -0800269//
Colin Crossd079e0b2022-08-16 10:27:33 -0700270// SOONG_CONFIG_acme_board := soc_a
271// SOONG_CONFIG_acme_feature := true
272// SOONG_CONFIG_acme_width := 200
Colin Cross9d34f352019-11-22 16:03:51 -0800273//
274// Then libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE".
Jingwen Chena47f28d2021-11-02 16:43:57 +0000275func SoongConfigModuleTypeFactory() Module {
Colin Cross9d34f352019-11-22 16:03:51 -0800276 module := &soongConfigModuleTypeModule{}
277
278 module.AddProperties(&module.properties)
279
280 AddLoadHook(module, func(ctx LoadHookContext) {
281 // A soong_config_module_type module should implicitly import itself.
282 importModuleTypes(ctx, ctx.BlueprintsFile(), module.properties.Name)
283 })
284
285 initAndroidModuleBase(module)
286
287 return module
288}
289
290func (m *soongConfigModuleTypeModule) Name() string {
Colin Crossa6389e92022-06-22 16:44:07 -0700291 return m.properties.Name + fmt.Sprintf("%p", m)
Colin Cross9d34f352019-11-22 16:03:51 -0800292}
Colin Crossa6389e92022-06-22 16:44:07 -0700293func (*soongConfigModuleTypeModule) Namespaceless() {}
Colin Cross9d34f352019-11-22 16:03:51 -0800294func (*soongConfigModuleTypeModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
295
296type soongConfigStringVariableDummyModule struct {
297 ModuleBase
298 properties soongconfig.VariableProperties
299 stringProperties soongconfig.StringVariableProperties
300}
301
302type soongConfigBoolVariableDummyModule struct {
303 ModuleBase
304 properties soongconfig.VariableProperties
305}
306
307// soong_config_string_variable defines a variable and a set of possible string values for use
308// in a soong_config_module_type definition.
Jingwen Chena47f28d2021-11-02 16:43:57 +0000309func SoongConfigStringVariableDummyFactory() Module {
Colin Cross9d34f352019-11-22 16:03:51 -0800310 module := &soongConfigStringVariableDummyModule{}
311 module.AddProperties(&module.properties, &module.stringProperties)
312 initAndroidModuleBase(module)
313 return module
314}
315
316// soong_config_string_variable defines a variable with true or false values for use
317// in a soong_config_module_type definition.
Jingwen Chena47f28d2021-11-02 16:43:57 +0000318func SoongConfigBoolVariableDummyFactory() Module {
Colin Cross9d34f352019-11-22 16:03:51 -0800319 module := &soongConfigBoolVariableDummyModule{}
320 module.AddProperties(&module.properties)
321 initAndroidModuleBase(module)
322 return module
323}
324
325func (m *soongConfigStringVariableDummyModule) Name() string {
Colin Crossa6389e92022-06-22 16:44:07 -0700326 return m.properties.Name + fmt.Sprintf("%p", m)
Colin Cross9d34f352019-11-22 16:03:51 -0800327}
Colin Crossa6389e92022-06-22 16:44:07 -0700328func (*soongConfigStringVariableDummyModule) Namespaceless() {}
Colin Cross9d34f352019-11-22 16:03:51 -0800329func (*soongConfigStringVariableDummyModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
330
331func (m *soongConfigBoolVariableDummyModule) Name() string {
Colin Crossa6389e92022-06-22 16:44:07 -0700332 return m.properties.Name + fmt.Sprintf("%p", m)
Colin Cross9d34f352019-11-22 16:03:51 -0800333}
Colin Crossa6389e92022-06-22 16:44:07 -0700334func (*soongConfigBoolVariableDummyModule) Namespaceless() {}
Colin Cross9d34f352019-11-22 16:03:51 -0800335func (*soongConfigBoolVariableDummyModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
336
Jingwen Chena47f28d2021-11-02 16:43:57 +0000337// importModuleTypes registers the module factories for a list of module types defined
338// in an Android.bp file. These module factories are scoped for the current Android.bp
339// file only.
Colin Cross9d34f352019-11-22 16:03:51 -0800340func importModuleTypes(ctx LoadHookContext, from string, moduleTypes ...string) {
341 from = filepath.Clean(from)
342 if filepath.Ext(from) != ".bp" {
343 ctx.PropertyErrorf("from", "%q must be a file with extension .bp", from)
344 return
345 }
346
347 if strings.HasPrefix(from, "../") {
348 ctx.PropertyErrorf("from", "%q must not use ../ to escape the source tree",
349 from)
350 return
351 }
352
353 moduleTypeDefinitions := loadSoongConfigModuleTypeDefinition(ctx, from)
354 if moduleTypeDefinitions == nil {
355 return
356 }
357 for _, moduleType := range moduleTypes {
358 if factory, ok := moduleTypeDefinitions[moduleType]; ok {
359 ctx.registerScopedModuleType(moduleType, factory)
360 } else {
361 ctx.PropertyErrorf("module_types", "module type %q not defined in %q",
362 moduleType, from)
363 }
364 }
365}
366
367// loadSoongConfigModuleTypeDefinition loads module types from an Android.bp file. It caches the
368// result so each file is only parsed once.
369func loadSoongConfigModuleTypeDefinition(ctx LoadHookContext, from string) map[string]blueprint.ModuleFactory {
370 type onceKeyType string
371 key := NewCustomOnceKey(onceKeyType(filepath.Clean(from)))
372
373 reportErrors := func(ctx LoadHookContext, filename string, errs ...error) {
374 for _, err := range errs {
375 if parseErr, ok := err.(*parser.ParseError); ok {
376 ctx.Errorf(parseErr.Pos, "%s", parseErr.Err)
377 } else {
378 ctx.Errorf(scanner.Position{Filename: filename}, "%s", err)
379 }
380 }
381 }
382
383 return ctx.Config().Once(key, func() interface{} {
Colin Cross39e545c2020-02-05 16:26:19 -0800384 ctx.AddNinjaFileDeps(from)
Colin Cross9d34f352019-11-22 16:03:51 -0800385 r, err := ctx.Config().fs.Open(from)
386 if err != nil {
387 ctx.PropertyErrorf("from", "failed to open %q: %s", from, err)
388 return (map[string]blueprint.ModuleFactory)(nil)
389 }
Liz Kammer0fe123d2022-02-07 10:17:35 -0500390 defer r.Close()
Colin Cross9d34f352019-11-22 16:03:51 -0800391
392 mtDef, errs := soongconfig.Parse(r, from)
Colin Cross9d34f352019-11-22 16:03:51 -0800393 if len(errs) > 0 {
394 reportErrors(ctx, from, errs...)
395 return (map[string]blueprint.ModuleFactory)(nil)
396 }
397
Liz Kammer44bc9a32022-12-21 14:43:46 -0500398 if ctx.Config().BuildMode == Bp2build {
Liz Kammer8103dc42023-03-06 09:02:38 -0500399 ctx.Config().Bp2buildSoongConfigDefinitions.AddVars(mtDef)
Liz Kammer44bc9a32022-12-21 14:43:46 -0500400 }
401
Colin Cross9d34f352019-11-22 16:03:51 -0800402 globalModuleTypes := ctx.moduleFactories()
403
404 factories := make(map[string]blueprint.ModuleFactory)
405
406 for name, moduleType := range mtDef.ModuleTypes {
407 factory := globalModuleTypes[moduleType.BaseModuleType]
408 if factory != nil {
Chris Parsonsad876012022-08-20 14:48:32 -0400409 factories[name] = configModuleFactory(factory, moduleType, ctx.Config().BuildMode == Bp2build)
Colin Cross9d34f352019-11-22 16:03:51 -0800410 } else {
411 reportErrors(ctx, from,
412 fmt.Errorf("missing global module type factory for %q", moduleType.BaseModuleType))
413 }
414 }
415
416 if ctx.Failed() {
417 return (map[string]blueprint.ModuleFactory)(nil)
418 }
419
420 return factories
421 }).(map[string]blueprint.ModuleFactory)
422}
423
Jingwen Chena47f28d2021-11-02 16:43:57 +0000424// configModuleFactory takes an existing soongConfigModuleFactory and a
425// ModuleType to create a new ModuleFactory that uses a custom loadhook.
426func configModuleFactory(factory blueprint.ModuleFactory, moduleType *soongconfig.ModuleType, bp2build bool) blueprint.ModuleFactory {
Paul Duffine8b47682023-01-09 15:42:57 +0000427 // Defer creation of conditional properties struct until the first call from the factory
428 // method. That avoids having to make a special call to the factory to create the properties
429 // structs from which the conditional properties struct is created. This is needed in order to
430 // allow singleton modules to be customized by soong_config_module_type as the
431 // SingletonModuleFactoryAdaptor factory registers a load hook for the singleton module
432 // everytime that it is called. Calling the factory twice causes a build failure as the load
433 // hook is called twice, the first time it updates the singleton module to indicate that it has
434 // been registered as a module, and the second time it fails because it thinks it has been
435 // registered again and a singleton module can only be registered once.
436 //
437 // This is an issue for singleton modules because:
438 // * Load hooks are registered on the module object and are only called when the module object
439 // is created by Blueprint while processing the Android.bp file.
440 // * The module factory for a singleton module returns the same module object each time it is
441 // called, and registers its load hook on that same module object.
442 // * When the module factory is called by Blueprint it then calls all the load hooks that have
443 // been registered for every call to that module factory.
444 //
445 // It is not an issue for normal modules because they return a new module object each time the
446 // factory is called and so any load hooks registered on module objects which are discarded will
447 // not be run.
448 once := &sync.Once{}
449 conditionalFactoryProps := reflect.Value{}
450 getConditionalFactoryProps := func(props []interface{}) reflect.Value {
451 once.Do(func() {
452 conditionalFactoryProps = soongconfig.CreateProperties(props, moduleType)
453 })
454 return conditionalFactoryProps
Jingwen Chena47f28d2021-11-02 16:43:57 +0000455 }
Colin Cross9d34f352019-11-22 16:03:51 -0800456
Jingwen Chena47f28d2021-11-02 16:43:57 +0000457 return func() (blueprint.Module, []interface{}) {
458 module, props := factory()
Paul Duffine8b47682023-01-09 15:42:57 +0000459 conditionalFactoryProps := getConditionalFactoryProps(props)
460 if !conditionalFactoryProps.IsValid() {
461 return module, props
462 }
463
Jingwen Chena47f28d2021-11-02 16:43:57 +0000464 conditionalProps := proptools.CloneEmptyProperties(conditionalFactoryProps)
465 props = append(props, conditionalProps.Interface())
Colin Cross9d34f352019-11-22 16:03:51 -0800466
Jingwen Chen01812022021-11-19 14:29:43 +0000467 if bp2build {
Jingwen Chena47f28d2021-11-02 16:43:57 +0000468 // The loadhook is different for bp2build, since we don't want to set a specific
469 // set of property values based on a vendor var -- we want __all of them__ to
470 // generate select statements, so we put the entire soong_config_variables
471 // struct, together with the namespace representing those variables, while
472 // creating the custom module with the factory.
473 AddLoadHook(module, func(ctx LoadHookContext) {
474 if m, ok := module.(Bazelable); ok {
475 m.SetBaseModuleType(moduleType.BaseModuleType)
476 // Instead of applying all properties, keep the entire conditionalProps struct as
477 // part of the custom module so dependent modules can create the selects accordingly
478 m.setNamespacedVariableProps(namespacedVariableProperties{
Jingwen Chen84817de2021-11-17 10:57:35 +0000479 moduleType.ConfigNamespace: []interface{}{conditionalProps.Interface()},
Jingwen Chena47f28d2021-11-02 16:43:57 +0000480 })
481 }
482 })
483 } else {
484 // Regular Soong operation wraps the existing module factory with a
485 // conditional on Soong config variables by reading the product
486 // config variables from Make.
Colin Cross9d34f352019-11-22 16:03:51 -0800487 AddLoadHook(module, func(ctx LoadHookContext) {
488 config := ctx.Config().VendorConfig(moduleType.ConfigNamespace)
Dan Willemsenb0935db2020-03-23 19:42:18 -0700489 newProps, err := soongconfig.PropertiesToApply(moduleType, conditionalProps, config)
490 if err != nil {
491 ctx.ModuleErrorf("%s", err)
492 return
493 }
494 for _, ps := range newProps {
Colin Cross9d34f352019-11-22 16:03:51 -0800495 ctx.AppendProperties(ps)
496 }
497 })
Colin Cross9d34f352019-11-22 16:03:51 -0800498 }
Jingwen Chena47f28d2021-11-02 16:43:57 +0000499 return module, props
Colin Cross9d34f352019-11-22 16:03:51 -0800500 }
501}