platform_build_soong/android/apex.go

760 lines
27 KiB
Go
Raw Normal View History

// 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
import (
"fmt"
"sort"
"strconv"
"strings"
"sync"
"github.com/google/blueprint"
)
var (
SdkVersion_Android10 = uncheckedFinalApiLevel(29)
)
// ApexInfo describes the metadata common to all modules in an apexBundle.
type ApexInfo struct {
// Name of the apex variation that this module is mutated into, or "" for
// a platform variant. 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 one or more APEXes.
ApexVariationName string
// Serialized ApiLevel. Use via MinSdkVersion() method. Cannot be stored in
// its struct form because this is cloned into properties structs, and
// ApiLevel has private members.
MinSdkVersionStr 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-12 03:17:01 +08:00
// True if the module comes from an updatable APEX.
Updatable bool
RequiredSdks SdkRefs
InApexes []string
ApexContents []*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-12 03:17:01 +08:00
}
var ApexInfoProvider = blueprint.NewMutatorProvider(ApexInfo{}, "apex")
func (i ApexInfo) mergedName(ctx PathContext) string {
name := "apex" + strconv.Itoa(i.MinSdkVersion(ctx).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-12 03:17:01 +08:00
for _, sdk := range i.RequiredSdks {
name += "_" + sdk.Name + "_" + sdk.Version
}
return name
}
func (this *ApexInfo) MinSdkVersion(ctx PathContext) ApiLevel {
return ApiLevelOrPanic(ctx, this.MinSdkVersionStr)
}
func (i ApexInfo) IsForPlatform() bool {
return i.ApexVariationName == ""
}
func (i ApexInfo) InApex(apex string) bool {
for _, a := range i.InApexes {
if a == apex {
return true
}
}
return false
}
// ApexTestForInfo stores the contents of APEXes for which this module is a test and thus has
// access to APEX internals.
type ApexTestForInfo struct {
ApexContents []*ApexContents
}
var ApexTestForInfoProvider = blueprint.NewMutatorProvider(ApexTestForInfo{}, "apex_test_for")
// Extracted from ApexModule to make it easier to define custom subsets of the
// ApexModule interface and improve code navigation within the IDE.
type DepIsInSameApex interface {
// DepIsInSameApex tests if the other module 'dep' is installed to the same
// APEX as this module
DepIsInSameApex(ctx BaseModuleContext, dep Module) bool
}
// 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 (installed to one of the regular partitions).
//
// 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 APEXs.
//
// 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 APEXs. 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.
type ApexModule interface {
Module
DepIsInSameApex
apexModuleBase() *ApexModuleBase
// Marks that this module should be built for the specified APEX.
// Call this before apex.apexMutator is run.
BuildForApex(apex ApexInfo)
// Returns true if this module is present in any APEXes
// directly or indirectly.
// Call this after apex.apexMutator is run.
InAnyApex() bool
// Returns true if this module is directly in any APEXes.
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-12 03:17:01 +08:00
// Call this after apex.apexMutator is run.
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-12 03:17:01 +08:00
// Returns true if any variant of this module is directly in any APEXes.
// Call this after apex.apexMutator is run.
AnyVariantDirectlyInAnyApex() bool
// Tests if this module could have APEX variants. APEX variants are
// created only for the modules that returns true here. This is useful
// for not creating APEX variants for certain types of shared libraries
// such as NDK stubs.
CanHaveApexVariants() bool
// 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.
IsInstallableToApex() bool
// Tests if this module is available for the specified APEX or ":platform"
AvailableFor(what string) bool
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 15:37:39 +08:00
// Return 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.
NotAvailableForPlatform() bool
// Mark that this module is not available to platform. Set by the
// check-platform-availability mutator in the apex package.
SetNotAvailableForPlatform()
// List of APEXes that this module tests. The module has access to
// the private part of the listed APEXes even when it is not included in the
// APEXes.
TestFor() []string
// Returns nil if this module supports sdkVersion
// Otherwise, returns error with reason
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-12 03:17:01 +08:00
// Returns true if this module needs a unique variation per apex, for example if
// use_apex_name_macro is set.
UniqueApexVariations() bool
}
type ApexProperties struct {
// 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).
//
// "//apex_available:anyapex" is a pseudo APEX name that matches to any APEX.
// "//apex_available:platform" refers to non-APEX partitions like "system.img".
// "com.android.gki.*" matches any APEX module name with the prefix "com.android.gki.".
// Default is ["//apex_available:platform"].
Apex_available []string
// 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.
AnyVariantDirectlyInAnyApex bool `blueprint:"mutated"`
// DirectlyInAnyApex is true if any APEX variant (including the "" variant used for the
// platform) of this module is directly in any APEX.
DirectlyInAnyApex bool `blueprint:"mutated"`
// DirectlyInAnyApex is true if any APEX variant (including the "" variant used for the
// platform) of this module is directly or indirectly in any APEX.
InAnyApex 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 15:37:39 +08: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-12 03:17:01 +08:00
UniqueApexVariationsForDeps bool `blueprint:"mutated"`
}
// Marker interface that identifies dependencies that are excluded from APEX
// contents.
type ExcludeFromApexContentsTag interface {
blueprint.DependencyTag
// Method that differentiates this interface from others.
ExcludeFromApexContents()
}
// 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.
type CopyDirectlyInAnyApexTag interface {
blueprint.DependencyTag
CopyDirectlyInAnyApex()
}
// Provides default implementation for the ApexModule interface. APEX-aware
// modules are expected to include this struct and call InitApexModule().
type ApexModuleBase struct {
ApexProperties ApexProperties
canHaveApexVariants bool
apexVariationsLock sync.Mutex // protects apexVariations during parallel apexDepsMutator
apexVariations []ApexInfo
}
func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase {
return m
}
func (m *ApexModuleBase) ApexAvailable() []string {
return m.ApexProperties.Apex_available
}
func (m *ApexModuleBase) TestFor() []string {
// To be implemented by concrete types inheriting ApexModuleBase
return nil
}
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-12 03:17:01 +08:00
func (m *ApexModuleBase) UniqueApexVariations() bool {
return false
}
func (m *ApexModuleBase) BuildForApex(apex ApexInfo) {
m.apexVariationsLock.Lock()
defer m.apexVariationsLock.Unlock()
for _, v := range m.apexVariations {
if v.ApexVariationName == apex.ApexVariationName {
return
}
}
m.apexVariations = append(m.apexVariations, apex)
}
func (m *ApexModuleBase) DirectlyInAnyApex() bool {
return m.ApexProperties.DirectlyInAnyApex
}
func (m *ApexModuleBase) AnyVariantDirectlyInAnyApex() bool {
return m.ApexProperties.AnyVariantDirectlyInAnyApex
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-12 03:17:01 +08:00
}
func (m *ApexModuleBase) InAnyApex() bool {
return m.ApexProperties.InAnyApex
}
func (m *ApexModuleBase) CanHaveApexVariants() bool {
return m.canHaveApexVariants
}
func (m *ApexModuleBase) IsInstallableToApex() bool {
// should be overriden if needed
return false
}
const (
AvailableToPlatform = "//apex_available:platform"
AvailableToAnyApex = "//apex_available:anyapex"
AvailableToGkiApex = "com.android.gki.*"
)
func CheckAvailableForApex(what string, apex_available []string) bool {
if len(apex_available) == 0 {
// apex_available defaults to ["//apex_available:platform"],
// which means 'available to the platform but no apexes'.
return what == AvailableToPlatform
}
return InList(what, apex_available) ||
(what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available)) ||
(strings.HasPrefix(what, "com.android.gki.") && InList(AvailableToGkiApex, apex_available))
}
func (m *ApexModuleBase) AvailableFor(what string) bool {
return CheckAvailableForApex(what, m.ApexProperties.Apex_available)
}
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 15:37:39 +08:00
func (m *ApexModuleBase) NotAvailableForPlatform() bool {
return m.ApexProperties.NotAvailableForPlatform
}
func (m *ApexModuleBase) SetNotAvailableForPlatform() {
m.ApexProperties.NotAvailableForPlatform = true
}
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
}
func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
for _, n := range m.ApexProperties.Apex_available {
if n == AvailableToPlatform || n == AvailableToAnyApex || n == AvailableToGkiApex {
continue
}
if !mctx.OtherModuleExists(n) && !mctx.Config().AllowMissingDependencies() {
mctx.PropertyErrorf("apex_available", "%q is not a valid module name", n)
}
}
}
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] }
func (a byApexName) Less(i, j int) bool { return a[i].ApexVariationName < a[j].ApexVariationName }
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-12 03:17:01 +08: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
// variation names to the new variation names.
func mergeApexVariations(ctx PathContext, apexVariations []ApexInfo) (merged []ApexInfo, aliases [][2]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-12 03:17:01 +08:00
sort.Sort(byApexName(apexVariations))
seen := make(map[string]int)
for _, apexInfo := range apexVariations {
apexName := apexInfo.ApexVariationName
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-12 03:17:01 +08:00
if index, exists := seen[mergedName]; exists {
merged[index].InApexes = append(merged[index].InApexes, apexName)
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-12 03:17:01 +08:00
merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable
} else {
seen[mergedName] = len(merged)
apexInfo.ApexVariationName = 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-12 03:17:01 +08:00
apexInfo.InApexes = CopyOf(apexInfo.InApexes)
apexInfo.ApexContents = append([]*ApexContents(nil), 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-12 03:17:01 +08:00
merged = append(merged, apexInfo)
}
aliases = append(aliases, [2]string{apexName, mergedName})
}
return merged, aliases
}
func CreateApexVariations(mctx BottomUpMutatorContext, module ApexModule) []Module {
base := module.apexModuleBase()
if len(base.apexVariations) > 0 {
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-31 01:49:53 +08: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-12 03:17:01 +08:00
var apexVariations []ApexInfo
var aliases [][2]string
if !mctx.Module().(ApexModule).UniqueApexVariations() && !base.ApexProperties.UniqueApexVariationsForDeps {
apexVariations, aliases = mergeApexVariations(mctx, base.apexVariations)
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-12 03:17:01 +08:00
} else {
apexVariations = base.apexVariations
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-12 03:17:01 +08:00
}
// base.apexVariations is only needed to propagate the list of apexes from
// apexDepsMutator to 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.apexVariations = nil
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-12 03:17:01 +08:00
sort.Sort(byApexName(apexVariations))
variations := []string{}
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-31 01:49:53 +08:00
variations = append(variations, "") // Original variation for platform
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-12 03:17:01 +08:00
for _, apex := range apexVariations {
variations = append(variations, apex.ApexVariationName)
}
defaultVariation := ""
mctx.SetDefaultDependencyVariation(&defaultVariation)
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-31 01:49:53 +08:00
var inApex ApexMembership
for _, a := range apexVariations {
for _, apexContents := range a.ApexContents {
inApex = inApex.merge(apexContents.contents[mctx.ModuleName()])
}
}
base.ApexProperties.InAnyApex = true
base.ApexProperties.DirectlyInAnyApex = inApex == directlyInApex
modules := mctx.CreateVariations(variations...)
for i, mod := range modules {
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-31 01:49:53 +08:00
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.
mod.MakeUninstallable()
}
if !platformVariation {
mctx.SetVariationProvider(mod, ApexInfoProvider, apexVariations[i-1])
}
}
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-12 03:17:01 +08:00
for _, alias := range aliases {
mctx.CreateAliasVariation(alias[0], alias[1])
}
return modules
}
return nil
}
// 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.
func UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext, am ApexModule) {
// anyInSameApex returns true if the two ApexInfo lists contain any values in an InApexes 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.
anyInSameApex := func(a, b []ApexInfo) bool {
collectApexes := func(infos []ApexInfo) []string {
var ret []string
for _, info := range infos {
ret = append(ret, info.InApexes...)
}
return ret
}
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-12 03:17:01 +08:00
}
mctx.VisitDirectDeps(func(dep Module) {
if depApexModule, ok := dep.(ApexModule); ok {
if anyInSameApex(depApexModule.apexModuleBase().apexVariations, am.apexModuleBase().apexVariations) &&
(depApexModule.UniqueApexVariations() ||
depApexModule.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps) {
am.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps = true
}
}
})
}
// 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.
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()
base.ApexProperties.DirectlyInAnyApex = depBase.ApexProperties.DirectlyInAnyApex
base.ApexProperties.InAnyApex = depBase.ApexProperties.InAnyApex
}
})
if base.ApexProperties.DirectlyInAnyApex {
// Variants of a module are always visited sequentially in order, so it is safe to
// write to another variant of this module.
// For a BottomUpMutator the PrimaryModule() is visited first and FinalModule() is
// visited last.
mctx.FinalModule().(ApexModule).apexModuleBase().ApexProperties.AnyVariantDirectlyInAnyApex = true
}
// If this is the FinalModule (last visited module) copy AnyVariantDirectlyInAnyApex to
// all the other variants
if am == mctx.FinalModule().(ApexModule) {
mctx.VisitAllModuleVariants(func(variant Module) {
variant.(ApexModule).apexModuleBase().ApexProperties.AnyVariantDirectlyInAnyApex =
base.ApexProperties.AnyVariantDirectlyInAnyApex
})
}
}
type ApexMembership int
const (
notInApex ApexMembership = 0
indirectlyInApex = iota
directlyInApex
)
// Each apexBundle has an apexContents, and modules in that apex have a provider containing the
// apexContents of each apexBundle they are part of.
type ApexContents struct {
ApexName string
contents map[string]ApexMembership
}
func NewApexContents(name string, contents map[string]ApexMembership) *ApexContents {
return &ApexContents{
ApexName: name,
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-12 03:17:01 +08:00
}
}
func (i ApexMembership) Add(direct bool) ApexMembership {
if direct || i == directlyInApex {
return directlyInApex
}
return indirectlyInApex
}
func (i ApexMembership) merge(other ApexMembership) ApexMembership {
if other == directlyInApex || i == directlyInApex {
return directlyInApex
}
if other == indirectlyInApex || i == indirectlyInApex {
return indirectlyInApex
}
return notInApex
}
func (ac *ApexContents) DirectlyInApex(name string) bool {
return ac.contents[name] == directlyInApex
}
func (ac *ApexContents) InApex(name string) bool {
return ac.contents[name] != notInApex
}
// Tests whether a module named moduleName is directly depended on by all APEXes
// in an ApexInfo.
func DirectlyInAllApexes(apexInfo ApexInfo, moduleName string) bool {
for _, contents := range apexInfo.ApexContents {
if !contents.DirectlyInApex(moduleName) {
return false
}
}
return true
}
func InitApexModule(m ApexModule) {
base := m.apexModuleBase()
base.canHaveApexVariants = true
m.AddProperties(&base.ApexProperties)
}
// 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
// min_sdk_version of the ApexModule
MinSdkVersion string
}
// A map of a dependency name to its ApexModuleDepInfo
type DepNameToDepInfoMap map[string]ApexModuleDepInfo
type ApexBundleDepsInfo struct {
flatListPath OutputPath
fullListPath OutputPath
}
type ApexBundleDepsInfoIntf interface {
Updatable() bool
FlatListPath() Path
FullListPath() Path
}
func (d *ApexBundleDepsInfo) FlatListPath() Path {
return d.flatListPath
}
func (d *ApexBundleDepsInfo) FullListPath() Path {
return d.fullListPath
}
// 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
func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion string, depInfos DepNameToDepInfoMap) {
var fullContent strings.Builder
var flatContent strings.Builder
fmt.Fprintf(&fullContent, "%s(minSdkVersion:%s):\\n", ctx.ModuleName(), minSdkVersion)
for _, key := range FirstUniqueStrings(SortedStringKeys(depInfos)) {
info := depInfos[key]
toName := fmt.Sprintf("%s(minSdkVersion:%s)", info.To, info.MinSdkVersion)
if info.IsExternal {
toName = toName + " (external)"
}
fmt.Fprintf(&fullContent, " %s <- %s\\n", toName, strings.Join(SortedUniqueStrings(info.From), ", "))
fmt.Fprintf(&flatContent, "%s\\n", toName)
}
d.fullListPath = PathForModuleOut(ctx, "depsinfo", "fulllist.txt").OutputPath
ctx.Build(pctx, BuildParams{
Rule: WriteFile,
Description: "Full Dependency Info",
Output: d.fullListPath,
Args: map[string]string{
"content": fullContent.String(),
},
})
d.flatListPath = PathForModuleOut(ctx, "depsinfo", "flatlist.txt").OutputPath
ctx.Build(pctx, BuildParams{
Rule: WriteFile,
Description: "Flat Dependency Info",
Output: d.flatListPath,
Args: map[string]string{
"content": flatContent.String(),
},
})
}
// TODO(b/158059172): remove minSdkVersion allowlist
var minSdkVersionAllowlist = func(apiMap map[string]int) map[string]ApiLevel {
list := make(map[string]ApiLevel, len(apiMap))
for name, finalApiInt := range apiMap {
list[name] = uncheckedFinalApiLevel(finalApiInt)
}
return list
}(map[string]int{
"adbd": 30,
"android.net.ipsec.ike": 30,
"androidx-constraintlayout_constraintlayout-solver": 30,
"androidx.annotation_annotation": 28,
"androidx.arch.core_core-common": 28,
"androidx.collection_collection": 28,
"androidx.lifecycle_lifecycle-common": 28,
"apache-commons-compress": 29,
"bouncycastle_ike_digests": 30,
"brotli-java": 29,
"captiveportal-lib": 28,
"flatbuffer_headers": 30,
"framework-permission": 30,
"framework-statsd": 30,
"gemmlowp_headers": 30,
"ike-internals": 30,
"kotlinx-coroutines-android": 28,
"kotlinx-coroutines-core": 28,
"libadb_crypto": 30,
"libadb_pairing_auth": 30,
"libadb_pairing_connection": 30,
"libadb_pairing_server": 30,
"libadb_protos": 30,
"libadb_tls_connection": 30,
"libadbconnection_client": 30,
"libadbconnection_server": 30,
"libadbd_core": 30,
"libadbd_services": 30,
"libadbd": 30,
"libapp_processes_protos_lite": 30,
"libasyncio": 30,
"libbrotli": 30,
"libbuildversion": 30,
"libcrypto_static": 30,
"libcrypto_utils": 30,
"libdiagnose_usb": 30,
"libeigen": 30,
"liblz4": 30,
"libmdnssd": 30,
"libneuralnetworks_common": 30,
"libneuralnetworks_headers": 30,
"libneuralnetworks": 30,
"libprocpartition": 30,
"libprotobuf-java-lite": 30,
"libprotoutil": 30,
"libqemu_pipe": 30,
"libstats_jni": 30,
"libstatslog_statsd": 30,
"libstatsmetadata": 30,
"libstatspull": 30,
"libstatssocket": 30,
"libsync": 30,
"libtextclassifier_hash_headers": 30,
"libtextclassifier_hash_static": 30,
"libtflite_kernel_utils": 30,
"libwatchdog": 29,
"libzstd": 30,
"metrics-constants-protos": 28,
"net-utils-framework-common": 29,
"permissioncontroller-statsd": 28,
"philox_random_headers": 30,
"philox_random": 30,
"service-permission": 30,
"service-statsd": 30,
"statsd-aidl-ndk_platform": 30,
"statsd": 30,
"tensorflow_headers": 30,
"xz-java": 29,
})
// 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
// UpdatableModule represents updatable APEX/APK
type UpdatableModule interface {
Module
WalkPayloadDeps(ctx ModuleContext, do PayloadDepsCallback)
}
// CheckMinSdkVersion checks if every dependency of an updatable module sets min_sdk_version accordingly
func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion ApiLevel) {
// 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
}
// do not enforce deps.min_sdk_version if APEX/APK doesn't set min_sdk_version or
// min_sdk_version is not finalized (e.g. current or codenames)
if minSdkVersion.IsCurrent() {
return
}
m.WalkPayloadDeps(ctx, func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool {
if externalDep {
// external deps are outside the payload boundary, which is "stable" interface.
// We don't have to check min_sdk_version for external dependencies.
return false
}
if am, ok := from.(DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
return false
}
if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil {
toName := ctx.OtherModuleName(to)
if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver.GreaterThan(minSdkVersion) {
ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v. Dependency path: %s",
minSdkVersion, ctx.ModuleName(), err.Error(), ctx.GetPathString(false))
return false
}
}
return true
})
}