Merge tag 'android-11.0.0_r48' into int/11/fp3
Android 11.0.0 Release 48 (RD2A.211001.002)
* tag 'android-11.0.0_r48':
Change-Id: Ifd87537fe1386f6acc0f68aaddfe240265ea155c
diff --git a/android/arch.go b/android/arch.go
index 18ff13e..ad91c7e 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -127,6 +127,7 @@
"cortex-a76",
"krait",
"kryo",
+ "kryo300",
"kryo385",
"exynos-m1",
"exynos-m2",
@@ -141,6 +142,7 @@
"cortex-a75",
"cortex-a76",
"kryo",
+ "kryo300",
"kryo385",
"exynos-m1",
"exynos-m2",
@@ -1625,6 +1627,7 @@
{"arm", "armv7-a-neon", "cortex-a76", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "krait", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "kryo", []string{"armeabi-v7a"}},
+ {"arm", "armv7-a-neon", "kryo300", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "kryo385", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "exynos-m1", []string{"armeabi-v7a"}},
{"arm", "armv7-a-neon", "exynos-m2", []string{"armeabi-v7a"}},
@@ -1636,6 +1639,7 @@
{"arm64", "armv8-a", "exynos-m2", []string{"arm64-v8a"}},
{"arm64", "armv8-2a", "cortex-a75", []string{"arm64-v8a"}},
{"arm64", "armv8-2a", "cortex-a76", []string{"arm64-v8a"}},
+ {"arm64", "armv8-2a", "kryo300", []string{"arm64-v8a"}},
{"arm64", "armv8-2a", "kryo385", []string{"arm64-v8a"}},
{"mips", "mips32-fp", "", []string{"mips"}},
{"mips", "mips32r2-fp", "", []string{"mips"}},
diff --git a/android/config.go b/android/config.go
index 3417729..28d9de9 100644
--- a/android/config.go
+++ b/android/config.go
@@ -36,6 +36,9 @@
var Bool = proptools.Bool
var String = proptools.String
+// StringDefault re-exports proptools.StringDefault for the android package.
+var StringDefault = proptools.StringDefault
+
const FutureApiLevel = 10000
// The configuration file name
@@ -964,6 +967,10 @@
return c.multilibConflicts[arch]
}
+func (c *config) PrebuiltHiddenApiDir(ctx PathContext) string {
+ return String(c.productVariables.PrebuiltHiddenApiDir)
+}
+
func (c *deviceConfig) Arches() []Arch {
var arches []Arch
for _, target := range c.config.Targets[Android] {
@@ -991,6 +998,14 @@
return String(c.config.productVariables.DeviceVndkVersion)
}
+func (c *deviceConfig) RecoverySnapshotVersion() string {
+ return String(c.config.productVariables.RecoverySnapshotVersion)
+}
+
+func (c *deviceConfig) RamdiskSnapshotVersion() string {
+ return String(c.config.productVariables.RamdiskSnapshotVersion)
+}
+
func (c *deviceConfig) PlatformVndkVersion() string {
return String(c.config.productVariables.Platform_vndk_version)
}
@@ -1172,6 +1187,27 @@
return HasAnyPrefix(path, c.productVariables.IntegerOverflowExcludePaths)
}
+func (c *config) IntegerOverflowEnabledForPath(path string) bool {
+ if c.productVariables.IntegerOverflowIncludePaths == nil {
+ return false
+ }
+ return HasAnyPrefix(path, c.productVariables.IntegerOverflowIncludePaths)
+}
+
+func (c *config) BoundSanitizerEnabledForPath(path string) bool {
+ if c.productVariables.BoundSanitizerIncludePaths == nil {
+ return false
+ }
+ return HasAnyPrefix(path, c.productVariables.BoundSanitizerIncludePaths)
+}
+
+func (c *config) BoundSanitizerDisabledForPath(path string) bool {
+ if c.productVariables.BoundSanitizerExcludePaths == nil {
+ return false
+ }
+ return HasAnyPrefix(path, c.productVariables.BoundSanitizerExcludePaths)
+}
+
func (c *config) CFIDisabledForPath(path string) bool {
if c.productVariables.CFIExcludePaths == nil {
return false
@@ -1277,3 +1313,83 @@
func (c *deviceConfig) BoardUsesRecoveryAsBoot() bool {
return Bool(c.config.productVariables.BoardUsesRecoveryAsBoot)
}
+
+func (c *deviceConfig) DirectedVendorSnapshot() bool {
+ return c.config.productVariables.DirectedVendorSnapshot
+}
+
+func (c *deviceConfig) VendorSnapshotModules() map[string]bool {
+ return c.config.productVariables.VendorSnapshotModules
+}
+
+func (c *deviceConfig) DirectedRecoverySnapshot() bool {
+ return c.config.productVariables.DirectedRecoverySnapshot
+}
+
+func (c *deviceConfig) RecoverySnapshotModules() map[string]bool {
+ return c.config.productVariables.RecoverySnapshotModules
+}
+
+func (c *deviceConfig) DirectedRamdiskSnapshot() bool {
+ return c.config.productVariables.DirectedRamdiskSnapshot
+}
+
+func (c *deviceConfig) RamdiskSnapshotModules() map[string]bool {
+ return c.config.productVariables.RamdiskSnapshotModules
+}
+
+func createDirsMap(previous map[string]bool, dirs []string) (map[string]bool, error) {
+ var ret = make(map[string]bool)
+ for _, dir := range dirs {
+ clean := filepath.Clean(dir)
+ if previous[clean] || ret[clean] {
+ return nil, fmt.Errorf("Duplicate entry %s", dir)
+ }
+ ret[clean] = true
+ }
+ return ret, nil
+}
+
+func (c *deviceConfig) createDirsMapOnce(onceKey OnceKey, previous map[string]bool, dirs []string) map[string]bool {
+ dirMap := c.Once(onceKey, func() interface{} {
+ ret, err := createDirsMap(previous, dirs)
+ if err != nil {
+ panic(fmt.Errorf("%s: %w", *onceKey.key.(*string), err))
+ }
+ return ret
+ })
+ if dirMap == nil {
+ return nil
+ }
+ return dirMap.(map[string]bool)
+}
+
+var vendorSnapshotDirsExcludedKey = NewOnceKey("VendorSnapshotDirsExcludedMap")
+
+func (c *deviceConfig) VendorSnapshotDirsExcludedMap() map[string]bool {
+ return c.createDirsMapOnce(vendorSnapshotDirsExcludedKey, nil,
+ c.config.productVariables.VendorSnapshotDirsExcluded)
+}
+
+var vendorSnapshotDirsIncludedKey = NewOnceKey("VendorSnapshotDirsIncludedMap")
+
+func (c *deviceConfig) VendorSnapshotDirsIncludedMap() map[string]bool {
+ excludedMap := c.VendorSnapshotDirsExcludedMap()
+ return c.createDirsMapOnce(vendorSnapshotDirsIncludedKey, excludedMap,
+ c.config.productVariables.VendorSnapshotDirsIncluded)
+}
+
+var recoverySnapshotDirsExcludedKey = NewOnceKey("RecoverySnapshotDirsExcludedMap")
+
+func (c *deviceConfig) RecoverySnapshotDirsExcludedMap() map[string]bool {
+ return c.createDirsMapOnce(recoverySnapshotDirsExcludedKey, nil,
+ c.config.productVariables.RecoverySnapshotDirsExcluded)
+}
+
+var recoverySnapshotDirsIncludedKey = NewOnceKey("RecoverySnapshotDirsIncludedMap")
+
+func (c *deviceConfig) RecoverySnapshotDirsIncludedMap() map[string]bool {
+ excludedMap := c.RecoverySnapshotDirsExcludedMap()
+ return c.createDirsMapOnce(recoverySnapshotDirsIncludedKey, excludedMap,
+ c.config.productVariables.RecoverySnapshotDirsIncluded)
+}
diff --git a/android/env.go b/android/env.go
index 46bd3d6..59e0887 100644
--- a/android/env.go
+++ b/android/env.go
@@ -32,6 +32,7 @@
var originalEnv map[string]string
var SoongDelveListen string
var SoongDelvePath string
+var SdclangEnv map[string]string
func init() {
// Delve support needs to read this environment variable very early, before NewConfig has created a way to
@@ -41,10 +42,12 @@
SoongDelvePath, _ = exec.LookPath("dlv")
originalEnv = make(map[string]string)
+ SdclangEnv = make(map[string]string)
for _, env := range os.Environ() {
idx := strings.IndexRune(env, '=')
if idx != -1 {
originalEnv[env[:idx]] = env[idx+1:]
+ SdclangEnv[env[:idx]] = env[idx+1:]
}
}
// Clear the environment to prevent use of os.Getenv(), which would not provide dependencies on environment
diff --git a/android/module.go b/android/module.go
index a498839..8809153 100644
--- a/android/module.go
+++ b/android/module.go
@@ -231,6 +231,8 @@
InstallBypassMake() bool
SkipInstall()
IsSkipInstall() bool
+ ReplacedByPrebuilt()
+ IsReplacedByPrebuilt() bool
ExportedToMake() bool
InitRc() Paths
VintfFragments() Paths
@@ -512,6 +514,12 @@
SkipInstall bool `blueprint:"mutated"`
+ // Whether the module has been replaced by a prebuilt
+ ReplacedByPrebuilt bool `blueprint:"mutated"`
+
+ // Disabled by mutators. If set to true, it overrides Enabled property.
+ ForcedDisabled bool `blueprint:"mutated"`
+
NamespaceExportedToMake bool `blueprint:"mutated"`
MissingDeps []string `blueprint:"mutated"`
@@ -941,6 +949,9 @@
}
func (m *ModuleBase) Enabled() bool {
+ if m.commonProperties.ForcedDisabled {
+ return false
+ }
if m.commonProperties.Enabled == nil {
return !m.Os().DefaultDisabled
}
@@ -948,7 +959,7 @@
}
func (m *ModuleBase) Disable() {
- m.commonProperties.Enabled = proptools.BoolPtr(false)
+ m.commonProperties.ForcedDisabled = true
}
func (m *ModuleBase) SkipInstall() {
@@ -959,6 +970,15 @@
return m.commonProperties.SkipInstall == true
}
+func (m *ModuleBase) ReplacedByPrebuilt() {
+ m.commonProperties.ReplacedByPrebuilt = true
+ m.SkipInstall()
+}
+
+func (m *ModuleBase) IsReplacedByPrebuilt() bool {
+ return m.commonProperties.ReplacedByPrebuilt
+}
+
func (m *ModuleBase) ExportedToMake() bool {
return m.commonProperties.NamespaceExportedToMake
}
diff --git a/android/prebuilt.go b/android/prebuilt.go
index ee4a13a..8ad81e6 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -227,7 +227,7 @@
p := m.(PrebuiltInterface).Prebuilt()
if p.usePrebuilt(ctx, s) {
p.properties.UsePrebuilt = true
- s.SkipInstall()
+ s.ReplacedByPrebuilt()
}
})
}
diff --git a/android/variable.go b/android/variable.go
index 983c235..34d145e 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -131,6 +131,34 @@
Srcs []string `android:"arch_variant"`
Exclude_srcs []string `android:"arch_variant"`
} `android:"arch_variant"`
+
+ Real_hal struct {
+ Cflags []string
+ Exclude_srcs []string
+ Include_dirs []string
+ Shared_libs []string
+ Static_libs []string
+ Srcs []string
+ }
+
+ Qmaa_hal struct {
+ Cflags []string
+ Exclude_srcs []string
+ Include_dirs []string
+ Shared_libs []string
+ Static_libs []string
+ Srcs []string
+ }
+
+ Device_support_hwfde struct {
+ Cflags []string
+ Header_libs []string
+ Shared_libs []string
+ }
+
+ Device_support_hwfde_perf struct {
+ Cflags []string
+ }
} `android:"arch_variant"`
}
@@ -163,6 +191,9 @@
DeviceVndkVersion *string `json:",omitempty"`
DeviceSystemSdkVersions []string `json:",omitempty"`
+ RecoverySnapshotVersion *string `json:",omitempty"`
+ RamdiskSnapshotVersion *string `json:",omitempty"`
+
DeviceSecondaryArch *string `json:",omitempty"`
DeviceSecondaryArchVariant *string `json:",omitempty"`
DeviceSecondaryCpuVariant *string `json:",omitempty"`
@@ -203,6 +234,10 @@
AppsDefaultVersionName *string `json:",omitempty"`
+ Real_hal *bool `json:",omitempty"`
+ Qmaa_hal *bool `json:",omitempty"`
+ Device_support_hwfde *bool `json:",omitempty"`
+ Device_support_hwfde_perf *bool `json:",omitempty"`
Allow_missing_dependencies *bool `json:",omitempty"`
Unbundled_build *bool `json:",omitempty"`
Unbundled_build_sdks_from_source *bool `json:",omitempty"`
@@ -234,6 +269,10 @@
UpdatableBootJars []string `json:",omitempty"`
IntegerOverflowExcludePaths []string `json:",omitempty"`
+ IntegerOverflowIncludePaths []string `json:",omitempty"`
+
+ BoundSanitizerExcludePaths []string `json:",omitempty"`
+ BoundSanitizerIncludePaths []string `json:",omitempty"`
EnableCFI *bool `json:",omitempty"`
CFIExcludePaths []string `json:",omitempty"`
@@ -292,6 +331,20 @@
VndkUseCoreVariant *bool `json:",omitempty"`
VndkSnapshotBuildArtifacts *bool `json:",omitempty"`
+ DirectedVendorSnapshot bool `json:",omitempty"`
+ VendorSnapshotModules map[string]bool `json:",omitempty"`
+
+ DirectedRecoverySnapshot bool `json:",omitempty"`
+ RecoverySnapshotModules map[string]bool `json:",omitempty"`
+
+ DirectedRamdiskSnapshot bool `json:",omitempty"`
+ RamdiskSnapshotModules map[string]bool `json:",omitempty"`
+
+ VendorSnapshotDirsIncluded []string `json:",omitempty"`
+ VendorSnapshotDirsExcluded []string `json:",omitempty"`
+ RecoverySnapshotDirsExcluded []string `json:",omitempty"`
+ RecoverySnapshotDirsIncluded []string `json:",omitempty"`
+
BoardVendorSepolicyDirs []string `json:",omitempty"`
BoardOdmSepolicyDirs []string `json:",omitempty"`
BoardPlatPublicSepolicyDirs []string `json:",omitempty"`
@@ -336,6 +389,8 @@
InstallExtraFlattenedApexes *bool `json:",omitempty"`
BoardUsesRecoveryAsBoot *bool `json:",omitempty"`
+
+ PrebuiltHiddenApiDir *string `json:",omitempty"`
}
func boolPtr(v bool) *bool {
diff --git a/apex/apex.go b/apex/apex.go
index 7da8e1c..3c07903 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -627,6 +627,13 @@
"android.hidl.manager-V1.0-java",
"android.hidl.manager-V1.1-java",
"android.hidl.manager-V1.2-java",
+ "vendor.qti.hardware.wifi.hostapd-V1.0-java",
+ "vendor.qti.hardware.wifi.hostapd-V1.1-java",
+ "vendor.qti.hardware.wifi.hostapd-V1.2-java",
+ "vendor.qti.hardware.wifi.supplicant-V2.0-java",
+ "vendor.qti.hardware.wifi.supplicant-V2.1-java",
+ "vendor.qti.hardware.wifi.supplicant-V2.2-java",
+ "vendor.qti.hardware.fstman-V1.0-java",
"bouncycastle-unbundled",
"dnsresolver_aidl_interface-V2-java",
"error_prone_annotations",
@@ -1759,6 +1766,7 @@
}
var _ javaDependency = (*java.Library)(nil)
+var _ javaDependency = (*java.Import)(nil)
var _ javaDependency = (*java.SdkLibrary)(nil)
var _ javaDependency = (*java.DexImport)(nil)
var _ javaDependency = (*java.SdkLibraryImport)(nil)
@@ -2048,7 +2056,7 @@
}
case javaLibTag:
switch child.(type) {
- case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport:
+ case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport, *java.Import:
af := apexFileForJavaLibrary(ctx, child.(javaDependency), child.(android.Module))
if !af.Ok() {
ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 8803a5f..9f930d1 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -3484,6 +3484,34 @@
`)
}
+func TestApexWithJavaImport(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ java_libs: ["myjavaimport"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_import {
+ name: "myjavaimport",
+ apex_available: ["myapex"],
+ jars: ["my.jar"],
+ compile_dex: true,
+ }
+ `)
+
+ module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+ apexRule := module.Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+ ensureContains(t, copyCmds, "image.apex/javalib/myjavaimport.jar")
+}
+
func TestApexWithApps(t *testing.T) {
ctx, _ := testApex(t, `
apex {
diff --git a/cc/Android.bp b/cc/Android.bp
index 9ece05f..c2c08d1 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -19,6 +19,7 @@
"check.go",
"coverage.go",
"gen.go",
+ "image.go",
"linkable.go",
"lto.go",
"makevars.go",
@@ -29,6 +30,7 @@
"sanitize.go",
"sabi.go",
"sdk.go",
+ "snapshot_prebuilt.go",
"snapshot_utils.go",
"stl.go",
"strip.go",
diff --git a/cc/androidmk.go b/cc/androidmk.go
index fede601..0ad2fcf 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -92,6 +92,12 @@
if len(c.Properties.AndroidMkWholeStaticLibs) > 0 {
entries.AddStrings("LOCAL_WHOLE_STATIC_LIBRARIES", c.Properties.AndroidMkWholeStaticLibs...)
}
+ if len(c.Properties.AndroidMkHeaderLibs) > 0 {
+ entries.AddStrings("LOCAL_HEADER_LIBRARIES", c.Properties.AndroidMkHeaderLibs...)
+ }
+ if lib, ok := c.compiler.(*libraryDecorator); ok {
+ entries.AddStrings("LOCAL_SRC_FILES", lib.baseCompiler.srcsBeforeGen.Strings()...)
+ }
entries.SetString("LOCAL_SOONG_LINK_TYPE", c.makeLinkType)
if c.UseVndk() {
entries.SetBool("LOCAL_USE_VNDK", true)
@@ -486,7 +492,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() {
@@ -497,12 +503,14 @@
entries.Class = "HEADER_LIBRARIES"
}
- if c.androidMkVendorSuffix {
- entries.SubName = vendorSuffix
- } else {
- entries.SubName = ""
+ entries.SubName = ""
+
+ if c.sanitizerProperties.CfiEnabled {
+ entries.SubName += ".cfi"
}
+ entries.SubName += c.androidMkSuffix
+
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
c.libraryDecorator.androidMkWriteExportedFlags(entries)
@@ -512,7 +520,10 @@
entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
entries.SetString("LOCAL_MODULE_STEM", stem)
- if c.shared() {
+ // TODO(b/181815415) remove isLlndk() when possible
+ if c.isLlndk() {
+ entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
+ } else if c.shared() {
entries.SetString("LOCAL_MODULE_PATH", path)
}
if c.tocFile.Valid() {
@@ -526,28 +537,18 @@
})
}
-func (c *vendorSnapshotBinaryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+func (c *snapshotBinaryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
entries.Class = "EXECUTABLES"
-
- if c.androidMkVendorSuffix {
- entries.SubName = vendorSuffix
- } else {
- entries.SubName = ""
- }
+ entries.SubName = c.androidMkSuffix
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
entries.AddStrings("LOCAL_MODULE_SYMLINKS", c.Properties.Symlinks...)
})
}
-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 {
- entries.SubName = vendorSuffix
- } else {
- entries.SubName = ""
- }
+ entries.SubName = c.androidMkSuffix
entries.ExtraFooters = append(entries.ExtraFooters,
func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
diff --git a/cc/builder.go b/cc/builder.go
index 5deb129..6423339 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -322,6 +322,7 @@
aidlFlags string
rsFlags string
toolchain config.Toolchain
+ sdclang bool
tidy bool
gcovCoverage bool
sAbiDump bool
@@ -519,7 +520,13 @@
ccDesc := ccCmd
- ccCmd = "${config.ClangBin}/" + ccCmd
+ var extraFlags string
+ if flags.sdclang {
+ ccCmd = "${config.SDClangBin}/" + ccCmd
+ extraFlags = " ${config.SDClangFlags}"
+ } else {
+ ccCmd = "${config.ClangBin}/" + ccCmd
+ }
var implicitOutputs android.WritablePaths
if coverage {
@@ -537,7 +544,7 @@
Implicits: cFlagsDeps,
OrderOnly: pathDeps,
Args: map[string]string{
- "cFlags": moduleFlags,
+ "cFlags": moduleFlags + extraFlags,
"ccCmd": ccCmd,
},
})
@@ -618,6 +625,9 @@
flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths) {
arCmd := "${config.ClangBin}/llvm-ar"
+ if flags.sdclang {
+ arCmd = "${config.ClangBin}/llvm-ar"
+ }
arFlags := "crsPD"
if !ctx.Darwin() {
arFlags += " -format=gnu"
@@ -642,7 +652,14 @@
objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps android.Paths,
crtBegin, crtEnd android.OptionalPath, groupLate bool, flags builderFlags, outputFile android.WritablePath, implicitOutputs android.WritablePaths) {
- ldCmd := "${config.ClangBin}/clang++"
+ var ldCmd string
+ var extraFlags string
+ if flags.sdclang {
+ ldCmd = "${config.SDClangBin}/clang++"
+ extraFlags = " ${config.SDClangFlags}"
+ } else {
+ ldCmd = "${config.ClangBin}/clang++"
+ }
var libFlagsList []string
@@ -697,7 +714,7 @@
"crtBegin": crtBegin.String(),
"libFlags": strings.Join(libFlagsList, " "),
"extraLibFlags": flags.extraLibFlags,
- "ldFlags": flags.globalLdFlags + " " + flags.localLdFlags,
+ "ldFlags": flags.globalLdFlags + " " + flags.localLdFlags + " " + extraFlags,
"crtEnd": crtEnd.String(),
}
if ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
@@ -800,6 +817,19 @@
if isVndkExt {
localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-allow-extensions")
}
+ var sdclangAbiCheckIgnoreList = []string{
+ "libbinder",
+ "libhwbinder",
+ "libprotobuf-cpp-lite",
+ "libprotobuf-cpp-full",
+ "libunwindstack",
+ "libvixl-arm64",
+ "libvixl-arm",
+ }
+ if config.SDClang && !inList("-advice-only", localAbiCheckAllowFlags) &&
+ inList(ctx.ModuleName(), sdclangAbiCheckIgnoreList) {
+ localAbiCheckAllowFlags = append(localAbiCheckAllowFlags, "-advice-only")
+ }
ctx.Build(pctx, android.BuildParams{
Rule: sAbiDiff,
@@ -851,12 +881,19 @@
func TransformObjsToObj(ctx android.ModuleContext, objFiles android.Paths,
flags builderFlags, outputFile android.WritablePath, deps android.Paths) {
- ldCmd := "${config.ClangBin}/clang++"
+ var ldCmd string
+ var extraFlags string
+ if flags.sdclang {
+ ldCmd = "${config.SDClangBin}/clang++"
+ extraFlags = " ${config.SDClangFlags}"
+ } else {
+ ldCmd = "${config.ClangBin}/clang++"
+ }
rule := partialLd
args := map[string]string{
"ldCmd": ldCmd,
- "ldFlags": flags.globalLdFlags + " " + flags.localLdFlags,
+ "ldFlags": flags.globalLdFlags + " " + flags.localLdFlags + " " + extraFlags,
}
if ctx.Config().IsEnvTrue("RBE_CXX_LINKS") {
rule = partialLdRE
diff --git a/cc/cc.go b/cc/cc.go
index 0f874f1..bc1e5ec 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -52,6 +52,10 @@
ctx.BottomUp("sysprop_cc", SyspropMutator).Parallel()
ctx.BottomUp("vendor_snapshot", VendorSnapshotMutator).Parallel()
ctx.BottomUp("vendor_snapshot_source", VendorSnapshotSourceMutator).Parallel()
+ ctx.BottomUp("recovery_snapshot", RecoverySnapshotMutator).Parallel()
+ ctx.BottomUp("recovery_snapshot_source", RecoverySnapshotSourceMutator).Parallel()
+ ctx.BottomUp("ramdisk_snapshot", RamdiskSnapshotMutator).Parallel()
+ ctx.BottomUp("ramdisk_snapshot_source", RamdiskSnapshotSourceMutator).Parallel()
})
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -183,6 +187,7 @@
SystemIncludeFlags []string
Toolchain config.Toolchain
+ Sdclang bool
Tidy bool
GcovCoverage bool
SAbiDump bool
@@ -209,6 +214,9 @@
// Deprecated. true is the default, false is invalid.
Clang *bool `android:"arch_variant"`
+ // compile module with SDLLVM instead of AOSP LLVM
+ Sdclang *bool `android:"arch_variant"`
+
// Minimum sdk version supported when compiling against the ndk. Setting this property causes
// two variants to be built, one for the platform and one for apps.
Sdk_version *string
@@ -223,6 +231,7 @@
AndroidMkStaticLibs []string `blueprint:"mutated"`
AndroidMkRuntimeLibs []string `blueprint:"mutated"`
AndroidMkWholeStaticLibs []string `blueprint:"mutated"`
+ AndroidMkHeaderLibs []string `blueprint:"mutated"`
HideFromMake bool `blueprint:"mutated"`
PreventInstall bool `blueprint:"mutated"`
ApexesProvidingSharedLibs []string `blueprint:"mutated"`
@@ -270,6 +279,27 @@
// Set when both SDK and platform variants are exported to Make to trigger renaming the SDK
// variant to have a ".sdk" suffix.
SdkAndPlatformVariantVisibleToMake bool `blueprint:"mutated"`
+
+ // Normally Soong uses the directory structure to decide which modules
+ // should be included (framework) or excluded (non-framework) from the
+ // different snapshots (vendor, recovery, etc.), 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
+
+ // Normally Soong uses the directory structure to decide which modules
+ // should be included (framework) or excluded (non-framework) from the
+ // different snapshots (vendor, recovery, etc.), but this property
+ // allows a partner to exclude a module normally thought of as a
+ // framework module from the recovery snapshot.
+ Exclude_from_recovery_snapshot *bool
+
+ // Normally Soong uses the directory structure to decide which modules
+ // should be included (framework) or excluded (non-framework) from the
+ // different snapshots (vendor, recovery, etc.), but this property
+ // allows a partner to exclude a module normally thought of as a
+ // framework module from the ramdisk snapshot.
+ Exclude_from_ramdisk_snapshot *bool
}
type VendorProperties struct {
@@ -930,48 +960,6 @@
return ""
}
-// Returns true only when this module is configured to have core, product and vendor
-// variants.
-func (c *Module) HasVendorVariant() bool {
- return c.IsVndk() || Bool(c.VendorProperties.Vendor_available)
-}
-
-const (
- // VendorVariationPrefix is the variant prefix used for /vendor code that compiles
- // against the VNDK.
- VendorVariationPrefix = "vendor."
-
- // ProductVariationPrefix is the variant prefix used for /product code that compiles
- // against the VNDK.
- ProductVariationPrefix = "product."
-)
-
-// Returns true if the module is "product" variant. Usually these modules are installed in /product
-func (c *Module) inProduct() bool {
- return c.Properties.ImageVariationPrefix == ProductVariationPrefix
-}
-
-// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
-func (c *Module) inVendor() bool {
- return c.Properties.ImageVariationPrefix == VendorVariationPrefix
-}
-
-func (c *Module) InRamdisk() bool {
- return c.ModuleBase.InRamdisk() || c.ModuleBase.InstallInRamdisk()
-}
-
-func (c *Module) InRecovery() bool {
- return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery()
-}
-
-func (c *Module) OnlyInRamdisk() bool {
- return c.ModuleBase.InstallInRamdisk()
-}
-
-func (c *Module) OnlyInRecovery() bool {
- return c.ModuleBase.InstallInRecovery()
-}
-
func (c *Module) IsStubs() bool {
if library, ok := c.linker.(*libraryDecorator); ok {
return library.buildStubs()
@@ -1045,6 +1033,19 @@
return nil
}
+func (c *Module) ExcludeFromVendorSnapshot() bool {
+ return Bool(c.Properties.Exclude_from_vendor_snapshot)
+}
+
+func (c *Module) ExcludeFromRecoverySnapshot() bool {
+ return Bool(c.Properties.Exclude_from_recovery_snapshot)
+}
+
+func (c *Module) ExcludeFromRamdiskSnapshot() bool {
+ return Bool(c.Properties.Exclude_from_ramdisk_snapshot)
+}
+
+
func isBionic(name string) bool {
switch name {
case "libc", "libm", "libdl", "libdl_android", "linker":
@@ -1079,16 +1080,6 @@
moduleContextImpl
}
-func (ctx *moduleContext) ProductSpecific() bool {
- return ctx.ModuleContext.ProductSpecific() ||
- (ctx.mod.HasVendorVariant() && ctx.mod.inProduct() && !ctx.mod.IsVndk())
-}
-
-func (ctx *moduleContext) SocSpecific() bool {
- return ctx.ModuleContext.SocSpecific() ||
- (ctx.mod.HasVendorVariant() && ctx.mod.inVendor() && !ctx.mod.IsVndk())
-}
-
type moduleContextImpl struct {
mod *Module
ctx BaseModuleContext
@@ -1184,22 +1175,6 @@
return ctx.mod.MustUseVendorVariant()
}
-func (ctx *moduleContextImpl) inProduct() bool {
- return ctx.mod.inProduct()
-}
-
-func (ctx *moduleContextImpl) inVendor() bool {
- return ctx.mod.inVendor()
-}
-
-func (ctx *moduleContextImpl) inRamdisk() bool {
- return ctx.mod.InRamdisk()
-}
-
-func (ctx *moduleContextImpl) inRecovery() bool {
- return ctx.mod.InRecovery()
-}
-
// Check whether ABI dumps should be created for this module.
func (ctx *moduleContextImpl) shouldCreateSourceAbiDump() bool {
if ctx.ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") {
@@ -1466,6 +1441,7 @@
flags := Flags{
Toolchain: c.toolchain(ctx),
EmitXrefs: ctx.Config().EmitXrefRules(),
+ Sdclang: c.sdclang(ctx),
}
if c.compiler != nil {
flags = c.compiler.compilerFlags(ctx, flags, deps)
@@ -1555,9 +1531,10 @@
// Note: this is still non-installable
}
- // glob exported headers for snapshot, if BOARD_VNDK_VERSION is current.
- if i, ok := c.linker.(snapshotLibraryInterface); ok && ctx.DeviceConfig().VndkVersion() == "current" {
- if isSnapshotAware(ctx, c) {
+ // glob exported headers for snapshot, if BOARD_VNDK_VERSION is current or
+ // RECOVERY_SNAPSHOT_VERSION is current or RAMDISK_SNAPSHOT_VERSION is current.
+ if i, ok := c.linker.(snapshotLibraryInterface); ok {
+ if shouldCollectHeadersForSnapshot(ctx, c) {
i.collectHeadersForSnapshot(ctx)
}
}
@@ -1756,21 +1733,24 @@
vendorPublicLibraries := vendorPublicLibraries(actx.Config())
vendorSnapshotSharedLibs := vendorSnapshotSharedLibs(actx.Config())
+ recoverySnapshotSharedLibs := recoverySnapshotSharedLibs(actx.Config())
+ ramdiskSnapshotSharedLibs := ramdiskSnapshotSharedLibs(actx.Config())
rewriteVendorLibs := func(lib string) string {
+ // Only a module with BOARD_VNDK_VERSION uses snapshot.
+ // We check this before checking if the library is an
+ // llndk so that the snapshot can contain llndk
+ // libraries.
+ if c.VndkVersion() == actx.DeviceConfig().VndkVersion() {
+ if snapshot, ok := vendorSnapshotSharedLibs.get(lib, actx.Arch().ArchType); ok {
+ return snapshot
+ }
+ }
+
if isLlndkLibrary(lib, ctx.Config()) {
return lib + llndkLibrarySuffix
}
- // only modules with BOARD_VNDK_VERSION uses snapshot.
- if c.VndkVersion() != actx.DeviceConfig().VndkVersion() {
- return lib
- }
-
- if snapshot, ok := vendorSnapshotSharedLibs.get(lib, actx.Arch().ArchType); ok {
- return snapshot
- }
-
return lib
}
@@ -1780,7 +1760,31 @@
for _, entry := range list {
// strip #version suffix out
name, _ := StubsLibNameAndVersion(entry)
- if ctx.useSdk() && inList(name, ndkPrebuiltSharedLibraries) {
+ if c.InRecovery() {
+ recoverySnapshotVersion :=
+ actx.DeviceConfig().RecoverySnapshotVersion()
+ if recoverySnapshotVersion == "current" ||
+ recoverySnapshotVersion == "" {
+ nonvariantLibs = append(nonvariantLibs, name)
+ } else if snapshot, ok := recoverySnapshotSharedLibs.get(
+ name, actx.Arch().ArchType); ok {
+ nonvariantLibs = append(nonvariantLibs, snapshot)
+ } else {
+ nonvariantLibs = append(nonvariantLibs, name)
+ }
+ } else if c.InRamdisk() {
+ ramdiskSnapshotVersion :=
+ actx.DeviceConfig().RamdiskSnapshotVersion()
+ if ramdiskSnapshotVersion == "current" ||
+ ramdiskSnapshotVersion == "" {
+ nonvariantLibs = append(nonvariantLibs, name)
+ } else if snapshot, ok := ramdiskSnapshotSharedLibs.get(
+ name, actx.Arch().ArchType); ok {
+ nonvariantLibs = append(nonvariantLibs, snapshot)
+ } else {
+ nonvariantLibs = append(nonvariantLibs, name)
+ }
+ } else if ctx.useSdk() && inList(name, ndkPrebuiltSharedLibraries) {
if !inList(name, ndkMigratedLibs) {
nonvariantLibs = append(nonvariantLibs, name+".ndk."+version)
} else {
@@ -1838,14 +1842,55 @@
return lib
}
- vendorSnapshotHeaderLibs := vendorSnapshotHeaderLibs(actx.Config())
+ snapshotHeaderLibs := vendorSnapshotHeaderLibs(actx.Config())
+ snapshotStaticLibs := vendorSnapshotStaticLibs(actx.Config())
+ snapshotObjects := vendorSnapshotObjects(actx.Config())
+
+ if c.InRecovery() {
+ rewriteSnapshotLibs = func(lib string, snapshotMap *snapshotMap) string {
+ recoverySnapshotVersion :=
+ actx.DeviceConfig().RecoverySnapshotVersion()
+ if recoverySnapshotVersion == "current" ||
+ recoverySnapshotVersion == "" {
+ return lib
+ } else if snapshot, ok := snapshotMap.get(lib, actx.Arch().ArchType); ok {
+ return snapshot
+ }
+
+ return lib
+ }
+
+ snapshotHeaderLibs = recoverySnapshotHeaderLibs(actx.Config())
+ snapshotStaticLibs = recoverySnapshotStaticLibs(actx.Config())
+ snapshotObjects = recoverySnapshotObjects(actx.Config())
+ }
+
+ if c.InRamdisk() {
+ rewriteSnapshotLibs = func(lib string, snapshotMap *snapshotMap) string {
+ ramdiskSnapshotVersion :=
+ actx.DeviceConfig().RamdiskSnapshotVersion()
+ if ramdiskSnapshotVersion == "current" ||
+ ramdiskSnapshotVersion == "" {
+ return lib
+ } else if snapshot, ok := snapshotMap.get(lib, actx.Arch().ArchType); ok {
+ return snapshot
+ }
+
+ return lib
+ }
+
+ snapshotHeaderLibs = ramdiskSnapshotHeaderLibs(actx.Config())
+ snapshotStaticLibs = ramdiskSnapshotStaticLibs(actx.Config())
+ snapshotObjects = ramdiskSnapshotObjects(actx.Config())
+ }
+
for _, lib := range deps.HeaderLibs {
depTag := headerDepTag
if inList(lib, deps.ReexportHeaderLibHeaders) {
depTag = headerExportDepTag
}
- lib = rewriteSnapshotLibs(lib, vendorSnapshotHeaderLibs)
+ lib = rewriteSnapshotLibs(lib, snapshotHeaderLibs)
if buildStubs {
actx.AddFarVariationDependencies(append(ctx.Target().Variations(), c.ImageVariation()),
@@ -1862,7 +1907,6 @@
}
syspropImplLibraries := syspropImplLibraries(actx.Config())
- vendorSnapshotStaticLibs := vendorSnapshotStaticLibs(actx.Config())
for _, lib := range deps.WholeStaticLibs {
depTag := wholeStaticDepTag
@@ -1870,7 +1914,7 @@
lib = impl
}
- lib = rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs)
+ lib = rewriteSnapshotLibs(lib, snapshotStaticLibs)
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
@@ -1887,7 +1931,7 @@
lib = impl
}
- lib = rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs)
+ lib = rewriteSnapshotLibs(lib, snapshotStaticLibs)
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
@@ -1900,13 +1944,13 @@
if deps.StaticUnwinderIfLegacy {
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
- }, staticUnwinderDepTag, rewriteSnapshotLibs(staticUnwinder(actx), vendorSnapshotStaticLibs))
+ }, staticUnwinderDepTag, rewriteSnapshotLibs(staticUnwinder(actx), snapshotStaticLibs))
}
for _, lib := range deps.LateStaticLibs {
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
- }, lateStaticDepTag, rewriteSnapshotLibs(lib, vendorSnapshotStaticLibs))
+ }, lateStaticDepTag, rewriteSnapshotLibs(lib, snapshotStaticLibs))
}
addSharedLibDependencies := func(depTag DependencyTag, name string, version string) {
@@ -1980,14 +2024,13 @@
}
actx.AddVariationDependencies(nil, objDepTag, deps.ObjFiles...)
-
- vendorSnapshotObjects := vendorSnapshotObjects(actx.Config())
-
if deps.CrtBegin != "" {
- actx.AddVariationDependencies(nil, CrtBeginDepTag, rewriteSnapshotLibs(deps.CrtBegin, vendorSnapshotObjects))
+ actx.AddVariationDependencies(nil, CrtBeginDepTag,
+ rewriteSnapshotLibs(deps.CrtBegin, snapshotObjects))
}
if deps.CrtEnd != "" {
- actx.AddVariationDependencies(nil, CrtEndDepTag, rewriteSnapshotLibs(deps.CrtEnd, vendorSnapshotObjects))
+ actx.AddVariationDependencies(nil, CrtEndDepTag,
+ rewriteSnapshotLibs(deps.CrtEnd, snapshotObjects))
}
if deps.LinkerFlagsFile != "" {
actx.AddDependency(c, linkerFlagsDepTag, deps.LinkerFlagsFile)
@@ -2175,6 +2218,21 @@
}
}
+func (c *Module) sdclang(ctx BaseModuleContext) bool {
+ sdclang := Bool(c.Properties.Sdclang)
+
+ // SDLLVM is not for host build
+ if ctx.Host() || config.ForceSDClangOff {
+ return false
+ }
+
+ if c.Properties.Sdclang == nil && config.SDClang {
+ return true
+ }
+
+ return sdclang
+}
+
// Convert dependencies to paths. Returns a PathDeps containing paths
func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
var depPaths PathDeps
@@ -2182,8 +2240,6 @@
directStaticDeps := []LinkableInterface{}
directSharedDeps := []LinkableInterface{}
- vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
-
reexportExporter := func(exporter exportedFlagsProducer) {
depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, exporter.exportedDirs()...)
depPaths.ReexportedSystemDirs = append(depPaths.ReexportedSystemDirs, exporter.exportedSystemDirs()...)
@@ -2523,59 +2579,6 @@
*depPtr = append(*depPtr, dep.Path())
}
- vendorSuffixModules := vendorSuffixModules(ctx.Config())
-
- baseLibName := func(depName string) string {
- libName := strings.TrimSuffix(depName, llndkLibrarySuffix)
- libName = strings.TrimSuffix(libName, vendorPublicLibrarySuffix)
- libName = strings.TrimPrefix(libName, "prebuilt_")
- return libName
- }
-
- makeLibName := func(depName string) string {
- libName := baseLibName(depName)
- isLLndk := isLlndkLibrary(libName, ctx.Config())
- isVendorPublicLib := inList(libName, *vendorPublicLibraries)
- bothVendorAndCoreVariantsExist := ccDep.HasVendorVariant() || isLLndk
-
- if c, ok := ccDep.(*Module); ok {
- // Use base module name for snapshots when exporting to Makefile.
- if c.isSnapshotPrebuilt() {
- baseName := c.BaseModuleName()
-
- if c.IsVndk() {
- return baseName + ".vendor"
- }
-
- if vendorSuffixModules[baseName] {
- return baseName + ".vendor"
- } else {
- return baseName
- }
- }
- }
-
- if ctx.DeviceConfig().VndkUseCoreVariant() && ccDep.IsVndk() && !ccDep.MustUseVendorVariant() && !c.InRamdisk() && !c.InRecovery() {
- // The vendor module is a no-vendor-variant VNDK library. Depend on the
- // core module instead.
- return libName
- } else if c.UseVndk() && bothVendorAndCoreVariantsExist {
- // The vendor module in Make will have been renamed to not conflict with the core
- // module, so update the dependency name here accordingly.
- return libName + c.getNameSuffixWithVndkVersion(ctx)
- } else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib {
- return libName + vendorPublicLibrarySuffix
- } else if ccDep.InRamdisk() && !ccDep.OnlyInRamdisk() {
- return libName + ramdiskSuffix
- } else if ccDep.InRecovery() && !ccDep.OnlyInRecovery() {
- return libName + recoverySuffix
- } else if ccDep.Module().Target().NativeBridge == android.NativeBridgeEnabled {
- return libName + nativeBridgeSuffix
- } else {
- return libName
- }
- }
-
// Export the shared libs to Make.
switch depTag {
case SharedDepTag, sharedExportDepTag, lateSharedDepTag, earlySharedDepTag:
@@ -2593,7 +2596,7 @@
// Note: the order of libs in this list is not important because
// they merely serve as Make dependencies and do not affect this lib itself.
c.Properties.AndroidMkSharedLibs = append(
- c.Properties.AndroidMkSharedLibs, makeLibName(depName))
+ c.Properties.AndroidMkSharedLibs, c.makeLibName(ctx, ccDep, depName))
// Record baseLibName for snapshots.
c.Properties.SnapshotSharedLibs = append(c.Properties.SnapshotSharedLibs, baseLibName(depName))
case ndkStubDepTag, ndkLateStubDepTag:
@@ -2602,15 +2605,18 @@
depName+"."+ccDep.ApiLevel())
case StaticDepTag, staticExportDepTag, lateStaticDepTag:
c.Properties.AndroidMkStaticLibs = append(
- c.Properties.AndroidMkStaticLibs, makeLibName(depName))
+ c.Properties.AndroidMkStaticLibs, c.makeLibName(ctx, ccDep, depName))
case runtimeDepTag:
c.Properties.AndroidMkRuntimeLibs = append(
- c.Properties.AndroidMkRuntimeLibs, makeLibName(depName))
+ c.Properties.AndroidMkRuntimeLibs, c.makeLibName(ctx, ccDep, depName))
// Record baseLibName for snapshots.
c.Properties.SnapshotRuntimeLibs = append(c.Properties.SnapshotRuntimeLibs, baseLibName(depName))
case wholeStaticDepTag:
c.Properties.AndroidMkWholeStaticLibs = append(
- c.Properties.AndroidMkWholeStaticLibs, makeLibName(depName))
+ c.Properties.AndroidMkWholeStaticLibs, c.makeLibName(ctx, ccDep, depName))
+ case headerDepTag:
+ c.Properties.AndroidMkHeaderLibs = append(
+ c.Properties.AndroidMkHeaderLibs, c.makeLibName(ctx, ccDep, depName))
}
})
@@ -2636,6 +2642,68 @@
return depPaths
}
+// baseLibName trims known prefixes and suffixes
+func baseLibName(depName string) string {
+ libName := strings.TrimSuffix(depName, llndkLibrarySuffix)
+ libName = strings.TrimSuffix(libName, vendorPublicLibrarySuffix)
+ libName = strings.TrimPrefix(libName, "prebuilt_")
+ return libName
+}
+
+func (c *Module) makeLibName(ctx android.ModuleContext, ccDep LinkableInterface, depName string) string {
+ vendorSuffixModules := vendorSuffixModules(ctx.Config())
+ recoverySuffixModules := recoverySuffixModules(ctx.Config())
+ ramdiskSuffixModules := ramdiskSuffixModules(ctx.Config())
+ vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
+
+ libName := baseLibName(depName)
+ isLLndk := isLlndkLibrary(libName, ctx.Config())
+ isVendorPublicLib := inList(libName, *vendorPublicLibraries)
+ bothVendorAndCoreVariantsExist := ccDep.HasVendorVariant() || isLLndk
+
+ if c, ok := ccDep.(*Module); ok {
+ // Use base module name for snapshots when exporting to Makefile.
+ if c.isSnapshotPrebuilt() {
+ baseName := c.BaseModuleName()
+
+ if c.IsVndk() {
+ return baseName + ".vendor"
+ }
+
+ if c.inVendor() && vendorSuffixModules[baseName] {
+ return baseName + ".vendor"
+ } else if c.InRecovery() && recoverySuffixModules[baseName] {
+ return baseName + ".recovery"
+ } else if c.InRamdisk() && ramdiskSuffixModules[baseName] {
+ return baseName + ".ramdisk"
+ } else {
+ return baseName
+ }
+ }
+ }
+
+ if ctx.DeviceConfig().VndkUseCoreVariant() && ccDep.IsVndk() && !ccDep.MustUseVendorVariant() &&
+ !c.InRamdisk() && !c.InRecovery() {
+ // The vendor module is a no-vendor-variant VNDK library. Depend on the
+ // core module instead.
+ return libName
+ } else if c.UseVndk() && bothVendorAndCoreVariantsExist {
+ // The vendor module in Make will have been renamed to not conflict with the core
+ // module, so update the dependency name here accordingly.
+ return libName + c.getNameSuffixWithVndkVersion(ctx)
+ } else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib {
+ return libName + vendorPublicLibrarySuffix
+ } else if ccDep.InRamdisk() && !ccDep.OnlyInRamdisk() {
+ return libName + ramdiskSuffix
+ } else if ccDep.InRecovery() && !ccDep.OnlyInRecovery() {
+ return libName + recoverySuffix
+ } else if ccDep.Module().Target().NativeBridge == android.NativeBridgeEnabled {
+ return libName + nativeBridgeSuffix
+ } else {
+ return libName
+ }
+}
+
func (c *Module) InstallInData() bool {
if c.installer == nil {
return false
@@ -2944,227 +3012,6 @@
}
}
-var _ android.ImageInterface = (*Module)(nil)
-
-func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
- // Sanity check
- vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
- productSpecific := mctx.ProductSpecific()
-
- if m.VendorProperties.Vendor_available != nil && vendorSpecific {
- mctx.PropertyErrorf("vendor_available",
- "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
- }
-
- if vndkdep := m.vndkdep; vndkdep != nil {
- if vndkdep.isVndk() {
- if vendorSpecific || productSpecific {
- if !vndkdep.isVndkExt() {
- mctx.PropertyErrorf("vndk",
- "must set `extends: \"...\"` to vndk extension")
- } else if m.VendorProperties.Vendor_available != nil {
- mctx.PropertyErrorf("vendor_available",
- "must not set at the same time as `vndk: {extends: \"...\"}`")
- }
- } else {
- if vndkdep.isVndkExt() {
- mctx.PropertyErrorf("vndk",
- "must set `vendor: true` or `product_specific: true` to set `extends: %q`",
- m.getVndkExtendsModuleName())
- }
- if m.VendorProperties.Vendor_available == nil {
- mctx.PropertyErrorf("vndk",
- "vendor_available must be set to either true or false when `vndk: {enabled: true}`")
- }
- }
- } else {
- if vndkdep.isVndkSp() {
- mctx.PropertyErrorf("vndk",
- "must set `enabled: true` to set `support_system_process: true`")
- }
- if vndkdep.isVndkExt() {
- mctx.PropertyErrorf("vndk",
- "must set `enabled: true` to set `extends: %q`",
- m.getVndkExtendsModuleName())
- }
- }
- }
-
- var coreVariantNeeded bool = false
- var ramdiskVariantNeeded bool = false
- var recoveryVariantNeeded bool = false
-
- var vendorVariants []string
- var productVariants []string
-
- platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
- boardVndkVersion := mctx.DeviceConfig().VndkVersion()
- productVndkVersion := mctx.DeviceConfig().ProductVndkVersion()
- if boardVndkVersion == "current" {
- boardVndkVersion = platformVndkVersion
- }
- if productVndkVersion == "current" {
- productVndkVersion = platformVndkVersion
- }
-
- if boardVndkVersion == "" {
- // If the device isn't compiling against the VNDK, we always
- // use the core mode.
- coreVariantNeeded = true
- } else if _, ok := m.linker.(*llndkStubDecorator); ok {
- // LL-NDK stubs only exist in the vendor and product variants,
- // since the real libraries will be used in the core variant.
- vendorVariants = append(vendorVariants,
- platformVndkVersion,
- boardVndkVersion,
- )
- productVariants = append(productVariants,
- platformVndkVersion,
- productVndkVersion,
- )
- } else if _, ok := m.linker.(*llndkHeadersDecorator); ok {
- // ... and LL-NDK headers as well
- vendorVariants = append(vendorVariants,
- platformVndkVersion,
- boardVndkVersion,
- )
- productVariants = append(productVariants,
- platformVndkVersion,
- productVndkVersion,
- )
- } else if m.isSnapshotPrebuilt() {
- // Make vendor variants only for the versions in BOARD_VNDK_VERSION and
- // PRODUCT_EXTRA_VNDK_VERSIONS.
- if snapshot, ok := m.linker.(interface {
- version() string
- }); ok {
- vendorVariants = append(vendorVariants, snapshot.version())
- } else {
- mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
- }
- } else if m.HasVendorVariant() && !m.isVndkExt() {
- // This will be available in /system, /vendor and /product
- // or a /system directory that is available to vendor and product.
- coreVariantNeeded = true
-
- // We assume that modules under proprietary paths are compatible for
- // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
- // PLATFORM_VNDK_VERSION.
- if isVendorProprietaryPath(mctx.ModuleDir()) {
- vendorVariants = append(vendorVariants, boardVndkVersion)
- } else {
- vendorVariants = append(vendorVariants, platformVndkVersion)
- }
-
- // vendor_available modules are also available to /product.
- productVariants = append(productVariants, platformVndkVersion)
- // VNDK is always PLATFORM_VNDK_VERSION
- if !m.IsVndk() {
- productVariants = append(productVariants, productVndkVersion)
- }
- } else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
- // This will be available in /vendor (or /odm) only
- // We assume that modules under proprietary paths are compatible for
- // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
- // PLATFORM_VNDK_VERSION.
- if isVendorProprietaryPath(mctx.ModuleDir()) {
- vendorVariants = append(vendorVariants, boardVndkVersion)
- } else {
- vendorVariants = append(vendorVariants, platformVndkVersion)
- }
- } else {
- // This is either in /system (or similar: /data), or is a
- // modules built with the NDK. Modules built with the NDK
- // will be restricted using the existing link type checks.
- coreVariantNeeded = true
- }
-
- if boardVndkVersion != "" && productVndkVersion != "" {
- if coreVariantNeeded && productSpecific && String(m.Properties.Sdk_version) == "" {
- // The module has "product_specific: true" that does not create core variant.
- coreVariantNeeded = false
- productVariants = append(productVariants, productVndkVersion)
- }
- } else {
- // Unless PRODUCT_PRODUCT_VNDK_VERSION is set, product partition has no
- // restriction to use system libs.
- // No product variants defined in this case.
- productVariants = []string{}
- }
-
- if Bool(m.Properties.Ramdisk_available) {
- ramdiskVariantNeeded = true
- }
-
- if m.ModuleBase.InstallInRamdisk() {
- ramdiskVariantNeeded = true
- coreVariantNeeded = false
- }
-
- if Bool(m.Properties.Recovery_available) {
- recoveryVariantNeeded = true
- }
-
- if m.ModuleBase.InstallInRecovery() {
- recoveryVariantNeeded = true
- coreVariantNeeded = false
- }
-
- for _, variant := range android.FirstUniqueStrings(vendorVariants) {
- m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, VendorVariationPrefix+variant)
- }
-
- for _, variant := range android.FirstUniqueStrings(productVariants) {
- m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, ProductVariationPrefix+variant)
- }
-
- m.Properties.RamdiskVariantNeeded = ramdiskVariantNeeded
- m.Properties.RecoveryVariantNeeded = recoveryVariantNeeded
- m.Properties.CoreVariantNeeded = coreVariantNeeded
-}
-
-func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
- return c.Properties.CoreVariantNeeded
-}
-
-func (c *Module) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
- return c.Properties.RamdiskVariantNeeded
-}
-
-func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
- return c.Properties.RecoveryVariantNeeded
-}
-
-func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string {
- return c.Properties.ExtraVariants
-}
-
-func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) {
- m := module.(*Module)
- if variant == android.RamdiskVariation {
- m.MakeAsPlatform()
- } else if variant == android.RecoveryVariation {
- m.MakeAsPlatform()
- squashRecoverySrcs(m)
- } else if strings.HasPrefix(variant, VendorVariationPrefix) {
- m.Properties.ImageVariationPrefix = VendorVariationPrefix
- m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
- squashVendorSrcs(m)
-
- // Makefile shouldn't know vendor modules other than BOARD_VNDK_VERSION.
- // Hide other vendor variants to avoid collision.
- vndkVersion := ctx.DeviceConfig().VndkVersion()
- if vndkVersion != "current" && vndkVersion != "" && vndkVersion != m.Properties.VndkVersion {
- m.Properties.HideFromMake = true
- m.SkipInstall()
- }
- } else if strings.HasPrefix(variant, ProductVariationPrefix) {
- m.Properties.ImageVariationPrefix = ProductVariationPrefix
- m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
- squashVendorSrcs(m)
- }
-}
-
func getCurrentNdkPrebuiltVersion(ctx DepsContext) string {
if ctx.Config().PlatformSdkVersionInt() > config.NdkMaxPrebuiltVersionInt {
return strconv.Itoa(config.NdkMaxPrebuiltVersionInt)
diff --git a/cc/cc_test.go b/cc/cc_test.go
index f73e021..2d2a99a 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -258,7 +258,8 @@
}
}
-func checkSnapshot(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
+func checkSnapshotIncludeExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string, include bool, fake bool) {
+ t.Helper()
mod, ok := ctx.ModuleForTests(moduleName, variant).Module().(android.OutputFileProducer)
if !ok {
t.Errorf("%q must have output\n", moduleName)
@@ -271,12 +272,37 @@
}
snapshotPath := filepath.Join(subDir, snapshotFilename)
- out := singleton.Output(snapshotPath)
- if out.Input.String() != outputFiles[0].String() {
- t.Errorf("The input of snapshot %q must be %q, but %q", moduleName, out.Input.String(), outputFiles[0])
+ if include {
+ out := singleton.Output(snapshotPath)
+ if fake {
+ if out.Rule == nil {
+ t.Errorf("Missing rule for module %q output file %q", moduleName, outputFiles[0])
+ }
+ } else {
+ if out.Input.String() != outputFiles[0].String() {
+ t.Errorf("The input of snapshot %q must be %q, but %q", moduleName, out.Input.String(), outputFiles[0])
+ }
+ }
+ } else {
+ out := singleton.MaybeOutput(snapshotPath)
+ if out.Rule != nil {
+ t.Errorf("There must be no rule for module %q output file %q", moduleName, outputFiles[0])
+ }
}
}
+func checkSnapshot(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
+ checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, false)
+}
+
+func checkSnapshotExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
+ checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, false, false)
+}
+
+func checkSnapshotRule(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
+ checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, true)
+}
+
func checkWriteFileOutput(t *testing.T, params android.TestingBuildParams, expected []string) {
t.Helper()
assertString(t, params.Rule.String(), android.WriteFile.String())
@@ -833,131 +859,6 @@
`)
}
-func TestVendorSnapshot(t *testing.T) {
- bp := `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvendor",
- vendor: true,
- nocrt: true,
- }
-
- cc_library {
- name: "libvendor_available",
- vendor_available: true,
- nocrt: true,
- }
-
- cc_library_headers {
- name: "libvendor_headers",
- vendor_available: true,
- nocrt: true,
- }
-
- cc_binary {
- name: "vendor_bin",
- vendor: true,
- nocrt: true,
- }
-
- cc_binary {
- name: "vendor_available_bin",
- vendor_available: true,
- nocrt: true,
- }
-
- toolchain_library {
- name: "libb",
- vendor_available: true,
- src: "libb.a",
- }
-
- cc_object {
- name: "obj",
- vendor_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 Vendor snapshot output.
-
- snapshotDir := "vendor-snapshot"
- snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
- snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
-
- var jsonFiles []string
-
- for _, arch := range [][]string{
- []string{"arm64", "armv8-a"},
- []string{"arm", "armv7-a-neon"},
- } {
- archType := arch[0]
- archVariant := arch[1]
- archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
-
- // For shared libraries, only non-VNDK vendor_available modules are captured
- sharedVariant := fmt.Sprintf("android_vendor.VER_%s_%s_shared", archType, archVariant)
- sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
- checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(sharedDir, "libvendor.so.json"),
- filepath.Join(sharedDir, "libvendor_available.so.json"))
-
- // For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
- staticVariant := fmt.Sprintf("android_vendor.VER_%s_%s_static", archType, archVariant)
- staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
- checkSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.a", staticDir, staticVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.a", staticDir, staticVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(staticDir, "libb.a.json"),
- filepath.Join(staticDir, "libvndk.a.json"),
- filepath.Join(staticDir, "libvendor.a.json"),
- filepath.Join(staticDir, "libvendor_available.a.json"))
-
- // For binary executables, all vendor:true and vendor_available modules are captured.
- if archType == "arm64" {
- binaryVariant := fmt.Sprintf("android_vendor.VER_%s_%s", archType, archVariant)
- binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
- checkSnapshot(t, ctx, snapshotSingleton, "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
- jsonFiles = append(jsonFiles,
- filepath.Join(binaryDir, "vendor_bin.json"),
- filepath.Join(binaryDir, "vendor_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, "libvendor_headers.json"))
-
- // For object modules, all vendor:true and vendor_available modules are captured.
- objectVariant := fmt.Sprintf("android_vendor.VER_%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/config/global.go b/cc/config/global.go
index 473c806..b633a72 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -15,6 +15,13 @@
package config
import (
+ "encoding/json"
+ "fmt"
+ //"io/ioutil"
+ "os"
+ //"path"
+ //"path/filepath"
+ "strconv"
"strings"
"android/soong/android"
@@ -112,7 +119,9 @@
noOverrideGlobalCflags = []string{
"-Werror=int-to-pointer-cast",
"-Werror=pointer-to-int-cast",
- "-Werror=fortify-source",
+ // SDClang does not support -Werror=fortify-source.
+ // TODO: b/142476859
+ // "-Werror=fortify-source",
}
IllegalFlags = []string{
@@ -126,6 +135,10 @@
NdkMaxPrebuiltVersionInt = 27
+ SDClang = false
+ SDClangPath = ""
+ ForceSDClangOff = false
+
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
ClangDefaultVersion = "clang-r383902b1"
@@ -212,6 +225,8 @@
pctx.PrefixedExistentPathsForSourcesVariable("CommonNativehelperInclude", "-I",
[]string{"libnativehelper/include_jni"})
+ setSdclangVars()
+
pctx.SourcePathVariable("ClangDefaultBase", ClangDefaultBase)
pctx.VariableFunc("ClangBase", func(ctx android.PackageVarContext) string {
if override := ctx.Config().Getenv("LLVM_PREBUILTS_BASE"); override != "" {
@@ -264,6 +279,149 @@
pctx.VariableFunc("REAbiLinkerExecStrategy", remoteexec.EnvOverrideFunc("RBE_ABI_LINKER_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
}
+func setSdclangVars() {
+ sdclangPath := ""
+ sdclangAEFlag := ""
+ sdclangFlags := ""
+
+ product := android.SdclangEnv["TARGET_PRODUCT"]
+ aeConfigPath := android.SdclangEnv["SDCLANG_AE_CONFIG"]
+ sdclangConfigPath := android.SdclangEnv["SDCLANG_CONFIG"]
+ sdclangSA := android.SdclangEnv["SDCLANG_SA_ENABLED"]
+
+ type sdclangAEConfig struct {
+ SDCLANG_AE_FLAG string
+ }
+
+ // Load AE config file and set AE flag
+ if file, err := os.Open(aeConfigPath); err == nil {
+ decoder := json.NewDecoder(file)
+ aeConfig := sdclangAEConfig{}
+ if err := decoder.Decode(&aeConfig); err == nil {
+ sdclangAEFlag = aeConfig.SDCLANG_AE_FLAG
+ } else {
+ panic(err)
+ }
+ }
+
+ // Load SD Clang config file and set SD Clang variables
+ var sdclangConfig interface{}
+ if file, err := os.Open(sdclangConfigPath); err == nil {
+ decoder := json.NewDecoder(file)
+ // Parse the config file
+ if err := decoder.Decode(&sdclangConfig); err == nil {
+ config := sdclangConfig.(map[string]interface{})
+ // Retrieve the default block
+ if dev, ok := config["default"]; ok {
+ devConfig := dev.(map[string]interface{})
+ // FORCE_SDCLANG_OFF is required in the default block
+ if _, ok := devConfig["FORCE_SDCLANG_OFF"]; ok {
+ ForceSDClangOff = devConfig["FORCE_SDCLANG_OFF"].(bool)
+ }
+ // SDCLANG is optional in the default block
+ if _, ok := devConfig["SDCLANG"]; ok {
+ SDClang = devConfig["SDCLANG"].(bool)
+ }
+ // SDCLANG_PATH is required in the default block
+ if _, ok := devConfig["SDCLANG_PATH"]; ok {
+ sdclangPath = devConfig["SDCLANG_PATH"].(string)
+ } else {
+ panic("SDCLANG_PATH is required in the default block")
+ }
+ // SDCLANG_FLAGS is optional in the default block
+ if _, ok := devConfig["SDCLANG_FLAGS"]; ok {
+ sdclangFlags = devConfig["SDCLANG_FLAGS"].(string)
+ }
+ } else {
+ panic("Default block is required in the SD Clang config file")
+ }
+ // Retrieve the device specific block if it exists in the config file
+ if dev, ok := config[product]; ok {
+ devConfig := dev.(map[string]interface{})
+ // SDCLANG is optional in the device specific block
+ if _, ok := devConfig["SDCLANG"]; ok {
+ SDClang = devConfig["SDCLANG"].(bool)
+ }
+ // SDCLANG_PATH is optional in the device specific block
+ if _, ok := devConfig["SDCLANG_PATH"]; ok {
+ sdclangPath = devConfig["SDCLANG_PATH"].(string)
+ }
+ // SDCLANG_FLAGS is optional in the device specific block
+ if _, ok := devConfig["SDCLANG_FLAGS"]; ok {
+ sdclangFlags = devConfig["SDCLANG_FLAGS"].(string)
+ }
+ }
+ b, _ := strconv.ParseBool(sdclangSA)
+ if(b) {
+ llvmsa_loc := "llvmsa"
+ s := []string{sdclangFlags, "--compile-and-analyze", llvmsa_loc}
+ sdclangFlags = strings.Join(s, " ")
+ fmt.Println("Clang SA is enabled: ", sdclangFlags)
+ } else {
+ fmt.Println("Clang SA is not enabled")
+ }
+ } else {
+ panic(err)
+ }
+ } else {
+ fmt.Println(err)
+ }
+
+ // Override SDCLANG if the varialbe is set in the environment
+ if sdclang := android.SdclangEnv["SDCLANG"]; sdclang != "" {
+ if override, err := strconv.ParseBool(sdclang); err == nil {
+ SDClang = override
+ }
+ }
+
+ // Sanity check SDCLANG_PATH
+ if envPath := android.SdclangEnv["SDCLANG_PATH"]; sdclangPath == "" && envPath == "" {
+ panic("SDCLANG_PATH can not be empty")
+ }
+
+ // Override SDCLANG_PATH if the variable is set in the environment
+ pctx.VariableFunc("SDClangBin", func(ctx android.PackageVarContext) string {
+ if override := ctx.Config().Getenv("SDCLANG_PATH"); override != "" {
+ return override
+ }
+ return sdclangPath
+ })
+
+ // Override SDCLANG_COMMON_FLAGS if the variable is set in the environment
+ pctx.VariableFunc("SDClangFlags", func(ctx android.PackageVarContext) string {
+ if override := ctx.Config().Getenv("SDCLANG_COMMON_FLAGS"); override != "" {
+ return override
+ }
+ return sdclangAEFlag + " " + sdclangFlags
+ })
+
+ SDClangPath = sdclangPath
+ // Find the path to SDLLVM's ASan libraries
+ // TODO (b/117846004): Disable setting SDClangAsanLibDir due to unit test path issues
+ //absPath := sdclangPath
+ //if envPath := android.SdclangEnv["SDCLANG_PATH"]; envPath != "" {
+ // absPath = envPath
+ //}
+ //if !filepath.IsAbs(absPath) {
+ // absPath = path.Join(androidRoot, absPath)
+ //}
+ //
+ //libDirPrefix := "../lib/clang"
+ //libDir, err := ioutil.ReadDir(path.Join(absPath, libDirPrefix))
+ //if err != nil {
+ // libDirPrefix = "../lib64/clang"
+ // libDir, err = ioutil.ReadDir(path.Join(absPath, libDirPrefix))
+ //}
+ //if err != nil {
+ // panic(err)
+ //}
+ //if len(libDir) != 1 || !libDir[0].IsDir() {
+ // panic("Failed to find sanitizer libraries")
+ //}
+ //
+ //pctx.StaticVariable("SDClangAsanLibDir", path.Join(absPath, libDirPrefix, libDir[0].Name(), "lib/linux"))
+}
+
var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
func bionicHeaders(kernelArch string) string {
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index 6f2e807..ccf6eed 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -47,4 +47,5 @@
"libstagefright_xmlparser",
"libui",
"libxml2",
+ "libmedia_helper",//Remove it from the list once the workaround patch is cleared in S
}
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 13b5511..7e306c5 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -107,6 +107,7 @@
"resolv",
"rt",
"util",
+ "supc++",
}, "-l")
)
diff --git a/cc/genrule.go b/cc/genrule.go
index 66d1784..e6ef62a 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -64,12 +64,29 @@
return Bool(g.Vendor_available) || !(ctx.SocSpecific() || ctx.DeviceSpecific())
}
-func (g *GenruleExtraProperties) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
- return Bool(g.Ramdisk_available)
-}
+
func (g *GenruleExtraProperties) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
- return Bool(g.Recovery_available)
+ // If the build is using a snapshot, the recovery variant under AOSP directories
+ // is not needed.
+ recoverySnapshotVersion := ctx.DeviceConfig().RecoverySnapshotVersion()
+ if recoverySnapshotVersion != "current" && recoverySnapshotVersion != "" &&
+ !isRecoveryProprietaryModule(ctx) {
+ return false
+ } else {
+ return Bool(g.Recovery_available)
+ }
+}
+func (g *GenruleExtraProperties) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ // If the build is using a snapshot, the ramdisk variant under AOSP directories
+ // is not needed.
+ ramdiskSnapshotVersion := ctx.DeviceConfig().RamdiskSnapshotVersion()
+ if ramdiskSnapshotVersion != "current" && ramdiskSnapshotVersion != "" &&
+ !isRamdiskProprietaryModule(ctx) {
+ return false
+ } else {
+ return Bool(g.Ramdisk_available)
+ }
}
func (g *GenruleExtraProperties) ExtraImageVariations(ctx android.BaseModuleContext) []string {
@@ -84,7 +101,7 @@
// If not, we assume modules under proprietary paths are compatible for
// BOARD_VNDK_VERSION. The other modules are regarded as AOSP, that is
// PLATFORM_VNDK_VERSION.
- if vndkVersion == "current" || !isVendorProprietaryPath(ctx.ModuleDir()) {
+ if vndkVersion == "current" || !isVendorProprietaryModule(ctx) {
variants = append(variants, VendorVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
} else {
variants = append(variants, VendorVariationPrefix+vndkVersion)
diff --git a/cc/image.go b/cc/image.go
new file mode 100644
index 0000000..6b3b083
--- /dev/null
+++ b/cc/image.go
@@ -0,0 +1,408 @@
+// Copyright 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 cc
+
+// This file contains image variant related things, including image mutator functions, utility
+// functions to determine where a module is installed, etc.
+
+import (
+ "strings"
+
+ "android/soong/android"
+)
+
+var _ android.ImageInterface = (*Module)(nil)
+
+type imageVariantType string
+
+const (
+ coreImageVariant imageVariantType = "core"
+ vendorImageVariant imageVariantType = "vendor"
+ productImageVariant imageVariantType = "product"
+ ramdiskImageVariant imageVariantType = "ramdisk"
+ recoveryImageVariant imageVariantType = "recovery"
+ hostImageVariant imageVariantType = "host"
+)
+
+func (c *Module) getImageVariantType() imageVariantType {
+ if c.Host() {
+ return hostImageVariant
+ } else if c.inVendor() {
+ return vendorImageVariant
+ } else if c.inProduct() {
+ return productImageVariant
+ } else if c.InRamdisk() {
+ return ramdiskImageVariant
+ } else if c.InRecovery() {
+ return recoveryImageVariant
+ } else {
+ return coreImageVariant
+ }
+}
+
+const (
+ // VendorVariationPrefix is the variant prefix used for /vendor code that compiles
+ // against the VNDK.
+ VendorVariationPrefix = "vendor."
+
+ // ProductVariationPrefix is the variant prefix used for /product code that compiles
+ // against the VNDK.
+ ProductVariationPrefix = "product."
+)
+
+func (ctx *moduleContext) ProductSpecific() bool {
+ return ctx.ModuleContext.ProductSpecific() ||
+ (ctx.mod.HasVendorVariant() && ctx.mod.inProduct() && !ctx.mod.IsVndk())
+}
+
+func (ctx *moduleContext) SocSpecific() bool {
+ return ctx.ModuleContext.SocSpecific() ||
+ (ctx.mod.HasVendorVariant() && ctx.mod.inVendor() && !ctx.mod.IsVndk())
+}
+
+func (ctx *moduleContextImpl) inProduct() bool {
+ return ctx.mod.inProduct()
+}
+
+func (ctx *moduleContextImpl) inVendor() bool {
+ return ctx.mod.inVendor()
+}
+
+func (ctx *moduleContextImpl) inRamdisk() bool {
+ return ctx.mod.InRamdisk()
+}
+
+func (ctx *moduleContextImpl) inRecovery() bool {
+ return ctx.mod.InRecovery()
+}
+
+// Returns true only when this module is configured to have core, product and vendor
+// variants.
+func (c *Module) HasVendorVariant() bool {
+ return c.IsVndk() || Bool(c.VendorProperties.Vendor_available)
+}
+
+// Returns true if the module is "product" variant. Usually these modules are installed in /product
+func (c *Module) inProduct() bool {
+ return c.Properties.ImageVariationPrefix == ProductVariationPrefix
+}
+
+// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
+func (c *Module) inVendor() bool {
+ return c.Properties.ImageVariationPrefix == VendorVariationPrefix
+}
+
+func (c *Module) InRamdisk() bool {
+ return c.ModuleBase.InRamdisk() || c.ModuleBase.InstallInRamdisk()
+}
+
+func (c *Module) InRecovery() bool {
+ return c.ModuleBase.InRecovery() || c.ModuleBase.InstallInRecovery()
+}
+
+func (c *Module) OnlyInRamdisk() bool {
+ return c.ModuleBase.InstallInRamdisk()
+}
+
+func (c *Module) OnlyInRecovery() bool {
+ return c.ModuleBase.InstallInRecovery()
+}
+
+func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
+ // Validation check
+ vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
+ productSpecific := mctx.ProductSpecific()
+
+ if m.VendorProperties.Vendor_available != nil && vendorSpecific {
+ mctx.PropertyErrorf("vendor_available",
+ "doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
+ }
+
+ if vndkdep := m.vndkdep; vndkdep != nil {
+ if vndkdep.isVndk() {
+ if vendorSpecific || productSpecific {
+ if !vndkdep.isVndkExt() {
+ mctx.PropertyErrorf("vndk",
+ "must set `extends: \"...\"` to vndk extension")
+ } else if m.VendorProperties.Vendor_available != nil {
+ mctx.PropertyErrorf("vendor_available",
+ "must not set at the same time as `vndk: {extends: \"...\"}`")
+ }
+ } else {
+ if vndkdep.isVndkExt() {
+ mctx.PropertyErrorf("vndk",
+ "must set `vendor: true` or `product_specific: true` to set `extends: %q`",
+ m.getVndkExtendsModuleName())
+ }
+ if m.VendorProperties.Vendor_available == nil {
+ mctx.PropertyErrorf("vndk",
+ "vendor_available must be set to either true or false when `vndk: {enabled: true}`")
+ }
+ }
+ } else {
+ if vndkdep.isVndkSp() {
+ mctx.PropertyErrorf("vndk",
+ "must set `enabled: true` to set `support_system_process: true`")
+ }
+ if vndkdep.isVndkExt() {
+ mctx.PropertyErrorf("vndk",
+ "must set `enabled: true` to set `extends: %q`",
+ m.getVndkExtendsModuleName())
+ }
+ }
+ }
+
+ var coreVariantNeeded bool = false
+ var ramdiskVariantNeeded bool = false
+ var recoveryVariantNeeded bool = false
+
+ var vendorVariants []string
+ var productVariants []string
+
+ platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
+ boardVndkVersion := mctx.DeviceConfig().VndkVersion()
+ productVndkVersion := mctx.DeviceConfig().ProductVndkVersion()
+ recoverySnapshotVersion := mctx.DeviceConfig().RecoverySnapshotVersion()
+ usingRecoverySnapshot := recoverySnapshotVersion != "current" &&
+ recoverySnapshotVersion != ""
+ ramdiskSnapshotVersion := mctx.DeviceConfig().RamdiskSnapshotVersion()
+ usingRamdiskSnapshot := ramdiskSnapshotVersion != "current" &&
+ ramdiskSnapshotVersion != ""
+ if boardVndkVersion == "current" {
+ boardVndkVersion = platformVndkVersion
+ }
+ if productVndkVersion == "current" {
+ productVndkVersion = platformVndkVersion
+ }
+ usingVendorSnapshot := boardVndkVersion != platformVndkVersion
+
+ if boardVndkVersion == "" {
+ // If the device isn't compiling against the VNDK, we always
+ // use the core mode.
+ coreVariantNeeded = true
+ } else if _, ok := m.linker.(*llndkStubDecorator); ok {
+ // LL-NDK stubs only exist in the vendor and product variants,
+ // since the real libraries will be used in the core variant.
+
+ if usingVendorSnapshot {
+ // If we're using the vendor snapshot, avoid providing
+ // the boardVndkVersion. This requires that the vendor
+ // snapshot provide the library instead, which happens
+ // below as a snapshot prebuilt.
+ vendorVariants = append(vendorVariants,
+ platformVndkVersion,
+ )
+ } else {
+ vendorVariants = append(vendorVariants,
+ platformVndkVersion,
+ boardVndkVersion,
+ )
+ }
+
+ productVariants = append(productVariants,
+ platformVndkVersion,
+ productVndkVersion,
+ )
+ } else if _, ok := m.linker.(*llndkHeadersDecorator); ok {
+ // ... and LL-NDK headers as well
+
+ if usingVendorSnapshot {
+ // If we're using the vendor snapshot, avoid providing
+ // the boardVndkVersion. This requires that the vendor
+ // snapshot provide the headers instead, which happens
+ // below as a snapshot prebuilt.
+ vendorVariants = append(vendorVariants,
+ platformVndkVersion,
+ )
+ } else {
+ vendorVariants = append(vendorVariants,
+ platformVndkVersion,
+ boardVndkVersion,
+ )
+ }
+
+ productVariants = append(productVariants,
+ platformVndkVersion,
+ productVndkVersion,
+ )
+ } else if m.isSnapshotPrebuilt() {
+ // Make vendor variants only for the versions in BOARD_VNDK_VERSION and
+ // PRODUCT_EXTRA_VNDK_VERSIONS.
+ if snapshot, ok := m.linker.(interface {
+ version() string
+ }); ok {
+ if m.InstallInRecovery() {
+ recoveryVariantNeeded = true
+ } else if m.InstallInRamdisk() {
+ ramdiskVariantNeeded = true
+ } else {
+ vendorVariants = append(vendorVariants, snapshot.version())
+ }
+ } else {
+ mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
+ }
+ } else if m.HasVendorVariant() && !m.isVndkExt() {
+ // This will be available in /system, /vendor and /product
+ // or a /system directory that is available to vendor and product.
+ coreVariantNeeded = true
+
+ // We assume that modules under proprietary paths are compatible for
+ // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
+ // PLATFORM_VNDK_VERSION.
+ if isVendorProprietaryModule(mctx) {
+ vendorVariants = append(vendorVariants, boardVndkVersion)
+ } else {
+ vendorVariants = append(vendorVariants, platformVndkVersion)
+ }
+
+ // vendor_available modules are also available to /product.
+ productVariants = append(productVariants, platformVndkVersion)
+ // VNDK is always PLATFORM_VNDK_VERSION
+ if !m.IsVndk() {
+ productVariants = append(productVariants, productVndkVersion)
+ }
+ } else if vendorSpecific && String(m.Properties.Sdk_version) == "" {
+ // This will be available in /vendor (or /odm) only
+
+ // kernel_headers is a special module type whose exported headers
+ // are coming from DeviceKernelHeaders() which is always vendor
+ // dependent. They'll always have both vendor variants.
+ // For other modules, we assume that modules under proprietary
+ // paths are compatible for BOARD_VNDK_VERSION. The other modules
+ // are regarded as AOSP, which is PLATFORM_VNDK_VERSION.
+ if _, ok := m.linker.(*kernelHeadersDecorator); ok {
+ vendorVariants = append(vendorVariants,
+ platformVndkVersion,
+ boardVndkVersion,
+ )
+ } else if isVendorProprietaryModule(mctx) {
+ vendorVariants = append(vendorVariants, boardVndkVersion)
+ } else {
+ vendorVariants = append(vendorVariants, platformVndkVersion)
+ }
+ } else {
+ // This is either in /system (or similar: /data), or is a
+ // modules built with the NDK. Modules built with the NDK
+ // will be restricted using the existing link type checks.
+ coreVariantNeeded = true
+ }
+
+ if boardVndkVersion != "" && productVndkVersion != "" {
+ if coreVariantNeeded && productSpecific && String(m.Properties.Sdk_version) == "" {
+ // The module has "product_specific: true" that does not create core variant.
+ coreVariantNeeded = false
+ productVariants = append(productVariants, productVndkVersion)
+ }
+ } else {
+ // Unless PRODUCT_PRODUCT_VNDK_VERSION is set, product partition has no
+ // restriction to use system libs.
+ // No product variants defined in this case.
+ productVariants = []string{}
+ }
+
+ if Bool(m.Properties.Ramdisk_available) {
+ ramdiskVariantNeeded = true
+ }
+
+ if m.ModuleBase.InstallInRamdisk() {
+ ramdiskVariantNeeded = true
+ coreVariantNeeded = false
+ }
+
+ if Bool(m.Properties.Recovery_available) {
+ recoveryVariantNeeded = true
+ }
+
+ if m.ModuleBase.InstallInRecovery() {
+ recoveryVariantNeeded = true
+ coreVariantNeeded = false
+ }
+
+ // If using a snapshot, the recovery variant under AOSP directories is not needed,
+ // except for kernel headers, which needs all variants.
+ if _, ok := m.linker.(*kernelHeadersDecorator); !ok &&
+ !m.isSnapshotPrebuilt() &&
+ usingRecoverySnapshot &&
+ !isRecoveryProprietaryModule(mctx) {
+ recoveryVariantNeeded = false
+ }
+ if _, ok := m.linker.(*kernelHeadersDecorator); !ok &&
+ !m.isSnapshotPrebuilt() &&
+ usingRamdiskSnapshot &&
+ !isRamdiskProprietaryModule(mctx) {
+ ramdiskVariantNeeded = false
+ }
+
+ for _, variant := range android.FirstUniqueStrings(vendorVariants) {
+ m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, VendorVariationPrefix+variant)
+ }
+
+ for _, variant := range android.FirstUniqueStrings(productVariants) {
+ m.Properties.ExtraVariants = append(m.Properties.ExtraVariants, ProductVariationPrefix+variant)
+ }
+
+ m.Properties.RamdiskVariantNeeded = ramdiskVariantNeeded
+ m.Properties.RecoveryVariantNeeded = recoveryVariantNeeded
+ m.Properties.CoreVariantNeeded = coreVariantNeeded
+
+ // Disable the module if no variants are needed.
+ if !ramdiskVariantNeeded &&
+ !recoveryVariantNeeded &&
+ !coreVariantNeeded &&
+ len(m.Properties.ExtraVariants) == 0 {
+ m.Disable()
+ }
+}
+
+func (c *Module) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+ return c.Properties.CoreVariantNeeded
+}
+
+func (c *Module) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return c.Properties.RamdiskVariantNeeded
+}
+
+func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
+ return c.Properties.RecoveryVariantNeeded
+}
+
+func (c *Module) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+ return c.Properties.ExtraVariants
+}
+
+func (c *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) {
+ m := module.(*Module)
+ if variant == android.RamdiskVariation {
+ m.MakeAsPlatform()
+ } else if variant == android.RecoveryVariation {
+ m.MakeAsPlatform()
+ squashRecoverySrcs(m)
+ } else if strings.HasPrefix(variant, VendorVariationPrefix) {
+ m.Properties.ImageVariationPrefix = VendorVariationPrefix
+ m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
+ squashVendorSrcs(m)
+
+ // Makefile shouldn't know vendor modules other than BOARD_VNDK_VERSION.
+ // Hide other vendor variants to avoid collision.
+ vndkVersion := ctx.DeviceConfig().VndkVersion()
+ if vndkVersion != "current" && vndkVersion != "" && vndkVersion != m.Properties.VndkVersion {
+ m.Properties.HideFromMake = true
+ m.SkipInstall()
+ }
+ } else if strings.HasPrefix(variant, ProductVariationPrefix) {
+ m.Properties.ImageVariationPrefix = ProductVariationPrefix
+ m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
+ squashVendorSrcs(m)
+ }
+}
diff --git a/cc/library.go b/cc/library.go
index 3deb173..147865b 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1073,9 +1073,14 @@
func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objects, fileName string, soFile android.Path) {
if library.shouldCreateSourceAbiDump(ctx) {
- vndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
- if ver := ctx.DeviceConfig().VndkVersion(); ver != "" && ver != "current" {
- vndkVersion = ver
+ var vndkVersion string
+
+ if ctx.useVndk() {
+ // For modules linking against vndk, follow its vndk version
+ vndkVersion = ctx.Module().(*Module).VndkVersion()
+ } else {
+ // Regard the other modules as PLATFORM_VNDK_VERSION
+ vndkVersion = ctx.DeviceConfig().PlatformVndkVersion()
}
exportIncludeDirs := library.flagExporter.exportedIncludes(ctx)
@@ -1560,9 +1565,8 @@
func VersionVariantAvailable(module interface {
Host() bool
InRamdisk() bool
- InRecovery() bool
}) bool {
- return !module.Host() && !module.InRamdisk() && !module.InRecovery()
+ return !module.Host() && !module.InRamdisk()
}
// VersionMutator splits a module into the mandatory non-stubs variant
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 7ff20f4..19f5641 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -116,6 +116,7 @@
srcDir := android.PathForModuleSrc(ctx, srcHeaderDir)
srcFiles := ctx.GlobFiles(filepath.Join(srcDir.String(), "**/*.h"), nil)
+ var depPaths []android.Path
var installPaths []android.WritablePath
for _, header := range srcFiles {
headerDir := filepath.Dir(header.String())
@@ -126,9 +127,14 @@
continue
}
- installPaths = append(installPaths, outDir.Join(ctx, relHeaderDir, header.Base()))
+ outputPath := outDir.Join(ctx, relHeaderDir, header.Base())
+ depPaths = append(depPaths, outputPath)
+ installPaths = append(installPaths, outputPath)
}
+ // Add the processed, exported headers so that they can be collected in
+ // a snapshot later, if necessary.
+ stub.addExportedGeneratedHeaders(depPaths...)
return processHeadersWithVersioner(ctx, srcDir, outDir, srcFiles, installPaths)
}
@@ -225,6 +231,8 @@
func llndkHeadersFactory() android.Module {
module, library := NewLibrary(android.DeviceSupported)
library.HeaderOnly()
+ module.stl = nil
+ module.sanitize = nil
decorator := &llndkHeadersDecorator{
libraryDecorator: library,
diff --git a/cc/lto.go b/cc/lto.go
index 4489fc7..0ac3ccc 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -16,6 +16,8 @@
import (
"android/soong/android"
+ "android/soong/cc/config"
+ "strings"
)
// LTO (link-time optimization) allows the compiler to optimize and generate
@@ -89,7 +91,13 @@
if lto.LTO() {
var ltoFlag string
if Bool(lto.Properties.Lto.Thin) {
- ltoFlag = "-flto=thin -fsplit-lto-unit"
+ // TODO(b/129607781) sdclang does not currently support
+ // the "-fsplit-lto-unit" option
+ if flags.Sdclang && !strings.Contains(config.SDClangPath, "9.0") {
+ ltoFlag = "-flto=thin"
+ } else {
+ ltoFlag = "-flto=thin -fsplit-lto-unit"
+ }
} else {
ltoFlag = "-flto"
}
diff --git a/cc/makevars.go b/cc/makevars.go
index 0f9f4c1..3c8c355 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -17,6 +17,7 @@
import (
"fmt"
"sort"
+ "strconv"
"strings"
"sync"
@@ -71,6 +72,7 @@
}
func makeVarsProvider(ctx android.MakeVarsContext) {
+ sdclangMakeVars(ctx)
vendorPublicLibraries := vendorPublicLibraries(ctx.Config())
ctx.Strict("LLVM_RELEASE_VERSION", "${config.ClangShortVersion}")
@@ -100,6 +102,8 @@
ctx.Strict("NDK_PREBUILT_SHARED_LIBRARIES", strings.Join(ndkPrebuiltSharedLibs, " "))
ctx.Strict("BOARD_VNDK_VERSION", ctx.DeviceConfig().VndkVersion())
+ ctx.Strict("RECOVERY_SNAPSHOT_VERSION", ctx.DeviceConfig().RecoverySnapshotVersion())
+ ctx.Strict("RAMDISK_SNAPSHOT_VERSION", ctx.DeviceConfig().RamdiskSnapshotVersion())
// Filter vendor_public_library that are exported to make
exportedVendorPublicLibraries := []string{}
@@ -190,6 +194,17 @@
}
}
+func sdclangMakeVars(ctx android.MakeVarsContext) {
+ if config.ForceSDClangOff {
+ ctx.Strict("FORCE_SDCLANG_OFF", strconv.FormatBool(config.ForceSDClangOff))
+ }
+ if config.SDClang {
+ ctx.Strict("SDCLANG", strconv.FormatBool(config.SDClang))
+ }
+ ctx.Strict("SDCLANG_PATH", "${config.SDClangBin}")
+ ctx.Strict("SDCLANG_COMMON_FLAGS", "${config.SDClangFlags}")
+}
+
func makeVarsToolchain(ctx android.MakeVarsContext, secondPrefix string,
target android.Target) {
var typePrefix string
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 463a02a..54020e8 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -61,9 +61,7 @@
cfiAsflags = []string{"-flto", "-fvisibility=default"}
cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi",
"-Wl,-plugin-opt,O1"}
- cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map"
- cfiStaticLibsMutex sync.Mutex
- hwasanStaticLibsMutex sync.Mutex
+ cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map"
intOverflowCflags = []string{"-fsanitize-blacklist=build/soong/cc/config/integer_overflow_blacklist.txt"}
@@ -303,6 +301,35 @@
}
}
+ if s.Integer_overflow == nil && ctx.Config().IntegerOverflowEnabledForPath(ctx.ModuleDir()) && ctx.Arch().ArchType == android.Arm64 {
+ s.Integer_overflow = boolPtr(true)
+ }
+
+ if ctx.Config().BoundSanitizerEnabledForPath(ctx.ModuleDir()) && ctx.Arch().ArchType == android.Arm64 {
+ s.Misc_undefined = append(s.Misc_undefined, "bounds")
+ }
+
+ if ctx.Config().BoundSanitizerDisabledForPath(ctx.ModuleDir()) && ctx.Arch().ArchType == android.Arm64 {
+ indx := indexList("bounds", s.Misc_undefined)
+ if (indexList("bounds", s.Misc_undefined) != -1) {
+ s.Misc_undefined = append(s.Misc_undefined[0:indx], s.Misc_undefined[indx+1:]...)
+ }
+ }
+
+ // Disable integer-overflow in exclude path
+ if ctx.Config().IntegerOverflowDisabledForPath(ctx.ModuleDir()) && ctx.Arch().ArchType == android.Arm64 {
+ indx := indexList("signed-integer-overflow", s.Misc_undefined)
+ if (indexList("signed-integer-overflow", s.Misc_undefined) != -1) {
+ s.Misc_undefined = append(s.Misc_undefined[0:indx], s.Misc_undefined[indx+1:]...)
+ }
+
+ indx = indexList("unsigned-integer-overflow", s.Misc_undefined)
+ if (indexList("unsigned-integer-overflow", s.Misc_undefined) != -1) {
+ s.Misc_undefined = append(s.Misc_undefined[0:indx], s.Misc_undefined[indx+1:]...)
+ }
+ s.Integer_overflow = nil
+ }
+
// Enable CFI for all components in the include paths (for Aarch64 only)
if s.Cfi == nil && ctx.Config().CFIEnabledForPath(ctx.ModuleDir()) && ctx.Arch().ArchType == android.Arm64 {
s.Cfi = boolPtr(true)
@@ -310,17 +337,24 @@
s.Diag.Cfi = boolPtr(true)
}
}
+ // Disable CFI for all component in the exclude path (for Aarch64 only)
+ if ctx.Config().CFIDisabledForPath(ctx.ModuleDir()) && ctx.Arch().ArchType == android.Arm64 {
+ s.Cfi = nil
+ if inList("cfi", ctx.Config().SanitizeDeviceDiag()) {
+ s.Diag.Cfi = nil
+ }
+ }
// CFI needs gold linker, and mips toolchain does not have one.
if !ctx.Config().EnableCFI() || ctx.Arch().ArchType == android.Mips || ctx.Arch().ArchType == android.Mips64 {
- s.Cfi = nil
- s.Diag.Cfi = nil
+ s.Cfi = boolPtr(false)
+ s.Diag.Cfi = boolPtr(false)
}
// Also disable CFI for arm32 until b/35157333 is fixed.
if ctx.Arch().ArchType == android.Arm {
- s.Cfi = nil
- s.Diag.Cfi = nil
+ s.Cfi = boolPtr(false)
+ s.Diag.Cfi = boolPtr(false)
}
// HWASan requires AArch64 hardware feature (top-byte-ignore).
@@ -335,14 +369,14 @@
// Also disable CFI if ASAN is enabled.
if Bool(s.Address) || Bool(s.Hwaddress) {
- s.Cfi = nil
- s.Diag.Cfi = nil
+ s.Cfi = boolPtr(false)
+ s.Diag.Cfi = boolPtr(false)
}
// Disable sanitizers that depend on the UBSan runtime for windows/darwin builds.
if !ctx.Os().Linux() {
- s.Cfi = nil
- s.Diag.Cfi = nil
+ s.Cfi = boolPtr(false)
+ s.Diag.Cfi = boolPtr(false)
s.Misc_undefined = nil
s.Undefined = nil
s.All_undefined = nil
@@ -351,14 +385,15 @@
// Also disable CFI for VNDK variants of components
if ctx.isVndk() && ctx.useVndk() {
- s.Cfi = nil
- s.Diag.Cfi = nil
- }
-
- // Also disable CFI if building against snapshot.
- vndkVersion := ctx.DeviceConfig().VndkVersion()
- if ctx.useVndk() && vndkVersion != "current" && vndkVersion != "" {
- s.Cfi = nil
+ if ctx.static() {
+ // Cfi variant for static vndk should be captured as vendor snapshot,
+ // so don't strictly disable Cfi.
+ s.Cfi = nil
+ s.Diag.Cfi = nil
+ } else {
+ s.Cfi = boolPtr(false)
+ s.Diag.Cfi = boolPtr(false)
+ }
}
// HWASan ramdisk (which is built from recovery) goes over some bootloader limit.
@@ -403,7 +438,7 @@
// TODO(b/131771163): CFI transiently depends on LTO, and thus Fuzzer is
// mutually incompatible.
if Bool(s.Fuzzer) {
- s.Cfi = nil
+ s.Cfi = boolPtr(false)
}
}
@@ -724,27 +759,64 @@
return ok && t.Library || t == reuseObjTag || t == objDepTag
}
+// Determines if the current module is a static library going to be captured
+// as vendor snapshot. Such modules must create both cfi and non-cfi variants,
+// except for ones which explicitly disable cfi.
+func needsCfiForVendorSnapshot(mctx android.TopDownMutatorContext) bool {
+ if isVendorProprietaryModule(mctx) {
+ return false
+ }
+
+ c := mctx.Module().(*Module)
+
+ if !c.inVendor() {
+ return false
+ }
+
+ if !c.static() {
+ return false
+ }
+
+ if c.Prebuilt() != nil {
+ return false
+ }
+
+ return c.sanitize != nil &&
+ !Bool(c.sanitize.Properties.Sanitize.Never) &&
+ !c.sanitize.isSanitizerExplicitlyDisabled(cfi)
+}
+
// Propagate sanitizer requirements down from binaries
func sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) {
return func(mctx android.TopDownMutatorContext) {
- if c, ok := mctx.Module().(*Module); ok && c.sanitize.isSanitizerEnabled(t) {
- mctx.WalkDeps(func(child, parent android.Module) bool {
- if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
- return false
- }
- if d, ok := child.(*Module); ok && d.sanitize != nil &&
- !Bool(d.sanitize.Properties.Sanitize.Never) &&
- !d.sanitize.isSanitizerExplicitlyDisabled(t) {
- if t == cfi || t == hwasan || t == scs {
- if d.static() {
+ if c, ok := mctx.Module().(*Module); ok {
+ enabled := c.sanitize.isSanitizerEnabled(t)
+ if t == cfi && needsCfiForVendorSnapshot(mctx) {
+ // We shouldn't change the result of isSanitizerEnabled(cfi) to correctly
+ // determine defaultVariation in sanitizerMutator below.
+ // Instead, just mark SanitizeDep to forcefully create cfi variant.
+ enabled = true
+ c.sanitize.Properties.SanitizeDep = true
+ }
+ if enabled {
+ mctx.WalkDeps(func(child, parent android.Module) bool {
+ if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
+ return false
+ }
+ if d, ok := child.(*Module); ok && d.sanitize != nil &&
+ !Bool(d.sanitize.Properties.Sanitize.Never) &&
+ !d.sanitize.isSanitizerExplicitlyDisabled(t) {
+ if t == cfi || t == hwasan || t == scs {
+ if d.static() {
+ d.sanitize.Properties.SanitizeDep = true
+ }
+ } else {
d.sanitize.Properties.SanitizeDep = true
}
- } else {
- d.sanitize.Properties.SanitizeDep = true
}
- }
- return true
- })
+ return true
+ })
+ }
} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok {
// If an APEX module includes a lib which is enabled for a sanitizer T, then
// the APEX module is also enabled for the same sanitizer type.
@@ -793,7 +865,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
}
@@ -1047,15 +1119,9 @@
// Export the static lib name to make
if c.static() && c.ExportedToMake() {
if t == cfi {
- appendStringSync(c.Name(), cfiStaticLibs(mctx.Config()), &cfiStaticLibsMutex)
+ cfiStaticLibs(mctx.Config()).add(c, c.Name())
} else if t == hwasan {
- if c.UseVndk() {
- appendStringSync(c.Name(), hwasanVendorStaticLibs(mctx.Config()),
- &hwasanStaticLibsMutex)
- } else {
- appendStringSync(c.Name(), hwasanStaticLibs(mctx.Config()),
- &hwasanStaticLibsMutex)
- }
+ hwasanStaticLibs(mctx.Config()).add(c, c.Name())
}
}
} else {
@@ -1080,38 +1146,96 @@
} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled(mctx, t.name()) {
// APEX modules fall here
mctx.CreateVariations(t.variationName())
+ } else if c, ok := mctx.Module().(*Module); ok {
+ // Check if it's a snapshot module supporting sanitizer
+ if s, ok := c.linker.(snapshotSanitizer); ok && s.isSanitizerEnabled(t) {
+ // Set default variation as above.
+ defaultVariation := t.variationName()
+ mctx.SetDefaultDependencyVariation(&defaultVariation)
+ modules := mctx.CreateVariations("", t.variationName())
+ modules[0].(*Module).linker.(snapshotSanitizer).setSanitizerVariation(t, false)
+ modules[1].(*Module).linker.(snapshotSanitizer).setSanitizerVariation(t, true)
+
+ // Export the static lib name to make
+ if c.static() && c.ExportedToMake() {
+ if t == cfi {
+ // use BaseModuleName which is the name for Make.
+ cfiStaticLibs(mctx.Config()).add(c, c.BaseModuleName())
+ }
+ }
+ }
+ }
+ }
+}
+
+type sanitizerStaticLibsMap struct {
+ // libsMap contains one list of modules per each image and each arch.
+ // e.g. libs[vendor]["arm"] contains arm modules installed to vendor
+ libsMap map[imageVariantType]map[string][]string
+ libsMapLock sync.Mutex
+ sanitizerType sanitizerType
+}
+
+func newSanitizerStaticLibsMap(t sanitizerType) *sanitizerStaticLibsMap {
+ return &sanitizerStaticLibsMap{
+ sanitizerType: t,
+ libsMap: make(map[imageVariantType]map[string][]string),
+ }
+}
+
+// Add the current module to sanitizer static libs maps
+// Each module should pass its exported name as names of Make and Soong can differ.
+func (s *sanitizerStaticLibsMap) add(c *Module, name string) {
+ image := c.getImageVariantType()
+ arch := c.Arch().ArchType.String()
+
+ s.libsMapLock.Lock()
+ defer s.libsMapLock.Unlock()
+
+ if _, ok := s.libsMap[image]; !ok {
+ s.libsMap[image] = make(map[string][]string)
+ }
+
+ s.libsMap[image][arch] = append(s.libsMap[image][arch], name)
+}
+
+// Exports makefile variables in the following format:
+// SOONG_{sanitizer}_{image}_{arch}_STATIC_LIBRARIES
+// e.g. SOONG_cfi_core_x86_STATIC_LIBRARIES
+// These are to be used by use_soong_sanitized_static_libraries.
+// See build/make/core/binary.mk for more details.
+func (s *sanitizerStaticLibsMap) exportToMake(ctx android.MakeVarsContext) {
+ for _, image := range android.SortedStringKeys(s.libsMap) {
+ archMap := s.libsMap[imageVariantType(image)]
+ for _, arch := range android.SortedStringKeys(archMap) {
+ libs := archMap[arch]
+ sort.Strings(libs)
+
+ key := fmt.Sprintf(
+ "SOONG_%s_%s_%s_STATIC_LIBRARIES",
+ s.sanitizerType.variationName(),
+ image, // already upper
+ arch)
+
+ ctx.Strict(key, strings.Join(libs, " "))
}
}
}
var cfiStaticLibsKey = android.NewOnceKey("cfiStaticLibs")
-func cfiStaticLibs(config android.Config) *[]string {
+func cfiStaticLibs(config android.Config) *sanitizerStaticLibsMap {
return config.Once(cfiStaticLibsKey, func() interface{} {
- return &[]string{}
- }).(*[]string)
+ return newSanitizerStaticLibsMap(cfi)
+ }).(*sanitizerStaticLibsMap)
}
var hwasanStaticLibsKey = android.NewOnceKey("hwasanStaticLibs")
-func hwasanStaticLibs(config android.Config) *[]string {
+func hwasanStaticLibs(config android.Config) *sanitizerStaticLibsMap {
return config.Once(hwasanStaticLibsKey, func() interface{} {
- return &[]string{}
- }).(*[]string)
-}
-
-var hwasanVendorStaticLibsKey = android.NewOnceKey("hwasanVendorStaticLibs")
-
-func hwasanVendorStaticLibs(config android.Config) *[]string {
- return config.Once(hwasanVendorStaticLibsKey, func() interface{} {
- return &[]string{}
- }).(*[]string)
-}
-
-func appendStringSync(item string, list *[]string, mutex *sync.Mutex) {
- mutex.Lock()
- *list = append(*list, item)
- mutex.Unlock()
+ return newSanitizerStaticLibsMap(hwasan)
+ }).(*sanitizerStaticLibsMap)
}
func enableMinimalRuntime(sanitize *sanitize) bool {
@@ -1141,17 +1265,9 @@
}
func cfiMakeVarsProvider(ctx android.MakeVarsContext) {
- cfiStaticLibs := cfiStaticLibs(ctx.Config())
- sort.Strings(*cfiStaticLibs)
- ctx.Strict("SOONG_CFI_STATIC_LIBRARIES", strings.Join(*cfiStaticLibs, " "))
+ cfiStaticLibs(ctx.Config()).exportToMake(ctx)
}
func hwasanMakeVarsProvider(ctx android.MakeVarsContext) {
- hwasanStaticLibs := hwasanStaticLibs(ctx.Config())
- sort.Strings(*hwasanStaticLibs)
- ctx.Strict("SOONG_HWASAN_STATIC_LIBRARIES", strings.Join(*hwasanStaticLibs, " "))
-
- hwasanVendorStaticLibs := hwasanVendorStaticLibs(ctx.Config())
- sort.Strings(*hwasanVendorStaticLibs)
- ctx.Strict("SOONG_HWASAN_VENDOR_STATIC_LIBRARIES", strings.Join(*hwasanVendorStaticLibs, " "))
+ hwasanStaticLibs(ctx.Config()).exportToMake(ctx)
}
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
new file mode 100644
index 0000000..5989dd8
--- /dev/null
+++ b/cc/snapshot_prebuilt.go
@@ -0,0 +1,1310 @@
+// Copyright 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 cc
+
+// This file defines snapshot prebuilt modules, e.g. vendor snapshot and recovery snapshot. Such
+// snapshot modules will override original source modules with setting BOARD_VNDK_VERSION, with
+// snapshot mutators and snapshot information maps which are also defined in this file.
+
+import (
+ "path/filepath"
+ "strings"
+ "sync"
+
+ "android/soong/android"
+
+ "github.com/google/blueprint/proptools"
+)
+
+// Defines the specifics of different images to which the snapshot process is applicable, e.g.,
+// vendor, recovery, ramdisk.
+type snapshotImage interface {
+ // Used to register callbacks with the build system.
+ init()
+
+ // Returns true if a snapshot should be generated for this image.
+ shouldGenerateSnapshot(ctx android.SingletonContext) bool
+
+ // 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, deviceConfig) returns true, then the module in dir
+ // will be built from sources.
+ isProprietaryPath(dir string, deviceConfig android.DeviceConfig) 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
+
+ // Returns the snapshotMap to be used for a given module and config, or nil if the
+ // module is not included in this image.
+ getSnapshotMap(m *Module, cfg android.Config) *snapshotMap
+
+ // Returns mutex used for mutual exclusion when updating the snapshot maps.
+ getMutex() *sync.Mutex
+
+ // For a given arch, a maps of which modules are included in this image.
+ suffixModules(config android.Config) map[string]bool
+
+ // Whether to add a given module to the suffix map.
+ shouldBeAddedToSuffixModules(m *Module) bool
+
+ // Returns true if the build is using a snapshot for this image.
+ isUsingSnapshot(cfg android.DeviceConfig) bool
+
+ // Whether to skip the module mutator for a module in a given context.
+ skipModuleMutator(ctx android.BottomUpMutatorContext) bool
+
+ // Whether to skip the source mutator for a given module.
+ skipSourceMutator(ctx android.BottomUpMutatorContext) bool
+
+ // Whether to exclude a given module from the directed snapshot or not.
+ // If the makefile variable DIRECTED_{IMAGE}_SNAPSHOT is true, directed snapshot is turned on,
+ // and only modules listed in {IMAGE}_SNAPSHOT_MODULES will be captured.
+ excludeFromDirectedSnapshot(cfg android.DeviceConfig, name string) bool
+}
+
+type vendorSnapshotImage struct{}
+type recoverySnapshotImage struct{}
+type ramdiskSnapshotImage struct{}
+
+type directoryMap map[string]bool
+
+var (
+ // Modules under following directories are ignored. They are OEM's and vendor's
+ // proprietary modules(device/, kernel/, vendor/, and hardware/).
+ defaultDirectoryExcludedMap = directoryMap{
+ "device": true,
+ "hardware": true,
+ "kernel": true,
+ "vendor": true,
+ // QC specific directories to be ignored
+ "disregard": true,
+ }
+
+ // Modules under following directories are included as they are in AOSP,
+ // although hardware/ and kernel/ are normally for vendor's own.
+ defaultDirectoryIncludedMap = directoryMap{
+ "kernel/configs": true,
+ "kernel/prebuilts": true,
+ "kernel/tests": true,
+ "hardware/interfaces": true,
+ "hardware/libhardware": true,
+ "hardware/libhardware_legacy": true,
+ "hardware/ril": true,
+ }
+)
+
+func (vendorSnapshotImage) 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)
+
+ android.RegisterSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton)
+}
+
+func (vendorSnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
+ // BOARD_VNDK_VERSION must be set to 'current' in order to generate a snapshot.
+ return ctx.DeviceConfig().VndkVersion() == "current"
+}
+
+func (vendorSnapshotImage) inImage(m *Module) func() bool {
+ return m.inVendor
+}
+
+func (vendorSnapshotImage) available(m *Module) *bool {
+ return m.VendorProperties.Vendor_available
+}
+
+func isDirectoryExcluded(dir string, excludedMap directoryMap, includedMap directoryMap) bool {
+ if dir == "." || dir == "/" {
+ return false
+ }
+ if includedMap[dir] {
+ return false
+ } else if excludedMap[dir] {
+ return true
+ } else if defaultDirectoryIncludedMap[dir] {
+ return false
+ } else if defaultDirectoryExcludedMap[dir] {
+ return true
+ } else {
+ return isDirectoryExcluded(filepath.Dir(dir), excludedMap, includedMap)
+ }
+}
+
+func (vendorSnapshotImage) isProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
+ return isDirectoryExcluded(dir, deviceConfig.VendorSnapshotDirsExcludedMap(), deviceConfig.VendorSnapshotDirsIncludedMap())
+}
+
+// vendor snapshot includes static/header libraries with vndk: {enabled: true}.
+func (vendorSnapshotImage) includeVndk() bool {
+ return true
+}
+
+func (vendorSnapshotImage) excludeFromSnapshot(m *Module) bool {
+ return m.ExcludeFromVendorSnapshot()
+}
+
+func (vendorSnapshotImage) getSnapshotMap(m *Module, cfg android.Config) *snapshotMap {
+ if lib, ok := m.linker.(libraryInterface); ok {
+ if lib.static() {
+ return vendorSnapshotStaticLibs(cfg)
+ } else if lib.shared() {
+ return vendorSnapshotSharedLibs(cfg)
+ } else {
+ // header
+ return vendorSnapshotHeaderLibs(cfg)
+ }
+ } else if m.binary() {
+ return vendorSnapshotBinaries(cfg)
+ } else if m.object() {
+ return vendorSnapshotObjects(cfg)
+ } else {
+ return nil
+ }
+}
+
+func (vendorSnapshotImage) getMutex() *sync.Mutex {
+ return &vendorSnapshotsLock
+}
+
+func (vendorSnapshotImage) suffixModules(config android.Config) map[string]bool {
+ return vendorSuffixModules(config)
+}
+
+func (vendorSnapshotImage) shouldBeAddedToSuffixModules(module *Module) bool {
+ // vendor suffix should be added to snapshots if the source module isn't vendor: true.
+ if module.SocSpecific() {
+ return false
+ }
+
+ // But we can't just check SocSpecific() since we already passed the image mutator.
+ // Check ramdisk and recovery to see if we are real "vendor: true" module.
+ ramdiskAvailable := module.InRamdisk() && !module.OnlyInRamdisk()
+ recoveryAvailable := module.InRecovery() && !module.OnlyInRecovery()
+
+ return !ramdiskAvailable && !recoveryAvailable
+}
+
+func (vendorSnapshotImage) isUsingSnapshot(cfg android.DeviceConfig) bool {
+ vndkVersion := cfg.VndkVersion()
+ return vndkVersion != "current" && vndkVersion != ""
+}
+
+func (vendorSnapshotImage) skipModuleMutator(ctx android.BottomUpMutatorContext) bool {
+ vndkVersion := ctx.DeviceConfig().VndkVersion()
+ module, ok := ctx.Module().(*Module)
+ return !ok || module.VndkVersion() != vndkVersion
+}
+
+func (vendorSnapshotImage) skipSourceMutator(ctx android.BottomUpMutatorContext) bool {
+ vndkVersion := ctx.DeviceConfig().VndkVersion()
+ module, ok := ctx.Module().(*Module)
+ if !ok {
+ return true
+ }
+ if module.VndkVersion() != vndkVersion {
+ return true
+ }
+ return false
+}
+
+// returns true iff a given module SHOULD BE EXCLUDED, false if included
+func (vendorSnapshotImage) excludeFromDirectedSnapshot(cfg android.DeviceConfig, name string) bool {
+ // If we're using full snapshot, not directed snapshot, capture every module
+ if !cfg.DirectedVendorSnapshot() {
+ return false
+ }
+ // Else, checks if name is in VENDOR_SNAPSHOT_MODULES.
+ return !cfg.VendorSnapshotModules()[name]
+}
+
+func (recoverySnapshotImage) 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 (recoverySnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
+ // RECOVERY_SNAPSHOT_VERSION must be set to 'current' in order to generate a
+ // snapshot.
+ return ctx.DeviceConfig().RecoverySnapshotVersion() == "current"
+}
+
+func (recoverySnapshotImage) inImage(m *Module) func() bool {
+ return m.InRecovery
+}
+
+func (recoverySnapshotImage) available(m *Module) *bool {
+ return m.Properties.Recovery_available
+}
+
+func (recoverySnapshotImage) isProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
+ return isDirectoryExcluded(dir, deviceConfig.RecoverySnapshotDirsExcludedMap(), deviceConfig.RecoverySnapshotDirsIncludedMap())
+}
+
+// recovery snapshot does NOT treat vndk specially.
+func (recoverySnapshotImage) includeVndk() bool {
+ return false
+}
+
+func (recoverySnapshotImage) excludeFromSnapshot(m *Module) bool {
+ return m.ExcludeFromRecoverySnapshot()
+}
+
+func (recoverySnapshotImage) getSnapshotMap(m *Module, cfg android.Config) *snapshotMap {
+ if lib, ok := m.linker.(libraryInterface); ok {
+ if lib.static() {
+ return recoverySnapshotStaticLibs(cfg)
+ } else if lib.shared() {
+ return recoverySnapshotSharedLibs(cfg)
+ } else {
+ // header
+ return recoverySnapshotHeaderLibs(cfg)
+ }
+ } else if m.binary() {
+ return recoverySnapshotBinaries(cfg)
+ } else if m.object() {
+ return recoverySnapshotObjects(cfg)
+ } else {
+ return nil
+ }
+}
+
+func (recoverySnapshotImage) getMutex() *sync.Mutex {
+ return &recoverySnapshotsLock
+}
+
+func (recoverySnapshotImage) suffixModules(config android.Config) map[string]bool {
+ return recoverySuffixModules(config)
+}
+
+func (recoverySnapshotImage) shouldBeAddedToSuffixModules(module *Module) bool {
+ return proptools.BoolDefault(module.Properties.Recovery_available, false)
+}
+
+func (recoverySnapshotImage) isUsingSnapshot(cfg android.DeviceConfig) bool {
+ recoverySnapshotVersion := cfg.RecoverySnapshotVersion()
+ return recoverySnapshotVersion != "current" && recoverySnapshotVersion != ""
+}
+
+func (recoverySnapshotImage) skipModuleMutator(ctx android.BottomUpMutatorContext) bool {
+ module, ok := ctx.Module().(*Module)
+ return !ok || !module.InRecovery()
+}
+
+func (recoverySnapshotImage) skipSourceMutator(ctx android.BottomUpMutatorContext) bool {
+ module, ok := ctx.Module().(*Module)
+ return !ok || !module.InRecovery()
+}
+
+func (recoverySnapshotImage) excludeFromDirectedSnapshot(cfg android.DeviceConfig, name string) bool {
+ // If we're using full snapshot, not directed snapshot, capture every module
+ if !cfg.DirectedRecoverySnapshot() {
+ return false
+ }
+ // Else, checks if name is in RECOVERY_SNAPSHOT_MODULES.
+ return !cfg.RecoverySnapshotModules()[name]
+}
+
+func (ramdiskSnapshotImage) init() {
+ android.RegisterSingletonType("ramdisk-snapshot", RamdiskSnapshotSingleton)
+ android.RegisterModuleType("ramdisk_snapshot_shared", RamdiskSnapshotSharedFactory)
+ android.RegisterModuleType("ramdisk_snapshot_static", RamdiskSnapshotStaticFactory)
+ android.RegisterModuleType("ramdisk_snapshot_header", RamdiskSnapshotHeaderFactory)
+ android.RegisterModuleType("ramdisk_snapshot_binary", RamdiskSnapshotBinaryFactory)
+ android.RegisterModuleType("ramdisk_snapshot_object", RamdiskSnapshotObjectFactory)
+}
+
+func (ramdiskSnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
+ // RAMDISK_SNAPSHOT_VERSION must be set to 'current' in order to generate a
+ // snapshot.
+ return ctx.DeviceConfig().RamdiskSnapshotVersion() == "current"
+}
+
+func (ramdiskSnapshotImage) inImage(m *Module) func() bool {
+ return m.InRamdisk
+}
+
+func (ramdiskSnapshotImage) available(m *Module) *bool {
+ return m.Properties.Ramdisk_available
+}
+
+func (ramdiskSnapshotImage) isProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
+ return isDirectoryExcluded(dir, nil, nil)
+}
+
+// ramdisk snapshot does NOT treat vndk specially.
+func (ramdiskSnapshotImage) includeVndk() bool {
+ return false
+}
+
+func (ramdiskSnapshotImage) excludeFromSnapshot(m *Module) bool {
+ return m.ExcludeFromRamdiskSnapshot()
+}
+
+func (ramdiskSnapshotImage) getSnapshotMap(m *Module, cfg android.Config) *snapshotMap {
+ if lib, ok := m.linker.(libraryInterface); ok {
+ if lib.static() {
+ return ramdiskSnapshotStaticLibs(cfg)
+ } else if lib.shared() {
+ return ramdiskSnapshotSharedLibs(cfg)
+ } else {
+ // header
+ return ramdiskSnapshotHeaderLibs(cfg)
+ }
+ } else if m.binary() {
+ return ramdiskSnapshotBinaries(cfg)
+ } else if m.object() {
+ return ramdiskSnapshotObjects(cfg)
+ } else {
+ return nil
+ }
+}
+
+func (ramdiskSnapshotImage) getMutex() *sync.Mutex {
+ return &ramdiskSnapshotsLock
+}
+
+func (ramdiskSnapshotImage) suffixModules(config android.Config) map[string]bool {
+ return ramdiskSuffixModules(config)
+}
+
+func (ramdiskSnapshotImage) shouldBeAddedToSuffixModules(module *Module) bool {
+ return proptools.BoolDefault(module.Properties.Ramdisk_available, false)
+}
+
+func (ramdiskSnapshotImage) isUsingSnapshot(cfg android.DeviceConfig) bool {
+ ramdiskSnapshotVersion := cfg.RamdiskSnapshotVersion()
+ return ramdiskSnapshotVersion != "current" && ramdiskSnapshotVersion != ""
+}
+
+func (ramdiskSnapshotImage) skipModuleMutator(ctx android.BottomUpMutatorContext) bool {
+ module, ok := ctx.Module().(*Module)
+ return !ok || !module.InRamdisk()
+}
+
+func (ramdiskSnapshotImage) skipSourceMutator(ctx android.BottomUpMutatorContext) bool {
+ module, ok := ctx.Module().(*Module)
+ return !ok || !module.InRamdisk()
+}
+
+func (ramdiskSnapshotImage) excludeFromDirectedSnapshot(cfg android.DeviceConfig, name string) bool {
+ // If we're using full snapshot, not directed snapshot, capture every module
+ if !cfg.DirectedRamdiskSnapshot() {
+ return false
+ }
+ // Else, checks if name is in RAMDSIK_SNAPSHOT_MODULES.
+ return !cfg.RamdiskSnapshotModules()[name]
+}
+
+var vendorSnapshotImageSingleton vendorSnapshotImage
+var recoverySnapshotImageSingleton recoverySnapshotImage
+var ramdiskSnapshotImageSingleton ramdiskSnapshotImage
+
+func init() {
+ vendorSnapshotImageSingleton.init()
+ recoverySnapshotImageSingleton.init()
+ ramdiskSnapshotImageSingleton.init()
+}
+
+const (
+ vendorSnapshotHeaderSuffix = ".vendor_header."
+ vendorSnapshotSharedSuffix = ".vendor_shared."
+ vendorSnapshotStaticSuffix = ".vendor_static."
+ vendorSnapshotBinarySuffix = ".vendor_binary."
+ vendorSnapshotObjectSuffix = ".vendor_object."
+)
+
+const (
+ recoverySnapshotHeaderSuffix = ".recovery_header."
+ recoverySnapshotSharedSuffix = ".recovery_shared."
+ recoverySnapshotStaticSuffix = ".recovery_static."
+ recoverySnapshotBinarySuffix = ".recovery_binary."
+ recoverySnapshotObjectSuffix = ".recovery_object."
+)
+
+const (
+ ramdiskSnapshotHeaderSuffix = ".ramdisk_header."
+ ramdiskSnapshotSharedSuffix = ".ramdisk_shared."
+ ramdiskSnapshotStaticSuffix = ".ramdisk_static."
+ ramdiskSnapshotBinarySuffix = ".ramdisk_binary."
+ ramdiskSnapshotObjectSuffix = ".ramdisk_object."
+)
+
+var (
+ vendorSnapshotsLock sync.Mutex
+ vendorSuffixModulesKey = android.NewOnceKey("vendorSuffixModules")
+ vendorSnapshotHeaderLibsKey = android.NewOnceKey("vendorSnapshotHeaderLibs")
+ vendorSnapshotStaticLibsKey = android.NewOnceKey("vendorSnapshotStaticLibs")
+ vendorSnapshotSharedLibsKey = android.NewOnceKey("vendorSnapshotSharedLibs")
+ vendorSnapshotBinariesKey = android.NewOnceKey("vendorSnapshotBinaries")
+ vendorSnapshotObjectsKey = android.NewOnceKey("vendorSnapshotObjects")
+)
+
+var (
+ recoverySnapshotsLock sync.Mutex
+ recoverySuffixModulesKey = android.NewOnceKey("recoverySuffixModules")
+ recoverySnapshotHeaderLibsKey = android.NewOnceKey("recoverySnapshotHeaderLibs")
+ recoverySnapshotStaticLibsKey = android.NewOnceKey("recoverySnapshotStaticLibs")
+ recoverySnapshotSharedLibsKey = android.NewOnceKey("recoverySnapshotSharedLibs")
+ recoverySnapshotBinariesKey = android.NewOnceKey("recoverySnapshotBinaries")
+ recoverySnapshotObjectsKey = android.NewOnceKey("recoverySnapshotObjects")
+)
+var (
+ ramdiskSnapshotsLock sync.Mutex
+ ramdiskSuffixModulesKey = android.NewOnceKey("ramdiskSuffixModules")
+ ramdiskSnapshotHeaderLibsKey = android.NewOnceKey("ramdiskSnapshotHeaderLibs")
+ ramdiskSnapshotStaticLibsKey = android.NewOnceKey("ramdiskSnapshotStaticLibs")
+ ramdiskSnapshotSharedLibsKey = android.NewOnceKey("ramdiskSnapshotSharedLibs")
+ ramdiskSnapshotBinariesKey = android.NewOnceKey("ramdiskSnapshotBinaries")
+ ramdiskSnapshotObjectsKey = android.NewOnceKey("ramdiskSnapshotObjects")
+)
+
+// vendorSuffixModules holds names of modules whose vendor variants should have the vendor suffix.
+// This is determined by source modules, and then this will be used when exporting snapshot modules
+// to Makefile.
+//
+// For example, if libbase has "vendor_available: true", the name of core variant will be "libbase"
+// while the name of vendor variant will be "libbase.vendor". In such cases, the vendor snapshot of
+// "libbase" should be exported with the name "libbase.vendor".
+//
+// Refer to VendorSnapshotSourceMutator and makeLibName which use this.
+func vendorSuffixModules(config android.Config) map[string]bool {
+ return config.Once(vendorSuffixModulesKey, func() interface{} {
+ return make(map[string]bool)
+ }).(map[string]bool)
+}
+
+// these are vendor snapshot maps holding names of vendor snapshot modules
+func vendorSnapshotHeaderLibs(config android.Config) *snapshotMap {
+ return config.Once(vendorSnapshotHeaderLibsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func vendorSnapshotSharedLibs(config android.Config) *snapshotMap {
+ return config.Once(vendorSnapshotSharedLibsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func vendorSnapshotStaticLibs(config android.Config) *snapshotMap {
+ return config.Once(vendorSnapshotStaticLibsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func vendorSnapshotBinaries(config android.Config) *snapshotMap {
+ return config.Once(vendorSnapshotBinariesKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func vendorSnapshotObjects(config android.Config) *snapshotMap {
+ return config.Once(vendorSnapshotObjectsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func recoverySuffixModules(config android.Config) map[string]bool {
+ return config.Once(recoverySuffixModulesKey, func() interface{} {
+ return make(map[string]bool)
+ }).(map[string]bool)
+}
+
+func recoverySnapshotHeaderLibs(config android.Config) *snapshotMap {
+ return config.Once(recoverySnapshotHeaderLibsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func recoverySnapshotSharedLibs(config android.Config) *snapshotMap {
+ return config.Once(recoverySnapshotSharedLibsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func recoverySnapshotStaticLibs(config android.Config) *snapshotMap {
+ return config.Once(recoverySnapshotStaticLibsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func recoverySnapshotBinaries(config android.Config) *snapshotMap {
+ return config.Once(recoverySnapshotBinariesKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func recoverySnapshotObjects(config android.Config) *snapshotMap {
+ return config.Once(recoverySnapshotObjectsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func ramdiskSuffixModules(config android.Config) map[string]bool {
+ return config.Once(ramdiskSuffixModulesKey, func() interface{} {
+ return make(map[string]bool)
+ }).(map[string]bool)
+}
+
+func ramdiskSnapshotHeaderLibs(config android.Config) *snapshotMap {
+ return config.Once(ramdiskSnapshotHeaderLibsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func ramdiskSnapshotSharedLibs(config android.Config) *snapshotMap {
+ return config.Once(ramdiskSnapshotSharedLibsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func ramdiskSnapshotStaticLibs(config android.Config) *snapshotMap {
+ return config.Once(ramdiskSnapshotStaticLibsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func ramdiskSnapshotBinaries(config android.Config) *snapshotMap {
+ return config.Once(ramdiskSnapshotBinariesKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+func ramdiskSnapshotObjects(config android.Config) *snapshotMap {
+ return config.Once(ramdiskSnapshotObjectsKey, func() interface{} {
+ return newSnapshotMap()
+ }).(*snapshotMap)
+}
+
+type baseSnapshotDecoratorProperties struct {
+ // snapshot version.
+ Version string
+
+ // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64')
+ Target_arch string
+
+ // Suffix to be added to the module name, e.g., vendor_shared,
+ // recovery_shared, etc.
+ Module_suffix string
+}
+
+// baseSnapshotDecorator provides common basic functions for all snapshot modules, such as snapshot
+// version, snapshot arch, etc. It also adds a special suffix to Soong module name, so it doesn't
+// collide with source modules. e.g. the following example module,
+//
+// vendor_snapshot_static {
+// name: "libbase",
+// arch: "arm64",
+// version: 30,
+// ...
+// }
+//
+// will be seen as "libbase.vendor_static.30.arm64" by Soong.
+type baseSnapshotDecorator struct {
+ baseProperties baseSnapshotDecoratorProperties
+}
+
+func (p *baseSnapshotDecorator) Name(name string) string {
+ return name + p.NameSuffix()
+}
+
+func (p *baseSnapshotDecorator) NameSuffix() string {
+ versionSuffix := p.version()
+ if p.arch() != "" {
+ versionSuffix += "." + p.arch()
+ }
+
+ return p.baseProperties.Module_suffix + versionSuffix
+}
+
+func (p *baseSnapshotDecorator) version() string {
+ return p.baseProperties.Version
+}
+
+func (p *baseSnapshotDecorator) arch() string {
+ return p.baseProperties.Target_arch
+}
+
+func (p *baseSnapshotDecorator) module_suffix() string {
+ return p.baseProperties.Module_suffix
+}
+
+func (p *baseSnapshotDecorator) isSnapshotPrebuilt() bool {
+ return true
+}
+
+// Call this with a module suffix after creating a snapshot module, such as
+// vendorSnapshotSharedSuffix, recoverySnapshotBinarySuffix, etc.
+func (p *baseSnapshotDecorator) init(m *Module, suffix string) {
+ p.baseProperties.Module_suffix = suffix
+ m.AddProperties(&p.baseProperties)
+ android.AddLoadHook(m, func(ctx android.LoadHookContext) {
+ vendorSnapshotLoadHook(ctx, p)
+ })
+}
+
+// vendorSnapshotLoadHook disables snapshots if it's not BOARD_VNDK_VERSION.
+// As vendor snapshot is only for vendor, such modules won't be used at all.
+func vendorSnapshotLoadHook(ctx android.LoadHookContext, p *baseSnapshotDecorator) {
+ if p.version() != ctx.DeviceConfig().VndkVersion() {
+ ctx.Module().Disable()
+ return
+ }
+}
+
+//
+// Module definitions for snapshots of libraries (shared, static, header).
+//
+// Modules (vendor|recovery)_snapshot_(shared|static|header) are defined here. Shared libraries and
+// static libraries have their prebuilt library files (.so for shared, .a for static) as their src,
+// which can be installed or linked against. Also they export flags needed when linked, such as
+// include directories, c flags, sanitize dependency information, etc.
+//
+// These modules are auto-generated by development/vendor_snapshot/update.py.
+type snapshotLibraryProperties struct {
+ // Prebuilt file for each arch.
+ Src *string `android:"arch_variant"`
+
+ // list of directories that will be added to the include path (using -I).
+ Export_include_dirs []string `android:"arch_variant"`
+
+ // list of directories that will be added to the system path (using -isystem).
+ Export_system_include_dirs []string `android:"arch_variant"`
+
+ // list of flags that will be used for any module that links against this module.
+ Export_flags []string `android:"arch_variant"`
+
+ // Whether this prebuilt needs to depend on sanitize ubsan runtime or not.
+ Sanitize_ubsan_dep *bool `android:"arch_variant"`
+
+ // Whether this prebuilt needs to depend on sanitize minimal runtime or not.
+ Sanitize_minimal_dep *bool `android:"arch_variant"`
+
+ // TODO(b/181815415) remove Is_llndk when possible
+ // Whether this prebuilt is a snapshot of an llndk library.
+ Is_llndk *bool
+}
+
+type snapshotSanitizer interface {
+ isSanitizerEnabled(t sanitizerType) bool
+ setSanitizerVariation(t sanitizerType, enabled bool)
+}
+
+type snapshotLibraryDecorator struct {
+ baseSnapshotDecorator
+ *libraryDecorator
+ properties snapshotLibraryProperties
+ sanitizerProperties struct {
+ CfiEnabled bool `blueprint:"mutated"`
+
+ // Library flags for cfi variant.
+ Cfi snapshotLibraryProperties `android:"arch_variant"`
+ }
+ androidMkSuffix string
+}
+
+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 *snapshotLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
+ arches := config.Arches()
+ if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
+ return false
+ }
+ if !p.header() && p.properties.Src == nil {
+ return false
+ }
+ return true
+}
+
+// cc modules' link functions are to link compiled objects into final binaries.
+// As snapshots are prebuilts, this just returns the prebuilt binary after doing things which are
+// done by normal library decorator, e.g. exporting flags.
+func (p *snapshotLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path {
+ m := ctx.Module().(*Module)
+
+ if m.inVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] {
+ p.androidMkSuffix = vendorSuffix
+ } else if m.InRecovery() && recoverySuffixModules(ctx.Config())[m.BaseModuleName()] {
+ p.androidMkSuffix = recoverySuffix
+ } else if m.InRamdisk() && ramdiskSuffixModules(ctx.Config())[m.BaseModuleName()] {
+ p.androidMkSuffix = ramdiskSuffix
+ }
+ if p.header() {
+ return p.libraryDecorator.link(ctx, flags, deps, objs)
+ }
+
+ if p.sanitizerProperties.CfiEnabled {
+ p.properties = p.sanitizerProperties.Cfi
+ }
+
+ if !p.matchesWithDevice(ctx.DeviceConfig()) {
+ return nil
+ }
+
+ p.libraryDecorator.reexportDirs(android.PathsForModuleSrc(ctx, p.properties.Export_include_dirs)...)
+ p.libraryDecorator.reexportSystemDirs(android.PathsForModuleSrc(ctx, p.properties.Export_system_include_dirs)...)
+ p.libraryDecorator.reexportFlags(p.properties.Export_flags...)
+
+ in := android.PathForModuleSrc(ctx, *p.properties.Src)
+ p.unstrippedOutputFile = in
+
+ if p.shared() {
+ libName := in.Base()
+ builderFlags := flagsToBuilderFlags(flags)
+
+ // Optimize out relinking against shared libraries whose interface hasn't changed by
+ // depending on a table of contents file instead of the library itself.
+ tocFile := android.PathForModuleOut(ctx, libName+".toc")
+ p.tocFile = android.OptionalPathForPath(tocFile)
+ TransformSharedObjectToToc(ctx, in, tocFile, builderFlags)
+ }
+
+ return in
+}
+
+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 *snapshotLibraryDecorator) nativeCoverage() bool {
+ return false
+}
+
+func (p *snapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) bool {
+ switch t {
+ case cfi:
+ return p.sanitizerProperties.Cfi.Src != nil
+ default:
+ return false
+ }
+}
+
+func (p *snapshotLibraryDecorator) setSanitizerVariation(t sanitizerType, enabled bool) {
+ if !enabled {
+ return
+ }
+ switch t {
+ case cfi:
+ p.sanitizerProperties.CfiEnabled = true
+ default:
+ return
+ }
+}
+
+// TODO(b/181815415) remove isLlndk() when possible
+func (p *snapshotLibraryDecorator) isLlndk() bool {
+ return Bool(p.properties.Is_llndk)
+}
+
+func snapshotLibraryFactory(suffix string) (*Module, *snapshotLibraryDecorator) {
+ module, library := NewLibrary(android.DeviceSupported)
+
+ module.stl = nil
+ module.sanitize = nil
+ library.StripProperties.Strip.None = BoolPtr(true)
+
+ prebuilt := &snapshotLibraryDecorator{
+ libraryDecorator: library,
+ }
+
+ prebuilt.baseLinker.Properties.No_libcrt = BoolPtr(true)
+ prebuilt.baseLinker.Properties.Nocrt = BoolPtr(true)
+
+ // Prevent default system libs (libc, libm, and libdl) from being linked
+ if prebuilt.baseLinker.Properties.System_shared_libs == nil {
+ prebuilt.baseLinker.Properties.System_shared_libs = []string{}
+ }
+
+ module.compiler = nil
+ module.linker = prebuilt
+ module.installer = prebuilt
+
+ prebuilt.init(module, suffix)
+ module.AddProperties(
+ &prebuilt.properties,
+ &prebuilt.sanitizerProperties,
+ )
+
+ return module, prebuilt
+}
+
+// vendor_snapshot_shared is a special prebuilt shared library which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_shared
+// overrides the vendor variant of the cc shared library with the same name, if BOARD_VNDK_VERSION
+// is set.
+func VendorSnapshotSharedFactory() android.Module {
+ module, prebuilt := snapshotLibraryFactory(vendorSnapshotSharedSuffix)
+ prebuilt.libraryDecorator.BuildOnlyShared()
+ return module.Init()
+}
+
+// recovery_snapshot_shared is a special prebuilt shared library which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of recovery snapshot, recovery_snapshot_shared
+// overrides the recovery variant of the cc shared library with the same name, if BOARD_VNDK_VERSION
+// is set.
+func RecoverySnapshotSharedFactory() android.Module {
+ module, prebuilt := snapshotLibraryFactory(recoverySnapshotSharedSuffix)
+ prebuilt.libraryDecorator.BuildOnlyShared()
+ return module.Init()
+}
+
+// ramdisk_snapshot_shared is a special prebuilt shared library which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of ramdisk snapshot, ramdisk_snapshot_shared
+// overrides the ramdisk variant of the cc shared library with the same name, if BOARD_VNDK_VERSION
+// is set.
+func RamdiskSnapshotSharedFactory() android.Module {
+ module, prebuilt := snapshotLibraryFactory(ramdiskSnapshotSharedSuffix)
+ prebuilt.libraryDecorator.BuildOnlyShared()
+ return module.Init()
+}
+
+// vendor_snapshot_static is a special prebuilt static library which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_static
+// overrides the vendor variant of the cc static library with the same name, if BOARD_VNDK_VERSION
+// is set.
+func VendorSnapshotStaticFactory() android.Module {
+ module, prebuilt := snapshotLibraryFactory(vendorSnapshotStaticSuffix)
+ prebuilt.libraryDecorator.BuildOnlyStatic()
+ return module.Init()
+}
+
+// recovery_snapshot_static is a special prebuilt static library which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of recovery snapshot, recovery_snapshot_static
+// overrides the recovery variant of the cc static library with the same name, if BOARD_VNDK_VERSION
+// is set.
+func RecoverySnapshotStaticFactory() android.Module {
+ module, prebuilt := snapshotLibraryFactory(recoverySnapshotStaticSuffix)
+ prebuilt.libraryDecorator.BuildOnlyStatic()
+ return module.Init()
+}
+
+// ramdisk_snapshot_static is a special prebuilt static library which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of ramdisk snapshot, ramdisk_snapshot_static
+// overrides the ramdisk variant of the cc static library with the same name, if BOARD_VNDK_VERSION
+// is set.
+func RamdiskSnapshotStaticFactory() android.Module {
+ module, prebuilt := snapshotLibraryFactory(ramdiskSnapshotStaticSuffix)
+ prebuilt.libraryDecorator.BuildOnlyStatic()
+ return module.Init()
+}
+
+// vendor_snapshot_header is a special header library which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_header
+// overrides the vendor variant of the cc header library with the same name, if BOARD_VNDK_VERSION
+// is set.
+func VendorSnapshotHeaderFactory() android.Module {
+ module, prebuilt := snapshotLibraryFactory(vendorSnapshotHeaderSuffix)
+ prebuilt.libraryDecorator.HeaderOnly()
+ return module.Init()
+}
+
+// recovery_snapshot_header is a special header library which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of recovery snapshot, recovery_snapshot_header
+// overrides the recovery variant of the cc header library with the same name, if BOARD_VNDK_VERSION
+// is set.
+func RecoverySnapshotHeaderFactory() android.Module {
+ module, prebuilt := snapshotLibraryFactory(recoverySnapshotHeaderSuffix)
+ prebuilt.libraryDecorator.HeaderOnly()
+ return module.Init()
+}
+
+// ramdisk_snapshot_header is a special header library which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of ramdisk snapshot, ramdisk_snapshot_header
+// overrides the ramdisk variant of the cc header library with the same name, if BOARD_VNDK_VERSION
+// is set.
+func RamdiskSnapshotHeaderFactory() android.Module {
+ module, prebuilt := snapshotLibraryFactory(ramdiskSnapshotHeaderSuffix)
+ prebuilt.libraryDecorator.HeaderOnly()
+ return module.Init()
+}
+
+var _ snapshotSanitizer = (*snapshotLibraryDecorator)(nil)
+
+//
+// Module definitions for snapshots of executable binaries.
+//
+// Modules (vendor|recovery)_snapshot_binary are defined here. They have their prebuilt executable
+// binaries (e.g. toybox, sh) as their src, which can be installed.
+//
+// These modules are auto-generated by development/vendor_snapshot/update.py.
+type snapshotBinaryProperties struct {
+ // Prebuilt file for each arch.
+ Src *string `android:"arch_variant"`
+}
+
+type snapshotBinaryDecorator struct {
+ baseSnapshotDecorator
+ *binaryDecorator
+ properties snapshotBinaryProperties
+ androidMkSuffix string
+}
+
+func (p *snapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
+ if config.DeviceArch() != p.arch() {
+ return false
+ }
+ if p.properties.Src == nil {
+ return false
+ }
+ return true
+}
+
+// cc modules' link functions are to link compiled objects into final binaries.
+// As snapshots are prebuilts, this just returns the prebuilt binary
+func (p *snapshotBinaryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path {
+ if !p.matchesWithDevice(ctx.DeviceConfig()) {
+ return nil
+ }
+
+ in := android.PathForModuleSrc(ctx, *p.properties.Src)
+ p.unstrippedOutputFile = in
+ binName := in.Base()
+
+ m := ctx.Module().(*Module)
+ if m.inVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] {
+ p.androidMkSuffix = vendorSuffix
+ } else if m.InRecovery() && recoverySuffixModules(ctx.Config())[m.BaseModuleName()] {
+ p.androidMkSuffix = recoverySuffix
+ } else if m.InRamdisk() && ramdiskSuffixModules(ctx.Config())[m.BaseModuleName()] {
+ p.androidMkSuffix = ramdiskSuffix
+
+ }
+
+ // use cpExecutable to make it executable
+ outputFile := android.PathForModuleOut(ctx, binName)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.CpExecutable,
+ Description: "prebuilt",
+ Output: outputFile,
+ Input: in,
+ })
+
+ return outputFile
+}
+
+func (p *snapshotBinaryDecorator) nativeCoverage() bool {
+ return false
+}
+
+// vendor_snapshot_binary is a special prebuilt executable binary which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_binary
+// overrides the vendor variant of the cc binary with the same name, if BOARD_VNDK_VERSION is set.
+func VendorSnapshotBinaryFactory() android.Module {
+ return snapshotBinaryFactory(vendorSnapshotBinarySuffix)
+}
+
+// recovery_snapshot_binary is a special prebuilt executable binary which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of recovery snapshot, recovery_snapshot_binary
+// overrides the recovery variant of the cc binary with the same name, if BOARD_VNDK_VERSION is set.
+func RecoverySnapshotBinaryFactory() android.Module {
+ return snapshotBinaryFactory(recoverySnapshotBinarySuffix)
+}
+
+// ramdisk_snapshot_binary is a special prebuilt executable binary which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of ramdisk snapshot, ramdisk_snapshot_binary
+// overrides the ramdisk variant of the cc binary with the same name, if BOARD_VNDK_VERSION is set.
+func RamdiskSnapshotBinaryFactory() android.Module {
+ return snapshotBinaryFactory(ramdiskSnapshotBinarySuffix)
+}
+
+func snapshotBinaryFactory(suffix string) android.Module {
+ module, binary := NewBinary(android.DeviceSupported)
+ binary.baseLinker.Properties.No_libcrt = BoolPtr(true)
+ binary.baseLinker.Properties.Nocrt = BoolPtr(true)
+
+ // Prevent default system libs (libc, libm, and libdl) from being linked
+ if binary.baseLinker.Properties.System_shared_libs == nil {
+ binary.baseLinker.Properties.System_shared_libs = []string{}
+ }
+
+ prebuilt := &snapshotBinaryDecorator{
+ binaryDecorator: binary,
+ }
+
+ module.compiler = nil
+ module.sanitize = nil
+ module.stl = nil
+ module.linker = prebuilt
+
+ prebuilt.init(module, suffix)
+ module.AddProperties(&prebuilt.properties)
+ return module.Init()
+}
+
+//
+// Module definitions for snapshots of object files (*.o).
+//
+// Modules (vendor|recovery)_snapshot_object are defined here. They have their prebuilt object
+// files (*.o) as their src.
+//
+// These modules are auto-generated by development/vendor_snapshot/update.py.
+type vendorSnapshotObjectProperties struct {
+ // Prebuilt file for each arch.
+ Src *string `android:"arch_variant"`
+}
+
+type snapshotObjectLinker struct {
+ baseSnapshotDecorator
+ objectLinker
+ properties vendorSnapshotObjectProperties
+ androidMkSuffix string
+}
+
+func (p *snapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool {
+ if config.DeviceArch() != p.arch() {
+ return false
+ }
+ if p.properties.Src == nil {
+ return false
+ }
+ return true
+}
+
+// cc modules' link functions are to link compiled objects into final binaries.
+// As snapshots are prebuilts, this just returns the prebuilt binary
+func (p *snapshotObjectLinker) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path {
+ if !p.matchesWithDevice(ctx.DeviceConfig()) {
+ return nil
+ }
+
+ m := ctx.Module().(*Module)
+
+ if m.inVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] {
+ p.androidMkSuffix = vendorSuffix
+ } else if m.InRecovery() && recoverySuffixModules(ctx.Config())[m.BaseModuleName()] {
+ p.androidMkSuffix = recoverySuffix
+ } else if m.InRamdisk() && ramdiskSuffixModules(ctx.Config())[m.BaseModuleName()] {
+ p.androidMkSuffix = ramdiskSuffix
+ }
+
+ return android.PathForModuleSrc(ctx, *p.properties.Src)
+}
+
+func (p *snapshotObjectLinker) nativeCoverage() bool {
+ return false
+}
+
+// vendor_snapshot_object is a special prebuilt compiled object file which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_object
+// overrides the vendor variant of the cc object with the same name, if BOARD_VNDK_VERSION is set.
+func VendorSnapshotObjectFactory() android.Module {
+ module := newObject()
+
+ prebuilt := &snapshotObjectLinker{
+ objectLinker: objectLinker{
+ baseLinker: NewBaseLinker(nil),
+ },
+ }
+ module.linker = prebuilt
+
+ prebuilt.init(module, vendorSnapshotObjectSuffix)
+ module.AddProperties(&prebuilt.properties)
+ return module.Init()
+}
+
+// recovery_snapshot_object is a special prebuilt compiled object file which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of recovery snapshot, recovery_snapshot_object
+// overrides the recovery variant of the cc object with the same name, if BOARD_VNDK_VERSION is set.
+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()
+}
+
+// ramdisk_snapshot_object is a special prebuilt compiled object file which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of ramdisk snapshot, ramdisk_snapshot_object
+// overrides the recovery variant of the cc object with the same name, if BOARD_VNDK_VERSION is set.
+func RamdiskSnapshotObjectFactory() android.Module {
+ module := newObject()
+
+ prebuilt := &snapshotObjectLinker{
+ objectLinker: objectLinker{
+ baseLinker: NewBaseLinker(nil),
+ },
+ }
+ module.linker = prebuilt
+
+ prebuilt.init(module, ramdiskSnapshotObjectSuffix)
+ module.AddProperties(&prebuilt.properties)
+ return module.Init()
+}
+
+type snapshotInterface interface {
+ matchesWithDevice(config android.DeviceConfig) bool
+}
+
+var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil)
+var _ snapshotInterface = (*snapshotLibraryDecorator)(nil)
+var _ snapshotInterface = (*snapshotBinaryDecorator)(nil)
+var _ snapshotInterface = (*snapshotObjectLinker)(nil)
+
+//
+// Mutators that helps vendor snapshot modules override source modules.
+//
+
+// VendorSnapshotMutator gathers all snapshots for vendor, and disable all snapshots which don't
+// match with device, e.g.
+// - snapshot version is different with BOARD_VNDK_VERSION
+// - snapshot arch is different with device's arch (e.g. arm vs x86)
+//
+// This also handles vndk_prebuilt_shared, except for they won't be disabled in any cases, given
+// that any versions of VNDK might be packed into vndk APEX.
+//
+// TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules
+func VendorSnapshotMutator(ctx android.BottomUpMutatorContext) {
+ snapshotMutator(ctx, vendorSnapshotImageSingleton)
+}
+
+func RecoverySnapshotMutator(ctx android.BottomUpMutatorContext) {
+ snapshotMutator(ctx, recoverySnapshotImageSingleton)
+}
+
+func RamdiskSnapshotMutator(ctx android.BottomUpMutatorContext) {
+ snapshotMutator(ctx, ramdiskSnapshotImageSingleton)
+}
+
+func snapshotMutator(ctx android.BottomUpMutatorContext, image snapshotImage) {
+ if !image.isUsingSnapshot(ctx.DeviceConfig()) {
+ return
+ }
+ module, ok := ctx.Module().(*Module)
+ if !ok || !module.Enabled() {
+ return
+ }
+ if image.skipModuleMutator(ctx) {
+ return
+ }
+ if !module.isSnapshotPrebuilt() {
+ return
+ }
+
+ // isSnapshotPrebuilt ensures snapshotInterface
+ if !module.linker.(snapshotInterface).matchesWithDevice(ctx.DeviceConfig()) {
+ // Disable unnecessary snapshot module, but do not disable
+ // vndk_prebuilt_shared because they might be packed into vndk APEX
+ if !module.IsVndk() {
+ module.Disable()
+ }
+ return
+ }
+
+ var snapshotMap *snapshotMap = image.getSnapshotMap(module, ctx.Config())
+ if snapshotMap == nil {
+ return
+ }
+
+ mutex := image.getMutex()
+ mutex.Lock()
+ defer mutex.Unlock()
+ snapshotMap.add(module.BaseModuleName(), ctx.Arch().ArchType, ctx.ModuleName())
+}
+
+// VendorSnapshotSourceMutator disables source modules which have corresponding snapshots.
+func VendorSnapshotSourceMutator(ctx android.BottomUpMutatorContext) {
+ snapshotSourceMutator(ctx, vendorSnapshotImageSingleton)
+}
+
+func RecoverySnapshotSourceMutator(ctx android.BottomUpMutatorContext) {
+ snapshotSourceMutator(ctx, recoverySnapshotImageSingleton)
+}
+func RamdiskSnapshotSourceMutator(ctx android.BottomUpMutatorContext) {
+ snapshotSourceMutator(ctx, ramdiskSnapshotImageSingleton)
+}
+
+func snapshotSourceMutator(ctx android.BottomUpMutatorContext, image snapshotImage) {
+ if !ctx.Device() {
+ return
+ }
+ if !image.isUsingSnapshot(ctx.DeviceConfig()) {
+ return
+ }
+
+ module, ok := ctx.Module().(*Module)
+ if !ok {
+ return
+ }
+
+ if image.shouldBeAddedToSuffixModules(module) {
+ mutex := image.getMutex()
+ mutex.Lock()
+ defer mutex.Unlock()
+
+ image.suffixModules(ctx.Config())[ctx.ModuleName()] = true
+ }
+
+ if module.isSnapshotPrebuilt() {
+ return
+ }
+ if image.skipSourceMutator(ctx) {
+ return
+ }
+
+ var snapshotMap *snapshotMap = image.getSnapshotMap(module, ctx.Config())
+ if snapshotMap == nil {
+ return
+ }
+
+ if _, ok := snapshotMap.get(ctx.ModuleName(), ctx.Arch().ArchType); !ok {
+ // Corresponding snapshot doesn't exist
+ return
+ }
+
+ // Disables source modules if corresponding snapshot exists.
+ if lib, ok := module.linker.(libraryInterface); ok && lib.buildStatic() && lib.buildShared() {
+ // But do not disable because the shared variant depends on the static variant.
+ module.SkipInstall()
+ module.Properties.HideFromMake = true
+ } else {
+ module.Disable()
+ }
+}
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index 26e7c8d..2739a78 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -58,38 +58,22 @@
return snapshot, found
}
-func isSnapshotAware(ctx android.ModuleContext, m *Module) bool {
+// shouldCollectHeadersForSnapshot determines if the module is a possible candidate for snapshot.
+// If it's true, collectHeadersForSnapshot will be called in GenerateAndroidBuildActions.
+func shouldCollectHeadersForSnapshot(ctx android.ModuleContext, m *Module) bool {
+ if ctx.DeviceConfig().VndkVersion() != "current" &&
+ ctx.DeviceConfig().RecoverySnapshotVersion() != "current" &&
+ ctx.DeviceConfig().RamdiskSnapshotVersion() != "current" {
+ return false
+ }
if _, _, ok := isVndkSnapshotLibrary(ctx.DeviceConfig(), m); ok {
return ctx.Config().VndkSnapshotBuildArtifacts()
- } else if isVendorSnapshotModule(m, ctx.ModuleDir()) {
- return true
+ }
+ for _, image := range []snapshotImage{vendorSnapshotImageSingleton, recoverySnapshotImageSingleton,
+ ramdiskSnapshotImageSingleton } {
+ if isSnapshotAware(ctx.DeviceConfig(), m, image.isProprietaryPath(ctx.ModuleDir(), ctx.DeviceConfig()), image) {
+ return true
+ }
}
return false
}
-
-func copyFile(ctx android.SingletonContext, path android.Path, out string) android.OutputPath {
- outPath := android.PathForOutput(ctx, out)
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Input: path,
- Output: outPath,
- Description: "Cp " + out,
- Args: map[string]string{
- "cpFlags": "-f -L",
- },
- })
- return outPath
-}
-
-func writeStringToFile(ctx android.SingletonContext, content, out string) android.OutputPath {
- outPath := android.PathForOutput(ctx, out)
- ctx.Build(pctx, android.BuildParams{
- Rule: android.WriteFile,
- Output: outPath,
- Description: "WriteFile " + out,
- Args: map[string]string{
- "content": content,
- },
- })
- return outPath
-}
diff --git a/cc/testing.go b/cc/testing.go
index 7a86a8d..a8c494b 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "android/soong/genrule"
)
func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
@@ -32,6 +33,7 @@
ctx.RegisterModuleType("cc_object", ObjectFactory)
ctx.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory)
ctx.RegisterModuleType("ndk_prebuilt_object", NdkPrebuiltObjectFactory)
+ ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
}
func GatherRequiredDepsForTest(oses ...android.OsType) string {
@@ -464,10 +466,14 @@
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
ctx.RegisterModuleType("vndk_libraries_txt", VndkLibrariesTxtFactory)
+ ctx.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
RegisterRequiredBuildComponentsForTest(ctx)
ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
+ ctx.RegisterSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton)
+ ctx.RegisterSingletonType("recovery-snapshot", RecoverySnapshotSingleton)
+ ctx.RegisterSingletonType("ramdisk-snapshot", RamdiskSnapshotSingleton)
return ctx
}
diff --git a/cc/util.go b/cc/util.go
index af26268..ce29a08 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -82,6 +82,7 @@
tidyFlags: strings.Join(in.TidyFlags, " "),
sAbiFlags: strings.Join(in.SAbiFlags, " "),
toolchain: in.Toolchain,
+ sdclang: in.Sdclang,
gcovCoverage: in.GcovCoverage,
tidy: in.Tidy,
sAbiDump: in.SAbiDump,
@@ -120,3 +121,41 @@
return "mkdir -p " + dir + " && " +
"ln -sf " + target + " " + filepath.Join(dir, linkName)
}
+
+func copyFileRule(ctx android.SingletonContext, path android.Path, out string) android.OutputPath {
+ outPath := android.PathForOutput(ctx, out)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: path,
+ Output: outPath,
+ Description: "Cp " + out,
+ Args: map[string]string{
+ "cpFlags": "-f -L",
+ },
+ })
+ return outPath
+}
+
+func combineNoticesRule(ctx android.SingletonContext, paths android.Paths, out string) android.OutputPath {
+ outPath := android.PathForOutput(ctx, out)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cat,
+ Inputs: paths,
+ Output: outPath,
+ Description: "combine notices for " + out,
+ })
+ return outPath
+}
+
+func writeStringToFileRule(ctx android.SingletonContext, content, out string) android.OutputPath {
+ outPath := android.PathForOutput(ctx, out)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.WriteFile,
+ Output: outPath,
+ Description: "WriteFile " + out,
+ Args: map[string]string{
+ "content": content,
+ },
+ })
+ return outPath
+}
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index b11b1a8..ed2c370 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -18,524 +18,198 @@
"path/filepath"
"sort"
"strings"
- "sync"
"github.com/google/blueprint/proptools"
"android/soong/android"
)
-const (
- vendorSnapshotHeaderSuffix = ".vendor_header."
- vendorSnapshotSharedSuffix = ".vendor_shared."
- vendorSnapshotStaticSuffix = ".vendor_static."
- vendorSnapshotBinarySuffix = ".vendor_binary."
- vendorSnapshotObjectSuffix = ".vendor_object."
-)
-
-var (
- vendorSnapshotsLock sync.Mutex
- vendorSuffixModulesKey = android.NewOnceKey("vendorSuffixModules")
- vendorSnapshotHeaderLibsKey = android.NewOnceKey("vendorSnapshotHeaderLibs")
- vendorSnapshotStaticLibsKey = android.NewOnceKey("vendorSnapshotStaticLibs")
- vendorSnapshotSharedLibsKey = android.NewOnceKey("vendorSnapshotSharedLibs")
- vendorSnapshotBinariesKey = android.NewOnceKey("vendorSnapshotBinaries")
- vendorSnapshotObjectsKey = android.NewOnceKey("vendorSnapshotObjects")
-)
-
-// vendor snapshot maps hold names of vendor snapshot modules per arch
-func vendorSuffixModules(config android.Config) map[string]bool {
- return config.Once(vendorSuffixModulesKey, func() interface{} {
- return make(map[string]bool)
- }).(map[string]bool)
+var vendorSnapshotSingleton = snapshotSingleton{
+ "vendor",
+ "SOONG_VENDOR_SNAPSHOT_ZIP",
+ android.OptionalPath{},
+ true,
+ vendorSnapshotImageSingleton,
+ false, /* fake */
+ true, /* usesLlndkLibraries */
}
-func vendorSnapshotHeaderLibs(config android.Config) *snapshotMap {
- return config.Once(vendorSnapshotHeaderLibsKey, func() interface{} {
- return newSnapshotMap()
- }).(*snapshotMap)
+var vendorFakeSnapshotSingleton = snapshotSingleton{
+ "vendor",
+ "SOONG_VENDOR_FAKE_SNAPSHOT_ZIP",
+ android.OptionalPath{},
+ true,
+ vendorSnapshotImageSingleton,
+ true, /* fake */
+ true, /* usesLlndkLibraries */
}
-func vendorSnapshotSharedLibs(config android.Config) *snapshotMap {
- return config.Once(vendorSnapshotSharedLibsKey, func() interface{} {
- return newSnapshotMap()
- }).(*snapshotMap)
+var recoverySnapshotSingleton = snapshotSingleton{
+ "recovery",
+ "SOONG_RECOVERY_SNAPSHOT_ZIP",
+ android.OptionalPath{},
+ false,
+ recoverySnapshotImageSingleton,
+ false, /* fake */
+ false, /* usesLlndkLibraries */
}
-func vendorSnapshotStaticLibs(config android.Config) *snapshotMap {
- return config.Once(vendorSnapshotStaticLibsKey, func() interface{} {
- return newSnapshotMap()
- }).(*snapshotMap)
-}
-
-func vendorSnapshotBinaries(config android.Config) *snapshotMap {
- return config.Once(vendorSnapshotBinariesKey, func() interface{} {
- return newSnapshotMap()
- }).(*snapshotMap)
-}
-
-func vendorSnapshotObjects(config android.Config) *snapshotMap {
- return config.Once(vendorSnapshotObjectsKey, func() interface{} {
- return newSnapshotMap()
- }).(*snapshotMap)
-}
-
-type vendorSnapshotLibraryProperties struct {
- // snapshot version.
- Version string
-
- // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64')
- Target_arch string
-
- // Prebuilt file for each arch.
- Src *string `android:"arch_variant"`
-
- // list of flags that will be used for any module that links against this module.
- Export_flags []string `android:"arch_variant"`
-
- // Check the prebuilt ELF files (e.g. DT_SONAME, DT_NEEDED, resolution of undefined symbols,
- // etc).
- Check_elf_files *bool
-
- // Whether this prebuilt needs to depend on sanitize ubsan runtime or not.
- Sanitize_ubsan_dep *bool `android:"arch_variant"`
-
- // Whether this prebuilt needs to depend on sanitize minimal runtime or not.
- Sanitize_minimal_dep *bool `android:"arch_variant"`
-}
-
-type vendorSnapshotLibraryDecorator struct {
- *libraryDecorator
- properties vendorSnapshotLibraryProperties
- androidMkVendorSuffix bool
-}
-
-func (p *vendorSnapshotLibraryDecorator) Name(name string) string {
- return name + p.NameSuffix()
-}
-
-func (p *vendorSnapshotLibraryDecorator) NameSuffix() string {
- versionSuffix := p.version()
- if p.arch() != "" {
- versionSuffix += "." + p.arch()
- }
-
- var linkageSuffix string
- if p.buildShared() {
- linkageSuffix = vendorSnapshotSharedSuffix
- } else if p.buildStatic() {
- linkageSuffix = vendorSnapshotStaticSuffix
- } else {
- linkageSuffix = vendorSnapshotHeaderSuffix
- }
-
- return linkageSuffix + versionSuffix
-}
-
-func (p *vendorSnapshotLibraryDecorator) version() string {
- return p.properties.Version
-}
-
-func (p *vendorSnapshotLibraryDecorator) arch() string {
- return p.properties.Target_arch
-}
-
-func (p *vendorSnapshotLibraryDecorator) 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 {
- arches := config.Arches()
- if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
- return false
- }
- if !p.header() && p.properties.Src == nil {
- return false
- }
- return true
-}
-
-func (p *vendorSnapshotLibraryDecorator) link(ctx ModuleContext,
- flags Flags, deps PathDeps, objs Objects) android.Path {
- m := ctx.Module().(*Module)
- p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
-
- if p.header() {
- return p.libraryDecorator.link(ctx, flags, deps, objs)
- }
-
- if !p.matchesWithDevice(ctx.DeviceConfig()) {
- return nil
- }
-
- p.libraryDecorator.exportIncludes(ctx)
- p.libraryDecorator.reexportFlags(p.properties.Export_flags...)
-
- in := android.PathForModuleSrc(ctx, *p.properties.Src)
- p.unstrippedOutputFile = in
-
- if p.shared() {
- libName := in.Base()
- builderFlags := flagsToBuilderFlags(flags)
-
- // Optimize out relinking against shared libraries whose interface hasn't changed by
- // depending on a table of contents file instead of the library itself.
- tocFile := android.PathForModuleOut(ctx, libName+".toc")
- p.tocFile = android.OptionalPathForPath(tocFile)
- TransformSharedObjectToToc(ctx, in, tocFile, builderFlags)
- }
-
- return in
-}
-
-func (p *vendorSnapshotLibraryDecorator) nativeCoverage() bool {
- return false
-}
-
-func (p *vendorSnapshotLibraryDecorator) isSnapshotPrebuilt() bool {
- return true
-}
-
-func (p *vendorSnapshotLibraryDecorator) install(ctx ModuleContext, file android.Path) {
- if p.matchesWithDevice(ctx.DeviceConfig()) && (p.shared() || p.static()) {
- p.baseInstaller.install(ctx, file)
- }
-}
-
-type vendorSnapshotInterface interface {
- version() string
-}
-
-func vendorSnapshotLoadHook(ctx android.LoadHookContext, p vendorSnapshotInterface) {
- if p.version() != ctx.DeviceConfig().VndkVersion() {
- ctx.Module().Disable()
- return
- }
-}
-
-func vendorSnapshotLibrary() (*Module, *vendorSnapshotLibraryDecorator) {
- module, library := NewLibrary(android.DeviceSupported)
-
- module.stl = nil
- module.sanitize = nil
- library.StripProperties.Strip.None = BoolPtr(true)
-
- prebuilt := &vendorSnapshotLibraryDecorator{
- libraryDecorator: library,
- }
-
- prebuilt.baseLinker.Properties.No_libcrt = BoolPtr(true)
- prebuilt.baseLinker.Properties.Nocrt = BoolPtr(true)
-
- // Prevent default system libs (libc, libm, and libdl) from being linked
- if prebuilt.baseLinker.Properties.System_shared_libs == nil {
- prebuilt.baseLinker.Properties.System_shared_libs = []string{}
- }
-
- module.compiler = nil
- module.linker = prebuilt
- module.installer = prebuilt
-
- module.AddProperties(
- &prebuilt.properties,
- )
-
- return module, prebuilt
-}
-
-func VendorSnapshotSharedFactory() android.Module {
- module, prebuilt := vendorSnapshotLibrary()
- prebuilt.libraryDecorator.BuildOnlyShared()
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- vendorSnapshotLoadHook(ctx, prebuilt)
- })
- return module.Init()
-}
-
-func VendorSnapshotStaticFactory() android.Module {
- module, prebuilt := vendorSnapshotLibrary()
- prebuilt.libraryDecorator.BuildOnlyStatic()
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- vendorSnapshotLoadHook(ctx, prebuilt)
- })
- return module.Init()
-}
-
-func VendorSnapshotHeaderFactory() android.Module {
- module, prebuilt := vendorSnapshotLibrary()
- prebuilt.libraryDecorator.HeaderOnly()
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- vendorSnapshotLoadHook(ctx, prebuilt)
- })
- return module.Init()
-}
-
-type vendorSnapshotBinaryProperties struct {
- // snapshot version.
- Version string
-
- // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab')
- Target_arch string
-
- // Prebuilt file for each arch.
- Src *string `android:"arch_variant"`
-}
-
-type vendorSnapshotBinaryDecorator struct {
- *binaryDecorator
- properties vendorSnapshotBinaryProperties
- androidMkVendorSuffix bool
-}
-
-func (p *vendorSnapshotBinaryDecorator) Name(name string) string {
- return name + p.NameSuffix()
-}
-
-func (p *vendorSnapshotBinaryDecorator) NameSuffix() string {
- versionSuffix := p.version()
- if p.arch() != "" {
- versionSuffix += "." + p.arch()
- }
- return vendorSnapshotBinarySuffix + versionSuffix
-}
-
-func (p *vendorSnapshotBinaryDecorator) version() string {
- return p.properties.Version
-}
-
-func (p *vendorSnapshotBinaryDecorator) arch() string {
- return p.properties.Target_arch
-}
-
-func (p *vendorSnapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
- if config.DeviceArch() != p.arch() {
- return false
- }
- if p.properties.Src == nil {
- return false
- }
- return true
-}
-
-func (p *vendorSnapshotBinaryDecorator) link(ctx ModuleContext,
- flags Flags, deps PathDeps, objs Objects) android.Path {
- if !p.matchesWithDevice(ctx.DeviceConfig()) {
- return nil
- }
-
- in := android.PathForModuleSrc(ctx, *p.properties.Src)
- builderFlags := flagsToBuilderFlags(flags)
- p.unstrippedOutputFile = in
- binName := in.Base()
- if p.needsStrip(ctx) {
- stripped := android.PathForModuleOut(ctx, "stripped", binName)
- p.stripExecutableOrSharedLib(ctx, in, stripped, builderFlags)
- in = stripped
- }
-
- m := ctx.Module().(*Module)
- p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
-
- // use cpExecutable to make it executable
- outputFile := android.PathForModuleOut(ctx, binName)
- ctx.Build(pctx, android.BuildParams{
- Rule: android.CpExecutable,
- Description: "prebuilt",
- Output: outputFile,
- Input: in,
- })
-
- return outputFile
-}
-
-func (p *vendorSnapshotBinaryDecorator) isSnapshotPrebuilt() bool {
- return true
-}
-
-func VendorSnapshotBinaryFactory() android.Module {
- module, binary := NewBinary(android.DeviceSupported)
- binary.baseLinker.Properties.No_libcrt = BoolPtr(true)
- binary.baseLinker.Properties.Nocrt = BoolPtr(true)
-
- // Prevent default system libs (libc, libm, and libdl) from being linked
- if binary.baseLinker.Properties.System_shared_libs == nil {
- binary.baseLinker.Properties.System_shared_libs = []string{}
- }
-
- prebuilt := &vendorSnapshotBinaryDecorator{
- binaryDecorator: binary,
- }
-
- module.compiler = nil
- module.sanitize = nil
- module.stl = nil
- module.linker = prebuilt
-
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- vendorSnapshotLoadHook(ctx, prebuilt)
- })
-
- module.AddProperties(&prebuilt.properties)
- return module.Init()
-}
-
-type vendorSnapshotObjectProperties struct {
- // snapshot version.
- Version string
-
- // Target arch name of the snapshot (e.g. 'arm64' for variant 'aosp_arm64_ab')
- Target_arch string
-
- // Prebuilt file for each arch.
- Src *string `android:"arch_variant"`
-}
-
-type vendorSnapshotObjectLinker struct {
- objectLinker
- properties vendorSnapshotObjectProperties
- androidMkVendorSuffix bool
-}
-
-func (p *vendorSnapshotObjectLinker) Name(name string) string {
- return name + p.NameSuffix()
-}
-
-func (p *vendorSnapshotObjectLinker) NameSuffix() string {
- versionSuffix := p.version()
- if p.arch() != "" {
- versionSuffix += "." + p.arch()
- }
- return vendorSnapshotObjectSuffix + versionSuffix
-}
-
-func (p *vendorSnapshotObjectLinker) version() string {
- return p.properties.Version
-}
-
-func (p *vendorSnapshotObjectLinker) arch() string {
- return p.properties.Target_arch
-}
-
-func (p *vendorSnapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool {
- if config.DeviceArch() != p.arch() {
- return false
- }
- if p.properties.Src == nil {
- return false
- }
- return true
-}
-
-func (p *vendorSnapshotObjectLinker) link(ctx ModuleContext,
- flags Flags, deps PathDeps, objs Objects) android.Path {
- if !p.matchesWithDevice(ctx.DeviceConfig()) {
- return nil
- }
-
- m := ctx.Module().(*Module)
- p.androidMkVendorSuffix = vendorSuffixModules(ctx.Config())[m.BaseModuleName()]
-
- return android.PathForModuleSrc(ctx, *p.properties.Src)
-}
-
-func (p *vendorSnapshotObjectLinker) nativeCoverage() bool {
- return false
-}
-
-func (p *vendorSnapshotObjectLinker) isSnapshotPrebuilt() bool {
- return true
-}
-
-func VendorSnapshotObjectFactory() android.Module {
- module := newObject()
-
- prebuilt := &vendorSnapshotObjectLinker{
- objectLinker: objectLinker{
- baseLinker: NewBaseLinker(nil),
- },
- }
- module.linker = prebuilt
-
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- vendorSnapshotLoadHook(ctx, prebuilt)
- })
-
- 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)
+var ramdiskSnapshotSingleton = snapshotSingleton{
+ "ramdisk",
+ "SOONG_RAMDISK_SNAPSHOT_ZIP",
+ android.OptionalPath{},
+ false,
+ ramdiskSnapshotImageSingleton,
+ false, /* fake */
+ false, /* usesLlndkLibraries */
}
func VendorSnapshotSingleton() android.Singleton {
- return &vendorSnapshotSingleton{}
+ return &vendorSnapshotSingleton
}
-type vendorSnapshotSingleton struct {
- vendorSnapshotZipFile android.OptionalPath
+func VendorFakeSnapshotSingleton() android.Singleton {
+ return &vendorFakeSnapshotSingleton
}
-var (
- // Modules under following directories are ignored. They are OEM's and vendor's
- // proprietary modules(device/, vendor/, and hardware/).
- // TODO(b/65377115): Clean up these with more maintainable way
- vendorProprietaryDirs = []string{
- "device",
- "vendor",
- "hardware",
+func RecoverySnapshotSingleton() android.Singleton {
+ return &recoverySnapshotSingleton
+}
+
+func RamdiskSnapshotSingleton() android.Singleton {
+ return &ramdiskSnapshotSingleton
+}
+
+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 snapshotImage
+
+ // Whether this singleton is for fake snapshot or not.
+ // Fake snapshot is a snapshot whose prebuilt binaries and headers are empty.
+ // It is much faster to generate, and can be used to inspect dependencies.
+ fake bool
+
+ // Whether the image uses llndk libraries.
+ usesLlndkLibraries bool
+}
+
+// Determine if a dir under source tree is an SoC-owned proprietary directory based
+// on vendor snapshot configuration
+// Examples: device/, vendor/
+func isVendorProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
+ return VendorSnapshotSingleton().(*snapshotSingleton).image.isProprietaryPath(dir, deviceConfig)
+}
+
+// Determine if a dir under source tree is an SoC-owned proprietary directory based
+// on recovery snapshot configuration
+// Examples: device/, vendor/
+func isRecoveryProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
+ return RecoverySnapshotSingleton().(*snapshotSingleton).image.isProprietaryPath(dir, deviceConfig)
+}
+
+// Determine if a dir under source tree is an SoC-owned proprietary directory based
+// on ramdisk snapshot configuration
+// Examples: device/, vendor/
+func isRamdiskProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
+ return RamdiskSnapshotSingleton().(*snapshotSingleton).image.isProprietaryPath(dir, deviceConfig)
+}
+
+func isVendorProprietaryModule(ctx android.BaseModuleContext) bool {
+ // Any module in a vendor proprietary path is a vendor proprietary
+ // module.
+ if isVendorProprietaryPath(ctx.ModuleDir(), ctx.DeviceConfig()) {
+ return true
}
- // Modules under following directories are included as they are in AOSP,
- // although hardware/ is normally for vendor's own.
- // TODO(b/65377115): Clean up these with more maintainable way
- aospDirsUnderProprietary = []string{
- "hardware/interfaces",
- "hardware/libhardware",
- "hardware/libhardware_legacy",
- "hardware/ril",
- }
-)
-
-// 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 {
- if strings.HasPrefix(dir, p) {
- // filter out AOSP defined directories, e.g. hardware/interfaces/
- aosp := false
- for _, p := range aospDirsUnderProprietary {
- if strings.HasPrefix(dir, p) {
- aosp = true
- break
- }
- }
- if !aosp {
- return true
- }
+ // However if the module is not in a vendor proprietary path, it may
+ // still be a vendor proprietary module. This happens for cc modules
+ // that are excluded from the vendor snapshot, and it means that the
+ // vendor has assumed control of the framework-provided module.
+ if c, ok := ctx.Module().(*Module); ok {
+ if c.ExcludeFromVendorSnapshot() {
+ return true
}
}
+
return false
}
-// Determine if a module is going to be included in vendor snapshot or not.
-//
-// Targets of vendor snapshot are "vendor: true" or "vendor_available: true" modules in
-// AOSP. They are not guaranteed to be compatible with older vendor images. (e.g. might
-// 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, moduleDir string) bool {
+func isRecoveryProprietaryModule(ctx android.BaseModuleContext) bool {
+
+ // Any module in a vendor proprietary path is a vendor proprietary
+ // module.
+ if isRecoveryProprietaryPath(ctx.ModuleDir(), ctx.DeviceConfig()) {
+ return true
+ }
+
+ // However if the module is not in a vendor proprietary path, it may
+ // still be a vendor proprietary module. This happens for cc modules
+ // that are excluded from the vendor snapshot, and it means that the
+ // vendor has assumed control of the framework-provided module.
+
+ if c, ok := ctx.Module().(*Module); ok {
+ if c.ExcludeFromRecoverySnapshot() {
+ return true
+ }
+ }
+
+ return false
+}
+func isRamdiskProprietaryModule(ctx android.BaseModuleContext) bool {
+
+ // Any module in a vendor proprietary path is a vendor proprietary
+ // module.
+ if isRamdiskProprietaryPath(ctx.ModuleDir(), ctx.DeviceConfig()) {
+ return true
+ }
+
+ // However if the module is not in a vendor proprietary path, it may
+ // still be a vendor proprietary module. This happens for cc modules
+ // that are excluded from the vendor snapshot, and it means that the
+ // vendor has assumed control of the framework-provided module.
+
+ if c, ok := ctx.Module().(*Module); ok {
+ if c.ExcludeFromRamdiskSnapshot() {
+ return true
+ }
+ }
+
+ return false
+}
+
+// Determines if the module is a candidate for snapshot.
+func isSnapshotAware(cfg android.DeviceConfig, m *Module, inProprietaryPath bool, image snapshotImage) bool {
if !m.Enabled() || m.Properties.HideFromMake {
return false
}
- // skip proprietary modules, but include all VNDK (static)
- if isVendorProprietaryPath(moduleDir) && !m.IsVndk() {
+ // When android/prebuilt.go selects between source and prebuilt, it sets
+ // SkipInstall on the other one to avoid duplicate install rules in make.
+ if m.IsSkipInstall() {
+ return false
+ }
+ // 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
+ // the module is marked to be excluded. If so, skip it.
+ if image.excludeFromSnapshot(m) {
return false
}
if m.Target().Os.Class != android.Device {
@@ -545,7 +219,7 @@
return false
}
// the module must be installed in /vendor
- if !m.IsForPlatform() || m.isSnapshotPrebuilt() || !m.inVendor() {
+ if !m.IsForPlatform() || m.isSnapshotPrebuilt() || !image.inImage(m)() {
return false
}
// skip kernel_headers which always depend on vendor
@@ -557,40 +231,45 @@
if l, ok := m.linker.(snapshotLibraryInterface); ok {
// TODO(b/65377115): add full support for sanitizer
if m.sanitize != nil {
- // cfi, scs and hwasan export both sanitized and unsanitized variants for static and header
+ // scs and hwasan export both sanitized and unsanitized variants for static and header
// Always use unsanitized variants of them.
- for _, t := range []sanitizerType{cfi, scs, hwasan} {
+ for _, t := range []sanitizerType{scs, hwasan} {
if !l.shared() && m.sanitize.isSanitizerEnabled(t) {
return false
}
}
+ // cfi also exports both variants. But for static, we capture both.
+ if !l.static() && !l.shared() && m.sanitize.isSanitizerEnabled(cfi) {
+ return false
+ }
}
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) {
- // BOARD_VNDK_VERSION must be set to 'current' in order to generate a vendor snapshot.
- if ctx.DeviceConfig().VndkVersion() != "current" {
+func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ if !c.image.shouldGenerateSnapshot(ctx) {
return
}
@@ -629,7 +308,12 @@
(header files of same directory structure with source tree)
*/
- snapshotDir := "vendor-snapshot"
+ snapshotDir := c.name + "-snapshot"
+ if c.fake {
+ // If this is a fake snapshot singleton, place all files under fake/ subdirectory to avoid
+ // collision with real snapshot files
+ snapshotDir = filepath.Join("fake", snapshotDir)
+ }
snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
includeDir := filepath.Join(snapshotArchDir, "include")
@@ -641,7 +325,19 @@
var headers android.Paths
- installSnapshot := func(m *Module) android.Paths {
+ copyFile := func(ctx android.SingletonContext, path android.Path, out string, fake bool) android.OutputPath {
+ if fake {
+ // All prebuilt binaries and headers are installed by copyFile function. This makes a fake
+ // snapshot just touch prebuilts and headers, rather than installing real files.
+ return writeStringToFileRule(ctx, "", out)
+ } else {
+ return copyFileRule(ctx, path, out)
+ }
+ }
+
+ // installSnapshot function copies prebuilt file (.so, .a, or executable) and json flag file.
+ // For executables, init_rc and vintf_fragments files are also copied.
+ installSnapshot := func(m *Module, fake bool) android.Paths {
targetArch := "arch-" + m.Target().Arch.ArchType.String()
if m.Target().Arch.ArchVariant != "" {
targetArch += "-" + m.Target().Arch.ArchVariant
@@ -657,8 +353,10 @@
ExportedDirs []string `json:",omitempty"`
ExportedSystemDirs []string `json:",omitempty"`
ExportedFlags []string `json:",omitempty"`
+ Sanitize string `json:",omitempty"`
SanitizeMinimalDep bool `json:",omitempty"`
SanitizeUbsanDep bool `json:",omitempty"`
+ IsLlndk bool `json:",omitempty"`
// binary flags
Symlinks []string `json:",omitempty"`
@@ -674,8 +372,13 @@
}{}
// Common properties among snapshots.
- prop.ModuleName = ctx.ModuleName(m)
- if m.isVndkExt() {
+ if m.isLlndk(ctx.Config()) && c.usesLlndkLibraries {
+ prop.ModuleName = m.BaseModuleName()
+ prop.IsLlndk = true
+ } else {
+ prop.ModuleName = ctx.ModuleName(m)
+ }
+ if c.supportsVndkExt && m.isVndkExt() {
// vndk exts are installed to /vendor/lib(64)?/vndk(-sp)?
if m.isVndkSp() {
prop.RelativeInstallPath = "vndk-sp"
@@ -699,13 +402,14 @@
out := filepath.Join(configsDir, path.Base())
if !installedConfigs[out] {
installedConfigs[out] = true
- ret = append(ret, copyFile(ctx, path, out))
+ ret = append(ret, copyFile(ctx, path, out, fake))
}
}
var propOut string
if l, ok := m.linker.(snapshotLibraryInterface); ok {
+
// library flags
prop.ExportedFlags = l.exportedFlags()
for _, dir := range l.exportedDirs() {
@@ -738,8 +442,17 @@
if libType != "header" {
libPath := m.outputFile.Path()
stem = libPath.Base()
+ if l.static() && m.sanitize != nil && m.sanitize.isSanitizerEnabled(cfi) {
+ // both cfi and non-cfi variant for static libraries can exist.
+ // attach .cfi to distinguish between cfi and non-cfi.
+ // e.g. libbase.a -> libbase.cfi.a
+ ext := filepath.Ext(stem)
+ stem = strings.TrimSuffix(stem, ext) + ".cfi" + ext
+ prop.Sanitize = "cfi"
+ prop.ModuleName += ".cfi"
+ }
snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem)
- ret = append(ret, copyFile(ctx, libPath, snapshotLibOut))
+ ret = append(ret, copyFile(ctx, libPath, snapshotLibOut, fake))
} else {
stem = ctx.ModuleName(m)
}
@@ -753,7 +466,7 @@
// install bin
binPath := m.outputFile.Path()
snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
- ret = append(ret, copyFile(ctx, binPath, snapshotBinOut))
+ ret = append(ret, copyFile(ctx, binPath, snapshotBinOut, fake))
propOut = snapshotBinOut + ".json"
} else if m.object() {
// object files aren't installed to the device, so their names can conflict.
@@ -761,7 +474,7 @@
objPath := m.outputFile.Path()
snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object",
ctx.ModuleName(m)+filepath.Ext(objPath.Base()))
- ret = append(ret, copyFile(ctx, objPath, snapshotObjOut))
+ ret = append(ret, copyFile(ctx, objPath, snapshotObjOut, fake))
propOut = snapshotObjOut + ".json"
} else {
ctx.Errorf("unknown module %q in vendor snapshot", m.String())
@@ -773,7 +486,7 @@
ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
return nil
}
- ret = append(ret, writeStringToFile(ctx, string(j), propOut))
+ ret = append(ret, writeStringToFileRule(ctx, string(j), propOut))
return ret
}
@@ -785,11 +498,44 @@
}
moduleDir := ctx.ModuleDir(module)
- if !isVendorSnapshotModule(m, moduleDir) {
+ inProprietaryPath := c.image.isProprietaryPath(moduleDir, ctx.DeviceConfig())
+
+ if c.image.excludeFromSnapshot(m) {
+ 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(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 \""+
+ c.name+
+ "_available: true\" and \"exclude_from_vendor_snapshot: true\"",
+ m.String())
+ return
+ }
+ }
+
+ if !isSnapshotAware(ctx.DeviceConfig(), m, inProprietaryPath, c.image) {
return
}
- snapshotOutputs = append(snapshotOutputs, installSnapshot(m)...)
+ // If we are using directed snapshot and a module is not included in the
+ // list, we will still include the module as if it was a fake module.
+ // The reason is that soong needs all the dependencies to be present, even
+ // if they are not using during the build.
+ installAsFake := c.fake
+ if c.image.excludeFromDirectedSnapshot(ctx.DeviceConfig(), m.BaseModuleName()) {
+ installAsFake = true
+ }
+
+ // installSnapshot installs prebuilts and json flag files
+ snapshotOutputs = append(snapshotOutputs, installSnapshot(m, installAsFake)...)
+ // just gather headers and notice files here, because they are to be deduplicated
if l, ok := m.linker.(snapshotLibraryInterface); ok {
headers = append(headers, l.snapshotHeaders()...)
}
@@ -800,16 +546,14 @@
// skip already copied notice file
if !installedNotices[noticeOut] {
installedNotices[noticeOut] = true
- snapshotOutputs = append(snapshotOutputs, copyFile(
- ctx, m.NoticeFile().Path(), noticeOut))
+ snapshotOutputs = append(snapshotOutputs, copyFile(ctx, m.NoticeFile().Path(), noticeOut, installAsFake))
}
}
})
// install all headers after removing duplicates
for _, header := range android.FirstUniquePaths(headers) {
- snapshotOutputs = append(snapshotOutputs, copyFile(
- ctx, header, filepath.Join(includeDir, header.String())))
+ snapshotOutputs = append(snapshotOutputs, copyFile(ctx, header, filepath.Join(includeDir, header.String()), c.fake))
}
// All artifacts are ready. Sort them to normalize ninja and then zip.
@@ -817,11 +561,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 ", "\\'").
@@ -836,148 +586,13 @@
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())
-}
-
-type snapshotInterface interface {
- matchesWithDevice(config android.DeviceConfig) bool
-}
-
-var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil)
-var _ snapshotInterface = (*vendorSnapshotLibraryDecorator)(nil)
-var _ snapshotInterface = (*vendorSnapshotBinaryDecorator)(nil)
-var _ snapshotInterface = (*vendorSnapshotObjectLinker)(nil)
-
-// gathers all snapshot modules for vendor, and disable unnecessary snapshots
-// TODO(b/145966707): remove mutator and utilize android.Prebuilt to override source modules
-func VendorSnapshotMutator(ctx android.BottomUpMutatorContext) {
- vndkVersion := ctx.DeviceConfig().VndkVersion()
- // don't need snapshot if current
- if vndkVersion == "current" || vndkVersion == "" {
- return
- }
-
- module, ok := ctx.Module().(*Module)
- if !ok || !module.Enabled() || module.VndkVersion() != vndkVersion {
- return
- }
-
- if !module.isSnapshotPrebuilt() {
- return
- }
-
- // isSnapshotPrebuilt ensures snapshotInterface
- if !module.linker.(snapshotInterface).matchesWithDevice(ctx.DeviceConfig()) {
- // Disable unnecessary snapshot module, but do not disable
- // vndk_prebuilt_shared because they might be packed into vndk APEX
- if !module.IsVndk() {
- module.Disable()
- }
- return
- }
-
- var snapshotMap *snapshotMap
-
- if lib, ok := module.linker.(libraryInterface); ok {
- if lib.static() {
- snapshotMap = vendorSnapshotStaticLibs(ctx.Config())
- } else if lib.shared() {
- snapshotMap = vendorSnapshotSharedLibs(ctx.Config())
- } else {
- // header
- snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
- }
- } else if _, ok := module.linker.(*vendorSnapshotBinaryDecorator); ok {
- snapshotMap = vendorSnapshotBinaries(ctx.Config())
- } else if _, ok := module.linker.(*vendorSnapshotObjectLinker); ok {
- snapshotMap = vendorSnapshotObjects(ctx.Config())
- } else {
- return
- }
-
- vendorSnapshotsLock.Lock()
- defer vendorSnapshotsLock.Unlock()
- snapshotMap.add(module.BaseModuleName(), ctx.Arch().ArchType, ctx.ModuleName())
-}
-
-// Disables source modules which have snapshots
-func VendorSnapshotSourceMutator(ctx android.BottomUpMutatorContext) {
- if !ctx.Device() {
- return
- }
-
- vndkVersion := ctx.DeviceConfig().VndkVersion()
- // don't need snapshot if current
- if vndkVersion == "current" || vndkVersion == "" {
- return
- }
-
- module, ok := ctx.Module().(*Module)
- if !ok {
- return
- }
-
- // vendor suffix should be added to snapshots if the source module isn't vendor: true.
- if !module.SocSpecific() {
- // But we can't just check SocSpecific() since we already passed the image mutator.
- // Check ramdisk and recovery to see if we are real "vendor: true" module.
- ramdisk_available := module.InRamdisk() && !module.OnlyInRamdisk()
- recovery_available := module.InRecovery() && !module.OnlyInRecovery()
-
- if !ramdisk_available && !recovery_available {
- vendorSnapshotsLock.Lock()
- defer vendorSnapshotsLock.Unlock()
-
- vendorSuffixModules(ctx.Config())[ctx.ModuleName()] = true
- }
- }
-
- if module.isSnapshotPrebuilt() || module.VndkVersion() != ctx.DeviceConfig().VndkVersion() {
- // only non-snapshot modules with BOARD_VNDK_VERSION
- return
- }
-
- // .. and also filter out llndk library
- if module.isLlndk(ctx.Config()) {
- return
- }
-
- var snapshotMap *snapshotMap
-
- if lib, ok := module.linker.(libraryInterface); ok {
- if lib.static() {
- snapshotMap = vendorSnapshotStaticLibs(ctx.Config())
- } else if lib.shared() {
- snapshotMap = vendorSnapshotSharedLibs(ctx.Config())
- } else {
- // header
- snapshotMap = vendorSnapshotHeaderLibs(ctx.Config())
- }
- } else if module.binary() {
- snapshotMap = vendorSnapshotBinaries(ctx.Config())
- } else if module.object() {
- snapshotMap = vendorSnapshotObjects(ctx.Config())
- } else {
- return
- }
-
- if _, ok := snapshotMap.get(ctx.ModuleName(), ctx.Arch().ArchType); !ok {
- // Corresponding snapshot doesn't exist
- return
- }
-
- // Disables source modules if corresponding snapshot exists.
- if lib, ok := module.linker.(libraryInterface); ok && lib.buildStatic() && lib.buildShared() {
- // But do not disable because the shared variant depends on the static variant.
- module.SkipInstall()
- module.Properties.HideFromMake = true
- } else {
- module.Disable()
- }
+func (c *snapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
+ ctx.Strict(
+ c.makeVar,
+ c.snapshotZipFile.String())
}
diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go
new file mode 100644
index 0000000..67f2b3d
--- /dev/null
+++ b/cc/vendor_snapshot_test.go
@@ -0,0 +1,1456 @@
+// Copyright 2021 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 cc
+
+import (
+ "android/soong/android"
+ "fmt"
+ "path/filepath"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+func TestVendorSnapshotCapture(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libvendor",
+ vendor: true,
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libvendor_available",
+ vendor_available: true,
+ nocrt: true,
+ }
+
+ cc_library_headers {
+ name: "libvendor_headers",
+ vendor_available: true,
+ nocrt: true,
+ }
+
+ cc_binary {
+ name: "vendor_bin",
+ vendor: true,
+ nocrt: true,
+ }
+
+ cc_binary {
+ name: "vendor_available_bin",
+ vendor_available: true,
+ nocrt: true,
+ }
+
+ toolchain_library {
+ name: "libb",
+ vendor_available: true,
+ src: "libb.a",
+ }
+
+ cc_object {
+ name: "obj",
+ vendor_available: true,
+ }
+
+ cc_library {
+ name: "libllndk",
+ llndk_stubs: "libllndk.llndk",
+ }
+
+ llndk_library {
+ name: "libllndk.llndk",
+ symbol_file: "",
+ }
+`
+ 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 Vendor snapshot output.
+
+ snapshotDir := "vendor-snapshot"
+ snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
+
+ var jsonFiles []string
+
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ []string{"arm", "armv7-a-neon"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
+
+ // For shared libraries, only non-VNDK vendor_available modules are captured
+ sharedVariant := fmt.Sprintf("android_vendor.VER_%s_%s_shared", archType, archVariant)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(sharedDir, "libvendor.so.json"),
+ filepath.Join(sharedDir, "libvendor_available.so.json"))
+
+ // LLNDK modules are not captured
+ checkSnapshotExclude(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", sharedDir, sharedVariant)
+
+ // For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
+ // Also cfi variants are captured, except for prebuilts like toolchain_library
+ staticVariant := fmt.Sprintf("android_vendor.VER_%s_%s_static", archType, archVariant)
+ staticCfiVariant := fmt.Sprintf("android_vendor.VER_%s_%s_static_cfi", archType, archVariant)
+ staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
+ checkSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.cfi.a", staticDir, staticCfiVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.cfi.a", staticDir, staticCfiVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.cfi.a", staticDir, staticCfiVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(staticDir, "libb.a.json"),
+ filepath.Join(staticDir, "libvndk.a.json"),
+ filepath.Join(staticDir, "libvndk.cfi.a.json"),
+ filepath.Join(staticDir, "libvendor.a.json"),
+ filepath.Join(staticDir, "libvendor.cfi.a.json"),
+ filepath.Join(staticDir, "libvendor_available.a.json"),
+ filepath.Join(staticDir, "libvendor_available.cfi.a.json"))
+
+ // For binary executables, all vendor:true and vendor_available modules are captured.
+ if archType == "arm64" {
+ binaryVariant := fmt.Sprintf("android_vendor.VER_%s_%s", archType, archVariant)
+ binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
+ checkSnapshot(t, ctx, snapshotSingleton, "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(binaryDir, "vendor_bin.json"),
+ filepath.Join(binaryDir, "vendor_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, "libvendor_headers.json"))
+
+ // For object modules, all vendor:true and vendor_available modules are captured.
+ objectVariant := fmt.Sprintf("android_vendor.VER_%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)
+ }
+ }
+
+ // fake snapshot should have all outputs in the normal snapshot.
+ fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot")
+ for _, output := range snapshotSingleton.AllOutputs() {
+ fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1)
+ if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil {
+ t.Errorf("%q expected but not found", fakeOutput)
+ }
+ }
+}
+
+func TestVendorSnapshotDirected(t *testing.T) {
+ bp := `
+ cc_library_shared {
+ name: "libvendor",
+ vendor: true,
+ nocrt: true,
+ }
+
+ cc_library_shared {
+ name: "libvendor_available",
+ vendor_available: true,
+ nocrt: true,
+ }
+
+ genrule {
+ name: "libfoo_gen",
+ cmd: "",
+ out: ["libfoo.so"],
+ }
+
+ cc_prebuilt_library_shared {
+ name: "libfoo",
+ vendor: true,
+ prefer: true,
+ srcs: [":libfoo_gen"],
+ }
+
+ cc_library_shared {
+ name: "libfoo",
+ vendor: true,
+ nocrt: true,
+ }
+`
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ config.TestProductVariables.DirectedVendorSnapshot = true
+ config.TestProductVariables.VendorSnapshotModules = make(map[string]bool)
+ config.TestProductVariables.VendorSnapshotModules["libvendor"] = true
+ config.TestProductVariables.VendorSnapshotModules["libfoo"] = true
+ ctx := testCcWithConfig(t, config)
+
+ // Check Vendor snapshot output.
+
+ snapshotDir := "vendor-snapshot"
+ snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
+
+ var includeJsonFiles []string
+
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ []string{"arm", "armv7-a-neon"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
+
+ sharedVariant := fmt.Sprintf("android_vendor.VER_%s_%s_shared", archType, archVariant)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+
+ // Included modules
+ checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json"))
+ // Check that snapshot captures "prefer: true" prebuilt
+ checkSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json"))
+
+ // Excluded modules. Modules not included in the directed vendor snapshot
+ // are still include as fake modules.
+ checkSnapshotRule(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor_available.so.json"))
+ }
+
+ // Verify that each json file for an included module has a rule.
+ for _, jsonFile := range includeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("include json file %q not found", jsonFile)
+ }
+ }
+}
+
+func TestVendorSnapshotUse(t *testing.T) {
+ frameworkBp := `
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ compile_multilib: "64",
+ }
+
+ cc_library {
+ name: "libvendor",
+ vendor: true,
+ nocrt: true,
+ no_libcrt: true,
+ stl: "none",
+ system_shared_libs: [],
+ compile_multilib: "64",
+ }
+
+ cc_library {
+ name: "libvendor_available",
+ vendor_available: true,
+ nocrt: true,
+ no_libcrt: true,
+ stl: "none",
+ system_shared_libs: [],
+ compile_multilib: "64",
+ }
+
+ cc_binary {
+ name: "bin",
+ vendor: true,
+ nocrt: true,
+ no_libcrt: true,
+ stl: "none",
+ system_shared_libs: [],
+ compile_multilib: "64",
+ }
+`
+
+ vndkBp := `
+ vndk_prebuilt_shared {
+ name: "libvndk",
+ version: "BOARD",
+ target_arch: "arm64",
+ vendor_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ },
+ arch: {
+ arm64: {
+ srcs: ["libvndk.so"],
+ export_include_dirs: ["include/libvndk"],
+ },
+ },
+ }
+
+ // old snapshot module which has to be ignored
+ vndk_prebuilt_shared {
+ name: "libvndk",
+ version: "OLD",
+ target_arch: "arm64",
+ vendor_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ },
+ arch: {
+ arm64: {
+ srcs: ["libvndk.so"],
+ export_include_dirs: ["include/libvndk"],
+ },
+ },
+ }
+`
+
+ vendorProprietaryBp := `
+ cc_library {
+ name: "libvendor_without_snapshot",
+ vendor: true,
+ nocrt: true,
+ no_libcrt: true,
+ stl: "none",
+ system_shared_libs: [],
+ compile_multilib: "64",
+ }
+
+ cc_library_shared {
+ name: "libclient",
+ vendor: true,
+ nocrt: true,
+ no_libcrt: true,
+ stl: "none",
+ system_shared_libs: [],
+ shared_libs: ["libvndk", "libvendor_available"],
+ static_libs: ["libvendor", "libvendor_without_snapshot"],
+ compile_multilib: "64",
+ srcs: ["client.cpp"],
+ }
+
+ cc_binary {
+ name: "bin_without_snapshot",
+ vendor: true,
+ nocrt: true,
+ no_libcrt: true,
+ stl: "none",
+ system_shared_libs: [],
+ static_libs: ["libvndk"],
+ compile_multilib: "64",
+ srcs: ["bin.cpp"],
+ }
+
+ vendor_snapshot {
+ name: "vendor_snapshot",
+ compile_multilib: "first",
+ version: "BOARD",
+ vndk_libs: [
+ "libvndk",
+ ],
+ static_libs: [
+ "libvendor",
+ "libvendor_available",
+ "libvndk",
+ ],
+ shared_libs: [
+ "libvendor",
+ "libvendor_available",
+ ],
+ binaries: [
+ "bin",
+ ],
+ }
+
+ vendor_snapshot_static {
+ name: "libvndk",
+ version: "BOARD",
+ target_arch: "arm64",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "libvndk.a",
+ export_include_dirs: ["include/libvndk"],
+ },
+ },
+ }
+
+ vendor_snapshot_shared {
+ name: "libvendor",
+ version: "BOARD",
+ target_arch: "arm64",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "libvendor.so",
+ export_include_dirs: ["include/libvendor"],
+ },
+ },
+ }
+
+ vendor_snapshot_static {
+ name: "libvendor",
+ version: "BOARD",
+ target_arch: "arm64",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "libvendor.a",
+ export_include_dirs: ["include/libvendor"],
+ },
+ },
+ }
+
+ vendor_snapshot_shared {
+ name: "libvendor_available",
+ androidmk_suffix: ".vendor",
+ version: "BOARD",
+ target_arch: "arm64",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "libvendor_available.so",
+ export_include_dirs: ["include/libvendor"],
+ },
+ },
+ }
+
+ vendor_snapshot_static {
+ name: "libvendor_available",
+ androidmk_suffix: ".vendor",
+ version: "BOARD",
+ target_arch: "arm64",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "libvendor_available.a",
+ export_include_dirs: ["include/libvendor"],
+ },
+ },
+ }
+
+ vendor_snapshot_binary {
+ name: "bin",
+ version: "BOARD",
+ target_arch: "arm64",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "bin",
+ },
+ },
+ }
+
+ // old snapshot module which has to be ignored
+ vendor_snapshot_binary {
+ name: "bin",
+ version: "OLD",
+ target_arch: "arm64",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "bin",
+ },
+ },
+ }
+`
+ depsBp := GatherRequiredDepsForTest(android.Android)
+
+ mockFS := map[string][]byte{
+ "deps/Android.bp": []byte(depsBp),
+ "framework/Android.bp": []byte(frameworkBp),
+ "vendor/Android.bp": []byte(vendorProprietaryBp),
+ "vendor/bin": nil,
+ "vendor/bin.cpp": nil,
+ "vendor/client.cpp": nil,
+ "vendor/include/libvndk/a.h": nil,
+ "vendor/include/libvendor/b.h": nil,
+ "vendor/libvndk.a": nil,
+ "vendor/libvendor.a": nil,
+ "vendor/libvendor.so": nil,
+ "vndk/Android.bp": []byte(vndkBp),
+ "vndk/include/libvndk/a.h": nil,
+ "vndk/libvndk.so": nil,
+ }
+
+ config := TestConfig(buildDir, android.Android, nil, "", mockFS)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("BOARD")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ ctx := CreateTestContext(config)
+ ctx.Register()
+
+ _, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "vendor/Android.bp", "vndk/Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ sharedVariant := "android_vendor.BOARD_arm64_armv8-a_shared"
+ staticVariant := "android_vendor.BOARD_arm64_armv8-a_static"
+ binaryVariant := "android_vendor.BOARD_arm64_armv8-a"
+
+ // libclient uses libvndk.vndk.BOARD.arm64, libvendor.vendor_static.BOARD.arm64, libvendor_without_snapshot
+ libclientCcFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("cc").Args["cFlags"]
+ for _, includeFlags := range []string{
+ "-Ivndk/include/libvndk", // libvndk
+ "-Ivendor/include/libvendor", // libvendor
+ } {
+ if !strings.Contains(libclientCcFlags, includeFlags) {
+ t.Errorf("flags for libclient must contain %#v, but was %#v.",
+ includeFlags, libclientCcFlags)
+ }
+ }
+
+ libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("ld").Args["libFlags"]
+ for _, input := range [][]string{
+ []string{sharedVariant, "libvndk.vndk.BOARD.arm64"},
+ []string{staticVariant, "libvendor.vendor_static.BOARD.arm64"},
+ []string{staticVariant, "libvendor_without_snapshot"},
+ } {
+ outputPaths := getOutputPaths(ctx, input[0] /* variant */, []string{input[1]} /* module name */)
+ if !strings.Contains(libclientLdFlags, outputPaths[0].String()) {
+ t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientLdFlags)
+ }
+ }
+
+ libclientAndroidMkSharedLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkSharedLibs
+ if g, w := libclientAndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor"}; !reflect.DeepEqual(g, w) {
+ t.Errorf("wanted libclient AndroidMkSharedLibs %q, got %q", w, g)
+ }
+
+ libclientAndroidMkStaticLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkStaticLibs
+ if g, w := libclientAndroidMkStaticLibs, []string{"libvendor", "libvendor_without_snapshot"}; !reflect.DeepEqual(g, w) {
+ t.Errorf("wanted libclient AndroidMkStaticLibs %q, got %q", w, g)
+ }
+
+ // bin_without_snapshot uses libvndk.vendor_static.BOARD.arm64
+ binWithoutSnapshotCcFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("cc").Args["cFlags"]
+ if !strings.Contains(binWithoutSnapshotCcFlags, "-Ivendor/include/libvndk") {
+ t.Errorf("flags for bin_without_snapshot must contain %#v, but was %#v.",
+ "-Ivendor/include/libvndk", binWithoutSnapshotCcFlags)
+ }
+
+ binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("ld").Args["libFlags"]
+ libVndkStaticOutputPaths := getOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.BOARD.arm64"})
+ if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) {
+ t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v",
+ libVndkStaticOutputPaths[0], binWithoutSnapshotLdFlags)
+ }
+
+ // libvendor.so is installed by libvendor.vendor_shared.BOARD.arm64
+ ctx.ModuleForTests("libvendor.vendor_shared.BOARD.arm64", sharedVariant).Output("libvendor.so")
+
+ // libvendor_available.so is installed by libvendor_available.vendor_shared.BOARD.arm64
+ ctx.ModuleForTests("libvendor_available.vendor_shared.BOARD.arm64", sharedVariant).Output("libvendor_available.so")
+
+ // libvendor_without_snapshot.so is installed by libvendor_without_snapshot
+ ctx.ModuleForTests("libvendor_without_snapshot", sharedVariant).Output("libvendor_without_snapshot.so")
+
+ // bin is installed by bin.vendor_binary.BOARD.arm64
+ ctx.ModuleForTests("bin.vendor_binary.BOARD.arm64", binaryVariant).Output("bin")
+
+ // bin_without_snapshot is installed by bin_without_snapshot
+ ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Output("bin_without_snapshot")
+
+ // libvendor, libvendor_available and bin don't have vendor.BOARD variant
+ libvendorVariants := ctx.ModuleVariantsForTests("libvendor")
+ if inList(sharedVariant, libvendorVariants) {
+ t.Errorf("libvendor must not have variant %#v, but it does", sharedVariant)
+ }
+
+ libvendorAvailableVariants := ctx.ModuleVariantsForTests("libvendor_available")
+ if inList(sharedVariant, libvendorAvailableVariants) {
+ t.Errorf("libvendor_available must not have variant %#v, but it does", sharedVariant)
+ }
+
+ binVariants := ctx.ModuleVariantsForTests("bin")
+ if inList(binaryVariant, binVariants) {
+ t.Errorf("bin must not have variant %#v, but it does", sharedVariant)
+ }
+}
+
+func TestVendorSnapshotSanitizer(t *testing.T) {
+ bp := `
+ vendor_snapshot_static {
+ name: "libsnapshot",
+ vendor: true,
+ target_arch: "arm64",
+ version: "BOARD",
+ arch: {
+ arm64: {
+ src: "libsnapshot.a",
+ cfi: {
+ src: "libsnapshot.cfi.a",
+ }
+ },
+ },
+ }
+`
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("BOARD")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ ctx := testCcWithConfig(t, config)
+
+ // Check non-cfi and cfi variant.
+ staticVariant := "android_vendor.BOARD_arm64_armv8-a_static"
+ staticCfiVariant := "android_vendor.BOARD_arm64_armv8-a_static_cfi"
+
+ staticModule := ctx.ModuleForTests("libsnapshot.vendor_static.BOARD.arm64", staticVariant).Module().(*Module)
+ assertString(t, staticModule.outputFile.Path().Base(), "libsnapshot.a")
+
+ staticCfiModule := ctx.ModuleForTests("libsnapshot.vendor_static.BOARD.arm64", staticCfiVariant).Module().(*Module)
+ assertString(t, staticCfiModule.outputFile.Path().Base(), "libsnapshot.cfi.a")
+}
+
+func assertExcludeFromVendorSnapshotIs(t *testing.T, ctx *android.TestContext, name string, expected bool) {
+ t.Helper()
+ m := ctx.ModuleForTests(name, vendorVariant).Module().(*Module)
+ if m.ExcludeFromVendorSnapshot() != expected {
+ t.Errorf("expected %q ExcludeFromVendorSnapshot to be %t", m.String(), expected)
+ }
+}
+
+func assertExcludeFromRecoverySnapshotIs(t *testing.T, ctx *android.TestContext, name string, expected bool) {
+ t.Helper()
+ m := ctx.ModuleForTests(name, recoveryVariant).Module().(*Module)
+ if m.ExcludeFromRecoverySnapshot() != expected {
+ t.Errorf("expected %q ExcludeFromRecoverySnapshot to be %t", m.String(), expected)
+ }
+}
+
+func TestVendorSnapshotExclude(t *testing.T) {
+
+ // This test verifies that the exclude_from_vendor_snapshot property
+ // makes its way from the Android.bp source file into the module data
+ // structure. It also verifies that modules are correctly included or
+ // excluded in the vendor snapshot based on their path (framework or
+ // vendor) and the exclude_from_vendor_snapshot property.
+
+ frameworkBp := `
+ cc_library_shared {
+ name: "libinclude",
+ srcs: ["src/include.cpp"],
+ vendor_available: true,
+ }
+ cc_library_shared {
+ name: "libexclude",
+ srcs: ["src/exclude.cpp"],
+ vendor: true,
+ exclude_from_vendor_snapshot: true,
+ }
+ cc_library_shared {
+ name: "libavailable_exclude",
+ srcs: ["src/exclude.cpp"],
+ vendor_available: true,
+ exclude_from_vendor_snapshot: true,
+ }
+ `
+
+ vendorProprietaryBp := `
+ cc_library_shared {
+ name: "libvendor",
+ srcs: ["vendor.cpp"],
+ vendor: true,
+ }
+ `
+
+ depsBp := GatherRequiredDepsForTest(android.Android)
+
+ mockFS := map[string][]byte{
+ "deps/Android.bp": []byte(depsBp),
+ "framework/Android.bp": []byte(frameworkBp),
+ "framework/include.cpp": nil,
+ "framework/exclude.cpp": nil,
+ "device/Android.bp": []byte(vendorProprietaryBp),
+ "device/vendor.cpp": nil,
+ }
+
+ config := TestConfig(buildDir, android.Android, nil, "", mockFS)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ ctx := CreateTestContext(config)
+ ctx.Register()
+
+ _, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "device/Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ // Test an include and exclude framework module.
+ assertExcludeFromVendorSnapshotIs(t, ctx, "libinclude", false)
+ assertExcludeFromVendorSnapshotIs(t, ctx, "libexclude", true)
+ assertExcludeFromVendorSnapshotIs(t, ctx, "libavailable_exclude", true)
+
+ // A vendor module is excluded, but by its path, not the
+ // exclude_from_vendor_snapshot property.
+ assertExcludeFromVendorSnapshotIs(t, ctx, "libvendor", false)
+
+ // Verify the content of the vendor snapshot.
+
+ snapshotDir := "vendor-snapshot"
+ snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
+
+ var includeJsonFiles []string
+ var excludeJsonFiles []string
+
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ []string{"arm", "armv7-a-neon"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
+
+ sharedVariant := fmt.Sprintf("android_vendor.VER_%s_%s_shared", archType, archVariant)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+
+ // Included modules
+ checkSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
+
+ // Excluded modules
+ checkSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
+ checkSnapshotExclude(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json"))
+ checkSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
+ }
+
+ // Verify that each json file for an included module has a rule.
+ for _, jsonFile := range includeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("include json file %q not found", jsonFile)
+ }
+ }
+
+ // Verify that each json file for an excluded module has no rule.
+ for _, jsonFile := range excludeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
+ t.Errorf("exclude json file %q found", jsonFile)
+ }
+ }
+}
+
+func TestVendorSnapshotExcludeInVendorProprietaryPathErrors(t *testing.T) {
+
+ // This test verifies that using the exclude_from_vendor_snapshot
+ // property on a module in a vendor proprietary path generates an
+ // error. These modules are already excluded, so we prohibit using the
+ // property in this way, which could add to confusion.
+
+ vendorProprietaryBp := `
+ cc_library_shared {
+ name: "libvendor",
+ srcs: ["vendor.cpp"],
+ vendor: true,
+ exclude_from_vendor_snapshot: true,
+ }
+ `
+
+ depsBp := GatherRequiredDepsForTest(android.Android)
+
+ mockFS := map[string][]byte{
+ "deps/Android.bp": []byte(depsBp),
+ "device/Android.bp": []byte(vendorProprietaryBp),
+ "device/vendor.cpp": nil,
+ }
+
+ config := TestConfig(buildDir, android.Android, nil, "", mockFS)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ ctx := CreateTestContext(config)
+ ctx.Register()
+
+ _, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "device/Android.bp"})
+ android.FailIfErrored(t, errs)
+
+ _, errs = ctx.PrepareBuildActions(config)
+ 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"`,
+ `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"`,
+ })
+}
+
+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.RecoverySnapshotVersion = 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 TestRecoverySnapshotExclude(t *testing.T) {
+ // This test verifies that the exclude_from_recovery_snapshot property
+ // makes its way from the Android.bp source file into the module data
+ // structure. It also verifies that modules are correctly included or
+ // excluded in the recovery snapshot based on their path (framework or
+ // vendor) and the exclude_from_recovery_snapshot property.
+
+ frameworkBp := `
+ cc_library_shared {
+ name: "libinclude",
+ srcs: ["src/include.cpp"],
+ recovery_available: true,
+ }
+ cc_library_shared {
+ name: "libexclude",
+ srcs: ["src/exclude.cpp"],
+ recovery: true,
+ exclude_from_recovery_snapshot: true,
+ }
+ cc_library_shared {
+ name: "libavailable_exclude",
+ srcs: ["src/exclude.cpp"],
+ recovery_available: true,
+ exclude_from_recovery_snapshot: true,
+ }
+ `
+
+ vendorProprietaryBp := `
+ cc_library_shared {
+ name: "librecovery",
+ srcs: ["recovery.cpp"],
+ recovery: true,
+ }
+ `
+
+ depsBp := GatherRequiredDepsForTest(android.Android)
+
+ mockFS := map[string][]byte{
+ "deps/Android.bp": []byte(depsBp),
+ "framework/Android.bp": []byte(frameworkBp),
+ "framework/include.cpp": nil,
+ "framework/exclude.cpp": nil,
+ "device/Android.bp": []byte(vendorProprietaryBp),
+ "device/recovery.cpp": nil,
+ }
+
+ config := TestConfig(buildDir, android.Android, nil, "", mockFS)
+ config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ ctx := CreateTestContext(config)
+ ctx.Register()
+
+ _, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "device/Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ // Test an include and exclude framework module.
+ assertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude", false)
+ assertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude", true)
+ assertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude", true)
+
+ // A recovery module is excluded, but by its path, not the
+ // exclude_from_recovery_snapshot property.
+ assertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery", false)
+
+ // Verify the content of the recovery snapshot.
+
+ snapshotDir := "recovery-snapshot"
+ snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
+
+ var includeJsonFiles []string
+ var excludeJsonFiles []string
+
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
+
+ sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+
+ // Included modules
+ checkSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
+
+ // Excluded modules
+ checkSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
+ checkSnapshotExclude(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
+ checkSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
+ }
+
+ // Verify that each json file for an included module has a rule.
+ for _, jsonFile := range includeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("include json file %q not found", jsonFile)
+ }
+ }
+
+ // Verify that each json file for an excluded module has no rule.
+ for _, jsonFile := range excludeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
+ t.Errorf("exclude json file %q found", jsonFile)
+ }
+ }
+}
+
+func TestRecoverySnapshotDirected(t *testing.T) {
+ bp := `
+ cc_library_shared {
+ name: "librecovery",
+ recovery: true,
+ nocrt: true,
+ }
+
+ cc_library_shared {
+ name: "librecovery_available",
+ recovery_available: true,
+ nocrt: true,
+ }
+
+ genrule {
+ name: "libfoo_gen",
+ cmd: "",
+ out: ["libfoo.so"],
+ }
+
+ cc_prebuilt_library_shared {
+ name: "libfoo",
+ recovery: true,
+ prefer: true,
+ srcs: [":libfoo_gen"],
+ }
+
+ cc_library_shared {
+ name: "libfoo",
+ recovery: true,
+ nocrt: true,
+ }
+`
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ config.TestProductVariables.DirectedRecoverySnapshot = true
+ config.TestProductVariables.RecoverySnapshotModules = make(map[string]bool)
+ config.TestProductVariables.RecoverySnapshotModules["librecovery"] = true
+ config.TestProductVariables.RecoverySnapshotModules["libfoo"] = true
+ ctx := testCcWithConfig(t, config)
+
+ // Check recovery snapshot output.
+
+ snapshotDir := "recovery-snapshot"
+ snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
+
+ var includeJsonFiles []string
+
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
+
+ sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+
+ // Included modules
+ checkSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
+ // Check that snapshot captures "prefer: true" prebuilt
+ checkSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json"))
+
+ // Excluded modules. Modules not included in the directed recovery snapshot
+ // are still include as fake modules.
+ checkSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery_available.so.json"))
+ }
+
+ // Verify that each json file for an included module has a rule.
+ for _, jsonFile := range includeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("include json file %q not found", jsonFile)
+ }
+ }
+}
+
+func TestRamdiskSnapshotCapture(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ ramdisk_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libramdisk",
+ ramdisk: true,
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libramdisk_available",
+ ramdisk_available: true,
+ nocrt: true,
+ }
+
+ cc_library_headers {
+ name: "libramdisk_headers",
+ ramdisk_available: true,
+ nocrt: true,
+ }
+
+ cc_binary {
+ name: "ramdisk_bin",
+ ramdisk: true,
+ nocrt: true,
+ }
+
+ cc_binary {
+ name: "ramdisk_available_bin",
+ ramdisk_available: true,
+ nocrt: true,
+ }
+
+ toolchain_library {
+ name: "libb",
+ ramdisk_available: true,
+ src: "libb.a",
+ }
+
+ cc_object {
+ name: "obj",
+ ramdisk_available: true,
+ }
+`
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.RamdiskSnapshotVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ ctx := testCcWithConfig(t, config)
+
+ // Check Ramdisk snapshot output.
+
+ snapshotDir := "ramdisk-snapshot"
+ snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("ramdisk-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 ramdisk_available modules are captured.
+ sharedVariant := fmt.Sprintf("android_ramdisk_%s_%s_shared", archType, archVariant)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+ checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", sharedDir, sharedVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libramdisk", "libramdisk.so", sharedDir, sharedVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libramdisk_available", "libramdisk_available.so", sharedDir, sharedVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(sharedDir, "libvndk.so.json"),
+ filepath.Join(sharedDir, "libramdisk.so.json"),
+ filepath.Join(sharedDir, "libramdisk_available.so.json"))
+
+ // For static libraries, all ramdisk:true and ramdisk_available modules are captured.
+ staticVariant := fmt.Sprintf("android_ramdisk_%s_%s_static", archType, archVariant)
+ staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
+ checkSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libramdisk", "libramdisk.a", staticDir, staticVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "libramdisk_available", "libramdisk_available.a", staticDir, staticVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(staticDir, "libb.a.json"),
+ filepath.Join(staticDir, "libramdisk.a.json"),
+ filepath.Join(staticDir, "libramdisk_available.a.json"))
+
+ // For binary executables, all ramdisk:true and ramdisk_available modules are captured.
+ if archType == "arm64" {
+ binaryVariant := fmt.Sprintf("android_ramdisk_%s_%s", archType, archVariant)
+ binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
+ checkSnapshot(t, ctx, snapshotSingleton, "ramdisk_bin", "ramdisk_bin", binaryDir, binaryVariant)
+ checkSnapshot(t, ctx, snapshotSingleton, "ramdisk_available_bin", "ramdisk_available_bin", binaryDir, binaryVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(binaryDir, "ramdisk_bin.json"),
+ filepath.Join(binaryDir, "ramdisk_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, "libramdisk_headers.json"))
+
+ // For object modules, all vendor:true and vendor_available modules are captured.
+ objectVariant := fmt.Sprintf("android_ramdisk_%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 TestRamdiskSnapshotExclude(t *testing.T) {
+ // This test verifies that the exclude_from_ramdisk_snapshot property
+ // makes its way from the Android.bp source file into the module data
+ // structure. It also verifies that modules are correctly included or
+ // excluded in the ramdisk snapshot based on their path (framework or
+ // vendor) and the exclude_from_ramdisk_snapshot property.
+
+ frameworkBp := `
+ cc_library_shared {
+ name: "libinclude",
+ srcs: ["src/include.cpp"],
+ ramdisk_available: true,
+ }
+ cc_library_shared {
+ name: "libexclude",
+ srcs: ["src/exclude.cpp"],
+ ramdisk: true,
+ exclude_from_ramdisk_snapshot: true,
+ }
+ cc_library_shared {
+ name: "libavailable_exclude",
+ srcs: ["src/exclude.cpp"],
+ ramdisk_available: true,
+ exclude_from_ramdisk_snapshot: true,
+ }
+ `
+
+ vendorProprietaryBp := `
+ cc_library_shared {
+ name: "libramdisk",
+ srcs: ["ramdisk.cpp"],
+ ramdisk: true,
+ }
+ `
+
+ depsBp := GatherRequiredDepsForTest(android.Android)
+
+ mockFS := map[string][]byte{
+ "deps/Android.bp": []byte(depsBp),
+ "framework/Android.bp": []byte(frameworkBp),
+ "framework/include.cpp": nil,
+ "framework/exclude.cpp": nil,
+ "device/Android.bp": []byte(vendorProprietaryBp),
+ "device/ramdisk.cpp": nil,
+ }
+
+ config := TestConfig(buildDir, android.Android, nil, "", mockFS)
+ config.TestProductVariables.RamdiskSnapshotVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ ctx := CreateTestContext(config)
+ ctx.Register()
+
+ _, errs := ctx.ParseFileList(".", []string{"deps/Android.bp", "framework/Android.bp", "device/Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ // Test an include and exclude framework module.
+ assertExcludeFromRamdiskSnapshotIs(t, ctx, "libinclude", false)
+ assertExcludeFromRamdiskSnapshotIs(t, ctx, "libexclude", true)
+ assertExcludeFromRamdiskSnapshotIs(t, ctx, "libavailable_exclude", true)
+
+ // A ramdisk module is excluded, but by its path, not the
+ // exclude_from_ramdisk_snapshot property.
+ assertExcludeFromRamdiskSnapshotIs(t, ctx, "libramdisk", false)
+
+ // Verify the content of the ramdisk snapshot.
+
+ snapshotDir := "ramdisk-snapshot"
+ snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("ramdisk-snapshot")
+
+ var includeJsonFiles []string
+ var excludeJsonFiles []string
+
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
+
+ sharedVariant := fmt.Sprintf("android_ramdisk_%s_%s_shared", archType, archVariant)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+
+ // Included modules
+ checkSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
+
+ // Excluded modules
+ checkSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
+ checkSnapshotExclude(t, ctx, snapshotSingleton, "libramdisk", "libramdisk.so", sharedDir, sharedVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libramdisk.so.json"))
+ checkSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
+ }
+
+ // Verify that each json file for an included module has a rule.
+ for _, jsonFile := range includeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("include json file %q not found", jsonFile)
+ }
+ }
+
+ // Verify that each json file for an excluded module has no rule.
+ for _, jsonFile := range excludeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
+ t.Errorf("exclude json file %q found", jsonFile)
+ }
+ }
+}
+
+func TestRamdiskSnapshotDirected(t *testing.T) {
+ bp := `
+ cc_library_shared {
+ name: "libramdisk",
+ ramdisk: true,
+ nocrt: true,
+ }
+
+ cc_library_shared {
+ name: "libramdisk_available",
+ ramdisk_available: true,
+ nocrt: true,
+ }
+
+ genrule {
+ name: "libfoo_gen",
+ cmd: "",
+ out: ["libfoo.so"],
+ }
+
+ cc_prebuilt_library_shared {
+ name: "libfoo",
+ ramdisk: true,
+ prefer: true,
+ srcs: [":libfoo_gen"],
+ }
+
+ cc_library_shared {
+ name: "libfoo",
+ ramdisk: true,
+ nocrt: true,
+ }
+`
+ config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
+ config.TestProductVariables.RamdiskSnapshotVersion = StringPtr("current")
+ config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
+ config.TestProductVariables.DirectedRamdiskSnapshot = true
+ config.TestProductVariables.RamdiskSnapshotModules = make(map[string]bool)
+ config.TestProductVariables.RamdiskSnapshotModules["libramdisk"] = true
+ config.TestProductVariables.RamdiskSnapshotModules["libfoo"] = true
+ ctx := testCcWithConfig(t, config)
+
+ // Check ramdisk snapshot output.
+
+ snapshotDir := "ramdisk-snapshot"
+ snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("ramdisk-snapshot")
+
+ var includeJsonFiles []string
+
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
+
+ sharedVariant := fmt.Sprintf("android_ramdisk_%s_%s_shared", archType, archVariant)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+
+ // Included modules
+ checkSnapshot(t, ctx, snapshotSingleton, "libramdisk", "libramdisk.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libramdisk.so.json"))
+ // Check that snapshot captures "prefer: true" prebuilt
+ checkSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json"))
+
+ // Excluded modules. Modules not included in the directed ramdisk snapshot
+ // are still include as fake modules.
+ checkSnapshotRule(t, ctx, snapshotSingleton, "libramdisk_available", "libramdisk_available.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libramdisk_available.so.json"))
+ }
+
+ // Verify that each json file for an included module has a rule.
+ for _, jsonFile := range includeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("include json file %q not found", jsonFile)
+ }
+ }
+}
diff --git a/cc/vndk.go b/cc/vndk.go
index a060869..339102e 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -616,7 +616,7 @@
libPath := m.outputFile.Path()
snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "shared", vndkType, libPath.Base())
- ret = append(ret, copyFile(ctx, libPath, snapshotLibOut))
+ ret = append(ret, copyFileRule(ctx, libPath, snapshotLibOut))
if ctx.Config().VndkSnapshotBuildArtifacts() {
prop := struct {
@@ -637,7 +637,7 @@
ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
return nil, false
}
- ret = append(ret, writeStringToFile(ctx, string(j), propOut))
+ ret = append(ret, writeStringToFileRule(ctx, string(j), propOut))
}
return ret, true
}
@@ -671,7 +671,7 @@
// skip already copied notice file
if _, ok := noticeBuilt[noticeName]; !ok {
noticeBuilt[noticeName] = true
- snapshotOutputs = append(snapshotOutputs, copyFile(
+ snapshotOutputs = append(snapshotOutputs, copyFileRule(
ctx, m.NoticeFile().Path(), filepath.Join(noticeDir, noticeName)))
}
}
@@ -683,7 +683,7 @@
// install all headers after removing duplicates
for _, header := range android.FirstUniquePaths(headers) {
- snapshotOutputs = append(snapshotOutputs, copyFile(
+ snapshotOutputs = append(snapshotOutputs, copyFileRule(
ctx, header, filepath.Join(includeDir, header.String())))
}
@@ -693,7 +693,7 @@
if !ok || !m.Enabled() || m.Name() == vndkUsingCoreVariantLibrariesTxt {
return
}
- snapshotOutputs = append(snapshotOutputs, copyFile(
+ snapshotOutputs = append(snapshotOutputs, copyFileRule(
ctx, m.OutputFile(), filepath.Join(configsDir, m.Name())))
})
@@ -714,7 +714,7 @@
txtBuilder.WriteString(" ")
txtBuilder.WriteString(m[k])
}
- return writeStringToFile(ctx, txtBuilder.String(), path)
+ return writeStringToFileRule(ctx, txtBuilder.String(), path)
}
/*
diff --git a/genrule/genrule.go b/genrule/genrule.go
index fe877fe..9f21a35 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -31,10 +31,10 @@
)
func init() {
- registerGenruleBuildComponents(android.InitRegistrationContext)
+ RegisterGenruleBuildComponents(android.InitRegistrationContext)
}
-func registerGenruleBuildComponents(ctx android.RegistrationContext) {
+func RegisterGenruleBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("genrule_defaults", defaultsFactory)
ctx.RegisterModuleType("gensrcs", GenSrcsFactory)
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 4b36600..ff5c8e9 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -57,7 +57,7 @@
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("tool", toolFactory)
- registerGenruleBuildComponents(ctx)
+ RegisterGenruleBuildComponents(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
ctx.Register(config)
diff --git a/java/Android.bp b/java/Android.bp
index 1fda7f7..f9ef551 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -57,6 +57,7 @@
"device_host_converter_test.go",
"dexpreopt_test.go",
"dexpreopt_bootjars_test.go",
+ "hiddenapi_singleton_test.go",
"java_test.go",
"jdeps_test.go",
"kotlin_test.go",
diff --git a/java/androidmk.go b/java/androidmk.go
index ae257d7..8b7df6f 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -127,8 +127,8 @@
entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", library.additionalCheckedModules.Strings()...)
}
- if library.proguardDictionary != nil {
- entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.proguardDictionary)
+ if library.dexer.proguardDictionary.Valid() {
+ entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.dexer.proguardDictionary.Path())
}
entries.SetString("LOCAL_MODULE_STEM", library.Stem())
@@ -194,9 +194,12 @@
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !Bool(prebuilt.properties.Installable))
+ if prebuilt.dexJarFile != nil {
+ entries.SetPath("LOCAL_SOONG_DEX_JAR", prebuilt.dexJarFile)
+ }
entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.combinedClasspathFile)
entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.combinedClasspathFile)
- entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion().raw)
+ entries.SetString("LOCAL_SDK_VERSION", prebuilt.makeSdkVersion())
entries.SetString("LOCAL_MODULE_STEM", prebuilt.Stem())
},
},
@@ -332,8 +335,8 @@
if app.jacocoReportClassesFile != nil {
entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", app.jacocoReportClassesFile)
}
- if app.proguardDictionary != nil {
- entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", app.proguardDictionary)
+ if app.dexer.proguardDictionary.Valid() {
+ entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", app.dexer.proguardDictionary.Path())
}
if app.Name() == "framework-res" {
@@ -678,6 +681,9 @@
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", a.dexpreopter.builtInstalled)
}
entries.AddStrings("LOCAL_INSTALLED_MODULE_STEM", a.installPath.Rel())
+ if Bool(a.properties.Export_package_resources) {
+ entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", a.outputFile)
+ }
},
},
}}
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index 7daa624..32e6f0e 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -169,3 +169,25 @@
t.Errorf("did not expect explicit DistFile, got %v", without_tag_entries[0].DistFile)
}
}
+
+func TestImportSoongDexJar(t *testing.T) {
+ ctx, config := testJava(t, `
+ java_import {
+ name: "my-java-import",
+ jars: ["a.jar"],
+ prefer: true,
+ compile_dex: true,
+ }
+ `)
+
+ mod := ctx.ModuleForTests("my-java-import", "android_common").Module()
+ entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+ expectedSoongDexJar := buildDir + "/.intermediates/my-java-import/android_common/dex/my-java-import.jar"
+ actualSoongDexJar := entries.EntryMap["LOCAL_SOONG_DEX_JAR"]
+
+ if len(actualSoongDexJar) != 1 {
+ t.Errorf("LOCAL_SOONG_DEX_JAR incorrect len %d", len(actualSoongDexJar))
+ } else if actualSoongDexJar[0] != expectedSoongDexJar {
+ t.Errorf("LOCAL_SOONG_DEX_JAR mismatch, actual: %s, expected: %s", actualSoongDexJar[0], expectedSoongDexJar)
+ }
+}
diff --git a/java/app.go b/java/app.go
index 2ec27f3..0c9fb9a 100755
--- a/java/app.go
+++ b/java/app.go
@@ -585,11 +585,11 @@
func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
a.dexpreopter.installPath = a.installPath(ctx)
- if a.deviceProperties.Uncompress_dex == nil {
+ if a.dexProperties.Uncompress_dex == nil {
// If the value was not force-set by the user, use reasonable default based on the module.
- a.deviceProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx))
+ a.dexProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx))
}
- a.dexpreopter.uncompressedDex = *a.deviceProperties.Uncompress_dex
+ a.dexpreopter.uncompressedDex = *a.dexProperties.Uncompress_dex
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
@@ -1001,8 +1001,8 @@
func AndroidAppFactory() android.Module {
module := &AndroidApp{}
- module.Module.deviceProperties.Optimize.EnabledByDefault = true
- module.Module.deviceProperties.Optimize.Shrink = proptools.BoolPtr(true)
+ module.Module.dexProperties.Optimize.EnabledByDefault = true
+ module.Module.dexProperties.Optimize.Shrink = proptools.BoolPtr(true)
module.Module.properties.Instrument = true
module.Module.properties.Installable = proptools.BoolPtr(true)
@@ -1119,7 +1119,7 @@
func AndroidTestFactory() android.Module {
module := &AndroidTest{}
- module.Module.deviceProperties.Optimize.EnabledByDefault = true
+ module.Module.dexProperties.Optimize.EnabledByDefault = true
module.Module.properties.Instrument = true
module.Module.properties.Installable = proptools.BoolPtr(true)
@@ -1170,7 +1170,7 @@
func AndroidTestHelperAppFactory() android.Module {
module := &AndroidTestHelperApp{}
- module.Module.deviceProperties.Optimize.EnabledByDefault = true
+ module.Module.dexProperties.Optimize.EnabledByDefault = true
module.Module.properties.Installable = proptools.BoolPtr(true)
module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true)
@@ -1338,6 +1338,10 @@
// Optional name for the installed app. If unspecified, it is derived from the module name.
Filename *string
+
+ // If set, create package-export.apk, which other packages can
+ // use to get PRODUCT-agnostic resource data like IDs and type definitions.
+ Export_package_resources *bool
}
func (a *AndroidAppImport) IsInstallable() bool {
@@ -1381,13 +1385,17 @@
}
}
+func (a *AndroidAppImport) isPrebuiltFrameworkRes() bool {
+ return a.Name() == "prebuilt_framework-res"
+}
+
func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) {
cert := android.SrcIsModule(String(a.properties.Certificate))
if cert != "" {
ctx.AddDependency(ctx.Module(), certificateTag, cert)
}
- a.usesLibrary.deps(ctx, true)
+ a.usesLibrary.deps(ctx, !a.isPrebuiltFrameworkRes())
}
func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
@@ -1481,7 +1489,12 @@
a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed.OutputPath)
var installDir android.InstallPath
- if Bool(a.properties.Privileged) {
+
+ if a.isPrebuiltFrameworkRes() {
+ // framework-res.apk is installed as system/framework/framework-res.apk
+ installDir = android.PathForModuleInstall(ctx, "framework")
+ a.preprocessed = true
+ } else if Bool(a.properties.Privileged) {
installDir = android.PathForModuleInstall(ctx, "priv-app", a.BaseModuleName())
} else if ctx.InstallInTestcases() {
installDir = android.PathForModuleInstall(ctx, a.BaseModuleName(), ctx.DeviceConfig().DeviceArch())
@@ -1510,7 +1523,15 @@
// TODO: Handle EXTERNAL
// Sign or align the package if package has not been preprocessed
- if a.preprocessed {
+
+ if a.isPrebuiltFrameworkRes() {
+ a.outputFile = srcApk
+ certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
+ if len(certificates) != 1 {
+ ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates)
+ }
+ a.certificate = certificates[0]
+ } else if a.preprocessed {
a.outputFile = srcApk
a.certificate = PresignedCertificate
} else if !Bool(a.properties.Presigned) {
@@ -1596,6 +1617,71 @@
return sdkSpecFrom("")
}
+func (a *AndroidAppImport) HeaderJars() android.Paths {
+ return nil
+}
+
+func (a *AndroidAppImport) ImplementationAndResourcesJars() android.Paths {
+ return nil
+}
+
+func (a *AndroidAppImport) ImplementationJars() android.Paths {
+ return nil
+}
+
+func (a *AndroidAppImport) ResourceJars() android.Paths {
+ return nil
+}
+
+func (a *AndroidAppImport) DexJar() android.Path {
+ return nil
+}
+
+func (a *AndroidAppImport) AidlIncludeDirs() android.Paths {
+ return nil
+}
+
+func (a *AndroidAppImport) ExportedSdkLibs() []string {
+ return nil
+}
+
+func (a *AndroidAppImport) ExportedPlugins() (android.Paths, []string) {
+ return nil, nil
+}
+
+func (a *AndroidAppImport) SrcJarArgs() ([]string, android.Paths) {
+ return nil, nil
+}
+
+func (a *AndroidAppImport) ExportPackage() android.Path {
+ if Bool(a.properties.Export_package_resources) {
+ return a.outputFile
+ }
+ return nil
+}
+
+func (a *AndroidAppImport) ExportedProguardFlagFiles() android.Paths {
+ return nil
+}
+
+func (a *AndroidAppImport) ExportedRRODirs() []rroDir {
+ return nil
+}
+
+func (a *AndroidAppImport) ExportedStaticPackages() android.Paths {
+ return nil
+}
+
+func (a *AndroidAppImport) ExportedManifests() android.Paths {
+ return nil
+}
+
+func (a *AndroidAppImport) ExportedAssets() android.OptionalPath {
+ return android.OptionalPath{}
+}
+
+var _ AndroidLibraryDependency = (*AndroidAppImport)(nil)
+
func createVariantGroupType(variants []string, variantGroupName string) reflect.Type {
props := reflect.TypeOf((*AndroidAppImportProperties)(nil))
diff --git a/java/app_test.go b/java/app_test.go
index 8ef3152..513767d 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2374,6 +2374,69 @@
}
}
+func TestAndroidAppImport_frameworkRes(t *testing.T) {
+ ctx, config := testJava(t, `
+ android_app_import {
+ name: "framework-res",
+ certificate: "platform",
+ apk: "package-res.apk",
+ prefer: true,
+ export_package_resources: true,
+ // Disable dexpreopt and verify_uses_libraries check as the app
+ // contains no Java code to be dexpreopted.
+ enforce_uses_libs: false,
+ dex_preopt: {
+ enabled: false,
+ },
+ }
+ `)
+
+ mod := ctx.ModuleForTests("prebuilt_framework-res", "android_common").Module()
+ a := mod.(*AndroidAppImport)
+
+ if !a.preprocessed {
+ t.Errorf("prebuilt framework-res is not preprocessed")
+ }
+
+ expectedInstallPath := buildDir + "/target/product/test_device/system/framework/framework-res.apk"
+
+ if a.dexpreopter.installPath.String() != expectedInstallPath {
+ t.Errorf("prebuilt framework-res installed to incorrect location, actual: %s, expected: %s", a.dexpreopter.installPath, expectedInstallPath)
+
+ }
+
+ entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+
+ expectedPath := "."
+ // From apk property above, in the root of the source tree.
+ expectedPrebuiltModuleFile := "package-res.apk"
+ // Verify that the apk is preprocessed: The export package is the same
+ // as the prebuilt.
+ expectedSoongResourceExportPackage := expectedPrebuiltModuleFile
+
+ actualPath := entries.EntryMap["LOCAL_PATH"]
+ actualPrebuiltModuleFile := entries.EntryMap["LOCAL_PREBUILT_MODULE_FILE"]
+ actualSoongResourceExportPackage := entries.EntryMap["LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE"]
+
+ if len(actualPath) != 1 {
+ t.Errorf("LOCAL_PATH incorrect len %d", len(actualPath))
+ } else if actualPath[0] != expectedPath {
+ t.Errorf("LOCAL_PATH mismatch, actual: %s, expected: %s", actualPath[0], expectedPath)
+ }
+
+ if len(actualPrebuiltModuleFile) != 1 {
+ t.Errorf("LOCAL_PREBUILT_MODULE_FILE incorrect len %d", len(actualPrebuiltModuleFile))
+ } else if actualPrebuiltModuleFile[0] != expectedPrebuiltModuleFile {
+ t.Errorf("LOCAL_PREBUILT_MODULE_FILE mismatch, actual: %s, expected: %s", actualPrebuiltModuleFile[0], expectedPrebuiltModuleFile)
+ }
+
+ if len(actualSoongResourceExportPackage) != 1 {
+ t.Errorf("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE incorrect len %d", len(actualSoongResourceExportPackage))
+ } else if actualSoongResourceExportPackage[0] != expectedSoongResourceExportPackage {
+ t.Errorf("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE mismatch, actual: %s, expected: %s", actualSoongResourceExportPackage[0], expectedSoongResourceExportPackage)
+ }
+}
+
func TestAndroidTestImport(t *testing.T) {
ctx, config := testJava(t, `
android_test_import {
diff --git a/java/dex.go b/java/dex.go
index 9e61e95..cd45a93 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -24,6 +24,60 @@
"android/soong/remoteexec"
)
+type DexProperties struct {
+ // If set to true, compile dex regardless of installable. Defaults to false.
+ Compile_dex *bool
+
+ // list of module-specific flags that will be used for dex compiles
+ Dxflags []string `android:"arch_variant"`
+
+ Optimize struct {
+ // If false, disable all optimization. Defaults to true for android_app and android_test
+ // modules, false for java_library and java_test modules.
+ Enabled *bool
+ // True if the module containing this has it set by default.
+ EnabledByDefault bool `blueprint:"mutated"`
+
+ // If true, optimize for size by removing unused code. Defaults to true for apps,
+ // false for libraries and tests.
+ Shrink *bool
+
+ // If true, optimize bytecode. Defaults to false.
+ Optimize *bool
+
+ // If true, obfuscate bytecode. Defaults to false.
+ Obfuscate *bool
+
+ // If true, do not use the flag files generated by aapt that automatically keep
+ // classes referenced by the app manifest. Defaults to false.
+ No_aapt_flags *bool
+
+ // Flags to pass to proguard.
+ Proguard_flags []string
+
+ // Specifies the locations of files containing proguard flags.
+ Proguard_flags_files []string `android:"path"`
+ }
+
+ // Keep the data uncompressed. We always need uncompressed dex for execution,
+ // so this might actually save space by avoiding storing the same data twice.
+ // This defaults to reasonable value based on module and should not be set.
+ // It exists only to support ART tests.
+ Uncompress_dex *bool
+}
+
+type dexer struct {
+ dexProperties DexProperties
+
+ // list of extra proguard flag files
+ extraProguardFlagFiles android.Paths
+ proguardDictionary android.OptionalPath
+}
+
+func (d *dexer) effectiveOptimizeEnabled() bool {
+ return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault)
+}
+
var d8, d8RE = remoteexec.MultiCommandStaticRules(pctx, "d8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
@@ -86,8 +140,8 @@
},
}, []string{"outDir", "outDict", "r8Flags", "zipFlags"}, []string{"implicits"})
-func (j *Module) dexCommonFlags(ctx android.ModuleContext) []string {
- flags := j.deviceProperties.Dxflags
+func (d *dexer) dexCommonFlags(ctx android.ModuleContext, minSdkVersion sdkSpec) []string {
+ flags := d.dexProperties.Dxflags
// Translate all the DX flags to D8 ones until all the build files have been migrated
// to D8 flags. See: b/69377755
flags = android.RemoveListFromList(flags,
@@ -103,30 +157,27 @@
"--verbose")
}
- minSdkVersion, err := j.minSdkVersion().effectiveVersion(ctx)
+ effectiveVersion, err := minSdkVersion.effectiveVersion(ctx)
if err != nil {
ctx.PropertyErrorf("min_sdk_version", "%s", err)
}
- flags = append(flags, "--min-api "+minSdkVersion.asNumberString())
+ flags = append(flags, "--min-api "+effectiveVersion.asNumberString())
return flags
}
-func (j *Module) d8Flags(ctx android.ModuleContext, flags javaBuilderFlags) ([]string, android.Paths) {
- d8Flags := j.dexCommonFlags(ctx)
-
+func d8Flags(flags javaBuilderFlags) (d8Flags []string, d8Deps android.Paths) {
d8Flags = append(d8Flags, flags.bootClasspath.FormRepeatedClassPath("--lib ")...)
d8Flags = append(d8Flags, flags.classpath.FormRepeatedClassPath("--lib ")...)
- var d8Deps android.Paths
d8Deps = append(d8Deps, flags.bootClasspath...)
d8Deps = append(d8Deps, flags.classpath...)
return d8Flags, d8Deps
}
-func (j *Module) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Flags []string, r8Deps android.Paths) {
- opt := j.deviceProperties.Optimize
+func (d *dexer) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Flags []string, r8Deps android.Paths) {
+ opt := d.dexProperties.Optimize
// When an app contains references to APIs that are not in the SDK specified by
// its LOCAL_SDK_VERSION for example added by support library or by runtime
@@ -140,8 +191,6 @@
proguardRaiseDeps = append(proguardRaiseDeps, dep.(Dependency).HeaderJars()...)
})
- r8Flags = append(r8Flags, j.dexCommonFlags(ctx)...)
-
r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars"))
r8Flags = append(r8Flags, flags.bootClasspath.FormJavaClassPath("-libraryjars"))
r8Flags = append(r8Flags, flags.classpath.FormJavaClassPath("-libraryjars"))
@@ -154,15 +203,10 @@
android.PathForSource(ctx, "build/make/core/proguard.flags"),
}
- if j.shouldInstrumentStatic(ctx) {
- flagFiles = append(flagFiles,
- android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
- }
-
- flagFiles = append(flagFiles, j.extraProguardFlagFiles...)
+ flagFiles = append(flagFiles, d.extraProguardFlagFiles...)
// TODO(ccross): static android library proguard files
- flagFiles = append(flagFiles, android.PathsForModuleSrc(ctx, j.deviceProperties.Optimize.Proguard_flags_files)...)
+ flagFiles = append(flagFiles, android.PathsForModuleSrc(ctx, opt.Proguard_flags_files)...)
r8Flags = append(r8Flags, android.JoinWithPrefix(flagFiles.Strings(), "-include "))
r8Deps = append(r8Deps, flagFiles...)
@@ -171,7 +215,7 @@
r8Deps = append(r8Deps, android.PathForSource(ctx,
"build/make/core/proguard_basic_keeps.flags"))
- r8Flags = append(r8Flags, j.deviceProperties.Optimize.Proguard_flags...)
+ r8Flags = append(r8Flags, opt.Proguard_flags...)
// TODO(ccross): Don't shrink app instrumentation tests by default.
if !Bool(opt.Shrink) {
@@ -197,29 +241,30 @@
return r8Flags, r8Deps
}
-func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags,
+func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, minSdkVersion sdkSpec,
classesJar android.Path, jarName string) android.ModuleOutPath {
- useR8 := j.deviceProperties.EffectiveOptimizeEnabled()
-
// Compile classes.jar into classes.dex and then javalib.jar
javalibJar := android.PathForModuleOut(ctx, "dex", jarName)
outDir := android.PathForModuleOut(ctx, "dex")
zipFlags := "--ignore_missing_files"
- if proptools.Bool(j.deviceProperties.Uncompress_dex) {
+ if proptools.Bool(d.dexProperties.Uncompress_dex) {
zipFlags += " -L 0"
}
+ commonFlags := d.dexCommonFlags(ctx, minSdkVersion)
+
+ useR8 := d.effectiveOptimizeEnabled()
if useR8 {
proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
- j.proguardDictionary = proguardDictionary
- r8Flags, r8Deps := j.r8Flags(ctx, flags)
+ d.proguardDictionary = android.OptionalPathForPath(proguardDictionary)
+ r8Flags, r8Deps := d.r8Flags(ctx, flags)
rule := r8
args := map[string]string{
- "r8Flags": strings.Join(r8Flags, " "),
+ "r8Flags": strings.Join(append(commonFlags, r8Flags...), " "),
"zipFlags": zipFlags,
- "outDict": j.proguardDictionary.String(),
+ "outDict": proguardDictionary.String(),
"outDir": outDir.String(),
}
if ctx.Config().IsEnvTrue("RBE_R8") {
@@ -236,7 +281,7 @@
Args: args,
})
} else {
- d8Flags, d8Deps := j.d8Flags(ctx, flags)
+ d8Flags, d8Deps := d8Flags(flags)
rule := d8
if ctx.Config().IsEnvTrue("RBE_D8") {
rule = d8RE
@@ -248,13 +293,13 @@
Input: classesJar,
Implicits: d8Deps,
Args: map[string]string{
- "d8Flags": strings.Join(d8Flags, " "),
+ "d8Flags": strings.Join(append(commonFlags, d8Flags...), " "),
"zipFlags": zipFlags,
"outDir": outDir.String(),
},
})
}
- if proptools.Bool(j.deviceProperties.Uncompress_dex) {
+ if proptools.Bool(d.dexProperties.Uncompress_dex) {
alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", jarName)
TransformZipAlign(ctx, alignedJavalibJar, javalibJar)
javalibJar = alignedJavalibJar
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 95dd0bb..9a0729d 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -66,6 +66,19 @@
stubFlagsRule(ctx)
+ // If there is a prebuilt hiddenapi dir, generate rules to use the
+ // files within. Generally, we build the hiddenapi files from source
+ // during the build, ensuring consistency. It's possible, in a split
+ // build (framework and vendor) scenario, for the vendor build to use
+ // prebuilt hiddenapi files from the framework build. In this scenario,
+ // the framework and vendor builds must use the same source to ensure
+ // consistency.
+
+ if ctx.Config().PrebuiltHiddenApiDir(ctx) != "" {
+ h.flags = prebuiltFlagsRule(ctx)
+ return
+ }
+
// These rules depend on files located in frameworks/base, skip them if running in a tree that doesn't have them.
if ctx.Config().FrameworksBaseDirExists(ctx) {
h.flags = flagsRule(ctx)
@@ -163,6 +176,7 @@
return
}
}
+
bootDexJars = append(bootDexJars, jar)
}
}
@@ -216,6 +230,19 @@
}
}
+func prebuiltFlagsRule(ctx android.SingletonContext) android.Path {
+ outputPath := hiddenAPISingletonPaths(ctx).flags
+ inputPath := android.PathForSource(ctx, ctx.Config().PrebuiltHiddenApiDir(ctx), "hiddenapi-flags.csv")
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Output: outputPath,
+ Input: inputPath,
+ })
+
+ return outputPath
+}
+
// flagsRule creates a rule to build hiddenapi-flags.csv out of flags.csv files generated for boot image modules and
// the greylists.
func flagsRule(ctx android.SingletonContext) android.Path {
@@ -397,6 +424,20 @@
return
}
+ if ctx.Config().PrebuiltHiddenApiDir(ctx) != "" {
+ outputPath := hiddenAPISingletonPaths(ctx).index
+ inputPath := android.PathForSource(ctx, ctx.Config().PrebuiltHiddenApiDir(ctx), "hiddenapi-index.csv")
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Output: outputPath,
+ Input: inputPath,
+ })
+
+ h.index = outputPath
+ return
+ }
+
indexes := android.Paths{}
ctx.VisitAllModules(func(module android.Module) {
if h, ok := module.(hiddenAPIIntf); ok {
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
new file mode 100644
index 0000000..e4dc037
--- /dev/null
+++ b/java/hiddenapi_singleton_test.go
@@ -0,0 +1,182 @@
+// 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 java
+
+import (
+ "android/soong/android"
+ "strings"
+ "testing"
+)
+
+func testConfigWithBootJars(bp string, bootJars []string, prebuiltHiddenApiDir *string) android.Config {
+ config := testConfig(nil, bp, nil)
+ config.TestProductVariables.BootJars = bootJars
+ config.TestProductVariables.PrebuiltHiddenApiDir = prebuiltHiddenApiDir
+ return config
+}
+
+func testContextWithHiddenAPI() *android.TestContext {
+ ctx := testContext()
+ ctx.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory)
+ return ctx
+}
+
+func testHiddenAPI(t *testing.T, bp string, bootJars []string, prebuiltHiddenApiDir *string) (*android.TestContext, android.Config) {
+ t.Helper()
+
+ config := testConfigWithBootJars(bp, bootJars, prebuiltHiddenApiDir)
+ ctx := testContextWithHiddenAPI()
+
+ run(t, ctx, config)
+
+ return ctx, config
+}
+
+func TestHiddenAPISingleton(t *testing.T) {
+ ctx, _ := testHiddenAPI(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ compile_dex: true,
+ }
+ `, []string{"foo"}, nil)
+
+ hiddenAPI := ctx.SingletonForTests("hiddenapi")
+ hiddenapiRule := hiddenAPI.Rule("hiddenapi")
+ want := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/aligned/foo.jar"
+ if !strings.Contains(hiddenapiRule.RuleParams.Command, want) {
+ t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", want, hiddenapiRule.RuleParams.Command)
+ }
+}
+
+func TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
+ ctx, _ := testHiddenAPI(t, `
+ java_import {
+ name: "foo",
+ jars: ["a.jar"],
+ compile_dex: true,
+ }
+ `, []string{"foo"}, nil)
+
+ hiddenAPI := ctx.SingletonForTests("hiddenapi")
+ hiddenapiRule := hiddenAPI.Rule("hiddenapi")
+ want := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/aligned/foo.jar"
+ if !strings.Contains(hiddenapiRule.RuleParams.Command, want) {
+ t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", want, hiddenapiRule.RuleParams.Command)
+ }
+}
+
+func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) {
+ ctx, _ := testHiddenAPI(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ compile_dex: true,
+ }
+
+ java_import {
+ name: "foo",
+ jars: ["a.jar"],
+ compile_dex: true,
+ prefer: false,
+ }
+ `, []string{"foo"}, nil)
+
+ hiddenAPI := ctx.SingletonForTests("hiddenapi")
+ hiddenapiRule := hiddenAPI.Rule("hiddenapi")
+ fromSourceJarArg := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/aligned/foo.jar"
+ if !strings.Contains(hiddenapiRule.RuleParams.Command, fromSourceJarArg) {
+ t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", fromSourceJarArg, hiddenapiRule.RuleParams.Command)
+ }
+
+ prebuiltJarArg := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/dex/foo.jar"
+ if strings.Contains(hiddenapiRule.RuleParams.Command, prebuiltJarArg) {
+ t.Errorf("Did not expect %s in hiddenapi command, but it was present: %s", prebuiltJarArg, hiddenapiRule.RuleParams.Command)
+ }
+}
+
+func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) {
+ ctx, _ := testHiddenAPI(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ compile_dex: true,
+ }
+
+ java_import {
+ name: "foo",
+ jars: ["a.jar"],
+ compile_dex: true,
+ prefer: true,
+ }
+ `, []string{"foo"}, nil)
+
+ hiddenAPI := ctx.SingletonForTests("hiddenapi")
+ hiddenapiRule := hiddenAPI.Rule("hiddenapi")
+ prebuiltJarArg := "--boot-dex=" + buildDir + "/.intermediates/prebuilt_foo/android_common/dex/foo.jar"
+ if !strings.Contains(hiddenapiRule.RuleParams.Command, prebuiltJarArg) {
+ t.Errorf("Expected %s in hiddenapi command, but it was not present: %s", prebuiltJarArg, hiddenapiRule.RuleParams.Command)
+ }
+
+ fromSourceJarArg := "--boot-dex=" + buildDir + "/.intermediates/foo/android_common/aligned/foo.jar"
+ if strings.Contains(hiddenapiRule.RuleParams.Command, fromSourceJarArg) {
+ t.Errorf("Did not expect %s in hiddenapi command, but it was present: %s", fromSourceJarArg, hiddenapiRule.RuleParams.Command)
+ }
+}
+
+func TestHiddenAPISingletonWithPrebuiltCsvFile(t *testing.T) {
+
+ // The idea behind this test is to ensure that when the build is
+ // confugured with a PrebuiltHiddenApiDir that the rules for the
+ // hiddenapi singleton copy the prebuilts to the typical output
+ // location, and then use that output location for the hiddenapi encode
+ // dex step.
+
+ // Where to find the prebuilt hiddenapi files:
+ prebuiltHiddenApiDir := "path/to/prebuilt/hiddenapi"
+
+ ctx, _ := testHiddenAPI(t, `
+ java_import {
+ name: "foo",
+ jars: ["a.jar"],
+ compile_dex: true,
+ }
+ `, []string{"foo"}, &prebuiltHiddenApiDir)
+
+ expectedCpInput := prebuiltHiddenApiDir + "/hiddenapi-flags.csv"
+ expectedCpOutput := buildDir + "/hiddenapi/hiddenapi-flags.csv"
+ expectedFlagsCsv := buildDir + "/hiddenapi/hiddenapi-flags.csv"
+
+ foo := ctx.ModuleForTests("foo", "android_common")
+
+ hiddenAPI := ctx.SingletonForTests("hiddenapi")
+ cpRule := hiddenAPI.Rule("Cp")
+ actualCpInput := cpRule.BuildParams.Input
+ actualCpOutput := cpRule.BuildParams.Output
+ encodeDexRule := foo.Rule("hiddenAPIEncodeDex")
+ actualFlagsCsv := encodeDexRule.BuildParams.Args["flagsCsv"]
+
+ if actualCpInput.String() != expectedCpInput {
+ t.Errorf("Prebuilt hiddenapi cp rule input mismatch, actual: %s, expected: %s", actualCpInput, expectedCpInput)
+ }
+
+ if actualCpOutput.String() != expectedCpOutput {
+ t.Errorf("Prebuilt hiddenapi cp rule output mismatch, actual: %s, expected: %s", actualCpOutput, expectedCpOutput)
+ }
+
+ if actualFlagsCsv != expectedFlagsCsv {
+ t.Errorf("Prebuilt hiddenapi encode dex rule flags csv mismatch, actual: %s, expected: %s", actualFlagsCsv, expectedFlagsCsv)
+ }
+}
diff --git a/java/java.go b/java/java.go
index 69826ee..adeb0f7 100644
--- a/java/java.go
+++ b/java/java.go
@@ -259,9 +259,6 @@
}
type CompilerDeviceProperties struct {
- // list of module-specific flags that will be used for dex compiles
- Dxflags []string `android:"arch_variant"`
-
// if not blank, set to the version of the sdk to compile against.
// Defaults to compiling against the current platform.
Sdk_version *string
@@ -307,37 +304,6 @@
}
}
- // If set to true, compile dex regardless of installable. Defaults to false.
- Compile_dex *bool
-
- Optimize struct {
- // If false, disable all optimization. Defaults to true for android_app and android_test
- // modules, false for java_library and java_test modules.
- Enabled *bool
- // True if the module containing this has it set by default.
- EnabledByDefault bool `blueprint:"mutated"`
-
- // If true, optimize for size by removing unused code. Defaults to true for apps,
- // false for libraries and tests.
- Shrink *bool
-
- // If true, optimize bytecode. Defaults to false.
- Optimize *bool
-
- // If true, obfuscate bytecode. Defaults to false.
- Obfuscate *bool
-
- // If true, do not use the flag files generated by aapt that automatically keep
- // classes referenced by the app manifest. Defaults to false.
- No_aapt_flags *bool
-
- // Flags to pass to proguard.
- Proguard_flags []string
-
- // Specifies the locations of files containing proguard flags.
- Proguard_flags_files []string `android:"path"`
- }
-
// When targeting 1.9 and above, override the modules to use with --system,
// otherwise provides defaults libraries to add to the bootclasspath.
System_modules *string
@@ -351,12 +317,6 @@
// set the name of the output
Stem *string
- // Keep the data uncompressed. We always need uncompressed dex for execution,
- // so this might actually save space by avoiding storing the same data twice.
- // This defaults to reasonable value based on module and should not be set.
- // It exists only to support ART tests.
- Uncompress_dex *bool
-
IsSDKLibrary bool `blueprint:"mutated"`
// If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file.
@@ -364,10 +324,6 @@
V4_signature *bool
}
-func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool {
- return BoolDefault(me.Optimize.Enabled, me.Optimize.EnabledByDefault)
-}
-
// Functionality common to Module and Import
//
// It is embedded in Module so its functionality can be used by methods in Module
@@ -436,9 +392,6 @@
// output file containing uninstrumented classes that will be instrumented by jacoco
jacocoReportClassesFile android.Path
- // output file containing mapping of obfuscated names
- proguardDictionary android.Path
-
// output file of the module, which may be a classes jar or a dex jar
outputFile android.Path
extraOutputFiles android.Paths
@@ -454,9 +407,6 @@
compiledJavaSrcs android.Paths
compiledSrcJars android.Paths
- // list of extra progurad flag files
- extraProguardFlagFiles android.Paths
-
// manifest file to use instead of properties.Manifest
overrideManifest android.OptionalPath
@@ -483,6 +433,7 @@
extraResources android.Paths
hiddenAPI
+ dexer
dexpreopter
linter
@@ -503,6 +454,7 @@
j.addHostProperties()
j.AddProperties(
&j.deviceProperties,
+ &j.dexer.dexProperties,
&j.dexpreoptProperties,
&j.linter.properties,
)
@@ -515,7 +467,10 @@
case ".jar":
return android.Paths{j.implementationAndResourcesJar}, nil
case ".proguard_map":
- return android.Paths{j.proguardDictionary}, nil
+ if j.dexer.proguardDictionary.Valid() {
+ return android.Paths{j.dexer.proguardDictionary.Path()}, nil
+ }
+ return nil, fmt.Errorf("%q was requested, but no output file was found.", tag)
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
@@ -644,6 +599,21 @@
ctx.Config().UnbundledBuild())
}
+func (j *Module) shouldInstrumentInApex(ctx android.BaseModuleContext) bool {
+ // Force enable the instrumentation for java code that is built for APEXes ...
+ // except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent
+ // doesn't make sense) or framework libraries (e.g. libraries found in the InstrumentFrameworkModules list) unless EMMA_INSTRUMENT_FRAMEWORK is true.
+ isJacocoAgent := ctx.ModuleName() == "jacocoagent"
+ if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !isJacocoAgent && !j.IsForPlatform() {
+ if !inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
+ return true
+ } else if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
+ return true
+ }
+ }
+ return false
+}
+
func (j *Module) sdkVersion() sdkSpec {
return sdkSpecFrom(String(j.deviceProperties.Sdk_version))
}
@@ -680,28 +650,32 @@
return j.ApexModuleBase.AvailableFor(what)
}
+func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext sdkContext, d dexer) {
+ sdkDep := decodeSdkDep(ctx, sdkContext)
+ if sdkDep.useDefaultLibs {
+ ctx.AddVariationDependencies(nil, bootClasspathTag, config.DefaultBootclasspathLibraries...)
+ ctx.AddVariationDependencies(nil, systemModulesTag, config.DefaultSystemModules)
+ if sdkDep.hasFrameworkLibs() {
+ ctx.AddVariationDependencies(nil, libTag, config.DefaultLibraries...)
+ }
+ } else if sdkDep.useModule {
+ ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...)
+ ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...)
+ if d.effectiveOptimizeEnabled() && sdkDep.hasStandardLibs() {
+ ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultBootclasspathLibraries...)
+ ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultLibraries...)
+ }
+ }
+ if sdkDep.systemModules != "" {
+ ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
+ }
+}
+
func (j *Module) deps(ctx android.BottomUpMutatorContext) {
if ctx.Device() {
j.linter.deps(ctx)
- sdkDep := decodeSdkDep(ctx, sdkContext(j))
- if sdkDep.useDefaultLibs {
- ctx.AddVariationDependencies(nil, bootClasspathTag, config.DefaultBootclasspathLibraries...)
- ctx.AddVariationDependencies(nil, systemModulesTag, config.DefaultSystemModules)
- if sdkDep.hasFrameworkLibs() {
- ctx.AddVariationDependencies(nil, libTag, config.DefaultLibraries...)
- }
- } else if sdkDep.useModule {
- ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...)
- ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...)
- if j.deviceProperties.EffectiveOptimizeEnabled() && sdkDep.hasStandardLibs() {
- ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultBootclasspathLibraries...)
- ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultLibraries...)
- }
- }
- if sdkDep.systemModules != "" {
- ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
- }
+ sdkDeps(ctx, sdkContext(j), j.dexer)
}
syspropPublicStubs := syspropPublicStubs(ctx.Config())
@@ -1564,11 +1538,7 @@
j.headerJarFile = j.implementationJarFile
}
- // Force enable the instrumentation for java code that is built for APEXes ...
- // except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent
- // doesn't make sense)
- isJacocoAgent := ctx.ModuleName() == "jacocoagent"
- if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !isJacocoAgent && !j.IsForPlatform() {
+ if j.shouldInstrumentInApex(ctx) {
j.properties.Instrument = true
}
@@ -1590,8 +1560,8 @@
// Enable dex compilation for the APEX variants, unless it is disabled explicitly
if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !j.IsForPlatform() {
- if j.deviceProperties.Compile_dex == nil {
- j.deviceProperties.Compile_dex = proptools.BoolPtr(true)
+ if j.dexProperties.Compile_dex == nil {
+ j.dexProperties.Compile_dex = proptools.BoolPtr(true)
}
if j.deviceProperties.Hostdex == nil {
j.deviceProperties.Hostdex = proptools.BoolPtr(true)
@@ -1599,10 +1569,14 @@
}
if ctx.Device() && j.hasCode(ctx) &&
- (Bool(j.properties.Installable) || Bool(j.deviceProperties.Compile_dex)) {
+ (Bool(j.properties.Installable) || Bool(j.dexProperties.Compile_dex)) {
+ if j.shouldInstrumentStatic(ctx) {
+ j.dexer.extraProguardFlagFiles = append(j.dexer.extraProguardFlagFiles,
+ android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
+ }
// Dex compilation
var dexOutputFile android.ModuleOutPath
- dexOutputFile = j.compileDex(ctx, flags, outputFile, jarName)
+ dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
if ctx.Failed() {
return
}
@@ -1610,9 +1584,25 @@
configurationName := j.ConfigurationName()
primary := configurationName == ctx.ModuleName()
+ // A source module that has been replaced by a prebuilt can never be the primary module
+ // as long as the prebuilt actually provides a build dex jar. If it doesn't then use
+ // the source module for now.
+ if j.IsReplacedByPrebuilt() {
+ ctx.VisitDirectDepsWithTag(android.PrebuiltDepTag, func(prebuilt android.Module) {
+ if h, ok := prebuilt.(hiddenAPIIntf); ok && h.bootDexJar() != nil {
+ // It is safe to ignore the source module as the prebuilt module provides an
+ // appropriate boot dex jar.
+ primary = false
+ } else {
+ // The prebuilt doesn't provide a suitable boot dex jar so keep using the
+ // source module instead.
+ }
+ })
+ }
+
// Hidden API CSV generation and dex encoding
dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, configurationName, primary, dexOutputFile, j.implementationJarFile,
- proptools.Bool(j.deviceProperties.Uncompress_dex))
+ proptools.Bool(j.dexProperties.Uncompress_dex))
// merge dex jar with resources if necessary
if j.resourceJar != nil {
@@ -1620,7 +1610,7 @@
combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName)
TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
false, nil, nil)
- if *j.deviceProperties.Uncompress_dex {
+ if *j.dexProperties.Uncompress_dex {
combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName)
TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
dexOutputFile = combinedAlignedJar
@@ -1937,11 +1927,11 @@
j.checkSdkVersions(ctx)
j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")
j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
- if j.deviceProperties.Uncompress_dex == nil {
+ if j.dexProperties.Uncompress_dex == nil {
// If the value was not force-set by the user, use reasonable default based on the module.
- j.deviceProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
+ j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
}
- j.dexpreopter.uncompressedDex = *j.deviceProperties.Uncompress_dex
+ j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
j.compile(ctx, nil)
exclusivelyForApex := android.InAnyApex(ctx.ModuleName()) && !j.IsForPlatform()
@@ -2178,6 +2168,7 @@
prebuiltTestProperties prebuiltTestProperties
testConfig android.Path
+ dexJarFile android.Path
}
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -2476,8 +2467,15 @@
// Functionality common to Module and Import.
embeddableInModuleAndImport
+ hiddenAPI
+ dexer
+ dexpreopter
+
properties ImportProperties
+ // output file containing classes.dex and resources
+ dexJarFile android.Path
+
combinedClasspathFile android.Path
exportedSdkLibs []string
}
@@ -2486,10 +2484,22 @@
return sdkSpecFrom(String(j.properties.Sdk_version))
}
+func (j *Import) makeSdkVersion() string {
+ return j.sdkVersion().raw
+}
+
+func (j *Import) systemModules() string {
+ return "none"
+}
+
func (j *Import) minSdkVersion() sdkSpec {
return j.sdkVersion()
}
+func (j *Import) targetSdkVersion() sdkSpec {
+ return j.sdkVersion()
+}
+
func (j *Import) MinSdkVersion() string {
return j.minSdkVersion().version.String()
}
@@ -2514,8 +2524,16 @@
return nil
}
+func (j *Import) LintDepSets() LintDepSets {
+ return LintDepSets{}
+}
+
func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
+
+ if ctx.Device() && Bool(j.dexProperties.Compile_dex) {
+ sdkDeps(ctx, sdkContext(j), j.dexer)
+ }
}
func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -2538,6 +2556,8 @@
// added to the Android manifest.
j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...)
+ var flags javaBuilderFlags
+
ctx.VisitDirectDeps(func(module android.Module) {
otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
@@ -2546,12 +2566,16 @@
case Dependency:
switch tag {
case libTag, staticLibTag:
+ flags.classpath = append(flags.classpath, dep.HeaderJars()...)
// sdk lib names from dependencies are re-exported
j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
+ case bootClasspathTag:
+ flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars()...)
}
case SdkLibraryDependency:
switch tag {
case libTag:
+ flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
// names of sdk libs that are directly depended are exported
j.exportedSdkLibs = append(j.exportedSdkLibs, otherName)
}
@@ -2563,6 +2587,41 @@
ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
jarName, outputFile)
}
+
+ if ctx.Device() && Bool(j.dexProperties.Compile_dex) {
+ sdkDep := decodeSdkDep(ctx, sdkContext(j))
+ if sdkDep.invalidVersion {
+ ctx.AddMissingDependencies(sdkDep.bootclasspath)
+ ctx.AddMissingDependencies(sdkDep.java9Classpath)
+ } else if sdkDep.useFiles {
+ // sdkDep.jar is actually equivalent to turbine header.jar.
+ flags.classpath = append(flags.classpath, sdkDep.jars...)
+ }
+
+ // Dex compilation
+
+ j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", jarName)
+ if j.dexProperties.Uncompress_dex == nil {
+ // If the value was not force-set by the user, use reasonable default based on the module.
+ j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
+ }
+ j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
+
+ var dexOutputFile android.ModuleOutPath
+ dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
+ if ctx.Failed() {
+ return
+ }
+
+ configurationName := j.BaseModuleName()
+ primary := j.Prebuilt().UsePrebuilt()
+
+ // Hidden API CSV generation and dex encoding
+ dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, configurationName, primary, dexOutputFile, outputFile,
+ proptools.Bool(j.dexProperties.Uncompress_dex))
+
+ j.dexJarFile = dexOutputFile
+ }
}
var _ Dependency = (*Import)(nil)
@@ -2593,7 +2652,7 @@
}
func (j *Import) DexJar() android.Path {
- return nil
+ return j.dexJarFile
}
func (j *Import) AidlIncludeDirs() android.Paths {
@@ -2642,6 +2701,12 @@
var _ android.PrebuiltInterface = (*Import)(nil)
+func (j *Import) IsInstallable() bool {
+ return Bool(j.properties.Installable)
+}
+
+var _ dexpreopterInterface = (*Import)(nil)
+
// java_import imports one or more `.jar` files into the build graph as if they were built by a java_library module.
//
// By default, a java_import has a single variant that expects a `.jar` file containing `.class` files that were
@@ -2652,10 +2717,15 @@
func ImportFactory() android.Module {
module := &Import{}
- module.AddProperties(&module.properties)
+ module.AddProperties(
+ &module.properties,
+ &module.dexer.dexProperties,
+ )
module.initModuleAndImport(&module.ModuleBase)
+ module.dexProperties.Optimize.EnabledByDefault = false
+
android.InitPrebuiltModule(module, &module.properties.Jars)
android.InitApexModule(module)
android.InitSdkAwareModule(module)
@@ -2854,6 +2924,7 @@
module.AddProperties(
&CompilerProperties{},
&CompilerDeviceProperties{},
+ &DexProperties{},
&DexpreoptProperties{},
&android.ProtoProperties{},
&aaptProperties{},
diff --git a/java/java_test.go b/java/java_test.go
index 8797119..97ec426 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -30,7 +30,6 @@
"android/soong/android"
"android/soong/cc"
"android/soong/dexpreopt"
- "android/soong/genrule"
)
var buildDir string
@@ -80,7 +79,6 @@
RegisterSystemModulesBuildComponents(ctx)
ctx.RegisterModuleType("java_plugin", PluginFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
RegisterDocsBuildComponents(ctx)
RegisterStubsBuildComponents(ctx)
RegisterSdkLibraryBuildComponents(ctx)
@@ -486,6 +484,8 @@
java_import {
name: "baz",
jars: ["b.jar"],
+ sdk_version: "current",
+ compile_dex: true,
}
dex_import {
@@ -516,8 +516,10 @@
fooModule := ctx.ModuleForTests("foo", "android_common")
javac := fooModule.Rule("javac")
combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
- barJar := ctx.ModuleForTests("bar", "android_common").Rule("combineJar").Output
- bazJar := ctx.ModuleForTests("baz", "android_common").Rule("combineJar").Output
+ barModule := ctx.ModuleForTests("bar", "android_common")
+ barJar := barModule.Rule("combineJar").Output
+ bazModule := ctx.ModuleForTests("baz", "android_common")
+ bazJar := bazModule.Rule("combineJar").Output
sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").Rule("combineJar").Output
fooLibrary := fooModule.Module().(*Library)
@@ -532,6 +534,11 @@
t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barJar.String())
}
+ barDexJar := barModule.Module().(*Import).DexJar()
+ if barDexJar != nil {
+ t.Errorf("bar dex jar build path expected to be nil, got %q", barDexJar)
+ }
+
if !strings.Contains(javac.Args["classpath"], sdklibStubsJar.String()) {
t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], sdklibStubsJar.String())
}
@@ -540,6 +547,12 @@
t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, bazJar.String())
}
+ bazDexJar := bazModule.Module().(*Import).DexJar().String()
+ expectedDexJar := buildDir + "/.intermediates/baz/android_common/dex/baz.jar"
+ if bazDexJar != expectedDexJar {
+ t.Errorf("baz dex jar build path expected %q, got %q", expectedDexJar, bazDexJar)
+ }
+
ctx.ModuleForTests("qux", "android_common").Rule("Cp")
}
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index 999c72f..bcc6cc0 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -34,6 +34,13 @@
type prebuiltApisProperties struct {
// list of api version directories
Api_dirs []string
+
+ // The sdk_version of java_import modules generated based on jar files.
+ // Defaults to "current"
+ Imports_sdk_version *string
+
+ // If set to true, compile dex for java_import modules. Defaults to false.
+ Imports_compile_dex *bool
}
type prebuiltApis struct {
@@ -74,18 +81,19 @@
return mctx.ModuleName() + "_" + scope + "_" + apiver + "_" + module
}
-func createImport(mctx android.LoadHookContext, module string, scope string, apiver string, path string) {
+func createImport(mctx android.LoadHookContext, module, scope, apiver, path, sdkVersion string, compileDex bool) {
props := struct {
Name *string
Jars []string
Sdk_version *string
Installable *bool
+ Compile_dex *bool
}{}
props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, module, scope, apiver))
props.Jars = append(props.Jars, path)
- // TODO(hansson): change to scope after migration is done.
- props.Sdk_version = proptools.StringPtr("current")
+ props.Sdk_version = proptools.StringPtr(sdkVersion)
props.Installable = proptools.BoolPtr(false)
+ props.Compile_dex = proptools.BoolPtr(compileDex)
mctx.CreateModule(ImportFactory, &props)
}
@@ -101,10 +109,10 @@
mctx.CreateModule(android.FileGroupFactory, &filegroupProps)
}
-func getPrebuiltFiles(mctx android.LoadHookContext, name string) []string {
+func getPrebuiltFiles(mctx android.LoadHookContext, p *prebuiltApis, name string) []string {
mydir := mctx.ModuleDir() + "/"
var files []string
- for _, apiver := range mctx.Module().(*prebuiltApis).properties.Api_dirs {
+ for _, apiver := range p.properties.Api_dirs {
for _, scope := range []string{"public", "system", "test", "core", "module-lib", "system-server"} {
vfiles, err := mctx.GlobWithDeps(mydir+apiver+"/"+scope+"/"+name, nil)
if err != nil {
@@ -116,16 +124,19 @@
return files
}
-func prebuiltSdkStubs(mctx android.LoadHookContext) {
+func prebuiltSdkStubs(mctx android.LoadHookContext, p *prebuiltApis) {
mydir := mctx.ModuleDir() + "/"
// <apiver>/<scope>/<module>.jar
- files := getPrebuiltFiles(mctx, "*.jar")
+ files := getPrebuiltFiles(mctx, p, "*.jar")
+
+ sdkVersion := proptools.StringDefault(p.properties.Imports_sdk_version, "current")
+ compileDex := proptools.BoolDefault(p.properties.Imports_compile_dex, false)
for _, f := range files {
// create a Import module for each jar file
localPath := strings.TrimPrefix(f, mydir)
module, apiver, scope := parseJarPath(localPath)
- createImport(mctx, module, scope, apiver, localPath)
+ createImport(mctx, module, scope, apiver, localPath, sdkVersion, compileDex)
}
}
@@ -140,8 +151,8 @@
mctx.CreateModule(SystemModulesFactory, &props)
}
-func prebuiltSdkSystemModules(mctx android.LoadHookContext) {
- for _, apiver := range mctx.Module().(*prebuiltApis).properties.Api_dirs {
+func prebuiltSdkSystemModules(mctx android.LoadHookContext, p *prebuiltApis) {
+ for _, apiver := range p.properties.Api_dirs {
jar := android.ExistentPathForSource(mctx,
mctx.ModuleDir(), apiver, "public", "core-for-system-modules.jar")
if jar.Valid() {
@@ -150,10 +161,10 @@
}
}
-func prebuiltApiFiles(mctx android.LoadHookContext) {
+func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) {
mydir := mctx.ModuleDir() + "/"
// <apiver>/<scope>/api/<module>.txt
- files := getPrebuiltFiles(mctx, "api/*.txt")
+ files := getPrebuiltFiles(mctx, p, "api/*.txt")
if len(files) == 0 {
mctx.ModuleErrorf("no api file found under %q", mydir)
@@ -201,10 +212,10 @@
}
func createPrebuiltApiModules(mctx android.LoadHookContext) {
- if _, ok := mctx.Module().(*prebuiltApis); ok {
- prebuiltApiFiles(mctx)
- prebuiltSdkStubs(mctx)
- prebuiltSdkSystemModules(mctx)
+ if p, ok := mctx.Module().(*prebuiltApis); ok {
+ prebuiltApiFiles(mctx, p)
+ prebuiltSdkStubs(mctx, p)
+ prebuiltSdkSystemModules(mctx, p)
}
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index f2a509a..7d973c4 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1110,6 +1110,7 @@
&module.properties,
&module.protoProperties,
&module.deviceProperties,
+ &module.dexProperties,
&module.dexpreoptProperties,
&module.linter.properties,
&props,
@@ -1174,8 +1175,8 @@
// We compile the stubs for 1.8 in line with the main android.jar stubs, and potential
// interop with older developer tools that don't support 1.9.
props.Java_version = proptools.StringPtr("1.8")
- if module.deviceProperties.Compile_dex != nil {
- props.Compile_dex = module.deviceProperties.Compile_dex
+ if module.dexProperties.Compile_dex != nil {
+ props.Compile_dex = module.dexProperties.Compile_dex
}
// Dist the class jar artifact for sdk builds.
diff --git a/java/testing.go b/java/testing.go
index 48e449f..500b8de 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -132,6 +132,7 @@
srcs: ["a.java"],
sdk_version: "none",
system_modules: "core-platform-api-stubs-system-modules",
+ compile_dex: true,
}
`, extra)
}
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index 0bcdccb..e1123e0 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -104,6 +104,7 @@
productOut("*.img"),
productOut("*.zip"),
productOut("android-info.txt"),
+ productOut("misc_info.txt"),
productOut("apex"),
productOut("kernel"),
productOut("data"),
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 5717401..405f379 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -74,6 +74,12 @@
}
var Configuration = map[string]PathConfig{
+ "aarch64-linux-android-ar": Log,
+ "aarch64-linux-android-gcc": Log,
+ "aarch64-linux-android-ld": Log,
+ "aarch64-linux-android-nm": Log,
+ "aarch64-linux-android-objcopy": Log,
+ "aarch64-linux-android-objdump": Log,
"bash": Allowed,
"dd": Allowed,
"diff": Allowed,
@@ -89,6 +95,8 @@
"lsof": Allowed,
"openssl": Allowed,
"patch": Allowed,
+ "perl": Log,
+ "printf": Log,
"pstree": Allowed,
"rsync": Allowed,
"sh": Allowed,
@@ -110,10 +118,72 @@
"ld.gold": Forbidden,
"pkg-config": Forbidden,
- // These are toybox tools that only work on Linux.
- "pgrep": LinuxOnlyPrebuilt,
- "pkill": LinuxOnlyPrebuilt,
- "ps": LinuxOnlyPrebuilt,
+ // On Linux we'll use the toybox versions of these instead.
+ "basename": LinuxOnlyPrebuilt,
+ "cat": LinuxOnlyPrebuilt,
+ "chmod": LinuxOnlyPrebuilt,
+ // TODO (b/121282416): switch back to LinuxOnlyPrebuilt when build is hermetic
+ "cmp": Log,
+ // TODO (b/121282416): switch back to LinuxOnlyPrebuilt when build is hermetic
+ "cp": Log,
+ "comm": LinuxOnlyPrebuilt,
+ "cut": LinuxOnlyPrebuilt,
+ "date": LinuxOnlyPrebuilt,
+ // TODO (b/121282416): switch back to LinuxOnlyPrebuilt when build is hermetic
+ "dirname": Log,
+ "du": LinuxOnlyPrebuilt,
+ "echo": LinuxOnlyPrebuilt,
+ "egrep": LinuxOnlyPrebuilt,
+ "env": LinuxOnlyPrebuilt,
+ "getconf": LinuxOnlyPrebuilt,
+ "grep": LinuxOnlyPrebuilt,
+ "head": LinuxOnlyPrebuilt,
+ "hostname": LinuxOnlyPrebuilt,
+ "id": LinuxOnlyPrebuilt,
+ "ln": LinuxOnlyPrebuilt,
+ "ls": LinuxOnlyPrebuilt,
+ "md5sum": LinuxOnlyPrebuilt,
+ // TODO (b/121282416): switch back to LinuxOnlyPrebuilt when build is hermetic
+ "mkdir": Log,
+ "mktemp": LinuxOnlyPrebuilt,
+ "mv": LinuxOnlyPrebuilt,
+ "od": LinuxOnlyPrebuilt,
+ // TODO (b/121282416): switch back to LinuxOnlyPrebuilt when build is hermetic
+ "paste": Log,
+ "pgrep": LinuxOnlyPrebuilt,
+ "pkill": LinuxOnlyPrebuilt,
+ "ps": LinuxOnlyPrebuilt,
+ // TODO (b/121282416): switch back to LinuxOnlyPrebuilt when build is hermetic
+ "pwd": Log,
+ "readlink": LinuxOnlyPrebuilt,
+ "rm": LinuxOnlyPrebuilt,
+ // TODO (b/121282416): switch back to LinuxOnlyPrebuilt when build is hermetic
+ "rmdir": Log,
+ "sed": LinuxOnlyPrebuilt,
+ "seq": LinuxOnlyPrebuilt,
+ "setsid": LinuxOnlyPrebuilt,
+ "sha1sum": LinuxOnlyPrebuilt,
+ "sha256sum": LinuxOnlyPrebuilt,
+ "sha512sum": LinuxOnlyPrebuilt,
+ "sleep": LinuxOnlyPrebuilt,
+ "sort": LinuxOnlyPrebuilt,
+ "stat": LinuxOnlyPrebuilt,
+ // TODO (b/121282416): switch back to LinuxOnlyPrebuilt when build is hermetic
+ "tail": Log,
+ "tar": LinuxOnlyPrebuilt,
+ "tee": LinuxOnlyPrebuilt,
+ "timeout": LinuxOnlyPrebuilt,
+ // TODO (b/121282416): switch back to LinuxOnlyPrebuilt when build is hermetic
+ "touch": Log,
+ "true": LinuxOnlyPrebuilt,
+ "uname": LinuxOnlyPrebuilt,
+ "uniq": LinuxOnlyPrebuilt,
+ "unix2dos": LinuxOnlyPrebuilt,
+ "wc": LinuxOnlyPrebuilt,
+ "whoami": LinuxOnlyPrebuilt,
+ "which": LinuxOnlyPrebuilt,
+ // TODO (b/121282416): switch back to LinuxOnlyPrebuilt when build is hermetic
+ "xxd": Log,
}
func init() {
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index 2de772b..850ca3b 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -33,14 +33,14 @@
var (
noSandbox = Sandbox{}
basicSandbox = Sandbox{
- Enabled: true,
+ Enabled: false,
}
dumpvarsSandbox = basicSandbox
katiSandbox = basicSandbox
soongSandbox = basicSandbox
ninjaSandbox = Sandbox{
- Enabled: true,
+ Enabled: false,
DisableWhenUsingGoma: true,
AllowBuildBrokenUsesNetwork: true,
@@ -54,6 +54,9 @@
working bool
group string
+ srcDir string
+ outDir string
+ distDir string
}
func (c *Cmd) sandboxSupported() bool {
@@ -72,15 +75,34 @@
sandboxConfig.group = "nobody"
}
- cmd := exec.CommandContext(c.ctx.Context, nsjailPath,
+ sandboxConfig.srcDir = absPath(c.ctx, ".")
+ sandboxConfig.outDir = absPath(c.ctx, c.config.OutDir())
+ sandboxConfig.distDir = absPath(c.ctx, c.config.DistDir())
+
+ sandboxArgs := []string{
"-H", "android-build",
"-e",
"-u", "nobody",
"-g", sandboxConfig.group,
- "-B", "/",
+ "-R", "/",
+ "-B", sandboxConfig.srcDir,
+ "-B", "/tmp",
+ "-B", sandboxConfig.outDir,
+ }
+
+ if _, err := os.Stat(sandboxConfig.distDir); !os.IsNotExist(err) {
+ //Mount dist dir as read-write if it already exists
+ sandboxArgs = append(sandboxArgs, "-B",
+ sandboxConfig.distDir)
+ }
+
+ sandboxArgs = append(sandboxArgs,
"--disable_clone_newcgroup",
"--",
"/bin/bash", "-c", `if [ $(hostname) == "android-build" ]; then echo "Android" "Success"; else echo Failure; fi`)
+
+ cmd := exec.CommandContext(c.ctx.Context, nsjailPath, sandboxArgs...)
+
cmd.Env = c.config.Environment().Environ()
c.ctx.Verboseln(cmd.Args)
@@ -144,8 +166,17 @@
"--rlimit_fsize", "soft",
"--rlimit_nofile", "soft",
- // For now, just map everything. Eventually we should limit this, especially to make most things readonly.
- "-B", "/",
+ // For now, just map everything. Make most things readonly.
+ "-R", "/",
+
+ // Mount source are read-write
+ "-B", sandboxConfig.srcDir,
+
+ //Mount out dir as read-write
+ "-B", sandboxConfig.outDir,
+
+ // Mount a writable tmp dir
+ "-B", "/tmp",
// Disable newcgroup for now, since it may require newer kernels
// TODO: try out cgroups
@@ -155,6 +186,11 @@
"-q",
}
+ if _, err := os.Stat(sandboxConfig.distDir); !os.IsNotExist(err) {
+ //Mount dist dir as read-write if it already exists
+ sandboxArgs = append(sandboxArgs, "-B", sandboxConfig.distDir)
+ }
+
if c.Sandbox.AllowBuildBrokenUsesNetwork && c.config.BuildBrokenUsesNetwork() {
c.ctx.Printf("AllowBuildBrokenUsesNetwork: %v", c.Sandbox.AllowBuildBrokenUsesNetwork)
c.ctx.Printf("BuildBrokenUsesNetwork: %v", c.config.BuildBrokenUsesNetwork())