617 lines
34 KiB
Markdown
617 lines
34 KiB
Markdown
|
# Soong-Bazel equivalents
|
|||
|
|
|||
|
This doc aims to describe *internal*-facing implementation concepts. For
|
|||
|
external-facing, see
|
|||
|
https://android.googlesource.com/platform/build/bazel/+/refs/heads/master/docs/concepts.md.
|
|||
|
|
|||
|
[TOC]
|
|||
|
|
|||
|
## Overview
|
|||
|
|
|||
|
Soong/Ninja | Bazel | Remarks
|
|||
|
--------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | -------
|
|||
|
make phony goal, e.g. "dist", "sdk", "apps_only", "droidcore" | Top level `filegroup` rule target | [Details](#phony-goal)
|
|||
|
Ninja build target (phony) | (readable) alias to a file target |
|
|||
|
Ninja build target (non-phony) | File target |
|
|||
|
`ModuleFactory` | `RuleConfiguredTargetFactory` |
|
|||
|
`Module type` (e.g. `cc_library`) | Rule class (e.g. `cc_library`) |
|
|||
|
Module object instance | Target (instance of a rule) | [Details](#instance)
|
|||
|
Module properties | [Rule attributes](https://docs.bazel.build/versions/main/skylark/rules.html#attributes) | [Details](#props)
|
|||
|
Module name | Target label |
|
|||
|
Module variant | (Split) configured target |
|
|||
|
[LoadHooks](#loadhooks) | [macros (ish)](https://docs.bazel.build/versions/main/skylark/macros.html) |
|
|||
|
Top-down mutators on modules | Split configuration on targets | Allows building multiple "variants" of the same build artifact in the same build.
|
|||
|
Bottom-up mutators on modules | [Aspects](https://docs.bazel.build/versions/main/skylark/aspects.html) on targets |
|
|||
|
[Build statement (Ninja)](#ninja-build-statement) | Action (result of ctx.actions.run) |
|
|||
|
[Rule statement (Ninja)](#ninja-rules) | [ctx.actions.run() API](https://docs.bazel.build/versions/main/skylark/lib/actions.html) |
|
|||
|
`out/soong/build.ninja` and `out/build-<target>.ninja` | Action graph (serialized) |
|
|||
|
Pool (ninja) | Thread pools / `ExecutorService` |
|
|||
|
Blueprint's Registration and Parse, `ResolveDependencies` phase | Loading phase |
|
|||
|
Blueprint's [Generate and Write phases](#blueprint-analysis) | Analysis Phase |
|
|||
|
Ninja execution | Execution phase |
|
|||
|
Blueprints/`Android.bp` files | `BUILD`/`BUILD.bazel` files |
|
|||
|
[Namespaces](#namespaces) | [Packages](#pkgs) | Most Soong modules are within the global namespace
|
|||
|
[Mutators](#mutators) | Configuration keys (ish) |
|
|||
|
[Variation](#variation) | Configuration value |
|
|||
|
[Singleton](#singleton) | Aspect-ish |
|
|||
|
Target (system + vendor + product) | [Platform](https://docs.bazel.build/versions/main/platforms.html) |
|
|||
|
Bash scripts e.g. envsetup functions, `soong_ui.bash`) | Repository rule |
|
|||
|
Product and board configuration makefile and env variables | Configuration in Bazel (ish) | [Details](#config)
|
|||
|
[Dependency Tags](#deptags) | Provider names |
|
|||
|
|
|||
|
## Remarks
|
|||
|
|
|||
|
### Phony goals {#phony-goal}
|
|||
|
|
|||
|
Soong maintains the make terminology of
|
|||
|
[goals](https://www.gnu.org/software/make/manual/html_node/Goals.html) to denote
|
|||
|
what should be built. All modules can be specified by name as a goal, in
|
|||
|
addition, phony goals are supported.
|
|||
|
|
|||
|
A Phony goal creates a Make-style phony rule, a rule with no commands that can
|
|||
|
depend on other phony rules or real files. Phony can be called on the same name
|
|||
|
multiple times to add additional dependencies. These are often used to build
|
|||
|
many targets at once. The default goal for Android's build system is `droid`.
|
|||
|
Some other common phony goals include: `nothing` (perform loading/analysis),
|
|||
|
`docs`, `checkbuild`, `apps_only`.
|
|||
|
|
|||
|
Some common phony goals are defined in
|
|||
|
[`build/make/core/main.mk`](http://cs.android.com/android/platform/superproject/+/master:build/make/core/main.mk)
|
|||
|
The purpose is to help `soong_ui` to determine what top level files to build.
|
|||
|
|
|||
|
### Module/Target {#instance}
|
|||
|
|
|||
|
When a Module is instantiated by Blueprint (which calls the appropriate
|
|||
|
`ModuleFactory`), the [property structs](#props) are populated by Blueprint.
|
|||
|
|
|||
|
Blueprint performs no additional operations on these properties, such that
|
|||
|
dependencies on other modules and references to source files are unresolved
|
|||
|
initially. [`Mutators`](#mutators) then introspect the values of properties to
|
|||
|
[specify dependencies](https://cs.android.com/android/platform/superproject/+/master:build/blueprint/module_ctx.go;l=871-886,918-960;drc=030150d8f9d164783ea661f07793c45198739cca)
|
|||
|
between modules, which
|
|||
|
[Blueprint resolves](https://cs.android.com/android/platform/superproject/+/master:build/blueprint/context.go;l=1630,1667;drc=5c4abb15e3b84ab0bcedfa119e2feb397d1fb106).
|
|||
|
Source files (including globs) and output paths for references to other modules
|
|||
|
are resolved during [blueprint analysis](#blueprint-analysis) via the various
|
|||
|
`Path[s]ForModuleSrc[Excludes]` functions within
|
|||
|
[build/soong/android/paths.go](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/paths.go).
|
|||
|
|
|||
|
For a Bazel target instance, the dependencies and source file references within
|
|||
|
[`attrs`](#attributes) have been resolved by Bazel.
|
|||
|
|
|||
|
Bazel
|
|||
|
[implementation](https://github.com/bazelbuild/bazel/blob/a20b32690a71caf712d1d241f01fef16649562ba/src/main/java/com/google/devtools/build/lib/skyframe/TransitiveBaseTraversalFunction.java#L113-L140)
|
|||
|
to collect deps.
|
|||
|
|
|||
|
### Properties/Attributes {#props}
|
|||
|
|
|||
|
#### Properties
|
|||
|
|
|||
|
Within Soong/Blueprint, properties are represented as Go structs, which can be
|
|||
|
nested, with no depth limit. Properties can be primitive or pointer types, but
|
|||
|
they must be one of these types: `int64`, `string`, `bool`, `list`.
|
|||
|
|
|||
|
These properties can be defined from various structs within the module type
|
|||
|
factory itself (via
|
|||
|
[AddProperties](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/module.go;l=1276;drc=8631cc7327919845c9d9037188cbd483d22ba077))
|
|||
|
or from common helper functions such as:
|
|||
|
|
|||
|
* `InitAndroidModule`:
|
|||
|
[specifies](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/module.go;l=1042-1045;drc=8631cc7327919845c9d9037188cbd483d22ba077)
|
|||
|
name-related, common, and dist properties.
|
|||
|
* `InitAndroidArchModule`: adds
|
|||
|
[host/device properies](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/module.go;l=1077;drc=8631cc7327919845c9d9037188cbd483d22ba077)
|
|||
|
|
|||
|
Go comments for a property will be treated as documentation to describe the
|
|||
|
property. In some cases, these comments describe a default value for the
|
|||
|
property. However, the default value is not based on the comment or field
|
|||
|
definition but resolved somewhere within the module's mutators or build. These
|
|||
|
defaults are often determined using Blueprint
|
|||
|
[`proptools`](https://cs.android.com/android/platform/superproject/+/master:build/blueprint/proptools/proptools.go)
|
|||
|
`*Default` functions. For example, `cc` modules have a property
|
|||
|
[`include_build_directory`](https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/compiler.go;l=265;drc=135bf55281d79576f33469ce4f9abc517a614af5),
|
|||
|
which is described in the comments. The default value is
|
|||
|
[resolved](https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/compiler.go;l=265;drc=135bf55281d79576f33469ce4f9abc517a614af5)
|
|||
|
when compiler flags are being determined.
|
|||
|
|
|||
|
In general, these can be set in an Android.bp file. However, if the property is
|
|||
|
tagged with `` `blueprint:"mutated"` ``, it can only be set programmatically
|
|||
|
within Blueprint/Soong. Additionally, `mutated` tagged properties also support
|
|||
|
`map` and `int` types in addition to those mentioned above. These `mutated`
|
|||
|
properties are used to propagate data that gets set during mutations, which
|
|||
|
ensures that the information is copied successfully to module variants during
|
|||
|
mutation.
|
|||
|
|
|||
|
Soong supports additional property tags to provide additional
|
|||
|
functionality/information about a property:
|
|||
|
|
|||
|
* `` `android:arch_variant` ``: This specifies that a property can be
|
|||
|
configured for different architectures, operating systems, targets, etc. The
|
|||
|
[arch mutator](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/arch.go;l=597;drc=135bf55281d79576f33469ce4f9abc517a614af5),
|
|||
|
will merge target-specific properties into the correct variant for
|
|||
|
properties with this tag.
|
|||
|
|
|||
|
Note: if a nested property is arch-variant, all recursively nesting structs
|
|||
|
that can be specified in an Android.bp file must also be tagged as
|
|||
|
arch-variant.
|
|||
|
|
|||
|
* `` `android:variant_prepend` ``: When merging properties for the arch
|
|||
|
variant, the arch-specific values should be *prepended* rather than appended
|
|||
|
to existing property values.
|
|||
|
|
|||
|
* `` `android:path` ``: This specifies that this property will contain some
|
|||
|
combination of:
|
|||
|
|
|||
|
* module-relative paths
|
|||
|
* references to other modules in the form:
|
|||
|
* `":<name>{.<tag>}"`, where `{.<tag>}` is optional to specify a
|
|||
|
non-default output file, specific to the module type
|
|||
|
* `"<namespace>:<name>{.<tag>}""`
|
|||
|
|
|||
|
Note: Dependencies to other modules for these properties will be
|
|||
|
automatically added by the
|
|||
|
[pathdeps mutator](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/path_properties.go;l=40;drc=40131a3f9e5ac974a44d3bd1293d31d585dc3a07).
|
|||
|
|
|||
|
#### Attributes
|
|||
|
|
|||
|
Similar to properties,
|
|||
|
[attributes](https://docs.bazel.build/versions/main/skylark/lib/attr.html) only
|
|||
|
support a few types. The difference is that Bazel attributes cannot be nested .
|
|||
|
|
|||
|
Some attributes are
|
|||
|
[common](https://docs.bazel.build/versions/2.1.0/be/common-definitions.html#common-attributes)
|
|||
|
across many/all rule classes, including (but not limited to) `name`, `tag`,
|
|||
|
`visibility`.
|
|||
|
|
|||
|
The definition of an attribute can contain settings, such as: its default value,
|
|||
|
whether it is mandatory ot have a value, and its documentation.
|
|||
|
|
|||
|
To specify a source file or reference to another module, use `label` or
|
|||
|
`label_list` attribute types (rather than regular `string` or `string_list`
|
|||
|
types). These support additional restrictions (as compared to `string*` types),
|
|||
|
such as:
|
|||
|
|
|||
|
* whether files are supported
|
|||
|
* the providers that must be given by a dependency
|
|||
|
* whether the dependency should be executable
|
|||
|
* the configuration (host, target)
|
|||
|
* aspects
|
|||
|
|
|||
|
Unlike Soong, when accessing this attribute within the rule's implementation (at
|
|||
|
anlysis time), the label(s) will be resolved to the file or target they refer
|
|||
|
to.
|
|||
|
|
|||
|
Attributes do not need to specify whether they accept
|
|||
|
[configurable attribute](https://docs.bazel.build/versions/main/configurable-attributes.html).
|
|||
|
However, the rule definition can specify the configuration or specify a
|
|||
|
[configuration transition](https://docs.bazel.build/versions/main/skylark/lib/transition.html).
|
|||
|
|
|||
|
However, not all target definitions within a `BUILD` file are invoking a rule.
|
|||
|
Instead, they may invoke a Starlark macro, which is a load-time wrapper around
|
|||
|
rules. Arguments for a macro are not typed. If macros are used, their arguments
|
|||
|
would have to be wrangled into an attribute-compatible type.
|
|||
|
|
|||
|
### LoadHooks
|
|||
|
|
|||
|
[LoadHooks](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/hooks.go;l=24-36;drc=07656410df1836a70bea3054e50bb410ecbf8e07)
|
|||
|
provide access to :
|
|||
|
|
|||
|
* append/prepend additional properties to the module
|
|||
|
(`AppendProperties`/`PrependProperties`)
|
|||
|
* create a new module `CreateModule`
|
|||
|
|
|||
|
`LoadHooks` make it easier to extend existing module factories to always specify
|
|||
|
certain properties or to split a single `Android.bp` definition into multiple
|
|||
|
Module instances .
|
|||
|
|
|||
|
### Build Statement (ninja) {#ninja-build-statement}
|
|||
|
|
|||
|
[Ninja build statements](https://ninja-build.org/manual.html#_build_statements) can be
|
|||
|
expanded from [Ninja rules](https://ninja-build.org/manual.html#_rules), which are like
|
|||
|
templates.
|
|||
|
|
|||
|
```
|
|||
|
# rule
|
|||
|
rule cattool
|
|||
|
depfile = out/test/depfile.d
|
|||
|
command = ${in} ${out}
|
|||
|
|
|||
|
# build statement
|
|||
|
build out/test/output.txt: cattool test/cattool.sh test/one test/two
|
|||
|
|
|||
|
# build statement
|
|||
|
build out/test/other_output.txt: cattool test/cattool.sh test/three test/four
|
|||
|
```
|
|||
|
|
|||
|
Rules for `Android.mk` modules (`out/build-<target>.ninja`) and build statements
|
|||
|
are 1:1. That is every rule is only used once by a single build statement.
|
|||
|
|
|||
|
Soong (`out/soong/build.ninja`) rules are reused extensively in build statements
|
|||
|
(1:many). For example the `Cp` rule is a commonly used rule for creating build
|
|||
|
statements which copy files.
|
|||
|
|
|||
|
### Ninja Rules in Soong {#ninja-rules}
|
|||
|
|
|||
|
In Soong, Ninja rules can be defined in two ways:
|
|||
|
|
|||
|
* [rule_builder](http://cs.android.com/android/platform/superproject/+/master:build/soong/android/rule_builder.go)
|
|||
|
* [package_ctx](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/package_ctx.go;l=102-293;drc=77cdcfdeafd383ef1f1214226c47eb20c902a28f)
|
|||
|
|
|||
|
### Blueprint Generate & Write phase {#blueprint-analysis}
|
|||
|
|
|||
|
1. [`ResolveDependencies`](https://cs.android.com/android/platform/superproject/+/master:build/blueprint/context.go;l=1547;drc=5c4abb15e3b84ab0bcedfa119e2feb397d1fb106)
|
|||
|
Running a series of Mutators, to add dependencies, split modules with
|
|||
|
variations, etc
|
|||
|
1. [`PrepareBuildActions`](https://cs.android.com/android/platform/superproject/+/master:build/blueprint/context.go;l=2367;drc=5c4abb15e3b84ab0bcedfa119e2feb397d1fb106):
|
|||
|
|
|||
|
1. Running Modules’ `GenerateBuildActions` to generate Ninja statements,
|
|||
|
which in turn calls each module's
|
|||
|
[`GenerateAndroidBuildActions`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/module.go;l=445-448;drc=8631cc7327919845c9d9037188cbd483d22ba077).
|
|||
|
1. Running Singletons to generate Ninja statements that generate docs,
|
|||
|
android.mk statements, etc
|
|||
|
|
|||
|
### Soong namespaces {#namespace}
|
|||
|
|
|||
|
Module
|
|||
|
[Namespaces](https://android.googlesource.com/platform/build/soong/+/master/README.md#namespaces)
|
|||
|
can import other namespaces, and there’s a module name lookup algorithm which
|
|||
|
terminates in the global namespace.
|
|||
|
|
|||
|
Note: this is not widely used and most Soong modules are in the global
|
|||
|
namespace.
|
|||
|
|
|||
|
### Bazel packages {#pkgs}
|
|||
|
|
|||
|
[Packages](https://docs.bazel.build/versions/main/build-ref.html#packages) can
|
|||
|
nest subpackages recursively, but they are independent containers of Bazel
|
|||
|
targets. This means that Bazel target names only need to be unique within a
|
|||
|
package.
|
|||
|
|
|||
|
### Mutators
|
|||
|
|
|||
|
blueprint invokes mutators are invoking in the order they are registered (e.g.
|
|||
|
top-down and bottom-up can be interleaved). Each mutator applys a single
|
|||
|
visitation to every module in the graph.
|
|||
|
|
|||
|
Mutators visiting module can parallelized, while maintaining their ordering, by
|
|||
|
calling `.Parallel()`.
|
|||
|
|
|||
|
While top-down and bottom-up mutators differ in their purposes, the interface
|
|||
|
available to each contains many similarities. Both have access to:
|
|||
|
[`BaseModuleContext`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/module.go;l=139;drc=8631cc7327919845c9d9037188cbd483d22ba077)
|
|||
|
and
|
|||
|
[`BaseMutatorContext`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/mutator.go;l=246;drc=2ada09a5463a0108d713773679c5ba2c35450fa4).
|
|||
|
|
|||
|
In addition to the registration order, Soong supports phase-based ordering of
|
|||
|
mutators:
|
|||
|
|
|||
|
1. Pre-Arch: mutators that need to run before arch-variation. For example,
|
|||
|
defaults are handled at this stage such properties from defaults are
|
|||
|
correctly propagated to arch-variants later.
|
|||
|
|
|||
|
1. (Hard-coded)
|
|||
|
[`archMutator`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/arch.go;l=597;drc=135bf55281d79576f33469ce4f9abc517a614af5)
|
|||
|
splits a module into the appropriate target(s). Next, the arch- and
|
|||
|
OS-specific properties are merged into the appropriate variant.
|
|||
|
|
|||
|
1. Pre-Deps: mutators that can/need to run before deps have been resolved, for
|
|||
|
instance, creating variations that have an impact on dependency resolution.
|
|||
|
|
|||
|
1. (Hard-coded)
|
|||
|
[`depsMutator`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/mutator.go;l=502;drc=2ada09a5463a0108d713773679c5ba2c35450fa4),
|
|||
|
which calls the `DepsMutator` function that *must* be part of a Soong
|
|||
|
`Module`'s interface.
|
|||
|
|
|||
|
1. Post-Deps: mutators that need to run after deps have been resolved
|
|||
|
|
|||
|
1. Final-Deps like post-deps but variations cannot be created
|
|||
|
|
|||
|
#### Top-down Mutator
|
|||
|
|
|||
|
A top-down mutator is invoked on a module before its dependencies.
|
|||
|
|
|||
|
The general purpose is to propagate dependency info from a module to its
|
|||
|
dependencies.
|
|||
|
|
|||
|
#### Bottom-up Mutator
|
|||
|
|
|||
|
A bottom-up mutator is invoked on a module only after the mutator has been
|
|||
|
invoked on all its dependencies.
|
|||
|
|
|||
|
The general purpose of a bottom-up mutator is to split modules into variants.
|
|||
|
|
|||
|
### Soong/Blueprint Variation {#variation}
|
|||
|
|
|||
|
A tuple (name of mutator, variation / config value) passed to
|
|||
|
`CreateVariations`.
|
|||
|
|
|||
|
### Configuration {#config}
|
|||
|
|
|||
|
Soong's config process encompasses both *what* should build and *how* it should
|
|||
|
build. This section focuses on the *how* aspect.
|
|||
|
|
|||
|
We do not cover how Soong's configuration will be implemented in Bazel, but the
|
|||
|
general capabilities of Bazel to configure builds.
|
|||
|
|
|||
|
#### Soong
|
|||
|
|
|||
|
Android users can configure their builds based on:
|
|||
|
|
|||
|
* Specifying a target (via lunch, banchan, tapas, or Soong’s command line
|
|||
|
options)
|
|||
|
* Environment variables
|
|||
|
|
|||
|
Some environment variables or command line options are used directly to alter
|
|||
|
the build. However, specification of target product encompasses many aspects of
|
|||
|
both *what* and *how* things are built. This configuration is currently handled
|
|||
|
within Make but is in the process of being migrated to Starlark.
|
|||
|
|
|||
|
Soong
|
|||
|
[invokes Kati](https://cs.android.com/android/platform/superproject/+/master:build/soong/ui/build/dumpvars.go;drc=7ae80a704494bbb934dced97ed97eb55a21a9a00)
|
|||
|
to run in a "config" mode, also commonly known as "product config". This mode
|
|||
|
limits the scope of what `.mk` files are parsed. The product-specific handlers
|
|||
|
are largely in:
|
|||
|
|
|||
|
* [`product_config.mk`](https://cs.android.com/android/platform/superproject/+/master:build/make/core/product_config.mk;drc=d189ab71f3505ea28324ebfaced2466af5eb0af7):
|
|||
|
this subset of functionality is also commonly referred to as "product
|
|||
|
config"
|
|||
|
* [`board_config.mk`](https://cs.android.com/android/platform/superproject/+/master:build/make/core/board_config.mk)
|
|||
|
|
|||
|
However, these cover only a subset of
|
|||
|
[`config.mk`](https://cs.android.com/android/platform/superproject/+/master:build/make/core/config.mk).
|
|||
|
This ensures that all values have appropriate defaults and specify details
|
|||
|
necessary to the build. Some examples:
|
|||
|
|
|||
|
* [handling of version defaults](https://cs.android.com/android/platform/superproject/+/master:build/make/core/version_defaults.mk)
|
|||
|
* [rbe setup](https://cs.android.com/android/platform/superproject/+/master:build/make/core/rbe.mk)
|
|||
|
* [user-defined config](https://cs.android.com/android/platform/superproject/+/master:build/make/core/config.mk;l=300-308;drc=ee20ae1a8dcdfe7b843d65099000708800d9b93a):
|
|||
|
[buildspec.mk](http://cs.android.com/android/platform/superproject/+/master:build/make/buildspec.mk.default)
|
|||
|
is similar to
|
|||
|
[`.bazelrc`](https://docs.bazel.build/versions/main/guide.html#bazelrc-the-bazel-configuration-file)
|
|||
|
file.
|
|||
|
* ensuring
|
|||
|
[`PRODUCT_SHIPPING_API_LEVEL`](https://cs.android.com/android/platform/superproject/+/master:build/make/core/config.mk;l=729-745;drc=ee20ae1a8dcdfe7b843d65099000708800d9b93a)
|
|||
|
is defaulted if not specified by the target.
|
|||
|
|
|||
|
Finally, Kati dumps variables to be consumed by Soong:
|
|||
|
|
|||
|
* environment variables specifically requested by Soong
|
|||
|
* writes
|
|||
|
[`soong.variables`](http://cs.android.com/android/platform/superproject/+/master:build/make/core/soong_config.mk),
|
|||
|
a JSON file
|
|||
|
|
|||
|
Throughout Soong, environment variables can be accessed to alter the build via
|
|||
|
the `Config`:
|
|||
|
|
|||
|
* [`GetEnv`](http://cs.android.com/search?q=f:soong%20%5C.GetEnv%5C%28%20-f:%2Fui%2F%20-f:%2Fcmd%2F&sq=)
|
|||
|
* [`GetEnvWithDefault`](http://cs.android.com/search?q=f:soong%20%5C.GetEnvWithDefault%5C%28%20-f:%2Fui%2F%20-f:%2Fcmd%2F&sq=)
|
|||
|
* [`IsEnvTrue`](http://cs.android.com/search?q=f:soong%20%5C.IsEnvTrue%5C%28%20-f:%2Fui%2F%20-f:%2Fcmd%2F&sq=)
|
|||
|
* [`IsEnvFalse`](http://cs.android.com/search?q=f:soong%20%5C.IsEnvFalse%5C%28%20-f:%2Fui%2F%20-f:%2Fcmd%2F&sq=)
|
|||
|
|
|||
|
Soong
|
|||
|
[loads the `soong.variables`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/config.go;l=174;drc=b078ade28d94c85cec78e9776eb31948a5647070)
|
|||
|
config file, stored as
|
|||
|
[`productVariables`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/variable.go;l=163;drc=16e77a9b303a71018eb6630f12f1414cd6ad615c).
|
|||
|
These variables are used in three ways:
|
|||
|
|
|||
|
* Direct access from `Config`, for example: paths can be
|
|||
|
[opted out](https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/sanitize.go;l=364,371,393;drc=582fc2d1dde6c70687e6a0bea192f2a2ef67bbd5)
|
|||
|
of specific sanitizers
|
|||
|
* In limited cases, users can use these within their `Android.bp` file to
|
|||
|
control what is built or perform variable replacement.
|
|||
|
[`variableProperties`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/variable.go;l=38;drc=16e77a9b303a71018eb6630f12f1414cd6ad615c)
|
|||
|
limits which configuration variables can be specified within an `Android.bp`
|
|||
|
file and which properties they can apply to. The values specified within an
|
|||
|
`Android.bp` file, are merged/replaced by the
|
|||
|
[`VariableMutator`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/variable.go;l=539;drc=16e77a9b303a71018eb6630f12f1414cd6ad615c),
|
|||
|
which appends performs string replacement if requested and merges the
|
|||
|
properties into the modules.
|
|||
|
* Through
|
|||
|
[Soong Config Variables](https://android.googlesource.com/platform/build/soong/+/refs/heads/master/README.md#soong-config-variables):
|
|||
|
which allow users to specify additional configuration variables that can be
|
|||
|
used within an `Android.bp` file for the module type and properties they
|
|||
|
request. Soong config variable structs are
|
|||
|
[dynamically generated](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/soongconfig/modules.go;l=257;drc=997f27aa0353dabf76d063d78ee5d4495da85651)
|
|||
|
via reflection. In the
|
|||
|
[factory](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/soong_config_modules.go;l=423;drc=18fd09998223d004a926b02938e4cb588e4cc934),
|
|||
|
the properties to merge into the module instance are
|
|||
|
[identified](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/soongconfig/modules.go;l=416;drc=997f27aa0353dabf76d063d78ee5d4495da85651)
|
|||
|
based on the config variable's type.
|
|||
|
|
|||
|
The product configuration also provides information about architecture and
|
|||
|
operating system, both for target(s) and host. This is used within the
|
|||
|
[`archMutator`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/arch.go;l=569-597;drc=135bf55281d79576f33469ce4f9abc517a614af5)
|
|||
|
to split a module into the required variants and merge target-specific
|
|||
|
properties into the appropriate variant. Only properties which have been tagged
|
|||
|
with `android:"arch_variant"` can be specified within an `Android.bp` as
|
|||
|
arch/os/target-specific. For example:
|
|||
|
|
|||
|
```go
|
|||
|
type properties struct {
|
|||
|
// this property will be arch-variant
|
|||
|
Arch_variant_not_nested *string `android:"arch_variant"`
|
|||
|
|
|||
|
Nested_with_arch_variant struct {
|
|||
|
// this property is arch-variant
|
|||
|
Arch_variant_nested *string `android:"arch_variant"`
|
|||
|
|
|||
|
// this property is **not** arch-variant
|
|||
|
Not_arch_variant_nested *string
|
|||
|
} `android:"arch_variant"`
|
|||
|
|
|||
|
Nested_no_arch_variant struct {
|
|||
|
// this property is **NOT** arch-variant
|
|||
|
No_arch_variant_nested_not_arch_variant *string `android:"arch_variant"`
|
|||
|
|
|||
|
// this property is **not** arch-variant
|
|||
|
No_arch_variant_nested *string
|
|||
|
}
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
The arch/os/target-specific structs are
|
|||
|
[dynamically generated](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/arch.go;l=780-787;drc=135bf55281d79576f33469ce4f9abc517a614af5)
|
|||
|
based on the tags using reflection.
|
|||
|
|
|||
|
#### Bazel
|
|||
|
|
|||
|
Bazel documentation covers configurable builds fairly extensively, so this is a
|
|||
|
short overview that primarily links to existing Bazel documentation rather than
|
|||
|
repeating it here.
|
|||
|
|
|||
|
[Configurable attributes](https://docs.bazel.build/versions/main/configurable-attributes.html),
|
|||
|
(aka `select()`) allows users to toggle values of build rule attributes on the
|
|||
|
command line.
|
|||
|
|
|||
|
Within a `rule`, the value of a `select` will have been resolved based on the
|
|||
|
configuration at analysis phase. However, within a macro (at loading phase,
|
|||
|
before analysis phase), a `select()` is an opaque type that cannot be inspected.
|
|||
|
This restricts what operations are possible on the arguments passed to a macro.
|
|||
|
|
|||
|
The conditions within a `select` statement are one of:
|
|||
|
|
|||
|
* [`config_setting`](https://docs.bazel.build/versions/main/be/general.html#config_setting)
|
|||
|
* [`constraint_value`](https://docs.bazel.build/versions/main/be/platform.html#constraint_value)
|
|||
|
|
|||
|
A `config_setting` is a collection of build settings, whether defined by Bazel,
|
|||
|
or user-defined.
|
|||
|
|
|||
|
User-defined
|
|||
|
[build settings](https://docs.bazel.build/versions/main/skylark/config.html#defining-build-settings)
|
|||
|
allow users to specify additional configuration, which *optionally* can be
|
|||
|
specified as a flag. In addition to specifying build settings within a
|
|||
|
`config_setting`, rules can depend directly on them.
|
|||
|
|
|||
|
In addition, Bazel supports
|
|||
|
[`platform`s](https://docs.bazel.build/versions/main/be/platform.html#platform),
|
|||
|
which is a named collection of constraints. Both a target and host platform can
|
|||
|
be specified on the command line.
|
|||
|
[More about platforms](https://docs.bazel.build/versions/main/platforms.html).
|
|||
|
|
|||
|
## Communicating between modules/targets
|
|||
|
|
|||
|
### Soong communication
|
|||
|
|
|||
|
There are many mechanisms to communicate between Soong modules. Because of this,
|
|||
|
it can be difficult to trace the information communicated between modules.
|
|||
|
|
|||
|
#### Dependency Tags {#deptags}
|
|||
|
|
|||
|
Dependency tags are the primary way to filter module dependencies by what
|
|||
|
purpose the dependency serves. For example, to filter for annotation processor
|
|||
|
plugins in the deps of a Java library module, use `ctx.VisitDirectDeps` and
|
|||
|
check the tags:
|
|||
|
|
|||
|
```
|
|||
|
ctx.VisitDirectDeps(func(module android.Module) {
|
|||
|
tag := ctx.OtherModuleDependencyTag(module)
|
|||
|
if tag == pluginTag { patchPaths += ":" + strings.Split(ctx.OtherModuleDir(module), "/")[0] }
|
|||
|
}
|
|||
|
)
|
|||
|
```
|
|||
|
|
|||
|
At this point the module managing the dependency, may have enough information to
|
|||
|
cast it to a specific type or interface and perform more specific operations.
|
|||
|
|
|||
|
For instance, shared libraries and executables have
|
|||
|
[special handling](http://cs.android.com/android/platform/superproject/+/master:build/soong/cc/cc.go;l=2771-2776;drc=5df7bd33f7b64e2b880856e3193419697a8fb693)
|
|||
|
for static library dependencies: where the coverage files and source based ABI
|
|||
|
dump files are needed explicitly. Based on the dependency tag, the module is
|
|||
|
cast to a concrete type, like `cc.Module`, where internal fields are accessed
|
|||
|
and used to obtain the desired data.
|
|||
|
|
|||
|
Usage of dependency tags can be more evident when used between module types
|
|||
|
representing different langauges, as the functions must be exported in Go due to
|
|||
|
Soong's language-based package layout. For example, rust uses `cc` module's
|
|||
|
[`HasStubVariants`](http://cs.android.com/android/platform/superproject/+/master:build/soong/rust/rust.go;l=1457-1458;drc=9f59e8db270f58a3f2e4fe5bc041f84363a5877e).
|
|||
|
|
|||
|
#### Interfaces
|
|||
|
|
|||
|
A common mechanism for a module to communicate information about itself is to
|
|||
|
define or implement a Go interface.
|
|||
|
|
|||
|
Some interfaces are common throughout Soong:
|
|||
|
|
|||
|
* [`SourceFileProducer`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/module.go;l=2967;drc=8707cd74bf083fe4a31e5f5aa5e74bd2a47e9e58),
|
|||
|
by implementing `Srcs() Paths`
|
|||
|
* [`OutputFileProducer`](http://cs.android.com/android/platform/superproject/+/master:build/soong/android/module.go;l=2974;drc=8707cd74bf083fe4a31e5f5aa5e74bd2a47e9e58)
|
|||
|
by implementing `OutputFiles(string) (Paths, error)`
|
|||
|
* [`HostToolProvider`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/module.go;l=3032;drc=8707cd74bf083fe4a31e5f5aa5e74bd2a47e9e58)
|
|||
|
by implementing `HostToolPath() OptionalPath`
|
|||
|
|
|||
|
`SourceFileProducer` and `OutputFileProducer` are used to resolve references to
|
|||
|
other modules via `android:"path"` references.
|
|||
|
|
|||
|
Modules may define additional interfaces. For example, `genrule` defines a
|
|||
|
[`SourceFileGenerator` interface](http://cs.android.com/android/platform/superproject/+/master:build/soong/genrule/genrule.go;l=98-102;drc=2ada09a5463a0108d713773679c5ba2c35450fa4).
|
|||
|
|
|||
|
#### Providers
|
|||
|
|
|||
|
Soong has Bazel-inspired providers, but providers are not used in all cases yet.
|
|||
|
|
|||
|
Usages of providers are the easiest, simplest, and cleanest communication
|
|||
|
approach in Soong.
|
|||
|
|
|||
|
In the module providing information, these are specified via
|
|||
|
[`SetProvider`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/module.go;l=212;drc=5a34ffb350fb295780e5c373fd1c78430fa4e3ed)
|
|||
|
and
|
|||
|
[`SetVariationProvider`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/mutator.go;l=719;drc=5a34ffb350fb295780e5c373fd1c78430fa4e3ed).
|
|||
|
|
|||
|
In the module retrieving information,
|
|||
|
[`HasProvider`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/module.go;l=205-206;drc=8631cc7327919845c9d9037188cbd483d22ba077)
|
|||
|
and
|
|||
|
[`Provider`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/module.go;l=198-203;drc=8631cc7327919845c9d9037188cbd483d22ba077)
|
|||
|
or
|
|||
|
[`OtherModuleHasProvider`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/module.go;l=195-196;drc=8631cc7327919845c9d9037188cbd483d22ba077)
|
|||
|
and
|
|||
|
[`OtherModuleProvider`](https://cs.android.com/android/platform/superproject/+/master:build/soong/android/module.go;l=189-193;drc=8631cc7327919845c9d9037188cbd483d22ba077)
|
|||
|
are used to test existence and retrieve a provider.
|
|||
|
|
|||
|
### Bazel communication
|
|||
|
|
|||
|
Targets primarily communicate with each other via providers in Bazel rule
|
|||
|
implementations. All rules have access to any of the providers but rules will
|
|||
|
pick and choose which ones to access based on their needs. For example, all
|
|||
|
rules can access `JavaInfo` provider, which provides information about compile
|
|||
|
and rolled-up runtime jars for javac and java invocations downstream. However,
|
|||
|
the `JavaInfo` provider is only useful to `java_*` rules or rules that need jvm
|
|||
|
information.
|
|||
|
|
|||
|
#### Starlark rules
|
|||
|
|
|||
|
[Providers](https://docs.bazel.build/versions/main/skylark/rules.html#providers)
|
|||
|
are pieces of information exposed to other modules.
|
|||
|
|
|||
|
One such provider is `DefaultInfo`, which contains the default output files and
|
|||
|
[`runfiles`](https://docs.bazel.build/versions/main/skylark/rules.html#runfiles).
|
|||
|
|
|||
|
Rule authors can also create
|
|||
|
[custom providers](https://docs.bazel.build/versions/main/skylark/lib/Provider.html#modules.Provider)
|
|||
|
or implement existing providers to communicate information specific to their
|
|||
|
rule logic. For instance, in Android Starlark
|
|||
|
[`cc_object`](http://cs/android/build/bazel/rules/cc_object.bzl?l=86-87&rcl=42607e831f8ff73c82825b663609cafb777c18e1)
|
|||
|
rule implementation, we return a
|
|||
|
[`CcInfo`](https://docs.bazel.build/versions/main/skylark/lib/CcInfo.html)
|
|||
|
provider and a custom
|
|||
|
[`CcObjectInfo`](http://cs/android/build/bazel/rules/cc_object.bzl?l=17-21&rcl=42607e831f8ff73c82825b663609cafb777c18e1)
|
|||
|
provider.
|
|||
|
|
|||
|
#### Native rules
|
|||
|
|
|||
|
For implementation of native rules in Java,
|
|||
|
[`ruleContext.getPrerequisite`](https://github.com/bazelbuild/bazel/blob/a20b32690a71caf712d1d241f01fef16649562ba/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java#L911-L983)
|
|||
|
is used to extract providers from dependencies.
|
|||
|
|
|||
|
#### `depset` construction
|
|||
|
|
|||
|
[`depset`](https://docs.bazel.build/versions/main/glossary.html#depset) are used
|
|||
|
in conjunction with providers to accumulate data efficiently from transitive
|
|||
|
dependencies. used to accumulate data from transitive dependencies.
|
|||
|
|
|||
|
#### `exports`
|
|||
|
|
|||
|
Some target have an `exports` attribute by convention, like
|
|||
|
[`java_library.exports`](https://docs.bazel.build/versions/main/be/java.html#java_import.exports).
|
|||
|
This attribute is commonly used to propagate transitive dependencies to the
|
|||
|
dependent as though the dependent has a direct edge to the transitive
|
|||
|
dependencies.
|