2018-10-02 17:38:19 +02:00
|
|
|
// Copyright 2018 Google Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package android
|
|
|
|
|
Don't create unnecessary APEX variations
This change fixes a problem that APEX variations are created for the
modules that actually shouldn't built for any APEX. For example,
consider this case.
apex { name: "myapex", native_shared_libs: ["mylib"],}
cc_library { name: "mylib", shared_libs: ["libfoo#10"],}
cc_library { name: "libfoo",
shared_libs: ["libbar"],
stubs: { versions: ["10"], }, }
cc_library { name: "libbar", ...}
Before this change, both the stubs and non-stubs variations of libfoo
were mutated with apexMuator, which is incorrect for the non-stubs
varia; there is no dependency chain from the apex "myapex" to the
non-stubs variation, but to the stubs variation due to the #10 syntax.
This was happening becauses we used the name of the module to determine
whether it should be built for APEX or not. Both stubs and non-stubs
variations have the same module name "libfoo".
Fixing this issue by recording the list of APEX variations required
directly on the module. So, the stubs variation of libfoo has myapex in
its apex variations list, but the non-stubs variation doesn't, and thus
apexMutator does not pick up the non-stubs variation.
Test: m (apex_test updated and passing)
Test: cherry-pick ag/5747464 and m
Change-Id: I31e618626809a828a55fff513ef5f81f79637afa
2018-12-10 17:35:25 +01:00
|
|
|
import (
|
2020-02-26 14:45:42 +01:00
|
|
|
"fmt"
|
2019-06-04 00:07:03 +02:00
|
|
|
"sort"
|
2020-02-26 14:45:42 +01:00
|
|
|
"strconv"
|
2020-04-27 18:08:37 +02:00
|
|
|
"strings"
|
Don't create unnecessary APEX variations
This change fixes a problem that APEX variations are created for the
modules that actually shouldn't built for any APEX. For example,
consider this case.
apex { name: "myapex", native_shared_libs: ["mylib"],}
cc_library { name: "mylib", shared_libs: ["libfoo#10"],}
cc_library { name: "libfoo",
shared_libs: ["libbar"],
stubs: { versions: ["10"], }, }
cc_library { name: "libbar", ...}
Before this change, both the stubs and non-stubs variations of libfoo
were mutated with apexMuator, which is incorrect for the non-stubs
varia; there is no dependency chain from the apex "myapex" to the
non-stubs variation, but to the stubs variation due to the #10 syntax.
This was happening becauses we used the name of the module to determine
whether it should be built for APEX or not. Both stubs and non-stubs
variations have the same module name "libfoo".
Fixing this issue by recording the list of APEX variations required
directly on the module. So, the stubs variation of libfoo has myapex in
its apex variations list, but the non-stubs variation doesn't, and thus
apexMutator does not pick up the non-stubs variation.
Test: m (apex_test updated and passing)
Test: cherry-pick ag/5747464 and m
Change-Id: I31e618626809a828a55fff513ef5f81f79637afa
2018-12-10 17:35:25 +01:00
|
|
|
"sync"
|
2020-04-07 16:25:44 +02:00
|
|
|
|
|
|
|
"github.com/google/blueprint"
|
Don't create unnecessary APEX variations
This change fixes a problem that APEX variations are created for the
modules that actually shouldn't built for any APEX. For example,
consider this case.
apex { name: "myapex", native_shared_libs: ["mylib"],}
cc_library { name: "mylib", shared_libs: ["libfoo#10"],}
cc_library { name: "libfoo",
shared_libs: ["libbar"],
stubs: { versions: ["10"], }, }
cc_library { name: "libbar", ...}
Before this change, both the stubs and non-stubs variations of libfoo
were mutated with apexMuator, which is incorrect for the non-stubs
varia; there is no dependency chain from the apex "myapex" to the
non-stubs variation, but to the stubs variation due to the #10 syntax.
This was happening becauses we used the name of the module to determine
whether it should be built for APEX or not. Both stubs and non-stubs
variations have the same module name "libfoo".
Fixing this issue by recording the list of APEX variations required
directly on the module. So, the stubs variation of libfoo has myapex in
its apex variations list, but the non-stubs variation doesn't, and thus
apexMutator does not pick up the non-stubs variation.
Test: m (apex_test updated and passing)
Test: cherry-pick ag/5747464 and m
Change-Id: I31e618626809a828a55fff513ef5f81f79637afa
2018-12-10 17:35:25 +01:00
|
|
|
)
|
Stubs variant is used when building for APEX
When a native module is built for an APEX and is depending on a native
library having stubs (i.e. stubs.versions property is set), the stubs
variant is used unless the dependent lib is directly included in the
same APEX with the depending module.
Example:
apex {
name: "myapex",
native_shared_libs: ["libX", "libY"],
}
cc_library {
name: "libX",
shared_libs: ["libY", "libZ"],
}
cc_library {
name: "libY",
stubs: { versions: ["1", "2"], },
}
cc_library {
name: "libZ",
stubs: { versions: ["1", "2"], },
}
In this case, libX is linking to the impl variant of libY (that provides
private APIs) while libY is linking to the version 2 stubs of libZ. This is
because libY is directly included in the same apex via
native_shared_libs property, but libZ isn't.
Bug: 112672359
Test: apex_test added
Change-Id: If9871b70dc74a06bd828dd4cd1aeebd2e68b837c
2018-11-18 10:02:45 +01:00
|
|
|
|
2020-07-23 07:32:17 +02:00
|
|
|
var (
|
2020-11-17 17:34:22 +01:00
|
|
|
// This is the sdk version when APEX was first introduced
|
2020-07-23 07:32:17 +02:00
|
|
|
SdkVersion_Android10 = uncheckedFinalApiLevel(29)
|
2020-03-12 10:37:20 +01:00
|
|
|
)
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// ApexInfo describes the metadata about one or more apexBundles that an apex variant of a module is
|
|
|
|
// part of. When an apex variant is created, the variant is associated with one apexBundle. But
|
|
|
|
// when multiple apex variants are merged for deduping (see mergeApexVariations), this holds the
|
|
|
|
// information about the apexBundles that are merged together.
|
|
|
|
// Accessible via `ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)`
|
2020-02-13 02:13:25 +01:00
|
|
|
type ApexInfo struct {
|
2020-11-17 17:34:22 +01:00
|
|
|
// Name of the apex variation that this module (i.e. the apex variant of the module) is
|
2021-05-12 10:13:56 +02:00
|
|
|
// mutated into, or "" for a platform (i.e. non-APEX) variant. Note that this name and the
|
|
|
|
// Soong module name of the APEX can be different. That happens when there is
|
|
|
|
// `override_apex` that overrides `apex`. In that case, both Soong modules have the same
|
|
|
|
// apex variation name which usually is `com.android.foo`. This name is also the `name`
|
|
|
|
// in the path `/apex/<name>` where this apex is activated on at runtime.
|
|
|
|
//
|
|
|
|
// Also note that a module can be included in multiple APEXes, in which case, the module is
|
|
|
|
// mutated into one or more variants, each of which is for an APEX. The variants then can
|
|
|
|
// later be deduped if they don't need to be compiled differently. This is an optimization
|
|
|
|
// done in mergeApexVariations.
|
2020-08-13 20:24:56 +02:00
|
|
|
ApexVariationName string
|
2020-02-13 02:13:25 +01:00
|
|
|
|
2021-04-15 08:17:54 +02:00
|
|
|
// ApiLevel that this module has to support at minimum.
|
|
|
|
MinSdkVersion ApiLevel
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// True if this module comes from an updatable apexBundle.
|
|
|
|
Updatable bool
|
|
|
|
|
2021-06-22 13:23:05 +02:00
|
|
|
// True if this module can use private platform APIs. Only non-updatable APEX can set this
|
|
|
|
// to true.
|
|
|
|
UsePlatformApis bool
|
|
|
|
|
2021-05-12 10:13:56 +02:00
|
|
|
// List of Apex variant names that this module is associated with. This initially is the
|
|
|
|
// same as the `ApexVariationName` field. Then when multiple apex variants are merged in
|
|
|
|
// mergeApexVariations, ApexInfo struct of the merged variant holds the list of apexBundles
|
|
|
|
// that are merged together.
|
|
|
|
InApexVariants []string
|
2020-11-17 17:34:22 +01:00
|
|
|
|
Record the actual APEXes that a module is part of.
Consider this case:
apex {
name: "com.android.foo",
native_libs: ["foo"],
}
override_apex {
name: "com.mycompany.android.foo",
base: "com.android.foo",
}
cc_library {
name: "foo",
}
There are two APEXes defined: "com.android.foo" and
"com.mycompany.android.foo" which is a copy of "com.android.foo" with
some properties overridden (e.g. signing keys).
The module "foo" is mutated into two variants by the apex mutator: the
platform variant and the apex variant. The former has the variation name
"" and the later has "apex<min_api_ver>" which usually is "apex10000".
Internally, the apex variant has an alias "com.android.foo".
ApexInfo.InApexVariants() returns only "com.android.foo" when called for
the module "foo".
We can see that the information that "foo" is also part of
"com.mycompany.android.foo" is completely lost. This is causing problem
when we compare the apex membership by their "soong module name", not
the "apex name". In the example above, the two modules have different
soone module names, but have the same apex name: "com.android.foo".
To fix that, this CL introduces a new field `InApexes` to the `ApexInfo`
struct. It has the actual name of the APEXes that the module is part of.
With the example above, `InApexes` is ["com.android.foo",
"com.mycompany.android.foo"].
Bug: 180325915
Test: m nothing
Test: m nothing on non-AOSP targets with ag/13740887 applied.
Change-Id: I4e7a7ac5495d2e622ba92a4358ed967e066c6c2e
2021-05-12 10:13:56 +02:00
|
|
|
// List of APEX Soong module names that this module is part of. Note that the list includes
|
|
|
|
// different variations of the same APEX. For example, if module `foo` is included in the
|
|
|
|
// apex `com.android.foo`, and also if there is an override_apex module
|
|
|
|
// `com.mycompany.android.foo` overriding `com.android.foo`, then this list contains both
|
|
|
|
// `com.android.foo` and `com.mycompany.android.foo`. If the APEX Soong module is a
|
|
|
|
// prebuilt, the name here doesn't have the `prebuilt_` prefix.
|
|
|
|
InApexModules []string
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Pointers to the ApexContents struct each of which is for apexBundle modules that this
|
|
|
|
// module is part of. The ApexContents gives information about which modules the apexBundle
|
|
|
|
// has and whether a module became part of the apexBundle via a direct dependency or not.
|
2020-09-16 03:30:11 +02:00
|
|
|
ApexContents []*ApexContents
|
2020-11-02 18:32:38 +01:00
|
|
|
|
|
|
|
// True if this is for a prebuilt_apex.
|
|
|
|
//
|
|
|
|
// If true then this will customize the apex processing to make it suitable for handling
|
|
|
|
// prebuilt_apex, e.g. it will prevent ApexInfos from being merged together.
|
|
|
|
//
|
|
|
|
// See Prebuilt.ApexInfoMutator for more information.
|
|
|
|
ForPrebuiltApex bool
|
2023-04-12 19:14:11 +02:00
|
|
|
|
|
|
|
// Returns the name of the test apexes that this module is included in.
|
|
|
|
TestApexes []string
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
}
|
|
|
|
|
2020-09-16 03:30:11 +02:00
|
|
|
var ApexInfoProvider = blueprint.NewMutatorProvider(ApexInfo{}, "apex")
|
|
|
|
|
2021-06-25 09:11:22 +02:00
|
|
|
func (i ApexInfo) AddJSONData(d *map[string]interface{}) {
|
|
|
|
(*d)["Apex"] = map[string]interface{}{
|
|
|
|
"ApexVariationName": i.ApexVariationName,
|
|
|
|
"MinSdkVersion": i.MinSdkVersion,
|
|
|
|
"InApexModules": i.InApexModules,
|
|
|
|
"InApexVariants": i.InApexVariants,
|
|
|
|
"ForPrebuiltApex": i.ForPrebuiltApex,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// mergedName gives the name of the alias variation that will be used when multiple apex variations
|
|
|
|
// of a module can be deduped into one variation. For example, if libfoo is included in both apex.a
|
|
|
|
// and apex.b, and if the two APEXes have the same min_sdk_version (say 29), then libfoo doesn't
|
|
|
|
// have to be built twice, but only once. In that case, the two apex variations apex.a and apex.b
|
2021-06-22 13:23:05 +02:00
|
|
|
// are configured to have the same alias variation named apex29. Whether platform APIs is allowed
|
|
|
|
// or not also matters; if two APEXes don't have the same allowance, they get different names and
|
|
|
|
// thus wouldn't be merged.
|
2020-10-02 19:26:04 +02:00
|
|
|
func (i ApexInfo) mergedName(ctx PathContext) string {
|
2021-04-15 08:17:54 +02:00
|
|
|
name := "apex" + strconv.Itoa(i.MinSdkVersion.FinalOrFutureInt())
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
return name
|
2020-02-13 02:13:25 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// IsForPlatform tells whether this module is for the platform or not. If false is returned, it
|
|
|
|
// means that this apex variant of the module is built for an APEX.
|
2020-09-16 03:30:11 +02:00
|
|
|
func (i ApexInfo) IsForPlatform() bool {
|
|
|
|
return i.ApexVariationName == ""
|
|
|
|
}
|
|
|
|
|
2021-05-12 10:13:56 +02:00
|
|
|
// InApexVariant tells whether this apex variant of the module is part of the given apexVariant or
|
|
|
|
// not.
|
|
|
|
func (i ApexInfo) InApexVariant(apexVariant string) bool {
|
|
|
|
for _, a := range i.InApexVariants {
|
|
|
|
if a == apexVariant {
|
2020-10-28 20:20:06 +01:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
Record the actual APEXes that a module is part of.
Consider this case:
apex {
name: "com.android.foo",
native_libs: ["foo"],
}
override_apex {
name: "com.mycompany.android.foo",
base: "com.android.foo",
}
cc_library {
name: "foo",
}
There are two APEXes defined: "com.android.foo" and
"com.mycompany.android.foo" which is a copy of "com.android.foo" with
some properties overridden (e.g. signing keys).
The module "foo" is mutated into two variants by the apex mutator: the
platform variant and the apex variant. The former has the variation name
"" and the later has "apex<min_api_ver>" which usually is "apex10000".
Internally, the apex variant has an alias "com.android.foo".
ApexInfo.InApexVariants() returns only "com.android.foo" when called for
the module "foo".
We can see that the information that "foo" is also part of
"com.mycompany.android.foo" is completely lost. This is causing problem
when we compare the apex membership by their "soong module name", not
the "apex name". In the example above, the two modules have different
soone module names, but have the same apex name: "com.android.foo".
To fix that, this CL introduces a new field `InApexes` to the `ApexInfo`
struct. It has the actual name of the APEXes that the module is part of.
With the example above, `InApexes` is ["com.android.foo",
"com.mycompany.android.foo"].
Bug: 180325915
Test: m nothing
Test: m nothing on non-AOSP targets with ag/13740887 applied.
Change-Id: I4e7a7ac5495d2e622ba92a4358ed967e066c6c2e
2021-05-12 10:13:56 +02:00
|
|
|
func (i ApexInfo) InApexModule(apexModuleName string) bool {
|
|
|
|
for _, a := range i.InApexModules {
|
|
|
|
if a == apexModuleName {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// ApexTestForInfo stores the contents of APEXes for which this module is a test - although this
|
|
|
|
// module is not part of the APEX - and thus has access to APEX internals.
|
2020-09-16 03:30:11 +02:00
|
|
|
type ApexTestForInfo struct {
|
|
|
|
ApexContents []*ApexContents
|
|
|
|
}
|
|
|
|
|
|
|
|
var ApexTestForInfoProvider = blueprint.NewMutatorProvider(ApexTestForInfo{}, "apex_test_for")
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// DepIsInSameApex defines an interface that should be used to determine whether a given dependency
|
|
|
|
// should be considered as part of the same APEX as the current module or not. Note: this was
|
|
|
|
// extracted from ApexModule to make it easier to define custom subsets of the ApexModule interface
|
|
|
|
// and improve code navigation within the IDE.
|
2020-03-30 16:33:32 +02:00
|
|
|
type DepIsInSameApex interface {
|
2020-11-17 17:34:22 +01:00
|
|
|
// DepIsInSameApex tests if the other module 'dep' is considered as part of the same APEX as
|
|
|
|
// this module. For example, a static lib dependency usually returns true here, while a
|
|
|
|
// shared lib dependency to a stub library returns false.
|
2021-03-18 16:41:29 +01:00
|
|
|
//
|
|
|
|
// This method must not be called directly without first ignoring dependencies whose tags
|
|
|
|
// implement ExcludeFromApexContentsTag. Calls from within the func passed to WalkPayloadDeps()
|
|
|
|
// are fine as WalkPayloadDeps() will ignore those dependencies automatically. Otherwise, use
|
|
|
|
// IsDepInSameApex instead.
|
2020-03-30 16:33:32 +02:00
|
|
|
DepIsInSameApex(ctx BaseModuleContext, dep Module) bool
|
|
|
|
}
|
|
|
|
|
2021-03-18 16:41:29 +01:00
|
|
|
func IsDepInSameApex(ctx BaseModuleContext, module, dep Module) bool {
|
|
|
|
depTag := ctx.OtherModuleDependencyTag(dep)
|
|
|
|
if _, ok := depTag.(ExcludeFromApexContentsTag); ok {
|
|
|
|
// The tag defines a dependency that never requires the child module to be part of the same
|
|
|
|
// apex as the parent.
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return module.(DepIsInSameApex).DepIsInSameApex(ctx, dep)
|
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// ApexModule is the interface that a module type is expected to implement if the module has to be
|
|
|
|
// built differently depending on whether the module is destined for an APEX or not (i.e., installed
|
|
|
|
// to one of the regular partitions).
|
2018-10-02 17:38:19 +02:00
|
|
|
//
|
2020-11-17 17:34:22 +01:00
|
|
|
// Native shared libraries are one such module type; when it is built for an APEX, it should depend
|
|
|
|
// only on stable interfaces such as NDK, stable AIDL, or C APIs from other APEXes.
|
2018-10-02 17:38:19 +02:00
|
|
|
//
|
2020-11-17 17:34:22 +01:00
|
|
|
// A module implementing this interface will be mutated into multiple variations by apex.apexMutator
|
|
|
|
// if it is directly or indirectly included in one or more APEXes. Specifically, if a module is
|
|
|
|
// included in apex.foo and apex.bar then three apex variants are created: platform, apex.foo and
|
|
|
|
// apex.bar. The platform variant is for the regular partitions (e.g., /system or /vendor, etc.)
|
|
|
|
// while the other two are for the APEXs, respectively. The latter two variations can be merged (see
|
|
|
|
// mergedName) when the two APEXes have the same min_sdk_version requirement.
|
2018-10-02 17:38:19 +02:00
|
|
|
type ApexModule interface {
|
|
|
|
Module
|
2020-03-30 16:33:32 +02:00
|
|
|
DepIsInSameApex
|
|
|
|
|
2018-10-02 17:38:19 +02:00
|
|
|
apexModuleBase() *ApexModuleBase
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Marks that this module should be built for the specified APEX. Call this BEFORE
|
|
|
|
// apex.apexMutator is run.
|
2020-07-22 08:17:19 +02:00
|
|
|
BuildForApex(apex ApexInfo)
|
apexDepsMutator is a top-down mutator
apex { name: ["myapex"], native_shared_libs: ["libX", "libY"] }
cc_library { name: "libX", shared_libs: ["libY"] }
cc_library { name: "libY", shared_libs: ["libZ"], stubs: {...} }
apexDepsMutator was a bottom up mutator and it uses WalkDeps to traverse
the dependency tree rooted at myapex in a depth-first order. While
traversing the tree, if calls BuildForApex for a module that will be
part of the APEX.
libY is visited twice. Once via libX and once via myapex. If the visit
from libX was before the visit from myapex (since this is a depth-first
traversing), BuildForApex is not called for libY and its dependency
libZ, because libY provides a stub. And then when libY is again visited
via myapex, BuildForApex is correctly called for the module, but not for
its dependencies libZ because the paths from libY to libZ was already
visited.
As a result, the apex variant of libY has a dependency to the non-apex
variant of libZ.
Fixing the problem by changing the mutator a top-down one.
Bug: 148645937
Test: m
Change-Id: Ib2cb28852087c63a568b3fd036504e9261cf0782
2020-02-11 23:53:12 +01:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Returns true if this module is present in any APEX either directly or indirectly. Call
|
|
|
|
// this after apex.apexMutator is run.
|
2020-09-16 03:30:11 +02:00
|
|
|
InAnyApex() bool
|
2018-10-02 17:38:19 +02:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Returns true if this module is directly in any APEX. Call this AFTER apex.apexMutator is
|
|
|
|
// run.
|
2020-09-16 03:30:11 +02:00
|
|
|
DirectlyInAnyApex() bool
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
|
2020-12-09 13:18:56 +01:00
|
|
|
// NotInPlatform tells whether or not this module is included in an APEX and therefore
|
|
|
|
// shouldn't be exposed to the platform (i.e. outside of the APEX) directly. A module is
|
|
|
|
// considered to be included in an APEX either when there actually is an APEX that
|
|
|
|
// explicitly has the module as its dependency or the module is not available to the
|
|
|
|
// platform, which indicates that the module belongs to at least one or more other APEXes.
|
|
|
|
NotInPlatform() bool
|
Don't create unnecessary APEX variations
This change fixes a problem that APEX variations are created for the
modules that actually shouldn't built for any APEX. For example,
consider this case.
apex { name: "myapex", native_shared_libs: ["mylib"],}
cc_library { name: "mylib", shared_libs: ["libfoo#10"],}
cc_library { name: "libfoo",
shared_libs: ["libbar"],
stubs: { versions: ["10"], }, }
cc_library { name: "libbar", ...}
Before this change, both the stubs and non-stubs variations of libfoo
were mutated with apexMuator, which is incorrect for the non-stubs
varia; there is no dependency chain from the apex "myapex" to the
non-stubs variation, but to the stubs variation due to the #10 syntax.
This was happening becauses we used the name of the module to determine
whether it should be built for APEX or not. Both stubs and non-stubs
variations have the same module name "libfoo".
Fixing this issue by recording the list of APEX variations required
directly on the module. So, the stubs variation of libfoo has myapex in
its apex variations list, but the non-stubs variation doesn't, and thus
apexMutator does not pick up the non-stubs variation.
Test: m (apex_test updated and passing)
Test: cherry-pick ag/5747464 and m
Change-Id: I31e618626809a828a55fff513ef5f81f79637afa
2018-12-10 17:35:25 +01:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Tests if this module could have APEX variants. Even when a module type implements
|
|
|
|
// ApexModule interface, APEX variants are created only for the module instances that return
|
|
|
|
// true here. This is useful for not creating APEX variants for certain types of shared
|
|
|
|
// libraries such as NDK stubs.
|
2018-10-02 17:38:19 +02:00
|
|
|
CanHaveApexVariants() bool
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Tests if this module can be installed to APEX as a file. For example, this would return
|
|
|
|
// true for shared libs while return false for static libs because static libs are not
|
|
|
|
// installable module (but it can still be mutated for APEX)
|
2018-10-02 17:38:19 +02:00
|
|
|
IsInstallableToApex() bool
|
Don't create unnecessary APEX variations
This change fixes a problem that APEX variations are created for the
modules that actually shouldn't built for any APEX. For example,
consider this case.
apex { name: "myapex", native_shared_libs: ["mylib"],}
cc_library { name: "mylib", shared_libs: ["libfoo#10"],}
cc_library { name: "libfoo",
shared_libs: ["libbar"],
stubs: { versions: ["10"], }, }
cc_library { name: "libbar", ...}
Before this change, both the stubs and non-stubs variations of libfoo
were mutated with apexMuator, which is incorrect for the non-stubs
varia; there is no dependency chain from the apex "myapex" to the
non-stubs variation, but to the stubs variation due to the #10 syntax.
This was happening becauses we used the name of the module to determine
whether it should be built for APEX or not. Both stubs and non-stubs
variations have the same module name "libfoo".
Fixing this issue by recording the list of APEX variations required
directly on the module. So, the stubs variation of libfoo has myapex in
its apex variations list, but the non-stubs variation doesn't, and thus
apexMutator does not pick up the non-stubs variation.
Test: m (apex_test updated and passing)
Test: cherry-pick ag/5747464 and m
Change-Id: I31e618626809a828a55fff513ef5f81f79637afa
2018-12-10 17:35:25 +01:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Tests if this module is available for the specified APEX or ":platform". This is from the
|
|
|
|
// apex_available property of the module.
|
Add apex_available to control the availablity of a module to APEXes
apex_available property controls the availability of a module to APEXes.
For example, `apex_available: ["myapex", "otherapex"]` makes the module
available only to the two APEXes: myapex and otherapex, and nothing
else, even to the platform.
If the module is intended to be available to any APEX, then a pseudo
name "//apex_available:anyapex" can be used.
If the module is intended to be available to the platform, then another
pseudo name "//apex_available:platform" is used.
For now, if unspecified, this property defaults to ["//apex_available:platform",
"//apex_available:anyapex"], which means the module is available to everybody.
This will be reduced to ["//apex_available:platform"], when marking for
apex_available for existing modules are finished.
Bug: 139870423
Bug: 128708192
Test: m
Change-Id: Id4b233c3056c7858f984cbf9427cfac4118b2682
2019-09-30 09:04:35 +02:00
|
|
|
AvailableFor(what string) bool
|
2019-10-15 08:20:07 +02:00
|
|
|
|
2021-05-12 17:16:51 +02:00
|
|
|
// AlwaysRequiresPlatformApexVariant allows the implementing module to determine whether an
|
|
|
|
// APEX mutator should always be created for it.
|
|
|
|
//
|
|
|
|
// Returns false by default.
|
|
|
|
AlwaysRequiresPlatformApexVariant() bool
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Returns true if this module is not available to platform (i.e. apex_available property
|
|
|
|
// doesn't have "//apex_available:platform"), or shouldn't be available to platform, which
|
|
|
|
// is the case when this module depends on other module that isn't available to platform.
|
mark platform un-availability
A module is marked unavailable for platform when 1) it does not have
"//apex_available:platform" in its apex_available property, or 2)
it depends on another module that is unavailable for platform.
In that case, LOCAL_NOT_AVAILABLE_FOR_PLATFORM is set to true for the
module in the Make world. Later, that flag is used to ensure that there
is no module with the flag is installed to the device.
The reason why this isn't entirely done in Soong is because Soong
doesn't know if a module will be installed to the device or not. To
explain this, let's have an example.
cc_test { name: "mytest", static_libs: ["libfoo"]}
cc_library_static { name: "libfoo", static_libs: ["libbar"]}
cc_library { name: "libbar", apex_available: ["com.android.xxx"]}
Here, libbar is not available for platform, but is used by libfoo which
is available for platform (apex_available defaults to
"//apex_available:platform"). libfoo is again depended on by mytest
which again is available for platform. The use of libbar should be
allowed in the context of test; we don't want to make libbar available
to platform just for the dependency from test because it will allow
non-test uses of the library as well.
Soong by itself can't tell whether libfoo and libbar are used only in the
context of a test. There could be another module depending them, e.g.,
cc_library_shared { name: "mylib", static_libs: ["libfoo"] }
can exist and it might be installed to the device, in which case
we really should trigger an error.
Since Make has the knowledge of what's installed and what's not,
the check should be done there.
Bug: 153073816
Test: m
Test: remove "//apex_available:platform" from libmdnssd (it is currently
installed to /system/lib), and check that `m system_image` fails
Change-Id: Ia304cc5f41f173229e8a154e90cea4dce46dcebe
2020-04-07 09:37:39 +02:00
|
|
|
NotAvailableForPlatform() bool
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Marks that this module is not available to platform. Set by the
|
mark platform un-availability
A module is marked unavailable for platform when 1) it does not have
"//apex_available:platform" in its apex_available property, or 2)
it depends on another module that is unavailable for platform.
In that case, LOCAL_NOT_AVAILABLE_FOR_PLATFORM is set to true for the
module in the Make world. Later, that flag is used to ensure that there
is no module with the flag is installed to the device.
The reason why this isn't entirely done in Soong is because Soong
doesn't know if a module will be installed to the device or not. To
explain this, let's have an example.
cc_test { name: "mytest", static_libs: ["libfoo"]}
cc_library_static { name: "libfoo", static_libs: ["libbar"]}
cc_library { name: "libbar", apex_available: ["com.android.xxx"]}
Here, libbar is not available for platform, but is used by libfoo which
is available for platform (apex_available defaults to
"//apex_available:platform"). libfoo is again depended on by mytest
which again is available for platform. The use of libbar should be
allowed in the context of test; we don't want to make libbar available
to platform just for the dependency from test because it will allow
non-test uses of the library as well.
Soong by itself can't tell whether libfoo and libbar are used only in the
context of a test. There could be another module depending them, e.g.,
cc_library_shared { name: "mylib", static_libs: ["libfoo"] }
can exist and it might be installed to the device, in which case
we really should trigger an error.
Since Make has the knowledge of what's installed and what's not,
the check should be done there.
Bug: 153073816
Test: m
Test: remove "//apex_available:platform" from libmdnssd (it is currently
installed to /system/lib), and check that `m system_image` fails
Change-Id: Ia304cc5f41f173229e8a154e90cea4dce46dcebe
2020-04-07 09:37:39 +02:00
|
|
|
// check-platform-availability mutator in the apex package.
|
|
|
|
SetNotAvailableForPlatform()
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Returns the list of APEXes that this module is a test for. The module has access to the
|
|
|
|
// private part of the listed APEXes even when it is not included in the APEXes. This by
|
|
|
|
// default returns nil. A module type should override the default implementation. For
|
|
|
|
// example, cc_test module type returns the value of test_for here.
|
2020-04-13 09:19:48 +02:00
|
|
|
TestFor() []string
|
2020-04-15 04:03:39 +02:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Returns nil (success) if this module should support the given sdk version. Returns an
|
|
|
|
// error if not. No default implementation is provided for this method. A module type
|
|
|
|
// implementing this interface should provide an implementation. A module supports an sdk
|
|
|
|
// version when the module's min_sdk_version is equal to or less than the given sdk version.
|
2020-07-23 07:32:17 +02:00
|
|
|
ShouldSupportSdkVersion(ctx BaseModuleContext, sdkVersion ApiLevel) error
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Returns true if this module needs a unique variation per apex, effectively disabling the
|
|
|
|
// deduping. This is turned on when, for example if use_apex_name_macro is set so that each
|
|
|
|
// apex variant should be built with different macro definitions.
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
UniqueApexVariations() bool
|
2018-10-02 17:38:19 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Properties that are common to all module types implementing ApexModule interface.
|
2018-10-02 17:38:19 +02:00
|
|
|
type ApexProperties struct {
|
2020-11-17 17:34:22 +01:00
|
|
|
// Availability of this module in APEXes. Only the listed APEXes can contain this module. If
|
|
|
|
// the module has stubs then other APEXes and the platform may access it through them
|
|
|
|
// (subject to visibility).
|
2020-01-17 14:02:56 +01:00
|
|
|
//
|
Add apex_available to control the availablity of a module to APEXes
apex_available property controls the availability of a module to APEXes.
For example, `apex_available: ["myapex", "otherapex"]` makes the module
available only to the two APEXes: myapex and otherapex, and nothing
else, even to the platform.
If the module is intended to be available to any APEX, then a pseudo
name "//apex_available:anyapex" can be used.
If the module is intended to be available to the platform, then another
pseudo name "//apex_available:platform" is used.
For now, if unspecified, this property defaults to ["//apex_available:platform",
"//apex_available:anyapex"], which means the module is available to everybody.
This will be reduced to ["//apex_available:platform"], when marking for
apex_available for existing modules are finished.
Bug: 139870423
Bug: 128708192
Test: m
Change-Id: Id4b233c3056c7858f984cbf9427cfac4118b2682
2019-09-30 09:04:35 +02:00
|
|
|
// "//apex_available:anyapex" is a pseudo APEX name that matches to any APEX.
|
|
|
|
// "//apex_available:platform" refers to non-APEX partitions like "system.img".
|
2020-07-29 02:37:46 +02:00
|
|
|
// "com.android.gki.*" matches any APEX module name with the prefix "com.android.gki.".
|
2020-02-12 18:30:45 +01:00
|
|
|
// Default is ["//apex_available:platform"].
|
Add apex_available to control the availablity of a module to APEXes
apex_available property controls the availability of a module to APEXes.
For example, `apex_available: ["myapex", "otherapex"]` makes the module
available only to the two APEXes: myapex and otherapex, and nothing
else, even to the platform.
If the module is intended to be available to any APEX, then a pseudo
name "//apex_available:anyapex" can be used.
If the module is intended to be available to the platform, then another
pseudo name "//apex_available:platform" is used.
For now, if unspecified, this property defaults to ["//apex_available:platform",
"//apex_available:anyapex"], which means the module is available to everybody.
This will be reduced to ["//apex_available:platform"], when marking for
apex_available for existing modules are finished.
Bug: 139870423
Bug: 128708192
Test: m
Change-Id: Id4b233c3056c7858f984cbf9427cfac4118b2682
2019-09-30 09:04:35 +02:00
|
|
|
Apex_available []string
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// See ApexModule.InAnyApex()
|
|
|
|
InAnyApex bool `blueprint:"mutated"`
|
2020-09-16 03:30:11 +02:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// See ApexModule.DirectlyInAnyApex()
|
2020-09-16 03:30:11 +02:00
|
|
|
DirectlyInAnyApex bool `blueprint:"mutated"`
|
|
|
|
|
2020-12-09 13:18:56 +01:00
|
|
|
// AnyVariantDirectlyInAnyApex is true in the primary variant of a module if _any_ variant
|
|
|
|
// of the module is directly in any apex. This includes host, arch, asan, etc. variants. It
|
|
|
|
// is unused in any variant that is not the primary variant. Ideally this wouldn't be used,
|
|
|
|
// as it incorrectly mixes arch variants if only one arch is in an apex, but a few places
|
|
|
|
// depend on it, for example when an ASAN variant is created before the apexMutator. Call
|
|
|
|
// this after apex.apexMutator is run.
|
2020-11-17 17:34:22 +01:00
|
|
|
AnyVariantDirectlyInAnyApex bool `blueprint:"mutated"`
|
mark platform un-availability
A module is marked unavailable for platform when 1) it does not have
"//apex_available:platform" in its apex_available property, or 2)
it depends on another module that is unavailable for platform.
In that case, LOCAL_NOT_AVAILABLE_FOR_PLATFORM is set to true for the
module in the Make world. Later, that flag is used to ensure that there
is no module with the flag is installed to the device.
The reason why this isn't entirely done in Soong is because Soong
doesn't know if a module will be installed to the device or not. To
explain this, let's have an example.
cc_test { name: "mytest", static_libs: ["libfoo"]}
cc_library_static { name: "libfoo", static_libs: ["libbar"]}
cc_library { name: "libbar", apex_available: ["com.android.xxx"]}
Here, libbar is not available for platform, but is used by libfoo which
is available for platform (apex_available defaults to
"//apex_available:platform"). libfoo is again depended on by mytest
which again is available for platform. The use of libbar should be
allowed in the context of test; we don't want to make libbar available
to platform just for the dependency from test because it will allow
non-test uses of the library as well.
Soong by itself can't tell whether libfoo and libbar are used only in the
context of a test. There could be another module depending them, e.g.,
cc_library_shared { name: "mylib", static_libs: ["libfoo"] }
can exist and it might be installed to the device, in which case
we really should trigger an error.
Since Make has the knowledge of what's installed and what's not,
the check should be done there.
Bug: 153073816
Test: m
Test: remove "//apex_available:platform" from libmdnssd (it is currently
installed to /system/lib), and check that `m system_image` fails
Change-Id: Ia304cc5f41f173229e8a154e90cea4dce46dcebe
2020-04-07 09:37:39 +02:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// See ApexModule.NotAvailableForPlatform()
|
mark platform un-availability
A module is marked unavailable for platform when 1) it does not have
"//apex_available:platform" in its apex_available property, or 2)
it depends on another module that is unavailable for platform.
In that case, LOCAL_NOT_AVAILABLE_FOR_PLATFORM is set to true for the
module in the Make world. Later, that flag is used to ensure that there
is no module with the flag is installed to the device.
The reason why this isn't entirely done in Soong is because Soong
doesn't know if a module will be installed to the device or not. To
explain this, let's have an example.
cc_test { name: "mytest", static_libs: ["libfoo"]}
cc_library_static { name: "libfoo", static_libs: ["libbar"]}
cc_library { name: "libbar", apex_available: ["com.android.xxx"]}
Here, libbar is not available for platform, but is used by libfoo which
is available for platform (apex_available defaults to
"//apex_available:platform"). libfoo is again depended on by mytest
which again is available for platform. The use of libbar should be
allowed in the context of test; we don't want to make libbar available
to platform just for the dependency from test because it will allow
non-test uses of the library as well.
Soong by itself can't tell whether libfoo and libbar are used only in the
context of a test. There could be another module depending them, e.g.,
cc_library_shared { name: "mylib", static_libs: ["libfoo"] }
can exist and it might be installed to the device, in which case
we really should trigger an error.
Since Make has the knowledge of what's installed and what's not,
the check should be done there.
Bug: 153073816
Test: m
Test: remove "//apex_available:platform" from libmdnssd (it is currently
installed to /system/lib), and check that `m system_image` fails
Change-Id: Ia304cc5f41f173229e8a154e90cea4dce46dcebe
2020-04-07 09:37:39 +02:00
|
|
|
NotAvailableForPlatform bool `blueprint:"mutated"`
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// See ApexModule.UniqueApexVariants()
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
UniqueApexVariationsForDeps bool `blueprint:"mutated"`
|
2023-04-12 19:14:11 +02:00
|
|
|
|
|
|
|
// The test apexes that includes this apex variant
|
|
|
|
TestApexes []string `blueprint:"mutated"`
|
2018-10-02 17:38:19 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Marker interface that identifies dependencies that are excluded from APEX contents.
|
2021-03-17 14:25:29 +01:00
|
|
|
//
|
|
|
|
// Unless the tag also implements the AlwaysRequireApexVariantTag this will prevent an apex variant
|
|
|
|
// from being created for the module.
|
2021-03-18 16:41:29 +01:00
|
|
|
//
|
|
|
|
// At the moment the sdk.sdkRequirementsMutator relies on the fact that the existing tags which
|
|
|
|
// implement this interface do not define dependencies onto members of an sdk_snapshot. If that
|
|
|
|
// changes then sdk.sdkRequirementsMutator will need fixing.
|
2020-04-07 16:25:44 +02:00
|
|
|
type ExcludeFromApexContentsTag interface {
|
|
|
|
blueprint.DependencyTag
|
|
|
|
|
|
|
|
// Method that differentiates this interface from others.
|
|
|
|
ExcludeFromApexContents()
|
|
|
|
}
|
|
|
|
|
2021-03-17 14:25:29 +01:00
|
|
|
// Marker interface that identifies dependencies that always requires an APEX variant to be created.
|
|
|
|
//
|
|
|
|
// It is possible for a dependency to require an apex variant but exclude the module from the APEX
|
|
|
|
// contents. See sdk.sdkMemberDependencyTag.
|
|
|
|
type AlwaysRequireApexVariantTag interface {
|
|
|
|
blueprint.DependencyTag
|
|
|
|
|
|
|
|
// Return true if this tag requires that the target dependency has an apex variant.
|
|
|
|
AlwaysRequireApexVariant() bool
|
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Marker interface that identifies dependencies that should inherit the DirectlyInAnyApex state
|
|
|
|
// from the parent to the child. For example, stubs libraries are marked as DirectlyInAnyApex if
|
|
|
|
// their implementation is in an apex.
|
2020-09-16 03:30:11 +02:00
|
|
|
type CopyDirectlyInAnyApexTag interface {
|
|
|
|
blueprint.DependencyTag
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Method that differentiates this interface from others.
|
2020-09-16 03:30:11 +02:00
|
|
|
CopyDirectlyInAnyApex()
|
|
|
|
}
|
|
|
|
|
2020-12-10 16:12:38 +01:00
|
|
|
// Interface that identifies dependencies to skip Apex dependency check
|
|
|
|
type SkipApexAllowedDependenciesCheck interface {
|
|
|
|
// Returns true to skip the Apex dependency check, which limits the allowed dependency in build.
|
|
|
|
SkipApexAllowedDependenciesCheck() bool
|
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// ApexModuleBase provides the default implementation for the ApexModule interface. APEX-aware
|
2018-10-02 17:38:19 +02:00
|
|
|
// modules are expected to include this struct and call InitApexModule().
|
|
|
|
type ApexModuleBase struct {
|
|
|
|
ApexProperties ApexProperties
|
|
|
|
|
|
|
|
canHaveApexVariants bool
|
2019-06-04 00:07:03 +02:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
apexInfos []ApexInfo
|
2020-12-08 11:34:30 +01:00
|
|
|
apexInfosLock sync.Mutex // protects apexInfos during parallel apexInfoMutator
|
2020-11-17 17:34:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Initializes ApexModuleBase struct. Not calling this (even when inheriting from ApexModuleBase)
|
|
|
|
// prevents the module from being mutated for apexBundle.
|
|
|
|
func InitApexModule(m ApexModule) {
|
|
|
|
base := m.apexModuleBase()
|
|
|
|
base.canHaveApexVariants = true
|
|
|
|
|
|
|
|
m.AddProperties(&base.ApexProperties)
|
2018-10-02 17:38:19 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Implements ApexModule
|
2018-10-02 17:38:19 +02:00
|
|
|
func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase {
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
2023-04-11 21:08:18 +02:00
|
|
|
var (
|
|
|
|
availableToPlatformList = []string{AvailableToPlatform}
|
|
|
|
)
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Implements ApexModule
|
2020-03-04 15:22:45 +01:00
|
|
|
func (m *ApexModuleBase) ApexAvailable() []string {
|
2023-04-11 21:08:18 +02:00
|
|
|
aa := m.ApexProperties.Apex_available
|
|
|
|
if len(aa) > 0 {
|
|
|
|
return aa
|
|
|
|
}
|
|
|
|
// Default is availability to platform
|
|
|
|
return CopyOf(availableToPlatformList)
|
2020-03-04 15:22:45 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Implements ApexModule
|
2020-07-22 08:17:19 +02:00
|
|
|
func (m *ApexModuleBase) BuildForApex(apex ApexInfo) {
|
2020-11-17 17:34:22 +01:00
|
|
|
m.apexInfosLock.Lock()
|
|
|
|
defer m.apexInfosLock.Unlock()
|
Record the actual APEXes that a module is part of.
Consider this case:
apex {
name: "com.android.foo",
native_libs: ["foo"],
}
override_apex {
name: "com.mycompany.android.foo",
base: "com.android.foo",
}
cc_library {
name: "foo",
}
There are two APEXes defined: "com.android.foo" and
"com.mycompany.android.foo" which is a copy of "com.android.foo" with
some properties overridden (e.g. signing keys).
The module "foo" is mutated into two variants by the apex mutator: the
platform variant and the apex variant. The former has the variation name
"" and the later has "apex<min_api_ver>" which usually is "apex10000".
Internally, the apex variant has an alias "com.android.foo".
ApexInfo.InApexVariants() returns only "com.android.foo" when called for
the module "foo".
We can see that the information that "foo" is also part of
"com.mycompany.android.foo" is completely lost. This is causing problem
when we compare the apex membership by their "soong module name", not
the "apex name". In the example above, the two modules have different
soone module names, but have the same apex name: "com.android.foo".
To fix that, this CL introduces a new field `InApexes` to the `ApexInfo`
struct. It has the actual name of the APEXes that the module is part of.
With the example above, `InApexes` is ["com.android.foo",
"com.mycompany.android.foo"].
Bug: 180325915
Test: m nothing
Test: m nothing on non-AOSP targets with ag/13740887 applied.
Change-Id: I4e7a7ac5495d2e622ba92a4358ed967e066c6c2e
2021-05-12 10:13:56 +02:00
|
|
|
for i, v := range m.apexInfos {
|
2020-08-13 20:24:56 +02:00
|
|
|
if v.ApexVariationName == apex.ApexVariationName {
|
Record the actual APEXes that a module is part of.
Consider this case:
apex {
name: "com.android.foo",
native_libs: ["foo"],
}
override_apex {
name: "com.mycompany.android.foo",
base: "com.android.foo",
}
cc_library {
name: "foo",
}
There are two APEXes defined: "com.android.foo" and
"com.mycompany.android.foo" which is a copy of "com.android.foo" with
some properties overridden (e.g. signing keys).
The module "foo" is mutated into two variants by the apex mutator: the
platform variant and the apex variant. The former has the variation name
"" and the later has "apex<min_api_ver>" which usually is "apex10000".
Internally, the apex variant has an alias "com.android.foo".
ApexInfo.InApexVariants() returns only "com.android.foo" when called for
the module "foo".
We can see that the information that "foo" is also part of
"com.mycompany.android.foo" is completely lost. This is causing problem
when we compare the apex membership by their "soong module name", not
the "apex name". In the example above, the two modules have different
soone module names, but have the same apex name: "com.android.foo".
To fix that, this CL introduces a new field `InApexes` to the `ApexInfo`
struct. It has the actual name of the APEXes that the module is part of.
With the example above, `InApexes` is ["com.android.foo",
"com.mycompany.android.foo"].
Bug: 180325915
Test: m nothing
Test: m nothing on non-AOSP targets with ag/13740887 applied.
Change-Id: I4e7a7ac5495d2e622ba92a4358ed967e066c6c2e
2021-05-12 10:13:56 +02:00
|
|
|
if len(apex.InApexModules) != 1 {
|
|
|
|
panic(fmt.Errorf("Newly created apexInfo must be for a single APEX"))
|
|
|
|
}
|
|
|
|
// Even when the ApexVariantNames are the same, the given ApexInfo might
|
|
|
|
// actually be for different APEX. This can happen when an APEX is
|
|
|
|
// overridden via override_apex. For example, there can be two apexes
|
|
|
|
// `com.android.foo` (from the `apex` module type) and
|
|
|
|
// `com.mycompany.android.foo` (from the `override_apex` module type), both
|
|
|
|
// of which has the same ApexVariantName `com.android.foo`. Add the apex
|
|
|
|
// name to the list so that it's not lost.
|
|
|
|
if !InList(apex.InApexModules[0], v.InApexModules) {
|
|
|
|
m.apexInfos[i].InApexModules = append(m.apexInfos[i].InApexModules, apex.InApexModules[0])
|
|
|
|
}
|
2020-07-22 08:17:19 +02:00
|
|
|
return
|
apexDepsMutator is a top-down mutator
apex { name: ["myapex"], native_shared_libs: ["libX", "libY"] }
cc_library { name: "libX", shared_libs: ["libY"] }
cc_library { name: "libY", shared_libs: ["libZ"], stubs: {...} }
apexDepsMutator was a bottom up mutator and it uses WalkDeps to traverse
the dependency tree rooted at myapex in a depth-first order. While
traversing the tree, if calls BuildForApex for a module that will be
part of the APEX.
libY is visited twice. Once via libX and once via myapex. If the visit
from libX was before the visit from myapex (since this is a depth-first
traversing), BuildForApex is not called for libY and its dependency
libZ, because libY provides a stub. And then when libY is again visited
via myapex, BuildForApex is correctly called for the module, but not for
its dependencies libZ because the paths from libY to libZ was already
visited.
As a result, the apex variant of libY has a dependency to the non-apex
variant of libZ.
Fixing the problem by changing the mutator a top-down one.
Bug: 148645937
Test: m
Change-Id: Ib2cb28852087c63a568b3fd036504e9261cf0782
2020-02-11 23:53:12 +01:00
|
|
|
}
|
Don't create unnecessary APEX variations
This change fixes a problem that APEX variations are created for the
modules that actually shouldn't built for any APEX. For example,
consider this case.
apex { name: "myapex", native_shared_libs: ["mylib"],}
cc_library { name: "mylib", shared_libs: ["libfoo#10"],}
cc_library { name: "libfoo",
shared_libs: ["libbar"],
stubs: { versions: ["10"], }, }
cc_library { name: "libbar", ...}
Before this change, both the stubs and non-stubs variations of libfoo
were mutated with apexMuator, which is incorrect for the non-stubs
varia; there is no dependency chain from the apex "myapex" to the
non-stubs variation, but to the stubs variation due to the #10 syntax.
This was happening becauses we used the name of the module to determine
whether it should be built for APEX or not. Both stubs and non-stubs
variations have the same module name "libfoo".
Fixing this issue by recording the list of APEX variations required
directly on the module. So, the stubs variation of libfoo has myapex in
its apex variations list, but the non-stubs variation doesn't, and thus
apexMutator does not pick up the non-stubs variation.
Test: m (apex_test updated and passing)
Test: cherry-pick ag/5747464 and m
Change-Id: I31e618626809a828a55fff513ef5f81f79637afa
2018-12-10 17:35:25 +01:00
|
|
|
}
|
2020-11-17 17:34:22 +01:00
|
|
|
m.apexInfos = append(m.apexInfos, apex)
|
Don't create unnecessary APEX variations
This change fixes a problem that APEX variations are created for the
modules that actually shouldn't built for any APEX. For example,
consider this case.
apex { name: "myapex", native_shared_libs: ["mylib"],}
cc_library { name: "mylib", shared_libs: ["libfoo#10"],}
cc_library { name: "libfoo",
shared_libs: ["libbar"],
stubs: { versions: ["10"], }, }
cc_library { name: "libbar", ...}
Before this change, both the stubs and non-stubs variations of libfoo
were mutated with apexMuator, which is incorrect for the non-stubs
varia; there is no dependency chain from the apex "myapex" to the
non-stubs variation, but to the stubs variation due to the #10 syntax.
This was happening becauses we used the name of the module to determine
whether it should be built for APEX or not. Both stubs and non-stubs
variations have the same module name "libfoo".
Fixing this issue by recording the list of APEX variations required
directly on the module. So, the stubs variation of libfoo has myapex in
its apex variations list, but the non-stubs variation doesn't, and thus
apexMutator does not pick up the non-stubs variation.
Test: m (apex_test updated and passing)
Test: cherry-pick ag/5747464 and m
Change-Id: I31e618626809a828a55fff513ef5f81f79637afa
2018-12-10 17:35:25 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Implements ApexModule
|
|
|
|
func (m *ApexModuleBase) InAnyApex() bool {
|
|
|
|
return m.ApexProperties.InAnyApex
|
|
|
|
}
|
|
|
|
|
|
|
|
// Implements ApexModule
|
2020-09-16 03:30:11 +02:00
|
|
|
func (m *ApexModuleBase) DirectlyInAnyApex() bool {
|
|
|
|
return m.ApexProperties.DirectlyInAnyApex
|
2018-10-02 17:38:19 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Implements ApexModule
|
2020-12-09 13:18:56 +01:00
|
|
|
func (m *ApexModuleBase) NotInPlatform() bool {
|
|
|
|
return m.ApexProperties.AnyVariantDirectlyInAnyApex || !m.AvailableFor(AvailableToPlatform)
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Implements ApexModule
|
2018-10-02 17:38:19 +02:00
|
|
|
func (m *ApexModuleBase) CanHaveApexVariants() bool {
|
|
|
|
return m.canHaveApexVariants
|
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Implements ApexModule
|
2018-10-02 17:38:19 +02:00
|
|
|
func (m *ApexModuleBase) IsInstallableToApex() bool {
|
2020-11-17 17:34:22 +01:00
|
|
|
// If needed, this will bel overridden by concrete types inheriting
|
|
|
|
// ApexModuleBase
|
2018-10-02 17:38:19 +02:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Implements ApexModule
|
|
|
|
func (m *ApexModuleBase) TestFor() []string {
|
|
|
|
// If needed, this will be overridden by concrete types inheriting
|
|
|
|
// ApexModuleBase
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-04-12 19:14:11 +02:00
|
|
|
// Returns the test apexes that this module is included in.
|
|
|
|
func (m *ApexModuleBase) TestApexes() []string {
|
|
|
|
return m.ApexProperties.TestApexes
|
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Implements ApexModule
|
|
|
|
func (m *ApexModuleBase) UniqueApexVariations() bool {
|
|
|
|
// If needed, this will bel overridden by concrete types inheriting
|
|
|
|
// ApexModuleBase
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// Implements ApexModule
|
|
|
|
func (m *ApexModuleBase) DepIsInSameApex(ctx BaseModuleContext, dep Module) bool {
|
|
|
|
// By default, if there is a dependency from A to B, we try to include both in the same
|
|
|
|
// APEX, unless B is explicitly from outside of the APEX (i.e. a stubs lib). Thus, returning
|
|
|
|
// true. This is overridden by some module types like apex.ApexBundle, cc.Module,
|
|
|
|
// java.Module, etc.
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
Add apex_available to control the availablity of a module to APEXes
apex_available property controls the availability of a module to APEXes.
For example, `apex_available: ["myapex", "otherapex"]` makes the module
available only to the two APEXes: myapex and otherapex, and nothing
else, even to the platform.
If the module is intended to be available to any APEX, then a pseudo
name "//apex_available:anyapex" can be used.
If the module is intended to be available to the platform, then another
pseudo name "//apex_available:platform" is used.
For now, if unspecified, this property defaults to ["//apex_available:platform",
"//apex_available:anyapex"], which means the module is available to everybody.
This will be reduced to ["//apex_available:platform"], when marking for
apex_available for existing modules are finished.
Bug: 139870423
Bug: 128708192
Test: m
Change-Id: Id4b233c3056c7858f984cbf9427cfac4118b2682
2019-09-30 09:04:35 +02:00
|
|
|
const (
|
2019-12-02 16:43:57 +01:00
|
|
|
AvailableToPlatform = "//apex_available:platform"
|
2020-03-06 13:30:13 +01:00
|
|
|
AvailableToAnyApex = "//apex_available:anyapex"
|
2020-07-29 02:37:46 +02:00
|
|
|
AvailableToGkiApex = "com.android.gki.*"
|
Add apex_available to control the availablity of a module to APEXes
apex_available property controls the availability of a module to APEXes.
For example, `apex_available: ["myapex", "otherapex"]` makes the module
available only to the two APEXes: myapex and otherapex, and nothing
else, even to the platform.
If the module is intended to be available to any APEX, then a pseudo
name "//apex_available:anyapex" can be used.
If the module is intended to be available to the platform, then another
pseudo name "//apex_available:platform" is used.
For now, if unspecified, this property defaults to ["//apex_available:platform",
"//apex_available:anyapex"], which means the module is available to everybody.
This will be reduced to ["//apex_available:platform"], when marking for
apex_available for existing modules are finished.
Bug: 139870423
Bug: 128708192
Test: m
Change-Id: Id4b233c3056c7858f984cbf9427cfac4118b2682
2019-09-30 09:04:35 +02:00
|
|
|
)
|
|
|
|
|
2023-04-12 21:05:49 +02:00
|
|
|
var (
|
|
|
|
AvailableToRecognziedWildcards = []string{
|
|
|
|
AvailableToPlatform,
|
|
|
|
AvailableToAnyApex,
|
|
|
|
AvailableToGkiApex,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// CheckAvailableForApex provides the default algorithm for checking the apex availability. When the
|
|
|
|
// availability is empty, it defaults to ["//apex_available:platform"] which means "available to the
|
|
|
|
// platform but not available to any APEX". When the list is not empty, `what` is matched against
|
|
|
|
// the list. If there is any matching element in the list, thus function returns true. The special
|
|
|
|
// availability "//apex_available:anyapex" matches with anything except for
|
|
|
|
// "//apex_available:platform".
|
2019-10-07 08:47:24 +02:00
|
|
|
func CheckAvailableForApex(what string, apex_available []string) bool {
|
|
|
|
if len(apex_available) == 0 {
|
2020-01-10 16:12:39 +01:00
|
|
|
return what == AvailableToPlatform
|
Add apex_available to control the availablity of a module to APEXes
apex_available property controls the availability of a module to APEXes.
For example, `apex_available: ["myapex", "otherapex"]` makes the module
available only to the two APEXes: myapex and otherapex, and nothing
else, even to the platform.
If the module is intended to be available to any APEX, then a pseudo
name "//apex_available:anyapex" can be used.
If the module is intended to be available to the platform, then another
pseudo name "//apex_available:platform" is used.
For now, if unspecified, this property defaults to ["//apex_available:platform",
"//apex_available:anyapex"], which means the module is available to everybody.
This will be reduced to ["//apex_available:platform"], when marking for
apex_available for existing modules are finished.
Bug: 139870423
Bug: 128708192
Test: m
Change-Id: Id4b233c3056c7858f984cbf9427cfac4118b2682
2019-09-30 09:04:35 +02:00
|
|
|
}
|
2019-10-07 08:47:24 +02:00
|
|
|
return InList(what, apex_available) ||
|
2020-07-29 02:37:46 +02:00
|
|
|
(what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available)) ||
|
|
|
|
(strings.HasPrefix(what, "com.android.gki.") && InList(AvailableToGkiApex, apex_available))
|
2019-10-07 08:47:24 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Implements ApexModule
|
2019-10-07 08:47:24 +02:00
|
|
|
func (m *ApexModuleBase) AvailableFor(what string) bool {
|
|
|
|
return CheckAvailableForApex(what, m.ApexProperties.Apex_available)
|
Add apex_available to control the availablity of a module to APEXes
apex_available property controls the availability of a module to APEXes.
For example, `apex_available: ["myapex", "otherapex"]` makes the module
available only to the two APEXes: myapex and otherapex, and nothing
else, even to the platform.
If the module is intended to be available to any APEX, then a pseudo
name "//apex_available:anyapex" can be used.
If the module is intended to be available to the platform, then another
pseudo name "//apex_available:platform" is used.
For now, if unspecified, this property defaults to ["//apex_available:platform",
"//apex_available:anyapex"], which means the module is available to everybody.
This will be reduced to ["//apex_available:platform"], when marking for
apex_available for existing modules are finished.
Bug: 139870423
Bug: 128708192
Test: m
Change-Id: Id4b233c3056c7858f984cbf9427cfac4118b2682
2019-09-30 09:04:35 +02:00
|
|
|
}
|
|
|
|
|
2021-05-12 17:16:51 +02:00
|
|
|
// Implements ApexModule
|
|
|
|
func (m *ApexModuleBase) AlwaysRequiresPlatformApexVariant() bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Implements ApexModule
|
mark platform un-availability
A module is marked unavailable for platform when 1) it does not have
"//apex_available:platform" in its apex_available property, or 2)
it depends on another module that is unavailable for platform.
In that case, LOCAL_NOT_AVAILABLE_FOR_PLATFORM is set to true for the
module in the Make world. Later, that flag is used to ensure that there
is no module with the flag is installed to the device.
The reason why this isn't entirely done in Soong is because Soong
doesn't know if a module will be installed to the device or not. To
explain this, let's have an example.
cc_test { name: "mytest", static_libs: ["libfoo"]}
cc_library_static { name: "libfoo", static_libs: ["libbar"]}
cc_library { name: "libbar", apex_available: ["com.android.xxx"]}
Here, libbar is not available for platform, but is used by libfoo which
is available for platform (apex_available defaults to
"//apex_available:platform"). libfoo is again depended on by mytest
which again is available for platform. The use of libbar should be
allowed in the context of test; we don't want to make libbar available
to platform just for the dependency from test because it will allow
non-test uses of the library as well.
Soong by itself can't tell whether libfoo and libbar are used only in the
context of a test. There could be another module depending them, e.g.,
cc_library_shared { name: "mylib", static_libs: ["libfoo"] }
can exist and it might be installed to the device, in which case
we really should trigger an error.
Since Make has the knowledge of what's installed and what's not,
the check should be done there.
Bug: 153073816
Test: m
Test: remove "//apex_available:platform" from libmdnssd (it is currently
installed to /system/lib), and check that `m system_image` fails
Change-Id: Ia304cc5f41f173229e8a154e90cea4dce46dcebe
2020-04-07 09:37:39 +02:00
|
|
|
func (m *ApexModuleBase) NotAvailableForPlatform() bool {
|
|
|
|
return m.ApexProperties.NotAvailableForPlatform
|
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Implements ApexModule
|
mark platform un-availability
A module is marked unavailable for platform when 1) it does not have
"//apex_available:platform" in its apex_available property, or 2)
it depends on another module that is unavailable for platform.
In that case, LOCAL_NOT_AVAILABLE_FOR_PLATFORM is set to true for the
module in the Make world. Later, that flag is used to ensure that there
is no module with the flag is installed to the device.
The reason why this isn't entirely done in Soong is because Soong
doesn't know if a module will be installed to the device or not. To
explain this, let's have an example.
cc_test { name: "mytest", static_libs: ["libfoo"]}
cc_library_static { name: "libfoo", static_libs: ["libbar"]}
cc_library { name: "libbar", apex_available: ["com.android.xxx"]}
Here, libbar is not available for platform, but is used by libfoo which
is available for platform (apex_available defaults to
"//apex_available:platform"). libfoo is again depended on by mytest
which again is available for platform. The use of libbar should be
allowed in the context of test; we don't want to make libbar available
to platform just for the dependency from test because it will allow
non-test uses of the library as well.
Soong by itself can't tell whether libfoo and libbar are used only in the
context of a test. There could be another module depending them, e.g.,
cc_library_shared { name: "mylib", static_libs: ["libfoo"] }
can exist and it might be installed to the device, in which case
we really should trigger an error.
Since Make has the knowledge of what's installed and what's not,
the check should be done there.
Bug: 153073816
Test: m
Test: remove "//apex_available:platform" from libmdnssd (it is currently
installed to /system/lib), and check that `m system_image` fails
Change-Id: Ia304cc5f41f173229e8a154e90cea4dce46dcebe
2020-04-07 09:37:39 +02:00
|
|
|
func (m *ApexModuleBase) SetNotAvailableForPlatform() {
|
|
|
|
m.ApexProperties.NotAvailableForPlatform = true
|
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// This function makes sure that the apex_available property is valid
|
Add apex_available to control the availablity of a module to APEXes
apex_available property controls the availability of a module to APEXes.
For example, `apex_available: ["myapex", "otherapex"]` makes the module
available only to the two APEXes: myapex and otherapex, and nothing
else, even to the platform.
If the module is intended to be available to any APEX, then a pseudo
name "//apex_available:anyapex" can be used.
If the module is intended to be available to the platform, then another
pseudo name "//apex_available:platform" is used.
For now, if unspecified, this property defaults to ["//apex_available:platform",
"//apex_available:anyapex"], which means the module is available to everybody.
This will be reduced to ["//apex_available:platform"], when marking for
apex_available for existing modules are finished.
Bug: 139870423
Bug: 128708192
Test: m
Change-Id: Id4b233c3056c7858f984cbf9427cfac4118b2682
2019-09-30 09:04:35 +02:00
|
|
|
func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
|
|
|
|
for _, n := range m.ApexProperties.Apex_available {
|
2020-07-29 02:37:46 +02:00
|
|
|
if n == AvailableToPlatform || n == AvailableToAnyApex || n == AvailableToGkiApex {
|
Add apex_available to control the availablity of a module to APEXes
apex_available property controls the availability of a module to APEXes.
For example, `apex_available: ["myapex", "otherapex"]` makes the module
available only to the two APEXes: myapex and otherapex, and nothing
else, even to the platform.
If the module is intended to be available to any APEX, then a pseudo
name "//apex_available:anyapex" can be used.
If the module is intended to be available to the platform, then another
pseudo name "//apex_available:platform" is used.
For now, if unspecified, this property defaults to ["//apex_available:platform",
"//apex_available:anyapex"], which means the module is available to everybody.
This will be reduced to ["//apex_available:platform"], when marking for
apex_available for existing modules are finished.
Bug: 139870423
Bug: 128708192
Test: m
Change-Id: Id4b233c3056c7858f984cbf9427cfac4118b2682
2019-09-30 09:04:35 +02:00
|
|
|
continue
|
|
|
|
}
|
2019-10-08 11:40:51 +02:00
|
|
|
if !mctx.OtherModuleExists(n) && !mctx.Config().AllowMissingDependencies() {
|
Add apex_available to control the availablity of a module to APEXes
apex_available property controls the availability of a module to APEXes.
For example, `apex_available: ["myapex", "otherapex"]` makes the module
available only to the two APEXes: myapex and otherapex, and nothing
else, even to the platform.
If the module is intended to be available to any APEX, then a pseudo
name "//apex_available:anyapex" can be used.
If the module is intended to be available to the platform, then another
pseudo name "//apex_available:platform" is used.
For now, if unspecified, this property defaults to ["//apex_available:platform",
"//apex_available:anyapex"], which means the module is available to everybody.
This will be reduced to ["//apex_available:platform"], when marking for
apex_available for existing modules are finished.
Bug: 139870423
Bug: 128708192
Test: m
Change-Id: Id4b233c3056c7858f984cbf9427cfac4118b2682
2019-09-30 09:04:35 +02:00
|
|
|
mctx.PropertyErrorf("apex_available", "%q is not a valid module name", n)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-25 02:25:06 +01:00
|
|
|
// AvailableToSameApexes returns true if the two modules are apex_available to
|
|
|
|
// exactly the same set of APEXes (and platform), i.e. if their apex_available
|
|
|
|
// properties have the same elements.
|
|
|
|
func AvailableToSameApexes(mod1, mod2 ApexModule) bool {
|
2023-04-25 20:03:54 +02:00
|
|
|
mod1ApexAvail := SortedUniqueStrings(mod1.apexModuleBase().ApexProperties.Apex_available)
|
|
|
|
mod2ApexAvail := SortedUniqueStrings(mod2.apexModuleBase().ApexProperties.Apex_available)
|
2021-03-25 02:25:06 +01:00
|
|
|
if len(mod1ApexAvail) != len(mod2ApexAvail) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for i, v := range mod1ApexAvail {
|
|
|
|
if v != mod2ApexAvail[i] {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2020-02-13 02:13:25 +01:00
|
|
|
type byApexName []ApexInfo
|
|
|
|
|
|
|
|
func (a byApexName) Len() int { return len(a) }
|
|
|
|
func (a byApexName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
2020-08-13 20:24:56 +02:00
|
|
|
func (a byApexName) Less(i, j int) bool { return a[i].ApexVariationName < a[j].ApexVariationName }
|
2020-02-13 02:13:25 +01:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// mergeApexVariations deduplicates apex variations that would build identically into a common
|
|
|
|
// variation. It returns the reduced list of variations and a list of aliases from the original
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
// variation names to the new variation names.
|
2020-11-17 17:34:22 +01:00
|
|
|
func mergeApexVariations(ctx PathContext, apexInfos []ApexInfo) (merged []ApexInfo, aliases [][2]string) {
|
|
|
|
sort.Sort(byApexName(apexInfos))
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
seen := make(map[string]int)
|
2020-11-17 17:34:22 +01:00
|
|
|
for _, apexInfo := range apexInfos {
|
2020-11-02 18:32:38 +01:00
|
|
|
// If this is for a prebuilt apex then use the actual name of the apex variation to prevent this
|
|
|
|
// from being merged with other ApexInfo. See Prebuilt.ApexInfoMutator for more information.
|
|
|
|
if apexInfo.ForPrebuiltApex {
|
|
|
|
merged = append(merged, apexInfo)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Merge the ApexInfo together. If a compatible ApexInfo exists then merge the information from
|
|
|
|
// this one into it, otherwise create a new merged ApexInfo from this one and save it away so
|
|
|
|
// other ApexInfo instances can be merged into it.
|
2021-05-12 10:13:56 +02:00
|
|
|
variantName := apexInfo.ApexVariationName
|
2020-07-23 07:32:17 +02:00
|
|
|
mergedName := apexInfo.mergedName(ctx)
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
if index, exists := seen[mergedName]; exists {
|
2020-11-17 17:34:22 +01:00
|
|
|
// Variants having the same mergedName are deduped
|
2021-05-12 10:13:56 +02:00
|
|
|
merged[index].InApexVariants = append(merged[index].InApexVariants, variantName)
|
Record the actual APEXes that a module is part of.
Consider this case:
apex {
name: "com.android.foo",
native_libs: ["foo"],
}
override_apex {
name: "com.mycompany.android.foo",
base: "com.android.foo",
}
cc_library {
name: "foo",
}
There are two APEXes defined: "com.android.foo" and
"com.mycompany.android.foo" which is a copy of "com.android.foo" with
some properties overridden (e.g. signing keys).
The module "foo" is mutated into two variants by the apex mutator: the
platform variant and the apex variant. The former has the variation name
"" and the later has "apex<min_api_ver>" which usually is "apex10000".
Internally, the apex variant has an alias "com.android.foo".
ApexInfo.InApexVariants() returns only "com.android.foo" when called for
the module "foo".
We can see that the information that "foo" is also part of
"com.mycompany.android.foo" is completely lost. This is causing problem
when we compare the apex membership by their "soong module name", not
the "apex name". In the example above, the two modules have different
soone module names, but have the same apex name: "com.android.foo".
To fix that, this CL introduces a new field `InApexes` to the `ApexInfo`
struct. It has the actual name of the APEXes that the module is part of.
With the example above, `InApexes` is ["com.android.foo",
"com.mycompany.android.foo"].
Bug: 180325915
Test: m nothing
Test: m nothing on non-AOSP targets with ag/13740887 applied.
Change-Id: I4e7a7ac5495d2e622ba92a4358ed967e066c6c2e
2021-05-12 10:13:56 +02:00
|
|
|
merged[index].InApexModules = append(merged[index].InApexModules, apexInfo.InApexModules...)
|
2020-09-16 03:30:11 +02:00
|
|
|
merged[index].ApexContents = append(merged[index].ApexContents, apexInfo.ApexContents...)
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable
|
2022-04-12 05:23:20 +02:00
|
|
|
// Platform APIs is allowed for this module only when all APEXes containing
|
|
|
|
// the module are with `use_platform_apis: true`.
|
|
|
|
merged[index].UsePlatformApis = merged[index].UsePlatformApis && apexInfo.UsePlatformApis
|
2023-04-12 19:14:11 +02:00
|
|
|
merged[index].TestApexes = append(merged[index].TestApexes, apexInfo.TestApexes...)
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
} else {
|
|
|
|
seen[mergedName] = len(merged)
|
2020-11-17 17:34:22 +01:00
|
|
|
apexInfo.ApexVariationName = mergedName
|
2021-05-12 10:13:56 +02:00
|
|
|
apexInfo.InApexVariants = CopyOf(apexInfo.InApexVariants)
|
Record the actual APEXes that a module is part of.
Consider this case:
apex {
name: "com.android.foo",
native_libs: ["foo"],
}
override_apex {
name: "com.mycompany.android.foo",
base: "com.android.foo",
}
cc_library {
name: "foo",
}
There are two APEXes defined: "com.android.foo" and
"com.mycompany.android.foo" which is a copy of "com.android.foo" with
some properties overridden (e.g. signing keys).
The module "foo" is mutated into two variants by the apex mutator: the
platform variant and the apex variant. The former has the variation name
"" and the later has "apex<min_api_ver>" which usually is "apex10000".
Internally, the apex variant has an alias "com.android.foo".
ApexInfo.InApexVariants() returns only "com.android.foo" when called for
the module "foo".
We can see that the information that "foo" is also part of
"com.mycompany.android.foo" is completely lost. This is causing problem
when we compare the apex membership by their "soong module name", not
the "apex name". In the example above, the two modules have different
soone module names, but have the same apex name: "com.android.foo".
To fix that, this CL introduces a new field `InApexes` to the `ApexInfo`
struct. It has the actual name of the APEXes that the module is part of.
With the example above, `InApexes` is ["com.android.foo",
"com.mycompany.android.foo"].
Bug: 180325915
Test: m nothing
Test: m nothing on non-AOSP targets with ag/13740887 applied.
Change-Id: I4e7a7ac5495d2e622ba92a4358ed967e066c6c2e
2021-05-12 10:13:56 +02:00
|
|
|
apexInfo.InApexModules = CopyOf(apexInfo.InApexModules)
|
2020-09-16 03:30:11 +02:00
|
|
|
apexInfo.ApexContents = append([]*ApexContents(nil), apexInfo.ApexContents...)
|
2023-04-12 19:14:11 +02:00
|
|
|
apexInfo.TestApexes = CopyOf(apexInfo.TestApexes)
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
merged = append(merged, apexInfo)
|
|
|
|
}
|
2021-05-12 10:13:56 +02:00
|
|
|
aliases = append(aliases, [2]string{variantName, mergedName})
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
}
|
|
|
|
return merged, aliases
|
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// CreateApexVariations mutates a given module into multiple apex variants each of which is for an
|
|
|
|
// apexBundle (and/or the platform) where the module is part of.
|
2020-09-16 03:30:11 +02:00
|
|
|
func CreateApexVariations(mctx BottomUpMutatorContext, module ApexModule) []Module {
|
|
|
|
base := module.apexModuleBase()
|
apex_available tracks static dependencies
This change fixes a bug that apex_available is not enforced for static
dependencies. For example, a module with 'apex_available:
["//apex_available:platform"]' was able to be statically linked to any
APEX. This was happening because the check was done on the modules that
are actually installed to an APEX. Static dependencies of the modules
were not counted as they are not installed to the APEX as files.
Fixing this bug by doing the check by traversing the tree in the method
checkApexAvailability.
This change includes a few number of related changes:
1) DepIsInSameApex implementation for cc.Module was changed as well.
Previuosly, it returned false only when the dependency is actually a
stub variant of a lib. Now, it returns false when the dependency has one
or more stub variants. To understand why, we need to recall that when
there is a dependency to a lib having stubs, we actually create two
dependencies: to the non-stub variant and to the stub variant during the
DepsMutator phase. And later in the build action generation phase, we
choose one of them depending on the context. Also recall that an APEX
variant is created only when DepIsInSameApex returns true. Given these,
with the previous implementatin of DepIsInSameApex, we did create apex
variants of the non-stub variant of the dependency, while not creating
the apex variant for the stub variant. This is not right; we needlessly
created the apex variant. The extra apex variant has caused no harm so
far, but since the apex_available check became more correct, it actually
breaks the build. To fix the issue, we stop creating the APEX variant
both for non-stub and stub variants.
2) platform variant is created regardless of the apex_available value.
This is required for the case when a library X that provides stub is in
an APEX A and is configured to be available only for A. In that case,
libs in other APEX can't use the stub library since the stub library is
mutated only for apex A. By creating the platform variant for the stub
library, it can be used from outside as the default dependency variation
is set to the platform variant when creating the APEX variations.
3) The ApexAvailableWhitelist is added with the dependencies that were
revealed with this change.
Exempt-From-Owner-Approval: cherry-pick from internal
Bug: 147671264
Test: m
Merged-In: Iaedc05494085ff4e8af227a6392bdd0c338b8e6e
(cherry picked from commit fa89944c79f19552e906b41fd03a4981903eee7e)
Change-Id: Iaedc05494085ff4e8af227a6392bdd0c338b8e6e
2020-01-30 18:49:53 +01:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Shortcut
|
|
|
|
if len(base.apexInfos) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
2018-12-26 08:32:21 +01:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Do some validity checks.
|
|
|
|
// TODO(jiyong): is this the right place?
|
|
|
|
base.checkApexAvailableProperty(mctx)
|
apex_available tracks static dependencies
This change fixes a bug that apex_available is not enforced for static
dependencies. For example, a module with 'apex_available:
["//apex_available:platform"]' was able to be statically linked to any
APEX. This was happening because the check was done on the modules that
are actually installed to an APEX. Static dependencies of the modules
were not counted as they are not installed to the APEX as files.
Fixing this bug by doing the check by traversing the tree in the method
checkApexAvailability.
This change includes a few number of related changes:
1) DepIsInSameApex implementation for cc.Module was changed as well.
Previuosly, it returned false only when the dependency is actually a
stub variant of a lib. Now, it returns false when the dependency has one
or more stub variants. To understand why, we need to recall that when
there is a dependency to a lib having stubs, we actually create two
dependencies: to the non-stub variant and to the stub variant during the
DepsMutator phase. And later in the build action generation phase, we
choose one of them depending on the context. Also recall that an APEX
variant is created only when DepIsInSameApex returns true. Given these,
with the previous implementatin of DepIsInSameApex, we did create apex
variants of the non-stub variant of the dependency, while not creating
the apex variant for the stub variant. This is not right; we needlessly
created the apex variant. The extra apex variant has caused no harm so
far, but since the apex_available check became more correct, it actually
breaks the build. To fix the issue, we stop creating the APEX variant
both for non-stub and stub variants.
2) platform variant is created regardless of the apex_available value.
This is required for the case when a library X that provides stub is in
an APEX A and is configured to be available only for A. In that case,
libs in other APEX can't use the stub library since the stub library is
mutated only for apex A. By creating the platform variant for the stub
library, it can be used from outside as the default dependency variation
is set to the platform variant when creating the APEX variations.
3) The ApexAvailableWhitelist is added with the dependencies that were
revealed with this change.
Exempt-From-Owner-Approval: cherry-pick from internal
Bug: 147671264
Test: m
Merged-In: Iaedc05494085ff4e8af227a6392bdd0c338b8e6e
(cherry picked from commit fa89944c79f19552e906b41fd03a4981903eee7e)
Change-Id: Iaedc05494085ff4e8af227a6392bdd0c338b8e6e
2020-01-30 18:49:53 +01:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
var apexInfos []ApexInfo
|
|
|
|
var aliases [][2]string
|
|
|
|
if !mctx.Module().(ApexModule).UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
|
|
|
|
apexInfos, aliases = mergeApexVariations(mctx, base.apexInfos)
|
|
|
|
} else {
|
|
|
|
apexInfos = base.apexInfos
|
|
|
|
}
|
2020-12-08 11:34:30 +01:00
|
|
|
// base.apexInfos is only needed to propagate the list of apexes from apexInfoMutator to
|
2020-11-17 17:34:22 +01:00
|
|
|
// apexMutator. It is no longer accurate after mergeApexVariations, and won't be copied to
|
|
|
|
// all but the first created variant. Clear it so it doesn't accidentally get used later.
|
|
|
|
base.apexInfos = nil
|
|
|
|
sort.Sort(byApexName(apexInfos))
|
|
|
|
|
|
|
|
var inApex ApexMembership
|
|
|
|
for _, a := range apexInfos {
|
|
|
|
for _, apexContents := range a.ApexContents {
|
|
|
|
inApex = inApex.merge(apexContents.contents[mctx.ModuleName()])
|
2020-09-16 03:30:11 +02:00
|
|
|
}
|
2020-11-17 17:34:22 +01:00
|
|
|
}
|
|
|
|
base.ApexProperties.InAnyApex = true
|
|
|
|
base.ApexProperties.DirectlyInAnyApex = inApex == directlyInApex
|
2020-09-16 03:30:11 +02:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
defaultVariation := ""
|
|
|
|
mctx.SetDefaultDependencyVariation(&defaultVariation)
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
variations := []string{defaultVariation}
|
2023-04-12 19:14:11 +02:00
|
|
|
testApexes := []string{}
|
2020-11-17 17:34:22 +01:00
|
|
|
for _, a := range apexInfos {
|
|
|
|
variations = append(variations, a.ApexVariationName)
|
2023-04-12 19:14:11 +02:00
|
|
|
testApexes = append(testApexes, a.TestApexes...)
|
2020-11-17 17:34:22 +01:00
|
|
|
}
|
|
|
|
modules := mctx.CreateVariations(variations...)
|
|
|
|
for i, mod := range modules {
|
|
|
|
platformVariation := i == 0
|
|
|
|
if platformVariation && !mctx.Host() && !mod.(ApexModule).AvailableFor(AvailableToPlatform) {
|
|
|
|
// Do not install the module for platform, but still allow it to output
|
|
|
|
// uninstallable AndroidMk entries in certain cases when they have side
|
|
|
|
// effects. TODO(jiyong): move this routine to somewhere else
|
2023-03-20 12:05:16 +01:00
|
|
|
mod.MakeUninstallable()
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
}
|
2020-11-17 17:34:22 +01:00
|
|
|
if !platformVariation {
|
|
|
|
mctx.SetVariationProvider(mod, ApexInfoProvider, apexInfos[i-1])
|
|
|
|
}
|
2023-04-12 19:14:11 +02:00
|
|
|
// Set the value of TestApexes in every single apex variant.
|
|
|
|
// This allows each apex variant to be aware of the test apexes in the user provided apex_available.
|
|
|
|
mod.(ApexModule).apexModuleBase().ApexProperties.TestApexes = testApexes
|
2020-11-17 17:34:22 +01:00
|
|
|
}
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
for _, alias := range aliases {
|
|
|
|
mctx.CreateAliasVariation(alias[0], alias[1])
|
Don't create unnecessary APEX variations
This change fixes a problem that APEX variations are created for the
modules that actually shouldn't built for any APEX. For example,
consider this case.
apex { name: "myapex", native_shared_libs: ["mylib"],}
cc_library { name: "mylib", shared_libs: ["libfoo#10"],}
cc_library { name: "libfoo",
shared_libs: ["libbar"],
stubs: { versions: ["10"], }, }
cc_library { name: "libbar", ...}
Before this change, both the stubs and non-stubs variations of libfoo
were mutated with apexMuator, which is incorrect for the non-stubs
varia; there is no dependency chain from the apex "myapex" to the
non-stubs variation, but to the stubs variation due to the #10 syntax.
This was happening becauses we used the name of the module to determine
whether it should be built for APEX or not. Both stubs and non-stubs
variations have the same module name "libfoo".
Fixing this issue by recording the list of APEX variations required
directly on the module. So, the stubs variation of libfoo has myapex in
its apex variations list, but the non-stubs variation doesn't, and thus
apexMutator does not pick up the non-stubs variation.
Test: m (apex_test updated and passing)
Test: cherry-pick ag/5747464 and m
Change-Id: I31e618626809a828a55fff513ef5f81f79637afa
2018-12-10 17:35:25 +01:00
|
|
|
}
|
2020-11-17 17:34:22 +01:00
|
|
|
|
|
|
|
return modules
|
Don't create unnecessary APEX variations
This change fixes a problem that APEX variations are created for the
modules that actually shouldn't built for any APEX. For example,
consider this case.
apex { name: "myapex", native_shared_libs: ["mylib"],}
cc_library { name: "mylib", shared_libs: ["libfoo#10"],}
cc_library { name: "libfoo",
shared_libs: ["libbar"],
stubs: { versions: ["10"], }, }
cc_library { name: "libbar", ...}
Before this change, both the stubs and non-stubs variations of libfoo
were mutated with apexMuator, which is incorrect for the non-stubs
varia; there is no dependency chain from the apex "myapex" to the
non-stubs variation, but to the stubs variation due to the #10 syntax.
This was happening becauses we used the name of the module to determine
whether it should be built for APEX or not. Both stubs and non-stubs
variations have the same module name "libfoo".
Fixing this issue by recording the list of APEX variations required
directly on the module. So, the stubs variation of libfoo has myapex in
its apex variations list, but the non-stubs variation doesn't, and thus
apexMutator does not pick up the non-stubs variation.
Test: m (apex_test updated and passing)
Test: cherry-pick ag/5747464 and m
Change-Id: I31e618626809a828a55fff513ef5f81f79637afa
2018-12-10 17:35:25 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// UpdateUniqueApexVariationsForDeps sets UniqueApexVariationsForDeps if any dependencies that are
|
|
|
|
// in the same APEX have unique APEX variations so that the module can link against the right
|
|
|
|
// variant.
|
2020-09-16 03:30:11 +02:00
|
|
|
func UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext, am ApexModule) {
|
2021-05-12 10:13:56 +02:00
|
|
|
// anyInSameApex returns true if the two ApexInfo lists contain any values in an
|
|
|
|
// InApexVariants list in common. It is used instead of DepIsInSameApex because it needs to
|
|
|
|
// determine if the dep is in the same APEX due to being directly included, not only if it
|
|
|
|
// is included _because_ it is a dependency.
|
2020-09-16 03:30:11 +02:00
|
|
|
anyInSameApex := func(a, b []ApexInfo) bool {
|
|
|
|
collectApexes := func(infos []ApexInfo) []string {
|
|
|
|
var ret []string
|
|
|
|
for _, info := range infos {
|
2021-05-12 10:13:56 +02:00
|
|
|
ret = append(ret, info.InApexVariants...)
|
2020-09-16 03:30:11 +02:00
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
Don't create unnecessary APEX variations
This change fixes a problem that APEX variations are created for the
modules that actually shouldn't built for any APEX. For example,
consider this case.
apex { name: "myapex", native_shared_libs: ["mylib"],}
cc_library { name: "mylib", shared_libs: ["libfoo#10"],}
cc_library { name: "libfoo",
shared_libs: ["libbar"],
stubs: { versions: ["10"], }, }
cc_library { name: "libbar", ...}
Before this change, both the stubs and non-stubs variations of libfoo
were mutated with apexMuator, which is incorrect for the non-stubs
varia; there is no dependency chain from the apex "myapex" to the
non-stubs variation, but to the stubs variation due to the #10 syntax.
This was happening becauses we used the name of the module to determine
whether it should be built for APEX or not. Both stubs and non-stubs
variations have the same module name "libfoo".
Fixing this issue by recording the list of APEX variations required
directly on the module. So, the stubs variation of libfoo has myapex in
its apex variations list, but the non-stubs variation doesn't, and thus
apexMutator does not pick up the non-stubs variation.
Test: m (apex_test updated and passing)
Test: cherry-pick ag/5747464 and m
Change-Id: I31e618626809a828a55fff513ef5f81f79637afa
2018-12-10 17:35:25 +01:00
|
|
|
|
2020-09-16 03:30:11 +02:00
|
|
|
aApexes := collectApexes(a)
|
|
|
|
bApexes := collectApexes(b)
|
|
|
|
sort.Strings(bApexes)
|
|
|
|
for _, aApex := range aApexes {
|
|
|
|
index := sort.SearchStrings(bApexes, aApex)
|
|
|
|
if index < len(bApexes) && bApexes[index] == aApex {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
}
|
2020-09-16 03:30:11 +02:00
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// If any of the dependencies requires unique apex variations, so does this module.
|
2020-09-16 03:30:11 +02:00
|
|
|
mctx.VisitDirectDeps(func(dep Module) {
|
|
|
|
if depApexModule, ok := dep.(ApexModule); ok {
|
2020-11-17 17:34:22 +01:00
|
|
|
if anyInSameApex(depApexModule.apexModuleBase().apexInfos, am.apexModuleBase().apexInfos) &&
|
2020-09-16 03:30:11 +02:00
|
|
|
(depApexModule.UniqueApexVariations() ||
|
|
|
|
depApexModule.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps) {
|
|
|
|
am.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
Stubs variant is used when building for APEX
When a native module is built for an APEX and is depending on a native
library having stubs (i.e. stubs.versions property is set), the stubs
variant is used unless the dependent lib is directly included in the
same APEX with the depending module.
Example:
apex {
name: "myapex",
native_shared_libs: ["libX", "libY"],
}
cc_library {
name: "libX",
shared_libs: ["libY", "libZ"],
}
cc_library {
name: "libY",
stubs: { versions: ["1", "2"], },
}
cc_library {
name: "libZ",
stubs: { versions: ["1", "2"], },
}
In this case, libX is linking to the impl variant of libY (that provides
private APIs) while libY is linking to the version 2 stubs of libZ. This is
because libY is directly included in the same apex via
native_shared_libs property, but libZ isn't.
Bug: 112672359
Test: apex_test added
Change-Id: If9871b70dc74a06bd828dd4cd1aeebd2e68b837c
2018-11-18 10:02:45 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// UpdateDirectlyInAnyApex uses the final module to store if any variant of this module is directly
|
|
|
|
// in any APEX, and then copies the final value to all the modules. It also copies the
|
|
|
|
// DirectlyInAnyApex value to any direct dependencies with a CopyDirectlyInAnyApexTag dependency
|
|
|
|
// tag.
|
2020-09-16 03:30:11 +02:00
|
|
|
func UpdateDirectlyInAnyApex(mctx BottomUpMutatorContext, am ApexModule) {
|
|
|
|
base := am.apexModuleBase()
|
|
|
|
// Copy DirectlyInAnyApex and InAnyApex from any direct dependencies with a
|
|
|
|
// CopyDirectlyInAnyApexTag dependency tag.
|
|
|
|
mctx.VisitDirectDeps(func(dep Module) {
|
|
|
|
if _, ok := mctx.OtherModuleDependencyTag(dep).(CopyDirectlyInAnyApexTag); ok {
|
|
|
|
depBase := dep.(ApexModule).apexModuleBase()
|
2021-05-26 03:12:57 +02:00
|
|
|
depBase.ApexProperties.DirectlyInAnyApex = base.ApexProperties.DirectlyInAnyApex
|
|
|
|
depBase.ApexProperties.InAnyApex = base.ApexProperties.InAnyApex
|
2020-09-16 03:30:11 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
if base.ApexProperties.DirectlyInAnyApex {
|
|
|
|
// Variants of a module are always visited sequentially in order, so it is safe to
|
2020-11-17 17:34:22 +01:00
|
|
|
// write to another variant of this module. For a BottomUpMutator the
|
|
|
|
// PrimaryModule() is visited first and FinalModule() is visited last.
|
2020-09-16 03:30:11 +02:00
|
|
|
mctx.FinalModule().(ApexModule).apexModuleBase().ApexProperties.AnyVariantDirectlyInAnyApex = true
|
2019-12-17 04:47:13 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// If this is the FinalModule (last visited module) copy
|
|
|
|
// AnyVariantDirectlyInAnyApex to all the other variants
|
2020-09-16 03:30:11 +02:00
|
|
|
if am == mctx.FinalModule().(ApexModule) {
|
|
|
|
mctx.VisitAllModuleVariants(func(variant Module) {
|
|
|
|
variant.(ApexModule).apexModuleBase().ApexProperties.AnyVariantDirectlyInAnyApex =
|
|
|
|
base.ApexProperties.AnyVariantDirectlyInAnyApex
|
|
|
|
})
|
Stubs variant is used when building for APEX
When a native module is built for an APEX and is depending on a native
library having stubs (i.e. stubs.versions property is set), the stubs
variant is used unless the dependent lib is directly included in the
same APEX with the depending module.
Example:
apex {
name: "myapex",
native_shared_libs: ["libX", "libY"],
}
cc_library {
name: "libX",
shared_libs: ["libY", "libZ"],
}
cc_library {
name: "libY",
stubs: { versions: ["1", "2"], },
}
cc_library {
name: "libZ",
stubs: { versions: ["1", "2"], },
}
In this case, libX is linking to the impl variant of libY (that provides
private APIs) while libY is linking to the version 2 stubs of libZ. This is
because libY is directly included in the same apex via
native_shared_libs property, but libZ isn't.
Bug: 112672359
Test: apex_test added
Change-Id: If9871b70dc74a06bd828dd4cd1aeebd2e68b837c
2018-11-18 10:02:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// ApexMembership tells how a module became part of an APEX.
|
2020-09-16 03:30:11 +02:00
|
|
|
type ApexMembership int
|
|
|
|
|
|
|
|
const (
|
|
|
|
notInApex ApexMembership = 0
|
|
|
|
indirectlyInApex = iota
|
|
|
|
directlyInApex
|
|
|
|
)
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// ApexContents gives an information about member modules of an apexBundle. Each apexBundle has an
|
|
|
|
// apexContents, and modules in that apex have a provider containing the apexContents of each
|
|
|
|
// apexBundle they are part of.
|
2020-09-16 03:30:11 +02:00
|
|
|
type ApexContents struct {
|
2020-11-02 18:32:38 +01:00
|
|
|
// map from a module name to its membership in this apexBundle
|
2020-09-16 03:30:11 +02:00
|
|
|
contents map[string]ApexMembership
|
|
|
|
}
|
|
|
|
|
2020-11-02 18:32:38 +01:00
|
|
|
// NewApexContents creates and initializes an ApexContents that is suitable
|
|
|
|
// for use with an apex module.
|
2022-08-16 19:27:33 +02:00
|
|
|
// - contents is a map from a module name to information about its membership within
|
|
|
|
// the apex.
|
2020-11-17 17:34:22 +01:00
|
|
|
func NewApexContents(contents map[string]ApexMembership) *ApexContents {
|
2020-09-16 03:30:11 +02:00
|
|
|
return &ApexContents{
|
|
|
|
contents: contents,
|
Reland: Deduplicate APEX variants that would build identically
APEX variants that share the same SDK version and updatability
almost always use identical command line arguments to build but
with different intermediates directories. This causes unnecessary
build time and disk space for duplicated work.
Deduplicate APEX variants that would build identically. Create
aliases from the per-APEX variations to the new shared variations
so that the APEX modules can continue to depend on them via the
APEX name as the variation.
This has one significant change in behavior. Before this change,
if an APEX had two libraries in its direct dependencies and one
of those libraries depended on the other, and the second library
had stubs, then the first library would depend on the implementation
of the second library and not the stubs. After this change, if
the first library is also present in a second APEX but the second
library is not, then the common variant shared between the two
APEXes would use the stubs, not the implementation.
In a correctly configured set of build rules this change will
be irrelevant, because if the compilation worked for the second
APEX using stubs then it will work for the common variant using
stubs. However, if an incorrect change to the build rules is
made this could lead to confusing errors, as a previously-working
common variant could suddenly stop building when a module is added
to a new APEX without its dependencies that require implementation
APIs to compile.
This change reduces the number of modules in an AOSP arm64-userdebug
build by 3% (52242 to 50586), reduces the number of variants of the
libcutils module from 74 to 53, and reduces the number of variants
of the massive libart[d] modules from 44 to 32.
This relands I0529837476a253c32b3dfb98dcccf107427c742c with a fix
to always mark permissions XML files of java_sdk_library modules as
unique per apex since they contain the APEX filename, and a fix
to UpdateUniqueApexVariationsForDeps to check ApexInfo.InApexes
instead of DepIsInSameApex to check if two modules are in the same
apex to account for a module that depends on another in a way that
doesn't normally include the dependency in the APEX (e.g. a libs
property), but the dependency is directly included in the APEX.
Bug: 164216768
Test: go test ./build/soong/apex/...
Change-Id: I2ae170601f764e5b88d0be2e0e6adc84e3a4d9cc
2020-08-11 21:17:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Updates an existing membership by adding a new direct (or indirect) membership
|
2020-09-16 03:30:11 +02:00
|
|
|
func (i ApexMembership) Add(direct bool) ApexMembership {
|
|
|
|
if direct || i == directlyInApex {
|
|
|
|
return directlyInApex
|
|
|
|
}
|
|
|
|
return indirectlyInApex
|
2019-01-15 20:53:23 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Merges two membership into one. Merging is needed because a module can be a part of an apexBundle
|
|
|
|
// in many different paths. For example, it could be dependend on by the apexBundle directly, but at
|
|
|
|
// the same time, there might be an indirect dependency to the module. In that case, the more
|
|
|
|
// specific dependency (the direct one) is chosen.
|
2020-09-16 03:30:11 +02:00
|
|
|
func (i ApexMembership) merge(other ApexMembership) ApexMembership {
|
|
|
|
if other == directlyInApex || i == directlyInApex {
|
|
|
|
return directlyInApex
|
2019-01-15 20:53:23 +01:00
|
|
|
}
|
2020-09-16 03:30:11 +02:00
|
|
|
|
|
|
|
if other == indirectlyInApex || i == indirectlyInApex {
|
|
|
|
return indirectlyInApex
|
Stubs variant is used when building for APEX
When a native module is built for an APEX and is depending on a native
library having stubs (i.e. stubs.versions property is set), the stubs
variant is used unless the dependent lib is directly included in the
same APEX with the depending module.
Example:
apex {
name: "myapex",
native_shared_libs: ["libX", "libY"],
}
cc_library {
name: "libX",
shared_libs: ["libY", "libZ"],
}
cc_library {
name: "libY",
stubs: { versions: ["1", "2"], },
}
cc_library {
name: "libZ",
stubs: { versions: ["1", "2"], },
}
In this case, libX is linking to the impl variant of libY (that provides
private APIs) while libY is linking to the version 2 stubs of libZ. This is
because libY is directly included in the same apex via
native_shared_libs property, but libZ isn't.
Bug: 112672359
Test: apex_test added
Change-Id: If9871b70dc74a06bd828dd4cd1aeebd2e68b837c
2018-11-18 10:02:45 +01:00
|
|
|
}
|
2020-09-16 03:30:11 +02:00
|
|
|
return notInApex
|
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Tests whether a module named moduleName is directly included in the apexBundle where this
|
|
|
|
// ApexContents is tagged.
|
|
|
|
func (ac *ApexContents) DirectlyInApex(moduleName string) bool {
|
|
|
|
return ac.contents[moduleName] == directlyInApex
|
Stubs variant is used when building for APEX
When a native module is built for an APEX and is depending on a native
library having stubs (i.e. stubs.versions property is set), the stubs
variant is used unless the dependent lib is directly included in the
same APEX with the depending module.
Example:
apex {
name: "myapex",
native_shared_libs: ["libX", "libY"],
}
cc_library {
name: "libX",
shared_libs: ["libY", "libZ"],
}
cc_library {
name: "libY",
stubs: { versions: ["1", "2"], },
}
cc_library {
name: "libZ",
stubs: { versions: ["1", "2"], },
}
In this case, libX is linking to the impl variant of libY (that provides
private APIs) while libY is linking to the version 2 stubs of libZ. This is
because libY is directly included in the same apex via
native_shared_libs property, but libZ isn't.
Bug: 112672359
Test: apex_test added
Change-Id: If9871b70dc74a06bd828dd4cd1aeebd2e68b837c
2018-11-18 10:02:45 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Tests whether a module named moduleName is included in the apexBundle where this ApexContent is
|
|
|
|
// tagged.
|
|
|
|
func (ac *ApexContents) InApex(moduleName string) bool {
|
|
|
|
return ac.contents[moduleName] != notInApex
|
Don't create unnecessary APEX variations
This change fixes a problem that APEX variations are created for the
modules that actually shouldn't built for any APEX. For example,
consider this case.
apex { name: "myapex", native_shared_libs: ["mylib"],}
cc_library { name: "mylib", shared_libs: ["libfoo#10"],}
cc_library { name: "libfoo",
shared_libs: ["libbar"],
stubs: { versions: ["10"], }, }
cc_library { name: "libbar", ...}
Before this change, both the stubs and non-stubs variations of libfoo
were mutated with apexMuator, which is incorrect for the non-stubs
varia; there is no dependency chain from the apex "myapex" to the
non-stubs variation, but to the stubs variation due to the #10 syntax.
This was happening becauses we used the name of the module to determine
whether it should be built for APEX or not. Both stubs and non-stubs
variations have the same module name "libfoo".
Fixing this issue by recording the list of APEX variations required
directly on the module. So, the stubs variation of libfoo has myapex in
its apex variations list, but the non-stubs variation doesn't, and thus
apexMutator does not pick up the non-stubs variation.
Test: m (apex_test updated and passing)
Test: cherry-pick ag/5747464 and m
Change-Id: I31e618626809a828a55fff513ef5f81f79637afa
2018-12-10 17:35:25 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// Tests whether a module named moduleName is directly depended on by all APEXes in an ApexInfo.
|
2020-09-16 03:30:11 +02:00
|
|
|
func DirectlyInAllApexes(apexInfo ApexInfo, moduleName string) bool {
|
|
|
|
for _, contents := range apexInfo.ApexContents {
|
|
|
|
if !contents.DirectlyInApex(moduleName) {
|
|
|
|
return false
|
Don't create unnecessary APEX variations
This change fixes a problem that APEX variations are created for the
modules that actually shouldn't built for any APEX. For example,
consider this case.
apex { name: "myapex", native_shared_libs: ["mylib"],}
cc_library { name: "mylib", shared_libs: ["libfoo#10"],}
cc_library { name: "libfoo",
shared_libs: ["libbar"],
stubs: { versions: ["10"], }, }
cc_library { name: "libbar", ...}
Before this change, both the stubs and non-stubs variations of libfoo
were mutated with apexMuator, which is incorrect for the non-stubs
varia; there is no dependency chain from the apex "myapex" to the
non-stubs variation, but to the stubs variation due to the #10 syntax.
This was happening becauses we used the name of the module to determine
whether it should be built for APEX or not. Both stubs and non-stubs
variations have the same module name "libfoo".
Fixing this issue by recording the list of APEX variations required
directly on the module. So, the stubs variation of libfoo has myapex in
its apex variations list, but the non-stubs variation doesn't, and thus
apexMutator does not pick up the non-stubs variation.
Test: m (apex_test updated and passing)
Test: cherry-pick ag/5747464 and m
Change-Id: I31e618626809a828a55fff513ef5f81f79637afa
2018-12-10 17:35:25 +01:00
|
|
|
}
|
|
|
|
}
|
2020-09-16 03:30:11 +02:00
|
|
|
return true
|
2018-12-07 15:08:36 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//Below are routines for extra safety checks.
|
|
|
|
//
|
|
|
|
// BuildDepsInfoLists is to flatten the dependency graph for an apexBundle into a text file
|
|
|
|
// (actually two in slightly different formats). The files are mostly for debugging, for example to
|
|
|
|
// see why a certain module is included in an APEX via which dependency path.
|
|
|
|
//
|
|
|
|
// CheckMinSdkVersion is to make sure that all modules in an apexBundle satisfy the min_sdk_version
|
|
|
|
// requirement of the apexBundle.
|
2020-04-27 18:08:37 +02:00
|
|
|
|
|
|
|
// A dependency info for a single ApexModule, either direct or transitive.
|
|
|
|
type ApexModuleDepInfo struct {
|
|
|
|
// Name of the dependency
|
|
|
|
To string
|
|
|
|
// List of dependencies To belongs to. Includes APEX itself, if a direct dependency.
|
|
|
|
From []string
|
|
|
|
// Whether the dependency belongs to the final compiled APEX.
|
|
|
|
IsExternal bool
|
2020-04-27 19:53:18 +02:00
|
|
|
// min_sdk_version of the ApexModule
|
|
|
|
MinSdkVersion string
|
2020-04-27 18:08:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// A map of a dependency name to its ApexModuleDepInfo
|
|
|
|
type DepNameToDepInfoMap map[string]ApexModuleDepInfo
|
|
|
|
|
|
|
|
type ApexBundleDepsInfo struct {
|
2020-05-14 00:44:03 +02:00
|
|
|
flatListPath OutputPath
|
|
|
|
fullListPath OutputPath
|
2020-04-27 18:08:37 +02:00
|
|
|
}
|
|
|
|
|
2020-04-28 15:57:42 +02:00
|
|
|
type ApexBundleDepsInfoIntf interface {
|
|
|
|
Updatable() bool
|
2020-04-27 19:07:06 +02:00
|
|
|
FlatListPath() Path
|
2020-04-27 18:08:37 +02:00
|
|
|
FullListPath() Path
|
|
|
|
}
|
|
|
|
|
2020-04-27 19:07:06 +02:00
|
|
|
func (d *ApexBundleDepsInfo) FlatListPath() Path {
|
|
|
|
return d.flatListPath
|
|
|
|
}
|
|
|
|
|
2020-04-27 18:08:37 +02:00
|
|
|
func (d *ApexBundleDepsInfo) FullListPath() Path {
|
|
|
|
return d.fullListPath
|
|
|
|
}
|
|
|
|
|
2020-04-27 19:07:06 +02:00
|
|
|
// Generate two module out files:
|
|
|
|
// 1. FullList with transitive deps and their parents in the dep graph
|
|
|
|
// 2. FlatList with a flat list of transitive deps
|
2021-03-11 19:03:42 +01:00
|
|
|
// In both cases transitive deps of external deps are not included. Neither are deps that are only
|
|
|
|
// available to APEXes; they are developed with updatability in mind and don't need manual approval.
|
2020-04-27 19:53:18 +02:00
|
|
|
func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion string, depInfos DepNameToDepInfoMap) {
|
2020-04-27 19:07:06 +02:00
|
|
|
var fullContent strings.Builder
|
|
|
|
var flatContent strings.Builder
|
|
|
|
|
2020-11-13 20:48:42 +01:00
|
|
|
fmt.Fprintf(&fullContent, "%s(minSdkVersion:%s):\n", ctx.ModuleName(), minSdkVersion)
|
2023-03-01 01:02:16 +01:00
|
|
|
for _, key := range FirstUniqueStrings(SortedKeys(depInfos)) {
|
2020-04-27 18:08:37 +02:00
|
|
|
info := depInfos[key]
|
2020-04-27 19:53:18 +02:00
|
|
|
toName := fmt.Sprintf("%s(minSdkVersion:%s)", info.To, info.MinSdkVersion)
|
2020-04-27 18:08:37 +02:00
|
|
|
if info.IsExternal {
|
|
|
|
toName = toName + " (external)"
|
|
|
|
}
|
2020-11-13 20:48:42 +01:00
|
|
|
fmt.Fprintf(&fullContent, " %s <- %s\n", toName, strings.Join(SortedUniqueStrings(info.From), ", "))
|
|
|
|
fmt.Fprintf(&flatContent, "%s\n", toName)
|
2020-04-27 18:08:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
d.fullListPath = PathForModuleOut(ctx, "depsinfo", "fulllist.txt").OutputPath
|
2020-11-13 20:48:42 +01:00
|
|
|
WriteFileRule(ctx, d.fullListPath, fullContent.String())
|
2020-04-27 19:07:06 +02:00
|
|
|
|
|
|
|
d.flatListPath = PathForModuleOut(ctx, "depsinfo", "flatlist.txt").OutputPath
|
2020-11-13 20:48:42 +01:00
|
|
|
WriteFileRule(ctx, d.flatListPath, flatContent.String())
|
2021-02-18 12:36:40 +01:00
|
|
|
|
|
|
|
ctx.Phony(fmt.Sprintf("%s-depsinfo", ctx.ModuleName()), d.fullListPath, d.flatListPath)
|
2020-04-27 18:08:37 +02:00
|
|
|
}
|
2020-04-15 04:03:39 +02:00
|
|
|
|
|
|
|
// Function called while walking an APEX's payload dependencies.
|
|
|
|
//
|
|
|
|
// Return true if the `to` module should be visited, false otherwise.
|
|
|
|
type PayloadDepsCallback func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool
|
2021-12-02 14:59:35 +01:00
|
|
|
type WalkPayloadDepsFunc func(ctx ModuleContext, do PayloadDepsCallback)
|
2020-04-15 04:03:39 +02:00
|
|
|
|
2021-12-02 14:59:35 +01:00
|
|
|
// ModuleWithMinSdkVersionCheck represents a module that implements min_sdk_version checks
|
|
|
|
type ModuleWithMinSdkVersionCheck interface {
|
2020-04-15 04:03:39 +02:00
|
|
|
Module
|
2023-03-03 22:20:36 +01:00
|
|
|
MinSdkVersion(ctx EarlyModuleContext) ApiLevel
|
2021-12-02 14:59:35 +01:00
|
|
|
CheckMinSdkVersion(ctx ModuleContext)
|
2020-04-15 04:03:39 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 17:34:22 +01:00
|
|
|
// CheckMinSdkVersion checks if every dependency of an updatable module sets min_sdk_version
|
|
|
|
// accordingly
|
2021-12-02 14:59:35 +01:00
|
|
|
func CheckMinSdkVersion(ctx ModuleContext, minSdkVersion ApiLevel, walk WalkPayloadDepsFunc) {
|
2020-04-15 04:03:39 +02:00
|
|
|
// do not enforce min_sdk_version for host
|
|
|
|
if ctx.Host() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// do not enforce for coverage build
|
|
|
|
if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") || ctx.DeviceConfig().NativeCoverageEnabled() || ctx.DeviceConfig().ClangCoverageEnabled() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-01-26 03:43:46 +01:00
|
|
|
// do not enforce deps.min_sdk_version if APEX/APK doesn't set min_sdk_version
|
|
|
|
if minSdkVersion.IsNone() {
|
2020-04-15 04:03:39 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-12-02 14:59:35 +01:00
|
|
|
walk(ctx, func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool {
|
2020-04-15 04:03:39 +02:00
|
|
|
if externalDep {
|
2020-11-17 17:34:22 +01:00
|
|
|
// external deps are outside the payload boundary, which is "stable"
|
|
|
|
// interface. We don't have to check min_sdk_version for external
|
|
|
|
// dependencies.
|
2020-04-15 04:03:39 +02:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
if am, ok := from.(DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
|
|
|
|
return false
|
|
|
|
}
|
2021-12-06 12:42:40 +01:00
|
|
|
if m, ok := to.(ModuleWithMinSdkVersionCheck); ok {
|
|
|
|
// This dependency performs its own min_sdk_version check, just make sure it sets min_sdk_version
|
|
|
|
// to trigger the check.
|
|
|
|
if !m.MinSdkVersion(ctx).Specified() {
|
|
|
|
ctx.OtherModuleErrorf(m, "must set min_sdk_version")
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
2020-04-15 04:03:39 +02:00
|
|
|
if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil {
|
|
|
|
toName := ctx.OtherModuleName(to)
|
2022-06-24 07:56:43 +02:00
|
|
|
ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v."+
|
|
|
|
"\n\nDependency path: %s\n\n"+
|
|
|
|
"Consider adding 'min_sdk_version: %q' to %q",
|
|
|
|
minSdkVersion, ctx.ModuleName(), err.Error(),
|
|
|
|
ctx.GetPathString(false),
|
|
|
|
minSdkVersion, toName)
|
|
|
|
return false
|
2020-04-15 04:03:39 +02:00
|
|
|
}
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
}
|
2023-04-12 21:05:49 +02:00
|
|
|
|
2023-08-19 00:43:28 +02:00
|
|
|
// Construct ApiLevel object from min_sdk_version string value
|
|
|
|
func MinSdkVersionFromValue(ctx EarlyModuleContext, value string) ApiLevel {
|
|
|
|
if value == "" {
|
|
|
|
return NoneApiLevel
|
|
|
|
}
|
|
|
|
apiLevel, err := ApiLevelFromUser(ctx, value)
|
|
|
|
if err != nil {
|
|
|
|
ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
|
|
|
|
return NoneApiLevel
|
|
|
|
}
|
|
|
|
return apiLevel
|
|
|
|
}
|
|
|
|
|
2023-04-12 21:05:49 +02:00
|
|
|
// Implemented by apexBundle.
|
|
|
|
type ApexTestInterface interface {
|
|
|
|
// Return true if the apex bundle is an apex_test
|
|
|
|
IsTestApex() bool
|
|
|
|
}
|