Merge "Revert "Rewrite sbox to use a textproto manifest""
diff --git a/android/Android.bp b/android/Android.bp
index 7bd1450..66d361e 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -15,6 +15,7 @@
"apex.go",
"api_levels.go",
"arch.go",
+ "arch_list.go",
"bazel_handler.go",
"config.go",
"csuite_config.go",
@@ -32,11 +33,13 @@
"mutator.go",
"namespace.go",
"neverallow.go",
+ "ninja_deps.go",
"notices.go",
"onceper.go",
"override_module.go",
"package.go",
"package_ctx.go",
+ "packaging.go",
"path_properties.go",
"paths.go",
"phony.go",
@@ -73,8 +76,10 @@
"mutator_test.go",
"namespace_test.go",
"neverallow_test.go",
+ "ninja_deps_test.go",
"onceper_test.go",
"package_test.go",
+ "packaging_test.go",
"path_properties_test.go",
"paths_test.go",
"prebuilt_test.go",
diff --git a/android/arch.go b/android/arch.go
index 98ff07a..eb651e6 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -27,28 +27,6 @@
"github.com/google/blueprint/proptools"
)
-const COMMON_VARIANT = "common"
-
-var (
- archTypeList []ArchType
-
- Arm = newArch("arm", "lib32")
- Arm64 = newArch("arm64", "lib64")
- X86 = newArch("x86", "lib32")
- X86_64 = newArch("x86_64", "lib64")
-
- Common = ArchType{
- Name: COMMON_VARIANT,
- }
-)
-
-var archTypeMap = map[string]ArchType{
- "arm": Arm,
- "arm64": Arm64,
- "x86": X86,
- "x86_64": X86_64,
-}
-
/*
Example blueprints file containing all variant property groups, with comment listing what type
of variants get properties in that group:
@@ -111,405 +89,26 @@
}
*/
-var archVariants = map[ArchType][]string{
- Arm: {
- "armv7-a",
- "armv7-a-neon",
- "armv8-a",
- "armv8-2a",
- "cortex-a7",
- "cortex-a8",
- "cortex-a9",
- "cortex-a15",
- "cortex-a53",
- "cortex-a53-a57",
- "cortex-a55",
- "cortex-a72",
- "cortex-a73",
- "cortex-a75",
- "cortex-a76",
- "krait",
- "kryo",
- "kryo385",
- "exynos-m1",
- "exynos-m2",
- },
- Arm64: {
- "armv8_a",
- "armv8_2a",
- "armv8-2a-dotprod",
- "cortex-a53",
- "cortex-a55",
- "cortex-a72",
- "cortex-a73",
- "cortex-a75",
- "cortex-a76",
- "kryo",
- "kryo385",
- "exynos-m1",
- "exynos-m2",
- },
- X86: {
- "amberlake",
- "atom",
- "broadwell",
- "haswell",
- "icelake",
- "ivybridge",
- "kabylake",
- "sandybridge",
- "silvermont",
- "skylake",
- "stoneyridge",
- "tigerlake",
- "whiskeylake",
- "x86_64",
- },
- X86_64: {
- "amberlake",
- "broadwell",
- "haswell",
- "icelake",
- "ivybridge",
- "kabylake",
- "sandybridge",
- "silvermont",
- "skylake",
- "stoneyridge",
- "tigerlake",
- "whiskeylake",
- },
-}
-
-var archFeatures = map[ArchType][]string{
- Arm: {
- "neon",
- },
- Arm64: {
- "dotprod",
- },
- X86: {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "aes_ni",
- "avx",
- "avx2",
- "avx512",
- "popcnt",
- "movbe",
- },
- X86_64: {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "aes_ni",
- "avx",
- "avx2",
- "avx512",
- "popcnt",
- },
-}
-
-var archFeatureMap = map[ArchType]map[string][]string{
- Arm: {
- "armv7-a-neon": {
- "neon",
- },
- "armv8-a": {
- "neon",
- },
- "armv8-2a": {
- "neon",
- },
- },
- Arm64: {
- "armv8-2a-dotprod": {
- "dotprod",
- },
- },
- X86: {
- "amberlake": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "avx",
- "avx2",
- "aes_ni",
- "popcnt",
- },
- "atom": {
- "ssse3",
- "movbe",
- },
- "broadwell": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "avx",
- "avx2",
- "aes_ni",
- "popcnt",
- },
- "haswell": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "aes_ni",
- "avx",
- "popcnt",
- "movbe",
- },
- "icelake": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "avx",
- "avx2",
- "avx512",
- "aes_ni",
- "popcnt",
- },
- "ivybridge": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "aes_ni",
- "avx",
- "popcnt",
- },
- "kabylake": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "avx",
- "avx2",
- "aes_ni",
- "popcnt",
- },
- "sandybridge": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "popcnt",
- },
- "silvermont": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "aes_ni",
- "popcnt",
- "movbe",
- },
- "skylake": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "avx",
- "avx2",
- "avx512",
- "aes_ni",
- "popcnt",
- },
- "stoneyridge": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "aes_ni",
- "avx",
- "avx2",
- "popcnt",
- "movbe",
- },
- "tigerlake": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "avx",
- "avx2",
- "avx512",
- "aes_ni",
- "popcnt",
- },
- "whiskeylake": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "avx",
- "avx2",
- "avx512",
- "aes_ni",
- "popcnt",
- },
- "x86_64": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "popcnt",
- },
- },
- X86_64: {
- "amberlake": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "avx",
- "avx2",
- "aes_ni",
- "popcnt",
- },
- "broadwell": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "avx",
- "avx2",
- "aes_ni",
- "popcnt",
- },
- "haswell": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "aes_ni",
- "avx",
- "popcnt",
- },
- "icelake": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "avx",
- "avx2",
- "avx512",
- "aes_ni",
- "popcnt",
- },
- "ivybridge": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "aes_ni",
- "avx",
- "popcnt",
- },
- "kabylake": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "avx",
- "avx2",
- "aes_ni",
- "popcnt",
- },
- "sandybridge": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "popcnt",
- },
- "silvermont": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "aes_ni",
- "popcnt",
- },
- "skylake": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "avx",
- "avx2",
- "avx512",
- "aes_ni",
- "popcnt",
- },
- "stoneyridge": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "aes_ni",
- "avx",
- "avx2",
- "popcnt",
- },
- "tigerlake": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "avx",
- "avx2",
- "avx512",
- "aes_ni",
- "popcnt",
- },
- "whiskeylake": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "avx",
- "avx2",
- "avx512",
- "aes_ni",
- "popcnt",
- },
- },
-}
-
-var defaultArchFeatureMap = map[OsType]map[ArchType][]string{}
-
-func RegisterDefaultArchVariantFeatures(os OsType, arch ArchType, features ...string) {
- checkCalledFromInit()
-
- for _, feature := range features {
- if !InList(feature, archFeatures[arch]) {
- panic(fmt.Errorf("Invalid feature %q for arch %q variant \"\"", feature, arch))
- }
- }
-
- if defaultArchFeatureMap[os] == nil {
- defaultArchFeatureMap[os] = make(map[ArchType][]string)
- }
- defaultArchFeatureMap[os][arch] = features
-}
-
// An Arch indicates a single CPU architecture.
type Arch struct {
- ArchType ArchType
- ArchVariant string
- CpuVariant string
- Abi []string
+ // The type of the architecture (arm, arm64, x86, or x86_64).
+ ArchType ArchType
+
+ // The variant of the architecture, for example "armv7-a" or "armv7-a-neon" for arm.
+ ArchVariant string
+
+ // The variant of the CPU, for example "cortex-a53" for arm64.
+ CpuVariant string
+
+ // The list of Android app ABIs supported by the CPU architecture, for example "arm64-v8a".
+ Abi []string
+
+ // The list of arch-specific features supported by the CPU architecture, for example "neon".
ArchFeatures []string
}
+// String returns the Arch as a string. The value is used as the name of the variant created
+// by archMutator.
func (a Arch) String() string {
s := a.ArchType.String()
if a.ArchVariant != "" {
@@ -521,12 +120,42 @@
return s
}
+// ArchType is used to define the 4 supported architecture types (arm, arm64, x86, x86_64), as
+// well as the "common" architecture used for modules that support multiple architectures, for
+// example Java modules.
type ArchType struct {
- Name string
- Field string
+ // Name is the name of the architecture type, "arm", "arm64", "x86", or "x86_64".
+ Name string
+
+ // Field is the name of the field used in properties that refer to the architecture, e.g. "Arm64".
+ Field string
+
+ // Multilib is either "lib32" or "lib64" for 32-bit or 64-bit architectures.
Multilib string
}
+// String returns the name of the ArchType.
+func (a ArchType) String() string {
+ return a.Name
+}
+
+const COMMON_VARIANT = "common"
+
+var (
+ archTypeList []ArchType
+
+ Arm = newArch("arm", "lib32")
+ Arm64 = newArch("arm64", "lib64")
+ X86 = newArch("x86", "lib32")
+ X86_64 = newArch("x86_64", "lib64")
+
+ Common = ArchType{
+ Name: COMMON_VARIANT,
+ }
+)
+
+var archTypeMap = map[string]ArchType{}
+
func newArch(name, multilib string) ArchType {
archType := ArchType{
Name: name,
@@ -534,25 +163,25 @@
Multilib: multilib,
}
archTypeList = append(archTypeList, archType)
+ archTypeMap[name] = archType
return archType
}
+// ArchTypeList returns the 4 supported ArchTypes for arm, arm64, x86 and x86_64.
func ArchTypeList() []ArchType {
return append([]ArchType(nil), archTypeList...)
}
-func (a ArchType) String() string {
- return a.Name
-}
-
-var _ encoding.TextMarshaler = ArchType{}
-
+// MarshalText allows an ArchType to be serialized through any encoder that supports
+// encoding.TextMarshaler.
func (a ArchType) MarshalText() ([]byte, error) {
return []byte(strconv.Quote(a.String())), nil
}
-var _ encoding.TextUnmarshaler = &ArchType{}
+var _ encoding.TextMarshaler = ArchType{}
+// UnmarshalText allows an ArchType to be deserialized through any decoder that supports
+// encoding.TextUnmarshaler.
func (a *ArchType) UnmarshalText(text []byte) error {
if u, ok := archTypeMap[string(text)]; ok {
*a = u
@@ -562,67 +191,22 @@
return fmt.Errorf("unknown ArchType %q", text)
}
-var BuildOs = func() OsType {
- switch runtime.GOOS {
- case "linux":
- return Linux
- case "darwin":
- return Darwin
- default:
- panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS))
- }
-}()
+var _ encoding.TextUnmarshaler = &ArchType{}
-var BuildArch = func() ArchType {
- switch runtime.GOARCH {
- case "amd64":
- return X86_64
- default:
- panic(fmt.Sprintf("unsupported Arch: %s", runtime.GOARCH))
- }
-}()
-
-var (
- OsTypeList []OsType
- commonTargetMap = make(map[string]Target)
-
- NoOsType OsType
- Linux = NewOsType("linux_glibc", Host, false)
- Darwin = NewOsType("darwin", Host, false)
- LinuxBionic = NewOsType("linux_bionic", Host, false)
- Windows = NewOsType("windows", Host, true)
- Android = NewOsType("android", Device, false)
- Fuchsia = NewOsType("fuchsia", Device, false)
-
- // A pseudo OSType for a common os variant, which is OSType agnostic and which
- // has dependencies on all the OS variants.
- CommonOS = NewOsType("common_os", Generic, false)
-
- osArchTypeMap = map[OsType][]ArchType{
- Linux: []ArchType{X86, X86_64},
- LinuxBionic: []ArchType{Arm64, X86_64},
- Darwin: []ArchType{X86_64},
- Windows: []ArchType{X86, X86_64},
- Android: []ArchType{Arm, Arm64, X86, X86_64},
- Fuchsia: []ArchType{Arm64, X86_64},
- }
-)
-
-type OsType struct {
- Name, Field string
- Class OsClass
-
- DefaultDisabled bool
-}
-
+// OsClass is an enum that describes whether a variant of a module runs on the host, on the device,
+// or is generic.
type OsClass int
const (
+ // Generic is used for variants of modules that are not OS-specific.
Generic OsClass = iota
+ // Device is used for variants of modules that run on the device.
Device
+ // Host is used for variants of modules that run on the host.
Host
)
+// String returns the OsClass as a string.
func (class OsClass) String() string {
switch class {
case Generic:
@@ -636,22 +220,48 @@
}
}
+// OsType describes an OS variant of a module.
+type OsType struct {
+ // Name is the name of the OS. It is also used as the name of the property in Android.bp
+ // files.
+ Name string
+
+ // Field is the name of the OS converted to an exported field name, i.e. with the first
+ // character capitalized.
+ Field string
+
+ // Class is the OsClass of the OS.
+ Class OsClass
+
+ // DefaultDisabled is set when the module variants for the OS should not be created unless
+ // the module explicitly requests them. This is used to limit Windows cross compilation to
+ // only modules that need it.
+ DefaultDisabled bool
+}
+
+// String returns the name of the OsType.
func (os OsType) String() string {
return os.Name
}
+// Bionic returns true if the OS uses the Bionic libc runtime, i.e. if the OS is Android or
+// is Linux with Bionic.
func (os OsType) Bionic() bool {
return os == Android || os == LinuxBionic
}
+// Linux returns true if the OS uses the Linux kernel, i.e. if the OS is Android or is Linux
+// with or without the Bionic libc runtime.
func (os OsType) Linux() bool {
return os == Android || os == Linux || os == LinuxBionic
}
-func NewOsType(name string, class OsClass, defDisabled bool) OsType {
+// newOsType constructs an OsType and adds it to the global lists.
+func newOsType(name string, class OsClass, defDisabled bool, archTypes ...ArchType) OsType {
+ checkCalledFromInit()
os := OsType{
Name: name,
- Field: strings.Title(name),
+ Field: proptools.FieldNameForProperty(name),
Class: class,
DefaultDisabled: defDisabled,
@@ -663,10 +273,12 @@
} else {
commonTargetMap[name] = Target{Os: os, Arch: Arch{ArchType: Common}}
}
+ osArchTypeMap[os] = archTypes
return os
}
+// osByName returns the OsType that has the given name, or NoOsType if none match.
func osByName(name string) OsType {
for _, os := range OsTypeList {
if os.Name == name {
@@ -677,18 +289,74 @@
return NoOsType
}
-type NativeBridgeSupport bool
+// BuildOs returns the OsType for the OS that the build is running on.
+var BuildOs = func() OsType {
+ switch runtime.GOOS {
+ case "linux":
+ return Linux
+ case "darwin":
+ return Darwin
+ default:
+ panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS))
+ }
+}()
-const (
- NativeBridgeDisabled NativeBridgeSupport = false
- NativeBridgeEnabled NativeBridgeSupport = true
+// BuildArch returns the ArchType for the CPU that the build is running on.
+var BuildArch = func() ArchType {
+ switch runtime.GOARCH {
+ case "amd64":
+ return X86_64
+ default:
+ panic(fmt.Sprintf("unsupported Arch: %s", runtime.GOARCH))
+ }
+}()
+
+var (
+ // OsTypeList contains a list of all the supported OsTypes, including ones not supported
+ // by the current build host or the target device.
+ OsTypeList []OsType
+ // commonTargetMap maps names of OsTypes to the corresponding common Target, i.e. the
+ // Target with the same OsType and the common ArchType.
+ commonTargetMap = make(map[string]Target)
+ // osArchTypeMap maps OsTypes to the list of supported ArchTypes for that OS.
+ osArchTypeMap = map[OsType][]ArchType{}
+
+ // NoOsType is a placeholder for when no OS is needed.
+ NoOsType OsType
+ // Linux is the OS for the Linux kernel plus the glibc runtime.
+ Linux = newOsType("linux_glibc", Host, false, X86, X86_64)
+ // Darwin is the OS for MacOS/Darwin host machines.
+ Darwin = newOsType("darwin", Host, false, X86_64)
+ // LinuxBionic is the OS for the Linux kernel plus the Bionic libc runtime, but without the
+ // rest of Android.
+ LinuxBionic = newOsType("linux_bionic", Host, false, Arm64, X86_64)
+ // Windows the OS for Windows host machines.
+ Windows = newOsType("windows", Host, true, X86, X86_64)
+ // Android is the OS for target devices that run all of Android, including the Linux kernel
+ // and the Bionic libc runtime.
+ Android = newOsType("android", Device, false, Arm, Arm64, X86, X86_64)
+ // Fuchsia is the OS for target devices that run Fuchsia.
+ Fuchsia = newOsType("fuchsia", Device, false, Arm64, X86_64)
+
+ // CommonOS is a pseudo OSType for a common OS variant, which is OsType agnostic and which
+ // has dependencies on all the OS variants.
+ CommonOS = newOsType("common_os", Generic, false)
)
+// Target specifies the OS and architecture that a module is being compiled for.
type Target struct {
- Os OsType
- Arch Arch
- NativeBridge NativeBridgeSupport
+ // Os the OS that the module is being compiled for (e.g. "linux_glibc", "android").
+ Os OsType
+ // Arch is the architecture that the module is being compiled for.
+ Arch Arch
+ // NativeBridge is NativeBridgeEnabled if the architecture is supported using NativeBridge
+ // (i.e. arm on x86) for this device.
+ NativeBridge NativeBridgeSupport
+ // NativeBridgeHostArchName is the name of the real architecture that is used to implement
+ // the NativeBridge architecture. For example, for arm on x86 this would be "x86".
NativeBridgeHostArchName string
+ // NativeBridgeRelativePath is the name of the subdirectory that will contain NativeBridge
+ // libraries and binaries.
NativeBridgeRelativePath string
// HostCross is true when the target cannot run natively on the current build host.
@@ -697,14 +365,25 @@
HostCross bool
}
+// NativeBridgeSupport is an enum that specifies if a Target supports NativeBridge.
+type NativeBridgeSupport bool
+
+const (
+ NativeBridgeDisabled NativeBridgeSupport = false
+ NativeBridgeEnabled NativeBridgeSupport = true
+)
+
+// String returns the OS and arch variations used for the Target.
func (target Target) String() string {
return target.OsVariation() + "_" + target.ArchVariation()
}
+// OsVariation returns the name of the variation used by the osMutator for the Target.
func (target Target) OsVariation() string {
return target.Os.String()
}
+// ArchVariation returns the name of the variation used by the archMutator for the Target.
func (target Target) ArchVariation() string {
var variation string
if target.NativeBridge {
@@ -715,6 +394,8 @@
return variation
}
+// Variations returns a list of blueprint.Variations for the osMutator and archMutator for the
+// Target.
func (target Target) Variations() []blueprint.Variation {
return []blueprint.Variation{
{Mutator: "os", Variation: target.OsVariation()},
@@ -722,10 +403,16 @@
}
}
+// osMutator splits an arch-specific module into a variant for each OS that is enabled for the
+// module. It uses the HostOrDevice value passed to InitAndroidArchModule and the
+// device_supported and host_supported properties to determine which OsTypes are enabled for this
+// module, then searches through the Targets to determine which have enabled Targets for this
+// module.
func osMutator(bpctx blueprint.BottomUpMutatorContext) {
var module Module
var ok bool
if module, ok = bpctx.Module().(Module); !ok {
+ // The module is not a Soong module, it is a Blueprint module.
if bootstrap.IsBootstrapModule(bpctx.Module()) {
// Bootstrap Go modules are always the build OS or linux bionic.
config := bpctx.Config().(Config)
@@ -749,35 +436,38 @@
base := module.base()
+ // Nothing to do for modules that are not architecture specific (e.g. a genrule).
if !base.ArchSpecific() {
return
}
+ // Collect a list of OSTypes supported by this module based on the HostOrDevice value
+ // passed to InitAndroidArchModule and the device_supported and host_supported properties.
var moduleOSList []OsType
-
for _, os := range OsTypeList {
for _, t := range mctx.Config().Targets[os] {
- if base.supportsTarget(t, mctx.Config()) {
+ if base.supportsTarget(t) {
moduleOSList = append(moduleOSList, os)
break
}
}
}
+ // If there are no supported OSes then disable the module.
if len(moduleOSList) == 0 {
base.Disable()
return
}
+ // Convert the list of supported OsTypes to the variation names.
osNames := make([]string, len(moduleOSList))
-
for i, os := range moduleOSList {
osNames[i] = os.String()
}
createCommonOSVariant := base.commonProperties.CreateCommonOSVariant
if createCommonOSVariant {
- // A CommonOS variant was requested so add it to the list of OS's variants to
+ // A CommonOS variant was requested so add it to the list of OS variants to
// create. It needs to be added to the end because it needs to depend on the
// the other variants in the list returned by CreateVariations(...) and inter
// variant dependencies can only be created from a later variant in that list to
@@ -787,6 +477,8 @@
moduleOSList = append(moduleOSList, CommonOS)
}
+ // Create the variations, annotate each one with which OS it was created for, and
+ // squash the appropriate OS-specific properties into the top level properties.
modules := mctx.CreateVariations(osNames...)
for i, m := range modules {
m.base().commonProperties.CompileOS = moduleOSList[i]
@@ -841,7 +533,7 @@
}
// archMutator splits a module into a variant for each Target requested by the module. Target selection
-// for a module is in three levels, OsClass, mulitlib, and then Target.
+// for a module is in three levels, OsClass, multilib, and then Target.
// OsClass selection is determined by:
// - The HostOrDeviceSupported value passed in to InitAndroidArchModule by the module type factory, which selects
// whether the module type can compile for host, device or both.
@@ -858,7 +550,11 @@
// but may be arm for a 32-bit only build.
// "32": compile for only a single 32-bit Target supported by the OsClass.
// "64": compile for only a single 64-bit Target supported by the OsClass.
-// "common": compile a for a single Target that will work on all Targets suported by the OsClass (for example Java).
+// "common": compile a for a single Target that will work on all Targets supported by the OsClass (for example Java).
+// "common_first": compile a for a Target that will work on all Targets supported by the OsClass
+// (same as "common"), plus a second Target for the preferred Target supported by the OsClass
+// (same as "first"). This is used for java_binary that produces a common .jar and a wrapper
+// executable script.
//
// Once the list of Targets is determined, the module is split into a variant for each Target.
//
@@ -899,8 +595,8 @@
osTargets := mctx.Config().Targets[os]
image := base.commonProperties.ImageVariation
- // Filter NativeBridge targets unless they are explicitly supported
- // Skip creating native bridge variants for vendor modules
+ // Filter NativeBridge targets unless they are explicitly supported.
+ // Skip creating native bridge variants for non-core modules.
if os == Android &&
!(Bool(base.commonProperties.Native_bridge_supported) && image == CoreVariation) {
@@ -919,17 +615,24 @@
osTargets = []Target{osTargets[0]}
}
+ // Some modules want compile_multilib: "first" to mean 32-bit, not 64-bit.
+ // This is used for Windows support and for HOST_PREFER_32_BIT=true support for Art modules.
prefer32 := false
if base.prefer32 != nil {
prefer32 = base.prefer32(mctx, base, os)
}
+ // Determine the multilib selection for this module.
multilib, extraMultilib := decodeMultilib(base, os.Class)
+
+ // Convert the multilib selection into a list of Targets.
targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
if err != nil {
mctx.ModuleErrorf("%s", err.Error())
}
+ // If the module is using extraMultilib, decode the extraMultilib selection into
+ // a separate list of Targets.
var multiTargets []Target
if extraMultilib != "" {
multiTargets, err = decodeMultilibTargets(extraMultilib, osTargets, prefer32)
@@ -938,23 +641,27 @@
}
}
+ // Recovery is always the primary architecture, filter out any other architectures.
if image == RecoveryVariation {
primaryArch := mctx.Config().DevicePrimaryArchType()
targets = filterToArch(targets, primaryArch)
multiTargets = filterToArch(multiTargets, primaryArch)
}
+ // If there are no supported targets disable the module.
if len(targets) == 0 {
base.Disable()
return
}
+ // Convert the targets into a list of arch variation names.
targetNames := make([]string, len(targets))
-
for i, target := range targets {
targetNames[i] = target.ArchVariation()
}
+ // Create the variations, annotate each one with which Target it was created for, and
+ // squash the appropriate arch-specific properties into the top level properties.
modules := mctx.CreateVariations(targetNames...)
for i, m := range modules {
addTargetProperties(m, targets[i], multiTargets, i == 0)
@@ -968,22 +675,34 @@
}
}
+// addTargetProperties annotates a variant with the Target is is being compiled for, the list
+// of additional Targets it is supporting (if any), and whether it is the primary Target for
+// the module.
func addTargetProperties(m Module, target Target, multiTargets []Target, primaryTarget bool) {
m.base().commonProperties.CompileTarget = target
m.base().commonProperties.CompileMultiTargets = multiTargets
m.base().commonProperties.CompilePrimary = primaryTarget
}
+// decodeMultilib returns the appropriate compile_multilib property for the module, or the default
+// multilib from the factory's call to InitAndroidArchModule if none was set. For modules that
+// called InitAndroidMultiTargetsArchModule it always returns "common" for multilib, and returns
+// the actual multilib in extraMultilib.
func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib string) {
+ // First check the "android.compile_multilib" or "host.compile_multilib" properties.
switch class {
case Device:
multilib = String(base.commonProperties.Target.Android.Compile_multilib)
case Host:
multilib = String(base.commonProperties.Target.Host.Compile_multilib)
}
+
+ // If those aren't set, try the "compile_multilib" property.
if multilib == "" {
multilib = String(base.commonProperties.Compile_multilib)
}
+
+ // If that wasn't set, use the default multilib set by the factory.
if multilib == "" {
multilib = base.commonProperties.Default_multilib
}
@@ -1000,6 +719,8 @@
}
}
+// filterToArch takes a list of Targets and an ArchType, and returns a modified list that contains
+// only Targets that have the specified ArchType.
func filterToArch(targets []Target, arch ArchType) []Target {
for i := 0; i < len(targets); i++ {
if targets[i].Arch.ArchType != arch {
@@ -1010,17 +731,27 @@
return targets
}
-type archPropTypeDesc struct {
- arch, multilib, target reflect.Type
-}
-
+// archPropRoot is a struct type used as the top level of the arch-specific properties. It
+// contains the "arch", "multilib", and "target" property structs. It is used to split up the
+// property structs to limit how much is allocated when a single arch-specific property group is
+// used. The types are interface{} because they will hold instances of runtime-created types.
type archPropRoot struct {
Arch, Multilib, Target interface{}
}
+// archPropTypeDesc holds the runtime-created types for the property structs to instantiate to
+// create an archPropRoot property struct.
+type archPropTypeDesc struct {
+ arch, multilib, target reflect.Type
+}
+
// createArchPropTypeDesc takes a reflect.Type that is either a struct or a pointer to a struct, and
// returns lists of reflect.Types that contains the arch-variant properties inside structs for each
// arch, multilib and target property.
+//
+// This is a relatively expensive operation, so the results are cached in the global
+// archPropTypeMap. It is constructed entirely based on compile-time data, so there is no need
+// to isolate the results between multiple tests running in parallel.
func createArchPropTypeDesc(props reflect.Type) []archPropTypeDesc {
// Each property struct shard will be nested many times under the runtime generated arch struct,
// which can hit the limit of 64kB for the name of runtime generated structs. They are nested
@@ -1029,7 +760,12 @@
// could cause problems if a single deeply nested property no longer fits in the name.
const maxArchTypeNameSize = 500
+ // Convert the type to a new set of types that contains only the arch-specific properties
+ // (those that are tagged with `android:"arch_specific"`), and sharded into multiple types
+ // to keep the runtime-generated names under the limit.
propShards, _ := proptools.FilterPropertyStructSharded(props, maxArchTypeNameSize, filterArchStruct)
+
+ // If the type has no arch-specific properties there is nothing to do.
if len(propShards) == 0 {
return nil
}
@@ -1037,6 +773,8 @@
var ret []archPropTypeDesc
for _, props := range propShards {
+ // variantFields takes a list of variant property field names and returns a list the
+ // StructFields with the names and the type of the current shard.
variantFields := func(names []string) []reflect.StructField {
ret := make([]reflect.StructField, len(names))
@@ -1048,9 +786,11 @@
return ret
}
+ // Create a type that contains the properties in this shard repeated for each
+ // architecture, architecture variant, and architecture feature.
archFields := make([]reflect.StructField, len(archTypeList))
for i, arch := range archTypeList {
- variants := []string{}
+ var variants []string
for _, archVariant := range archVariants[arch] {
archVariant := variantReplacer.Replace(archVariant)
@@ -1061,8 +801,13 @@
variants = append(variants, proptools.FieldNameForProperty(feature))
}
+ // Create the StructFields for each architecture variant architecture feature
+ // (e.g. "arch.arm.cortex-a53" or "arch.arm.neon").
fields := variantFields(variants)
+ // Create the StructField for the architecture itself (e.g. "arch.arm"). The special
+ // "BlueprintEmbed" name is used by Blueprint to put the properties in the
+ // parent struct.
fields = append([]reflect.StructField{{
Name: "BlueprintEmbed",
Type: props,
@@ -1074,10 +819,15 @@
Type: reflect.StructOf(fields),
}
}
+
+ // Create the type of the "arch" property struct for this shard.
archType := reflect.StructOf(archFields)
+ // Create the type for the "multilib" property struct for this shard, containing the
+ // "multilib.lib32" and "multilib.lib64" property structs.
multilibType := reflect.StructOf(variantFields([]string{"Lib32", "Lib64"}))
+ // Start with a list of the special targets
targets := []string{
"Host",
"Android64",
@@ -1090,11 +840,14 @@
"Native_bridge",
}
for _, os := range OsTypeList {
+ // Add all the OSes.
targets = append(targets, os.Field)
+ // Add the OS/Arch combinations, e.g. "android_arm64".
for _, archType := range osArchTypeMap[os] {
targets = append(targets, os.Field+"_"+archType.Name)
+ // Also add the special "linux_<arch>" and "bionic_<arch>" property structs.
if os.Linux() {
target := "Linux_" + archType.Name
if !InList(target, targets) {
@@ -1110,8 +863,10 @@
}
}
+ // Create the type for the "target" property struct for this shard.
targetType := reflect.StructOf(variantFields(targets))
+ // Return a descriptor of the 3 runtime-created types.
ret = append(ret, archPropTypeDesc{
arch: reflect.PtrTo(archType),
multilib: reflect.PtrTo(multilibType),
@@ -1121,6 +876,11 @@
return ret
}
+// variantReplacer converts architecture variant or architecture feature names into names that
+// are valid for an Android.bp file.
+var variantReplacer = strings.NewReplacer("-", "_", ".", "_")
+
+// filterArchStruct returns true if the given field is an architecture specific property.
func filterArchStruct(field reflect.StructField, prefix string) (bool, reflect.StructField) {
if proptools.HasTag(field, "android", "arch_variant") {
// The arch_variant field isn't necessary past this point
@@ -1147,12 +907,17 @@
return false, field
}
+// archPropTypeMap contains a cache of the results of createArchPropTypeDesc for each type. It is
+// shared across all Contexts, but is constructed based only on compile-time information so there
+// is no risk of contaminating one Context with data from another.
var archPropTypeMap OncePer
-func InitArchModule(m Module) {
+// initArchModule adds the architecture-specific property structs to a Module.
+func initArchModule(m Module) {
base := m.base()
+ // Store the original list of top level property structs
base.generalProperties = m.GetProperties()
for _, properties := range base.generalProperties {
@@ -1169,10 +934,13 @@
propertiesValue.Interface()))
}
+ // Get or create the arch-specific property struct types for this property struct type.
archPropTypes := archPropTypeMap.Once(NewCustomOnceKey(t), func() interface{} {
return createArchPropTypeDesc(t)
}).([]archPropTypeDesc)
+ // Instantiate one of each arch-specific property struct type and add it to the
+ // properties for the Module.
var archProperties []interface{}
for _, t := range archPropTypes {
archProperties = append(archProperties, &archPropRoot{
@@ -1185,14 +953,18 @@
m.AddProperties(archProperties...)
}
+ // Update the list of properties that can be set by a defaults module or a call to
+ // AppendMatchingProperties or PrependMatchingProperties.
base.customizableProperties = m.GetProperties()
}
-var variantReplacer = strings.NewReplacer("-", "_", ".", "_")
-
+// appendProperties squashes properties from the given field of the given src property struct
+// into the dst property struct. Returns the reflect.Value of the field in the src property
+// struct to be used for further appendProperties calls on fields of that property struct.
func (m *ModuleBase) appendProperties(ctx BottomUpMutatorContext,
dst interface{}, src reflect.Value, field, srcPrefix string) reflect.Value {
+ // Step into non-nil pointers to structs in the src value.
if src.Kind() == reflect.Ptr {
if src.IsNil() {
return src
@@ -1200,18 +972,25 @@
src = src.Elem()
}
+ // Find the requested field in the src struct.
src = src.FieldByName(field)
if !src.IsValid() {
ctx.ModuleErrorf("field %q does not exist", srcPrefix)
return src
}
+ // Save the value of the field in the src struct to return.
ret := src
+ // If the value of the field is a struct (as opposed to a pointer to a struct) then step
+ // into the BlueprintEmbed field.
if src.Kind() == reflect.Struct {
src = src.FieldByName("BlueprintEmbed")
}
+ // order checks the `android:"variant_prepend"` tag to handle properties where the
+ // arch-specific value needs to come before the generic value, for example for lists of
+ // include directories.
order := func(property string,
dstField, srcField reflect.StructField,
dstValue, srcValue interface{}) (proptools.Order, error) {
@@ -1222,6 +1001,7 @@
}
}
+ // Squash the located property struct into the destination property struct.
err := proptools.ExtendMatchingProperties([]interface{}{dst}, src.Interface(), nil, order)
if err != nil {
if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
@@ -1234,7 +1014,8 @@
return ret
}
-// Rewrite the module's properties structs to contain os-specific values.
+// Squash the appropriate OS-specific property structs into the matching top level property structs
+// based on the CompileOS value that was annotated on the variant.
func (m *ModuleBase) setOSProperties(ctx BottomUpMutatorContext) {
os := m.commonProperties.CompileOS
@@ -1328,7 +1109,8 @@
}
}
-// Rewrite the module's properties structs to contain arch-specific values.
+// Squash the appropriate arch-specific property structs into the matching top level property
+// structs based on the CompileTarget value that was annotated on the variant.
func (m *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
arch := m.Arch()
os := m.Os()
@@ -1480,22 +1262,7 @@
}
}
-func forEachInterface(v reflect.Value, f func(reflect.Value)) {
- switch v.Kind() {
- case reflect.Interface:
- f(v)
- case reflect.Struct:
- for i := 0; i < v.NumField(); i++ {
- forEachInterface(v.Field(i), f)
- }
- case reflect.Ptr:
- forEachInterface(v.Elem(), f)
- default:
- panic(fmt.Errorf("Unsupported kind %s", v.Kind()))
- }
-}
-
-// Convert the arch product variables into a list of targets for each os class structs
+// Convert the arch product variables into a list of targets for each OsType.
func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) {
variables := config.productVariables
@@ -1567,19 +1334,26 @@
return nil, fmt.Errorf("No host primary architecture set")
}
+ // The primary host target, which must always exist.
addTarget(BuildOs, *variables.HostArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
+ // An optional secondary host target.
if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
addTarget(BuildOs, *variables.HostSecondaryArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
}
+ // An optional host target that uses the Bionic glibc runtime.
if Bool(config.Host_bionic) {
addTarget(LinuxBionic, "x86_64", nil, nil, nil, NativeBridgeDisabled, nil, nil)
}
+
+ // An optional cross-compiled host target that uses the Bionic glibc runtime on an arm64
+ // architecture.
if Bool(config.Host_bionic_arm64) {
addTarget(LinuxBionic, "arm64", nil, nil, nil, NativeBridgeDisabled, nil, nil)
}
+ // Optional cross-compiled host targets, generally Windows.
if String(variables.CrossHost) != "" {
crossHostOs := osByName(*variables.CrossHost)
if crossHostOs == NoOsType {
@@ -1590,28 +1364,34 @@
return nil, fmt.Errorf("No cross-host primary architecture set")
}
+ // The primary cross-compiled host target.
addTarget(crossHostOs, *variables.CrossHostArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
+ // An optional secondary cross-compiled host target.
if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" {
addTarget(crossHostOs, *variables.CrossHostSecondaryArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
}
}
+ // Optional device targets
if variables.DeviceArch != nil && *variables.DeviceArch != "" {
var target = Android
if Bool(variables.Fuchsia) {
target = Fuchsia
}
+ // The primary device target.
addTarget(target, *variables.DeviceArch, variables.DeviceArchVariant,
variables.DeviceCpuVariant, variables.DeviceAbi, NativeBridgeDisabled, nil, nil)
+ // An optional secondary device target.
if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
addTarget(Android, *variables.DeviceSecondaryArch,
variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
variables.DeviceSecondaryAbi, NativeBridgeDisabled, nil, nil)
}
+ // An optional NativeBridge device target.
if variables.NativeBridgeArch != nil && *variables.NativeBridgeArch != "" {
addTarget(Android, *variables.NativeBridgeArch,
variables.NativeBridgeArchVariant, variables.NativeBridgeCpuVariant,
@@ -1619,6 +1399,7 @@
variables.NativeBridgeRelativePath)
}
+ // An optional secondary NativeBridge device target.
if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" &&
variables.NativeBridgeSecondaryArch != nil && *variables.NativeBridgeSecondaryArch != "" {
addTarget(Android, *variables.NativeBridgeSecondaryArch,
@@ -1653,6 +1434,7 @@
return false
}
+// archConfig describes a built-in configuration.
type archConfig struct {
arch string
archVariant string
@@ -1660,6 +1442,7 @@
abi []string
}
+// getMegaDeviceConfig returns a list of archConfigs for every architecture simultaneously.
func getMegaDeviceConfig() []archConfig {
return []archConfig{
{"arm", "armv7-a", "generic", []string{"armeabi-v7a"}},
@@ -1706,6 +1489,7 @@
}
}
+// getNdkAbisConfig returns a list of archConfigs for the ABIs supported by the NDK.
func getNdkAbisConfig() []archConfig {
return []archConfig{
{"arm", "armv7-a", "", []string{"armeabi-v7a"}},
@@ -1715,6 +1499,7 @@
}
}
+// getAmlAbisConfig returns a list of archConfigs for the ABIs supported by mainline modules.
func getAmlAbisConfig() []archConfig {
return []archConfig{
{"arm", "armv7-a-neon", "", []string{"armeabi-v7a"}},
@@ -1724,6 +1509,7 @@
}
}
+// decodeArchSettings converts a list of archConfigs into a list of Targets for the given OsType.
func decodeArchSettings(os OsType, archConfigs []archConfig) ([]Target, error) {
var ret []Target
@@ -1743,15 +1529,9 @@
return ret, nil
}
-// Convert a set of strings from product variables into a single Arch struct
+// decodeArch converts a set of strings from product variables into an Arch struct.
func decodeArch(os OsType, arch string, archVariant, cpuVariant *string, abi []string) (Arch, error) {
- stringPtr := func(p *string) string {
- if p != nil {
- return *p
- }
- return ""
- }
-
+ // Verify the arch is valid
archType, ok := archTypeMap[arch]
if !ok {
return Arch{}, fmt.Errorf("unknown arch %q", arch)
@@ -1759,19 +1539,22 @@
a := Arch{
ArchType: archType,
- ArchVariant: stringPtr(archVariant),
- CpuVariant: stringPtr(cpuVariant),
+ ArchVariant: String(archVariant),
+ CpuVariant: String(cpuVariant),
Abi: abi,
}
+ // Convert generic arch variants into the empty string.
if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
a.ArchVariant = ""
}
+ // Convert generic CPU variants into the empty string.
if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
a.CpuVariant = ""
}
+ // Filter empty ABIs out of the list.
for i := 0; i < len(a.Abi); i++ {
if a.Abi[i] == "" {
a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
@@ -1780,10 +1563,12 @@
}
if a.ArchVariant == "" {
+ // Set ArchFeatures from the default arch features.
if featureMap, ok := defaultArchFeatureMap[os]; ok {
a.ArchFeatures = featureMap[archType]
}
} else {
+ // Set ArchFeatures from the arch type.
if featureMap, ok := archFeatureMap[archType]; ok {
a.ArchFeatures = featureMap[a.ArchVariant]
}
@@ -1792,6 +1577,8 @@
return a, nil
}
+// filterMultilibTargets takes a list of Targets and a multilib value and returns a new list of
+// Targets containing only those that have the given multilib value.
func filterMultilibTargets(targets []Target, multilib string) []Target {
var ret []Target
for _, t := range targets {
@@ -1802,8 +1589,8 @@
return ret
}
-// Return the set of Os specific common architecture targets for each Os in a list of
-// targets.
+// getCommonTargets returns the set of Os specific common architecture targets for each Os in a list
+// of targets.
func getCommonTargets(targets []Target) []Target {
var ret []Target
set := make(map[string]bool)
@@ -1818,6 +1605,9 @@
return ret
}
+// firstTarget takes a list of Targets and a list of multilib values and returns a list of Targets
+// that contains zero or one Target for each OsType, selecting the one that matches the earliest
+// filter.
func firstTarget(targets []Target, filters ...string) []Target {
// find the first target from each OS
var ret []Target
@@ -1837,9 +1627,10 @@
return ret
}
-// Use the module multilib setting to select one or more targets from a target list
+// decodeMultilibTargets uses the module's multilib setting to select one or more targets from a
+// list of Targets.
func decodeMultilibTargets(multilib string, targets []Target, prefer32 bool) ([]Target, error) {
- buildTargets := []Target{}
+ var buildTargets []Target
switch multilib {
case "common":
diff --git a/android/arch_list.go b/android/arch_list.go
new file mode 100644
index 0000000..0c33b9d
--- /dev/null
+++ b/android/arch_list.go
@@ -0,0 +1,410 @@
+// Copyright 2020 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"
+
+var archVariants = map[ArchType][]string{
+ Arm: {
+ "armv7-a",
+ "armv7-a-neon",
+ "armv8-a",
+ "armv8-2a",
+ "cortex-a7",
+ "cortex-a8",
+ "cortex-a9",
+ "cortex-a15",
+ "cortex-a53",
+ "cortex-a53-a57",
+ "cortex-a55",
+ "cortex-a72",
+ "cortex-a73",
+ "cortex-a75",
+ "cortex-a76",
+ "krait",
+ "kryo",
+ "kryo385",
+ "exynos-m1",
+ "exynos-m2",
+ },
+ Arm64: {
+ "armv8_a",
+ "armv8_2a",
+ "armv8-2a-dotprod",
+ "cortex-a53",
+ "cortex-a55",
+ "cortex-a72",
+ "cortex-a73",
+ "cortex-a75",
+ "cortex-a76",
+ "kryo",
+ "kryo385",
+ "exynos-m1",
+ "exynos-m2",
+ },
+ X86: {
+ "amberlake",
+ "atom",
+ "broadwell",
+ "haswell",
+ "icelake",
+ "ivybridge",
+ "kabylake",
+ "sandybridge",
+ "silvermont",
+ "skylake",
+ "stoneyridge",
+ "tigerlake",
+ "whiskeylake",
+ "x86_64",
+ },
+ X86_64: {
+ "amberlake",
+ "broadwell",
+ "haswell",
+ "icelake",
+ "ivybridge",
+ "kabylake",
+ "sandybridge",
+ "silvermont",
+ "skylake",
+ "stoneyridge",
+ "tigerlake",
+ "whiskeylake",
+ },
+}
+
+var archFeatures = map[ArchType][]string{
+ Arm: {
+ "neon",
+ },
+ Arm64: {
+ "dotprod",
+ },
+ X86: {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "aes_ni",
+ "avx",
+ "avx2",
+ "avx512",
+ "popcnt",
+ "movbe",
+ },
+ X86_64: {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "aes_ni",
+ "avx",
+ "avx2",
+ "avx512",
+ "popcnt",
+ },
+}
+
+var archFeatureMap = map[ArchType]map[string][]string{
+ Arm: {
+ "armv7-a-neon": {
+ "neon",
+ },
+ "armv8-a": {
+ "neon",
+ },
+ "armv8-2a": {
+ "neon",
+ },
+ },
+ Arm64: {
+ "armv8-2a-dotprod": {
+ "dotprod",
+ },
+ },
+ X86: {
+ "amberlake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "aes_ni",
+ "popcnt",
+ },
+ "atom": {
+ "ssse3",
+ "movbe",
+ },
+ "broadwell": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "aes_ni",
+ "popcnt",
+ },
+ "haswell": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "aes_ni",
+ "avx",
+ "popcnt",
+ "movbe",
+ },
+ "icelake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "avx512",
+ "aes_ni",
+ "popcnt",
+ },
+ "ivybridge": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "aes_ni",
+ "avx",
+ "popcnt",
+ },
+ "kabylake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "aes_ni",
+ "popcnt",
+ },
+ "sandybridge": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "popcnt",
+ },
+ "silvermont": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "aes_ni",
+ "popcnt",
+ "movbe",
+ },
+ "skylake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "avx512",
+ "aes_ni",
+ "popcnt",
+ },
+ "stoneyridge": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "aes_ni",
+ "avx",
+ "avx2",
+ "popcnt",
+ "movbe",
+ },
+ "tigerlake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "avx512",
+ "aes_ni",
+ "popcnt",
+ },
+ "whiskeylake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "avx512",
+ "aes_ni",
+ "popcnt",
+ },
+ "x86_64": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "popcnt",
+ },
+ },
+ X86_64: {
+ "amberlake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "aes_ni",
+ "popcnt",
+ },
+ "broadwell": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "aes_ni",
+ "popcnt",
+ },
+ "haswell": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "aes_ni",
+ "avx",
+ "popcnt",
+ },
+ "icelake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "avx512",
+ "aes_ni",
+ "popcnt",
+ },
+ "ivybridge": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "aes_ni",
+ "avx",
+ "popcnt",
+ },
+ "kabylake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "aes_ni",
+ "popcnt",
+ },
+ "sandybridge": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "popcnt",
+ },
+ "silvermont": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "aes_ni",
+ "popcnt",
+ },
+ "skylake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "avx512",
+ "aes_ni",
+ "popcnt",
+ },
+ "stoneyridge": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "aes_ni",
+ "avx",
+ "avx2",
+ "popcnt",
+ },
+ "tigerlake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "avx512",
+ "aes_ni",
+ "popcnt",
+ },
+ "whiskeylake": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "avx",
+ "avx2",
+ "avx512",
+ "aes_ni",
+ "popcnt",
+ },
+ },
+}
+
+var defaultArchFeatureMap = map[OsType]map[ArchType][]string{}
+
+// RegisterDefaultArchVariantFeatures is called by files that define Toolchains to specify the
+// arch features that are available for the default arch variant. It must be called from an
+// init() function.
+func RegisterDefaultArchVariantFeatures(os OsType, arch ArchType, features ...string) {
+ checkCalledFromInit()
+
+ for _, feature := range features {
+ if !InList(feature, archFeatures[arch]) {
+ panic(fmt.Errorf("Invalid feature %q for arch %q variant \"\"", feature, arch))
+ }
+ }
+
+ if defaultArchFeatureMap[os] == nil {
+ defaultArchFeatureMap[os] = make(map[ArchType][]string)
+ }
+ defaultArchFeatureMap[os][arch] = features
+}
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index c87a945..7d8d12f 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -192,9 +192,9 @@
func (context *bazelContext) issueBazelCommand(command string, labels []string,
extraFlags ...string) (string, error) {
- cmdFlags := []string{"--bazelrc=build/bazel/common.bazelrc",
- "--output_base=" + context.outputBase, command}
+ cmdFlags := []string{"--output_base=" + context.outputBase, command}
cmdFlags = append(cmdFlags, labels...)
+ cmdFlags = append(cmdFlags, "--package_path=%workspace%/"+context.intermediatesDir())
cmdFlags = append(cmdFlags, extraFlags...)
bazelCmd := exec.Command(context.bazelPath, cmdFlags...)
@@ -211,6 +211,21 @@
}
}
+// Returns the string contents of a workspace file that should be output
+// adjacent to the main bzl file and build file.
+// This workspace file allows, via local_repository rule, sourcetree-level
+// BUILD targets to be referenced via @sourceroot.
+func (context *bazelContext) workspaceFileContents() []byte {
+ formatString := `
+# This file is generated by soong_build. Do not edit.
+local_repository(
+ name = "sourceroot",
+ path = "%s",
+)
+`
+ return []byte(fmt.Sprintf(formatString, context.workspaceDir))
+}
+
func (context *bazelContext) mainBzlFileContents() []byte {
contents := `
# This file is generated by soong_build. Do not edit.
@@ -225,6 +240,18 @@
return []byte(contents)
}
+// Returns a "canonicalized" corresponding to the given sourcetree-level label.
+// This abstraction is required because a sourcetree label such as //foo/bar:baz
+// must be referenced via the local repository prefix, such as
+// @sourceroot//foo/bar:baz.
+func canonicalizeLabel(label string) string {
+ if strings.HasPrefix(label, "//") {
+ return "@sourceroot" + label
+ } else {
+ return "@sourceroot//" + label
+ }
+}
+
func (context *bazelContext) mainBuildFileContents() []byte {
formatString := `
# This file is generated by soong_build. Do not edit.
@@ -236,7 +263,7 @@
`
var buildRootDeps []string = nil
for val, _ := range context.requests {
- buildRootDeps = append(buildRootDeps, fmt.Sprintf("\"%s\"", val.label))
+ buildRootDeps = append(buildRootDeps, fmt.Sprintf("\"%s\"", canonicalizeLabel(val.label)))
}
buildRootDepsString := strings.Join(buildRootDeps, ",\n ")
@@ -262,13 +289,19 @@
// TODO(cparsons): Sort by request type instead of assuming all requests
// are of GetAllFiles type.
for val, _ := range context.requests {
- buildRootDeps = append(buildRootDeps, fmt.Sprintf("\"%s\" : True", val.label))
+ buildRootDeps = append(buildRootDeps, fmt.Sprintf("\"%s\" : True", canonicalizeLabel(val.label)))
}
buildRootDepsString := strings.Join(buildRootDeps, ",\n ")
return []byte(fmt.Sprintf(formatString, buildRootDepsString))
}
+// Returns a workspace-relative path containing build-related metadata required
+// for interfacing with Bazel. Example: out/soong/bazel.
+func (context *bazelContext) intermediatesDir() string {
+ return filepath.Join(context.buildDir, "bazel")
+}
+
// Issues commands to Bazel to receive results for all cquery requests
// queued in the BazelContext.
func (context *bazelContext) InvokeBazel() error {
@@ -276,26 +309,38 @@
var cqueryOutput string
var err error
+
+ err = os.Mkdir(absolutePath(context.intermediatesDir()), 0777)
+ if err != nil {
+ return err
+ }
err = ioutil.WriteFile(
- absolutePath(filepath.Join(context.buildDir, "main.bzl")),
+ absolutePath(filepath.Join(context.intermediatesDir(), "main.bzl")),
context.mainBzlFileContents(), 0666)
if err != nil {
return err
}
err = ioutil.WriteFile(
- absolutePath(filepath.Join(context.buildDir, "BUILD.bazel")),
+ absolutePath(filepath.Join(context.intermediatesDir(), "BUILD.bazel")),
context.mainBuildFileContents(), 0666)
if err != nil {
return err
}
- cquery_file_relpath := filepath.Join(context.buildDir, "buildroot.cquery")
+ cquery_file_relpath := filepath.Join(context.intermediatesDir(), "buildroot.cquery")
err = ioutil.WriteFile(
absolutePath(cquery_file_relpath),
context.cqueryStarlarkFileContents(), 0666)
if err != nil {
return err
}
- buildroot_label := fmt.Sprintf("//%s:buildroot", context.buildDir)
+ workspace_file_relpath := filepath.Join(context.intermediatesDir(), "WORKSPACE.bazel")
+ err = ioutil.WriteFile(
+ absolutePath(workspace_file_relpath),
+ context.workspaceFileContents(), 0666)
+ if err != nil {
+ return err
+ }
+ buildroot_label := "//:buildroot"
cqueryOutput, err = context.issueBazelCommand("cquery",
[]string{fmt.Sprintf("deps(%s)", buildroot_label)},
"--output=starlark",
@@ -314,7 +359,7 @@
}
for val, _ := range context.requests {
- if cqueryResult, ok := cqueryResults[val.label]; ok {
+ if cqueryResult, ok := cqueryResults[canonicalizeLabel(val.label)]; ok {
context.results[val] = string(cqueryResult)
} else {
return fmt.Errorf("missing result for bazel target %s", val.label)
diff --git a/android/config.go b/android/config.go
index e87a4ac..d833c5c 100644
--- a/android/config.go
+++ b/android/config.go
@@ -126,6 +126,8 @@
// in tests when a path doesn't exist.
testAllowNonExistentPaths bool
+ ninjaFileDepsSet sync.Map
+
OncePer
}
diff --git a/android/defaults.go b/android/defaults.go
index eb013d7..44753ce 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -183,7 +183,7 @@
initAndroidModuleBase(module)
initProductVariableModule(module)
- InitArchModule(module)
+ initArchModule(module)
InitDefaultableModule(module)
// Add properties that will not have defaults applied to them.
diff --git a/android/makevars.go b/android/makevars.go
index 3ca7792..f784395 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -139,15 +139,24 @@
MakeVars(ctx MakeVarsContext)
}
-// registerSingletonMakeVarsProvider adds a singleton that implements SingletonMakeVarsProvider to the list of
-// MakeVarsProviders to run.
-func registerSingletonMakeVarsProvider(singleton SingletonMakeVarsProvider) {
- singletonMakeVarsProviders = append(singletonMakeVarsProviders,
- makeVarsProvider{pctx, SingletonmakeVarsProviderAdapter(singleton)})
+var singletonMakeVarsProvidersKey = NewOnceKey("singletonMakeVarsProvidersKey")
+
+// registerSingletonMakeVarsProvider adds a singleton that implements SingletonMakeVarsProvider to
+// the list of MakeVarsProviders to run.
+func registerSingletonMakeVarsProvider(config Config, singleton SingletonMakeVarsProvider) {
+ // Singletons are registered on the Context and may be different between different Contexts,
+ // for example when running multiple tests. Store the SingletonMakeVarsProviders in the
+ // Config so they are attached to the Context.
+ singletonMakeVarsProviders := config.Once(singletonMakeVarsProvidersKey, func() interface{} {
+ return &[]makeVarsProvider{}
+ }).(*[]makeVarsProvider)
+
+ *singletonMakeVarsProviders = append(*singletonMakeVarsProviders,
+ makeVarsProvider{pctx, singletonMakeVarsProviderAdapter(singleton)})
}
-// SingletonmakeVarsProviderAdapter converts a SingletonMakeVarsProvider to a MakeVarsProvider.
-func SingletonmakeVarsProviderAdapter(singleton SingletonMakeVarsProvider) MakeVarsProvider {
+// singletonMakeVarsProviderAdapter converts a SingletonMakeVarsProvider to a MakeVarsProvider.
+func singletonMakeVarsProviderAdapter(singleton SingletonMakeVarsProvider) MakeVarsProvider {
return func(ctx MakeVarsContext) { singleton.MakeVars(ctx) }
}
@@ -175,9 +184,6 @@
// Collection of makevars providers that are registered in init() methods.
var makeVarsInitProviders []makeVarsProvider
-// Collection of singleton makevars providers that are not registered as part of init() methods.
-var singletonMakeVarsProviders []makeVarsProvider
-
type makeVarsContext struct {
SingletonContext
config Config
@@ -224,7 +230,11 @@
var vars []makeVarsVariable
var dists []dist
var phonies []phony
- for _, provider := range append(makeVarsInitProviders) {
+
+ providers := append([]makeVarsProvider(nil), makeVarsInitProviders...)
+ providers = append(providers, *ctx.Config().Get(singletonMakeVarsProvidersKey).(*[]makeVarsProvider)...)
+
+ for _, provider := range providers {
mctx := &makeVarsContext{
SingletonContext: ctx,
pctx: provider.pctx,
@@ -237,25 +247,6 @@
dists = append(dists, mctx.dists...)
}
- for _, provider := range append(singletonMakeVarsProviders) {
- mctx := &makeVarsContext{
- SingletonContext: ctx,
- pctx: provider.pctx,
- }
-
- provider.call(mctx)
-
- vars = append(vars, mctx.vars...)
- phonies = append(phonies, mctx.phonies...)
- dists = append(dists, mctx.dists...)
- }
-
- // Clear singleton makevars providers after use. Since these are in-memory
- // singletons, this ensures state is reset if the build tree is processed
- // multiple times.
- // TODO(cparsons): Clean up makeVarsProviders to be part of the context.
- singletonMakeVarsProviders = nil
-
ctx.VisitAllModules(func(m Module) {
if provider, ok := m.(ModuleMakeVarsProvider); ok && m.Enabled() {
mctx := &makeVarsContext{
diff --git a/android/module.go b/android/module.go
index d677406..6b659d2 100644
--- a/android/module.go
+++ b/android/module.go
@@ -440,6 +440,7 @@
TargetRequiredModuleNames() []string
FilesToInstall() InstallPaths
+ PackagingSpecs() []PackagingSpec
}
// Qualified id for a module
@@ -716,7 +717,9 @@
DebugMutators []string `blueprint:"mutated"`
DebugVariations []string `blueprint:"mutated"`
- // set by ImageMutator
+ // ImageVariation is set by ImageMutator to specify which image this variation is for,
+ // for example "" for core or "recovery" for recovery. It will often be set to one of the
+ // constants in image.go, but can also be set to a custom value by individual module types.
ImageVariation string `blueprint:"mutated"`
}
@@ -765,27 +768,32 @@
type HostOrDeviceSupported int
const (
- _ HostOrDeviceSupported = iota
+ hostSupported = 1 << iota
+ hostCrossSupported
+ deviceSupported
+ hostDefault
+ deviceDefault
// Host and HostCross are built by default. Device is not supported.
- HostSupported
+ HostSupported = hostSupported | hostCrossSupported | hostDefault
// Host is built by default. HostCross and Device are not supported.
- HostSupportedNoCross
+ HostSupportedNoCross = hostSupported | hostDefault
// Device is built by default. Host and HostCross are not supported.
- DeviceSupported
+ DeviceSupported = deviceSupported | deviceDefault
// Device is built by default. Host and HostCross are supported.
- HostAndDeviceSupported
+ HostAndDeviceSupported = hostSupported | hostCrossSupported | deviceSupported | deviceDefault
// Host, HostCross, and Device are built by default.
- HostAndDeviceDefault
+ HostAndDeviceDefault = hostSupported | hostCrossSupported | hostDefault |
+ deviceSupported | deviceDefault
// Nothing is supported. This is not exposed to the user, but used to mark a
// host only module as unsupported when the module type is not supported on
// the host OS. E.g. benchmarks are supported on Linux but not Darwin.
- NeitherHostNorDeviceSupported
+ NeitherHostNorDeviceSupported = 0
)
type moduleKind int
@@ -819,6 +827,8 @@
m.base().module = m
}
+// InitAndroidModule initializes the Module as an Android module that is not architecture-specific.
+// It adds the common properties, for example "name" and "enabled".
func InitAndroidModule(m Module) {
initAndroidModuleBase(m)
base := m.base()
@@ -838,6 +848,12 @@
setPrimaryVisibilityProperty(m, "visibility", &base.commonProperties.Visibility)
}
+// InitAndroidArchModule initializes the Module as an Android module that is architecture-specific.
+// It adds the common properties, for example "name" and "enabled", as well as runtime generated
+// property structs for architecture-specific versions of generic properties tagged with
+// `android:"arch_variant"`.
+//
+// InitAndroidModule should not be called if InitAndroidArchModule was called.
func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
InitAndroidModule(m)
@@ -847,21 +863,37 @@
base.commonProperties.ArchSpecific = true
base.commonProperties.UseTargetVariants = true
- switch hod {
- case HostAndDeviceSupported, HostAndDeviceDefault:
+ if hod&hostSupported != 0 && hod&deviceSupported != 0 {
m.AddProperties(&base.hostAndDeviceProperties)
}
- InitArchModule(m)
+ initArchModule(m)
}
+// InitAndroidMultiTargetsArchModule initializes the Module as an Android module that is
+// architecture-specific, but will only have a single variant per OS that handles all the
+// architectures simultaneously. The list of Targets that it must handle will be available from
+// ModuleContext.MultiTargets. It adds the common properties, for example "name" and "enabled", as
+// well as runtime generated property structs for architecture-specific versions of generic
+// properties tagged with `android:"arch_variant"`.
+//
+// InitAndroidModule or InitAndroidArchModule should not be called if
+// InitAndroidMultiTargetsArchModule was called.
func InitAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
InitAndroidArchModule(m, hod, defaultMultilib)
m.base().commonProperties.UseTargetVariants = false
}
-// As InitAndroidMultiTargetsArchModule except it creates an additional CommonOS variant that
-// has dependencies on all the OsType specific variants.
+// InitCommonOSAndroidMultiTargetsArchModule initializes the Module as an Android module that is
+// architecture-specific, but will only have a single variant per OS that handles all the
+// architectures simultaneously, and will also have an additional CommonOS variant that has
+// dependencies on all the OS-specific variants. The list of Targets that it must handle will be
+// available from ModuleContext.MultiTargets. It adds the common properties, for example "name" and
+// "enabled", as well as runtime generated property structs for architecture-specific versions of
+// generic properties tagged with `android:"arch_variant"`.
+//
+// InitAndroidModule, InitAndroidArchModule or InitAndroidMultiTargetsArchModule should not be
+// called if InitCommonOSAndroidMultiTargetsArchModule was called.
func InitCommonOSAndroidMultiTargetsArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) {
InitAndroidArchModule(m, hod, defaultMultilib)
m.base().commonProperties.UseTargetVariants = false
@@ -934,6 +966,7 @@
noAddressSanitizer bool
installFiles InstallPaths
checkbuildFiles Paths
+ packagingSpecs []PackagingSpec
noticeFiles Paths
phonies map[string]Paths
@@ -1098,43 +1131,54 @@
return m.commonProperties.CommonOSVariant
}
-func (m *ModuleBase) supportsTarget(target Target, config Config) bool {
- switch m.commonProperties.HostOrDeviceSupported {
- case HostSupported:
- return target.Os.Class == Host
- case HostSupportedNoCross:
- return target.Os.Class == Host && !target.HostCross
- case DeviceSupported:
- return target.Os.Class == Device
- case HostAndDeviceSupported, HostAndDeviceDefault:
- supported := false
- if Bool(m.hostAndDeviceProperties.Host_supported) ||
- (m.commonProperties.HostOrDeviceSupported == HostAndDeviceDefault &&
- m.hostAndDeviceProperties.Host_supported == nil) {
- supported = supported || target.Os.Class == Host
+// supportsTarget returns true if the given Target is supported by the current module.
+func (m *ModuleBase) supportsTarget(target Target) bool {
+ switch target.Os.Class {
+ case Host:
+ if target.HostCross {
+ return m.HostCrossSupported()
+ } else {
+ return m.HostSupported()
}
- if m.hostAndDeviceProperties.Device_supported == nil ||
- *m.hostAndDeviceProperties.Device_supported {
- supported = supported || target.Os.Class == Device
- }
- return supported
+ case Device:
+ return m.DeviceSupported()
default:
return false
}
}
+// DeviceSupported returns true if the current module is supported and enabled for device targets,
+// i.e. the factory method set the HostOrDeviceSupported value to include device support and
+// the device support is enabled by default or enabled by the device_supported property.
func (m *ModuleBase) DeviceSupported() bool {
- return m.commonProperties.HostOrDeviceSupported == DeviceSupported ||
- m.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
- (m.hostAndDeviceProperties.Device_supported == nil ||
- *m.hostAndDeviceProperties.Device_supported)
+ hod := m.commonProperties.HostOrDeviceSupported
+ // deviceEnabled is true if the device_supported property is true or the HostOrDeviceSupported
+ // value has the deviceDefault bit set.
+ deviceEnabled := proptools.BoolDefault(m.hostAndDeviceProperties.Device_supported, hod&deviceDefault != 0)
+ return hod&deviceSupported != 0 && deviceEnabled
}
+// HostSupported returns true if the current module is supported and enabled for host targets,
+// i.e. the factory method set the HostOrDeviceSupported value to include host support and
+// the host support is enabled by default or enabled by the host_supported property.
func (m *ModuleBase) HostSupported() bool {
- return m.commonProperties.HostOrDeviceSupported == HostSupported ||
- m.commonProperties.HostOrDeviceSupported == HostAndDeviceSupported &&
- (m.hostAndDeviceProperties.Host_supported != nil &&
- *m.hostAndDeviceProperties.Host_supported)
+ hod := m.commonProperties.HostOrDeviceSupported
+ // hostEnabled is true if the host_supported property is true or the HostOrDeviceSupported
+ // value has the hostDefault bit set.
+ hostEnabled := proptools.BoolDefault(m.hostAndDeviceProperties.Host_supported, hod&hostDefault != 0)
+ return hod&hostSupported != 0 && hostEnabled
+}
+
+// HostCrossSupported returns true if the current module is supported and enabled for host cross
+// targets, i.e. the factory method set the HostOrDeviceSupported value to include host cross
+// support and the host cross support is enabled by default or enabled by the
+// host_supported property.
+func (m *ModuleBase) HostCrossSupported() bool {
+ hod := m.commonProperties.HostOrDeviceSupported
+ // hostEnabled is true if the host_supported property is true or the HostOrDeviceSupported
+ // value has the hostDefault bit set.
+ hostEnabled := proptools.BoolDefault(m.hostAndDeviceProperties.Host_supported, hod&hostDefault != 0)
+ return hod&hostCrossSupported != 0 && hostEnabled
}
func (m *ModuleBase) Platform() bool {
@@ -1259,6 +1303,10 @@
return m.installFiles
}
+func (m *ModuleBase) PackagingSpecs() []PackagingSpec {
+ return m.packagingSpecs
+}
+
func (m *ModuleBase) NoAddressSanitizer() bool {
return m.noAddressSanitizer
}
@@ -1581,6 +1629,7 @@
m.installFiles = append(m.installFiles, ctx.installFiles...)
m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
+ m.packagingSpecs = append(m.packagingSpecs, ctx.packagingSpecs...)
m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
for k, v := range ctx.phonies {
@@ -1748,6 +1797,7 @@
type moduleContext struct {
bp blueprint.ModuleContext
baseModuleContext
+ packagingSpecs []PackagingSpec
installDeps InstallPaths
installFiles InstallPaths
checkbuildFiles Paths
@@ -2284,16 +2334,15 @@
func (m *moduleContext) InstallFile(installPath InstallPath, name string, srcPath Path,
deps ...Path) InstallPath {
- return m.installFile(installPath, name, srcPath, Cp, deps)
+ return m.installFile(installPath, name, srcPath, deps, false)
}
func (m *moduleContext) InstallExecutable(installPath InstallPath, name string, srcPath Path,
deps ...Path) InstallPath {
- return m.installFile(installPath, name, srcPath, CpExecutable, deps)
+ return m.installFile(installPath, name, srcPath, deps, true)
}
-func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path,
- rule blueprint.Rule, deps []Path) InstallPath {
+func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path, deps []Path, executable bool) InstallPath {
fullInstallPath := installPath.Join(m, name)
m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
@@ -2312,6 +2361,11 @@
orderOnlyDeps = deps
}
+ rule := Cp
+ if executable {
+ rule = CpExecutable
+ }
+
m.Build(pctx, BuildParams{
Rule: rule,
Description: "install " + fullInstallPath.Base(),
@@ -2324,6 +2378,14 @@
m.installFiles = append(m.installFiles, fullInstallPath)
}
+
+ m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
+ relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
+ srcPath: srcPath,
+ symlinkTarget: "",
+ executable: executable,
+ })
+
m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
return fullInstallPath
}
@@ -2332,12 +2394,12 @@
fullInstallPath := installPath.Join(m, name)
m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, true)
+ relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
+ if err != nil {
+ panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
+ }
if !m.skipInstall(fullInstallPath) {
- relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
- if err != nil {
- panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
- }
m.Build(pctx, BuildParams{
Rule: Symlink,
Description: "install symlink " + fullInstallPath.Base(),
@@ -2352,6 +2414,14 @@
m.installFiles = append(m.installFiles, fullInstallPath)
m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
}
+
+ m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
+ relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
+ srcPath: nil,
+ symlinkTarget: relPath,
+ executable: false,
+ })
+
return fullInstallPath
}
@@ -2374,6 +2444,14 @@
m.installFiles = append(m.installFiles, fullInstallPath)
}
+
+ m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
+ relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
+ srcPath: nil,
+ symlinkTarget: absPath,
+ executable: false,
+ })
+
return fullInstallPath
}
diff --git a/android/ninja_deps.go b/android/ninja_deps.go
new file mode 100644
index 0000000..2f442d5
--- /dev/null
+++ b/android/ninja_deps.go
@@ -0,0 +1,43 @@
+// Copyright 2020 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 "sort"
+
+func (c *config) addNinjaFileDeps(deps ...string) {
+ for _, dep := range deps {
+ c.ninjaFileDepsSet.Store(dep, true)
+ }
+}
+
+func (c *config) ninjaFileDeps() []string {
+ var deps []string
+ c.ninjaFileDepsSet.Range(func(key, value interface{}) bool {
+ deps = append(deps, key.(string))
+ return true
+ })
+ sort.Strings(deps)
+ return deps
+}
+
+func ninjaDepsSingletonFactory() Singleton {
+ return &ninjaDepsSingleton{}
+}
+
+type ninjaDepsSingleton struct{}
+
+func (ninjaDepsSingleton) GenerateBuildActions(ctx SingletonContext) {
+ ctx.AddNinjaFileDeps(ctx.Config().ninjaFileDeps()...)
+}
diff --git a/android/ninja_deps_test.go b/android/ninja_deps_test.go
new file mode 100644
index 0000000..d3775ed
--- /dev/null
+++ b/android/ninja_deps_test.go
@@ -0,0 +1,75 @@
+// Copyright 2020 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 (
+ "testing"
+)
+
+func init() {
+ // This variable uses ExistentPathForSource on a PackageVarContext, which is a PathContext
+ // that is not a PathGlobContext. That requires the deps to be stored in the Config.
+ pctx.VariableFunc("test_ninja_deps_variable", func(ctx PackageVarContext) string {
+ // Using ExistentPathForSource to look for a file that does not exist in a directory that
+ // does exist (test_ninja_deps) from a PackageVarContext adds a dependency from build.ninja
+ // to the directory.
+ if ExistentPathForSource(ctx, "test_ninja_deps/does_not_exist").Valid() {
+ return "true"
+ } else {
+ return "false"
+ }
+ })
+}
+
+func testNinjaDepsSingletonFactory() Singleton {
+ return testNinjaDepsSingleton{}
+}
+
+type testNinjaDepsSingleton struct{}
+
+func (testNinjaDepsSingleton) GenerateBuildActions(ctx SingletonContext) {
+ // Reference the test_ninja_deps_variable in a build statement so Blueprint is forced to
+ // evaluate it.
+ ctx.Build(pctx, BuildParams{
+ Rule: Cp,
+ Input: PathForTesting("foo"),
+ Output: PathForOutput(ctx, "test_ninja_deps_out"),
+ Args: map[string]string{
+ "cpFlags": "${test_ninja_deps_variable}",
+ },
+ })
+}
+
+func TestNinjaDeps(t *testing.T) {
+ fs := map[string][]byte{
+ "test_ninja_deps/exists": nil,
+ }
+ config := TestConfig(buildDir, nil, "", fs)
+
+ ctx := NewTestContext(config)
+ ctx.RegisterSingletonType("test_ninja_deps_singleton", testNinjaDepsSingletonFactory)
+ ctx.RegisterSingletonType("ninja_deps_singleton", ninjaDepsSingletonFactory)
+ ctx.Register()
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ FailIfErrored(t, errs)
+ ninjaDeps, errs := ctx.PrepareBuildActions(config)
+ FailIfErrored(t, errs)
+
+ // Verify that the ninja file has a dependency on the test_ninja_deps directory.
+ if g, w := ninjaDeps, "test_ninja_deps"; !InList(w, g) {
+ t.Errorf("expected %q in %q", w, g)
+ }
+}
diff --git a/android/package_ctx.go b/android/package_ctx.go
index 0de356e..6d0fcb3 100644
--- a/android/package_ctx.go
+++ b/android/package_ctx.go
@@ -56,7 +56,7 @@
e.errors = append(e.errors, fmt.Errorf(format, args...))
}
func (e *configErrorWrapper) AddNinjaFileDeps(deps ...string) {
- e.pctx.AddNinjaFileDeps(deps...)
+ e.config.addNinjaFileDeps(deps...)
}
type PackageVarContext interface {
diff --git a/android/packaging.go b/android/packaging.go
new file mode 100644
index 0000000..512e4ba
--- /dev/null
+++ b/android/packaging.go
@@ -0,0 +1,205 @@
+// Copyright 2020 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"
+ "path/filepath"
+
+ "github.com/google/blueprint"
+)
+
+// PackagingSpec abstracts a request to place a built artifact at a certain path in a package.
+// A package can be the traditional <partition>.img, but isn't limited to those. Other examples could
+// be a new filesystem image that is a subset of system.img (e.g. for an Android-like mini OS running
+// on a VM), or a zip archive for some of the host tools.
+type PackagingSpec struct {
+ // Path relative to the root of the package
+ relPathInPackage string
+
+ // The path to the built artifact
+ srcPath Path
+
+ // If this is not empty, then relPathInPackage should be a symlink to this target. (Then
+ // srcPath is of course ignored.)
+ symlinkTarget string
+
+ // Whether relPathInPackage should be marked as executable or not
+ executable bool
+}
+
+type PackageModule interface {
+ Module
+ packagingBase() *PackagingBase
+
+ // AddDeps adds dependencies to the `deps` modules. This should be called in DepsMutator.
+ AddDeps(ctx BottomUpMutatorContext)
+
+ // CopyDepsToZip zips the built artifacts of the dependencies into the given zip file and
+ // returns zip entries in it. This is expected to be called in GenerateAndroidBuildActions,
+ // followed by a build rule that unzips it and creates the final output (img, zip, tar.gz,
+ // etc.) from the extracted files
+ CopyDepsToZip(ctx ModuleContext, zipOut OutputPath) []string
+}
+
+// PackagingBase provides basic functionality for packaging dependencies. A module is expected to
+// include this struct and call InitPackageModule.
+type PackagingBase struct {
+ properties PackagingProperties
+
+ // Allows this module to skip missing dependencies. In most cases, this
+ // is not required, but for rare cases like when there's a dependency
+ // to a module which exists in certain repo checkouts, this is needed.
+ IgnoreMissingDependencies bool
+}
+
+type depsProperty struct {
+ // Modules to include in this package
+ Deps []string `android:"arch_variant"`
+}
+
+type packagingMultilibProperties struct {
+ First depsProperty `android:"arch_variant"`
+ Common depsProperty `android:"arch_variant"`
+ Lib32 depsProperty `android:"arch_variant"`
+ Lib64 depsProperty `android:"arch_variant"`
+}
+
+type PackagingProperties struct {
+ Deps []string `android:"arch_variant"`
+ Multilib packagingMultilibProperties `android:"arch_variant"`
+}
+
+type packagingDependencyTag struct{ blueprint.BaseDependencyTag }
+
+var depTag = packagingDependencyTag{}
+
+func InitPackageModule(p PackageModule) {
+ base := p.packagingBase()
+ p.AddProperties(&base.properties)
+}
+
+func (p *PackagingBase) packagingBase() *PackagingBase {
+ return p
+}
+
+// From deps and multilib.*.deps, select the dependencies that are for the given arch
+// deps is for the current archicture when this module is not configured for multi target.
+// When configured for multi target, deps is selected for each of the targets and is NOT
+// selected for the current architecture which would be Common.
+func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) []string {
+ var ret []string
+ if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
+ ret = append(ret, p.properties.Deps...)
+ } else if arch.Multilib == "lib32" {
+ ret = append(ret, p.properties.Multilib.Lib32.Deps...)
+ } else if arch.Multilib == "lib64" {
+ ret = append(ret, p.properties.Multilib.Lib64.Deps...)
+ } else if arch == Common {
+ ret = append(ret, p.properties.Multilib.Common.Deps...)
+ }
+ for i, t := range ctx.MultiTargets() {
+ if t.Arch.ArchType == arch {
+ ret = append(ret, p.properties.Deps...)
+ if i == 0 {
+ ret = append(ret, p.properties.Multilib.First.Deps...)
+ }
+ }
+ }
+ return FirstUniqueStrings(ret)
+}
+
+func (p *PackagingBase) getSupportedTargets(ctx BaseModuleContext) []Target {
+ var ret []Target
+ // The current and the common OS targets are always supported
+ ret = append(ret, ctx.Target())
+ if ctx.Arch().ArchType != Common {
+ ret = append(ret, Target{Os: ctx.Os(), Arch: Arch{ArchType: Common}})
+ }
+ // If this module is configured for multi targets, those should be supported as well
+ ret = append(ret, ctx.MultiTargets()...)
+ return ret
+}
+
+// See PackageModule.AddDeps
+func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext) {
+ for _, t := range p.getSupportedTargets(ctx) {
+ for _, dep := range p.getDepsForArch(ctx, t.Arch.ArchType) {
+ if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) {
+ continue
+ }
+ ctx.AddFarVariationDependencies(t.Variations(), depTag, dep)
+ }
+ }
+}
+
+// See PackageModule.CopyDepsToZip
+func (p *PackagingBase) CopyDepsToZip(ctx ModuleContext, zipOut OutputPath) (entries []string) {
+ var supportedArches []string
+ for _, t := range p.getSupportedTargets(ctx) {
+ supportedArches = append(supportedArches, t.Arch.ArchType.String())
+ }
+ m := make(map[string]PackagingSpec)
+ ctx.WalkDeps(func(child Module, parent Module) bool {
+ // Don't track modules with unsupported arch
+ // TODO(jiyong): remove this when aosp/1501613 lands.
+ if !InList(child.Target().Arch.ArchType.String(), supportedArches) {
+ return false
+ }
+ for _, ps := range child.PackagingSpecs() {
+ if _, ok := m[ps.relPathInPackage]; !ok {
+ m[ps.relPathInPackage] = ps
+ }
+ }
+ return true
+ })
+
+ builder := NewRuleBuilder()
+
+ dir := PathForModuleOut(ctx, ".zip").OutputPath
+ builder.Command().Text("rm").Flag("-rf").Text(dir.String())
+ builder.Command().Text("mkdir").Flag("-p").Text(dir.String())
+
+ seenDir := make(map[string]bool)
+ for _, k := range SortedStringKeys(m) {
+ ps := m[k]
+ destPath := dir.Join(ctx, ps.relPathInPackage).String()
+ destDir := filepath.Dir(destPath)
+ entries = append(entries, ps.relPathInPackage)
+ if _, ok := seenDir[destDir]; !ok {
+ seenDir[destDir] = true
+ builder.Command().Text("mkdir").Flag("-p").Text(destDir)
+ }
+ if ps.symlinkTarget == "" {
+ builder.Command().Text("cp").Input(ps.srcPath).Text(destPath)
+ } else {
+ builder.Command().Text("ln").Flag("-sf").Text(ps.symlinkTarget).Text(destPath)
+ }
+ if ps.executable {
+ builder.Command().Text("chmod").Flag("a+x").Text(destPath)
+ }
+ }
+
+ builder.Command().
+ BuiltTool(ctx, "soong_zip").
+ FlagWithOutput("-o ", zipOut).
+ FlagWithArg("-C ", dir.String()).
+ Flag("-L 0"). // no compression because this will be unzipped soon
+ FlagWithArg("-D ", dir.String())
+ builder.Command().Text("rm").Flag("-rf").Text(dir.String())
+
+ builder.Build(pctx, ctx, "zip_deps", fmt.Sprintf("Zipping deps for %s", ctx.ModuleName()))
+ return entries
+}
diff --git a/android/packaging_test.go b/android/packaging_test.go
new file mode 100644
index 0000000..7710c7f
--- /dev/null
+++ b/android/packaging_test.go
@@ -0,0 +1,188 @@
+// Copyright 2020 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 (
+ "reflect"
+ "testing"
+)
+
+// Module to be packaged
+type componentTestModule struct {
+ ModuleBase
+ props struct {
+ Deps []string
+ }
+}
+
+func componentTestModuleFactory() Module {
+ m := &componentTestModule{}
+ m.AddProperties(&m.props)
+ InitAndroidArchModule(m, HostAndDeviceSupported, MultilibBoth)
+ return m
+}
+
+func (m *componentTestModule) DepsMutator(ctx BottomUpMutatorContext) {
+ ctx.AddDependency(ctx.Module(), nil, m.props.Deps...)
+}
+
+func (m *componentTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ builtFile := PathForModuleOut(ctx, m.Name())
+ dir := ctx.Target().Arch.ArchType.Multilib
+ installDir := PathForModuleInstall(ctx, dir)
+ ctx.InstallFile(installDir, m.Name(), builtFile)
+}
+
+// Module that itself is a package
+type packageTestModule struct {
+ ModuleBase
+ PackagingBase
+
+ entries []string
+}
+
+func packageTestModuleFactory() Module {
+ module := &packageTestModule{}
+ InitPackageModule(module)
+ InitAndroidMultiTargetsArchModule(module, DeviceSupported, MultilibCommon)
+ return module
+}
+
+func (m *packageTestModule) DepsMutator(ctx BottomUpMutatorContext) {
+ m.AddDeps(ctx)
+}
+
+func (m *packageTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ zipFile := PathForModuleOut(ctx, "myzip.zip").OutputPath
+ m.entries = m.CopyDepsToZip(ctx, zipFile)
+}
+
+func runPackagingTest(t *testing.T, bp string, expected []string) {
+ t.Helper()
+
+ config := TestArchConfig(buildDir, nil, bp, nil)
+
+ ctx := NewTestArchContext(config)
+ ctx.RegisterModuleType("component", componentTestModuleFactory)
+ ctx.RegisterModuleType("package_module", packageTestModuleFactory)
+ ctx.Register()
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ FailIfErrored(t, errs)
+
+ p := ctx.ModuleForTests("package", "android_common").Module().(*packageTestModule)
+ actual := p.entries
+ actual = SortedUniqueStrings(actual)
+ expected = SortedUniqueStrings(expected)
+ if !reflect.DeepEqual(actual, expected) {
+ t.Errorf("\ngot: %v\nexpected: %v\n", actual, expected)
+ }
+}
+
+func TestPackagingBase(t *testing.T) {
+ runPackagingTest(t,
+ `
+ component {
+ name: "foo",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ }
+ `, []string{"lib64/foo"})
+
+ runPackagingTest(t,
+ `
+ component {
+ name: "foo",
+ deps: ["bar"],
+ }
+
+ component {
+ name: "bar",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ }
+ `, []string{"lib64/foo", "lib64/bar"})
+
+ runPackagingTest(t,
+ `
+ component {
+ name: "foo",
+ deps: ["bar"],
+ }
+
+ component {
+ name: "bar",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ compile_multilib: "both",
+ }
+ `, []string{"lib32/foo", "lib32/bar", "lib64/foo", "lib64/bar"})
+
+ runPackagingTest(t,
+ `
+ component {
+ name: "foo",
+ }
+
+ component {
+ name: "bar",
+ compile_multilib: "32",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ multilib: {
+ lib32: {
+ deps: ["bar"],
+ },
+ },
+ compile_multilib: "both",
+ }
+ `, []string{"lib32/foo", "lib32/bar", "lib64/foo"})
+
+ runPackagingTest(t,
+ `
+ component {
+ name: "foo",
+ }
+
+ component {
+ name: "bar",
+ }
+
+ package_module {
+ name: "package",
+ deps: ["foo"],
+ multilib: {
+ first: {
+ deps: ["bar"],
+ },
+ },
+ compile_multilib: "both",
+ }
+ `, []string{"lib32/foo", "lib64/foo", "lib64/bar"})
+}
diff --git a/android/path_properties.go b/android/path_properties.go
index 6b1cdb3..4bb706a 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -21,27 +21,31 @@
"github.com/google/blueprint/proptools"
)
+// This file implements support for automatically adding dependencies on any module referenced
+// with the ":module" module reference syntax in a property that is annotated with `android:"path"`.
+// The dependency is used by android.PathForModuleSrc to convert the module reference into the path
+// to the output file of the referenced module.
+
func registerPathDepsMutator(ctx RegisterMutatorsContext) {
ctx.BottomUp("pathdeps", pathDepsMutator).Parallel()
}
-// The pathDepsMutator automatically adds dependencies on any module that is listed with ":module" syntax in a
-// property that is tagged with android:"path".
+// The pathDepsMutator automatically adds dependencies on any module that is listed with the
+// ":module" module reference syntax in a property that is tagged with `android:"path"`.
func pathDepsMutator(ctx BottomUpMutatorContext) {
- m := ctx.Module().(Module)
- if m == nil {
- return
- }
+ props := ctx.Module().base().generalProperties
- props := m.base().generalProperties
-
+ // Iterate through each property struct of the module extracting the contents of all properties
+ // tagged with `android:"path"`.
var pathProperties []string
for _, ps := range props {
- pathProperties = append(pathProperties, pathPropertiesForPropertyStruct(ctx, ps)...)
+ pathProperties = append(pathProperties, pathPropertiesForPropertyStruct(ps)...)
}
+ // Remove duplicates to avoid multiple dependencies.
pathProperties = FirstUniqueStrings(pathProperties)
+ // Add dependencies to anything that is a module reference.
for _, s := range pathProperties {
if m, t := SrcIsModuleWithTag(s); m != "" {
ctx.AddDependency(ctx.Module(), sourceOrOutputDepTag(t), m)
@@ -49,34 +53,45 @@
}
}
-// pathPropertiesForPropertyStruct uses the indexes of properties that are tagged with android:"path" to extract
-// all their values from a property struct, returning them as a single slice of strings..
-func pathPropertiesForPropertyStruct(ctx BottomUpMutatorContext, ps interface{}) []string {
+// pathPropertiesForPropertyStruct uses the indexes of properties that are tagged with
+// android:"path" to extract all their values from a property struct, returning them as a single
+// slice of strings.
+func pathPropertiesForPropertyStruct(ps interface{}) []string {
v := reflect.ValueOf(ps)
if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
panic(fmt.Errorf("type %s is not a pointer to a struct", v.Type()))
}
+
+ // If the property struct is a nil pointer it can't have any paths set in it.
if v.IsNil() {
return nil
}
+
+ // v is now the reflect.Value for the concrete property struct.
v = v.Elem()
+ // Get or create the list of indexes of properties that are tagged with `android:"path"`.
pathPropertyIndexes := pathPropertyIndexesForPropertyStruct(ps)
var ret []string
for _, i := range pathPropertyIndexes {
+ // Turn an index into a field.
sv := fieldByIndex(v, i)
if !sv.IsValid() {
+ // Skip properties inside a nil pointer.
continue
}
+ // If the field is a non-nil pointer step into it.
if sv.Kind() == reflect.Ptr {
if sv.IsNil() {
continue
}
sv = sv.Elem()
}
+
+ // Collect paths from all strings and slices of strings.
switch sv.Kind() {
case reflect.String:
ret = append(ret, sv.String())
@@ -91,8 +106,8 @@
return ret
}
-// fieldByIndex is like reflect.Value.FieldByIndex, but returns an invalid reflect.Value when traversing a nil pointer
-// to a struct.
+// fieldByIndex is like reflect.Value.FieldByIndex, but returns an invalid reflect.Value when
+// traversing a nil pointer to a struct.
func fieldByIndex(v reflect.Value, index []int) reflect.Value {
if len(index) == 1 {
return v.Field(index[0])
@@ -111,9 +126,9 @@
var pathPropertyIndexesCache OncePer
-// pathPropertyIndexesForPropertyStruct returns a list of all of the indexes of properties in property struct type that
-// are tagged with android:"path". Each index is a []int suitable for passing to reflect.Value.FieldByIndex. The value
-// is cached in a global cache by type.
+// pathPropertyIndexesForPropertyStruct returns a list of all of the indexes of properties in
+// property struct type that are tagged with `android:"path"`. Each index is a []int suitable for
+// passing to reflect.Value.FieldByIndex. The value is cached in a global cache by type.
func pathPropertyIndexesForPropertyStruct(ps interface{}) [][]int {
key := NewCustomOnceKey(reflect.TypeOf(ps))
return pathPropertyIndexesCache.Once(key, func() interface{} {
diff --git a/android/register.go b/android/register.go
index bd824c9..08e47b3 100644
--- a/android/register.go
+++ b/android/register.go
@@ -29,7 +29,7 @@
type singleton struct {
name string
- factory blueprint.SingletonFactory
+ factory SingletonFactory
}
var singletons []singleton
@@ -57,11 +57,11 @@
// SingletonFactoryAdaptor wraps a SingletonFactory into a blueprint.SingletonFactory by converting
// a Singleton into a blueprint.Singleton
-func SingletonFactoryAdaptor(factory SingletonFactory) blueprint.SingletonFactory {
+func SingletonFactoryAdaptor(ctx *Context, factory SingletonFactory) blueprint.SingletonFactory {
return func() blueprint.Singleton {
singleton := factory()
if makevars, ok := singleton.(SingletonMakeVarsProvider); ok {
- registerSingletonMakeVarsProvider(makevars)
+ registerSingletonMakeVarsProvider(ctx.config, makevars)
}
return &singletonAdaptor{Singleton: singleton}
}
@@ -72,11 +72,11 @@
}
func RegisterSingletonType(name string, factory SingletonFactory) {
- singletons = append(singletons, singleton{name, SingletonFactoryAdaptor(factory)})
+ singletons = append(singletons, singleton{name, factory})
}
func RegisterPreSingletonType(name string, factory SingletonFactory) {
- preSingletons = append(preSingletons, singleton{name, SingletonFactoryAdaptor(factory)})
+ preSingletons = append(preSingletons, singleton{name, factory})
}
type Context struct {
@@ -92,7 +92,7 @@
func (ctx *Context) Register() {
for _, t := range preSingletons {
- ctx.RegisterPreSingletonType(t.name, t.factory)
+ ctx.RegisterPreSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
}
for _, t := range moduleTypes {
@@ -100,21 +100,23 @@
}
for _, t := range singletons {
- ctx.RegisterSingletonType(t.name, t.factory)
+ ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
}
registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps)
- ctx.RegisterSingletonType("bazeldeps", SingletonFactoryAdaptor(BazelSingleton))
+ ctx.RegisterSingletonType("bazeldeps", SingletonFactoryAdaptor(ctx, BazelSingleton))
// Register phony just before makevars so it can write out its phony rules as Make rules
- ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(phonySingletonFactory))
+ ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(ctx, phonySingletonFactory))
// Register makevars after other singletons so they can export values through makevars
- ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(makeVarsSingletonFunc))
+ ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(ctx, makeVarsSingletonFunc))
- // Register env last so that it can track all used environment variables
- ctx.RegisterSingletonType("env", SingletonFactoryAdaptor(EnvSingleton))
+ // Register env and ninjadeps last so that they can track all used environment variables and
+ // Ninja file dependencies stored in the config.
+ ctx.RegisterSingletonType("env", SingletonFactoryAdaptor(ctx, EnvSingleton))
+ ctx.RegisterSingletonType("ninjadeps", SingletonFactoryAdaptor(ctx, ninjaDepsSingletonFactory))
}
func ModuleTypeFactories() map[string]ModuleFactory {
diff --git a/android/testing.go b/android/testing.go
index d83cecc..1e2ae13 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -104,7 +104,7 @@
}
func (ctx *TestContext) RegisterSingletonType(name string, factory SingletonFactory) {
- ctx.Context.RegisterSingletonType(name, SingletonFactoryAdaptor(factory))
+ ctx.Context.RegisterSingletonType(name, SingletonFactoryAdaptor(ctx.Context, factory))
}
func (ctx *TestContext) ModuleForTests(name, variant string) TestingModule {
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index 739a965..4540a1f 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -214,6 +214,8 @@
"LOCAL_PRIVATE_PLATFORM_APIS": "platform_apis",
"LOCAL_JETIFIER_ENABLED": "jetifier",
+
+ "LOCAL_IS_UNIT_TEST": "unit_test",
})
}
diff --git a/androidmk/androidmk/androidmk.go b/androidmk/androidmk/androidmk.go
index 03cf74d..f4e5fa0 100644
--- a/androidmk/androidmk/androidmk.go
+++ b/androidmk/androidmk/androidmk.go
@@ -137,7 +137,14 @@
switch x := node.(type) {
case *mkparser.Comment:
- file.insertComment("//" + x.Comment)
+ // Split the comment on escaped newlines and then
+ // add each chunk separately.
+ chunks := strings.Split(x.Comment, "\\\n")
+ file.insertComment("//" + chunks[0])
+ for i := 1; i < len(chunks); i++ {
+ file.bpPos.Line++
+ file.insertComment("//" + chunks[i])
+ }
case *mkparser.Assignment:
handleAssignment(file, x, assignmentCond)
case *mkparser.Directive:
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 16cb138..f32ff2a 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -1260,10 +1260,10 @@
desc: "comment with ESC",
in: `
# Comment line 1 \
-# Comment line 2
+ Comment line 2
`,
expected: `
-// Comment line 1 \
+// Comment line 1
// Comment line 2
`,
},
diff --git a/androidmk/parser/parser.go b/androidmk/parser/parser.go
index 86dabf9..c14910a 100644
--- a/androidmk/parser/parser.go
+++ b/androidmk/parser/parser.go
@@ -212,8 +212,21 @@
expression := SimpleMakeString("", pos)
switch d {
- case "endif", "endef", "else":
+ case "endif", "endef":
// Nothing
+ case "else":
+ p.ignoreSpaces()
+ if p.tok != '\n' {
+ d = p.scanner.TokenText()
+ p.accept(scanner.Ident)
+ if d == "ifdef" || d == "ifndef" || d == "ifeq" || d == "ifneq" {
+ d = "el" + d
+ p.ignoreSpaces()
+ expression = p.parseExpression()
+ } else {
+ p.errorf("expected ifdef/ifndef/ifeq/ifneq, found %s", d)
+ }
+ }
case "define":
expression, endPos = p.parseDefine()
default:
@@ -484,12 +497,6 @@
switch p.tok {
case '\\':
p.parseEscape()
- if p.tok == '\n' {
- // Special case: '\' does not "escape" newline in comment (b/127521510)
- comment += "\\"
- p.accept(p.tok)
- break loop
- }
comment += "\\" + p.scanner.TokenText()
p.accept(p.tok)
case '\n':
diff --git a/apex/apex.go b/apex/apex.go
index 91770f4..ce323ca 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -33,19 +33,456 @@
"android/soong/sh"
)
+func init() {
+ android.RegisterModuleType("apex", BundleFactory)
+ android.RegisterModuleType("apex_test", testApexBundleFactory)
+ android.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
+ android.RegisterModuleType("apex_defaults", defaultsFactory)
+ android.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
+ android.RegisterModuleType("override_apex", overrideApexFactory)
+ android.RegisterModuleType("apex_set", apexSetFactory)
+
+ android.PreDepsMutators(RegisterPreDepsMutators)
+ android.PostDepsMutators(RegisterPostDepsMutators)
+}
+
+func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
+ ctx.TopDown("apex_vndk", apexVndkMutator).Parallel()
+ ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel()
+}
+
+func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
+ ctx.TopDown("apex_deps", apexDepsMutator).Parallel()
+ ctx.BottomUp("apex_unique", apexUniqueVariationsMutator).Parallel()
+ ctx.BottomUp("apex_test_for_deps", apexTestForDepsMutator).Parallel()
+ ctx.BottomUp("apex_test_for", apexTestForMutator).Parallel()
+ ctx.BottomUp("apex", apexMutator).Parallel()
+ ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel()
+ ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel()
+ ctx.BottomUp("mark_platform_availability", markPlatformAvailability).Parallel()
+}
+
+type apexBundleProperties struct {
+ // Json manifest file describing meta info of this APEX bundle. Default:
+ // "apex_manifest.json"
+ Manifest *string `android:"path"`
+
+ // AndroidManifest.xml file used for the zip container of this APEX bundle.
+ // If unspecified, a default one is automatically generated.
+ AndroidManifest *string `android:"path"`
+
+ // Canonical name of the APEX bundle. Used to determine the path to the activated APEX on
+ // device (/apex/<apex_name>).
+ // If unspecified, defaults to the value of name.
+ Apex_name *string
+
+ // Determines the file contexts file for setting security context to each file in this APEX bundle.
+ // For platform APEXes, this should points to a file under /system/sepolicy
+ // Default: /system/sepolicy/apex/<module_name>_file_contexts.
+ File_contexts *string `android:"path"`
+
+ ApexNativeDependencies
+
+ // List of java libraries that are embedded inside this APEX bundle
+ Java_libs []string
+
+ // List of prebuilt files that are embedded inside this APEX bundle
+ Prebuilts []string
+
+ // List of BPF programs inside APEX
+ Bpfs []string
+
+ // Name of the apex_key module that provides the private key to sign APEX
+ Key *string
+
+ // The type of APEX to build. Controls what the APEX payload is. Either
+ // 'image', 'zip' or 'both'. Default: 'image'.
+ Payload_type *string
+
+ // The name of a certificate in the default certificate directory, blank to use the default product certificate,
+ // or an android_app_certificate module name in the form ":module".
+ Certificate *string
+
+ // Whether this APEX is installable to one of the partitions. Default: true.
+ Installable *bool
+
+ // For native libraries and binaries, use the vendor variant instead of the core (platform) variant.
+ // Default is false.
+ Use_vendor *bool
+
+ // For telling the apex to ignore special handling for system libraries such as bionic. Default is false.
+ Ignore_system_library_special_case *bool
+
+ Multilib apexMultilibProperties
+
+ // List of sanitizer names that this APEX is enabled for
+ SanitizerNames []string `blueprint:"mutated"`
+
+ PreventInstall bool `blueprint:"mutated"`
+
+ HideFromMake bool `blueprint:"mutated"`
+
+ // package format of this apex variant; could be non-flattened, flattened, or zip.
+ // imageApex, zipApex or flattened
+ ApexType apexPackaging `blueprint:"mutated"`
+
+ // List of SDKs that are used to build this APEX. A reference to an SDK should be either
+ // `name#version` or `name` which is an alias for `name#current`. If left empty, `platform#current`
+ // is implied. This value affects all modules included in this APEX. In other words, they are
+ // also built with the SDKs specified here.
+ Uses_sdks []string
+
+ // Whenever apex_payload.img of the APEX should include dm-verity hashtree.
+ // Should be only used in tests#.
+ Test_only_no_hashtree *bool
+
+ // Whenever apex_payload.img of the APEX should not be dm-verity signed.
+ // Should be only used in tests#.
+ Test_only_unsigned_payload *bool
+
+ IsCoverageVariant bool `blueprint:"mutated"`
+
+ // Whether this APEX is considered updatable or not. When set to true, this will enforce additional
+ // rules for making sure that the APEX is truly updatable.
+ // - To be updatable, min_sdk_version should be set as well
+ // This will also disable the size optimizations like symlinking to the system libs.
+ // Default is false.
+ Updatable *bool
+
+ // The minimum SDK version that this apex must be compatibile with.
+ Min_sdk_version *string
+
+ // If set true, VNDK libs are considered as stable libs and are not included in this apex.
+ // Should be only used in non-system apexes (e.g. vendor: true).
+ // Default is false.
+ Use_vndk_as_stable *bool
+
+ // The type of filesystem to use for an image apex. Either 'ext4' or 'f2fs'.
+ // Default 'ext4'.
+ Payload_fs_type *string
+}
+
+type ApexNativeDependencies struct {
+ // List of native libraries
+ Native_shared_libs []string
+
+ // List of JNI libraries
+ Jni_libs []string
+
+ // List of native executables
+ Binaries []string
+
+ // List of native tests
+ Tests []string
+}
+
+type apexMultilibProperties struct {
+ // Native dependencies whose compile_multilib is "first"
+ First ApexNativeDependencies
+
+ // Native dependencies whose compile_multilib is "both"
+ Both ApexNativeDependencies
+
+ // Native dependencies whose compile_multilib is "prefer32"
+ Prefer32 ApexNativeDependencies
+
+ // Native dependencies whose compile_multilib is "32"
+ Lib32 ApexNativeDependencies
+
+ // Native dependencies whose compile_multilib is "64"
+ Lib64 ApexNativeDependencies
+}
+
+type apexTargetBundleProperties struct {
+ Target struct {
+ // Multilib properties only for android.
+ Android struct {
+ Multilib apexMultilibProperties
+ }
+
+ // Multilib properties only for host.
+ Host struct {
+ Multilib apexMultilibProperties
+ }
+
+ // Multilib properties only for host linux_bionic.
+ Linux_bionic struct {
+ Multilib apexMultilibProperties
+ }
+
+ // Multilib properties only for host linux_glibc.
+ Linux_glibc struct {
+ Multilib apexMultilibProperties
+ }
+ }
+}
+
+type overridableProperties struct {
+ // List of APKs to package inside APEX
+ Apps []string
+
+ // List of runtime resource overlays (RROs) inside APEX
+ Rros []string
+
+ // Names of modules to be overridden. Listed modules can only be other binaries
+ // (in Make or Soong).
+ // This does not completely prevent installation of the overridden binaries, but if both
+ // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
+ // from PRODUCT_PACKAGES.
+ Overrides []string
+
+ // Logging Parent value
+ Logging_parent string
+
+ // Apex Container Package Name.
+ // Override value for attribute package:name in AndroidManifest.xml
+ Package_name string
+
+ // A txt file containing list of files that are allowed to be included in this APEX.
+ Allowed_files *string `android:"path"`
+}
+
+type apexBundle struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+ android.OverridableModuleBase
+ android.SdkBase
+
+ properties apexBundleProperties
+ targetProperties apexTargetBundleProperties
+ overridableProperties overridableProperties
+
+ // specific to apex_vndk modules
+ vndkProperties apexVndkProperties
+
+ bundleModuleFile android.WritablePath
+ outputFile android.WritablePath
+ installDir android.InstallPath
+
+ prebuiltFileToDelete string
+
+ public_key_file android.Path
+ private_key_file android.Path
+
+ container_certificate_file android.Path
+ container_private_key_file android.Path
+
+ fileContexts android.WritablePath
+
+ // list of files to be included in this apex
+ filesInfo []apexFile
+
+ // list of module names that should be installed along with this APEX
+ requiredDeps []string
+
+ // list of module names that this APEX is including (to be shown via *-deps-info target)
+ android.ApexBundleDepsInfo
+
+ testApex bool
+ vndkApex bool
+ artApex bool
+ primaryApexType bool
+
+ manifestJsonOut android.WritablePath
+ manifestPbOut android.WritablePath
+
+ // list of commands to create symlinks for backward compatibility.
+ // these commands will be attached as LOCAL_POST_INSTALL_CMD to
+ // apex package itself(for unflattened build) or apex_manifest(for flattened build)
+ // so that compat symlinks are always installed regardless of TARGET_FLATTEN_APEX setting.
+ compatSymlinks []string
+
+ // Suffix of module name in Android.mk
+ // ".flattened", ".apex", ".zipapex", or ""
+ suffix string
+
+ installedFilesFile android.WritablePath
+
+ // Whether to create symlink to the system file instead of having a file
+ // inside the apex or not
+ linkToSystemLib bool
+
+ // Struct holding the merged notice file paths in different formats
+ mergedNotices android.NoticeOutputs
+
+ // Optional list of lint report zip files for apexes that contain java or app modules
+ lintReports android.Paths
+
+ payloadFsType fsType
+
+ distFiles android.TaggedDistFiles
+}
+
+type apexFileClass int
+
const (
- imageApexSuffix = ".apex"
- zipApexSuffix = ".zipapex"
- flattenedSuffix = ".flattened"
-
- imageApexType = "image"
- zipApexType = "zip"
- flattenedApexType = "flattened"
-
- ext4FsType = "ext4"
- f2fsFsType = "f2fs"
+ etc apexFileClass = iota
+ nativeSharedLib
+ nativeExecutable
+ shBinary
+ pyBinary
+ goBinary
+ javaSharedLib
+ nativeTest
+ app
+ appSet
)
+func (class apexFileClass) NameInMake() string {
+ switch class {
+ case etc:
+ return "ETC"
+ case nativeSharedLib:
+ return "SHARED_LIBRARIES"
+ case nativeExecutable, shBinary, pyBinary, goBinary:
+ return "EXECUTABLES"
+ case javaSharedLib:
+ return "JAVA_LIBRARIES"
+ case nativeTest:
+ return "NATIVE_TESTS"
+ case app, appSet:
+ // b/142537672 Why isn't this APP? We want to have full control over
+ // the paths and file names of the apk file under the flattend APEX.
+ // If this is set to APP, then the paths and file names are modified
+ // by the Make build system. For example, it is installed to
+ // /system/apex/<apexname>/app/<Appname>/<apexname>.<Appname>/ instead of
+ // /system/apex/<apexname>/app/<Appname> because the build system automatically
+ // appends module name (which is <apexname>.<Appname> to the path.
+ return "ETC"
+ default:
+ panic(fmt.Errorf("unknown class %d", class))
+ }
+}
+
+// apexFile represents a file in an APEX bundle
+type apexFile struct {
+ builtFile android.Path
+ stem string
+ // Module name of `module` in AndroidMk. Note the generated AndroidMk module for
+ // apexFile is named something like <AndroidMk module name>.<apex name>[<apex suffix>]
+ androidMkModuleName string
+ installDir string
+ class apexFileClass
+ module android.Module
+ // list of symlinks that will be created in installDir that point to this apexFile
+ symlinks []string
+ dataPaths []android.DataPath
+ transitiveDep bool
+ moduleDir string
+
+ requiredModuleNames []string
+ targetRequiredModuleNames []string
+ hostRequiredModuleNames []string
+
+ jacocoReportClassesFile android.Path // only for javalibs and apps
+ lintDepSets java.LintDepSets // only for javalibs and apps
+ certificate java.Certificate // only for apps
+ overriddenPackageName string // only for apps
+
+ isJniLib bool
+
+ noticeFiles android.Paths
+}
+
+func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, androidMkModuleName string, installDir string, class apexFileClass, module android.Module) apexFile {
+ ret := apexFile{
+ builtFile: builtFile,
+ androidMkModuleName: androidMkModuleName,
+ installDir: installDir,
+ class: class,
+ module: module,
+ }
+ if module != nil {
+ ret.moduleDir = ctx.OtherModuleDir(module)
+ ret.requiredModuleNames = module.RequiredModuleNames()
+ ret.targetRequiredModuleNames = module.TargetRequiredModuleNames()
+ ret.hostRequiredModuleNames = module.HostRequiredModuleNames()
+ ret.noticeFiles = module.NoticeFiles()
+ }
+ return ret
+}
+
+func (af *apexFile) Ok() bool {
+ return af.builtFile != nil && af.builtFile.String() != ""
+}
+
+func (af *apexFile) apexRelativePath(path string) string {
+ return filepath.Join(af.installDir, path)
+}
+
+// Path() returns path of this apex file relative to the APEX root
+func (af *apexFile) Path() string {
+ return af.apexRelativePath(af.Stem())
+}
+
+func (af *apexFile) Stem() string {
+ if af.stem != "" {
+ return af.stem
+ }
+ return af.builtFile.Base()
+}
+
+// SymlinkPaths() returns paths of the symlinks (if any) relative to the APEX root
+func (af *apexFile) SymlinkPaths() []string {
+ var ret []string
+ for _, symlink := range af.symlinks {
+ ret = append(ret, af.apexRelativePath(symlink))
+ }
+ return ret
+}
+
+func (af *apexFile) AvailableToPlatform() bool {
+ if af.module == nil {
+ return false
+ }
+ if am, ok := af.module.(android.ApexModule); ok {
+ return am.AvailableFor(android.AvailableToPlatform)
+ }
+ return false
+}
+
+func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
+ nativeModules ApexNativeDependencies,
+ target android.Target, imageVariation string) {
+ // Use *FarVariation* to be able to depend on modules having
+ // conflicting variations with this module. This is required since
+ // arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64'
+ // for native shared libs.
+
+ binVariations := target.Variations()
+ libVariations := append(target.Variations(),
+ blueprint.Variation{Mutator: "link", Variation: "shared"})
+
+ if ctx.Device() {
+ binVariations = append(binVariations,
+ blueprint.Variation{Mutator: "image", Variation: imageVariation})
+ libVariations = append(libVariations,
+ blueprint.Variation{Mutator: "image", Variation: imageVariation},
+ blueprint.Variation{Mutator: "version", Variation: ""}) // "" is the non-stub variant
+ }
+
+ ctx.AddFarVariationDependencies(libVariations, sharedLibTag, nativeModules.Native_shared_libs...)
+
+ ctx.AddFarVariationDependencies(libVariations, jniLibTag, nativeModules.Jni_libs...)
+
+ ctx.AddFarVariationDependencies(binVariations, executableTag, nativeModules.Binaries...)
+
+ ctx.AddFarVariationDependencies(binVariations, testTag, nativeModules.Tests...)
+}
+
+func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
+ if ctx.Os().Class == android.Device {
+ proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Android.Multilib, nil)
+ } else {
+ proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Host.Multilib, nil)
+ if ctx.Os().Bionic() {
+ proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_bionic.Multilib, nil)
+ } else {
+ proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_glibc.Multilib, nil)
+ }
+ }
+}
+
type dependencyTag struct {
blueprint.BaseDependencyTag
name string
@@ -67,704 +504,162 @@
rroTag = dependencyTag{name: "rro", payload: true}
bpfTag = dependencyTag{name: "bpf", payload: true}
testForTag = dependencyTag{name: "test for"}
-
- apexAvailBaseline = makeApexAvailableBaseline()
-
- inverseApexAvailBaseline = invertApexBaseline(apexAvailBaseline)
)
-// Transform the map of apex -> modules to module -> apexes.
-func invertApexBaseline(m map[string][]string) map[string][]string {
- r := make(map[string][]string)
- for apex, modules := range m {
- for _, module := range modules {
- r[module] = append(r[module], apex)
+func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if proptools.Bool(a.properties.Use_vendor) && !android.InList(a.Name(), useVendorAllowList(ctx.Config())) {
+ ctx.PropertyErrorf("use_vendor", "not allowed to set use_vendor: true")
+ }
+
+ targets := ctx.MultiTargets()
+ config := ctx.DeviceConfig()
+ imageVariation := a.getImageVariation(ctx)
+
+ a.combineProperties(ctx)
+
+ has32BitTarget := false
+ for _, target := range targets {
+ if target.Arch.ArchType.Multilib == "lib32" {
+ has32BitTarget = true
}
}
- return r
-}
+ for i, target := range targets {
+ if target.HostCross {
+ // Don't include artifats for the host cross targets because there is no way
+ // for us to run those artifacts natively on host
+ continue
+ }
-// Retrieve the baseline of apexes to which the supplied module belongs.
-func BaselineApexAvailable(moduleName string) []string {
- return inverseApexAvailBaseline[normalizeModuleName(moduleName)]
-}
+ // When multilib.* is omitted for native_shared_libs/jni_libs/tests, it implies
+ // multilib.both
+ addDependenciesForNativeModules(ctx,
+ ApexNativeDependencies{
+ Native_shared_libs: a.properties.Native_shared_libs,
+ Tests: a.properties.Tests,
+ Jni_libs: a.properties.Jni_libs,
+ Binaries: nil,
+ },
+ target, imageVariation)
-// This is a map from apex to modules, which overrides the
-// apex_available setting for that particular module to make
-// it available for the apex regardless of its setting.
-// TODO(b/147364041): remove this
-func makeApexAvailableBaseline() map[string][]string {
- // The "Module separator"s below are employed to minimize merge conflicts.
- m := make(map[string][]string)
- //
- // Module separator
- //
- m["com.android.appsearch"] = []string{
- "icing-java-proto-lite",
- "libprotobuf-java-lite",
- }
- //
- // Module separator
- //
- m["com.android.bluetooth.updatable"] = []string{
- "android.hardware.audio.common@5.0",
- "android.hardware.bluetooth.a2dp@1.0",
- "android.hardware.bluetooth.audio@2.0",
- "android.hardware.bluetooth@1.0",
- "android.hardware.bluetooth@1.1",
- "android.hardware.graphics.bufferqueue@1.0",
- "android.hardware.graphics.bufferqueue@2.0",
- "android.hardware.graphics.common@1.0",
- "android.hardware.graphics.common@1.1",
- "android.hardware.graphics.common@1.2",
- "android.hardware.media@1.0",
- "android.hidl.safe_union@1.0",
- "android.hidl.token@1.0",
- "android.hidl.token@1.0-utils",
- "avrcp-target-service",
- "avrcp_headers",
- "bluetooth-protos-lite",
- "bluetooth.mapsapi",
- "com.android.vcard",
- "dnsresolver_aidl_interface-V2-java",
- "ipmemorystore-aidl-interfaces-V5-java",
- "ipmemorystore-aidl-interfaces-java",
- "internal_include_headers",
- "lib-bt-packets",
- "lib-bt-packets-avrcp",
- "lib-bt-packets-base",
- "libFraunhoferAAC",
- "libaudio-a2dp-hw-utils",
- "libaudio-hearing-aid-hw-utils",
- "libbinder_headers",
- "libbluetooth",
- "libbluetooth-types",
- "libbluetooth-types-header",
- "libbluetooth_gd",
- "libbluetooth_headers",
- "libbluetooth_jni",
- "libbt-audio-hal-interface",
- "libbt-bta",
- "libbt-common",
- "libbt-hci",
- "libbt-platform-protos-lite",
- "libbt-protos-lite",
- "libbt-sbc-decoder",
- "libbt-sbc-encoder",
- "libbt-stack",
- "libbt-utils",
- "libbtcore",
- "libbtdevice",
- "libbte",
- "libbtif",
- "libchrome",
- "libevent",
- "libfmq",
- "libg722codec",
- "libgui_headers",
- "libmedia_headers",
- "libmodpb64",
- "libosi",
- "libstagefright_foundation_headers",
- "libstagefright_headers",
- "libstatslog",
- "libstatssocket",
- "libtinyxml2",
- "libudrv-uipc",
- "libz",
- "media_plugin_headers",
- "net-utils-services-common",
- "netd_aidl_interface-unstable-java",
- "netd_event_listener_interface-java",
- "netlink-client",
- "networkstack-client",
- "sap-api-java-static",
- "services.net",
- }
- //
- // Module separator
- //
- m["com.android.cellbroadcast"] = []string{"CellBroadcastApp", "CellBroadcastServiceModule"}
- //
- // Module separator
- //
- m["com.android.extservices"] = []string{
- "error_prone_annotations",
- "ExtServices-core",
- "ExtServices",
- "libtextclassifier-java",
- "libz_current",
- "textclassifier-statsd",
- "TextClassifierNotificationLibNoManifest",
- "TextClassifierServiceLibNoManifest",
- }
- //
- // Module separator
- //
- m["com.android.neuralnetworks"] = []string{
- "android.hardware.neuralnetworks@1.0",
- "android.hardware.neuralnetworks@1.1",
- "android.hardware.neuralnetworks@1.2",
- "android.hardware.neuralnetworks@1.3",
- "android.hidl.allocator@1.0",
- "android.hidl.memory.token@1.0",
- "android.hidl.memory@1.0",
- "android.hidl.safe_union@1.0",
- "libarect",
- "libbuildversion",
- "libmath",
- "libprocpartition",
- "libsync",
- }
- //
- // Module separator
- //
- m["com.android.media"] = []string{
- "android.frameworks.bufferhub@1.0",
- "android.hardware.cas.native@1.0",
- "android.hardware.cas@1.0",
- "android.hardware.configstore-utils",
- "android.hardware.configstore@1.0",
- "android.hardware.configstore@1.1",
- "android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.allocator@3.0",
- "android.hardware.graphics.bufferqueue@1.0",
- "android.hardware.graphics.bufferqueue@2.0",
- "android.hardware.graphics.common@1.0",
- "android.hardware.graphics.common@1.1",
- "android.hardware.graphics.common@1.2",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@2.1",
- "android.hardware.graphics.mapper@3.0",
- "android.hardware.media.omx@1.0",
- "android.hardware.media@1.0",
- "android.hidl.allocator@1.0",
- "android.hidl.memory.token@1.0",
- "android.hidl.memory@1.0",
- "android.hidl.token@1.0",
- "android.hidl.token@1.0-utils",
- "bionic_libc_platform_headers",
- "exoplayer2-extractor",
- "exoplayer2-extractor-annotation-stubs",
- "gl_headers",
- "jsr305",
- "libEGL",
- "libEGL_blobCache",
- "libEGL_getProcAddress",
- "libFLAC",
- "libFLAC-config",
- "libFLAC-headers",
- "libGLESv2",
- "libaacextractor",
- "libamrextractor",
- "libarect",
- "libaudio_system_headers",
- "libaudioclient",
- "libaudioclient_headers",
- "libaudiofoundation",
- "libaudiofoundation_headers",
- "libaudiomanager",
- "libaudiopolicy",
- "libaudioutils",
- "libaudioutils_fixedfft",
- "libbinder_headers",
- "libbluetooth-types-header",
- "libbufferhub",
- "libbufferhub_headers",
- "libbufferhubqueue",
- "libc_malloc_debug_backtrace",
- "libcamera_client",
- "libcamera_metadata",
- "libdvr_headers",
- "libexpat",
- "libfifo",
- "libflacextractor",
- "libgrallocusage",
- "libgraphicsenv",
- "libgui",
- "libgui_headers",
- "libhardware_headers",
- "libinput",
- "liblzma",
- "libmath",
- "libmedia",
- "libmedia_codeclist",
- "libmedia_headers",
- "libmedia_helper",
- "libmedia_helper_headers",
- "libmedia_midiiowrapper",
- "libmedia_omx",
- "libmediautils",
- "libmidiextractor",
- "libmkvextractor",
- "libmp3extractor",
- "libmp4extractor",
- "libmpeg2extractor",
- "libnativebase_headers",
- "libnativewindow_headers",
- "libnblog",
- "liboggextractor",
- "libpackagelistparser",
- "libpdx",
- "libpdx_default_transport",
- "libpdx_headers",
- "libpdx_uds",
- "libprocinfo",
- "libspeexresampler",
- "libspeexresampler",
- "libstagefright_esds",
- "libstagefright_flacdec",
- "libstagefright_flacdec",
- "libstagefright_foundation",
- "libstagefright_foundation_headers",
- "libstagefright_foundation_without_imemory",
- "libstagefright_headers",
- "libstagefright_id3",
- "libstagefright_metadatautils",
- "libstagefright_mpeg2extractor",
- "libstagefright_mpeg2support",
- "libsync",
- "libui",
- "libui_headers",
- "libunwindstack",
- "libvibrator",
- "libvorbisidec",
- "libwavextractor",
- "libwebm",
- "media_ndk_headers",
- "media_plugin_headers",
- "updatable-media",
- }
- //
- // Module separator
- //
- m["com.android.media.swcodec"] = []string{
- "android.frameworks.bufferhub@1.0",
- "android.hardware.common-ndk_platform",
- "android.hardware.configstore-utils",
- "android.hardware.configstore@1.0",
- "android.hardware.configstore@1.1",
- "android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.allocator@3.0",
- "android.hardware.graphics.allocator@4.0",
- "android.hardware.graphics.bufferqueue@1.0",
- "android.hardware.graphics.bufferqueue@2.0",
- "android.hardware.graphics.common-ndk_platform",
- "android.hardware.graphics.common@1.0",
- "android.hardware.graphics.common@1.1",
- "android.hardware.graphics.common@1.2",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@2.1",
- "android.hardware.graphics.mapper@3.0",
- "android.hardware.graphics.mapper@4.0",
- "android.hardware.media.bufferpool@2.0",
- "android.hardware.media.c2@1.0",
- "android.hardware.media.c2@1.1",
- "android.hardware.media.omx@1.0",
- "android.hardware.media@1.0",
- "android.hardware.media@1.0",
- "android.hidl.memory.token@1.0",
- "android.hidl.memory@1.0",
- "android.hidl.safe_union@1.0",
- "android.hidl.token@1.0",
- "android.hidl.token@1.0-utils",
- "libEGL",
- "libFLAC",
- "libFLAC-config",
- "libFLAC-headers",
- "libFraunhoferAAC",
- "libLibGuiProperties",
- "libarect",
- "libaudio_system_headers",
- "libaudioutils",
- "libaudioutils",
- "libaudioutils_fixedfft",
- "libavcdec",
- "libavcenc",
- "libavservices_minijail",
- "libavservices_minijail",
- "libbinder_headers",
- "libbinderthreadstateutils",
- "libbluetooth-types-header",
- "libbufferhub_headers",
- "libcodec2",
- "libcodec2_headers",
- "libcodec2_hidl@1.0",
- "libcodec2_hidl@1.1",
- "libcodec2_internal",
- "libcodec2_soft_aacdec",
- "libcodec2_soft_aacenc",
- "libcodec2_soft_amrnbdec",
- "libcodec2_soft_amrnbenc",
- "libcodec2_soft_amrwbdec",
- "libcodec2_soft_amrwbenc",
- "libcodec2_soft_av1dec_gav1",
- "libcodec2_soft_avcdec",
- "libcodec2_soft_avcenc",
- "libcodec2_soft_common",
- "libcodec2_soft_flacdec",
- "libcodec2_soft_flacenc",
- "libcodec2_soft_g711alawdec",
- "libcodec2_soft_g711mlawdec",
- "libcodec2_soft_gsmdec",
- "libcodec2_soft_h263dec",
- "libcodec2_soft_h263enc",
- "libcodec2_soft_hevcdec",
- "libcodec2_soft_hevcenc",
- "libcodec2_soft_mp3dec",
- "libcodec2_soft_mpeg2dec",
- "libcodec2_soft_mpeg4dec",
- "libcodec2_soft_mpeg4enc",
- "libcodec2_soft_opusdec",
- "libcodec2_soft_opusenc",
- "libcodec2_soft_rawdec",
- "libcodec2_soft_vorbisdec",
- "libcodec2_soft_vp8dec",
- "libcodec2_soft_vp8enc",
- "libcodec2_soft_vp9dec",
- "libcodec2_soft_vp9enc",
- "libcodec2_vndk",
- "libdvr_headers",
- "libfmq",
- "libfmq",
- "libgav1",
- "libgralloctypes",
- "libgrallocusage",
- "libgraphicsenv",
- "libgsm",
- "libgui_bufferqueue_static",
- "libgui_headers",
- "libhardware",
- "libhardware_headers",
- "libhevcdec",
- "libhevcenc",
- "libion",
- "libjpeg",
- "liblzma",
- "libmath",
- "libmedia_codecserviceregistrant",
- "libmedia_headers",
- "libmpeg2dec",
- "libnativebase_headers",
- "libnativewindow_headers",
- "libpdx_headers",
- "libscudo_wrapper",
- "libsfplugin_ccodec_utils",
- "libspeexresampler",
- "libstagefright_amrnb_common",
- "libstagefright_amrnbdec",
- "libstagefright_amrnbenc",
- "libstagefright_amrwbdec",
- "libstagefright_amrwbenc",
- "libstagefright_bufferpool@2.0.1",
- "libstagefright_bufferqueue_helper",
- "libstagefright_enc_common",
- "libstagefright_flacdec",
- "libstagefright_foundation",
- "libstagefright_foundation_headers",
- "libstagefright_headers",
- "libstagefright_m4vh263dec",
- "libstagefright_m4vh263enc",
- "libstagefright_mp3dec",
- "libsync",
- "libui",
- "libui_headers",
- "libunwindstack",
- "libvorbisidec",
- "libvpx",
- "libyuv",
- "libyuv_static",
- "media_ndk_headers",
- "media_plugin_headers",
- "mediaswcodec",
- }
- //
- // Module separator
- //
- m["com.android.mediaprovider"] = []string{
- "MediaProvider",
- "MediaProviderGoogle",
- "fmtlib_ndk",
- "libbase_ndk",
- "libfuse",
- "libfuse_jni",
- }
- //
- // Module separator
- //
- m["com.android.permission"] = []string{
- "car-ui-lib",
- "iconloader",
- "kotlin-annotations",
- "kotlin-stdlib",
- "kotlin-stdlib-jdk7",
- "kotlin-stdlib-jdk8",
- "kotlinx-coroutines-android",
- "kotlinx-coroutines-android-nodeps",
- "kotlinx-coroutines-core",
- "kotlinx-coroutines-core-nodeps",
- "permissioncontroller-statsd",
- "GooglePermissionController",
- "PermissionController",
- "SettingsLibActionBarShadow",
- "SettingsLibAppPreference",
- "SettingsLibBarChartPreference",
- "SettingsLibLayoutPreference",
- "SettingsLibProgressBar",
- "SettingsLibSearchWidget",
- "SettingsLibSettingsTheme",
- "SettingsLibRestrictedLockUtils",
- "SettingsLibHelpUtils",
- }
- //
- // Module separator
- //
- m["com.android.runtime"] = []string{
- "bionic_libc_platform_headers",
- "libarm-optimized-routines-math",
- "libc_aeabi",
- "libc_bionic",
- "libc_bionic_ndk",
- "libc_bootstrap",
- "libc_common",
- "libc_common_shared",
- "libc_common_static",
- "libc_dns",
- "libc_dynamic_dispatch",
- "libc_fortify",
- "libc_freebsd",
- "libc_freebsd_large_stack",
- "libc_gdtoa",
- "libc_init_dynamic",
- "libc_init_static",
- "libc_jemalloc_wrapper",
- "libc_netbsd",
- "libc_nomalloc",
- "libc_nopthread",
- "libc_openbsd",
- "libc_openbsd_large_stack",
- "libc_openbsd_ndk",
- "libc_pthread",
- "libc_static_dispatch",
- "libc_syscalls",
- "libc_tzcode",
- "libc_unwind_static",
- "libdebuggerd",
- "libdebuggerd_common_headers",
- "libdebuggerd_handler_core",
- "libdebuggerd_handler_fallback",
- "libdl_static",
- "libjemalloc5",
- "liblinker_main",
- "liblinker_malloc",
- "liblz4",
- "liblzma",
- "libprocinfo",
- "libpropertyinfoparser",
- "libscudo",
- "libstdc++",
- "libsystemproperties",
- "libtombstoned_client_static",
- "libunwindstack",
- "libz",
- "libziparchive",
- }
- //
- // Module separator
- //
- m["com.android.tethering"] = []string{
- "android.hardware.tetheroffload.config-V1.0-java",
- "android.hardware.tetheroffload.control-V1.0-java",
- "android.hidl.base-V1.0-java",
- "libcgrouprc",
- "libcgrouprc_format",
- "libtetherutilsjni",
- "libvndksupport",
- "net-utils-framework-common",
- "netd_aidl_interface-V3-java",
- "netlink-client",
- "networkstack-aidl-interfaces-java",
- "tethering-aidl-interfaces-java",
- "TetheringApiCurrentLib",
- }
- //
- // Module separator
- //
- m["com.android.wifi"] = []string{
- "PlatformProperties",
- "android.hardware.wifi-V1.0-java",
- "android.hardware.wifi-V1.0-java-constants",
- "android.hardware.wifi-V1.1-java",
- "android.hardware.wifi-V1.2-java",
- "android.hardware.wifi-V1.3-java",
- "android.hardware.wifi-V1.4-java",
- "android.hardware.wifi.hostapd-V1.0-java",
- "android.hardware.wifi.hostapd-V1.1-java",
- "android.hardware.wifi.hostapd-V1.2-java",
- "android.hardware.wifi.supplicant-V1.0-java",
- "android.hardware.wifi.supplicant-V1.1-java",
- "android.hardware.wifi.supplicant-V1.2-java",
- "android.hardware.wifi.supplicant-V1.3-java",
- "android.hidl.base-V1.0-java",
- "android.hidl.manager-V1.0-java",
- "android.hidl.manager-V1.1-java",
- "android.hidl.manager-V1.2-java",
- "bouncycastle-unbundled",
- "dnsresolver_aidl_interface-V2-java",
- "error_prone_annotations",
- "framework-wifi-pre-jarjar",
- "framework-wifi-util-lib",
- "ipmemorystore-aidl-interfaces-V3-java",
- "ipmemorystore-aidl-interfaces-java",
- "ksoap2",
- "libnanohttpd",
- "libwifi-jni",
- "net-utils-services-common",
- "netd_aidl_interface-V2-java",
- "netd_aidl_interface-unstable-java",
- "netd_event_listener_interface-java",
- "netlink-client",
- "networkstack-client",
- "services.net",
- "wifi-lite-protos",
- "wifi-nano-protos",
- "wifi-service-pre-jarjar",
- "wifi-service-resources",
- }
- //
- // Module separator
- //
- m["com.android.sdkext"] = []string{
- "fmtlib_ndk",
- "libbase_ndk",
- "libprotobuf-cpp-lite-ndk",
- }
- //
- // Module separator
- //
- m["com.android.os.statsd"] = []string{
- "libstatssocket",
- }
- //
- // Module separator
- //
- m[android.AvailableToAnyApex] = []string{
- // TODO(b/156996905) Set apex_available/min_sdk_version for androidx/extras support libraries
- "androidx",
- "androidx-constraintlayout_constraintlayout",
- "androidx-constraintlayout_constraintlayout-nodeps",
- "androidx-constraintlayout_constraintlayout-solver",
- "androidx-constraintlayout_constraintlayout-solver-nodeps",
- "com.google.android.material_material",
- "com.google.android.material_material-nodeps",
+ // Add native modules targetting both ABIs
+ addDependenciesForNativeModules(ctx,
+ a.properties.Multilib.Both,
+ target,
+ imageVariation)
- "libatomic",
- "libclang_rt",
- "libgcc_stripped",
- "libprofile-clang-extras",
- "libprofile-clang-extras_ndk",
- "libprofile-extras",
- "libprofile-extras_ndk",
- "libunwind_llvm",
- }
- return m
-}
+ isPrimaryAbi := i == 0
+ if isPrimaryAbi {
+ // When multilib.* is omitted for binaries, it implies
+ // multilib.first
+ addDependenciesForNativeModules(ctx,
+ ApexNativeDependencies{
+ Native_shared_libs: nil,
+ Tests: nil,
+ Jni_libs: nil,
+ Binaries: a.properties.Binaries,
+ },
+ target, imageVariation)
-// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART.
-// Adding code to the bootclasspath in new packages will cause issues on module update.
-func qModulesPackages() map[string][]string {
- return map[string][]string{
- "com.android.conscrypt": []string{
- "android.net.ssl",
- "com.android.org.conscrypt",
- },
- "com.android.media": []string{
- "android.media",
- },
+ // Add native modules targetting the first ABI
+ addDependenciesForNativeModules(ctx,
+ a.properties.Multilib.First,
+ target,
+ imageVariation)
+ }
+
+ switch target.Arch.ArchType.Multilib {
+ case "lib32":
+ // Add native modules targetting 32-bit ABI
+ addDependenciesForNativeModules(ctx,
+ a.properties.Multilib.Lib32,
+ target,
+ imageVariation)
+
+ addDependenciesForNativeModules(ctx,
+ a.properties.Multilib.Prefer32,
+ target,
+ imageVariation)
+ case "lib64":
+ // Add native modules targetting 64-bit ABI
+ addDependenciesForNativeModules(ctx,
+ a.properties.Multilib.Lib64,
+ target,
+ imageVariation)
+
+ if !has32BitTarget {
+ addDependenciesForNativeModules(ctx,
+ a.properties.Multilib.Prefer32,
+ target,
+ imageVariation)
+ }
+ }
+ }
+
+ // For prebuilt_etc, use the first variant (64 on 64/32bit device,
+ // 32 on 32bit device) regardless of the TARGET_PREFER_* setting.
+ // b/144532908
+ archForPrebuiltEtc := config.Arches()[0]
+ for _, arch := range config.Arches() {
+ // Prefer 64-bit arch if there is any
+ if arch.ArchType.Multilib == "lib64" {
+ archForPrebuiltEtc = arch
+ break
+ }
+ }
+ ctx.AddFarVariationDependencies([]blueprint.Variation{
+ {Mutator: "os", Variation: ctx.Os().String()},
+ {Mutator: "arch", Variation: archForPrebuiltEtc.String()},
+ }, prebuiltTag, a.properties.Prebuilts...)
+
+ ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
+ javaLibTag, a.properties.Java_libs...)
+
+ ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
+ bpfTag, a.properties.Bpfs...)
+
+ // With EMMA_INSTRUMENT_FRAMEWORK=true the ART boot image includes jacoco library.
+ if a.artApex && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
+ ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
+ javaLibTag, "jacocoagent")
+ }
+
+ if String(a.properties.Key) == "" {
+ ctx.ModuleErrorf("key is missing")
+ return
+ }
+ ctx.AddDependency(ctx.Module(), keyTag, String(a.properties.Key))
+
+ cert := android.SrcIsModule(a.getCertString(ctx))
+ if cert != "" {
+ ctx.AddDependency(ctx.Module(), certificateTag, cert)
+ }
+
+ // TODO(jiyong): ensure that all apexes are with non-empty uses_sdks
+ if len(a.properties.Uses_sdks) > 0 {
+ sdkRefs := []android.SdkRef{}
+ for _, str := range a.properties.Uses_sdks {
+ parsed := android.ParseSdkRef(ctx, str, "uses_sdks")
+ sdkRefs = append(sdkRefs, parsed)
+ }
+ a.BuildWithSdks(sdkRefs)
}
}
-// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART.
-// Adding code to the bootclasspath in new packages will cause issues on module update.
-func rModulesPackages() map[string][]string {
- return map[string][]string{
- "com.android.mediaprovider": []string{
- "android.provider",
- },
- "com.android.permission": []string{
- "android.permission",
- "android.app.role",
- "com.android.permission",
- "com.android.role",
- },
- "com.android.sdkext": []string{
- "android.os.ext",
- },
- "com.android.os.statsd": []string{
- "android.app",
- "android.os",
- "android.util",
- "com.android.internal.statsd",
- "com.android.server.stats",
- },
- "com.android.wifi": []string{
- "com.android.server.wifi",
- "com.android.wifi.x",
- "android.hardware.wifi",
- "android.net.wifi",
- },
- "com.android.tethering": []string{
- "android.net",
- },
+func (a *apexBundle) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
+ if a.overridableProperties.Allowed_files != nil {
+ android.ExtractSourceDeps(ctx, a.overridableProperties.Allowed_files)
}
+ ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
+ androidAppTag, a.overridableProperties.Apps...)
+ ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
+ rroTag, a.overridableProperties.Rros...)
}
-func init() {
- android.RegisterModuleType("apex", BundleFactory)
- android.RegisterModuleType("apex_test", testApexBundleFactory)
- android.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
- android.RegisterModuleType("apex_defaults", defaultsFactory)
- android.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
- android.RegisterModuleType("override_apex", overrideApexFactory)
- android.RegisterModuleType("apex_set", apexSetFactory)
-
- android.PreDepsMutators(RegisterPreDepsMutators)
- android.PostDepsMutators(RegisterPostDepsMutators)
-
- android.AddNeverAllowRules(createApexPermittedPackagesRules(qModulesPackages())...)
- android.AddNeverAllowRules(createApexPermittedPackagesRules(rModulesPackages())...)
+type ApexBundleInfo struct {
+ Contents *android.ApexContents
}
-func createApexPermittedPackagesRules(modules_packages map[string][]string) []android.Rule {
- rules := make([]android.Rule, 0, len(modules_packages))
- for module_name, module_packages := range modules_packages {
- permitted_packages_rule := android.NeverAllow().
- BootclasspathJar().
- With("apex_available", module_name).
- WithMatcher("permitted_packages", android.NotInList(module_packages)).
- Because("jars that are part of the " + module_name +
- " module may only allow these packages: " + strings.Join(module_packages, ",") +
- ". Please jarjar or move code around.")
- rules = append(rules, permitted_packages_rule)
- }
- return rules
-}
-
-func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("apex_vndk", apexVndkMutator).Parallel()
- ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel()
-}
-
-func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("apex_deps", apexDepsMutator).Parallel()
- ctx.BottomUp("apex_unique", apexUniqueVariationsMutator).Parallel()
- ctx.BottomUp("apex_test_for_deps", apexTestForDepsMutator).Parallel()
- ctx.BottomUp("apex_test_for", apexTestForMutator).Parallel()
- ctx.BottomUp("apex", apexMutator).Parallel()
- ctx.BottomUp("apex_directly_in_any", apexDirectlyInAnyMutator).Parallel()
- ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel()
- ctx.BottomUp("mark_platform_availability", markPlatformAvailability).Parallel()
-}
+var ApexBundleInfoProvider = blueprint.NewMutatorProvider(ApexBundleInfo{}, "apex_deps")
// Mark the direct and transitive dependencies of apex bundles so that they
// can be built for the apex bundles.
@@ -967,6 +862,50 @@
}
}
+type apexPackaging int
+
+const (
+ imageApex apexPackaging = iota
+ zipApex
+ flattenedApex
+)
+
+const (
+ imageApexSuffix = ".apex"
+ zipApexSuffix = ".zipapex"
+ flattenedSuffix = ".flattened"
+
+ imageApexType = "image"
+ zipApexType = "zip"
+ flattenedApexType = "flattened"
+
+ ext4FsType = "ext4"
+ f2fsFsType = "f2fs"
+)
+
+// The suffix for the output "file", not the module
+func (a apexPackaging) suffix() string {
+ switch a {
+ case imageApex:
+ return imageApexSuffix
+ case zipApex:
+ return zipApexSuffix
+ default:
+ panic(fmt.Errorf("unknown APEX type %d", a))
+ }
+}
+
+func (a apexPackaging) name() string {
+ switch a {
+ case imageApex:
+ return imageApexType
+ case zipApex:
+ return zipApexType
+ default:
+ panic(fmt.Errorf("unknown APEX type %d", a))
+ }
+}
+
func apexFlattenedMutator(mctx android.BottomUpMutatorContext) {
if !mctx.Module().Enabled() {
return
@@ -1033,351 +972,6 @@
})
}
-type ApexNativeDependencies struct {
- // List of native libraries
- Native_shared_libs []string
-
- // List of JNI libraries
- Jni_libs []string
-
- // List of native executables
- Binaries []string
-
- // List of native tests
- Tests []string
-}
-
-type apexMultilibProperties struct {
- // Native dependencies whose compile_multilib is "first"
- First ApexNativeDependencies
-
- // Native dependencies whose compile_multilib is "both"
- Both ApexNativeDependencies
-
- // Native dependencies whose compile_multilib is "prefer32"
- Prefer32 ApexNativeDependencies
-
- // Native dependencies whose compile_multilib is "32"
- Lib32 ApexNativeDependencies
-
- // Native dependencies whose compile_multilib is "64"
- Lib64 ApexNativeDependencies
-}
-
-type apexBundleProperties struct {
- // Json manifest file describing meta info of this APEX bundle. Default:
- // "apex_manifest.json"
- Manifest *string `android:"path"`
-
- // AndroidManifest.xml file used for the zip container of this APEX bundle.
- // If unspecified, a default one is automatically generated.
- AndroidManifest *string `android:"path"`
-
- // Canonical name of the APEX bundle. Used to determine the path to the activated APEX on
- // device (/apex/<apex_name>).
- // If unspecified, defaults to the value of name.
- Apex_name *string
-
- // Determines the file contexts file for setting security context to each file in this APEX bundle.
- // For platform APEXes, this should points to a file under /system/sepolicy
- // Default: /system/sepolicy/apex/<module_name>_file_contexts.
- File_contexts *string `android:"path"`
-
- ApexNativeDependencies
-
- // List of java libraries that are embedded inside this APEX bundle
- Java_libs []string
-
- // List of prebuilt files that are embedded inside this APEX bundle
- Prebuilts []string
-
- // List of BPF programs inside APEX
- Bpfs []string
-
- // Name of the apex_key module that provides the private key to sign APEX
- Key *string
-
- // The type of APEX to build. Controls what the APEX payload is. Either
- // 'image', 'zip' or 'both'. Default: 'image'.
- Payload_type *string
-
- // The name of a certificate in the default certificate directory, blank to use the default product certificate,
- // or an android_app_certificate module name in the form ":module".
- Certificate *string
-
- // Whether this APEX is installable to one of the partitions. Default: true.
- Installable *bool
-
- // For native libraries and binaries, use the vendor variant instead of the core (platform) variant.
- // Default is false.
- Use_vendor *bool
-
- // For telling the apex to ignore special handling for system libraries such as bionic. Default is false.
- Ignore_system_library_special_case *bool
-
- Multilib apexMultilibProperties
-
- // List of sanitizer names that this APEX is enabled for
- SanitizerNames []string `blueprint:"mutated"`
-
- PreventInstall bool `blueprint:"mutated"`
-
- HideFromMake bool `blueprint:"mutated"`
-
- // package format of this apex variant; could be non-flattened, flattened, or zip.
- // imageApex, zipApex or flattened
- ApexType apexPackaging `blueprint:"mutated"`
-
- // List of SDKs that are used to build this APEX. A reference to an SDK should be either
- // `name#version` or `name` which is an alias for `name#current`. If left empty, `platform#current`
- // is implied. This value affects all modules included in this APEX. In other words, they are
- // also built with the SDKs specified here.
- Uses_sdks []string
-
- // Whenever apex_payload.img of the APEX should include dm-verity hashtree.
- // Should be only used in tests#.
- Test_only_no_hashtree *bool
-
- // Whenever apex_payload.img of the APEX should not be dm-verity signed.
- // Should be only used in tests#.
- Test_only_unsigned_payload *bool
-
- IsCoverageVariant bool `blueprint:"mutated"`
-
- // Whether this APEX is considered updatable or not. When set to true, this will enforce additional
- // rules for making sure that the APEX is truly updatable.
- // - To be updatable, min_sdk_version should be set as well
- // This will also disable the size optimizations like symlinking to the system libs.
- // Default is false.
- Updatable *bool
-
- // The minimum SDK version that this apex must be compatibile with.
- Min_sdk_version *string
-
- // If set true, VNDK libs are considered as stable libs and are not included in this apex.
- // Should be only used in non-system apexes (e.g. vendor: true).
- // Default is false.
- Use_vndk_as_stable *bool
-
- // The type of filesystem to use for an image apex. Either 'ext4' or 'f2fs'.
- // Default 'ext4'.
- Payload_fs_type *string
-}
-
-type ApexBundleInfo struct {
- Contents *android.ApexContents
-}
-
-var ApexBundleInfoProvider = blueprint.NewMutatorProvider(ApexBundleInfo{}, "apex_deps")
-
-type apexTargetBundleProperties struct {
- Target struct {
- // Multilib properties only for android.
- Android struct {
- Multilib apexMultilibProperties
- }
-
- // Multilib properties only for host.
- Host struct {
- Multilib apexMultilibProperties
- }
-
- // Multilib properties only for host linux_bionic.
- Linux_bionic struct {
- Multilib apexMultilibProperties
- }
-
- // Multilib properties only for host linux_glibc.
- Linux_glibc struct {
- Multilib apexMultilibProperties
- }
- }
-}
-
-type overridableProperties struct {
- // List of APKs to package inside APEX
- Apps []string
-
- // List of runtime resource overlays (RROs) inside APEX
- Rros []string
-
- // Names of modules to be overridden. Listed modules can only be other binaries
- // (in Make or Soong).
- // This does not completely prevent installation of the overridden binaries, but if both
- // binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
- // from PRODUCT_PACKAGES.
- Overrides []string
-
- // Logging Parent value
- Logging_parent string
-
- // Apex Container Package Name.
- // Override value for attribute package:name in AndroidManifest.xml
- Package_name string
-
- // A txt file containing list of files that are allowed to be included in this APEX.
- Allowed_files *string `android:"path"`
-}
-
-type apexPackaging int
-
-const (
- imageApex apexPackaging = iota
- zipApex
- flattenedApex
-)
-
-// The suffix for the output "file", not the module
-func (a apexPackaging) suffix() string {
- switch a {
- case imageApex:
- return imageApexSuffix
- case zipApex:
- return zipApexSuffix
- default:
- panic(fmt.Errorf("unknown APEX type %d", a))
- }
-}
-
-func (a apexPackaging) name() string {
- switch a {
- case imageApex:
- return imageApexType
- case zipApex:
- return zipApexType
- default:
- panic(fmt.Errorf("unknown APEX type %d", a))
- }
-}
-
-type apexFileClass int
-
-const (
- etc apexFileClass = iota
- nativeSharedLib
- nativeExecutable
- shBinary
- pyBinary
- goBinary
- javaSharedLib
- nativeTest
- app
- appSet
-)
-
-func (class apexFileClass) NameInMake() string {
- switch class {
- case etc:
- return "ETC"
- case nativeSharedLib:
- return "SHARED_LIBRARIES"
- case nativeExecutable, shBinary, pyBinary, goBinary:
- return "EXECUTABLES"
- case javaSharedLib:
- return "JAVA_LIBRARIES"
- case nativeTest:
- return "NATIVE_TESTS"
- case app, appSet:
- // b/142537672 Why isn't this APP? We want to have full control over
- // the paths and file names of the apk file under the flattend APEX.
- // If this is set to APP, then the paths and file names are modified
- // by the Make build system. For example, it is installed to
- // /system/apex/<apexname>/app/<Appname>/<apexname>.<Appname>/ instead of
- // /system/apex/<apexname>/app/<Appname> because the build system automatically
- // appends module name (which is <apexname>.<Appname> to the path.
- return "ETC"
- default:
- panic(fmt.Errorf("unknown class %d", class))
- }
-}
-
-// apexFile represents a file in an APEX bundle
-type apexFile struct {
- builtFile android.Path
- stem string
- // Module name of `module` in AndroidMk. Note the generated AndroidMk module for
- // apexFile is named something like <AndroidMk module name>.<apex name>[<apex suffix>]
- androidMkModuleName string
- installDir string
- class apexFileClass
- module android.Module
- // list of symlinks that will be created in installDir that point to this apexFile
- symlinks []string
- dataPaths []android.DataPath
- transitiveDep bool
- moduleDir string
-
- requiredModuleNames []string
- targetRequiredModuleNames []string
- hostRequiredModuleNames []string
-
- jacocoReportClassesFile android.Path // only for javalibs and apps
- lintDepSets java.LintDepSets // only for javalibs and apps
- certificate java.Certificate // only for apps
- overriddenPackageName string // only for apps
-
- isJniLib bool
-
- noticeFiles android.Paths
-}
-
-func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, androidMkModuleName string, installDir string, class apexFileClass, module android.Module) apexFile {
- ret := apexFile{
- builtFile: builtFile,
- androidMkModuleName: androidMkModuleName,
- installDir: installDir,
- class: class,
- module: module,
- }
- if module != nil {
- ret.moduleDir = ctx.OtherModuleDir(module)
- ret.requiredModuleNames = module.RequiredModuleNames()
- ret.targetRequiredModuleNames = module.TargetRequiredModuleNames()
- ret.hostRequiredModuleNames = module.HostRequiredModuleNames()
- ret.noticeFiles = module.NoticeFiles()
- }
- return ret
-}
-
-func (af *apexFile) Ok() bool {
- return af.builtFile != nil && af.builtFile.String() != ""
-}
-
-func (af *apexFile) apexRelativePath(path string) string {
- return filepath.Join(af.installDir, path)
-}
-
-// Path() returns path of this apex file relative to the APEX root
-func (af *apexFile) Path() string {
- return af.apexRelativePath(af.Stem())
-}
-
-func (af *apexFile) Stem() string {
- if af.stem != "" {
- return af.stem
- }
- return af.builtFile.Base()
-}
-
-// SymlinkPaths() returns paths of the symlinks (if any) relative to the APEX root
-func (af *apexFile) SymlinkPaths() []string {
- var ret []string
- for _, symlink := range af.symlinks {
- ret = append(ret, af.apexRelativePath(symlink))
- }
- return ret
-}
-
-func (af *apexFile) AvailableToPlatform() bool {
- if af.module == nil {
- return false
- }
- if am, ok := af.module.(android.ApexModule); ok {
- return am.AvailableFor(android.AvailableToPlatform)
- }
- return false
-}
-
type fsType int
const (
@@ -1396,268 +990,6 @@
}
}
-type apexBundle struct {
- android.ModuleBase
- android.DefaultableModuleBase
- android.OverridableModuleBase
- android.SdkBase
-
- properties apexBundleProperties
- targetProperties apexTargetBundleProperties
- overridableProperties overridableProperties
-
- // specific to apex_vndk modules
- vndkProperties apexVndkProperties
-
- bundleModuleFile android.WritablePath
- outputFile android.WritablePath
- installDir android.InstallPath
-
- prebuiltFileToDelete string
-
- public_key_file android.Path
- private_key_file android.Path
-
- container_certificate_file android.Path
- container_private_key_file android.Path
-
- fileContexts android.WritablePath
-
- // list of files to be included in this apex
- filesInfo []apexFile
-
- // list of module names that should be installed along with this APEX
- requiredDeps []string
-
- // list of module names that this APEX is including (to be shown via *-deps-info target)
- android.ApexBundleDepsInfo
-
- testApex bool
- vndkApex bool
- artApex bool
- primaryApexType bool
-
- manifestJsonOut android.WritablePath
- manifestPbOut android.WritablePath
-
- // list of commands to create symlinks for backward compatibility.
- // these commands will be attached as LOCAL_POST_INSTALL_CMD to
- // apex package itself(for unflattened build) or apex_manifest(for flattened build)
- // so that compat symlinks are always installed regardless of TARGET_FLATTEN_APEX setting.
- compatSymlinks []string
-
- // Suffix of module name in Android.mk
- // ".flattened", ".apex", ".zipapex", or ""
- suffix string
-
- installedFilesFile android.WritablePath
-
- // Whether to create symlink to the system file instead of having a file
- // inside the apex or not
- linkToSystemLib bool
-
- // Struct holding the merged notice file paths in different formats
- mergedNotices android.NoticeOutputs
-
- // Optional list of lint report zip files for apexes that contain java or app modules
- lintReports android.Paths
-
- payloadFsType fsType
-
- distFiles android.TaggedDistFiles
-}
-
-func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
- nativeModules ApexNativeDependencies,
- target android.Target, imageVariation string) {
- // Use *FarVariation* to be able to depend on modules having
- // conflicting variations with this module. This is required since
- // arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64'
- // for native shared libs.
-
- binVariations := target.Variations()
- libVariations := append(target.Variations(),
- blueprint.Variation{Mutator: "link", Variation: "shared"})
-
- if ctx.Device() {
- binVariations = append(binVariations,
- blueprint.Variation{Mutator: "image", Variation: imageVariation})
- libVariations = append(libVariations,
- blueprint.Variation{Mutator: "image", Variation: imageVariation},
- blueprint.Variation{Mutator: "version", Variation: ""}) // "" is the non-stub variant
- }
-
- ctx.AddFarVariationDependencies(libVariations, sharedLibTag, nativeModules.Native_shared_libs...)
-
- ctx.AddFarVariationDependencies(libVariations, jniLibTag, nativeModules.Jni_libs...)
-
- ctx.AddFarVariationDependencies(binVariations, executableTag, nativeModules.Binaries...)
-
- ctx.AddFarVariationDependencies(binVariations, testTag, nativeModules.Tests...)
-}
-
-func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
- if ctx.Os().Class == android.Device {
- proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Android.Multilib, nil)
- } else {
- proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Host.Multilib, nil)
- if ctx.Os().Bionic() {
- proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_bionic.Multilib, nil)
- } else {
- proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_glibc.Multilib, nil)
- }
- }
-}
-
-func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
- if proptools.Bool(a.properties.Use_vendor) && !android.InList(a.Name(), useVendorAllowList(ctx.Config())) {
- ctx.PropertyErrorf("use_vendor", "not allowed to set use_vendor: true")
- }
-
- targets := ctx.MultiTargets()
- config := ctx.DeviceConfig()
- imageVariation := a.getImageVariation(ctx)
-
- a.combineProperties(ctx)
-
- has32BitTarget := false
- for _, target := range targets {
- if target.Arch.ArchType.Multilib == "lib32" {
- has32BitTarget = true
- }
- }
- for i, target := range targets {
- if target.HostCross {
- // Don't include artifats for the host cross targets because there is no way
- // for us to run those artifacts natively on host
- continue
- }
-
- // When multilib.* is omitted for native_shared_libs/jni_libs/tests, it implies
- // multilib.both
- addDependenciesForNativeModules(ctx,
- ApexNativeDependencies{
- Native_shared_libs: a.properties.Native_shared_libs,
- Tests: a.properties.Tests,
- Jni_libs: a.properties.Jni_libs,
- Binaries: nil,
- },
- target, imageVariation)
-
- // Add native modules targetting both ABIs
- addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Both,
- target,
- imageVariation)
-
- isPrimaryAbi := i == 0
- if isPrimaryAbi {
- // When multilib.* is omitted for binaries, it implies
- // multilib.first
- addDependenciesForNativeModules(ctx,
- ApexNativeDependencies{
- Native_shared_libs: nil,
- Tests: nil,
- Jni_libs: nil,
- Binaries: a.properties.Binaries,
- },
- target, imageVariation)
-
- // Add native modules targetting the first ABI
- addDependenciesForNativeModules(ctx,
- a.properties.Multilib.First,
- target,
- imageVariation)
- }
-
- switch target.Arch.ArchType.Multilib {
- case "lib32":
- // Add native modules targetting 32-bit ABI
- addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Lib32,
- target,
- imageVariation)
-
- addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Prefer32,
- target,
- imageVariation)
- case "lib64":
- // Add native modules targetting 64-bit ABI
- addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Lib64,
- target,
- imageVariation)
-
- if !has32BitTarget {
- addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Prefer32,
- target,
- imageVariation)
- }
- }
- }
-
- // For prebuilt_etc, use the first variant (64 on 64/32bit device,
- // 32 on 32bit device) regardless of the TARGET_PREFER_* setting.
- // b/144532908
- archForPrebuiltEtc := config.Arches()[0]
- for _, arch := range config.Arches() {
- // Prefer 64-bit arch if there is any
- if arch.ArchType.Multilib == "lib64" {
- archForPrebuiltEtc = arch
- break
- }
- }
- ctx.AddFarVariationDependencies([]blueprint.Variation{
- {Mutator: "os", Variation: ctx.Os().String()},
- {Mutator: "arch", Variation: archForPrebuiltEtc.String()},
- }, prebuiltTag, a.properties.Prebuilts...)
-
- ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
- javaLibTag, a.properties.Java_libs...)
-
- ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
- bpfTag, a.properties.Bpfs...)
-
- // With EMMA_INSTRUMENT_FRAMEWORK=true the ART boot image includes jacoco library.
- if a.artApex && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
- ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
- javaLibTag, "jacocoagent")
- }
-
- if String(a.properties.Key) == "" {
- ctx.ModuleErrorf("key is missing")
- return
- }
- ctx.AddDependency(ctx.Module(), keyTag, String(a.properties.Key))
-
- cert := android.SrcIsModule(a.getCertString(ctx))
- if cert != "" {
- ctx.AddDependency(ctx.Module(), certificateTag, cert)
- }
-
- // TODO(jiyong): ensure that all apexes are with non-empty uses_sdks
- if len(a.properties.Uses_sdks) > 0 {
- sdkRefs := []android.SdkRef{}
- for _, str := range a.properties.Uses_sdks {
- parsed := android.ParseSdkRef(ctx, str, "uses_sdks")
- sdkRefs = append(sdkRefs, parsed)
- }
- a.BuildWithSdks(sdkRefs)
- }
-}
-
-func (a *apexBundle) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
- if a.overridableProperties.Allowed_files != nil {
- android.ExtractSourceDeps(ctx, a.overridableProperties.Allowed_files)
- }
- ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
- androidAppTag, a.overridableProperties.Apps...)
- ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(),
- rroTag, a.overridableProperties.Rros...)
-}
-
func (a *apexBundle) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
// direct deps of an APEX bundle are all part of the APEX bundle
return true
@@ -2615,3 +1947,674 @@
android.InitOverrideModule(m)
return m
}
+
+var (
+ apexAvailBaseline = makeApexAvailableBaseline()
+ inverseApexAvailBaseline = invertApexBaseline(apexAvailBaseline)
+)
+
+// Transform the map of apex -> modules to module -> apexes.
+func invertApexBaseline(m map[string][]string) map[string][]string {
+ r := make(map[string][]string)
+ for apex, modules := range m {
+ for _, module := range modules {
+ r[module] = append(r[module], apex)
+ }
+ }
+ return r
+}
+
+// Retrieve the baseline of apexes to which the supplied module belongs.
+func BaselineApexAvailable(moduleName string) []string {
+ return inverseApexAvailBaseline[normalizeModuleName(moduleName)]
+}
+
+// This is a map from apex to modules, which overrides the
+// apex_available setting for that particular module to make
+// it available for the apex regardless of its setting.
+// TODO(b/147364041): remove this
+func makeApexAvailableBaseline() map[string][]string {
+ // The "Module separator"s below are employed to minimize merge conflicts.
+ m := make(map[string][]string)
+ //
+ // Module separator
+ //
+ m["com.android.appsearch"] = []string{
+ "icing-java-proto-lite",
+ "libprotobuf-java-lite",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.bluetooth.updatable"] = []string{
+ "android.hardware.audio.common@5.0",
+ "android.hardware.bluetooth.a2dp@1.0",
+ "android.hardware.bluetooth.audio@2.0",
+ "android.hardware.bluetooth@1.0",
+ "android.hardware.bluetooth@1.1",
+ "android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.bufferqueue@2.0",
+ "android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.common@1.1",
+ "android.hardware.graphics.common@1.2",
+ "android.hardware.media@1.0",
+ "android.hidl.safe_union@1.0",
+ "android.hidl.token@1.0",
+ "android.hidl.token@1.0-utils",
+ "avrcp-target-service",
+ "avrcp_headers",
+ "bluetooth-protos-lite",
+ "bluetooth.mapsapi",
+ "com.android.vcard",
+ "dnsresolver_aidl_interface-V2-java",
+ "ipmemorystore-aidl-interfaces-V5-java",
+ "ipmemorystore-aidl-interfaces-java",
+ "internal_include_headers",
+ "lib-bt-packets",
+ "lib-bt-packets-avrcp",
+ "lib-bt-packets-base",
+ "libFraunhoferAAC",
+ "libaudio-a2dp-hw-utils",
+ "libaudio-hearing-aid-hw-utils",
+ "libbinder_headers",
+ "libbluetooth",
+ "libbluetooth-types",
+ "libbluetooth-types-header",
+ "libbluetooth_gd",
+ "libbluetooth_headers",
+ "libbluetooth_jni",
+ "libbt-audio-hal-interface",
+ "libbt-bta",
+ "libbt-common",
+ "libbt-hci",
+ "libbt-platform-protos-lite",
+ "libbt-protos-lite",
+ "libbt-sbc-decoder",
+ "libbt-sbc-encoder",
+ "libbt-stack",
+ "libbt-utils",
+ "libbtcore",
+ "libbtdevice",
+ "libbte",
+ "libbtif",
+ "libchrome",
+ "libevent",
+ "libfmq",
+ "libg722codec",
+ "libgui_headers",
+ "libmedia_headers",
+ "libmodpb64",
+ "libosi",
+ "libstagefright_foundation_headers",
+ "libstagefright_headers",
+ "libstatslog",
+ "libstatssocket",
+ "libtinyxml2",
+ "libudrv-uipc",
+ "libz",
+ "media_plugin_headers",
+ "net-utils-services-common",
+ "netd_aidl_interface-unstable-java",
+ "netd_event_listener_interface-java",
+ "netlink-client",
+ "networkstack-client",
+ "sap-api-java-static",
+ "services.net",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.cellbroadcast"] = []string{"CellBroadcastApp", "CellBroadcastServiceModule"}
+ //
+ // Module separator
+ //
+ m["com.android.extservices"] = []string{
+ "error_prone_annotations",
+ "ExtServices-core",
+ "ExtServices",
+ "libtextclassifier-java",
+ "libz_current",
+ "textclassifier-statsd",
+ "TextClassifierNotificationLibNoManifest",
+ "TextClassifierServiceLibNoManifest",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.neuralnetworks"] = []string{
+ "android.hardware.neuralnetworks@1.0",
+ "android.hardware.neuralnetworks@1.1",
+ "android.hardware.neuralnetworks@1.2",
+ "android.hardware.neuralnetworks@1.3",
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory.token@1.0",
+ "android.hidl.memory@1.0",
+ "android.hidl.safe_union@1.0",
+ "libarect",
+ "libbuildversion",
+ "libmath",
+ "libprocpartition",
+ "libsync",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.media"] = []string{
+ "android.frameworks.bufferhub@1.0",
+ "android.hardware.cas.native@1.0",
+ "android.hardware.cas@1.0",
+ "android.hardware.configstore-utils",
+ "android.hardware.configstore@1.0",
+ "android.hardware.configstore@1.1",
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.allocator@3.0",
+ "android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.bufferqueue@2.0",
+ "android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.common@1.1",
+ "android.hardware.graphics.common@1.2",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.1",
+ "android.hardware.graphics.mapper@3.0",
+ "android.hardware.media.omx@1.0",
+ "android.hardware.media@1.0",
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory.token@1.0",
+ "android.hidl.memory@1.0",
+ "android.hidl.token@1.0",
+ "android.hidl.token@1.0-utils",
+ "bionic_libc_platform_headers",
+ "exoplayer2-extractor",
+ "exoplayer2-extractor-annotation-stubs",
+ "gl_headers",
+ "jsr305",
+ "libEGL",
+ "libEGL_blobCache",
+ "libEGL_getProcAddress",
+ "libFLAC",
+ "libFLAC-config",
+ "libFLAC-headers",
+ "libGLESv2",
+ "libaacextractor",
+ "libamrextractor",
+ "libarect",
+ "libaudio_system_headers",
+ "libaudioclient",
+ "libaudioclient_headers",
+ "libaudiofoundation",
+ "libaudiofoundation_headers",
+ "libaudiomanager",
+ "libaudiopolicy",
+ "libaudioutils",
+ "libaudioutils_fixedfft",
+ "libbinder_headers",
+ "libbluetooth-types-header",
+ "libbufferhub",
+ "libbufferhub_headers",
+ "libbufferhubqueue",
+ "libc_malloc_debug_backtrace",
+ "libcamera_client",
+ "libcamera_metadata",
+ "libdvr_headers",
+ "libexpat",
+ "libfifo",
+ "libflacextractor",
+ "libgrallocusage",
+ "libgraphicsenv",
+ "libgui",
+ "libgui_headers",
+ "libhardware_headers",
+ "libinput",
+ "liblzma",
+ "libmath",
+ "libmedia",
+ "libmedia_codeclist",
+ "libmedia_headers",
+ "libmedia_helper",
+ "libmedia_helper_headers",
+ "libmedia_midiiowrapper",
+ "libmedia_omx",
+ "libmediautils",
+ "libmidiextractor",
+ "libmkvextractor",
+ "libmp3extractor",
+ "libmp4extractor",
+ "libmpeg2extractor",
+ "libnativebase_headers",
+ "libnativewindow_headers",
+ "libnblog",
+ "liboggextractor",
+ "libpackagelistparser",
+ "libpdx",
+ "libpdx_default_transport",
+ "libpdx_headers",
+ "libpdx_uds",
+ "libprocinfo",
+ "libspeexresampler",
+ "libspeexresampler",
+ "libstagefright_esds",
+ "libstagefright_flacdec",
+ "libstagefright_flacdec",
+ "libstagefright_foundation",
+ "libstagefright_foundation_headers",
+ "libstagefright_foundation_without_imemory",
+ "libstagefright_headers",
+ "libstagefright_id3",
+ "libstagefright_metadatautils",
+ "libstagefright_mpeg2extractor",
+ "libstagefright_mpeg2support",
+ "libsync",
+ "libui",
+ "libui_headers",
+ "libunwindstack",
+ "libvibrator",
+ "libvorbisidec",
+ "libwavextractor",
+ "libwebm",
+ "media_ndk_headers",
+ "media_plugin_headers",
+ "updatable-media",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.media.swcodec"] = []string{
+ "android.frameworks.bufferhub@1.0",
+ "android.hardware.common-ndk_platform",
+ "android.hardware.configstore-utils",
+ "android.hardware.configstore@1.0",
+ "android.hardware.configstore@1.1",
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.allocator@3.0",
+ "android.hardware.graphics.allocator@4.0",
+ "android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.bufferqueue@2.0",
+ "android.hardware.graphics.common-ndk_platform",
+ "android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.common@1.1",
+ "android.hardware.graphics.common@1.2",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.1",
+ "android.hardware.graphics.mapper@3.0",
+ "android.hardware.graphics.mapper@4.0",
+ "android.hardware.media.bufferpool@2.0",
+ "android.hardware.media.c2@1.0",
+ "android.hardware.media.c2@1.1",
+ "android.hardware.media.omx@1.0",
+ "android.hardware.media@1.0",
+ "android.hardware.media@1.0",
+ "android.hidl.memory.token@1.0",
+ "android.hidl.memory@1.0",
+ "android.hidl.safe_union@1.0",
+ "android.hidl.token@1.0",
+ "android.hidl.token@1.0-utils",
+ "libEGL",
+ "libFLAC",
+ "libFLAC-config",
+ "libFLAC-headers",
+ "libFraunhoferAAC",
+ "libLibGuiProperties",
+ "libarect",
+ "libaudio_system_headers",
+ "libaudioutils",
+ "libaudioutils",
+ "libaudioutils_fixedfft",
+ "libavcdec",
+ "libavcenc",
+ "libavservices_minijail",
+ "libavservices_minijail",
+ "libbinder_headers",
+ "libbinderthreadstateutils",
+ "libbluetooth-types-header",
+ "libbufferhub_headers",
+ "libcodec2",
+ "libcodec2_headers",
+ "libcodec2_hidl@1.0",
+ "libcodec2_hidl@1.1",
+ "libcodec2_internal",
+ "libcodec2_soft_aacdec",
+ "libcodec2_soft_aacenc",
+ "libcodec2_soft_amrnbdec",
+ "libcodec2_soft_amrnbenc",
+ "libcodec2_soft_amrwbdec",
+ "libcodec2_soft_amrwbenc",
+ "libcodec2_soft_av1dec_gav1",
+ "libcodec2_soft_avcdec",
+ "libcodec2_soft_avcenc",
+ "libcodec2_soft_common",
+ "libcodec2_soft_flacdec",
+ "libcodec2_soft_flacenc",
+ "libcodec2_soft_g711alawdec",
+ "libcodec2_soft_g711mlawdec",
+ "libcodec2_soft_gsmdec",
+ "libcodec2_soft_h263dec",
+ "libcodec2_soft_h263enc",
+ "libcodec2_soft_hevcdec",
+ "libcodec2_soft_hevcenc",
+ "libcodec2_soft_mp3dec",
+ "libcodec2_soft_mpeg2dec",
+ "libcodec2_soft_mpeg4dec",
+ "libcodec2_soft_mpeg4enc",
+ "libcodec2_soft_opusdec",
+ "libcodec2_soft_opusenc",
+ "libcodec2_soft_rawdec",
+ "libcodec2_soft_vorbisdec",
+ "libcodec2_soft_vp8dec",
+ "libcodec2_soft_vp8enc",
+ "libcodec2_soft_vp9dec",
+ "libcodec2_soft_vp9enc",
+ "libcodec2_vndk",
+ "libdvr_headers",
+ "libfmq",
+ "libfmq",
+ "libgav1",
+ "libgralloctypes",
+ "libgrallocusage",
+ "libgraphicsenv",
+ "libgsm",
+ "libgui_bufferqueue_static",
+ "libgui_headers",
+ "libhardware",
+ "libhardware_headers",
+ "libhevcdec",
+ "libhevcenc",
+ "libion",
+ "libjpeg",
+ "liblzma",
+ "libmath",
+ "libmedia_codecserviceregistrant",
+ "libmedia_headers",
+ "libmpeg2dec",
+ "libnativebase_headers",
+ "libnativewindow_headers",
+ "libpdx_headers",
+ "libscudo_wrapper",
+ "libsfplugin_ccodec_utils",
+ "libspeexresampler",
+ "libstagefright_amrnb_common",
+ "libstagefright_amrnbdec",
+ "libstagefright_amrnbenc",
+ "libstagefright_amrwbdec",
+ "libstagefright_amrwbenc",
+ "libstagefright_bufferpool@2.0.1",
+ "libstagefright_bufferqueue_helper",
+ "libstagefright_enc_common",
+ "libstagefright_flacdec",
+ "libstagefright_foundation",
+ "libstagefright_foundation_headers",
+ "libstagefright_headers",
+ "libstagefright_m4vh263dec",
+ "libstagefright_m4vh263enc",
+ "libstagefright_mp3dec",
+ "libsync",
+ "libui",
+ "libui_headers",
+ "libunwindstack",
+ "libvorbisidec",
+ "libvpx",
+ "libyuv",
+ "libyuv_static",
+ "media_ndk_headers",
+ "media_plugin_headers",
+ "mediaswcodec",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.mediaprovider"] = []string{
+ "MediaProvider",
+ "MediaProviderGoogle",
+ "fmtlib_ndk",
+ "libbase_ndk",
+ "libfuse",
+ "libfuse_jni",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.permission"] = []string{
+ "car-ui-lib",
+ "iconloader",
+ "kotlin-annotations",
+ "kotlin-stdlib",
+ "kotlin-stdlib-jdk7",
+ "kotlin-stdlib-jdk8",
+ "kotlinx-coroutines-android",
+ "kotlinx-coroutines-android-nodeps",
+ "kotlinx-coroutines-core",
+ "kotlinx-coroutines-core-nodeps",
+ "permissioncontroller-statsd",
+ "GooglePermissionController",
+ "PermissionController",
+ "SettingsLibActionBarShadow",
+ "SettingsLibAppPreference",
+ "SettingsLibBarChartPreference",
+ "SettingsLibLayoutPreference",
+ "SettingsLibProgressBar",
+ "SettingsLibSearchWidget",
+ "SettingsLibSettingsTheme",
+ "SettingsLibRestrictedLockUtils",
+ "SettingsLibHelpUtils",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.runtime"] = []string{
+ "bionic_libc_platform_headers",
+ "libarm-optimized-routines-math",
+ "libc_aeabi",
+ "libc_bionic",
+ "libc_bionic_ndk",
+ "libc_bootstrap",
+ "libc_common",
+ "libc_common_shared",
+ "libc_common_static",
+ "libc_dns",
+ "libc_dynamic_dispatch",
+ "libc_fortify",
+ "libc_freebsd",
+ "libc_freebsd_large_stack",
+ "libc_gdtoa",
+ "libc_init_dynamic",
+ "libc_init_static",
+ "libc_jemalloc_wrapper",
+ "libc_netbsd",
+ "libc_nomalloc",
+ "libc_nopthread",
+ "libc_openbsd",
+ "libc_openbsd_large_stack",
+ "libc_openbsd_ndk",
+ "libc_pthread",
+ "libc_static_dispatch",
+ "libc_syscalls",
+ "libc_tzcode",
+ "libc_unwind_static",
+ "libdebuggerd",
+ "libdebuggerd_common_headers",
+ "libdebuggerd_handler_core",
+ "libdebuggerd_handler_fallback",
+ "libdl_static",
+ "libjemalloc5",
+ "liblinker_main",
+ "liblinker_malloc",
+ "liblz4",
+ "liblzma",
+ "libprocinfo",
+ "libpropertyinfoparser",
+ "libscudo",
+ "libstdc++",
+ "libsystemproperties",
+ "libtombstoned_client_static",
+ "libunwindstack",
+ "libz",
+ "libziparchive",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.tethering"] = []string{
+ "android.hardware.tetheroffload.config-V1.0-java",
+ "android.hardware.tetheroffload.control-V1.0-java",
+ "android.hidl.base-V1.0-java",
+ "libcgrouprc",
+ "libcgrouprc_format",
+ "libtetherutilsjni",
+ "libvndksupport",
+ "net-utils-framework-common",
+ "netd_aidl_interface-V3-java",
+ "netlink-client",
+ "networkstack-aidl-interfaces-java",
+ "tethering-aidl-interfaces-java",
+ "TetheringApiCurrentLib",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.wifi"] = []string{
+ "PlatformProperties",
+ "android.hardware.wifi-V1.0-java",
+ "android.hardware.wifi-V1.0-java-constants",
+ "android.hardware.wifi-V1.1-java",
+ "android.hardware.wifi-V1.2-java",
+ "android.hardware.wifi-V1.3-java",
+ "android.hardware.wifi-V1.4-java",
+ "android.hardware.wifi.hostapd-V1.0-java",
+ "android.hardware.wifi.hostapd-V1.1-java",
+ "android.hardware.wifi.hostapd-V1.2-java",
+ "android.hardware.wifi.supplicant-V1.0-java",
+ "android.hardware.wifi.supplicant-V1.1-java",
+ "android.hardware.wifi.supplicant-V1.2-java",
+ "android.hardware.wifi.supplicant-V1.3-java",
+ "android.hidl.base-V1.0-java",
+ "android.hidl.manager-V1.0-java",
+ "android.hidl.manager-V1.1-java",
+ "android.hidl.manager-V1.2-java",
+ "bouncycastle-unbundled",
+ "dnsresolver_aidl_interface-V2-java",
+ "error_prone_annotations",
+ "framework-wifi-pre-jarjar",
+ "framework-wifi-util-lib",
+ "ipmemorystore-aidl-interfaces-V3-java",
+ "ipmemorystore-aidl-interfaces-java",
+ "ksoap2",
+ "libnanohttpd",
+ "libwifi-jni",
+ "net-utils-services-common",
+ "netd_aidl_interface-V2-java",
+ "netd_aidl_interface-unstable-java",
+ "netd_event_listener_interface-java",
+ "netlink-client",
+ "networkstack-client",
+ "services.net",
+ "wifi-lite-protos",
+ "wifi-nano-protos",
+ "wifi-service-pre-jarjar",
+ "wifi-service-resources",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.sdkext"] = []string{
+ "fmtlib_ndk",
+ "libbase_ndk",
+ "libprotobuf-cpp-lite-ndk",
+ }
+ //
+ // Module separator
+ //
+ m["com.android.os.statsd"] = []string{
+ "libstatssocket",
+ }
+ //
+ // Module separator
+ //
+ m[android.AvailableToAnyApex] = []string{
+ // TODO(b/156996905) Set apex_available/min_sdk_version for androidx/extras support libraries
+ "androidx",
+ "androidx-constraintlayout_constraintlayout",
+ "androidx-constraintlayout_constraintlayout-nodeps",
+ "androidx-constraintlayout_constraintlayout-solver",
+ "androidx-constraintlayout_constraintlayout-solver-nodeps",
+ "com.google.android.material_material",
+ "com.google.android.material_material-nodeps",
+
+ "libatomic",
+ "libclang_rt",
+ "libgcc_stripped",
+ "libprofile-clang-extras",
+ "libprofile-clang-extras_ndk",
+ "libprofile-extras",
+ "libprofile-extras_ndk",
+ "libunwind_llvm",
+ }
+ return m
+}
+
+func init() {
+ android.AddNeverAllowRules(createApexPermittedPackagesRules(qModulesPackages())...)
+ android.AddNeverAllowRules(createApexPermittedPackagesRules(rModulesPackages())...)
+}
+
+func createApexPermittedPackagesRules(modules_packages map[string][]string) []android.Rule {
+ rules := make([]android.Rule, 0, len(modules_packages))
+ for module_name, module_packages := range modules_packages {
+ permitted_packages_rule := android.NeverAllow().
+ BootclasspathJar().
+ With("apex_available", module_name).
+ WithMatcher("permitted_packages", android.NotInList(module_packages)).
+ Because("jars that are part of the " + module_name +
+ " module may only allow these packages: " + strings.Join(module_packages, ",") +
+ ". Please jarjar or move code around.")
+ rules = append(rules, permitted_packages_rule)
+ }
+ return rules
+}
+
+// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART.
+// Adding code to the bootclasspath in new packages will cause issues on module update.
+func qModulesPackages() map[string][]string {
+ return map[string][]string{
+ "com.android.conscrypt": []string{
+ "android.net.ssl",
+ "com.android.org.conscrypt",
+ },
+ "com.android.media": []string{
+ "android.media",
+ },
+ }
+}
+
+// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART.
+// Adding code to the bootclasspath in new packages will cause issues on module update.
+func rModulesPackages() map[string][]string {
+ return map[string][]string{
+ "com.android.mediaprovider": []string{
+ "android.provider",
+ },
+ "com.android.permission": []string{
+ "android.permission",
+ "android.app.role",
+ "com.android.permission",
+ "com.android.role",
+ },
+ "com.android.sdkext": []string{
+ "android.os.ext",
+ },
+ "com.android.os.statsd": []string{
+ "android.app",
+ "android.os",
+ "android.util",
+ "com.android.internal.statsd",
+ "com.android.server.stats",
+ },
+ "com.android.wifi": []string{
+ "com.android.server.wifi",
+ "com.android.wifi.x",
+ "android.hardware.wifi",
+ "android.net.wifi",
+ },
+ "com.android.tethering": []string{
+ "android.net",
+ },
+ }
+}
diff --git a/bazel/bazelenv.sh b/bazel/bazelenv.sh
deleted file mode 100755
index fcf71f1..0000000
--- a/bazel/bazelenv.sh
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/bin/bash
-
-# Copyright 2020 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.
-
-# Helper script for setting environment variables required for Bazel/Soong
-# mixed builds prototype. For development use only.
-#
-# Usage:
-# export BAZEL_PATH=[some_bazel_path] && source bazelenv.sh
-#
-# If BAZEL_PATH is not set, `which bazel` will be used
-# to locate the appropriate bazel to use.
-
-
-# Function to find top of the source tree (if $TOP isn't set) by walking up the
-# tree.
-function gettop
-{
- local TOPFILE=build/soong/root.bp
- if [ -n "${TOP-}" -a -f "${TOP-}/${TOPFILE}" ] ; then
- # The following circumlocution ensures we remove symlinks from TOP.
- (cd $TOP; PWD= /bin/pwd)
- else
- if [ -f $TOPFILE ] ; then
- # The following circumlocution (repeated below as well) ensures
- # that we record the true directory name and not one that is
- # faked up with symlink names.
- PWD= /bin/pwd
- else
- local HERE=$PWD
- T=
- while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
- \cd ..
- T=`PWD= /bin/pwd -P`
- done
- \cd $HERE
- if [ -f "$T/$TOPFILE" ]; then
- echo $T
- fi
- fi
- fi
-}
-
-BASE_DIR="$(mktemp -d)"
-
-if [ -z "$BAZEL_PATH" ] ; then
- export BAZEL_PATH="$(which bazel)"
-fi
-
-# TODO(cparsons): Use USE_BAZEL=1 instead once "mixed Soong/Bazel builds" are
-# production ready.
-export USE_BAZEL_ANALYSIS=1
-# TODO(cparsons): Retrieve this information in either envsetup.sh or
-# bazel.sh.
-export BAZEL_HOME="$BASE_DIR/bazelhome"
-export BAZEL_OUTPUT_BASE="$BASE_DIR/output"
-export BAZEL_WORKSPACE="$(gettop)"
-
-echo "USE_BAZEL_ANALYSIS=${USE_BAZEL_ANALYSIS}"
-echo "BAZEL_PATH=${BAZEL_PATH}"
-echo "BAZEL_HOME=${BAZEL_HOME}"
-echo "BAZEL_OUTPUT_BASE=${BAZEL_OUTPUT_BASE}"
-echo "BAZEL_WORKSPACE=${BAZEL_WORKSPACE}"
-
-mkdir -p $BAZEL_HOME
-mkdir -p $BAZEL_OUTPUT_BASE
diff --git a/bazel/master.WORKSPACE.bazel b/bazel/master.WORKSPACE.bazel
deleted file mode 100644
index e69de29..0000000
--- a/bazel/master.WORKSPACE.bazel
+++ /dev/null
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 38269cb..d32e4de 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -370,6 +370,9 @@
entries.SetBool("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", true)
}
entries.AddStrings("LOCAL_TEST_MAINLINE_MODULES", test.Properties.Test_mainline_modules...)
+ if Bool(test.Properties.Test_options.Unit_test) {
+ entries.SetBool("LOCAL_IS_UNIT_TEST", true)
+ }
})
androidMkWriteTestData(test.data, ctx, entries)
@@ -505,7 +508,7 @@
})
}
-func (c *vendorSnapshotLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+func (c *snapshotLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
// Each vendor snapshot is exported to androidMk only when BOARD_VNDK_VERSION != current
// and the version of the prebuilt is same as BOARD_VNDK_VERSION.
if c.shared() {
@@ -549,7 +552,7 @@
})
}
-func (c *vendorSnapshotBinaryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+func (c *snapshotBinaryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
entries.Class = "EXECUTABLES"
if c.androidMkVendorSuffix {
@@ -563,7 +566,7 @@
})
}
-func (c *vendorSnapshotObjectLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+func (c *snapshotObjectLinker) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
entries.Class = "STATIC_LIBRARIES"
if c.androidMkVendorSuffix {
diff --git a/cc/cc.go b/cc/cc.go
index 5e4faf2..bd6e5d5 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -88,7 +88,7 @@
ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
})
- android.RegisterSingletonType("kythe_extract_all", kytheExtractAllFactory)
+ ctx.RegisterSingletonType("kythe_extract_all", kytheExtractAllFactory)
}
type Deps struct {
@@ -305,10 +305,11 @@
// Normally Soong uses the directory structure to decide which modules
// should be included (framework) or excluded (non-framework) from the
- // vendor snapshot, but this property allows a partner to exclude a
- // module normally thought of as a framework module from the vendor
- // snapshot.
- Exclude_from_vendor_snapshot *bool
+ // different snapshots (vendor, recovery, etc.), but these properties
+ // allow a partner to exclude a module normally thought of as a
+ // framework module from a snapshot.
+ Exclude_from_vendor_snapshot *bool
+ Exclude_from_recovery_snapshot *bool
}
type VendorProperties struct {
@@ -368,7 +369,7 @@
useSdk() bool
sdkVersion() string
useVndk() bool
- isNdk() bool
+ isNdk(config android.Config) bool
isLlndk(config android.Config) bool
isLlndkPublic(config android.Config) bool
isVndkPrivate(config android.Config) bool
@@ -938,8 +939,8 @@
return c.coverage.Properties.IsCoverageVariant
}
-func (c *Module) IsNdk() bool {
- return inList(c.BaseModuleName(), ndkKnownLibs)
+func (c *Module) IsNdk(config android.Config) bool {
+ return inList(c.BaseModuleName(), *getNDKKnownLibs(config))
}
func (c *Module) isLlndk(config android.Config) bool {
@@ -1051,6 +1052,10 @@
return Bool(c.Properties.Exclude_from_vendor_snapshot)
}
+func (c *Module) ExcludeFromRecoverySnapshot() bool {
+ return Bool(c.Properties.Exclude_from_recovery_snapshot)
+}
+
func isBionic(name string) bool {
switch name {
case "libc", "libm", "libdl", "libdl_android", "linker":
@@ -1140,8 +1145,8 @@
return ctx.mod.UseVndk()
}
-func (ctx *moduleContextImpl) isNdk() bool {
- return ctx.mod.IsNdk()
+func (ctx *moduleContextImpl) isNdk(config android.Config) bool {
+ return ctx.mod.IsNdk(config)
}
func (ctx *moduleContextImpl) isLlndk(config android.Config) bool {
@@ -1761,7 +1766,7 @@
for _, entry := range list {
// strip #version suffix out
name, _ := StubsLibNameAndVersion(entry)
- if ctx.useSdk() && inList(name, ndkKnownLibs) {
+ if ctx.useSdk() && inList(name, *getNDKKnownLibs(ctx.Config())) {
variantLibs = append(variantLibs, name+ndkLibrarySuffix)
} else if ctx.useVndk() {
nonvariantLibs = append(nonvariantLibs, rewriteVendorLibs(entry))
diff --git a/cc/cc_test.go b/cc/cc_test.go
index f616cf3..f5ce867 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -1551,6 +1551,8 @@
android.CheckErrorsAgainstExpectations(t, errs, []string{
`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
+ `module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
+ `module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
})
}
@@ -1597,6 +1599,132 @@
})
}
+func TestRecoverySnapshotCapture(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ recovery_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "librecovery",
+ recovery: true,
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "librecovery_available",
+ recovery_available: true,
+ nocrt: true,
+ }
+
+ cc_library_headers {
+ name: "librecovery_headers",
+ recovery_available: true,
+ nocrt: true,
+ }
+
+ cc_binary {
+ name: "recovery_bin",
+ recovery: true,
+ nocrt: true,
+ }
+
+ cc_binary {
+ name: "recovery_available_bin",
+ recovery_available: true,
+ nocrt: true,
+ }
+
+ toolchain_library {
+ name: "libb",
+ recovery_available: true,
+ src: "libb.a",
+ }
+
+ cc_object {
+ name: "obj",
+ recovery_available: true,
+ }
+`
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ ctx := testCcWithConfig(t, config)
+
+ // Check Recovery snapshot output.
+
+ snapshotDir := "recovery-snapshot"
+ snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
+
+ var jsonFiles []string
+
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
+
+ // For shared libraries, only recovery_available modules are captured.
+ sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", sharedDir, sharedVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(sharedDir, "libvndk.so.json"),
+ filepath.Join(sharedDir, "librecovery.so.json"),
+ filepath.Join(sharedDir, "librecovery_available.so.json"))
+
+ // For static libraries, all recovery:true and recovery_available modules are captured.
+ staticVariant := fmt.Sprintf("android_recovery_%s_%s_static", archType, archVariant)
+ staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
+ checkSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.a", staticDir, staticVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(staticDir, "libb.a.json"),
+ filepath.Join(staticDir, "librecovery.a.json"),
+ filepath.Join(staticDir, "librecovery_available.a.json"))
+
+ // For binary executables, all recovery:true and recovery_available modules are captured.
+ if archType == "arm64" {
+ binaryVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant)
+ binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
+ checkSnapshot(t, ctx, snapshotSingleton, "recovery_bin", "recovery_bin", binaryDir, binaryVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "recovery_available_bin", "recovery_available_bin", binaryDir, binaryVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(binaryDir, "recovery_bin.json"),
+ filepath.Join(binaryDir, "recovery_available_bin.json"))
+ }
+
+ // For header libraries, all vendor:true and vendor_available modules are captured.
+ headerDir := filepath.Join(snapshotVariantPath, archDir, "header")
+ jsonFiles = append(jsonFiles, filepath.Join(headerDir, "librecovery_headers.json"))
+
+ // For object modules, all vendor:true and vendor_available modules are captured.
+ objectVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant)
+ objectDir := filepath.Join(snapshotVariantPath, archDir, "object")
+ checkSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
+ jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json"))
+ }
+
+ for _, jsonFile := range jsonFiles {
+ // verify all json files exist
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("%q expected but not found", jsonFile)
+ }
+ }
+}
+
func TestDoubleLoadableDepError(t *testing.T) {
// Check whether an error is emitted when a LLNDK depends on a non-double_loadable VNDK lib.
testCcError(t, "module \".*\" variant \".*\": link.* \".*\" which is not LL-NDK, VNDK-SP, .*double_loadable", `
diff --git a/cc/compiler.go b/cc/compiler.go
index 3c86d20..04ed80d 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -687,6 +687,9 @@
// list of shared libraries that provide headers for this binding.
Shared_libs []string `android:"arch_variant"`
+ // List of libraries which export include paths required for this module
+ Header_libs []string `android:"arch_variant,variant_prepend"`
+
// list of clang flags required to correctly interpret the headers.
Cflags []string `android:"arch_variant"`
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index eb3d16f..563ce76 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -22,6 +22,7 @@
"android.hardware.light-ndk_platform",
"android.hardware.identity-ndk_platform",
"android.hardware.keymint-ndk_platform",
+ "android.hardware.keymint-unstable-ndk_platform",
"android.hardware.nfc@1.2",
"android.hardware.power-ndk_platform",
"android.hardware.rebootescrow-ndk_platform",
diff --git a/cc/library.go b/cc/library.go
index eeddd90..2127c08 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -567,7 +567,7 @@
return ""
}
// Return NDK if the library is both NDK and LLNDK.
- if ctx.isNdk() {
+ if ctx.isNdk(ctx.Config()) {
return "NDK"
}
if ctx.isLlndkPublic(ctx.Config()) {
@@ -1099,7 +1099,7 @@
func getRefAbiDumpFile(ctx ModuleContext, vndkVersion, fileName string) android.Path {
// The logic must be consistent with classifySourceAbiDump.
- isNdk := ctx.isNdk()
+ isNdk := ctx.isNdk(ctx.Config())
isLlndkOrVndk := ctx.isLlndkPublic(ctx.Config()) || (ctx.useVndk() && ctx.isVndk())
refAbiDumpTextFile := android.PathForVndkRefAbiDump(ctx, vndkVersion, fileName, isNdk, isLlndkOrVndk, false)
@@ -1153,7 +1153,7 @@
library.sAbiDiff = SourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
refAbiDumpFile, fileName, exportedHeaderFlags,
Bool(library.Properties.Header_abi_checker.Check_all_apis),
- ctx.isLlndk(ctx.Config()), ctx.isNdk(), ctx.isVndkExt())
+ ctx.isLlndk(ctx.Config()), ctx.isNdk(ctx.Config()), ctx.isVndkExt())
}
}
}
diff --git a/cc/makevars.go b/cc/makevars.go
index dcfd6d8..bd8aab5 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -171,6 +171,7 @@
ctx.StrictRaw("SRC_HEADERS", strings.Join(includes, " "))
ctx.StrictRaw("SRC_SYSTEM_HEADERS", strings.Join(systemIncludes, " "))
+ ndkKnownLibs := *getNDKKnownLibs(ctx.Config())
sort.Strings(ndkKnownLibs)
ctx.Strict("NDK_KNOWN_LIBS", strings.Join(ndkKnownLibs, " "))
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 9097e7b..a5c43fe 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -45,8 +45,7 @@
ndkLibrarySuffix = ".ndk"
- // Added as a variation dependency via depsMutator.
- ndkKnownLibs = []string{}
+ ndkKnownLibsKey = android.NewOnceKey("ndkKnownLibsKey")
// protects ndkKnownLibs writes during parallel BeginMutator.
ndkKnownLibsLock sync.Mutex
)
@@ -158,6 +157,12 @@
return true
}
+func getNDKKnownLibs(config android.Config) *[]string {
+ return config.Once(ndkKnownLibsKey, func() interface{} {
+ return &[]string{}
+ }).(*[]string)
+}
+
func (c *stubDecorator) compilerInit(ctx BaseModuleContext) {
c.baseCompiler.compilerInit(ctx)
@@ -168,12 +173,13 @@
ndkKnownLibsLock.Lock()
defer ndkKnownLibsLock.Unlock()
- for _, lib := range ndkKnownLibs {
+ ndkKnownLibs := getNDKKnownLibs(ctx.Config())
+ for _, lib := range *ndkKnownLibs {
if lib == name {
return
}
}
- ndkKnownLibs = append(ndkKnownLibs, name)
+ *ndkKnownLibs = append(*ndkKnownLibs, name)
}
func addStubLibraryCompilerFlags(flags Flags) Flags {
diff --git a/cc/sanitize.go b/cc/sanitize.go
index b1326d9..dbc52a5 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -172,6 +172,12 @@
No_recover []string
}
+ // Sanitizers to run with flag configuration specified
+ Config struct {
+ // Enables CFI support flags for assembly-heavy libraries
+ Cfi_assembly_support *bool `android:"arch_variant"`
+ }
+
// value to pass to -fsanitize-recover=
Recover []string
@@ -543,6 +549,9 @@
flags.Local.CFlags = append(flags.Local.CFlags, cfiCflags...)
flags.Local.AsFlags = append(flags.Local.AsFlags, cfiAsflags...)
+ if Bool(sanitize.Properties.Sanitize.Config.Cfi_assembly_support) {
+ flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-cfi-canonical-jump-tables")
+ }
// Only append the default visibility flag if -fvisibility has not already been set
// to hidden.
if !inList("-fvisibility=hidden", flags.Local.CFlags) {
@@ -847,7 +856,7 @@
return true
}
- if p, ok := d.linker.(*vendorSnapshotLibraryDecorator); ok {
+ if p, ok := d.linker.(*snapshotLibraryDecorator); ok {
if Bool(p.properties.Sanitize_minimal_dep) {
c.sanitize.Properties.MinimalRuntimeDep = true
}
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index 05c06ac..a3d52e6 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -60,7 +60,8 @@
func isSnapshotAware(ctx android.ModuleContext, m *Module, apexInfo android.ApexInfo) bool {
if _, _, ok := isVndkSnapshotLibrary(ctx.DeviceConfig(), m, apexInfo); ok {
return ctx.Config().VndkSnapshotBuildArtifacts()
- } else if isVendorSnapshotModule(m, isVendorProprietaryPath(ctx.ModuleDir()), apexInfo) {
+ } else if isVendorSnapshotModule(m, isVendorProprietaryPath(ctx.ModuleDir()), apexInfo) ||
+ isRecoverySnapshotModule(m, isVendorProprietaryPath(ctx.ModuleDir()), apexInfo) {
return true
}
return false
diff --git a/cc/test.go b/cc/test.go
index 619dc4d..3772691 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -46,6 +46,9 @@
// a list of extra test configuration files that should be installed with the module.
Extra_test_configs []string `android:"path,arch_variant"`
+
+ // If the test is a hostside(no device required) unittest that shall be run during presubmit check.
+ Unit_test *bool
}
type TestBinaryProperties struct {
diff --git a/cc/testing.go b/cc/testing.go
index 5a311f4..7161313 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -563,6 +563,7 @@
RegisterRequiredBuildComponentsForTest(ctx)
ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
+ ctx.RegisterSingletonType("recovery-snapshot", RecoverySnapshotSingleton)
return ctx
}
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 78bde38..6563f6e 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -25,6 +25,115 @@
"android/soong/android"
)
+// Defines the specifics of different images to which the snapshot process is
+// applicable, e.g., vendor, recovery, ramdisk.
+type image interface {
+ // Used to register callbacks with the build system.
+ init()
+
+ // Function that returns true if the module is included in this image.
+ // Using a function return instead of a value to prevent early
+ // evalution of a function that may be not be defined.
+ inImage(m *Module) func() bool
+
+ // Returns the value of the "available" property for a given module for
+ // and snapshot, e.g., "vendor_available", "recovery_available", etc.
+ // or nil if the property is not defined.
+ available(m *Module) *bool
+
+ // Returns true if a dir under source tree is an SoC-owned proprietary
+ // directory, such as device/, vendor/, etc.
+ //
+ // For a given snapshot (e.g., vendor, recovery, etc.) if
+ // isProprietaryPath(dir) returns true, then the module in dir will be
+ // built from sources.
+ isProprietaryPath(dir string) bool
+
+ // Whether to include VNDK in the snapshot for this image.
+ includeVndk() bool
+
+ // Whether a given module has been explicitly excluded from the
+ // snapshot, e.g., using the exclude_from_vendor_snapshot or
+ // exclude_from_recovery_snapshot properties.
+ excludeFromSnapshot(m *Module) bool
+}
+
+type vendorImage struct{}
+type recoveryImage struct{}
+
+func (vendorImage) init() {
+ android.RegisterSingletonType(
+ "vendor-snapshot", VendorSnapshotSingleton)
+ android.RegisterModuleType(
+ "vendor_snapshot_shared", VendorSnapshotSharedFactory)
+ android.RegisterModuleType(
+ "vendor_snapshot_static", VendorSnapshotStaticFactory)
+ android.RegisterModuleType(
+ "vendor_snapshot_header", VendorSnapshotHeaderFactory)
+ android.RegisterModuleType(
+ "vendor_snapshot_binary", VendorSnapshotBinaryFactory)
+ android.RegisterModuleType(
+ "vendor_snapshot_object", VendorSnapshotObjectFactory)
+}
+
+func (vendorImage) inImage(m *Module) func() bool {
+ return m.inVendor
+}
+
+func (vendorImage) available(m *Module) *bool {
+ return m.VendorProperties.Vendor_available
+}
+
+func (vendorImage) isProprietaryPath(dir string) bool {
+ return isVendorProprietaryPath(dir)
+}
+
+func (vendorImage) includeVndk() bool {
+ return true
+}
+
+func (vendorImage) excludeFromSnapshot(m *Module) bool {
+ return m.ExcludeFromVendorSnapshot()
+}
+
+func (recoveryImage) init() {
+ android.RegisterSingletonType(
+ "recovery-snapshot", RecoverySnapshotSingleton)
+ android.RegisterModuleType(
+ "recovery_snapshot_shared", RecoverySnapshotSharedFactory)
+ android.RegisterModuleType(
+ "recovery_snapshot_static", RecoverySnapshotStaticFactory)
+ android.RegisterModuleType(
+ "recovery_snapshot_header", RecoverySnapshotHeaderFactory)
+ android.RegisterModuleType(
+ "recovery_snapshot_binary", RecoverySnapshotBinaryFactory)
+ android.RegisterModuleType(
+ "recovery_snapshot_object", RecoverySnapshotObjectFactory)
+}
+
+func (recoveryImage) inImage(m *Module) func() bool {
+ return m.InRecovery
+}
+
+func (recoveryImage) available(m *Module) *bool {
+ return m.Properties.Recovery_available
+}
+
+func (recoveryImage) isProprietaryPath(dir string) bool {
+ return isRecoveryProprietaryPath(dir)
+}
+
+func (recoveryImage) includeVndk() bool {
+ return false
+}
+
+func (recoveryImage) excludeFromSnapshot(m *Module) bool {
+ return m.ExcludeFromRecoverySnapshot()
+}
+
+var vendorImageSingleton vendorImage
+var recoveryImageSingleton recoveryImage
+
const (
vendorSnapshotHeaderSuffix = ".vendor_header."
vendorSnapshotSharedSuffix = ".vendor_shared."
@@ -33,6 +142,14 @@
vendorSnapshotObjectSuffix = ".vendor_object."
)
+const (
+ recoverySnapshotHeaderSuffix = ".recovery_header."
+ recoverySnapshotSharedSuffix = ".recovery_shared."
+ recoverySnapshotStaticSuffix = ".recovery_static."
+ recoverySnapshotBinarySuffix = ".recovery_binary."
+ recoverySnapshotObjectSuffix = ".recovery_object."
+)
+
var (
vendorSnapshotsLock sync.Mutex
vendorSuffixModulesKey = android.NewOnceKey("vendorSuffixModules")
@@ -136,7 +253,7 @@
}
}
-type vendorSnapshotLibraryProperties struct {
+type snapshotLibraryProperties struct {
// Prebuilt file for each arch.
Src *string `android:"arch_variant"`
@@ -161,25 +278,25 @@
setSanitizerVariation(t sanitizerType, enabled bool)
}
-type vendorSnapshotLibraryDecorator struct {
+type snapshotLibraryDecorator struct {
vendorSnapshotModuleBase
*libraryDecorator
- properties vendorSnapshotLibraryProperties
+ properties snapshotLibraryProperties
sanitizerProperties struct {
CfiEnabled bool `blueprint:"mutated"`
// Library flags for cfi variant.
- Cfi vendorSnapshotLibraryProperties `android:"arch_variant"`
+ Cfi snapshotLibraryProperties `android:"arch_variant"`
}
androidMkVendorSuffix bool
}
-func (p *vendorSnapshotLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
+func (p *snapshotLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
p.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(), p.NameSuffix())
return p.libraryDecorator.linkerFlags(ctx, flags)
}
-func (p *vendorSnapshotLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
+func (p *snapshotLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
arches := config.Arches()
if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
return false
@@ -190,7 +307,7 @@
return true
}
-func (p *vendorSnapshotLibraryDecorator) link(ctx ModuleContext,
+func (p *snapshotLibraryDecorator) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
m := ctx.Module().(*Module)
p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
@@ -246,17 +363,17 @@
return in
}
-func (p *vendorSnapshotLibraryDecorator) install(ctx ModuleContext, file android.Path) {
+func (p *snapshotLibraryDecorator) install(ctx ModuleContext, file android.Path) {
if p.matchesWithDevice(ctx.DeviceConfig()) && (p.shared() || p.static()) {
p.baseInstaller.install(ctx, file)
}
}
-func (p *vendorSnapshotLibraryDecorator) nativeCoverage() bool {
+func (p *snapshotLibraryDecorator) nativeCoverage() bool {
return false
}
-func (p *vendorSnapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) bool {
+func (p *snapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) bool {
switch t {
case cfi:
return p.sanitizerProperties.Cfi.Src != nil
@@ -265,7 +382,7 @@
}
}
-func (p *vendorSnapshotLibraryDecorator) setSanitizerVariation(t sanitizerType, enabled bool) {
+func (p *snapshotLibraryDecorator) setSanitizerVariation(t sanitizerType, enabled bool) {
if !enabled {
return
}
@@ -277,14 +394,14 @@
}
}
-func vendorSnapshotLibrary(suffix string) (*Module, *vendorSnapshotLibraryDecorator) {
+func snapshotLibrary(suffix string) (*Module, *snapshotLibraryDecorator) {
module, library := NewLibrary(android.DeviceSupported)
module.stl = nil
module.sanitize = nil
library.disableStripping()
- prebuilt := &vendorSnapshotLibraryDecorator{
+ prebuilt := &snapshotLibraryDecorator{
libraryDecorator: library,
}
@@ -310,38 +427,56 @@
}
func VendorSnapshotSharedFactory() android.Module {
- module, prebuilt := vendorSnapshotLibrary(vendorSnapshotSharedSuffix)
+ module, prebuilt := snapshotLibrary(vendorSnapshotSharedSuffix)
+ prebuilt.libraryDecorator.BuildOnlyShared()
+ return module.Init()
+}
+
+func RecoverySnapshotSharedFactory() android.Module {
+ module, prebuilt := snapshotLibrary(recoverySnapshotSharedSuffix)
prebuilt.libraryDecorator.BuildOnlyShared()
return module.Init()
}
func VendorSnapshotStaticFactory() android.Module {
- module, prebuilt := vendorSnapshotLibrary(vendorSnapshotStaticSuffix)
+ module, prebuilt := snapshotLibrary(vendorSnapshotStaticSuffix)
+ prebuilt.libraryDecorator.BuildOnlyStatic()
+ return module.Init()
+}
+
+func RecoverySnapshotStaticFactory() android.Module {
+ module, prebuilt := snapshotLibrary(recoverySnapshotStaticSuffix)
prebuilt.libraryDecorator.BuildOnlyStatic()
return module.Init()
}
func VendorSnapshotHeaderFactory() android.Module {
- module, prebuilt := vendorSnapshotLibrary(vendorSnapshotHeaderSuffix)
+ module, prebuilt := snapshotLibrary(vendorSnapshotHeaderSuffix)
prebuilt.libraryDecorator.HeaderOnly()
return module.Init()
}
-var _ snapshotSanitizer = (*vendorSnapshotLibraryDecorator)(nil)
+func RecoverySnapshotHeaderFactory() android.Module {
+ module, prebuilt := snapshotLibrary(recoverySnapshotHeaderSuffix)
+ prebuilt.libraryDecorator.HeaderOnly()
+ return module.Init()
+}
-type vendorSnapshotBinaryProperties struct {
+var _ snapshotSanitizer = (*snapshotLibraryDecorator)(nil)
+
+type snapshotBinaryProperties struct {
// Prebuilt file for each arch.
Src *string `android:"arch_variant"`
}
-type vendorSnapshotBinaryDecorator struct {
+type snapshotBinaryDecorator struct {
vendorSnapshotModuleBase
*binaryDecorator
- properties vendorSnapshotBinaryProperties
+ properties snapshotBinaryProperties
androidMkVendorSuffix bool
}
-func (p *vendorSnapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
+func (p *snapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
if config.DeviceArch() != p.arch() {
return false
}
@@ -351,7 +486,7 @@
return true
}
-func (p *vendorSnapshotBinaryDecorator) link(ctx ModuleContext,
+func (p *snapshotBinaryDecorator) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
if !p.matchesWithDevice(ctx.DeviceConfig()) {
return nil
@@ -382,11 +517,19 @@
return outputFile
}
-func (p *vendorSnapshotBinaryDecorator) nativeCoverage() bool {
+func (p *snapshotBinaryDecorator) nativeCoverage() bool {
return false
}
func VendorSnapshotBinaryFactory() android.Module {
+ return snapshotBinaryFactory(vendorSnapshotBinarySuffix)
+}
+
+func RecoverySnapshotBinaryFactory() android.Module {
+ return snapshotBinaryFactory(recoverySnapshotBinarySuffix)
+}
+
+func snapshotBinaryFactory(suffix string) android.Module {
module, binary := NewBinary(android.DeviceSupported)
binary.baseLinker.Properties.No_libcrt = BoolPtr(true)
binary.baseLinker.Properties.Nocrt = BoolPtr(true)
@@ -396,7 +539,7 @@
binary.baseLinker.Properties.System_shared_libs = []string{}
}
- prebuilt := &vendorSnapshotBinaryDecorator{
+ prebuilt := &snapshotBinaryDecorator{
binaryDecorator: binary,
}
@@ -405,7 +548,7 @@
module.stl = nil
module.linker = prebuilt
- prebuilt.init(module, vendorSnapshotBinarySuffix)
+ prebuilt.init(module, suffix)
module.AddProperties(&prebuilt.properties)
return module.Init()
}
@@ -415,14 +558,14 @@
Src *string `android:"arch_variant"`
}
-type vendorSnapshotObjectLinker struct {
+type snapshotObjectLinker struct {
vendorSnapshotModuleBase
objectLinker
properties vendorSnapshotObjectProperties
androidMkVendorSuffix bool
}
-func (p *vendorSnapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool {
+func (p *snapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool {
if config.DeviceArch() != p.arch() {
return false
}
@@ -432,7 +575,7 @@
return true
}
-func (p *vendorSnapshotObjectLinker) link(ctx ModuleContext,
+func (p *snapshotObjectLinker) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
if !p.matchesWithDevice(ctx.DeviceConfig()) {
return nil
@@ -444,14 +587,14 @@
return android.PathForModuleSrc(ctx, *p.properties.Src)
}
-func (p *vendorSnapshotObjectLinker) nativeCoverage() bool {
+func (p *snapshotObjectLinker) nativeCoverage() bool {
return false
}
func VendorSnapshotObjectFactory() android.Module {
module := newObject()
- prebuilt := &vendorSnapshotObjectLinker{
+ prebuilt := &snapshotObjectLinker{
objectLinker: objectLinker{
baseLinker: NewBaseLinker(nil),
},
@@ -463,21 +606,68 @@
return module.Init()
}
+func RecoverySnapshotObjectFactory() android.Module {
+ module := newObject()
+
+ prebuilt := &snapshotObjectLinker{
+ objectLinker: objectLinker{
+ baseLinker: NewBaseLinker(nil),
+ },
+ }
+ module.linker = prebuilt
+
+ prebuilt.init(module, recoverySnapshotObjectSuffix)
+ module.AddProperties(&prebuilt.properties)
+ return module.Init()
+}
+
func init() {
- android.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
- android.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory)
- android.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory)
- android.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory)
- android.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
- android.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory)
+ vendorImageSingleton.init()
+ recoveryImageSingleton.init()
+}
+
+var vendorSnapshotSingleton = snapshotSingleton{
+ "vendor",
+ "SOONG_VENDOR_SNAPSHOT_ZIP",
+ android.OptionalPath{},
+ true,
+ vendorImageSingleton,
+}
+
+var recoverySnapshotSingleton = snapshotSingleton{
+ "recovery",
+ "SOONG_RECOVERY_SNAPSHOT_ZIP",
+ android.OptionalPath{},
+ false,
+ recoveryImageSingleton,
}
func VendorSnapshotSingleton() android.Singleton {
- return &vendorSnapshotSingleton{}
+ return &vendorSnapshotSingleton
}
-type vendorSnapshotSingleton struct {
- vendorSnapshotZipFile android.OptionalPath
+func RecoverySnapshotSingleton() android.Singleton {
+ return &recoverySnapshotSingleton
+}
+
+type snapshotSingleton struct {
+ // Name, e.g., "vendor", "recovery", "ramdisk".
+ name string
+
+ // Make variable that points to the snapshot file, e.g.,
+ // "SOONG_RECOVERY_SNAPSHOT_ZIP".
+ makeVar string
+
+ // Path to the snapshot zip file.
+ snapshotZipFile android.OptionalPath
+
+ // Whether the image supports VNDK extension modules.
+ supportsVndkExt bool
+
+ // Implementation of the image interface specific to the image
+ // associated with this snapshot (e.g., specific to the vendor image,
+ // recovery image, etc.).
+ image image
}
var (
@@ -491,6 +681,17 @@
"hardware",
}
+ // Modules under following directories are ignored. They are OEM's and vendor's
+ // proprietary modules(device/, kernel/, vendor/, and hardware/).
+ // TODO(b/65377115): Clean up these with more maintainable way
+ recoveryProprietaryDirs = []string{
+ "bootable/recovery",
+ "device",
+ "hardware",
+ "kernel",
+ "vendor",
+ }
+
// Modules under following directories are included as they are in AOSP,
// although hardware/ and kernel/ are normally for vendor's own.
// TODO(b/65377115): Clean up these with more maintainable way
@@ -508,7 +709,17 @@
// Determine if a dir under source tree is an SoC-owned proprietary directory, such as
// device/, vendor/, etc.
func isVendorProprietaryPath(dir string) bool {
- for _, p := range vendorProprietaryDirs {
+ return isProprietaryPath(dir, vendorProprietaryDirs)
+}
+
+func isRecoveryProprietaryPath(dir string) bool {
+ return isProprietaryPath(dir, recoveryProprietaryDirs)
+}
+
+// Determine if a dir under source tree is an SoC-owned proprietary directory, such as
+// device/, vendor/, etc.
+func isProprietaryPath(dir string, proprietaryDirs []string) bool {
+ for _, p := range proprietaryDirs {
if strings.HasPrefix(dir, p) {
// filter out AOSP defined directories, e.g. hardware/interfaces/
aosp := false
@@ -556,6 +767,14 @@
// depend on newer VNDK) So they are captured as vendor snapshot To build older vendor
// image and newer system image altogether.
func isVendorSnapshotModule(m *Module, inVendorProprietaryPath bool, apexInfo android.ApexInfo) bool {
+ return isSnapshotModule(m, inVendorProprietaryPath, apexInfo, vendorImageSingleton)
+}
+
+func isRecoverySnapshotModule(m *Module, inRecoveryProprietaryPath bool, apexInfo android.ApexInfo) bool {
+ return isSnapshotModule(m, inRecoveryProprietaryPath, apexInfo, recoveryImageSingleton)
+}
+
+func isSnapshotModule(m *Module, inProprietaryPath bool, apexInfo android.ApexInfo, image image) bool {
if !m.Enabled() || m.Properties.HideFromMake {
return false
}
@@ -564,8 +783,9 @@
if m.IsSkipInstall() {
return false
}
- // skip proprietary modules, but include all VNDK (static)
- if inVendorProprietaryPath && !m.IsVndk() {
+ // skip proprietary modules, but (for the vendor snapshot only)
+ // include all VNDK (static)
+ if inProprietaryPath && (!image.includeVndk() || !m.IsVndk()) {
return false
}
// If the module would be included based on its path, check to see if
@@ -580,7 +800,7 @@
return false
}
// the module must be installed in /vendor
- if !apexInfo.IsForPlatform() || m.isSnapshotPrebuilt() || !m.inVendor() {
+ if !apexInfo.IsForPlatform() || m.isSnapshotPrebuilt() || !image.inImage(m)() {
return false
}
// skip kernel_headers which always depend on vendor
@@ -612,29 +832,31 @@
}
}
if l.static() {
- return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
+ return m.outputFile.Valid() && proptools.BoolDefault(image.available(m), true)
}
if l.shared() {
if !m.outputFile.Valid() {
return false
}
- if !m.IsVndk() {
- return true
+ if image.includeVndk() {
+ if !m.IsVndk() {
+ return true
+ }
+ return m.isVndkExt()
}
- return m.isVndkExt()
}
return true
}
// Binaries and Objects
if m.binary() || m.object() {
- return m.outputFile.Valid() && proptools.BoolDefault(m.VendorProperties.Vendor_available, true)
+ return m.outputFile.Valid() && proptools.BoolDefault(image.available(m), true)
}
return false
}
-func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
// BOARD_VNDK_VERSION must be set to 'current' in order to generate a vendor snapshot.
if ctx.DeviceConfig().VndkVersion() != "current" {
return
@@ -675,7 +897,7 @@
(header files of same directory structure with source tree)
*/
- snapshotDir := "vendor-snapshot"
+ snapshotDir := c.name + "-snapshot"
snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
includeDir := filepath.Join(snapshotArchDir, "include")
@@ -722,7 +944,7 @@
// Common properties among snapshots.
prop.ModuleName = ctx.ModuleName(m)
- if m.isVndkExt() {
+ if c.supportsVndkExt && m.isVndkExt() {
// vndk exts are installed to /vendor/lib(64)?/vndk(-sp)?
if m.isVndkSp() {
prop.RelativeInstallPath = "vndk-sp"
@@ -843,26 +1065,30 @@
}
moduleDir := ctx.ModuleDir(module)
- inVendorProprietaryPath := isVendorProprietaryPath(moduleDir)
+ inProprietaryPath := c.image.isProprietaryPath(moduleDir)
apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
if m.ExcludeFromVendorSnapshot() {
- if inVendorProprietaryPath {
+ if inProprietaryPath {
// Error: exclude_from_vendor_snapshot applies
// to framework-path modules only.
ctx.Errorf("module %q in vendor proprietary path %q may not use \"exclude_from_vendor_snapshot: true\"", m.String(), moduleDir)
return
}
- if Bool(m.VendorProperties.Vendor_available) {
+ if Bool(c.image.available(m)) {
// Error: may not combine "vendor_available:
// true" with "exclude_from_vendor_snapshot:
// true".
- ctx.Errorf("module %q may not use both \"vendor_available: true\" and \"exclude_from_vendor_snapshot: true\"", m.String())
+ ctx.Errorf(
+ "module %q may not use both \""+
+ c.name+
+ "_available: true\" and \"exclude_from_vendor_snapshot: true\"",
+ m.String())
return
}
}
- if !isVendorSnapshotModule(m, inVendorProprietaryPath, apexInfo) {
+ if !isSnapshotModule(m, inProprietaryPath, apexInfo, c.image) {
return
}
@@ -894,11 +1120,17 @@
return snapshotOutputs[i].String() < snapshotOutputs[j].String()
})
- zipPath := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+".zip")
+ zipPath := android.PathForOutput(
+ ctx,
+ snapshotDir,
+ c.name+"-"+ctx.Config().DeviceName()+".zip")
zipRule := android.NewRuleBuilder()
// filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr
- snapshotOutputList := android.PathForOutput(ctx, snapshotDir, "vendor-"+ctx.Config().DeviceName()+"_list")
+ snapshotOutputList := android.PathForOutput(
+ ctx,
+ snapshotDir,
+ c.name+"-"+ctx.Config().DeviceName()+"_list")
zipRule.Command().
Text("tr").
FlagWithArg("-d ", "\\'").
@@ -913,13 +1145,15 @@
FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()).
FlagWithInput("-l ", snapshotOutputList)
- zipRule.Build(pctx, ctx, zipPath.String(), "vendor snapshot "+zipPath.String())
+ zipRule.Build(pctx, ctx, zipPath.String(), c.name+" snapshot "+zipPath.String())
zipRule.DeleteTemporaryFiles()
- c.vendorSnapshotZipFile = android.OptionalPathForPath(zipPath)
+ c.snapshotZipFile = android.OptionalPathForPath(zipPath)
}
-func (c *vendorSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
- ctx.Strict("SOONG_VENDOR_SNAPSHOT_ZIP", c.vendorSnapshotZipFile.String())
+func (c *snapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
+ ctx.Strict(
+ c.makeVar,
+ c.snapshotZipFile.String())
}
type snapshotInterface interface {
@@ -927,9 +1161,9 @@
}
var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil)
-var _ snapshotInterface = (*vendorSnapshotLibraryDecorator)(nil)
-var _ snapshotInterface = (*vendorSnapshotBinaryDecorator)(nil)
-var _ snapshotInterface = (*vendorSnapshotObjectLinker)(nil)
+var _ snapshotInterface = (*snapshotLibraryDecorator)(nil)
+var _ snapshotInterface = (*snapshotBinaryDecorator)(nil)
+var _ snapshotInterface = (*snapshotObjectLinker)(nil)
// gathers all snapshot modules for vendor, and disable unnecessary snapshots
// TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules
@@ -970,9 +1204,9 @@
// header
snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
}
- } else if _, ok := module.linker.(*vendorSnapshotBinaryDecorator); ok {
+ } else if _, ok := module.linker.(*snapshotBinaryDecorator); ok {
snapshotMap = vendorSnapshotBinaries(ctx.Config())
- } else if _, ok := module.linker.(*vendorSnapshotObjectLinker); ok {
+ } else if _, ok := module.linker.(*snapshotObjectLinker); ok {
snapshotMap = vendorSnapshotObjects(ctx.Config())
} else {
return
diff --git a/cmd/soong_env/soong_env.go b/cmd/soong_env/soong_env.go
index d305d83..8020b17 100644
--- a/cmd/soong_env/soong_env.go
+++ b/cmd/soong_env/soong_env.go
@@ -12,10 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// soong_glob is the command line tool that checks if the list of files matching a glob has
-// changed, and only updates the output file list if it has changed. It is used to optimize
-// out build.ninja regenerations when non-matching files are added. See
-// android/soong/android/glob.go for a longer description.
+// soong_env determines if the given soong environment file (usually ".soong.environment") is stale
+// by comparing its contents to the current corresponding environment variable values.
+// It fails if the file cannot be opened or corrupted, or its contents differ from the current
+// values.
+
package main
import (
@@ -34,6 +35,7 @@
os.Exit(2)
}
+// This is a simple executable packaging, and the real work happens in env.StaleEnvFile.
func main() {
flag.Parse()
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index aee8e5a..29030d6 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -125,27 +125,35 @@
os.Exit(1)
}
+ // Create a terminal output that mimics Ninja's.
output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.simpleOutput,
build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"))
+ // Attach a new logger instance to the terminal output.
log := logger.New(output)
defer log.Cleanup()
+ // Create a context to simplify the program termination process.
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
+ // Create a new trace file writer, making it log events to the log instance.
trace := tracer.New(log)
defer trace.Close()
+ // Create and start a new metric record.
met := metrics.New()
met.SetBuildDateTime(buildStarted)
met.SetBuildCommand(os.Args)
+ // Create a new Status instance, which manages action counts and event output channels.
stat := &status.Status{}
defer stat.Finish()
+ // Hook up the terminal output and tracer to Status.
stat.AddOutput(output)
stat.AddOutput(trace.StatusTracer())
+ // Set up a cleanup procedure in case the normal termination process doesn't work.
build.SetupSignals(log, cancel, func() {
trace.Close()
log.Cleanup()
@@ -165,6 +173,7 @@
build.SetupOutDir(buildCtx, config)
+ // Set up files to be outputted in the log directory.
logsDir := config.OutDir()
if config.Dist() {
logsDir = filepath.Join(config.DistDir(), "logs")
@@ -192,7 +201,10 @@
defer met.Dump(soongMetricsFile)
defer build.DumpRBEMetrics(buildCtx, config, rbeMetricsFile)
+ // Read the time at the starting point.
if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
+ // soong_ui.bash uses the date command's %N (nanosec) flag when getting the start time,
+ // which Darwin doesn't support. Check if it was executed properly before parsing the value.
if !strings.HasSuffix(start, "N") {
if start_time, err := strconv.ParseUint(start, 10, 64); err == nil {
log.Verbosef("Took %dms to start up.",
@@ -211,6 +223,7 @@
fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.bp")
fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.mk")
+ // Create a source finder.
f := build.NewSourceFinder(buildCtx, config)
defer f.Shutdown()
build.FindSources(buildCtx, config, f)
@@ -354,6 +367,8 @@
return terminal.StdioImpl{}
}
+// dumpvar and dumpvars use stdout to output variable values, so use stderr instead of stdout when
+// reporting events to keep stdout clean from noise.
func customStdio() terminal.StdioInterface {
return terminal.NewCustomStdio(os.Stdin, os.Stderr, os.Stderr)
}
@@ -493,16 +508,6 @@
if c.flag == args[1] {
return &c, args[2:], nil
}
-
- // special case for --make-mode: if soong_ui was called from
- // build/make/core/main.mk, the makeparallel with --ninja
- // option specified puts the -j<num> before --make-mode.
- // TODO: Remove this hack once it has been fixed.
- if c.flag == makeModeFlagName {
- if inList(makeModeFlagName, args) {
- return &c, args[1:], nil
- }
- }
}
// command not found
diff --git a/cmd/zipsync/zipsync.go b/cmd/zipsync/zipsync.go
index 294e5ef..aecdc3d 100644
--- a/cmd/zipsync/zipsync.go
+++ b/cmd/zipsync/zipsync.go
@@ -53,6 +53,16 @@
return out.Close()
}
+func writeSymlink(filename string, in io.Reader) error {
+ b, err := ioutil.ReadAll(in)
+ if err != nil {
+ return err
+ }
+ dest := string(b)
+ err = os.Symlink(dest, filename)
+ return err
+}
+
func main() {
flag.Usage = func() {
fmt.Fprintln(os.Stderr, "usage: zipsync -d <output dir> [-l <output file>] [-f <pattern>] [zip]...")
@@ -122,7 +132,11 @@
if err != nil {
log.Fatal(err)
}
- must(writeFile(filename, in, f.FileInfo().Mode()))
+ if f.FileInfo().Mode()&os.ModeSymlink != 0 {
+ must(writeSymlink(filename, in))
+ } else {
+ must(writeFile(filename, in, f.FileInfo().Mode()))
+ }
in.Close()
files = append(files, filename)
}
diff --git a/env/env.go b/env/env.go
index a98e1f6..735a38a 100644
--- a/env/env.go
+++ b/env/env.go
@@ -27,6 +27,15 @@
type envFileEntry struct{ Key, Value string }
type envFileData []envFileEntry
+// Serializes the given environment variable name/value map into JSON formatted bytes by converting
+// to envFileEntry values and marshaling them.
+//
+// e.g. OUT_DIR = "out"
+// is converted to:
+// {
+// "Key": "OUT_DIR",
+// "Value": "out",
+// },
func EnvFileContents(envDeps map[string]string) ([]byte, error) {
contents := make(envFileData, 0, len(envDeps))
for key, value := range envDeps {
@@ -45,8 +54,11 @@
return data, nil
}
-func StaleEnvFile(filename string) (bool, error) {
- data, err := ioutil.ReadFile(filename)
+// Reads and deserializes a Soong environment file located at the given file path to determine its
+// staleness. If any environment variable values have changed, it prints them out and returns true.
+// Failing to read or parse the file also causes it to return true.
+func StaleEnvFile(filepath string) (bool, error) {
+ data, err := ioutil.ReadFile(filepath)
if err != nil {
return true, err
}
@@ -79,6 +91,7 @@
return false, nil
}
+// Implements sort.Interface so that we can use sort.Sort on envFileData arrays.
func (e envFileData) Len() int {
return len(e)
}
@@ -90,3 +103,5 @@
func (e envFileData) Swap(i, j int) {
e[i], e[j] = e[j], e[i]
}
+
+var _ sort.Interface = envFileData{}
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 44b8149..a6d1fcf 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -14,9 +14,20 @@
package etc
-import (
- "strconv"
+// This file implements module types that install prebuilt artifacts.
+//
+// There exist two classes of prebuilt modules in the Android tree. The first class are the ones
+// based on `android.Prebuilt`, such as `cc_prebuilt_library` and `java_import`. This kind of
+// modules may exist both as prebuilts and source at the same time, though only one would be
+// installed and the other would be marked disabled. The `prebuilt_postdeps` mutator would select
+// the actual modules to be installed. More details in android/prebuilt.go.
+//
+// The second class is described in this file. Unlike `android.Prebuilt` based module types,
+// `prebuilt_etc` exist only as prebuilts and cannot have a same-named source module counterpart.
+// This makes the logic of `prebuilt_etc` to be much simpler as they don't need to go through the
+// various `prebuilt_*` mutators.
+import (
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -42,7 +53,7 @@
}
type prebuiltEtcProperties struct {
- // Source file of this prebuilt.
+ // Source file of this prebuilt. Can reference a genrule type module with the ":module" syntax.
Src *string `android:"path,arch_variant"`
// optional subdirectory under which this file is installed into, cannot be specified with relative_install_path, prefer relative_install_path
@@ -209,6 +220,11 @@
func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
p.sourceFilePath = android.PathForModuleSrc(ctx, android.String(p.properties.Src))
+
+ // Determine the output file basename.
+ // If Filename is set, use the name specified by the property.
+ // If Filename_from_src is set, use the source file name.
+ // Otherwise use the module name.
filename := android.String(p.properties.Filename)
filename_from_src := android.Bool(p.properties.Filename_from_src)
if filename == "" {
@@ -274,11 +290,9 @@
if len(p.properties.Symlinks) > 0 {
entries.AddStrings("LOCAL_MODULE_SYMLINKS", p.properties.Symlinks...)
}
- entries.SetString("LOCAL_UNINSTALLABLE_MODULE", strconv.FormatBool(!p.Installable()))
+ entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.Installable())
if p.additionalDependencies != nil {
- for _, path := range *p.additionalDependencies {
- entries.AddStrings("LOCAL_ADDITIONAL_DEPENDENCIES", path.String())
- }
+ entries.AddStrings("LOCAL_ADDITIONAL_DEPENDENCIES", p.additionalDependencies.Strings()...)
}
},
},
diff --git a/filesystem/Android.bp b/filesystem/Android.bp
new file mode 100644
index 0000000..926df6e
--- /dev/null
+++ b/filesystem/Android.bp
@@ -0,0 +1,15 @@
+bootstrap_go_package {
+ name: "soong-filesystem",
+ pkgPath: "android/soong/filesystem",
+ deps: [
+ "blueprint",
+ "soong",
+ "soong-android",
+ ],
+ srcs: [
+ "filesystem.go",
+ ],
+ testSrcs: [
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
new file mode 100644
index 0000000..a1605b4
--- /dev/null
+++ b/filesystem/filesystem.go
@@ -0,0 +1,76 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// 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 filesystem
+
+import (
+ "fmt"
+
+ "android/soong/android"
+)
+
+func init() {
+ android.RegisterModuleType("android_filesystem", filesystemFactory)
+}
+
+type filesystem struct {
+ android.ModuleBase
+ android.PackagingBase
+}
+
+func filesystemFactory() android.Module {
+ module := &filesystem{}
+ android.InitPackageModule(module)
+ android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ return module
+}
+
+func (f *filesystem) DepsMutator(ctx android.BottomUpMutatorContext) {
+ f.AddDeps(ctx)
+}
+
+var pctx = android.NewPackageContext("android/soong/filesystem")
+
+func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ zipFile := android.PathForModuleOut(ctx, "temp.zip").OutputPath
+ f.CopyDepsToZip(ctx, zipFile)
+
+ rootDir := android.PathForModuleOut(ctx, "root").OutputPath
+ builder := android.NewRuleBuilder()
+ builder.Command().
+ BuiltTool(ctx, "zipsync").
+ FlagWithArg("-d ", rootDir.String()). // zipsync wipes this. No need to clear.
+ Input(zipFile)
+
+ mkuserimg := ctx.Config().HostToolPath(ctx, "mkuserimg_mke2fs")
+ propFile := android.PathForModuleOut(ctx, "prop").OutputPath
+ // TODO(jiyong): support more filesystem types other than ext4
+ propsText := fmt.Sprintf(`mount_point=system\n`+
+ `fs_type=ext4\n`+
+ `use_dynamic_partition_size=true\n`+
+ `ext_mkuserimg=%s\n`, mkuserimg.String())
+ builder.Command().Text("echo").Flag("-e").Flag(`"` + propsText + `"`).
+ Text(">").Output(propFile).
+ Implicit(mkuserimg)
+
+ image := android.PathForModuleOut(ctx, "filesystem.img").OutputPath
+ builder.Command().BuiltTool(ctx, "build_image").
+ Text(rootDir.String()). // input directory
+ Input(propFile).
+ Output(image).
+ Text(rootDir.String()) // directory where to find fs_config_files|dirs
+
+ // rootDir is not deleted. Might be useful for quick inspection.
+ builder.Build(pctx, ctx, "build_filesystem_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName()))
+}
diff --git a/java/androidmk.go b/java/androidmk.go
index f263cb8..386a97f 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -160,6 +160,9 @@
entries.SetString("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", "true")
}
entries.AddStrings("LOCAL_TEST_MAINLINE_MODULES", j.testProperties.Test_mainline_modules...)
+ if Bool(j.testProperties.Test_options.Unit_test) {
+ entries.SetBool("LOCAL_IS_UNIT_TEST", true)
+ }
})
return entriesList
diff --git a/java/app.go b/java/app.go
index 17de8b9..3446739 100755
--- a/java/app.go
+++ b/java/app.go
@@ -890,7 +890,7 @@
if IsJniDepTag(tag) || cc.IsSharedDepTag(tag) {
if dep, ok := module.(*cc.Module); ok {
- if dep.IsNdk() || dep.IsStubs() {
+ if dep.IsNdk(ctx.Config()) || dep.IsStubs() {
return false
}
diff --git a/java/app_test.go b/java/app_test.go
index 6429ab8..6efb0dc 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -291,7 +291,7 @@
}
`)
- testJavaError(t, "Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.", `
+ testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", `
android_app {
name: "foo",
srcs: ["a.java"],
@@ -335,7 +335,7 @@
}
`)
- testJavaError(t, "Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.", `
+ testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", `
android_app {
name: "foo",
srcs: ["a.java"],
diff --git a/java/droiddoc.go b/java/droiddoc.go
index c7a27c2..cf7f4fb 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1748,8 +1748,6 @@
properties PrebuiltStubsSourcesProperties
- // The source directories containing stubs source files.
- srcDirs android.Paths
stubsSrcJar android.ModuleOutPath
}
@@ -1769,21 +1767,29 @@
func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
p.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
- p.srcDirs = android.PathsForModuleSrc(ctx, p.properties.Srcs)
+ if len(p.properties.Srcs) != 1 {
+ ctx.PropertyErrorf("srcs", "must only specify one directory path, contains %d paths", len(p.properties.Srcs))
+ return
+ }
+
+ localSrcDir := p.properties.Srcs[0]
+ // Although PathForModuleSrc can return nil if either the path doesn't exist or
+ // the path components are invalid it won't in this case because no components
+ // are specified and the module directory must exist in order to get this far.
+ srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, localSrcDir)
+
+ // Glob the contents of the directory just in case the directory does not exist.
+ srcGlob := localSrcDir + "/**/*"
+ srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
rule := android.NewRuleBuilder()
- command := rule.Command().
+ rule.Command().
BuiltTool(ctx, "soong_zip").
Flag("-write_if_changed").
Flag("-jar").
- FlagWithOutput("-o ", p.stubsSrcJar)
-
- for _, d := range p.srcDirs {
- dir := d.String()
- command.
- FlagWithArg("-C ", dir).
- FlagWithInput("-D ", d)
- }
+ FlagWithOutput("-o ", p.stubsSrcJar).
+ FlagWithArg("-C ", srcDir.String()).
+ FlagWithRspFileInputList("-r ", srcPaths)
rule.Restat()
diff --git a/java/java.go b/java/java.go
index 5ded041..7cf04fa 100644
--- a/java/java.go
+++ b/java/java.go
@@ -248,6 +248,9 @@
Errorprone struct {
// List of javac flags that should only be used when running errorprone.
Javacflags []string
+
+ // List of java_plugin modules that provide extra errorprone checks.
+ Extra_check_modules []string
}
Proto struct {
@@ -569,6 +572,7 @@
libTag = dependencyTag{name: "javalib"}
java9LibTag = dependencyTag{name: "java9lib"}
pluginTag = dependencyTag{name: "plugin"}
+ errorpronePluginTag = dependencyTag{name: "errorprone-plugin"}
exportedPluginTag = dependencyTag{name: "exported-plugin"}
bootClasspathTag = dependencyTag{name: "bootclasspath"}
systemModulesTag = dependencyTag{name: "system modules"}
@@ -765,6 +769,7 @@
}
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), pluginTag, j.properties.Plugins...)
+ ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), errorpronePluginTag, j.properties.Errorprone.Extra_check_modules...)
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), exportedPluginTag, j.properties.Exported_plugins...)
android.ProtoDeps(ctx, &j.protoProperties)
@@ -852,21 +857,22 @@
}
type deps struct {
- classpath classpath
- java9Classpath classpath
- bootClasspath classpath
- processorPath classpath
- processorClasses []string
- staticJars android.Paths
- staticHeaderJars android.Paths
- staticResourceJars android.Paths
- aidlIncludeDirs android.Paths
- srcs android.Paths
- srcJars android.Paths
- systemModules *systemModules
- aidlPreprocess android.OptionalPath
- kotlinStdlib android.Paths
- kotlinAnnotations android.Paths
+ classpath classpath
+ java9Classpath classpath
+ bootClasspath classpath
+ processorPath classpath
+ errorProneProcessorPath classpath
+ processorClasses []string
+ staticJars android.Paths
+ staticHeaderJars android.Paths
+ staticResourceJars android.Paths
+ aidlIncludeDirs android.Paths
+ srcs android.Paths
+ srcJars android.Paths
+ systemModules *systemModules
+ aidlPreprocess android.OptionalPath
+ kotlinStdlib android.Paths
+ kotlinAnnotations android.Paths
disableTurbine bool
}
@@ -952,7 +958,9 @@
return
}
otherLinkType, _ := to.getLinkType(ctx.OtherModuleName(to))
- commonMessage := "Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source."
+ commonMessage := " In order to fix this, consider adjusting sdk_version: OR platform_apis: " +
+ "property of the source or target module so that target module is built with the same " +
+ "or smaller API set when compared to the source."
switch myLinkType {
case javaCore:
@@ -1066,6 +1074,12 @@
} else {
ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
}
+ case errorpronePluginTag:
+ if plugin, ok := dep.(*Plugin); ok {
+ deps.errorProneProcessorPath = append(deps.errorProneProcessorPath, plugin.ImplementationAndResourcesJars()...)
+ } else {
+ ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
+ }
case exportedPluginTag:
if plugin, ok := dep.(*Plugin); ok {
if plugin.pluginProperties.Generates_api != nil && *plugin.pluginProperties.Generates_api {
@@ -1189,7 +1203,7 @@
flags.javaVersion = getJavaVersion(ctx, String(j.properties.Java_version), sdkContext(j))
if ctx.Config().RunErrorProne() {
- if config.ErrorProneClasspath == nil {
+ if config.ErrorProneClasspath == nil && ctx.Config().TestProductVariables == nil {
ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
}
@@ -1209,6 +1223,7 @@
flags.classpath = append(flags.classpath, deps.classpath...)
flags.java9Classpath = append(flags.java9Classpath, deps.java9Classpath...)
flags.processorPath = append(flags.processorPath, deps.processorPath...)
+ flags.errorProneProcessorPath = append(flags.errorProneProcessorPath, deps.errorProneProcessorPath...)
flags.processors = append(flags.processors, deps.processorClasses...)
flags.processors = android.FirstUniqueStrings(flags.processors)
@@ -2226,6 +2241,9 @@
type TestOptions struct {
// a list of extra test configuration files that should be installed with the module.
Extra_test_configs []string `android:"path,arch_variant"`
+
+ // If the test is a hostside(no device required) unittest that shall be run during presubmit check.
+ Unit_test *bool
}
type testProperties struct {
@@ -2322,7 +2340,7 @@
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template,
- j.testProperties.Test_suites, j.testProperties.Auto_gen_config)
+ j.testProperties.Test_suites, j.testProperties.Auto_gen_config, j.testProperties.Test_options.Unit_test)
j.data = android.PathsForModuleSrc(ctx, j.testProperties.Data)
@@ -2341,7 +2359,7 @@
func (j *JavaTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.prebuiltTestProperties.Test_config, nil,
- j.prebuiltTestProperties.Test_suites, nil)
+ j.prebuiltTestProperties.Test_suites, nil, nil)
j.Import.GenerateAndroidBuildActions(ctx)
}
diff --git a/java/java_test.go b/java/java_test.go
index efca039..cf56e66 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -15,6 +15,7 @@
package java
import (
+ "fmt"
"io/ioutil"
"os"
"path/filepath"
@@ -92,8 +93,8 @@
ctx.PreDepsMutators(python.RegisterPythonPreDepsMutators)
ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
- ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(OverlaySingletonFactory))
- ctx.RegisterPreSingletonType("sdk_versions", android.SingletonFactoryAdaptor(sdkPreSingletonFactory))
+ ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(ctx.Context, OverlaySingletonFactory))
+ ctx.RegisterPreSingletonType("sdk_versions", android.SingletonFactoryAdaptor(ctx.Context, sdkPreSingletonFactory))
android.RegisterPrebuiltMutators(ctx)
@@ -202,7 +203,7 @@
}
`)
- testJavaError(t, "Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.", `
+ testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", `
java_library {
name: "foo",
srcs: ["a.java"],
@@ -246,7 +247,7 @@
}
`)
- testJavaError(t, "Adjust sdk_version: property of the source or target module so that target module is built with the same or smaller API set than the source.", `
+ testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", `
java_library {
name: "foo",
srcs: ["a.java"],
@@ -622,6 +623,35 @@
}
}
+func TestPrebuiltStubsSources(t *testing.T) {
+ test := func(t *testing.T, sourcesPath string, expectedInputs []string) {
+ ctx, _ := testJavaWithFS(t, fmt.Sprintf(`
+prebuilt_stubs_sources {
+ name: "stubs-source",
+ srcs: ["%s"],
+}`, sourcesPath), map[string][]byte{
+ "stubs/sources/pkg/A.java": nil,
+ "stubs/sources/pkg/B.java": nil,
+ })
+
+ zipSrc := ctx.ModuleForTests("stubs-source", "android_common").Rule("zip_src")
+ if expected, actual := expectedInputs, zipSrc.Inputs.Strings(); !reflect.DeepEqual(expected, actual) {
+ t.Errorf("mismatch of inputs to soong_zip: expected %q, actual %q", expected, actual)
+ }
+ }
+
+ t.Run("empty/missing directory", func(t *testing.T) {
+ test(t, "empty-directory", []string{})
+ })
+
+ t.Run("non-empty set of sources", func(t *testing.T) {
+ test(t, "stubs/sources", []string{
+ "stubs/sources/pkg/A.java",
+ "stubs/sources/pkg/B.java",
+ })
+ })
+}
+
func TestJavaSdkLibraryImport(t *testing.T) {
ctx, _ := testJava(t, `
java_library {
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index 60ca1c4..77ef294 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -84,11 +84,14 @@
}
func TestKapt(t *testing.T) {
- ctx, _ := testJava(t, `
+ bp := `
java_library {
name: "foo",
srcs: ["a.java", "b.kt"],
plugins: ["bar", "baz"],
+ errorprone: {
+ extra_check_modules: ["my_check"],
+ },
}
java_plugin {
@@ -102,64 +105,119 @@
processor_class: "com.baz",
srcs: ["b.java"],
}
- `)
- buildOS := android.BuildOs.String()
+ java_plugin {
+ name: "my_check",
+ srcs: ["b.java"],
+ }
+ `
+ t.Run("", func(t *testing.T) {
+ ctx, _ := testJava(t, bp)
- kapt := ctx.ModuleForTests("foo", "android_common").Rule("kapt")
- kotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
- javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
+ buildOS := android.BuildOs.String()
- bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String()
- baz := ctx.ModuleForTests("baz", buildOS+"_common").Rule("javac").Output.String()
+ kapt := ctx.ModuleForTests("foo", "android_common").Rule("kapt")
+ kotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
+ javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
- // Test that the kotlin and java sources are passed to kapt and kotlinc
- if len(kapt.Inputs) != 2 || kapt.Inputs[0].String() != "a.java" || kapt.Inputs[1].String() != "b.kt" {
- t.Errorf(`foo kapt inputs %v != ["a.java", "b.kt"]`, kapt.Inputs)
- }
- if len(kotlinc.Inputs) != 2 || kotlinc.Inputs[0].String() != "a.java" || kotlinc.Inputs[1].String() != "b.kt" {
- t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, kotlinc.Inputs)
- }
+ bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String()
+ baz := ctx.ModuleForTests("baz", buildOS+"_common").Rule("javac").Output.String()
- // Test that only the java sources are passed to javac
- if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
- t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
- }
+ // Test that the kotlin and java sources are passed to kapt and kotlinc
+ if len(kapt.Inputs) != 2 || kapt.Inputs[0].String() != "a.java" || kapt.Inputs[1].String() != "b.kt" {
+ t.Errorf(`foo kapt inputs %v != ["a.java", "b.kt"]`, kapt.Inputs)
+ }
+ if len(kotlinc.Inputs) != 2 || kotlinc.Inputs[0].String() != "a.java" || kotlinc.Inputs[1].String() != "b.kt" {
+ t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, kotlinc.Inputs)
+ }
- // Test that the kapt srcjar is a dependency of kotlinc and javac rules
- if !inList(kapt.Output.String(), kotlinc.Implicits.Strings()) {
- t.Errorf("expected %q in kotlinc implicits %v", kapt.Output.String(), kotlinc.Implicits.Strings())
- }
- if !inList(kapt.Output.String(), javac.Implicits.Strings()) {
- t.Errorf("expected %q in javac implicits %v", kapt.Output.String(), javac.Implicits.Strings())
- }
+ // Test that only the java sources are passed to javac
+ if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
+ t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
+ }
- // Test that the kapt srcjar is extracted by the kotlinc and javac rules
- if kotlinc.Args["srcJars"] != kapt.Output.String() {
- t.Errorf("expected %q in kotlinc srcjars %v", kapt.Output.String(), kotlinc.Args["srcJars"])
- }
- if javac.Args["srcJars"] != kapt.Output.String() {
- t.Errorf("expected %q in javac srcjars %v", kapt.Output.String(), kotlinc.Args["srcJars"])
- }
+ // Test that the kapt srcjar is a dependency of kotlinc and javac rules
+ if !inList(kapt.Output.String(), kotlinc.Implicits.Strings()) {
+ t.Errorf("expected %q in kotlinc implicits %v", kapt.Output.String(), kotlinc.Implicits.Strings())
+ }
+ if !inList(kapt.Output.String(), javac.Implicits.Strings()) {
+ t.Errorf("expected %q in javac implicits %v", kapt.Output.String(), javac.Implicits.Strings())
+ }
- // Test that the processors are passed to kapt
- expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar +
- " -P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + baz
- if kapt.Args["kaptProcessorPath"] != expectedProcessorPath {
- t.Errorf("expected kaptProcessorPath %q, got %q", expectedProcessorPath, kapt.Args["kaptProcessorPath"])
- }
- expectedProcessor := "-P plugin:org.jetbrains.kotlin.kapt3:processors=com.bar -P plugin:org.jetbrains.kotlin.kapt3:processors=com.baz"
- if kapt.Args["kaptProcessor"] != expectedProcessor {
- t.Errorf("expected kaptProcessor %q, got %q", expectedProcessor, kapt.Args["kaptProcessor"])
- }
+ // Test that the kapt srcjar is extracted by the kotlinc and javac rules
+ if kotlinc.Args["srcJars"] != kapt.Output.String() {
+ t.Errorf("expected %q in kotlinc srcjars %v", kapt.Output.String(), kotlinc.Args["srcJars"])
+ }
+ if javac.Args["srcJars"] != kapt.Output.String() {
+ t.Errorf("expected %q in javac srcjars %v", kapt.Output.String(), kotlinc.Args["srcJars"])
+ }
- // Test that the processors are not passed to javac
- if javac.Args["processorPath"] != "" {
- t.Errorf("expected processorPath '', got %q", javac.Args["processorPath"])
- }
- if javac.Args["processor"] != "-proc:none" {
- t.Errorf("expected processor '-proc:none', got %q", javac.Args["processor"])
- }
+ // Test that the processors are passed to kapt
+ expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar +
+ " -P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + baz
+ if kapt.Args["kaptProcessorPath"] != expectedProcessorPath {
+ t.Errorf("expected kaptProcessorPath %q, got %q", expectedProcessorPath, kapt.Args["kaptProcessorPath"])
+ }
+ expectedProcessor := "-P plugin:org.jetbrains.kotlin.kapt3:processors=com.bar -P plugin:org.jetbrains.kotlin.kapt3:processors=com.baz"
+ if kapt.Args["kaptProcessor"] != expectedProcessor {
+ t.Errorf("expected kaptProcessor %q, got %q", expectedProcessor, kapt.Args["kaptProcessor"])
+ }
+
+ // Test that the processors are not passed to javac
+ if javac.Args["processorpath"] != "" {
+ t.Errorf("expected processorPath '', got %q", javac.Args["processorpath"])
+ }
+ if javac.Args["processor"] != "-proc:none" {
+ t.Errorf("expected processor '-proc:none', got %q", javac.Args["processor"])
+ }
+ })
+
+ t.Run("errorprone", func(t *testing.T) {
+ env := map[string]string{
+ "RUN_ERROR_PRONE": "true",
+ }
+ config := testConfig(env, bp, nil)
+ ctx, _ := testJavaWithConfig(t, config)
+
+ buildOS := android.BuildOs.String()
+
+ kapt := ctx.ModuleForTests("foo", "android_common").Rule("kapt")
+ //kotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
+ javac := ctx.ModuleForTests("foo", "android_common").Description("javac")
+ errorprone := ctx.ModuleForTests("foo", "android_common").Description("errorprone")
+
+ bar := ctx.ModuleForTests("bar", buildOS+"_common").Description("javac").Output.String()
+ baz := ctx.ModuleForTests("baz", buildOS+"_common").Description("javac").Output.String()
+ myCheck := ctx.ModuleForTests("my_check", buildOS+"_common").Description("javac").Output.String()
+
+ // Test that the errorprone plugins are not passed to kapt
+ expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar +
+ " -P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + baz
+ if kapt.Args["kaptProcessorPath"] != expectedProcessorPath {
+ t.Errorf("expected kaptProcessorPath %q, got %q", expectedProcessorPath, kapt.Args["kaptProcessorPath"])
+ }
+ expectedProcessor := "-P plugin:org.jetbrains.kotlin.kapt3:processors=com.bar -P plugin:org.jetbrains.kotlin.kapt3:processors=com.baz"
+ if kapt.Args["kaptProcessor"] != expectedProcessor {
+ t.Errorf("expected kaptProcessor %q, got %q", expectedProcessor, kapt.Args["kaptProcessor"])
+ }
+
+ // Test that the errorprone plugins are not passed to javac
+ if javac.Args["processorpath"] != "" {
+ t.Errorf("expected processorPath '', got %q", javac.Args["processorpath"])
+ }
+ if javac.Args["processor"] != "-proc:none" {
+ t.Errorf("expected processor '-proc:none', got %q", javac.Args["processor"])
+ }
+
+ // Test that the errorprone plugins are passed to errorprone
+ expectedProcessorPath = "-processorpath " + myCheck
+ if errorprone.Args["processorpath"] != expectedProcessorPath {
+ t.Errorf("expected processorpath %q, got %q", expectedProcessorPath, errorprone.Args["processorpath"])
+ }
+ if errorprone.Args["processor"] != "-proc:none" {
+ t.Errorf("expected processor '-proc:none', got %q", errorprone.Args["processor"])
+ }
+ })
}
func TestKaptEncodeFlags(t *testing.T) {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 13cd5f9..ebf867d 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -435,8 +435,8 @@
// If set to true, the path of dist files is apistubs/core. Defaults to false.
Core_lib *bool
- // don't create dist rules.
- No_dist *bool `blueprint:"mutated"`
+ // If set to true then don't create dist rules.
+ No_dist *bool
// indicates whether system and test apis should be generated.
Generate_system_and_test_apis bool `blueprint:"mutated"`
@@ -1482,10 +1482,6 @@
return module.sdkJars(ctx, sdkVersion, false /*headerJars*/)
}
-func (module *SdkLibrary) SetNoDist() {
- module.sdkLibraryProperties.No_dist = proptools.BoolPtr(true)
-}
-
var javaSdkLibrariesKey = android.NewOnceKey("javaSdkLibraries")
func javaSdkLibraries(config android.Config) *[]string {
@@ -1513,12 +1509,10 @@
}
// If this builds against standard libraries (i.e. is not part of the core libraries)
- // then assume it provides both system and test apis. Otherwise, assume it does not and
- // also assume it does not contribute to the dist build.
+ // then assume it provides both system and test apis.
sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
hasSystemAndTestApis := sdkDep.hasStandardLibs()
module.sdkLibraryProperties.Generate_system_and_test_apis = hasSystemAndTestApis
- module.sdkLibraryProperties.No_dist = proptools.BoolPtr(!hasSystemAndTestApis)
missing_current_api := false
@@ -2300,11 +2294,10 @@
scopeSet.AddProperty("jars", jars)
// Merge the stubs source jar into the snapshot zip so that when it is unpacked
- // the source files are also unpacked. Use a glob so that if the directory is missing
- // (because there are no stubs sources for this scope) it will not fail.
+ // the source files are also unpacked.
snapshotRelativeDir := filepath.Join(scopeDir, ctx.Name()+"_stub_sources")
ctx.SnapshotBuilder().UnzipToSnapshot(properties.StubsSrcJar, snapshotRelativeDir)
- scopeSet.AddProperty("stub_srcs", []string{snapshotRelativeDir + "/**/*.java"})
+ scopeSet.AddProperty("stub_srcs", []string{snapshotRelativeDir})
if properties.CurrentApiFile != nil {
currentApiSnapshotPath := filepath.Join(scopeDir, ctx.Name()+".txt")
diff --git a/python/androidmk.go b/python/androidmk.go
index 8ad5889..040b6be 100644
--- a/python/androidmk.go
+++ b/python/androidmk.go
@@ -80,6 +80,10 @@
fmt.Fprintln(w, "LOCAL_TEST_DATA :=",
strings.Join(android.AndroidMkDataPaths(p.data), " "))
}
+
+ if Bool(p.testProperties.Test_options.Unit_test) {
+ fmt.Fprintln(w, "LOCAL_IS_UNIT_TEST := true")
+ }
})
base.subAndroidMk(ret, p.binaryDecorator.pythonInstaller)
}
diff --git a/python/test.go b/python/test.go
index 434e71a..f9baa46 100644
--- a/python/test.go
+++ b/python/test.go
@@ -26,6 +26,12 @@
android.RegisterModuleType("python_test", PythonTestFactory)
}
+// Test option struct.
+type TestOptions struct {
+ // If the test is a hostside(no device required) unittest that shall be run during presubmit check.
+ Unit_test *bool
+}
+
type TestProperties struct {
// the name of the test configuration (for example "AndroidTest.xml") that should be
// installed with the module.
@@ -38,6 +44,9 @@
// list of files or filegroup modules that provide data that should be installed alongside
// the test
Data []string `android:"path,arch_variant"`
+
+ // Test options.
+ Test_options TestOptions
}
type testDecorator struct {
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 29e4bd7..f98360a 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -116,6 +116,9 @@
if !BoolDefault(test.Properties.Auto_gen_config, true) {
fmt.Fprintln(w, "LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG := true")
}
+ if Bool(test.Properties.Test_options.Unit_test) {
+ fmt.Fprintln(w, "LOCAL_IS_UNIT_TEST := true")
+ }
})
// TODO(chh): add test data with androidMkWriteTestData(test.data, ctx, ret)
}
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 7cc0fc8..35a807b 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -258,5 +258,6 @@
deps.SharedLibs = append(deps.SharedLibs, b.ClangProperties.Shared_libs...)
deps.StaticLibs = append(deps.StaticLibs, b.ClangProperties.Static_libs...)
+ deps.HeaderLibs = append(deps.StaticLibs, b.ClangProperties.Header_libs...)
return deps
}
diff --git a/rust/bindgen_test.go b/rust/bindgen_test.go
index c7ce42b..af04cfc 100644
--- a/rust/bindgen_test.go
+++ b/rust/bindgen_test.go
@@ -32,6 +32,7 @@
cflags: ["--clang-flag()"],
shared_libs: ["libfoo_shared"],
static_libs: ["libfoo_static"],
+ header_libs: ["libfoo_header"],
}
cc_library_shared {
name: "libfoo_shared",
@@ -41,6 +42,10 @@
name: "libfoo_static",
export_include_dirs: ["static_include"],
}
+ cc_library_headers {
+ name: "libfoo_header",
+ export_include_dirs: ["header_include"],
+ }
cc_defaults {
name: "cc_defaults_flags",
cflags: ["--default-flag"],
@@ -60,6 +65,9 @@
if !strings.Contains(libbindgen.Args["cflags"], "-Istatic_include") {
t.Errorf("missing static_libs exported includes in rust_bindgen rule: cflags %#v", libbindgen.Args["cflags"])
}
+ if !strings.Contains(libbindgen.Args["cflags"], "-Iheader_include") {
+ t.Errorf("missing static_libs exported includes in rust_bindgen rule: cflags %#v", libbindgen.Args["cflags"])
+ }
if !strings.Contains(libbindgen.Args["cflags"], "--default-flag") {
t.Errorf("rust_bindgen missing cflags defined in cc_defaults: cflags %#v", libbindgen.Args["cflags"])
}
diff --git a/rust/protobuf.go b/rust/protobuf.go
index 76fed30..7d6e1fd 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -53,7 +53,7 @@
Proto_flags []string `android:"arch_variant"`
// List of libraries which export include paths required for this module
- Header_libs []string `android:"arch_variant"`
+ Header_libs []string `android:"arch_variant,variant_prepend"`
}
type protobufDecorator struct {
diff --git a/rust/test.go b/rust/test.go
index bc7f53c..408e03a 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -19,6 +19,12 @@
"android/soong/tradefed"
)
+// Test option struct.
+type TestOptions struct {
+ // If the test is a hostside(no device required) unittest that shall be run during presubmit check.
+ Unit_test *bool
+}
+
type TestProperties struct {
// Disables the creation of a test-specific directory when used with
// relative_install_path. Useful if several tests need to be in the same
@@ -44,6 +50,9 @@
// if set, build with the standard Rust test harness. Defaults to true.
Test_harness *bool
+
+ // Test options.
+ Test_options TestOptions
}
// A test module is a binary module with extra --test compiler flag
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index ec8ebb3..b44f66e 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -976,21 +976,21 @@
shared_library: false,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system: {
jars: ["sdk_library/system/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
current_api: "sdk_library/system/myjavalib.txt",
removed_api: "sdk_library/system/myjavalib-removed.txt",
sdk_version: "system_current",
},
test: {
jars: ["sdk_library/test/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/test/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/test/myjavalib_stub_sources"],
current_api: "sdk_library/test/myjavalib.txt",
removed_api: "sdk_library/test/myjavalib-removed.txt",
sdk_version: "test_current",
@@ -1005,21 +1005,21 @@
shared_library: false,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system: {
jars: ["sdk_library/system/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
current_api: "sdk_library/system/myjavalib.txt",
removed_api: "sdk_library/system/myjavalib-removed.txt",
sdk_version: "system_current",
},
test: {
jars: ["sdk_library/test/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/test/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/test/myjavalib_stub_sources"],
current_api: "sdk_library/test/myjavalib.txt",
removed_api: "sdk_library/test/myjavalib-removed.txt",
sdk_version: "test_current",
@@ -1077,7 +1077,7 @@
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "none",
@@ -1092,7 +1092,7 @@
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "none",
@@ -1146,7 +1146,7 @@
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "module_current",
@@ -1161,7 +1161,7 @@
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "module_current",
@@ -1218,14 +1218,14 @@
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system: {
jars: ["sdk_library/system/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
current_api: "sdk_library/system/myjavalib.txt",
removed_api: "sdk_library/system/myjavalib-removed.txt",
sdk_version: "system_current",
@@ -1240,14 +1240,14 @@
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system: {
jars: ["sdk_library/system/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
current_api: "sdk_library/system/myjavalib.txt",
removed_api: "sdk_library/system/myjavalib-removed.txt",
sdk_version: "system_current",
@@ -1311,21 +1311,21 @@
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system: {
jars: ["sdk_library/system/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
current_api: "sdk_library/system/myjavalib.txt",
removed_api: "sdk_library/system/myjavalib-removed.txt",
sdk_version: "system_current",
},
module_lib: {
jars: ["sdk_library/module-lib/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/module-lib/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/module-lib/myjavalib_stub_sources"],
current_api: "sdk_library/module-lib/myjavalib.txt",
removed_api: "sdk_library/module-lib/myjavalib-removed.txt",
sdk_version: "module_current",
@@ -1340,21 +1340,21 @@
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system: {
jars: ["sdk_library/system/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/system/myjavalib_stub_sources"],
current_api: "sdk_library/system/myjavalib.txt",
removed_api: "sdk_library/system/myjavalib-removed.txt",
sdk_version: "system_current",
},
module_lib: {
jars: ["sdk_library/module-lib/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/module-lib/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/module-lib/myjavalib_stub_sources"],
current_api: "sdk_library/module-lib/myjavalib.txt",
removed_api: "sdk_library/module-lib/myjavalib-removed.txt",
sdk_version: "module_current",
@@ -1419,14 +1419,14 @@
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system_server: {
jars: ["sdk_library/system-server/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system-server/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/system-server/myjavalib_stub_sources"],
current_api: "sdk_library/system-server/myjavalib.txt",
removed_api: "sdk_library/system-server/myjavalib-removed.txt",
sdk_version: "system_server_current",
@@ -1441,14 +1441,14 @@
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
},
system_server: {
jars: ["sdk_library/system-server/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/system-server/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/system-server/myjavalib_stub_sources"],
current_api: "sdk_library/system-server/myjavalib.txt",
removed_api: "sdk_library/system-server/myjavalib-removed.txt",
sdk_version: "system_server_current",
@@ -1508,7 +1508,7 @@
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
@@ -1524,7 +1524,7 @@
shared_library: true,
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
@@ -1584,7 +1584,7 @@
doctag_files: ["doctags/docs/known_doctags"],
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
@@ -1600,7 +1600,7 @@
doctag_files: ["doctags/docs/known_doctags"],
public: {
jars: ["sdk_library/public/myjavalib-stubs.jar"],
- stub_srcs: ["sdk_library/public/myjavalib_stub_sources/**/*.java"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
current_api: "sdk_library/public/myjavalib.txt",
removed_api: "sdk_library/public/myjavalib-removed.txt",
sdk_version: "current",
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index b35f831..27d71e8 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -188,7 +188,7 @@
}
func AutoGenJavaTestConfig(ctx android.ModuleContext, testConfigProp *string, testConfigTemplateProp *string,
- testSuites []string, autoGenConfig *bool) android.Path {
+ testSuites []string, autoGenConfig *bool, unitTest *bool) android.Path {
path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
if autogenPath != nil {
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
@@ -198,7 +198,11 @@
if ctx.Device() {
autogenTemplate(ctx, autogenPath, "${JavaTestConfigTemplate}", nil, "")
} else {
- autogenTemplate(ctx, autogenPath, "${JavaHostTestConfigTemplate}", nil, "")
+ if Bool(unitTest) {
+ autogenTemplate(ctx, autogenPath, "${JavaHostUnitTestConfigTemplate}", nil, "")
+ } else {
+ autogenTemplate(ctx, autogenPath, "${JavaHostTestConfigTemplate}", nil, "")
+ }
}
}
return autogenPath
diff --git a/tradefed/config.go b/tradefed/config.go
index f7e8349..f3566a8 100644
--- a/tradefed/config.go
+++ b/tradefed/config.go
@@ -27,6 +27,7 @@
pctx.SourcePathVariable("InstrumentationTestConfigTemplate", "build/make/core/instrumentation_test_config_template.xml")
pctx.SourcePathVariable("JavaTestConfigTemplate", "build/make/core/java_test_config_template.xml")
pctx.SourcePathVariable("JavaHostTestConfigTemplate", "build/make/core/java_host_test_config_template.xml")
+ pctx.SourcePathVariable("JavaHostUnitTestConfigTemplate", "build/make/core/java_host_unit_test_config_template.xml")
pctx.SourcePathVariable("NativeBenchmarkTestConfigTemplate", "build/make/core/native_benchmark_test_config_template.xml")
pctx.SourcePathVariable("NativeHostTestConfigTemplate", "build/make/core/native_host_test_config_template.xml")
pctx.SourcePathVariable("NativeTestConfigTemplate", "build/make/core/native_test_config_template.xml")
diff --git a/ui/build/bazel.go b/ui/build/bazel.go
index 7cc7caf..2d36f67 100644
--- a/ui/build/bazel.go
+++ b/ui/build/bazel.go
@@ -24,8 +24,8 @@
"android/soong/ui/metrics"
)
-// Main entry point to construct the Bazel build command line, environment variables
-// and post-processing steps (e.g. converge output directories)
+// Main entry point to construct the Bazel build command line, environment
+// variables and post-processing steps (e.g. converge output directories)
func runBazel(ctx Context, config Config) {
ctx.BeginTrace(metrics.RunBazel, "bazel")
defer ctx.EndTrace()
@@ -41,53 +41,86 @@
outputGroups = strings.Join(config.ninjaArgs, ",")
}
+ // Environment variables are the primary mechanism to pass information from
+ // soong_ui configuration or context to Bazel.
+ //
+ // Use *_NINJA variables to pass the root-relative path of the combined,
+ // kati-generated, soong-generated, and packaging Ninja files to Bazel.
+ // Bazel reads these from the lunch() repository rule.
config.environ.Set("COMBINED_NINJA", config.CombinedNinjaFile())
config.environ.Set("KATI_NINJA", config.KatiBuildNinjaFile())
config.environ.Set("PACKAGE_NINJA", config.KatiPackageNinjaFile())
config.environ.Set("SOONG_NINJA", config.SoongNinjaFile())
+ // `tools/bazel` is the default entry point for executing Bazel in the AOSP
+ // source tree.
bazelExecutable := filepath.Join("tools", "bazel")
cmd := Command(ctx, config, "bazel", bazelExecutable)
- if extra_startup_args, ok := cmd.Environment.Get("BAZEL_STARTUP_ARGS"); ok {
- cmd.Args = append(cmd.Args, strings.Fields(extra_startup_args)...)
+ // Append custom startup flags to the Bazel command. Startup flags affect
+ // the Bazel server itself, and any changes to these flags would incur a
+ // restart of the server, losing much of the in-memory incrementality.
+ if extraStartupArgs, ok := cmd.Environment.Get("BAZEL_STARTUP_ARGS"); ok {
+ cmd.Args = append(cmd.Args, strings.Fields(extraStartupArgs)...)
}
+ // Start constructing the `build` command.
actionName := "build"
cmd.Args = append(cmd.Args,
actionName,
+ // Use output_groups to select the set of outputs to produce from a
+ // ninja_build target.
"--output_groups="+outputGroups,
+ // Generate a performance profile
"--profile="+filepath.Join(shared.BazelMetricsFilename(config.OutDir(), actionName)),
"--slim_profile=true",
)
- if extra_build_args, ok := cmd.Environment.Get("BAZEL_BUILD_ARGS"); ok {
- cmd.Args = append(cmd.Args, strings.Fields(extra_build_args)...)
+ // Append custom build flags to the Bazel command. Changes to these flags
+ // may invalidate Bazel's analysis cache.
+ if extraBuildArgs, ok := cmd.Environment.Get("BAZEL_BUILD_ARGS"); ok {
+ cmd.Args = append(cmd.Args, strings.Fields(extraBuildArgs)...)
}
+ // Append the label of the default ninja_build target.
cmd.Args = append(cmd.Args,
"//:"+config.TargetProduct()+"-"+config.TargetBuildVariant(),
)
+ // Ensure that the PATH environment variable value used in the action
+ // environment is the restricted set computed from soong_ui, and not a
+ // user-provided one, for hermeticity reasons.
if pathEnvValue, ok := config.environ.Get("PATH"); ok {
cmd.Environment.Set("PATH", pathEnvValue)
cmd.Args = append(cmd.Args, "--action_env=PATH="+pathEnvValue)
}
+
cmd.Environment.Set("DIST_DIR", config.DistDir())
cmd.Environment.Set("SHELL", "/bin/bash")
+ // Print the full command line for debugging purposes.
ctx.Println(cmd.Cmd)
+
+ // Execute the command at the root of the directory.
cmd.Dir = filepath.Join(config.OutDir(), "..")
ctx.Status.Status("Starting Bazel..")
+
+ // Execute the build command.
cmd.RunAndStreamOrFatal()
+ // Post-processing steps start here. Once the Bazel build completes, the
+ // output files are still stored in the execution root, not in $OUT_DIR.
+ // Ensure that the $OUT_DIR contains the expected set of files by symlinking
+ // the files from the execution root's output direction into $OUT_DIR.
+
// Obtain the Bazel output directory for ninja_build.
infoCmd := Command(ctx, config, "bazel", bazelExecutable)
- if extra_startup_args, ok := infoCmd.Environment.Get("BAZEL_STARTUP_ARGS"); ok {
- infoCmd.Args = append(infoCmd.Args, strings.Fields(extra_startup_args)...)
+ if extraStartupArgs, ok := infoCmd.Environment.Get("BAZEL_STARTUP_ARGS"); ok {
+ infoCmd.Args = append(infoCmd.Args, strings.Fields(extraStartupArgs)...)
}
+ // Obtain the output directory path in the execution root.
infoCmd.Args = append(infoCmd.Args,
"info",
"output_path",
diff --git a/ui/build/config.go b/ui/build/config.go
index 641aae6..229bd5c 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -703,6 +703,10 @@
return c.ninjaArgs
}
+func (c *configImpl) BazelOutDir() string {
+ return filepath.Join(c.OutDir(), "bazel")
+}
+
func (c *configImpl) SoongOutDir() string {
return filepath.Join(c.OutDir(), "soong")
}
diff --git a/ui/build/finder.go b/ui/build/finder.go
index 7a85657..2eb84ca 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -27,8 +27,10 @@
"android/soong/ui/metrics"
)
-// This file provides an interface to the Finder for use in Soong UI
-// This file stores configuration information about which files to find
+// This file provides an interface to the Finder type for soong_ui. Finder is
+// used to recursively traverse the source tree to gather paths of files, such
+// as Android.bp or Android.mk, and store the lists/database of paths in files
+// under `$OUT_DIR/.module_paths`. This directory can also be dist'd.
// NewSourceFinder returns a new Finder configured to search for source files.
// Callers of NewSourceFinder should call <f.Shutdown()> when done
@@ -36,14 +38,18 @@
ctx.BeginTrace(metrics.RunSetupTool, "find modules")
defer ctx.EndTrace()
+ // Set up the working directory for the Finder.
dir, err := os.Getwd()
if err != nil {
ctx.Fatalf("No working directory for module-finder: %v", err.Error())
}
filesystem := fs.OsFs
- // if the root dir is ignored, then the subsequent error messages are very confusing,
- // so check for that upfront
+ // .out-dir and .find-ignore are markers for Finder to ignore siblings and
+ // subdirectories of the directory Finder finds them in, hence stopping the
+ // search recursively down those branches. It's possible that these files
+ // are in the root directory, and if they are, then the subsequent error
+ // messages are very confusing, so check for that here.
pruneFiles := []string{".out-dir", ".find-ignore"}
for _, name := range pruneFiles {
prunePath := filepath.Join(dir, name)
@@ -53,22 +59,34 @@
}
}
+ // Set up configuration parameters for the Finder cache.
cacheParams := finder.CacheParams{
WorkingDirectory: dir,
RootDirs: []string{"."},
ExcludeDirs: []string{".git", ".repo"},
PruneFiles: pruneFiles,
IncludeFiles: []string{
+ // Kati build definitions.
"Android.mk",
+ // Product configuration files.
"AndroidProducts.mk",
+ // General Soong build definitions, using the Blueprint syntax.
"Android.bp",
+ // build/blueprint build definitions, using the Blueprint syntax.
"Blueprints",
+ // Bazel build definitions.
"BUILD.bazel",
+ // Kati clean definitions.
"CleanSpec.mk",
+ // Ownership definition.
"OWNERS",
+ // Test configuration for modules in directories that contain this
+ // file.
"TEST_MAPPING",
+ // Bazel top-level file to mark a directory as a Bazel workspace.
"WORKSPACE",
},
+ // Bazel Starlark configuration files.
IncludeSuffixes: []string{".bzl"},
}
dumpDir := config.FileListDir()
@@ -80,6 +98,7 @@
return f
}
+// Finds the list of Bazel-related files (BUILD, WORKSPACE and Starlark) in the tree.
func findBazelFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) {
matches := []string{}
for _, foundName := range entries.FileNames {
@@ -98,12 +117,21 @@
dumpDir := config.FileListDir()
os.MkdirAll(dumpDir, 0777)
+ // Stop searching a subdirectory recursively after finding an Android.mk.
androidMks := f.FindFirstNamedAt(".", "Android.mk")
err := dumpListToFile(ctx, config, androidMks, filepath.Join(dumpDir, "Android.mk.list"))
if err != nil {
ctx.Fatalf("Could not export module list: %v", err)
}
+ // Stop searching a subdirectory recursively after finding a CleanSpec.mk.
+ cleanSpecs := f.FindFirstNamedAt(".", "CleanSpec.mk")
+ err = dumpListToFile(ctx, config, cleanSpecs, filepath.Join(dumpDir, "CleanSpec.mk.list"))
+ if err != nil {
+ ctx.Fatalf("Could not export module list: %v", err)
+ }
+
+ // Only consider AndroidProducts.mk in device/, vendor/ and product/, recursively in these directories.
androidProductsMks := f.FindNamedAt("device", "AndroidProducts.mk")
androidProductsMks = append(androidProductsMks, f.FindNamedAt("vendor", "AndroidProducts.mk")...)
androidProductsMks = append(androidProductsMks, f.FindNamedAt("product", "AndroidProducts.mk")...)
@@ -112,31 +140,30 @@
ctx.Fatalf("Could not export product list: %v", err)
}
+ // Recursively look for all Bazel related files.
bazelFiles := f.FindMatching(".", findBazelFiles)
err = dumpListToFile(ctx, config, bazelFiles, filepath.Join(dumpDir, "bazel.list"))
if err != nil {
ctx.Fatalf("Could not export bazel BUILD list: %v", err)
}
- cleanSpecs := f.FindFirstNamedAt(".", "CleanSpec.mk")
- err = dumpListToFile(ctx, config, cleanSpecs, filepath.Join(dumpDir, "CleanSpec.mk.list"))
- if err != nil {
- ctx.Fatalf("Could not export module list: %v", err)
- }
-
+ // Recursively look for all OWNERS files.
owners := f.FindNamedAt(".", "OWNERS")
err = dumpListToFile(ctx, config, owners, filepath.Join(dumpDir, "OWNERS.list"))
if err != nil {
ctx.Fatalf("Could not find OWNERS: %v", err)
}
+ // Recursively look for all TEST_MAPPING files.
testMappings := f.FindNamedAt(".", "TEST_MAPPING")
err = dumpListToFile(ctx, config, testMappings, filepath.Join(dumpDir, "TEST_MAPPING.list"))
if err != nil {
ctx.Fatalf("Could not find TEST_MAPPING: %v", err)
}
+ // Recursively look for all Android.bp files
androidBps := f.FindNamedAt(".", "Android.bp")
+ // The files are named "Blueprints" only in the build/blueprint directory.
androidBps = append(androidBps, f.FindNamedAt("build/blueprint", "Blueprints")...)
if len(androidBps) == 0 {
ctx.Fatalf("No Android.bp found")
@@ -148,10 +175,12 @@
if config.Dist() {
f.WaitForDbDump()
+ // Dist the files.db plain text database.
distFile(ctx, config, f.DbPath, "module_paths")
}
}
+// Write the .list files to disk.
func dumpListToFile(ctx Context, config Config, list []string, filePath string) (err error) {
desiredText := strings.Join(list, "\n")
desiredBytes := []byte(desiredText)
diff --git a/ui/build/kati.go b/ui/build/kati.go
index f6c0f52..06ec646 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -33,12 +33,18 @@
const katiCleanspecSuffix = "-cleanspec"
const katiPackageSuffix = "-package"
-// genKatiSuffix creates a suffix for kati-generated files so that we can cache
-// them based on their inputs. So this should encode all common changes to Kati
-// inputs. Currently that includes the TARGET_PRODUCT, kati-processed command
-// line arguments, and the directories specified by mm/mmm.
+// genKatiSuffix creates a filename suffix for kati-generated files so that we
+// can cache them based on their inputs. Such files include the generated Ninja
+// files and env.sh environment variable setup files.
+//
+// The filename suffix should encode all common changes to Kati inputs.
+// Currently that includes the TARGET_PRODUCT and kati-processed command line
+// arguments.
func genKatiSuffix(ctx Context, config Config) {
+ // Construct the base suffix.
katiSuffix := "-" + config.TargetProduct()
+
+ // Append kati arguments to the suffix.
if args := config.KatiArgs(); len(args) > 0 {
katiSuffix += "-" + spaceSlashReplacer.Replace(strings.Join(args, "_"))
}
@@ -60,51 +66,101 @@
}
}
+// Base function to construct and run the Kati command line with additional
+// arguments, and a custom function closure to mutate the environment Kati runs
+// in.
func runKati(ctx Context, config Config, extraSuffix string, args []string, envFunc func(*Environment)) {
executable := config.PrebuiltBuildTool("ckati")
+ // cKati arguments.
args = append([]string{
+ // Instead of executing commands directly, generate a Ninja file.
"--ninja",
+ // Generate Ninja files in the output directory.
"--ninja_dir=" + config.OutDir(),
+ // Filename suffix of the generated Ninja file.
"--ninja_suffix=" + config.KatiSuffix() + extraSuffix,
+ // Remove common parts at the beginning of a Ninja file, like build_dir,
+ // local_pool and _kati_always_build_. Allows Kati to be run multiple
+ // times, with generated Ninja files combined in a single invocation
+ // using 'include'.
"--no_ninja_prelude",
+ // Support declaring phony outputs in AOSP Ninja.
"--use_ninja_phony_output",
+ // Support declaring symlink outputs in AOSP Ninja.
"--use_ninja_symlink_outputs",
+ // Regenerate the Ninja file if environment inputs have changed. e.g.
+ // CLI flags, .mk file timestamps, env vars, $(wildcard ..) and some
+ // $(shell ..) results.
"--regen",
+ // Skip '-include' directives starting with the specified path. Used to
+ // ignore generated .mk files.
"--ignore_optional_include=" + filepath.Join(config.OutDir(), "%.P"),
+ // Detect the use of $(shell echo ...).
"--detect_android_echo",
+ // Colorful ANSI-based warning and error messages.
"--color_warnings",
+ // Generate all targets, not just the top level requested ones.
"--gen_all_targets",
+ // Use the built-in emulator of GNU find for better file finding
+ // performance. Used with $(shell find ...).
"--use_find_emulator",
+ // Fail when the find emulator encounters problems.
"--werror_find_emulator",
+ // Do not provide any built-in rules.
"--no_builtin_rules",
+ // Fail when suffix rules are used.
"--werror_suffix_rules",
- "--warn_real_to_phony",
- "--warn_phony_looks_real",
+ // Fail when a real target depends on a phony target.
"--werror_real_to_phony",
- "--werror_phony_looks_real",
- "--werror_writable",
+ // Makes real_to_phony checks assume that any top-level or leaf
+ // dependencies that does *not* have a '/' in it is a phony target.
"--top_level_phony",
+ // Fail when a phony target contains slashes.
+ "--werror_phony_looks_real",
+ // Fail when writing to a read-only directory.
+ "--werror_writable",
+ // Print Kati's internal statistics, such as the number of variables,
+ // implicit/explicit/suffix rules, and so on.
"--kati_stats",
}, args...)
+ // Generate a minimal Ninja file.
+ //
+ // Used for build_test and multiproduct_kati, which runs Kati several
+ // hundred times for different configurations to test file generation logic.
+ // These can result in generating Ninja files reaching ~1GB or more,
+ // resulting in ~hundreds of GBs of writes.
+ //
+ // Since we don't care about executing the Ninja files in these test cases,
+ // generating the Ninja file content wastes time, so skip writing any
+ // information out with --empty_ninja_file.
+ //
+ // From https://github.com/google/kati/commit/87b8da7af2c8bea28b1d8ab17679453d859f96e5
if config.Environment().IsEnvTrue("EMPTY_NINJA_FILE") {
args = append(args, "--empty_ninja_file")
}
+ // Apply 'local_pool' to to all rules that don't specify a pool.
if config.UseRemoteBuild() {
args = append(args, "--default_pool=local_pool")
}
cmd := Command(ctx, config, "ckati", executable, args...)
+
+ // Set up the nsjail sandbox.
cmd.Sandbox = katiSandbox
+
+ // Set up stdout and stderr.
pipe, err := cmd.StdoutPipe()
if err != nil {
ctx.Fatalln("Error getting output pipe for ckati:", err)
}
cmd.Stderr = cmd.Stdout
+ // Apply the caller's function closure to mutate the environment variables.
envFunc(cmd.Environment)
+ // Pass on various build environment metadata to Kati.
if _, ok := cmd.Environment.Get("BUILD_USERNAME"); !ok {
username := "unknown"
if u, err := user.Current(); err == nil {
@@ -125,6 +181,8 @@
}
cmd.StartOrFatal()
+ // Set up the ToolStatus command line reader for Kati for a consistent UI
+ // for the user.
status.KatiReader(ctx.Status.StartTool(), pipe)
cmd.WaitOrFatal()
}
@@ -134,35 +192,57 @@
defer ctx.EndTrace()
args := []string{
+ // Mark the output directory as writable.
"--writable", config.OutDir() + "/",
+ // Fail when encountering implicit rules. e.g.
+ // %.foo: %.bar
+ // cp $< $@
"--werror_implicit_rules",
+ // Entry point for the Kati Ninja file generation.
"-f", "build/make/core/main.mk",
}
if !config.BuildBrokenDupRules() {
+ // Fail when redefining / duplicating a target.
args = append(args, "--werror_overriding_commands")
}
args = append(args, config.KatiArgs()...)
args = append(args,
+ // Location of the Make vars .mk file generated by Soong.
"SOONG_MAKEVARS_MK="+config.SoongMakeVarsMk(),
+ // Location of the Android.mk file generated by Soong. This
+ // file contains Soong modules represented as Kati modules,
+ // allowing Kati modules to depend on Soong modules.
"SOONG_ANDROID_MK="+config.SoongAndroidMk(),
+ // Directory containing outputs for the target device.
"TARGET_DEVICE_DIR="+config.TargetDeviceDir(),
+ // Directory containing .mk files for packaging purposes, such as
+ // the dist.mk file, containing dist-for-goals data.
"KATI_PACKAGE_MK_DIR="+config.KatiPackageMkDir())
runKati(ctx, config, katiBuildSuffix, args, func(env *Environment) {})
+ // compress and dist the main build ninja file.
distGzipFile(ctx, config, config.KatiBuildNinjaFile())
+ // Cleanup steps.
cleanCopyHeaders(ctx, config)
cleanOldInstalledFiles(ctx, config)
}
+// Clean out obsolete header files on the disk that were *not copied* during the
+// build with BUILD_COPY_HEADERS and LOCAL_COPY_HEADERS.
+//
+// These should be increasingly uncommon, as it's a deprecated feature and there
+// isn't an equivalent feature in Soong.
func cleanCopyHeaders(ctx Context, config Config) {
ctx.BeginTrace("clean", "clean copy headers")
defer ctx.EndTrace()
+ // Read and parse the list of copied headers from a file in the product
+ // output directory.
data, err := ioutil.ReadFile(filepath.Join(config.ProductOut(), ".copied_headers_list"))
if err != nil {
if os.IsNotExist(err) {
@@ -178,6 +258,8 @@
headerDir := headers[0]
headers = headers[1:]
+ // Walk the tree and remove any headers that are not in the list of copied
+ // headers in the current build.
filepath.Walk(headerDir,
func(path string, info os.FileInfo, err error) error {
if err != nil {
@@ -196,6 +278,8 @@
})
}
+// Clean out any previously installed files from the disk that are not installed
+// in the current build.
func cleanOldInstalledFiles(ctx Context, config Config) {
ctx.BeginTrace("clean", "clean old installed files")
defer ctx.EndTrace()
@@ -213,18 +297,27 @@
cleanOldFiles(ctx, config.HostOut(), ".installable_test_files")
}
+// Generate the Ninja file containing the packaging command lines for the dist
+// dir.
func runKatiPackage(ctx Context, config Config) {
ctx.BeginTrace(metrics.RunKati, "kati package")
defer ctx.EndTrace()
args := []string{
+ // Mark the dist dir as writable.
"--writable", config.DistDir() + "/",
+ // Fail when encountering implicit rules. e.g.
"--werror_implicit_rules",
+ // Fail when redefining / duplicating a target.
"--werror_overriding_commands",
+ // Entry point.
"-f", "build/make/packaging/main.mk",
+ // Directory containing .mk files for packaging purposes, such as
+ // the dist.mk file, containing dist-for-goals data.
"KATI_PACKAGE_MK_DIR=" + config.KatiPackageMkDir(),
}
+ // Run Kati against a restricted set of environment variables.
runKati(ctx, config, katiPackageSuffix, args, func(env *Environment) {
env.Allow([]string{
// Some generic basics
@@ -251,16 +344,21 @@
}
})
+ // Compress and dist the packaging Ninja file.
distGzipFile(ctx, config, config.KatiPackageNinjaFile())
}
+// Run Kati on the cleanspec files to clean the build.
func runKatiCleanSpec(ctx Context, config Config) {
ctx.BeginTrace(metrics.RunKati, "kati cleanspec")
defer ctx.EndTrace()
runKati(ctx, config, katiCleanspecSuffix, []string{
+ // Fail when encountering implicit rules. e.g.
"--werror_implicit_rules",
+ // Fail when redefining / duplicating a target.
"--werror_overriding_commands",
+ // Entry point.
"-f", "build/make/core/cleanbuild.mk",
"SOONG_MAKEVARS_MK=" + config.SoongMakeVarsMk(),
"TARGET_DEVICE_DIR=" + config.TargetDeviceDir(),
diff --git a/ui/build/path.go b/ui/build/path.go
index 6f5cf78..86e61c0 100644
--- a/ui/build/path.go
+++ b/ui/build/path.go
@@ -29,6 +29,9 @@
"android/soong/ui/metrics"
)
+// parsePathDir returns the list of filenames of readable files in a directory.
+// This does not recurse into subdirectories, and does not contain subdirectory
+// names in the list.
func parsePathDir(dir string) []string {
f, err := os.Open(dir)
if err != nil {
@@ -54,10 +57,12 @@
return ret
}
-// A "lite" version of SetupPath used for dumpvars, or other places that need
-// minimal overhead (but at the expense of logging). If tmpDir is empty, the
-// default TMPDIR is used from config.
+// SetupLitePath is the "lite" version of SetupPath used for dumpvars, or other
+// places that does not need the full logging capabilities of path_interposer,
+// wants the minimal performance overhead, and still get the benefits of $PATH
+// hermeticity.
func SetupLitePath(ctx Context, config Config, tmpDir string) {
+ // Don't replace the path twice.
if config.pathReplaced {
return
}
@@ -67,6 +72,7 @@
origPath, _ := config.Environment().Get("PATH")
+ // If tmpDir is empty, the default TMPDIR is used from config.
if tmpDir == "" {
tmpDir, _ = config.Environment().Get("TMPDIR")
}
@@ -74,8 +80,10 @@
ensureEmptyDirectoriesExist(ctx, myPath)
os.Setenv("PATH", origPath)
+ // Iterate over the ACL configuration of host tools for this build.
for name, pathConfig := range paths.Configuration {
if !pathConfig.Symlink {
+ // Excludes 'Forbidden' and 'LinuxOnlyPrebuilt' PathConfigs.
continue
}
@@ -88,6 +96,7 @@
continue
}
+ // Symlink allowed host tools into a directory for hermeticity.
err = os.Symlink(origExec, filepath.Join(myPath, name))
if err != nil {
ctx.Fatalln("Failed to create symlink:", err)
@@ -96,14 +105,26 @@
myPath, _ = filepath.Abs(myPath)
+ // Set up the checked-in prebuilts path directory for the current host OS.
prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + runtime.GOOS + "-x86")
myPath = prebuiltsPath + string(os.PathListSeparator) + myPath
+ // Set $PATH to be the directories containing the host tool symlinks, and
+ // the prebuilts directory for the current host OS.
config.Environment().Set("PATH", myPath)
config.pathReplaced = true
}
+// SetupPath uses the path_interposer to intercept calls to $PATH binaries, and
+// communicates with the interposer to validate allowed $PATH binaries at
+// runtime, using logs as a medium.
+//
+// This results in hermetic directories in $PATH containing only allowed host
+// tools for the build, and replaces $PATH to contain *only* these directories,
+// and enables an incremental restriction of tools allowed in the $PATH without
+// breaking existing use cases.
func SetupPath(ctx Context, config Config) {
+ // Don't replace $PATH twice.
if config.pathReplaced {
return
}
@@ -112,9 +133,11 @@
defer ctx.EndTrace()
origPath, _ := config.Environment().Get("PATH")
+ // The directory containing symlinks from binaries in $PATH to the interposer.
myPath := filepath.Join(config.OutDir(), ".path")
interposer := myPath + "_interposer"
+ // Bootstrap the path_interposer Go binary with microfactory.
var cfg microfactory.Config
cfg.Map("android/soong", "build/soong")
cfg.TrimPath, _ = filepath.Abs(".")
@@ -122,15 +145,20 @@
ctx.Fatalln("Failed to build path interposer:", err)
}
+ // Save the original $PATH in a file.
if err := ioutil.WriteFile(interposer+"_origpath", []byte(origPath), 0777); err != nil {
ctx.Fatalln("Failed to write original path:", err)
}
+ // Communication with the path interposer works over log entries. Set up the
+ // listener channel for the log entries here.
entries, err := paths.LogListener(ctx.Context, interposer+"_log")
if err != nil {
ctx.Fatalln("Failed to listen for path logs:", err)
}
+ // Loop over all log entry listener channels to validate usage of only
+ // allowed PATH tools at runtime.
go func() {
for log := range entries {
curPid := os.Getpid()
@@ -140,6 +168,8 @@
break
}
}
+ // Compute the error message along with the process tree, including
+ // parents, for this log line.
procPrints := []string{
"See https://android.googlesource.com/platform/build/+/master/Changes.md#PATH_Tools for more information.",
}
@@ -150,6 +180,7 @@
}
}
+ // Validate usage against disallowed or missing PATH tools.
config := paths.GetConfig(log.Basename)
if config.Error {
ctx.Printf("Disallowed PATH tool %q used: %#v", log.Basename, log.Args)
@@ -165,8 +196,10 @@
}
}()
+ // Create the .path directory.
ensureEmptyDirectoriesExist(ctx, myPath)
+ // Compute the full list of binaries available in the original $PATH.
var execs []string
for _, pathEntry := range filepath.SplitList(origPath) {
if pathEntry == "" {
@@ -185,8 +218,14 @@
ctx.Fatalln("TEMPORARY_DISABLE_PATH_RESTRICTIONS was a temporary migration method, and is now obsolete.")
}
+ // Create symlinks from the path_interposer binary to all binaries for each
+ // directory in the original $PATH. This ensures that during the build,
+ // every call to a binary that's expected to be in the $PATH will be
+ // intercepted by the path_interposer binary, and validated with the
+ // LogEntry listener above at build time.
for _, name := range execs {
if !paths.GetConfig(name).Symlink {
+ // Ignore host tools that shouldn't be symlinked.
continue
}
@@ -200,11 +239,13 @@
myPath, _ = filepath.Abs(myPath)
- // We put some prebuilts in $PATH, since it's infeasible to add dependencies for all of
- // them.
+ // We put some prebuilts in $PATH, since it's infeasible to add dependencies
+ // for all of them.
prebuiltsPath, _ := filepath.Abs("prebuilts/build-tools/path/" + runtime.GOOS + "-x86")
myPath = prebuiltsPath + string(os.PathListSeparator) + myPath
+ // Replace the $PATH variable with the path_interposer symlinks, and
+ // checked-in prebuilts.
config.Environment().Set("PATH", myPath)
config.pathReplaced = true
}
diff --git a/ui/build/soong.go b/ui/build/soong.go
index b20237c..bb5cbf0 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -133,6 +133,13 @@
"-j", strconv.Itoa(config.Parallel()),
"--frontend_file", fifo,
"-f", filepath.Join(config.SoongOutDir(), file))
+
+ // For Bazel mixed builds.
+ cmd.Environment.Set("BAZEL_PATH", "./tools/bazel")
+ cmd.Environment.Set("BAZEL_HOME", filepath.Join(config.BazelOutDir(), "bazelhome"))
+ cmd.Environment.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output"))
+ cmd.Environment.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
+
cmd.Environment.Set("SOONG_SANDBOX_SOONG_BUILD", "true")
cmd.Sandbox = soongSandbox
cmd.RunAndStreamOrFatal()
diff --git a/zip/cmd/main.go b/zip/cmd/main.go
index d603586..fc976f6 100644
--- a/zip/cmd/main.go
+++ b/zip/cmd/main.go
@@ -12,6 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// soong_zip is a utility used during the build to create a zip archive by pulling the entries from
+// various sources:
+// * explicitly specified files
+// * files whose paths are read from a file
+// * directories traversed recursively
+// It can optionally change the recorded path of an entry.
+
package main
import (
diff --git a/zip/zip.go b/zip/zip.go
index e27432c..cb85f5c 100644
--- a/zip/zip.go
+++ b/zip/zip.go
@@ -126,6 +126,7 @@
return b
}
+// List reads the file names from the given file and adds them to the source files list.
func (b *FileArgsBuilder) List(name string) *FileArgsBuilder {
if b.err != nil {
return b
@@ -150,6 +151,7 @@
return b
}
+// RspFile reads the file names from given .rsp file and adds them to the source files list.
func (b *FileArgsBuilder) RspFile(name string) *FileArgsBuilder {
if b.err != nil {
return b
@@ -291,7 +293,7 @@
return args
}
-func ZipTo(args ZipArgs, w io.Writer) error {
+func zipTo(args ZipArgs, w io.Writer) error {
if args.EmulateJar {
args.AddDirectoryEntriesToZip = true
}
@@ -392,6 +394,7 @@
return z.write(w, pathMappings, args.ManifestSourcePath, args.EmulateJar, args.SrcJar, args.NumParallelJobs)
}
+// Zip creates an output zip archive from given sources.
func Zip(args ZipArgs) error {
if args.OutputFilePath == "" {
return fmt.Errorf("output file path must be nonempty")
@@ -416,7 +419,7 @@
out = f
}
- err := ZipTo(args, out)
+ err := zipTo(args, out)
if err != nil {
return err
}
@@ -450,7 +453,6 @@
RelativeRoot: fa.SourcePrefixToStrip,
}
}
-
}
dest = filepath.Join(fa.PathPrefixInZip, dest)
@@ -465,10 +467,9 @@
}
func jarSort(mappings []pathMapping) {
- less := func(i int, j int) (smaller bool) {
+ sort.SliceStable(mappings, func(i int, j int) bool {
return jar.EntryNamesLess(mappings[i].dest, mappings[j].dest)
- }
- sort.SliceStable(mappings, less)
+ })
}
func (z *ZipWriter) write(f io.Writer, pathMappings []pathMapping, manifest string, emulateJar, srcJar bool,
@@ -709,7 +710,7 @@
}
}
-func (z *ZipWriter) addManifest(dest string, src string, method uint16) error {
+func (z *ZipWriter) addManifest(dest string, src string, _ uint16) error {
if prev, exists := z.createdDirs[dest]; exists {
return fmt.Errorf("destination %q is both a directory %q and a file %q", dest, prev, src)
}
@@ -963,7 +964,7 @@
dir = filepath.Clean(dir)
// discover any uncreated directories in the path
- zipDirs := []string{}
+ var zipDirs []string
for dir != "" && dir != "." {
if _, exists := z.createdDirs[dir]; exists {
break
diff --git a/zip/zip_test.go b/zip/zip_test.go
index 302a749..a16e092 100644
--- a/zip/zip_test.go
+++ b/zip/zip_test.go
@@ -442,7 +442,7 @@
args.Stderr = &bytes.Buffer{}
buf := &bytes.Buffer{}
- err := ZipTo(args, buf)
+ err := zipTo(args, buf)
if (err != nil) != (test.err != nil) {
t.Fatalf("want error %v, got %v", test.err, err)
@@ -627,7 +627,7 @@
args.Stderr = &bytes.Buffer{}
buf := &bytes.Buffer{}
- err := ZipTo(args, buf)
+ err := zipTo(args, buf)
if err != nil {
t.Fatalf("got error %v", err)
}