Merge "Move construct_context.sh from Make to Soong. Update OWNERS list."
diff --git a/android/androidmk.go b/android/androidmk.go
index d579e30..3487b28 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -46,7 +46,7 @@
type AndroidMkData struct {
Class string
SubName string
- DistFile OptionalPath
+ DistFiles TaggedDistFiles
OutputFile OptionalPath
Disabled bool
Include string
@@ -72,7 +72,7 @@
type AndroidMkEntries struct {
Class string
SubName string
- DistFile OptionalPath
+ DistFiles TaggedDistFiles
OutputFile OptionalPath
Disabled bool
Include string
@@ -137,6 +137,96 @@
a.EntryMap[name] = append(a.EntryMap[name], value...)
}
+// Compute the list of Make strings to declare phone goals and dist-for-goals
+// calls from the module's dist and dists properties.
+func (a *AndroidMkEntries) GetDistForGoals(mod blueprint.Module) []string {
+ amod := mod.(Module).base()
+ name := amod.BaseModuleName()
+
+ var ret []string
+
+ availableTaggedDists := TaggedDistFiles{}
+ if a.DistFiles != nil && len(a.DistFiles[""]) > 0 {
+ availableTaggedDists = a.DistFiles
+ } else if a.OutputFile.Valid() {
+ availableTaggedDists = MakeDefaultDistFiles(a.OutputFile.Path())
+ }
+
+ // Iterate over this module's dist structs, merged from the dist and dists properties.
+ for _, dist := range amod.Dists() {
+ // Get the list of goals this dist should be enabled for. e.g. sdk, droidcore
+ goals := strings.Join(dist.Targets, " ")
+
+ // Get the tag representing the output files to be dist'd. e.g. ".jar", ".proguard_map"
+ var tag string
+ if dist.Tag == nil {
+ // If the dist struct does not specify a tag, use the default output files tag.
+ tag = ""
+ } else {
+ tag = *dist.Tag
+ }
+
+ // Get the paths of the output files to be dist'd, represented by the tag.
+ // Can be an empty list.
+ tagPaths := availableTaggedDists[tag]
+ if len(tagPaths) == 0 {
+ // Nothing to dist for this tag, continue to the next dist.
+ continue
+ }
+
+ if len(tagPaths) > 1 && (dist.Dest != nil || dist.Suffix != nil) {
+ errorMessage := "Cannot apply dest/suffix for more than one dist " +
+ "file for %s goals in module %s. The list of dist files, " +
+ "which should have a single element, is:\n%s"
+ panic(fmt.Errorf(errorMessage, goals, name, tagPaths))
+ }
+
+ ret = append(ret, fmt.Sprintf(".PHONY: %s\n", goals))
+
+ // Create dist-for-goals calls for each path in the dist'd files.
+ for _, path := range tagPaths {
+ // It's possible that the Path is nil from errant modules. Be defensive here.
+ if path == nil {
+ tagName := "default" // for error message readability
+ if dist.Tag != nil {
+ tagName = *dist.Tag
+ }
+ panic(fmt.Errorf("Dist file should not be nil for the %s tag in %s", tagName, name))
+ }
+
+ dest := filepath.Base(path.String())
+
+ if dist.Dest != nil {
+ var err error
+ if dest, err = validateSafePath(*dist.Dest); err != nil {
+ // This was checked in ModuleBase.GenerateBuildActions
+ panic(err)
+ }
+ }
+
+ if dist.Suffix != nil {
+ ext := filepath.Ext(dest)
+ suffix := *dist.Suffix
+ dest = strings.TrimSuffix(dest, ext) + suffix + ext
+ }
+
+ if dist.Dir != nil {
+ var err error
+ if dest, err = validateSafePath(*dist.Dir, dest); err != nil {
+ // This was checked in ModuleBase.GenerateBuildActions
+ panic(err)
+ }
+ }
+
+ ret = append(
+ ret,
+ fmt.Sprintf("$(call dist-for-goals,%s,%s:%s)\n", goals, path.String(), dest))
+ }
+ }
+
+ return ret
+}
+
func (a *AndroidMkEntries) fillInEntries(config Config, bpPath string, mod blueprint.Module) {
a.EntryMap = make(map[string][]string)
amod := mod.(Module).base()
@@ -149,42 +239,8 @@
a.Host_required = append(a.Host_required, amod.commonProperties.Host_required...)
a.Target_required = append(a.Target_required, amod.commonProperties.Target_required...)
- // Fill in the header part.
- if len(amod.commonProperties.Dist.Targets) > 0 {
- distFile := a.DistFile
- if !distFile.Valid() {
- distFile = a.OutputFile
- }
- if distFile.Valid() {
- dest := filepath.Base(distFile.String())
-
- if amod.commonProperties.Dist.Dest != nil {
- var err error
- if dest, err = validateSafePath(*amod.commonProperties.Dist.Dest); err != nil {
- // This was checked in ModuleBase.GenerateBuildActions
- panic(err)
- }
- }
-
- if amod.commonProperties.Dist.Suffix != nil {
- ext := filepath.Ext(dest)
- suffix := *amod.commonProperties.Dist.Suffix
- dest = strings.TrimSuffix(dest, ext) + suffix + ext
- }
-
- if amod.commonProperties.Dist.Dir != nil {
- var err error
- if dest, err = validateSafePath(*amod.commonProperties.Dist.Dir, dest); err != nil {
- // This was checked in ModuleBase.GenerateBuildActions
- panic(err)
- }
- }
-
- goals := strings.Join(amod.commonProperties.Dist.Targets, " ")
- fmt.Fprintln(&a.header, ".PHONY:", goals)
- fmt.Fprintf(&a.header, "$(call dist-for-goals,%s,%s:%s)\n",
- goals, distFile.String(), dest)
- }
+ for _, distString := range a.GetDistForGoals(mod) {
+ fmt.Fprintf(&a.header, distString)
}
fmt.Fprintln(&a.header, "\ninclude $(CLEAR_VARS)")
@@ -430,7 +486,7 @@
entries := AndroidMkEntries{
Class: data.Class,
SubName: data.SubName,
- DistFile: data.DistFile,
+ DistFiles: data.DistFiles,
OutputFile: data.OutputFile,
Disabled: data.Disabled,
Include: data.Include,
diff --git a/android/androidmk_test.go b/android/androidmk_test.go
index 71f8020..250f086 100644
--- a/android/androidmk_test.go
+++ b/android/androidmk_test.go
@@ -15,6 +15,7 @@
package android
import (
+ "fmt"
"io"
"reflect"
"testing"
@@ -22,10 +23,12 @@
type customModule struct {
ModuleBase
- data AndroidMkData
+ data AndroidMkData
+ distFiles TaggedDistFiles
}
func (m *customModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ m.distFiles = m.GenerateTaggedDistFiles(ctx)
}
func (m *customModule) AndroidMk() AndroidMkData {
@@ -36,6 +39,26 @@
}
}
+func (m *customModule) OutputFiles(tag string) (Paths, error) {
+ switch tag {
+ case "":
+ return PathsForTesting("one.out"), nil
+ case ".multiple":
+ return PathsForTesting("two.out", "three/four.out"), nil
+ default:
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ }
+}
+
+func (m *customModule) AndroidMkEntries() []AndroidMkEntries {
+ return []AndroidMkEntries{
+ {
+ Class: "CUSTOM_MODULE",
+ DistFiles: m.distFiles,
+ },
+ }
+}
+
func customModuleFactory() Module {
module := &customModule{}
InitAndroidModule(module)
@@ -76,3 +99,159 @@
assertEqual([]string{"baz"}, m.data.Host_required)
assertEqual([]string{"qux"}, m.data.Target_required)
}
+
+func TestGetDistForGoals(t *testing.T) {
+ testCases := []struct {
+ bp string
+ expectedAndroidMkLines []string
+ }{
+ {
+ bp: `
+ custom {
+ name: "foo",
+ dist: {
+ targets: ["my_goal"]
+ }
+ }
+ `,
+ expectedAndroidMkLines: []string{
+ ".PHONY: my_goal\n",
+ "$(call dist-for-goals,my_goal,one.out:one.out)\n",
+ },
+ },
+ {
+ bp: `
+ custom {
+ name: "foo",
+ dists: [
+ {
+ targets: ["my_goal"],
+ },
+ {
+ targets: ["my_second_goal", "my_third_goal"],
+ },
+ ],
+ }
+ `,
+ expectedAndroidMkLines: []string{
+ ".PHONY: my_goal\n",
+ "$(call dist-for-goals,my_goal,one.out:one.out)\n",
+ ".PHONY: my_second_goal my_third_goal\n",
+ "$(call dist-for-goals,my_second_goal my_third_goal,one.out:one.out)\n",
+ },
+ },
+ {
+ bp: `
+ custom {
+ name: "foo",
+ dist: {
+ targets: ["my_goal"],
+ },
+ dists: [
+ {
+ targets: ["my_second_goal", "my_third_goal"],
+ },
+ ],
+ }
+ `,
+ expectedAndroidMkLines: []string{
+ ".PHONY: my_second_goal my_third_goal\n",
+ "$(call dist-for-goals,my_second_goal my_third_goal,one.out:one.out)\n",
+ ".PHONY: my_goal\n",
+ "$(call dist-for-goals,my_goal,one.out:one.out)\n",
+ },
+ },
+ {
+ bp: `
+ custom {
+ name: "foo",
+ dist: {
+ targets: ["my_goal", "my_other_goal"],
+ tag: ".multiple",
+ },
+ dists: [
+ {
+ targets: ["my_second_goal"],
+ tag: ".multiple",
+ },
+ {
+ targets: ["my_third_goal"],
+ dir: "test/dir",
+ },
+ {
+ targets: ["my_fourth_goal"],
+ suffix: ".suffix",
+ },
+ {
+ targets: ["my_fifth_goal"],
+ dest: "new-name",
+ },
+ {
+ targets: ["my_sixth_goal"],
+ dest: "new-name",
+ dir: "some/dir",
+ suffix: ".suffix",
+ },
+ ],
+ }
+ `,
+ expectedAndroidMkLines: []string{
+ ".PHONY: my_second_goal\n",
+ "$(call dist-for-goals,my_second_goal,two.out:two.out)\n",
+ "$(call dist-for-goals,my_second_goal,three/four.out:four.out)\n",
+ ".PHONY: my_third_goal\n",
+ "$(call dist-for-goals,my_third_goal,one.out:test/dir/one.out)\n",
+ ".PHONY: my_fourth_goal\n",
+ "$(call dist-for-goals,my_fourth_goal,one.out:one.suffix.out)\n",
+ ".PHONY: my_fifth_goal\n",
+ "$(call dist-for-goals,my_fifth_goal,one.out:new-name)\n",
+ ".PHONY: my_sixth_goal\n",
+ "$(call dist-for-goals,my_sixth_goal,one.out:some/dir/new-name.suffix)\n",
+ ".PHONY: my_goal my_other_goal\n",
+ "$(call dist-for-goals,my_goal my_other_goal,two.out:two.out)\n",
+ "$(call dist-for-goals,my_goal my_other_goal,three/four.out:four.out)\n",
+ },
+ },
+ }
+
+ for _, testCase := range testCases {
+ config := TestConfig(buildDir, nil, testCase.bp, nil)
+ config.inMake = true // Enable androidmk Singleton
+
+ ctx := NewTestContext()
+ ctx.RegisterSingletonType("androidmk", AndroidMkSingleton)
+ ctx.RegisterModuleType("custom", customModuleFactory)
+ ctx.Register(config)
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ FailIfErrored(t, errs)
+
+ module := ctx.ModuleForTests("foo", "").Module().(*customModule)
+ entries := AndroidMkEntriesForTest(t, config, "", module)
+ if len(entries) != 1 {
+ t.Errorf("Expected a single AndroidMk entry, got %d", len(entries))
+ }
+ androidMkLines := entries[0].GetDistForGoals(module)
+
+ if len(androidMkLines) != len(testCase.expectedAndroidMkLines) {
+ t.Errorf(
+ "Expected %d AndroidMk lines, got %d:\n%v",
+ len(testCase.expectedAndroidMkLines),
+ len(androidMkLines),
+ androidMkLines,
+ )
+ }
+ for idx, line := range androidMkLines {
+ expectedLine := testCase.expectedAndroidMkLines[idx]
+ if line != expectedLine {
+ t.Errorf(
+ "Expected AndroidMk line to be '%s', got '%s'",
+ line,
+ expectedLine,
+ )
+ }
+ }
+ }
+}
diff --git a/android/apex.go b/android/apex.go
index 30152db..47f07ca 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -124,6 +124,10 @@
// the private part of the listed APEXes even when it is not included in the
// APEXes.
TestFor() []string
+
+ // Returns nil if this module supports sdkVersion
+ // Otherwise, returns error with reason
+ ShouldSupportSdkVersion(ctx BaseModuleContext, sdkVersion int) error
}
type ApexProperties struct {
@@ -477,3 +481,125 @@
},
})
}
+
+// TODO(b/158059172): remove minSdkVersion allowlist
+var minSdkVersionAllowlist = map[string]int{
+ "adbd": 30,
+ "android.net.ipsec.ike": 30,
+ "androidx-constraintlayout_constraintlayout-solver": 30,
+ "androidx.annotation_annotation": 28,
+ "androidx.arch.core_core-common": 28,
+ "androidx.collection_collection": 28,
+ "androidx.lifecycle_lifecycle-common": 28,
+ "apache-commons-compress": 29,
+ "bouncycastle_ike_digests": 30,
+ "brotli-java": 29,
+ "captiveportal-lib": 28,
+ "flatbuffer_headers": 30,
+ "framework-permission": 30,
+ "framework-statsd": 30,
+ "gemmlowp_headers": 30,
+ "ike-internals": 30,
+ "kotlinx-coroutines-android": 28,
+ "kotlinx-coroutines-core": 28,
+ "libadb_crypto": 30,
+ "libadb_pairing_auth": 30,
+ "libadb_pairing_connection": 30,
+ "libadb_pairing_server": 30,
+ "libadb_protos": 30,
+ "libadb_tls_connection": 30,
+ "libadbconnection_client": 30,
+ "libadbconnection_server": 30,
+ "libadbd_core": 30,
+ "libadbd_services": 30,
+ "libadbd": 30,
+ "libapp_processes_protos_lite": 30,
+ "libasyncio": 30,
+ "libbrotli": 30,
+ "libbuildversion": 30,
+ "libcrypto_static": 30,
+ "libcrypto_utils": 30,
+ "libdiagnose_usb": 30,
+ "libeigen": 30,
+ "liblz4": 30,
+ "libmdnssd": 30,
+ "libneuralnetworks_common": 30,
+ "libneuralnetworks_headers": 30,
+ "libneuralnetworks": 30,
+ "libprocpartition": 30,
+ "libprotobuf-java-lite": 30,
+ "libprotoutil": 30,
+ "libqemu_pipe": 30,
+ "libstats_jni": 30,
+ "libstatslog_statsd": 30,
+ "libstatsmetadata": 30,
+ "libstatspull": 30,
+ "libstatssocket": 30,
+ "libsync": 30,
+ "libtextclassifier_hash_headers": 30,
+ "libtextclassifier_hash_static": 30,
+ "libtflite_kernel_utils": 30,
+ "libwatchdog": 29,
+ "libzstd": 30,
+ "metrics-constants-protos": 28,
+ "net-utils-framework-common": 29,
+ "permissioncontroller-statsd": 28,
+ "philox_random_headers": 30,
+ "philox_random": 30,
+ "service-permission": 30,
+ "service-statsd": 30,
+ "statsd-aidl-ndk_platform": 30,
+ "statsd": 30,
+ "tensorflow_headers": 30,
+ "xz-java": 29,
+}
+
+// Function called while walking an APEX's payload dependencies.
+//
+// Return true if the `to` module should be visited, false otherwise.
+type PayloadDepsCallback func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool
+
+// UpdatableModule represents updatable APEX/APK
+type UpdatableModule interface {
+ Module
+ WalkPayloadDeps(ctx ModuleContext, do PayloadDepsCallback)
+}
+
+// CheckMinSdkVersion checks if every dependency of an updatable module sets min_sdk_version accordingly
+func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion int) {
+ // do not enforce min_sdk_version for host
+ if ctx.Host() {
+ return
+ }
+
+ // do not enforce for coverage build
+ if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") || ctx.DeviceConfig().NativeCoverageEnabled() || ctx.DeviceConfig().ClangCoverageEnabled() {
+ return
+ }
+
+ // do not enforce deps.min_sdk_version if APEX/APK doesn't set min_sdk_version or
+ // min_sdk_version is not finalized (e.g. current or codenames)
+ if minSdkVersion == FutureApiLevel {
+ return
+ }
+
+ m.WalkPayloadDeps(ctx, func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool {
+ if externalDep {
+ // external deps are outside the payload boundary, which is "stable" interface.
+ // We don't have to check min_sdk_version for external dependencies.
+ return false
+ }
+ if am, ok := from.(DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
+ return false
+ }
+ if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil {
+ toName := ctx.OtherModuleName(to)
+ if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver > minSdkVersion {
+ ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v. Dependency path: %s",
+ minSdkVersion, ctx.ModuleName(), err.Error(), ctx.GetPathString(false))
+ return false
+ }
+ }
+ return true
+ })
+}
diff --git a/android/hooks.go b/android/hooks.go
index f43a007..85fc081 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -120,6 +120,7 @@
type InstallHookContext interface {
ModuleContext
+ SrcPath() Path
Path() InstallPath
Symlink() bool
}
@@ -134,10 +135,17 @@
type installHookContext struct {
ModuleContext
+ srcPath Path
path InstallPath
symlink bool
}
+var _ InstallHookContext = &installHookContext{}
+
+func (x *installHookContext) SrcPath() Path {
+ return x.srcPath
+}
+
func (x *installHookContext) Path() InstallPath {
return x.path
}
@@ -146,10 +154,11 @@
return x.symlink
}
-func (x *hooks) runInstallHooks(ctx ModuleContext, path InstallPath, symlink bool) {
+func (x *hooks) runInstallHooks(ctx ModuleContext, srcPath Path, path InstallPath, symlink bool) {
if len(x.install) > 0 {
mctx := &installHookContext{
ModuleContext: ctx,
+ srcPath: srcPath,
path: path,
symlink: symlink,
}
diff --git a/android/module.go b/android/module.go
index f24047c..06079ca 100644
--- a/android/module.go
+++ b/android/module.go
@@ -315,6 +315,28 @@
return qualifiedModuleName{pkg: pkg, name: ""}
}
+type Dist struct {
+ // Copy the output of this module to the $DIST_DIR when `dist` is specified on the
+ // command line and any of these targets are also on the command line, or otherwise
+ // built
+ Targets []string `android:"arch_variant"`
+
+ // The name of the output artifact. This defaults to the basename of the output of
+ // the module.
+ Dest *string `android:"arch_variant"`
+
+ // The directory within the dist directory to store the artifact. Defaults to the
+ // top level directory ("").
+ Dir *string `android:"arch_variant"`
+
+ // A suffix to add to the artifact file name (before any extension).
+ Suffix *string `android:"arch_variant"`
+
+ // A string tag to select the OutputFiles associated with the tag. Defaults to the
+ // the empty "" string.
+ Tag *string `android:"arch_variant"`
+}
+
type nameProperties struct {
// The name of the module. Must be unique across all modules.
Name *string
@@ -454,23 +476,13 @@
// relative path to a file to include in the list of notices for the device
Notice *string `android:"path"`
- Dist struct {
- // copy the output of this module to the $DIST_DIR when `dist` is specified on the
- // command line and any of these targets are also on the command line, or otherwise
- // built
- Targets []string `android:"arch_variant"`
+ // configuration to distribute output files from this module to the distribution
+ // directory (default: $OUT/dist, configurable with $DIST_DIR)
+ Dist Dist `android:"arch_variant"`
- // The name of the output artifact. This defaults to the basename of the output of
- // the module.
- Dest *string `android:"arch_variant"`
-
- // The directory within the dist directory to store the artifact. Defaults to the
- // top level directory ("").
- Dir *string `android:"arch_variant"`
-
- // A suffix to add to the artifact file name (before any extension).
- Suffix *string `android:"arch_variant"`
- } `android:"arch_variant"`
+ // a list of configurations to distribute output files from this module to the
+ // distribution directory (default: $OUT/dist, configurable with $DIST_DIR)
+ Dists []Dist `android:"arch_variant"`
// The OsType of artifacts that this module variant is responsible for creating.
//
@@ -537,6 +549,14 @@
ImageVariation string `blueprint:"mutated"`
}
+// A map of OutputFile tag keys to Paths, for disting purposes.
+type TaggedDistFiles map[string]Paths
+
+func MakeDefaultDistFiles(paths ...Path) TaggedDistFiles {
+ // The default OutputFile tag is the empty "" string.
+ return TaggedDistFiles{"": paths}
+}
+
type hostAndDeviceProperties struct {
// If set to true, build a variant of the module for the host. Defaults to false.
Host_supported *bool
@@ -815,6 +835,41 @@
return m.visibilityPropertyInfo
}
+func (m *ModuleBase) Dists() []Dist {
+ if len(m.commonProperties.Dist.Targets) > 0 {
+ // Make a copy of the underlying Dists slice to protect against
+ // backing array modifications with repeated calls to this method.
+ distsCopy := append([]Dist(nil), m.commonProperties.Dists...)
+ return append(distsCopy, m.commonProperties.Dist)
+ } else {
+ return m.commonProperties.Dists
+ }
+}
+
+func (m *ModuleBase) GenerateTaggedDistFiles(ctx BaseModuleContext) TaggedDistFiles {
+ distFiles := make(TaggedDistFiles)
+ for _, dist := range m.Dists() {
+ var tag string
+ var distFilesForTag Paths
+ if dist.Tag == nil {
+ tag = ""
+ } else {
+ tag = *dist.Tag
+ }
+ distFilesForTag, err := m.base().module.(OutputFileProducer).OutputFiles(tag)
+ if err != nil {
+ ctx.PropertyErrorf("dist.tag", "%s", err.Error())
+ }
+ for _, distFile := range distFilesForTag {
+ if distFile != nil && !distFiles[tag].containsPath(distFile) {
+ distFiles[tag] = append(distFiles[tag], distFile)
+ }
+ }
+ }
+
+ return distFiles
+}
+
func (m *ModuleBase) Target() Target {
return m.commonProperties.CompileTarget
}
@@ -1959,7 +2014,7 @@
rule blueprint.Rule, deps []Path) InstallPath {
fullInstallPath := installPath.Join(m, name)
- m.module.base().hooks.runInstallHooks(m, fullInstallPath, false)
+ m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
if !m.skipInstall(fullInstallPath) {
@@ -1993,7 +2048,7 @@
func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath {
fullInstallPath := installPath.Join(m, name)
- m.module.base().hooks.runInstallHooks(m, fullInstallPath, true)
+ m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, true)
if !m.skipInstall(fullInstallPath) {
@@ -2022,7 +2077,7 @@
// (e.g. /apex/...)
func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath {
fullInstallPath := installPath.Join(m, name)
- m.module.base().hooks.runInstallHooks(m, fullInstallPath, true)
+ m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)
if !m.skipInstall(fullInstallPath) {
m.Build(pctx, BuildParams{
diff --git a/android/override_module.go b/android/override_module.go
index 90ddf50..6b246db 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -223,6 +223,11 @@
// next phase.
func overrideModuleDepsMutator(ctx BottomUpMutatorContext) {
if module, ok := ctx.Module().(OverrideModule); ok {
+ base := String(module.getOverrideModuleProperties().Base)
+ if !ctx.OtherModuleExists(base) {
+ ctx.PropertyErrorf("base", "%q is not a valid module name", base)
+ return
+ }
// See if there's a prebuilt module that overrides this override module with prefer flag,
// in which case we call SkipInstall on the corresponding variant later.
ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(dep Module) {
diff --git a/android/paths.go b/android/paths.go
index bed6f3f..d8d51a7 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -220,6 +220,15 @@
// Paths is a slice of Path objects, with helpers to operate on the collection.
type Paths []Path
+func (paths Paths) containsPath(path Path) bool {
+ for _, p := range paths {
+ if p == path {
+ return true
+ }
+ }
+ return false
+}
+
// PathsForSource returns Paths rooted from SrcDir
func PathsForSource(ctx PathContext, paths []string) Paths {
ret := make(Paths, len(paths))
diff --git a/androidmk/androidmk/androidmk.go b/androidmk/androidmk/androidmk.go
index dcd67d8..03cf74d 100644
--- a/androidmk/androidmk/androidmk.go
+++ b/androidmk/androidmk/androidmk.go
@@ -458,6 +458,9 @@
}
file.defs = append(file.defs, a)
} else {
+ if _, ok := file.globalAssignments[name]; ok {
+ return fmt.Errorf("cannot assign a variable multiple times: \"%s\"", name)
+ }
a := &bpparser.Assignment{
Name: name,
NamePos: pos,
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 4f307c4..726746b 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -1389,6 +1389,35 @@
`,
},
{
+ desc: "variableReassigned",
+ in: `
+include $(CLEAR_VARS)
+
+src_files:= a.cpp
+
+LOCAL_SRC_FILES:= $(src_files)
+LOCAL_MODULE:= test
+include $(BUILD_EXECUTABLE)
+
+# clear locally used variable
+src_files:=
+`,
+ expected: `
+
+
+src_files = ["a.cpp"]
+cc_binary {
+ name: "test",
+
+ srcs: src_files,
+}
+
+// clear locally used variable
+// ANDROIDMK TRANSLATION ERROR: cannot assign a variable multiple times: "src_files"
+// src_files :=
+`,
+ },
+ {
desc: "undefined_boolean_var",
in: `
include $(CLEAR_VARS)
diff --git a/apex/apex.go b/apex/apex.go
index 58cbb13..a9be1a8 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -16,7 +16,6 @@
import (
"fmt"
- "path"
"path/filepath"
"sort"
"strings"
@@ -1242,7 +1241,7 @@
container_certificate_file android.Path
container_private_key_file android.Path
- fileContexts android.Path
+ fileContexts android.WritablePath
// list of files to be included in this apex
filesInfo []apexFile
@@ -1724,13 +1723,8 @@
return true
}
-// Function called while walking an APEX's payload dependencies.
-//
-// Return true if the `to` module should be visited, false otherwise.
-type payloadDepsCallback func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool
-
// Visit dependencies that contributes to the payload of this APEX
-func (a *apexBundle) walkPayloadDeps(ctx android.ModuleContext, do payloadDepsCallback) {
+func (a *apexBundle) WalkPayloadDeps(ctx android.ModuleContext, do android.PayloadDepsCallback) {
ctx.WalkDeps(func(child, parent android.Module) bool {
am, ok := child.(android.ApexModule)
if !ok || !am.CanHaveApexVariants() {
@@ -1756,7 +1750,21 @@
}
func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) int {
- ver := proptools.StringDefault(a.properties.Min_sdk_version, "current")
+ ver := proptools.String(a.properties.Min_sdk_version)
+ if ver == "" {
+ return android.FutureApiLevel
+ }
+ // Treat the current codenames as "current", which means future API version (10000)
+ // Otherwise, ApiStrToNum converts codename(non-finalized) to a value from [9000...]
+ // and would fail to build against "current".
+ if android.InList(ver, ctx.Config().PlatformVersionActiveCodenames()) {
+ return android.FutureApiLevel
+ }
+ // In "REL" branch, "current" is mapped to finalized sdk version
+ if ctx.Config().PlatformSdkCodename() == "REL" && ver == "current" {
+ return ctx.Config().PlatformSdkVersionInt()
+ }
+ // Finalized codenames are OKAY and will be converted to int
intVer, err := android.ApiStrToNum(ctx, ver)
if err != nil {
ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
@@ -1784,7 +1792,7 @@
return
}
- a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
if externalDep {
// As soon as the dependency graph crosses the APEX boundary, don't go further.
return false
@@ -1820,6 +1828,17 @@
}
}
+func (a *apexBundle) checkMinSdkVersion(ctx android.ModuleContext) {
+ if a.testApex || a.vndkApex {
+ return
+ }
+ // Meaningless to check min_sdk_version when building use_vendor modules against non-Trebleized targets
+ if proptools.Bool(a.properties.Use_vendor) && ctx.DeviceConfig().VndkVersion() == "" {
+ return
+ }
+ android.CheckMinSdkVersion(a, ctx, a.minSdkVersion(ctx))
+}
+
// Ensures that a lib providing stub isn't statically linked
func (a *apexBundle) checkStaticLinkingToStubLibraries(ctx android.ModuleContext) {
// Practically, we only care about regular APEXes on the device.
@@ -1827,7 +1846,7 @@
return
}
- a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
if ccm, ok := to.(*cc.Module); ok {
apexName := ctx.ModuleName()
fromName := ctx.OtherModuleName(from)
@@ -1866,7 +1885,7 @@
}
func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- buildFlattenedAsDefault := ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
+ buildFlattenedAsDefault := ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuildApps()
switch a.properties.ApexType {
case imageApex:
if buildFlattenedAsDefault {
@@ -1902,6 +1921,7 @@
a.checkApexAvailability(ctx)
a.checkUpdatable(ctx)
+ a.checkMinSdkVersion(ctx)
a.checkStaticLinkingToStubLibraries(ctx)
handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
@@ -1935,7 +1955,7 @@
})
var filesInfo []apexFile
- // TODO(jiyong) do this using walkPayloadDeps
+ // TODO(jiyong) do this using WalkPayloadDeps
ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
depTag := ctx.OtherModuleDependencyTag(child)
if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
@@ -2174,22 +2194,6 @@
a.installDir = android.PathForModuleInstall(ctx, "apex")
a.filesInfo = filesInfo
- if a.properties.ApexType != zipApex {
- if a.properties.File_contexts == nil {
- a.fileContexts = android.PathForSource(ctx, "system/sepolicy/apex", ctx.ModuleName()+"-file_contexts")
- } else {
- a.fileContexts = android.PathForModuleSrc(ctx, *a.properties.File_contexts)
- if a.Platform() {
- if matched, err := path.Match("system/sepolicy/**/*", a.fileContexts.String()); err != nil || !matched {
- ctx.PropertyErrorf("file_contexts", "should be under system/sepolicy, but %q", a.fileContexts)
- }
- }
- }
- if !android.ExistentPathForSource(ctx, a.fileContexts.String()).Valid() {
- ctx.PropertyErrorf("file_contexts", "cannot find file_contexts file: %q", a.fileContexts)
- return
- }
- }
// Optimization. If we are building bundled APEX, for the files that are gathered due to the
// transitive dependencies, don't place them inside the APEX, but place a symlink pointing
// the same library in the system partition, thus effectively sharing the same libraries
@@ -2213,6 +2217,8 @@
// prepare apex_manifest.json
a.buildManifest(ctx, provideNativeLibs, requireNativeLibs)
+ a.buildFileContexts(ctx)
+
a.setCertificateAndPrivateKey(ctx)
if a.properties.ApexType == flattenedApex {
a.buildFlattenedApex(ctx)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 38c8489..f1638c3 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -206,6 +206,7 @@
config.TestProductVariables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"}
config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Q")
config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false)
+ config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
config.TestProductVariables.Platform_vndk_version = proptools.StringPtr("VER")
for _, handler := range handlers {
@@ -1104,13 +1105,13 @@
}{
{
name: "should link to the latest",
- minSdkVersion: "current",
+ minSdkVersion: "",
shouldLink: "30",
shouldNotLink: []string{"29"},
},
{
name: "should link to llndk#29",
- minSdkVersion: "29",
+ minSdkVersion: "min_sdk_version: \"29\",",
shouldLink: "29",
shouldNotLink: []string{"30"},
},
@@ -1123,7 +1124,7 @@
key: "myapex.key",
use_vendor: true,
native_shared_libs: ["mylib"],
- min_sdk_version: "`+tc.minSdkVersion+`",
+ `+tc.minSdkVersion+`
}
apex_key {
@@ -1140,6 +1141,7 @@
system_shared_libs: [],
stl: "none",
apex_available: [ "myapex" ],
+ min_sdk_version: "29",
}
cc_library {
@@ -1270,24 +1272,24 @@
ensureContains(t, libFlags, "libdl/android_arm64_armv8-a_shared/libdl.so")
}
-func TestApexUseStubsAccordingToMinSdkVersionInUnbundledBuild(t *testing.T) {
+func TestApexMinSdkVersion_NativeModulesShouldBeBuiltAgainstStubs(t *testing.T) {
// there are three links between liba --> libz
- // 1) myapex -> libx -> liba -> libz : this should be #2 link, but fallback to #1
- // 2) otherapex -> liby -> liba -> libz : this should be #3 link
+ // 1) myapex -> libx -> liba -> libz : this should be #29 link, but fallback to #28
+ // 2) otherapex -> liby -> liba -> libz : this should be #30 link
// 3) (platform) -> liba -> libz : this should be non-stub link
ctx, _ := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["libx"],
- min_sdk_version: "2",
+ min_sdk_version: "29",
}
apex {
name: "otherapex",
key: "myapex.key",
native_shared_libs: ["liby"],
- min_sdk_version: "3",
+ min_sdk_version: "30",
}
apex_key {
@@ -1302,6 +1304,7 @@
system_shared_libs: [],
stl: "none",
apex_available: [ "myapex" ],
+ min_sdk_version: "29",
}
cc_library {
@@ -1310,6 +1313,7 @@
system_shared_libs: [],
stl: "none",
apex_available: [ "otherapex" ],
+ min_sdk_version: "29",
}
cc_library {
@@ -1321,6 +1325,7 @@
"//apex_available:anyapex",
"//apex_available:platform",
],
+ min_sdk_version: "29",
}
cc_library {
@@ -1328,10 +1333,10 @@
system_shared_libs: [],
stl: "none",
stubs: {
- versions: ["1", "3"],
+ versions: ["28", "30"],
},
}
- `, withUnbundledBuild)
+ `)
expectLink := func(from, from_variant, to, to_variant string) {
ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
@@ -1343,13 +1348,13 @@
}
// platform liba is linked to non-stub version
expectLink("liba", "shared", "libz", "shared")
- // liba in myapex is linked to #1
- expectLink("liba", "shared_myapex", "libz", "shared_1")
- expectNoLink("liba", "shared_myapex", "libz", "shared_3")
+ // liba in myapex is linked to #28
+ expectLink("liba", "shared_myapex", "libz", "shared_28")
+ expectNoLink("liba", "shared_myapex", "libz", "shared_30")
expectNoLink("liba", "shared_myapex", "libz", "shared")
- // liba in otherapex is linked to #3
- expectLink("liba", "shared_otherapex", "libz", "shared_3")
- expectNoLink("liba", "shared_otherapex", "libz", "shared_1")
+ // liba in otherapex is linked to #30
+ expectLink("liba", "shared_otherapex", "libz", "shared_30")
+ expectNoLink("liba", "shared_otherapex", "libz", "shared_28")
expectNoLink("liba", "shared_otherapex", "libz", "shared")
}
@@ -1374,6 +1379,7 @@
system_shared_libs: [],
stl: "none",
apex_available: [ "myapex" ],
+ min_sdk_version: "R",
}
cc_library {
@@ -1407,7 +1413,7 @@
expectNoLink("libx", "shared_myapex", "libz", "shared")
}
-func TestApexMinSdkVersionDefaultsToLatest(t *testing.T) {
+func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) {
ctx, _ := testApex(t, `
apex {
name: "myapex",
@@ -1516,6 +1522,7 @@
name: "libx",
shared_libs: ["libbar"],
apex_available: [ "myapex" ],
+ min_sdk_version: "29",
}
cc_library {
@@ -1553,6 +1560,7 @@
cc_library {
name: "libx",
apex_available: [ "myapex" ],
+ min_sdk_version: "29",
}
`)
@@ -1564,7 +1572,7 @@
ensureListNotContains(t, cm.Properties.AndroidMkStaticLibs, "libgcc_stripped")
}
-func TestInvalidMinSdkVersion(t *testing.T) {
+func TestApexMinSdkVersion_ErrorIfIncompatibleStubs(t *testing.T) {
testApexError(t, `"libz" .*: not found a version\(<=29\)`, `
apex {
name: "myapex",
@@ -1585,6 +1593,7 @@
system_shared_libs: [],
stl: "none",
apex_available: [ "myapex" ],
+ min_sdk_version: "29",
}
cc_library {
@@ -1596,12 +1605,15 @@
},
}
`)
+}
- testApexError(t, `"myapex" .*: min_sdk_version: SDK version should be .*`, `
+func TestApexMinSdkVersion_ErrorIfIncompatibleVersion(t *testing.T) {
+ testApexError(t, `module "mylib".*: should support min_sdk_version\(29\)`, `
apex {
name: "myapex",
key: "myapex.key",
- min_sdk_version: "abc",
+ native_shared_libs: ["mylib"],
+ min_sdk_version: "29",
}
apex_key {
@@ -1609,6 +1621,67 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [
+ "myapex",
+ ],
+ min_sdk_version: "30",
+ }
+ `)
+}
+
+func TestApexMinSdkVersion_Okay(t *testing.T) {
+ testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ java_libs: ["libbar"],
+ min_sdk_version: "29",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["libfoo_dep"],
+ apex_available: ["myapex"],
+ min_sdk_version: "29",
+ }
+
+ cc_library {
+ name: "libfoo_dep",
+ srcs: ["mylib.cpp"],
+ apex_available: ["myapex"],
+ min_sdk_version: "29",
+ }
+
+ java_library {
+ name: "libbar",
+ sdk_version: "current",
+ srcs: ["a.java"],
+ static_libs: ["libbar_dep"],
+ apex_available: ["myapex"],
+ min_sdk_version: "29",
+ }
+
+ java_library {
+ name: "libbar_dep",
+ sdk_version: "current",
+ srcs: ["a.java"],
+ apex_available: ["myapex"],
+ min_sdk_version: "29",
+ }
`)
}
@@ -1659,6 +1732,7 @@
srcs: ["foo/bar/MyClass.java"],
sdk_version: "current",
apex_available: ["myapex"],
+ min_sdk_version: "29",
}
`,
},
@@ -1728,6 +1802,135 @@
}
}
+func TestApexMinSdkVersion_ErrorIfDepIsNewer(t *testing.T) {
+ testApexError(t, `module "mylib2".*: should support min_sdk_version\(29\) for "myapex"`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib"],
+ min_sdk_version: "29",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["mylib2"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [
+ "myapex",
+ ],
+ min_sdk_version: "29",
+ }
+
+ // indirect part of the apex
+ cc_library {
+ name: "mylib2",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [
+ "myapex",
+ ],
+ min_sdk_version: "30",
+ }
+ `)
+}
+
+func TestApexMinSdkVersion_ErrorIfDepIsNewer_Java(t *testing.T) {
+ testApexError(t, `module "bar".*: should support min_sdk_version\(29\) for "myapex"`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ apps: ["AppFoo"],
+ min_sdk_version: "29",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ android_app {
+ name: "AppFoo",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "current",
+ min_sdk_version: "29",
+ system_modules: "none",
+ stl: "none",
+ static_libs: ["bar"],
+ apex_available: [ "myapex" ],
+ }
+
+ java_library {
+ name: "bar",
+ sdk_version: "current",
+ srcs: ["a.java"],
+ apex_available: [ "myapex" ],
+ }
+ `)
+}
+
+func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib"],
+ min_sdk_version: "29",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ // mylib in myapex will link to mylib2#29
+ // mylib in otherapex will link to mylib2(non-stub) in otherapex as well
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["mylib2"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: ["myapex", "otherapex"],
+ min_sdk_version: "29",
+ }
+
+ cc_library {
+ name: "mylib2",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: ["otherapex"],
+ stubs: { versions: ["29", "30"] },
+ min_sdk_version: "30",
+ }
+
+ apex {
+ name: "otherapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib", "mylib2"],
+ min_sdk_version: "30",
+ }
+ `)
+ expectLink := func(from, from_variant, to, to_variant string) {
+ ld := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld")
+ libFlags := ld.Args["libFlags"]
+ ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
+ }
+ expectLink("mylib", "shared_myapex", "mylib2", "shared_29")
+ expectLink("mylib", "shared_otherapex", "mylib2", "shared_otherapex")
+}
+
func TestFilesInSubDir(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -2217,6 +2420,7 @@
"otherapex",
],
recovery_available: true,
+ min_sdk_version: "29",
}
cc_library {
name: "mylib2",
@@ -2228,6 +2432,7 @@
"otherapex",
],
use_apex_name_macro: true,
+ min_sdk_version: "29",
}
`)
@@ -3275,110 +3480,104 @@
}
}
-func TestFileContexts(t *testing.T) {
+func TestFileContexts_FindInDefaultLocationIfNotSet(t *testing.T) {
ctx, _ := testApex(t, `
- apex {
- name: "myapex",
- key: "myapex.key",
- }
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ }
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
`)
module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
- apexRule := module.Rule("apexRule")
- actual := apexRule.Args["file_contexts"]
- expected := "system/sepolicy/apex/myapex-file_contexts"
- if actual != expected {
- t.Errorf("wrong file_contexts. expected %q. actual %q", expected, actual)
- }
+ rule := module.Output("file_contexts")
+ ensureContains(t, rule.RuleParams.Command, "cat system/sepolicy/apex/myapex-file_contexts")
+}
+func TestFileContexts_ShouldBeUnderSystemSepolicyForSystemApexes(t *testing.T) {
testApexError(t, `"myapex" .*: file_contexts: should be under system/sepolicy`, `
- apex {
- name: "myapex",
- key: "myapex.key",
- file_contexts: "my_own_file_contexts",
- }
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ file_contexts: "my_own_file_contexts",
+ }
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
`, withFiles(map[string][]byte{
"my_own_file_contexts": nil,
}))
+}
+func TestFileContexts_ProductSpecificApexes(t *testing.T) {
testApexError(t, `"myapex" .*: file_contexts: cannot find`, `
- apex {
- name: "myapex",
- key: "myapex.key",
- product_specific: true,
- file_contexts: "product_specific_file_contexts",
- }
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ product_specific: true,
+ file_contexts: "product_specific_file_contexts",
+ }
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
`)
- ctx, _ = testApex(t, `
- apex {
- name: "myapex",
- key: "myapex.key",
- product_specific: true,
- file_contexts: "product_specific_file_contexts",
- }
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ product_specific: true,
+ file_contexts: "product_specific_file_contexts",
+ }
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
`, withFiles(map[string][]byte{
"product_specific_file_contexts": nil,
}))
- module = ctx.ModuleForTests("myapex", "android_common_myapex_image")
- apexRule = module.Rule("apexRule")
- actual = apexRule.Args["file_contexts"]
- expected = "product_specific_file_contexts"
- if actual != expected {
- t.Errorf("wrong file_contexts. expected %q. actual %q", expected, actual)
- }
+ module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+ rule := module.Output("file_contexts")
+ ensureContains(t, rule.RuleParams.Command, "cat product_specific_file_contexts")
+}
- ctx, _ = testApex(t, `
- apex {
- name: "myapex",
- key: "myapex.key",
- product_specific: true,
- file_contexts: ":my-file-contexts",
- }
+func TestFileContexts_SetViaFileGroup(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ product_specific: true,
+ file_contexts: ":my-file-contexts",
+ }
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
- filegroup {
- name: "my-file-contexts",
- srcs: ["product_specific_file_contexts"],
- }
+ filegroup {
+ name: "my-file-contexts",
+ srcs: ["product_specific_file_contexts"],
+ }
`, withFiles(map[string][]byte{
"product_specific_file_contexts": nil,
}))
- module = ctx.ModuleForTests("myapex", "android_common_myapex_image")
- apexRule = module.Rule("apexRule")
- actual = apexRule.Args["file_contexts"]
- expected = "product_specific_file_contexts"
- if actual != expected {
- t.Errorf("wrong file_contexts. expected %q. actual %q", expected, actual)
- }
+ module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+ rule := module.Output("file_contexts")
+ ensureContains(t, rule.RuleParams.Command, "cat product_specific_file_contexts")
}
func TestApexKeyFromOtherModule(t *testing.T) {
@@ -4349,6 +4548,7 @@
stl: "libc++",
system_shared_libs: [],
apex_available: [ "myapex" ],
+ min_sdk_version: "29",
}
`, withUnbundledBuild)
@@ -4749,6 +4949,7 @@
"myapex.updatable",
"//apex_available:platform",
],
+ min_sdk_version: "current",
}
cc_library {
@@ -4761,6 +4962,7 @@
"myapex.updatable",
"//apex_available:platform",
],
+ min_sdk_version: "current",
}
java_library {
@@ -4774,6 +4976,7 @@
"myapex.updatable",
"//apex_available:platform",
],
+ min_sdk_version: "current",
}
java_library {
@@ -4786,6 +4989,7 @@
"myapex.updatable",
"//apex_available:platform",
],
+ min_sdk_version: "current",
}
`
diff --git a/apex/builder.go b/apex/builder.go
index af43417..ede11d0 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -17,6 +17,7 @@
import (
"encoding/json"
"fmt"
+ "path"
"path/filepath"
"runtime"
"sort"
@@ -231,10 +232,42 @@
})
}
+func (a *apexBundle) buildFileContexts(ctx android.ModuleContext) {
+ if a.properties.ApexType == zipApex {
+ return
+ }
+ var fileContexts android.Path
+ if a.properties.File_contexts == nil {
+ fileContexts = android.PathForSource(ctx, "system/sepolicy/apex", ctx.ModuleName()+"-file_contexts")
+ } else {
+ fileContexts = android.PathForModuleSrc(ctx, *a.properties.File_contexts)
+ }
+ if a.Platform() {
+ if matched, err := path.Match("system/sepolicy/**/*", fileContexts.String()); err != nil || !matched {
+ ctx.PropertyErrorf("file_contexts", "should be under system/sepolicy, but %q", fileContexts)
+ return
+ }
+ }
+ if !android.ExistentPathForSource(ctx, fileContexts.String()).Valid() {
+ ctx.PropertyErrorf("file_contexts", "cannot find file_contexts file: %q", a.fileContexts)
+ return
+ }
+
+ output := android.PathForModuleOut(ctx, "file_contexts")
+ rule := android.NewRuleBuilder()
+ rule.Command().Text("rm").FlagWithOutput("-f ", output)
+ rule.Command().Text("cat").Input(fileContexts).Text(">>").Output(output)
+ rule.Command().Text("echo").Text(">>").Output(output)
+ rule.Command().Text("echo").Flag("/apex_manifest\\\\.pb u:object_r:system_file:s0").Text(">>").Output(output)
+ rule.Build(pctx, ctx, "file_contexts."+a.Name(), "Generate file_contexts")
+
+ a.fileContexts = output.OutputPath
+}
+
func (a *apexBundle) buildNoticeFiles(ctx android.ModuleContext, apexFileName string) android.NoticeOutputs {
var noticeFiles android.Paths
- a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
if externalDep {
// As soon as the dependency graph crosses the APEX boundary, don't go further.
return false
@@ -733,7 +766,7 @@
}
depInfos := android.DepNameToDepInfoMap{}
- a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
+ a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
if from.Name() == to.Name() {
// This can happen for cc.reuseObjTag. We are not interested in tracking this.
// As soon as the dependency graph crosses the APEX boundary, don't go further.
diff --git a/cc/androidmk.go b/cc/androidmk.go
index b3ad610..3f812c2 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -249,7 +249,10 @@
entries.Class = "HEADER_LIBRARIES"
}
- entries.DistFile = library.distFile
+ if library.distFile != nil {
+ entries.DistFiles = android.MakeDefaultDistFiles(library.distFile)
+ }
+
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
library.androidMkWriteExportedFlags(entries)
library.androidMkEntriesWriteAdditionalDependenciesForSourceAbiDiff(entries)
@@ -318,7 +321,7 @@
ctx.subAndroidMk(entries, binary.baseInstaller)
entries.Class = "EXECUTABLES"
- entries.DistFile = binary.distFile
+ entries.DistFiles = binary.distFiles
entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
entries.SetString("LOCAL_SOONG_UNSTRIPPED_BINARY", binary.unstrippedOutputFile.String())
if len(binary.symlinks) > 0 {
diff --git a/cc/binary.go b/cc/binary.go
index 251b7f0..565cb8a 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -98,8 +98,8 @@
// Output archive of gcno coverage information
coverageOutputFile android.OptionalPath
- // Location of the file that should be copied to dist dir when requested
- distFile android.OptionalPath
+ // Location of the files that should be copied to dist dir when requested
+ distFiles android.TaggedDistFiles
post_install_cmds []string
}
@@ -367,11 +367,11 @@
binary.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
} else {
versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
- binary.distFile = android.OptionalPathForPath(versionedOutputFile)
+ binary.distFiles = android.MakeDefaultDistFiles(versionedOutputFile)
if binary.stripper.needsStrip(ctx) {
out := android.PathForModuleOut(ctx, "versioned-stripped", fileName)
- binary.distFile = android.OptionalPathForPath(out)
+ binary.distFiles = android.MakeDefaultDistFiles(out)
binary.stripper.stripExecutableOrSharedLib(ctx, versionedOutputFile, out, builderFlags)
}
diff --git a/cc/cc.go b/cc/cc.go
index ebdb46c..c3b0d88 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -2905,6 +2905,54 @@
return true
}
+// b/154667674: refactor this to handle "current" in a consistent way
+func decodeSdkVersionString(ctx android.BaseModuleContext, versionString string) (int, error) {
+ if versionString == "" {
+ return 0, fmt.Errorf("not specified")
+ }
+ if versionString == "current" {
+ if ctx.Config().PlatformSdkCodename() == "REL" {
+ return ctx.Config().PlatformSdkVersionInt(), nil
+ }
+ return android.FutureApiLevel, nil
+ }
+ return android.ApiStrToNum(ctx, versionString)
+}
+
+func (c *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+ // We ignore libclang_rt.* prebuilt libs since they declare sdk_version: 14(b/121358700)
+ if strings.HasPrefix(ctx.OtherModuleName(c), "libclang_rt") {
+ return nil
+ }
+ // b/154569636: set min_sdk_version correctly for toolchain_libraries
+ if c.ToolchainLibrary() {
+ return nil
+ }
+ // We don't check for prebuilt modules
+ if _, ok := c.linker.(prebuiltLinkerInterface); ok {
+ return nil
+ }
+ minSdkVersion := c.MinSdkVersion()
+ if minSdkVersion == "apex_inherit" {
+ return nil
+ }
+ if minSdkVersion == "" {
+ // JNI libs within APK-in-APEX fall into here
+ // Those are okay to set sdk_version instead
+ // We don't have to check if this is a SDK variant because
+ // non-SDK variant resets sdk_version, which works too.
+ minSdkVersion = c.SdkVersion()
+ }
+ ver, err := decodeSdkVersionString(ctx, minSdkVersion)
+ if err != nil {
+ return err
+ }
+ if ver > sdkVersion {
+ return fmt.Errorf("newer SDK(%v)", ver)
+ }
+ return nil
+}
+
//
// Defaults
//
diff --git a/cc/library.go b/cc/library.go
index 968702e..98f4d48 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -369,7 +369,7 @@
unstrippedOutputFile android.Path
// Location of the file that should be copied to dist dir when requested
- distFile android.OptionalPath
+ distFile android.Path
versionScriptPath android.ModuleGenPath
@@ -894,7 +894,7 @@
library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
} else {
versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
- library.distFile = android.OptionalPathForPath(versionedOutputFile)
+ library.distFile = versionedOutputFile
library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
}
}
@@ -988,11 +988,11 @@
library.injectVersionSymbol(ctx, outputFile, versionedOutputFile)
} else {
versionedOutputFile := android.PathForModuleOut(ctx, "versioned", fileName)
- library.distFile = android.OptionalPathForPath(versionedOutputFile)
+ library.distFile = versionedOutputFile
if library.stripper.needsStrip(ctx) {
out := android.PathForModuleOut(ctx, "versioned-stripped", fileName)
- library.distFile = android.OptionalPathForPath(out)
+ library.distFile = out
library.stripper.stripExecutableOrSharedLib(ctx, versionedOutputFile, out, builderFlags)
}
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 4410302..9c54399 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -380,7 +380,11 @@
// Make sure that the include directories are unique.
p.ExportedIncludeDirs = android.FirstUniquePaths(exportedIncludeDirs)
p.exportedGeneratedIncludeDirs = android.FirstUniquePaths(exportedGeneratedIncludeDirs)
- p.ExportedSystemIncludeDirs = android.FirstUniquePaths(ccModule.ExportedSystemIncludeDirs())
+
+ // Take a copy before filtering out duplicates to avoid changing the slice owned by the
+ // ccModule.
+ dirs := append(android.Paths(nil), ccModule.ExportedSystemIncludeDirs()...)
+ p.ExportedSystemIncludeDirs = android.FirstUniquePaths(dirs)
p.ExportedFlags = ccModule.ExportedFlags()
if ccModule.linker != nil {
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index c4d7708..acdc581 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -145,6 +145,7 @@
libraryDecorator: library,
}
module.installer = nil
+ module.Properties.Sdk_version = StringPtr("minimum")
module.Properties.HideFromMake = true
module.Properties.AlwaysSdk = true
module.Properties.Sdk_version = StringPtr("current")
diff --git a/cc/testing.go b/cc/testing.go
index 479b424..b5cf45c 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -273,6 +273,7 @@
vendor_available: true,
recovery_available: true,
host_supported: true,
+ min_sdk_version: "29",
apex_available: [
"//apex_available:platform",
"//apex_available:anyapex",
@@ -287,6 +288,7 @@
vendor_available: true,
recovery_available: true,
host_supported: true,
+ min_sdk_version: "29",
vndk: {
enabled: true,
support_system_process: true,
@@ -305,6 +307,7 @@
host_supported: false,
vendor_available: true,
recovery_available: true,
+ min_sdk_version: "29",
apex_available: [
"//apex_available:platform",
"//apex_available:anyapex",
@@ -338,6 +341,7 @@
recovery_available: true,
vendor_available: true,
native_bridge_supported: true,
+ min_sdk_version: "29",
stl: "none",
}
@@ -365,6 +369,7 @@
recovery_available: true,
vendor_available: true,
native_bridge_supported: true,
+ min_sdk_version: "29",
stl: "none",
}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index f6904f1..8b80871 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -559,6 +559,12 @@
}
}
+func (g *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+ // Because generated outputs are checked by client modules(e.g. cc_library, ...)
+ // we can safely ignore the check here.
+ return nil
+}
+
func generatorFactory(taskGenerator taskFunc, props ...interface{}) *Module {
module := &Module{
taskGenerator: taskGenerator,
diff --git a/java/aar.go b/java/aar.go
index 074ead4..500788f 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -762,6 +762,10 @@
return a.depIsInSameApex(ctx, dep)
}
+func (g *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+ return nil
+}
+
var _ android.PrebuiltInterface = (*Import)(nil)
// android_library_import imports an `.aar` file into the build graph as if it was built with android_library.
diff --git a/java/androidmk.go b/java/androidmk.go
index 62cf169..e73b030 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -91,7 +91,7 @@
} else {
mainEntries = android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
- DistFile: android.OptionalPathForPath(library.distFile),
+ DistFiles: library.distFiles,
OutputFile: android.OptionalPathForPath(library.outputFile),
Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
@@ -550,14 +550,14 @@
// needed because an invalid output file would prevent the make entries from
// being written.
// TODO(b/146727827): Revert when we do not need to generate stubs and API separately.
- distFile := android.OptionalPathForPath(dstubs.apiFile)
+ distFile := dstubs.apiFile
outputFile := android.OptionalPathForPath(dstubs.stubsSrcJar)
if !outputFile.Valid() {
- outputFile = distFile
+ outputFile = android.OptionalPathForPath(distFile)
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
- DistFile: distFile,
+ DistFiles: android.MakeDefaultDistFiles(distFile),
OutputFile: outputFile,
Include: "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index d471fb7..075b7aa 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -156,17 +156,158 @@
}
`)
- without_tag_entries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_without_tag", "android_common").Module())
- with_tag_entries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_with_tag", "android_common").Module())
+ withoutTagEntries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_without_tag", "android_common").Module())
+ withTagEntries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_with_tag", "android_common").Module())
- if len(without_tag_entries) != 2 || len(with_tag_entries) != 2 {
- t.Errorf("two mk entries per module expected, got %d and %d", len(without_tag_entries), len(with_tag_entries))
+ if len(withoutTagEntries) != 2 || len(withTagEntries) != 2 {
+ t.Errorf("two mk entries per module expected, got %d and %d", len(withoutTagEntries), len(withTagEntries))
}
- if !with_tag_entries[0].DistFile.Valid() || !strings.Contains(with_tag_entries[0].DistFile.String(), "/javac/foo_with_tag.jar") {
- t.Errorf("expected classes.jar DistFile, got %v", with_tag_entries[0].DistFile)
+ if len(withTagEntries[0].DistFiles[".jar"]) != 1 ||
+ !strings.Contains(withTagEntries[0].DistFiles[".jar"][0].String(), "/javac/foo_with_tag.jar") {
+ t.Errorf("expected DistFiles to contain classes.jar, got %v", withTagEntries[0].DistFiles)
}
- if without_tag_entries[0].DistFile.Valid() {
- t.Errorf("did not expect explicit DistFile, got %v", without_tag_entries[0].DistFile)
+ if len(withoutTagEntries[0].DistFiles[".jar"]) > 0 {
+ t.Errorf("did not expect explicit DistFile for .jar tag, got %v", withoutTagEntries[0].DistFiles[".jar"])
+ }
+}
+
+func TestDistWithDest(t *testing.T) {
+ ctx, config := testJava(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ compile_dex: true,
+ dist: {
+ targets: ["my_goal"],
+ dest: "my/custom/dest/dir",
+ },
+ }
+ `)
+
+ module := ctx.ModuleForTests("foo", "android_common").Module()
+ entries := android.AndroidMkEntriesForTest(t, config, "", module)
+ if len(entries) != 2 {
+ t.Errorf("Expected 2 AndroidMk entries, got %d", len(entries))
+ }
+
+ distStrings := entries[0].GetDistForGoals(module)
+
+ if len(distStrings) != 2 {
+ t.Errorf("Expected 2 entries for dist: PHONY and dist-for-goals, but got %q", distStrings)
+ }
+
+ if distStrings[0] != ".PHONY: my_goal\n" {
+ t.Errorf("Expected .PHONY entry to declare my_goal, but got: %s", distStrings[0])
+ }
+
+ if !strings.Contains(distStrings[1], "$(call dist-for-goals,my_goal") ||
+ !strings.Contains(distStrings[1], ".intermediates/foo/android_common/dex/foo.jar:my/custom/dest/dir") {
+ t.Errorf(
+ "Expected dist-for-goals entry to contain my_goal and new dest dir, but got: %s", distStrings[1])
+ }
+}
+
+func TestDistsWithAllProperties(t *testing.T) {
+ ctx, config := testJava(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ compile_dex: true,
+ dist: {
+ targets: ["baz"],
+ },
+ dists: [
+ {
+ targets: ["bar"],
+ tag: ".jar",
+ dest: "bar.jar",
+ dir: "bar/dir",
+ suffix: ".qux",
+ },
+ ]
+ }
+ `)
+
+ module := ctx.ModuleForTests("foo", "android_common").Module()
+ entries := android.AndroidMkEntriesForTest(t, config, "", module)
+ if len(entries) != 2 {
+ t.Errorf("Expected 2 AndroidMk entries, got %d", len(entries))
+ }
+
+ distStrings := entries[0].GetDistForGoals(module)
+
+ if len(distStrings) != 4 {
+ t.Errorf("Expected 4 entries for dist: PHONY and dist-for-goals, but got %d", len(distStrings))
+ }
+
+ if distStrings[0] != ".PHONY: bar\n" {
+ t.Errorf("Expected .PHONY entry to declare bar, but got: %s", distStrings[0])
+ }
+
+ if !strings.Contains(distStrings[1], "$(call dist-for-goals,bar") ||
+ !strings.Contains(
+ distStrings[1],
+ ".intermediates/foo/android_common/javac/foo.jar:bar/dir/bar.qux.jar") {
+ t.Errorf(
+ "Expected dist-for-goals entry to contain bar and new dest dir, but got: %s", distStrings[1])
+ }
+
+ if distStrings[2] != ".PHONY: baz\n" {
+ t.Errorf("Expected .PHONY entry to declare baz, but got: %s", distStrings[2])
+ }
+
+ if !strings.Contains(distStrings[3], "$(call dist-for-goals,baz") ||
+ !strings.Contains(distStrings[3], ".intermediates/foo/android_common/dex/foo.jar:foo.jar") {
+ t.Errorf(
+ "Expected dist-for-goals entry to contain my_other_goal and new dest dir, but got: %s",
+ distStrings[3])
+ }
+}
+
+func TestDistsWithTag(t *testing.T) {
+ ctx, config := testJava(t, `
+ java_library {
+ name: "foo_without_tag",
+ srcs: ["a.java"],
+ compile_dex: true,
+ dists: [
+ {
+ targets: ["hi"],
+ },
+ ],
+ }
+ java_library {
+ name: "foo_with_tag",
+ srcs: ["a.java"],
+ compile_dex: true,
+ dists: [
+ {
+ targets: ["hi"],
+ tag: ".jar",
+ },
+ ],
+ }
+ `)
+
+ moduleWithoutTag := ctx.ModuleForTests("foo_without_tag", "android_common").Module()
+ moduleWithTag := ctx.ModuleForTests("foo_with_tag", "android_common").Module()
+
+ withoutTagEntries := android.AndroidMkEntriesForTest(t, config, "", moduleWithoutTag)
+ withTagEntries := android.AndroidMkEntriesForTest(t, config, "", moduleWithTag)
+
+ if len(withoutTagEntries) != 2 || len(withTagEntries) != 2 {
+ t.Errorf("two mk entries per module expected, got %d and %d", len(withoutTagEntries), len(withTagEntries))
+ }
+
+ distFilesWithoutTag := withoutTagEntries[0].DistFiles
+ distFilesWithTag := withTagEntries[0].DistFiles
+
+ if len(distFilesWithTag[".jar"]) != 1 ||
+ !strings.Contains(distFilesWithTag[".jar"][0].String(), "/javac/foo_with_tag.jar") {
+ t.Errorf("expected foo_with_tag's .jar-tagged DistFiles to contain classes.jar, got %v", distFilesWithTag[".jar"])
+ }
+ if len(distFilesWithoutTag[".jar"]) > 0 {
+ t.Errorf("did not expect foo_without_tag's .jar-tagged DistFiles to contain files, but got %v", distFilesWithoutTag[".jar"])
}
}
diff --git a/java/app.go b/java/app.go
index c568516..37a6453 100755
--- a/java/app.go
+++ b/java/app.go
@@ -421,8 +421,10 @@
if String(a.deviceProperties.Min_sdk_version) == "" {
ctx.PropertyErrorf("updatable", "updatable apps must set min_sdk_version.")
}
+
if minSdkVersion, err := a.minSdkVersion().effectiveVersion(ctx); err == nil {
a.checkJniLibsSdkVersion(ctx, minSdkVersion)
+ android.CheckMinSdkVersion(a, ctx, int(minSdkVersion))
} else {
ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
}
@@ -862,13 +864,13 @@
return jniLibs, certificates
}
-func (a *AndroidApp) walkPayloadDeps(ctx android.ModuleContext,
- do func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool)) {
-
+func (a *AndroidApp) WalkPayloadDeps(ctx android.ModuleContext, do android.PayloadDepsCallback) {
ctx.WalkDeps(func(child, parent android.Module) bool {
isExternal := !a.DepIsInSameApex(ctx, child)
if am, ok := child.(android.ApexModule); ok {
- do(ctx, parent, am, isExternal)
+ if !do(ctx, parent, am, isExternal) {
+ return false
+ }
}
return !isExternal
})
@@ -880,7 +882,7 @@
}
depsInfo := android.DepNameToDepInfoMap{}
- a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) {
+ a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
depName := to.Name()
if info, exist := depsInfo[depName]; exist {
info.From = append(info.From, from.Name())
@@ -900,6 +902,7 @@
MinSdkVersion: toMinSdkVersion,
}
}
+ return true
})
a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(), depsInfo)
@@ -1563,6 +1566,11 @@
return sdkSpecFrom("")
}
+func (j *AndroidAppImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+ // Do not check for prebuilts against the min_sdk_version of enclosing APEX
+ return 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 e45ba70..120dc00 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -473,6 +473,24 @@
}
}
+func TestUpdatableApps_TransitiveDepsShouldSetMinSdkVersion(t *testing.T) {
+ testJavaError(t, `module "bar".*: should support min_sdk_version\(29\)`, cc.GatherRequiredDepsForTest(android.Android)+`
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ updatable: true,
+ sdk_version: "current",
+ min_sdk_version: "29",
+ static_libs: ["bar"],
+ }
+
+ java_library {
+ name: "bar",
+ sdk_version: "current",
+ }
+ `)
+}
+
func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) {
testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
android_app {
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 7f1afd6..f1b7178 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -173,7 +173,7 @@
profileBootListing = android.ExistentPathForSource(ctx,
ctx.ModuleDir(), String(d.dexpreoptProperties.Dex_preopt.Profile)+"-boot")
profileIsTextListing = true
- } else {
+ } else if global.ProfileDir != "" {
profileClassListing = android.ExistentPathForSource(ctx,
global.ProfileDir, ctx.ModuleName()+".prof")
}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index a0b7edf..73b897a 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1325,7 +1325,6 @@
cmd.Flag("--exclude-documentation-from-stubs")
}
}
- cmd.FlagWithArg("--hide ", "ShowingMemberInHiddenClass") // b/159121253 -- remove it once all the violations are fixed.
}
func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
diff --git a/java/java.go b/java/java.go
index 7d32c34..0a8eb99 100644
--- a/java/java.go
+++ b/java/java.go
@@ -479,7 +479,7 @@
// list of the xref extraction files
kytheFiles android.Paths
- distFile android.Path
+ distFiles android.TaggedDistFiles
// Collect the module directory for IDE info in java/jdeps.go.
modulePaths []string
@@ -1887,6 +1887,24 @@
return j.depIsInSameApex(ctx, dep)
}
+func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+ sdkSpec := j.minSdkVersion()
+ if !sdkSpec.specified() {
+ return fmt.Errorf("min_sdk_version is not specified")
+ }
+ if sdkSpec.kind == sdkCore {
+ return nil
+ }
+ ver, err := sdkSpec.effectiveVersion(ctx)
+ if err != nil {
+ return err
+ }
+ if int(ver) > sdkVersion {
+ return fmt.Errorf("newer SDK(%v)", ver)
+ }
+ return nil
+}
+
func (j *Module) Stem() string {
return proptools.StringDefault(j.deviceProperties.Stem, j.Name())
}
@@ -1903,18 +1921,9 @@
// Java libraries (.jar file)
//
-type LibraryProperties struct {
- Dist struct {
- // The tag of the output of this module that should be output.
- Tag *string `android:"arch_variant"`
- } `android:"arch_variant"`
-}
-
type Library struct {
Module
- libraryProperties LibraryProperties
-
InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths)
}
@@ -1976,14 +1985,7 @@
j.Stem()+".jar", j.outputFile, extraInstallDeps...)
}
- // Verify Dist.Tag is set to a supported output
- if j.libraryProperties.Dist.Tag != nil {
- distFiles, err := j.OutputFiles(*j.libraryProperties.Dist.Tag)
- if err != nil {
- ctx.PropertyErrorf("dist.tag", "%s", err.Error())
- }
- j.distFile = distFiles[0]
- }
+ j.distFiles = j.GenerateTaggedDistFiles(ctx)
}
func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -2101,7 +2103,6 @@
module := &Library{}
module.addHostAndDeviceProperties()
- module.AddProperties(&module.libraryProperties)
module.initModuleAndImport(&module.ModuleBase)
@@ -2651,6 +2652,11 @@
return j.depIsInSameApex(ctx, dep)
}
+func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+ // Do not check for prebuilts against the min_sdk_version of enclosing APEX
+ return nil
+}
+
// Add compile time check for interface implementation
var _ android.IDEInfo = (*Import)(nil)
var _ android.IDECustomizedModuleName = (*Import)(nil)
@@ -2820,6 +2826,11 @@
return j.dexJarFile
}
+func (j *DexImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+ // we don't check prebuilt modules for sdk_version
+ return nil
+}
+
// dex_import imports a `.jar` file containing classes.dex files.
//
// A dex_import module cannot be used as a dependency of a java_* or android_* module, it can only be installed
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 676557e..91869ed 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1905,6 +1905,11 @@
return false
}
+func (module *SdkLibraryImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+ // we don't check prebuilt modules for sdk_version
+ return nil
+}
+
func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) {
return module.commonOutputFiles(tag)
}
@@ -2071,6 +2076,11 @@
// do nothing
}
+func (module *sdkLibraryXml) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+ // sdkLibraryXml doesn't need to be checked separately because java_sdk_library is checked
+ return nil
+}
+
// File path to the runtime implementation library
func (module *sdkLibraryXml) implPath() string {
implName := proptools.String(module.properties.Lib_name)
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 69d0df5..aea899b 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -86,8 +86,11 @@
func (binary *binaryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
ctx.subAndroidMk(ret, binary.baseCompiler)
+ if binary.distFile.Valid() {
+ ret.DistFiles = android.MakeDefaultDistFiles(binary.distFile.Path())
+ }
+
ret.Class = "EXECUTABLES"
- ret.DistFile = binary.distFile
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", binary.unstrippedOutputFile.String())
if binary.coverageOutputZipFile.Valid() {
@@ -127,7 +130,10 @@
ret.Class = "SHARED_LIBRARIES"
}
- ret.DistFile = library.distFile
+ if library.distFile.Valid() {
+ ret.DistFiles = android.MakeDefaultDistFiles(library.distFile.Path())
+ }
+
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
if !library.rlib() {
fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", library.unstrippedOutputFile.String())
@@ -143,7 +149,9 @@
ctx.subAndroidMk(ret, procMacro.baseCompiler)
ret.Class = "PROC_MACRO_LIBRARIES"
- ret.DistFile = procMacro.distFile
+ if procMacro.distFile.Valid() {
+ ret.DistFiles = android.MakeDefaultDistFiles(procMacro.distFile.Path())
+ }
}
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 703aaed..280c22a 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -93,7 +93,6 @@
config.TestProductVariables.NativeCoveragePaths = []string{"*"}
}
- t.Helper()
ctx := CreateTestContext()
ctx.Register(config)
diff --git a/scripts/rustfmt.toml b/scripts/rustfmt.toml
new file mode 100644
index 0000000..617d425
--- /dev/null
+++ b/scripts/rustfmt.toml
@@ -0,0 +1,5 @@
+# Android Format Style
+
+edition = "2018"
+use_small_heuristics = "Max"
+newline_style = "Unix"
diff --git a/scripts/transitive-deps.sh b/scripts/transitive-deps.sh
index c6f8b76..ba36ba4 100755
--- a/scripts/transitive-deps.sh
+++ b/scripts/transitive-deps.sh
@@ -56,7 +56,7 @@
temporary / intermediate files.
-sep=<delim> Use 'delim' as output field separator between notice
checksum and notice filename in notice output.
- e.g. sep='\t'
+ e.g. sep='\\t'
(Default space)
-csv Shorthand for -sep=','
-directories=<f> Output directory names of dependencies to 'f'.
@@ -280,7 +280,7 @@
notices=)
notices_out=$(expr "${flag}" : '^.*=\(.*\)$');;
*)
- die "Unknown flag ${1}";;
+ die "${usage}\n\nUnknown flag ${1}";;
esac
;;
*)
diff --git a/sdk/sdk.go b/sdk/sdk.go
index cb5a605..b9b8199 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -291,7 +291,7 @@
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "FAKE",
OutputFile: s.snapshotFile,
- DistFile: s.snapshotFile,
+ DistFiles: android.MakeDefaultDistFiles(s.snapshotFile.Path()),
Include: "$(BUILD_PHONY_PACKAGE)",
ExtraFooters: []android.AndroidMkExtraFootersFunc{
func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 9f27647..768c8e5 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -310,6 +310,10 @@
}}
}
+func (m *syspropLibrary) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion int) error {
+ return fmt.Errorf("sysprop_library is not supposed to be part of apex modules")
+}
+
// sysprop_library creates schematized APIs from sysprop description files (.sysprop).
// Both Java and C++ modules can link against sysprop_library, and API stability check
// against latest APIs (see build/soong/scripts/freeze-sysprop-api-files.sh)
diff --git a/ui/build/build.go b/ui/build/build.go
index 89c3fad..396f54c 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -243,6 +243,8 @@
// Write combined ninja file
createCombinedBuildNinjaFile(ctx, config)
+ distGzipFile(ctx, config, config.CombinedNinjaFile())
+
if what&RunBuildTests != 0 {
testForDanglingRules(ctx, config)
}
@@ -256,3 +258,47 @@
runNinja(ctx, config)
}
}
+
+// distGzipFile writes a compressed copy of src to the distDir if dist is enabled. Failures
+// are printed but non-fatal.
+func distGzipFile(ctx Context, config Config, src string, subDirs ...string) {
+ if !config.Dist() {
+ return
+ }
+
+ subDir := filepath.Join(subDirs...)
+ destDir := filepath.Join(config.DistDir(), "soong_ui", subDir)
+
+ err := os.MkdirAll(destDir, 0777)
+ if err != nil {
+ ctx.Printf("failed to mkdir %s: %s", destDir, err.Error())
+
+ }
+
+ err = gzipFileToDir(src, destDir)
+ if err != nil {
+ ctx.Printf("failed to dist %s: %s", filepath.Base(src), err.Error())
+ }
+}
+
+// distFile writes a copy of src to the distDir if dist is enabled. Failures are printed but
+// non-fatal.
+func distFile(ctx Context, config Config, src string, subDirs ...string) {
+ if !config.Dist() {
+ return
+ }
+
+ subDir := filepath.Join(subDirs...)
+ destDir := filepath.Join(config.DistDir(), "soong_ui", subDir)
+
+ err := os.MkdirAll(destDir, 0777)
+ if err != nil {
+ ctx.Printf("failed to mkdir %s: %s", destDir, err.Error())
+
+ }
+
+ _, err = copyFile(src, filepath.Join(destDir, filepath.Base(src)))
+ if err != nil {
+ ctx.Printf("failed to dist %s: %s", filepath.Base(src), err.Error())
+ }
+}
diff --git a/ui/build/finder.go b/ui/build/finder.go
index 0f34b5e..6786337 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -86,7 +86,7 @@
os.MkdirAll(dumpDir, 0777)
androidMks := f.FindFirstNamedAt(".", "Android.mk")
- err := dumpListToFile(androidMks, filepath.Join(dumpDir, "Android.mk.list"))
+ err := dumpListToFile(ctx, config, androidMks, filepath.Join(dumpDir, "Android.mk.list"))
if err != nil {
ctx.Fatalf("Could not export module list: %v", err)
}
@@ -94,25 +94,25 @@
androidProductsMks := f.FindNamedAt("device", "AndroidProducts.mk")
androidProductsMks = append(androidProductsMks, f.FindNamedAt("vendor", "AndroidProducts.mk")...)
androidProductsMks = append(androidProductsMks, f.FindNamedAt("product", "AndroidProducts.mk")...)
- err = dumpListToFile(androidProductsMks, filepath.Join(dumpDir, "AndroidProducts.mk.list"))
+ err = dumpListToFile(ctx, config, androidProductsMks, filepath.Join(dumpDir, "AndroidProducts.mk.list"))
if err != nil {
ctx.Fatalf("Could not export product list: %v", err)
}
cleanSpecs := f.FindFirstNamedAt(".", "CleanSpec.mk")
- err = dumpListToFile(cleanSpecs, filepath.Join(dumpDir, "CleanSpec.mk.list"))
+ err = dumpListToFile(ctx, config, cleanSpecs, filepath.Join(dumpDir, "CleanSpec.mk.list"))
if err != nil {
ctx.Fatalf("Could not export module list: %v", err)
}
owners := f.FindNamedAt(".", "OWNERS")
- err = dumpListToFile(owners, filepath.Join(dumpDir, "OWNERS.list"))
+ err = dumpListToFile(ctx, config, owners, filepath.Join(dumpDir, "OWNERS.list"))
if err != nil {
ctx.Fatalf("Could not find OWNERS: %v", err)
}
testMappings := f.FindNamedAt(".", "TEST_MAPPING")
- err = dumpListToFile(testMappings, filepath.Join(dumpDir, "TEST_MAPPING.list"))
+ err = dumpListToFile(ctx, config, testMappings, filepath.Join(dumpDir, "TEST_MAPPING.list"))
if err != nil {
ctx.Fatalf("Could not find TEST_MAPPING: %v", err)
}
@@ -122,18 +122,24 @@
if len(androidBps) == 0 {
ctx.Fatalf("No Android.bp found")
}
- err = dumpListToFile(androidBps, filepath.Join(dumpDir, "Android.bp.list"))
+ err = dumpListToFile(ctx, config, androidBps, filepath.Join(dumpDir, "Android.bp.list"))
if err != nil {
ctx.Fatalf("Could not find modules: %v", err)
}
}
-func dumpListToFile(list []string, filePath string) (err error) {
+func dumpListToFile(ctx Context, config Config, list []string, filePath string) (err error) {
desiredText := strings.Join(list, "\n")
desiredBytes := []byte(desiredText)
actualBytes, readErr := ioutil.ReadFile(filePath)
if readErr != nil || !bytes.Equal(desiredBytes, actualBytes) {
err = ioutil.WriteFile(filePath, desiredBytes, 0777)
+ if err != nil {
+ return err
+ }
}
- return err
+
+ distFile(ctx, config, filePath, "module_paths")
+
+ return nil
}
diff --git a/ui/build/kati.go b/ui/build/kati.go
index 2eb7850..1cd5fea 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -156,6 +156,8 @@
runKati(ctx, config, katiBuildSuffix, args, func(env *Environment) {})
+ distGzipFile(ctx, config, config.KatiBuildNinjaFile())
+
cleanCopyHeaders(ctx, config)
cleanOldInstalledFiles(ctx, config)
}
@@ -251,6 +253,8 @@
env.Set("DIST_DIR", config.DistDir())
}
})
+
+ distGzipFile(ctx, config, config.KatiPackageNinjaFile())
}
func runKatiCleanSpec(ctx Context, config Config) {
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 6a12add..749acb3 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -139,6 +139,13 @@
soongBuildMetrics := loadSoongBuildMetrics(ctx, config)
logSoongBuildMetrics(ctx, soongBuildMetrics)
+ distGzipFile(ctx, config, config.SoongNinjaFile(), "soong")
+
+ if !config.SkipMake() {
+ distGzipFile(ctx, config, config.SoongAndroidMk(), "soong")
+ distGzipFile(ctx, config, config.SoongMakeVarsMk(), "soong")
+ }
+
if ctx.Metrics != nil {
ctx.Metrics.SetSoongBuildMetrics(soongBuildMetrics)
}
diff --git a/ui/build/util.go b/ui/build/util.go
index d44cd6d..d4c3431 100644
--- a/ui/build/util.go
+++ b/ui/build/util.go
@@ -15,6 +15,8 @@
package build
import (
+ "compress/gzip"
+ "fmt"
"io"
"os"
"path/filepath"
@@ -142,3 +144,29 @@
return io.Copy(destination, source)
}
+
+// gzipFileToDir writes a compressed copy of src to destDir with the suffix ".gz".
+func gzipFileToDir(src, destDir string) error {
+ in, err := os.Open(src)
+ if err != nil {
+ return fmt.Errorf("failed to open %s: %s", src, err.Error())
+ }
+ defer in.Close()
+
+ dest := filepath.Join(destDir, filepath.Base(src)+".gz")
+
+ out, err := os.OpenFile(dest, os.O_CREATE|os.O_WRONLY, 0666)
+ if err != nil {
+ return fmt.Errorf("failed to open %s: %s", dest, err.Error())
+ }
+ defer out.Close()
+ gz := gzip.NewWriter(out)
+ defer gz.Close()
+
+ _, err = io.Copy(gz, in)
+ if err != nil {
+ return fmt.Errorf("failed to gzip %s: %s", dest, err.Error())
+ }
+
+ return nil
+}