Loading Android.bp +17 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ bootstrap_go_package { "blueprint", "blueprint-bootstrap", "soong", "soong-android-soongconfig", "soong-env", "soong-shared", ], Loading Loading @@ -73,6 +74,7 @@ bootstrap_go_package { "android/sdk.go", "android/sh_binary.go", "android/singleton.go", "android/soong_config_modules.go", "android/testing.go", "android/util.go", "android/variable.go", Loading Loading @@ -101,6 +103,7 @@ bootstrap_go_package { "android/prebuilt_test.go", "android/prebuilt_etc_test.go", "android/rule_builder_test.go", "android/soong_config_modules_test.go", "android/util_test.go", "android/variable_test.go", "android/visibility_test.go", Loading @@ -108,6 +111,20 @@ bootstrap_go_package { ], } bootstrap_go_package { name: "soong-android-soongconfig", pkgPath: "android/soong/android/soongconfig", deps: [ "blueprint", "blueprint-parser", "blueprint-proptools", ], srcs: [ "android/soongconfig/config.go", "android/soongconfig/modules.go", ], } bootstrap_go_package { name: "soong-cc-config", pkgPath: "android/soong/cc/config", Loading README.md +103 −25 Original line number Diff line number Diff line Loading @@ -376,36 +376,14 @@ The androidmk converter will produce multiple conflicting modules, which must be resolved by hand to a single module with any differences inside `target: { android: { }, host: { } }` blocks. ## Build logic The build logic is written in Go using the [blueprint](http://godoc.org/github.com/google/blueprint) framework. Build logic receives module definitions parsed into Go structures using reflection and produces build rules. The build rules are collected by blueprint and written to a [ninja](http://ninja-build.org) build file. ## Other documentation * [Best Practices](docs/best_practices.md) * [Build Performance](docs/perf.md) * [Generating CLion Projects](docs/clion.md) * [Generating YouCompleteMe/VSCode compile\_commands.json file](docs/compdb.md) * Make-specific documentation: [build/make/README.md](https://android.googlesource.com/platform/build/+/master/README.md) ## FAQ ### How do I write conditionals? ### Conditionals Soong deliberately does not support conditionals in Android.bp files. We Soong deliberately does not support most conditionals in Android.bp files. We suggest removing most conditionals from the build. See [Best Practices](docs/best_practices.md#removing-conditionals) for some examples on how to remove conditionals. In cases where build time conditionals are unavoidable, complexity in build rules that would require conditionals are handled in Go through Soong plugins. This allows Go language features to be used for better readability and testability, and implicit dependencies introduced by conditionals can be tracked. Most conditionals supported natively by Soong are converted to a map Most conditionals supported natively by Soong are converted to a map property. When building the module one of the properties in the map will be selected, and its values appended to the property with the same name at the top level of the module. Loading @@ -430,6 +408,106 @@ When building the module for arm the `generic.cpp` and `arm.cpp` sources will be built. When building for x86 the `generic.cpp` and 'x86.cpp' sources will be built. #### Soong Config Variables When converting vendor modules that contain conditionals, simple conditionals can be supported through Soong config variables using `soong_config_*` modules that describe the module types, variables and possible values: ``` soong_config_module_type { name: "acme_cc_defaults", module_type: "cc_defaults", config_namespace: "acme", variables: ["board", "feature"], properties: ["cflags", "srcs"], } soong_config_string_variable { name: "board", values: ["soc_a", "soc_b"], } soong_config_bool_variable { name: "feature", } ``` This example describes a new `acme_cc_defaults` module type that extends the `cc_defaults` module type, with two additional conditionals based on variables `board` and `feature`, which can affect properties `cflags` and `srcs`. The values of the variables can be set from a product's `BoardConfig.mk` file: ``` SOONG_CONFIG_NAMESPACES += acme SOONG_CONFIG_acme += \ board \ feature \ SOONG_CONFIG_acme_board := soc_a SOONG_CONFIG_acme_feature := true ``` The `acme_cc_defaults` module type can be used anywhere after the definition in the file where it is defined, or can be imported into another file with: ``` soong_config_module_type_import { from: "device/acme/Android.bp", module_types: ["acme_cc_defaults"], } ``` It can used like any other module type: ``` acme_cc_defaults { name: "acme_defaults", cflags: ["-DGENERIC"], soong_config_variables: { board: { soc_a: { cflags: ["-DSOC_A"], }, soc_b: { cflags: ["-DSOC_B"], }, }, feature: { cflags: ["-DFEATURE"], }, }, } cc_library { name: "libacme_foo", defaults: ["acme_defaults"], srcs: ["*.cpp"], } ``` With the `BoardConfig.mk` snippet above, libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE". `soong_config_module_type` modules will work best when used to wrap defaults modules (`cc_defaults`, `java_defaults`, etc.), which can then be referenced by all of the vendor's other modules using the normal namespace and visibility rules. ## Build logic The build logic is written in Go using the [blueprint](http://godoc.org/github.com/google/blueprint) framework. Build logic receives module definitions parsed into Go structures using reflection and produces build rules. The build rules are collected by blueprint and written to a [ninja](http://ninja-build.org) build file. ## Other documentation * [Best Practices](docs/best_practices.md) * [Build Performance](docs/perf.md) * [Generating CLion Projects](docs/clion.md) * [Generating YouCompleteMe/VSCode compile\_commands.json file](docs/compdb.md) * Make-specific documentation: [build/make/README.md](https://android.googlesource.com/platform/build/+/master/README.md) ## Developing for Soong To load Soong code in a Go-aware IDE, create a directory outside your android tree and then: Loading android/config.go +4 −30 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ import ( "github.com/google/blueprint/bootstrap" "github.com/google/blueprint/pathtools" "github.com/google/blueprint/proptools" "android/soong/android/soongconfig" ) var Bool = proptools.Bool Loading Loading @@ -66,19 +68,7 @@ type DeviceConfig struct { *deviceConfig } type VendorConfig interface { // Bool interprets the variable named `name` as a boolean, returning true if, after // lowercasing, it matches one of "1", "y", "yes", "on", or "true". Unset, or any other // value will return false. Bool(name string) bool // String returns the string value of `name`. If the variable was not set, it will // return the empty string. String(name string) string // IsSet returns whether the variable `name` was set by Make. IsSet(name string) bool } type VendorConfig soongconfig.SoongConfig type config struct { FileConfigurableOptions Loading Loading @@ -128,8 +118,6 @@ type deviceConfig struct { OncePer } type vendorConfig map[string]string type jsonConfigurable interface { SetDefaultConfig() } Loading Loading @@ -1141,21 +1129,7 @@ func (c *config) XOMDisabledForPath(path string) bool { } func (c *config) VendorConfig(name string) VendorConfig { return vendorConfig(c.productVariables.VendorVars[name]) } func (c vendorConfig) Bool(name string) bool { v := strings.ToLower(c[name]) return v == "1" || v == "y" || v == "yes" || v == "on" || v == "true" } func (c vendorConfig) String(name string) string { return c[name] } func (c vendorConfig) IsSet(name string) bool { _, ok := c[name] return ok return soongconfig.Config(c.productVariables.VendorVars[name]) } func (c *config) NdkAbis() bool { Loading android/hooks.go +11 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,9 @@ type LoadHookContext interface { AppendProperties(...interface{}) PrependProperties(...interface{}) CreateModule(ModuleFactory, ...interface{}) Module registerScopedModuleType(name string, factory blueprint.ModuleFactory) moduleFactories() map[string]blueprint.ModuleFactory } func AddLoadHook(m blueprint.Module, hook func(LoadHookContext)) { Loading @@ -52,6 +55,10 @@ type loadHookContext struct { module Module } func (l *loadHookContext) moduleFactories() map[string]blueprint.ModuleFactory { return l.bp.ModuleFactories() } func (l *loadHookContext) AppendProperties(props ...interface{}) { for _, p := range props { err := proptools.AppendMatchingProperties(l.Module().base().customizableProperties, Loading Loading @@ -101,6 +108,10 @@ func (l *loadHookContext) CreateModule(factory ModuleFactory, props ...interface return module } func (l *loadHookContext) registerScopedModuleType(name string, factory blueprint.ModuleFactory) { l.bp.RegisterScopedModuleType(name, factory) } type InstallHookContext interface { ModuleContext Path() InstallPath Loading android/module.go +6 −1 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ type EarlyModuleContext interface { ModuleName() string ModuleDir() string ModuleType() string BlueprintsFile() string ContainsProperty(name string) bool Errorf(pos scanner.Position, fmt string, args ...interface{}) Loading Loading @@ -524,9 +525,13 @@ func (k moduleKind) String() string { } } func initAndroidModuleBase(m Module) { m.base().module = m } func InitAndroidModule(m Module) { initAndroidModuleBase(m) base := m.base() base.module = m m.AddProperties( &base.nameProperties, Loading Loading
Android.bp +17 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ bootstrap_go_package { "blueprint", "blueprint-bootstrap", "soong", "soong-android-soongconfig", "soong-env", "soong-shared", ], Loading Loading @@ -73,6 +74,7 @@ bootstrap_go_package { "android/sdk.go", "android/sh_binary.go", "android/singleton.go", "android/soong_config_modules.go", "android/testing.go", "android/util.go", "android/variable.go", Loading Loading @@ -101,6 +103,7 @@ bootstrap_go_package { "android/prebuilt_test.go", "android/prebuilt_etc_test.go", "android/rule_builder_test.go", "android/soong_config_modules_test.go", "android/util_test.go", "android/variable_test.go", "android/visibility_test.go", Loading @@ -108,6 +111,20 @@ bootstrap_go_package { ], } bootstrap_go_package { name: "soong-android-soongconfig", pkgPath: "android/soong/android/soongconfig", deps: [ "blueprint", "blueprint-parser", "blueprint-proptools", ], srcs: [ "android/soongconfig/config.go", "android/soongconfig/modules.go", ], } bootstrap_go_package { name: "soong-cc-config", pkgPath: "android/soong/cc/config", Loading
README.md +103 −25 Original line number Diff line number Diff line Loading @@ -376,36 +376,14 @@ The androidmk converter will produce multiple conflicting modules, which must be resolved by hand to a single module with any differences inside `target: { android: { }, host: { } }` blocks. ## Build logic The build logic is written in Go using the [blueprint](http://godoc.org/github.com/google/blueprint) framework. Build logic receives module definitions parsed into Go structures using reflection and produces build rules. The build rules are collected by blueprint and written to a [ninja](http://ninja-build.org) build file. ## Other documentation * [Best Practices](docs/best_practices.md) * [Build Performance](docs/perf.md) * [Generating CLion Projects](docs/clion.md) * [Generating YouCompleteMe/VSCode compile\_commands.json file](docs/compdb.md) * Make-specific documentation: [build/make/README.md](https://android.googlesource.com/platform/build/+/master/README.md) ## FAQ ### How do I write conditionals? ### Conditionals Soong deliberately does not support conditionals in Android.bp files. We Soong deliberately does not support most conditionals in Android.bp files. We suggest removing most conditionals from the build. See [Best Practices](docs/best_practices.md#removing-conditionals) for some examples on how to remove conditionals. In cases where build time conditionals are unavoidable, complexity in build rules that would require conditionals are handled in Go through Soong plugins. This allows Go language features to be used for better readability and testability, and implicit dependencies introduced by conditionals can be tracked. Most conditionals supported natively by Soong are converted to a map Most conditionals supported natively by Soong are converted to a map property. When building the module one of the properties in the map will be selected, and its values appended to the property with the same name at the top level of the module. Loading @@ -430,6 +408,106 @@ When building the module for arm the `generic.cpp` and `arm.cpp` sources will be built. When building for x86 the `generic.cpp` and 'x86.cpp' sources will be built. #### Soong Config Variables When converting vendor modules that contain conditionals, simple conditionals can be supported through Soong config variables using `soong_config_*` modules that describe the module types, variables and possible values: ``` soong_config_module_type { name: "acme_cc_defaults", module_type: "cc_defaults", config_namespace: "acme", variables: ["board", "feature"], properties: ["cflags", "srcs"], } soong_config_string_variable { name: "board", values: ["soc_a", "soc_b"], } soong_config_bool_variable { name: "feature", } ``` This example describes a new `acme_cc_defaults` module type that extends the `cc_defaults` module type, with two additional conditionals based on variables `board` and `feature`, which can affect properties `cflags` and `srcs`. The values of the variables can be set from a product's `BoardConfig.mk` file: ``` SOONG_CONFIG_NAMESPACES += acme SOONG_CONFIG_acme += \ board \ feature \ SOONG_CONFIG_acme_board := soc_a SOONG_CONFIG_acme_feature := true ``` The `acme_cc_defaults` module type can be used anywhere after the definition in the file where it is defined, or can be imported into another file with: ``` soong_config_module_type_import { from: "device/acme/Android.bp", module_types: ["acme_cc_defaults"], } ``` It can used like any other module type: ``` acme_cc_defaults { name: "acme_defaults", cflags: ["-DGENERIC"], soong_config_variables: { board: { soc_a: { cflags: ["-DSOC_A"], }, soc_b: { cflags: ["-DSOC_B"], }, }, feature: { cflags: ["-DFEATURE"], }, }, } cc_library { name: "libacme_foo", defaults: ["acme_defaults"], srcs: ["*.cpp"], } ``` With the `BoardConfig.mk` snippet above, libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE". `soong_config_module_type` modules will work best when used to wrap defaults modules (`cc_defaults`, `java_defaults`, etc.), which can then be referenced by all of the vendor's other modules using the normal namespace and visibility rules. ## Build logic The build logic is written in Go using the [blueprint](http://godoc.org/github.com/google/blueprint) framework. Build logic receives module definitions parsed into Go structures using reflection and produces build rules. The build rules are collected by blueprint and written to a [ninja](http://ninja-build.org) build file. ## Other documentation * [Best Practices](docs/best_practices.md) * [Build Performance](docs/perf.md) * [Generating CLion Projects](docs/clion.md) * [Generating YouCompleteMe/VSCode compile\_commands.json file](docs/compdb.md) * Make-specific documentation: [build/make/README.md](https://android.googlesource.com/platform/build/+/master/README.md) ## Developing for Soong To load Soong code in a Go-aware IDE, create a directory outside your android tree and then: Loading
android/config.go +4 −30 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ import ( "github.com/google/blueprint/bootstrap" "github.com/google/blueprint/pathtools" "github.com/google/blueprint/proptools" "android/soong/android/soongconfig" ) var Bool = proptools.Bool Loading Loading @@ -66,19 +68,7 @@ type DeviceConfig struct { *deviceConfig } type VendorConfig interface { // Bool interprets the variable named `name` as a boolean, returning true if, after // lowercasing, it matches one of "1", "y", "yes", "on", or "true". Unset, or any other // value will return false. Bool(name string) bool // String returns the string value of `name`. If the variable was not set, it will // return the empty string. String(name string) string // IsSet returns whether the variable `name` was set by Make. IsSet(name string) bool } type VendorConfig soongconfig.SoongConfig type config struct { FileConfigurableOptions Loading Loading @@ -128,8 +118,6 @@ type deviceConfig struct { OncePer } type vendorConfig map[string]string type jsonConfigurable interface { SetDefaultConfig() } Loading Loading @@ -1141,21 +1129,7 @@ func (c *config) XOMDisabledForPath(path string) bool { } func (c *config) VendorConfig(name string) VendorConfig { return vendorConfig(c.productVariables.VendorVars[name]) } func (c vendorConfig) Bool(name string) bool { v := strings.ToLower(c[name]) return v == "1" || v == "y" || v == "yes" || v == "on" || v == "true" } func (c vendorConfig) String(name string) string { return c[name] } func (c vendorConfig) IsSet(name string) bool { _, ok := c[name] return ok return soongconfig.Config(c.productVariables.VendorVars[name]) } func (c *config) NdkAbis() bool { Loading
android/hooks.go +11 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,9 @@ type LoadHookContext interface { AppendProperties(...interface{}) PrependProperties(...interface{}) CreateModule(ModuleFactory, ...interface{}) Module registerScopedModuleType(name string, factory blueprint.ModuleFactory) moduleFactories() map[string]blueprint.ModuleFactory } func AddLoadHook(m blueprint.Module, hook func(LoadHookContext)) { Loading @@ -52,6 +55,10 @@ type loadHookContext struct { module Module } func (l *loadHookContext) moduleFactories() map[string]blueprint.ModuleFactory { return l.bp.ModuleFactories() } func (l *loadHookContext) AppendProperties(props ...interface{}) { for _, p := range props { err := proptools.AppendMatchingProperties(l.Module().base().customizableProperties, Loading Loading @@ -101,6 +108,10 @@ func (l *loadHookContext) CreateModule(factory ModuleFactory, props ...interface return module } func (l *loadHookContext) registerScopedModuleType(name string, factory blueprint.ModuleFactory) { l.bp.RegisterScopedModuleType(name, factory) } type InstallHookContext interface { ModuleContext Path() InstallPath Loading
android/module.go +6 −1 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ type EarlyModuleContext interface { ModuleName() string ModuleDir() string ModuleType() string BlueprintsFile() string ContainsProperty(name string) bool Errorf(pos scanner.Position, fmt string, args ...interface{}) Loading Loading @@ -524,9 +525,13 @@ func (k moduleKind) String() string { } } func initAndroidModuleBase(m Module) { m.base().module = m } func InitAndroidModule(m Module) { initAndroidModuleBase(m) base := m.base() base.module = m m.AddProperties( &base.nameProperties, Loading