Expand namespaces explanation.

Test: N/A
Change-Id: Iec7d40e6886285046fbe00aea8e19073c6c1ba73
This commit is contained in:
Sasha Smundak 2019-11-21 13:23:44 -08:00
parent 667039f404
commit d42609e15c
2 changed files with 104 additions and 27 deletions

127
README.md
View file

@ -74,7 +74,7 @@ cc_binary {
```
Variables are scoped to the remainder of the file they are declared in, as well
as any child blueprint files. Variables are immutable with one exception - they
as any child Android.bp files. Variables are immutable with one exception - they
can be appended to with a += assignment, but only before they have been
referenced.
@ -168,37 +168,114 @@ package {
}
```
### Name resolution
### Referencing Modules
Soong provides the ability for modules in different directories to specify
the same name, as long as each module is declared within a separate namespace.
A namespace can be declared like this:
A module `libfoo` can be referenced by its name
```
soong_namespace {
imports: ["path/to/otherNamespace1", "path/to/otherNamespace2"],
cc_binary {
name: "app",
shared_libs: ["libfoo"],
}
```
Each Soong module is assigned a namespace based on its location in the tree.
Each Soong module is considered to be in the namespace defined by the
soong_namespace found in an Android.bp in the current directory or closest
ancestor directory, unless no such soong_namespace module is found, in which
case the module is considered to be in the implicit root namespace.
Obviously, this works only if there is only one `libfoo` module in the source
tree. Ensuring such name uniqueness for larger trees may become problematic. We
might also want to use the same name in multiple mutually exclusive subtrees
(for example, implementing different devices) deliberately in order to describe
a functionally equivalent module. Enter Soong namespaces.
When Soong attempts to resolve dependency D declared my module M in namespace
N which imports namespaces I1, I2, I3..., then if D is a fully-qualified name
of the form "//namespace:module", only the specified namespace will be searched
for the specified module name. Otherwise, Soong will first look for a module
named D declared in namespace N. If that module does not exist, Soong will look
for a module named D in namespaces I1, I2, I3... Lastly, Soong will look in the
root namespace.
#### Namespaces
Until we have fully converted from Make to Soong, it will be necessary for the
Make product config to specify a value of PRODUCT_SOONG_NAMESPACES. Its value
should be a space-separated list of namespaces that Soong export to Make to be
built by the `m` command. After we have fully converted from Make to Soong, the
details of enabling namespaces could potentially change.
A presense of the `soong_namespace {..}` in an Android.bp file defines a
**namespace**. For instance, having
```
soong_namespace {
...
}
...
```
in `device/google/bonito/Android.bp` informs Soong that within the
`device/google/bonito` package the module names are unique, that is, all the
modules defined in the Android.bp files in the `device/google/bonito/` tree have
unique names. However, there may be modules with the same names outside
`device/google/bonito` tree. Indeed, there is a module `"pixelstats-vendor"`
both in `device/google/bonito/pixelstats` and in
`device/google/coral/pixelstats`.
The name of a namespace is the path of its directory. The name of the namespace
in the example above is thus `device/google/bonito`.
An implicit **global namespace** corresponds to the source tree as a whole. It
has empty name.
A module name's **scope** is the smallest namespace containing it. Suppose a
source tree has `device/my` and `device/my/display` namespaces. If `libfoo`
module is defined in `device/co/display/lib/Android.bp`, its namespace is
`device/co/display`.
The name uniqueness thus means that module's name is unique within its scope. In
other words, "//_scope_:_name_" is globally unique module reference, e.g,
`"//device/google/bonito:pixelstats-vendor"`. _Note_ that the name of the
namespace for a module may be different from module's package name: `libfoo`
belongs to `device/my/display` namespace but is contained in
`device/my/display/lib` package.
#### Name Resolution
The form of a module reference determines how Soong locates the module.
For a **global reference** of the "//_scope_:_name_" form, Soong verifies there
is a namespace called "_scope_", then verifies it contains a "_name_" module and
uses it. Soong verifies there is only one "_name_" in "_scope_" at the beginning
when it parses Android.bp files.
A **local reference** has "_name_" form, and resolving it involves looking for a
module "_name_" in one or more namespaces. By default only the global namespace
is searched for "_name_" (in other words, only the modules not belonging to an
explicitly defined scope are considered). The `imports` attribute of the
`soong_namespaces` allows to specify where to look for modules . For instance,
with `device/google/bonito/Android.bp` containing
```
soong_namespace {
imports: [
"hardware/google/interfaces",
"hardware/google/pixel",
"hardware/qcom/bootctrl",
],
}
```
a reference to `"libpixelstats"` will resolve to the module defined in
`hardware/google/pixel/pixelstats/Android.bp` because this module is in
`hardware/google/pixel` namespace.
**TODO**: Conventionally, languages with similar concepts provide separate
constructs for namespace definition and name resolution (`namespace` and `using`
in C++, for instance). Should Soong do that, too?
#### Referencing modules in makefiles
While we are gradually converting makefiles to Android.bp files, Android build
is described by a mixture of Android.bp and Android.mk files, and a module
defined in an Android.mk file can reference a module defined in Android.bp file.
For instance, a binary still defined in an Android.mk file may have a library
defined in already converted Android.bp as a dependency.
A module defined in an Android.bp file and belonging to the global namespace can
be referenced from a makefile without additional effort. If a module belongs to
an explicit namespace, it can be referenced from a makefile only after after the
name of the namespace has been added to the value of PRODUCT_SOONG_NAMESPACES
variable.
Note that makefiles have no notion of namespaces and exposing namespaces with
the same modules via PRODUCT_SOONG_NAMESPACES may cause Make failure. For
instance, exposing both `device/google/bonito` and `device/google/coral`
namespaces will cause Make failure because it will see two targets for the
`pixelstats-vendor` module.
### Visibility
@ -266,7 +343,7 @@ owner's responsibility to replace that with a more appropriate visibility.
### Formatter
Soong includes a canonical formatter for blueprint files, similar to
Soong includes a canonical formatter for Android.bp files, similar to
[gofmt](https://golang.org/cmd/gofmt/). To recursively reformat all Android.bp files
in the current directory:
```

View file

@ -240,8 +240,8 @@ PRODUCT_PROPERTY_OVERRIDES += ro.hardware.gralloc=soc_a
In cases where the names cannot be made unique a `soong_namespace` should be
used to partition a set of modules so that they are built only when the
namespace is listed in `PRODUCT_SOONG_NAMESPACES`. See the
[Name resolution](../README.md#name-resolution) section of the Soong README.md
for more on namespaces.
[Referencing Modules](../README.md#referencing-modules) section of the Soong
README.md for more on namespaces.
### Module with name based on variable