Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b7ec426e authored by Colin Cross's avatar Colin Cross Committed by Gerrit Code Review
Browse files

Merge "Simplify vendor conditionals"

parents 699cf17f 9d34f358
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ bootstrap_go_package {
        "blueprint",
        "blueprint-bootstrap",
        "soong",
        "soong-android-soongconfig",
        "soong-env",
        "soong-shared",
    ],
@@ -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",
@@ -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",
@@ -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",
+103 −25
Original line number Diff line number Diff line
@@ -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.
@@ -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:
+4 −30
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -128,8 +118,6 @@ type deviceConfig struct {
	OncePer
}

type vendorConfig map[string]string

type jsonConfigurable interface {
	SetDefaultConfig()
}
@@ -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 {
+11 −0
Original line number Diff line number Diff line
@@ -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)) {
@@ -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,
@@ -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
+6 −1
Original line number Diff line number Diff line
@@ -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{})
@@ -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