Merge "Exclude kernel_headers from vendor snapshot"
diff --git a/OWNERS b/OWNERS
index adf2b4c..dbb491d 100644
--- a/OWNERS
+++ b/OWNERS
@@ -11,3 +11,4 @@
per-file tidy.go = srhines@google.com, chh@google.com
per-file lto.go,pgo.go = srhines@google.com, pirama@google.com, yikong@google.com
per-file docs/map_files.md = danalbert@google.com, enh@google.com, jiyong@google.com
+per-file *ndk_api_coverage_parser.py = sophiez@google.com
\ No newline at end of file
diff --git a/android/Android.bp b/android/Android.bp
index 47dbc5d..487372b 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -36,6 +36,7 @@
"package_ctx.go",
"path_properties.go",
"paths.go",
+ "phony.go",
"prebuilt.go",
"proto.go",
"register.go",
diff --git a/android/arch.go b/android/arch.go
index 08c0256..9a54614 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -810,7 +810,7 @@
// Valid multilib values include:
// "both": compile for all Targets supported by the OsClass (generally x86_64 and x86, or arm64 and arm).
// "first": compile for only a single preferred Target supported by the OsClass. This is generally x86_64 or arm64,
-// but may be arm for a 32-bit only build or a build with TARGET_PREFER_32_BIT=true set.
+// but may be arm for a 32-bit only build.
// "32": compile for only a single 32-bit Target supported by the OsClass.
// "64": compile for only a single 64-bit Target supported by the OsClass.
// "common": compile a for a single Target that will work on all Targets suported by the OsClass (for example Java).
@@ -1026,6 +1026,7 @@
"Not_windows",
"Arm_on_x86",
"Arm_on_x86_64",
+ "Native_bridge",
}
for _, os := range OsTypeList {
targets = append(targets, os.Field)
@@ -1413,6 +1414,11 @@
prefix := "target.arm_on_x86_64"
m.appendProperties(ctx, genProps, targetProp, field, prefix)
}
+ if os == Android && m.Target().NativeBridge == NativeBridgeEnabled {
+ field := "Native_bridge"
+ prefix := "target.native_bridge"
+ m.appendProperties(ctx, genProps, targetProp, field, prefix)
+ }
}
}
}
diff --git a/android/arch_test.go b/android/arch_test.go
index b987d56..8525b03 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -383,3 +383,88 @@
})
}
}
+
+func TestArchMutatorNativeBridge(t *testing.T) {
+ bp := `
+ // This module is only enabled for x86.
+ module {
+ name: "foo",
+ }
+
+ // This module is enabled for x86 and arm (via native bridge).
+ module {
+ name: "bar",
+ native_bridge_supported: true,
+ }
+
+ // This module is enabled for arm (native_bridge) only.
+ module {
+ name: "baz",
+ native_bridge_supported: true,
+ enabled: false,
+ target: {
+ native_bridge: {
+ enabled: true,
+ }
+ }
+ }
+ `
+
+ testCases := []struct {
+ name string
+ config func(Config)
+ fooVariants []string
+ barVariants []string
+ bazVariants []string
+ }{
+ {
+ name: "normal",
+ config: nil,
+ fooVariants: []string{"android_x86_64_silvermont", "android_x86_silvermont"},
+ barVariants: []string{"android_x86_64_silvermont", "android_native_bridge_arm64_armv8-a", "android_x86_silvermont", "android_native_bridge_arm_armv7-a-neon"},
+ bazVariants: []string{"android_native_bridge_arm64_armv8-a", "android_native_bridge_arm_armv7-a-neon"},
+ },
+ }
+
+ enabledVariants := func(ctx *TestContext, name string) []string {
+ var ret []string
+ variants := ctx.ModuleVariantsForTests(name)
+ for _, variant := range variants {
+ m := ctx.ModuleForTests(name, variant)
+ if m.Module().Enabled() {
+ ret = append(ret, variant)
+ }
+ }
+ return ret
+ }
+
+ for _, tt := range testCases {
+ t.Run(tt.name, func(t *testing.T) {
+ config := TestArchConfigNativeBridge(buildDir, nil, bp, nil)
+
+ ctx := NewTestArchContext()
+ ctx.RegisterModuleType("module", archTestModuleFactory)
+ ctx.Register(config)
+ if tt.config != nil {
+ tt.config(config)
+ }
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ FailIfErrored(t, errs)
+
+ if g, w := enabledVariants(ctx, "foo"), tt.fooVariants; !reflect.DeepEqual(w, g) {
+ t.Errorf("want foo variants:\n%q\ngot:\n%q\n", w, g)
+ }
+
+ if g, w := enabledVariants(ctx, "bar"), tt.barVariants; !reflect.DeepEqual(w, g) {
+ t.Errorf("want bar variants:\n%q\ngot:\n%q\n", w, g)
+ }
+
+ if g, w := enabledVariants(ctx, "baz"), tt.bazVariants; !reflect.DeepEqual(w, g) {
+ t.Errorf("want qux variants:\n%q\ngot:\n%q\n", w, g)
+ }
+ })
+ }
+}
diff --git a/android/config.go b/android/config.go
index 59118ce..a53f44a 100644
--- a/android/config.go
+++ b/android/config.go
@@ -111,6 +111,10 @@
fs pathtools.FileSystem
mockBpList string
+ // If testAllowNonExistentPaths is true then PathForSource and PathForModuleSrc won't error
+ // in tests when a path doesn't exist.
+ testAllowNonExistentPaths bool
+
OncePer
}
@@ -230,6 +234,10 @@
buildDir: buildDir,
captureBuild: true,
env: envCopy,
+
+ // Set testAllowNonExistentPaths so that test contexts don't need to specify every path
+ // passed to PathForSource or PathForModuleSrc.
+ testAllowNonExistentPaths: true,
}
config.deviceConfig = &deviceConfig{
config: config,
@@ -732,14 +740,6 @@
return Bool(c.productVariables.Eng)
}
-func (c *config) DevicePrefer32BitApps() bool {
- return Bool(c.productVariables.DevicePrefer32BitApps)
-}
-
-func (c *config) DevicePrefer32BitExecutables() bool {
- return Bool(c.productVariables.DevicePrefer32BitExecutables)
-}
-
func (c *config) DevicePrimaryArchType() ArchType {
return c.Targets[Android][0].Arch.ArchType
}
@@ -1029,6 +1029,27 @@
return Bool(c.config.productVariables.SamplingPGO)
}
+// JavaCoverageEnabledForPath returns whether Java code coverage is enabled for
+// path. Coverage is enabled by default when the product variable
+// JavaCoveragePaths is empty. If JavaCoveragePaths is not empty, coverage is
+// enabled for any path which is part of this variable (and not part of the
+// JavaCoverageExcludePaths product variable). Value "*" in JavaCoveragePaths
+// represents any path.
+func (c *deviceConfig) JavaCoverageEnabledForPath(path string) bool {
+ coverage := false
+ if c.config.productVariables.JavaCoveragePaths == nil ||
+ InList("*", c.config.productVariables.JavaCoveragePaths) ||
+ HasAnyPrefix(path, c.config.productVariables.JavaCoveragePaths) {
+ coverage = true
+ }
+ if coverage && c.config.productVariables.JavaCoverageExcludePaths != nil {
+ if HasAnyPrefix(path, c.config.productVariables.JavaCoverageExcludePaths) {
+ coverage = false
+ }
+ }
+ return coverage
+}
+
func (c *config) NativeLineCoverage() bool {
return Bool(c.productVariables.NativeLineCoverage)
}
@@ -1041,15 +1062,20 @@
return Bool(c.config.productVariables.ClangCoverage)
}
-func (c *deviceConfig) CoverageEnabledForPath(path string) bool {
+// NativeCoverageEnabledForPath returns whether (GCOV- or Clang-based) native
+// code coverage is enabled for path. By default, coverage is not enabled for a
+// given path unless it is part of the NativeCoveragePaths product variable (and
+// not part of the NativeCoverageExcludePaths product variable). Value "*" in
+// NativeCoveragePaths represents any path.
+func (c *deviceConfig) NativeCoverageEnabledForPath(path string) bool {
coverage := false
- if c.config.productVariables.CoveragePaths != nil {
- if InList("*", c.config.productVariables.CoveragePaths) || HasAnyPrefix(path, c.config.productVariables.CoveragePaths) {
+ if c.config.productVariables.NativeCoveragePaths != nil {
+ if InList("*", c.config.productVariables.NativeCoveragePaths) || HasAnyPrefix(path, c.config.productVariables.NativeCoveragePaths) {
coverage = true
}
}
- if coverage && c.config.productVariables.CoverageExcludePaths != nil {
- if HasAnyPrefix(path, c.config.productVariables.CoverageExcludePaths) {
+ if coverage && c.config.productVariables.NativeCoverageExcludePaths != nil {
+ if HasAnyPrefix(path, c.config.productVariables.NativeCoverageExcludePaths) {
coverage = false
}
}
@@ -1163,8 +1189,8 @@
return Bool(c.productVariables.EnforceSystemCertificate)
}
-func (c *config) EnforceSystemCertificateWhitelist() []string {
- return c.productVariables.EnforceSystemCertificateWhitelist
+func (c *config) EnforceSystemCertificateAllowList() []string {
+ return c.productVariables.EnforceSystemCertificateAllowList
}
func (c *config) EnforceProductPartitionInterface() bool {
diff --git a/android/makevars.go b/android/makevars.go
index aba4cce..ff7c8e4 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -17,12 +17,11 @@
import (
"bytes"
"fmt"
- "io/ioutil"
- "os"
"strconv"
"strings"
"github.com/google/blueprint"
+ "github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
)
@@ -84,6 +83,29 @@
// builder whenever a file matching the pattern as added or removed, without rerunning if a
// file that does not match the pattern is added to a searched directory.
GlobWithDeps(pattern string, excludes []string) ([]string, error)
+
+ // Phony creates a phony rule in Make, which will allow additional DistForGoal
+ // dependencies to be added to it. Phony can be called on the same name multiple
+ // times to add additional dependencies.
+ Phony(names string, deps ...Path)
+
+ // DistForGoal creates a rule to copy one or more Paths to the artifacts
+ // directory on the build server when the specified goal is built.
+ DistForGoal(goal string, paths ...Path)
+
+ // DistForGoalWithFilename creates a rule to copy a Path to the artifacts
+ // directory on the build server with the given filename when the specified
+ // goal is built.
+ DistForGoalWithFilename(goal string, path Path, filename string)
+
+ // DistForGoals creates a rule to copy one or more Paths to the artifacts
+ // directory on the build server when any of the specified goals are built.
+ DistForGoals(goals []string, paths ...Path)
+
+ // DistForGoalsWithFilename creates a rule to copy a Path to the artifacts
+ // directory on the build server with the given filename when any of the
+ // specified goals are built.
+ DistForGoalsWithFilename(goals []string, path Path, filename string)
}
var _ PathContext = MakeVarsContext(nil)
@@ -130,9 +152,11 @@
type makeVarsContext struct {
SingletonContext
- config Config
- pctx PackageContext
- vars []makeVarsVariable
+ config Config
+ pctx PackageContext
+ vars []makeVarsVariable
+ phonies []phony
+ dists []dist
}
var _ MakeVarsContext = &makeVarsContext{}
@@ -144,6 +168,16 @@
strict bool
}
+type phony struct {
+ name string
+ deps []string
+}
+
+type dist struct {
+ goals []string
+ paths []string
+}
+
func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
if !ctx.Config().EmbeddedInMake() {
return
@@ -152,11 +186,16 @@
outFile := absolutePath(PathForOutput(ctx,
"make_vars"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
+ lateOutFile := absolutePath(PathForOutput(ctx,
+ "late"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
+
if ctx.Failed() {
return
}
- vars := []makeVarsVariable{}
+ var vars []makeVarsVariable
+ var dists []dist
+ var phonies []phony
for _, provider := range makeVarsProviders {
mctx := &makeVarsContext{
SingletonContext: ctx,
@@ -166,6 +205,8 @@
provider.call(mctx)
vars = append(vars, mctx.vars...)
+ phonies = append(phonies, mctx.phonies...)
+ dists = append(dists, mctx.dists...)
}
if ctx.Failed() {
@@ -174,17 +215,16 @@
outBytes := s.writeVars(vars)
- if _, err := os.Stat(absolutePath(outFile)); err == nil {
- if data, err := ioutil.ReadFile(absolutePath(outFile)); err == nil {
- if bytes.Equal(data, outBytes) {
- return
- }
- }
- }
-
- if err := ioutil.WriteFile(absolutePath(outFile), outBytes, 0666); err != nil {
+ if err := pathtools.WriteFileIfChanged(outFile, outBytes, 0666); err != nil {
ctx.Errorf(err.Error())
}
+
+ lateOutBytes := s.writeLate(phonies, dists)
+
+ if err := pathtools.WriteFileIfChanged(lateOutFile, lateOutBytes, 0666); err != nil {
+ ctx.Errorf(err.Error())
+ }
+
}
func (s *makeVarsSingleton) writeVars(vars []makeVarsVariable) []byte {
@@ -263,6 +303,33 @@
fmt.Fprintln(buf, "\nsoong-compare-var :=")
+ fmt.Fprintln(buf)
+
+ return buf.Bytes()
+}
+
+func (s *makeVarsSingleton) writeLate(phonies []phony, dists []dist) []byte {
+ buf := &bytes.Buffer{}
+
+ fmt.Fprint(buf, `# Autogenerated file
+
+# Values written by Soong read after parsing all Android.mk files.
+
+
+`)
+
+ for _, phony := range phonies {
+ fmt.Fprintf(buf, ".PHONY: %s\n", phony.name)
+ fmt.Fprintf(buf, "%s: %s\n", phony.name, strings.Join(phony.deps, "\\\n "))
+ }
+
+ fmt.Fprintln(buf)
+
+ for _, dist := range dists {
+ fmt.Fprintf(buf, "$(call dist-for-goals,%s,%s)\n",
+ strings.Join(dist.goals, " "), strings.Join(dist.paths, " "))
+ }
+
return buf.Bytes()
}
@@ -299,6 +366,17 @@
c.addVariableRaw(name, value, strict, sort)
}
+func (c *makeVarsContext) addPhony(name string, deps []string) {
+ c.phonies = append(c.phonies, phony{name, deps})
+}
+
+func (c *makeVarsContext) addDist(goals []string, paths []string) {
+ c.dists = append(c.dists, dist{
+ goals: goals,
+ paths: paths,
+ })
+}
+
func (c *makeVarsContext) Strict(name, ninjaStr string) {
c.addVariable(name, ninjaStr, true, false)
}
@@ -318,3 +396,23 @@
func (c *makeVarsContext) CheckRaw(name, value string) {
c.addVariableRaw(name, value, false, false)
}
+
+func (c *makeVarsContext) Phony(name string, deps ...Path) {
+ c.addPhony(name, Paths(deps).Strings())
+}
+
+func (c *makeVarsContext) DistForGoal(goal string, paths ...Path) {
+ c.DistForGoals([]string{goal}, paths...)
+}
+
+func (c *makeVarsContext) DistForGoalWithFilename(goal string, path Path, filename string) {
+ c.DistForGoalsWithFilename([]string{goal}, path, filename)
+}
+
+func (c *makeVarsContext) DistForGoals(goals []string, paths ...Path) {
+ c.addDist(goals, Paths(paths).Strings())
+}
+
+func (c *makeVarsContext) DistForGoalsWithFilename(goals []string, path Path, filename string) {
+ c.addDist(goals, []string{path.String() + ":" + filename})
+}
diff --git a/android/module.go b/android/module.go
index 82321f4..a488c0d 100644
--- a/android/module.go
+++ b/android/module.go
@@ -207,6 +207,10 @@
// Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
// and performs more verification.
Build(pctx PackageContext, params BuildParams)
+ // Phony creates a Make-style phony rule, a rule with no commands that can depend on other
+ // phony rules or real files. Phony can be called on the same name multiple times to add
+ // additional dependencies.
+ Phony(phony string, deps ...Path)
PrimaryModule() Module
FinalModule() Module
@@ -722,6 +726,7 @@
installFiles InstallPaths
checkbuildFiles Paths
noticeFiles Paths
+ phonies map[string]Paths
// Used by buildTargetSingleton to create checkbuild and per-directory build targets
// Only set on the final variant of each module
@@ -1093,26 +1098,17 @@
}
if len(allInstalledFiles) > 0 {
- name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-install")
- ctx.Build(pctx, BuildParams{
- Rule: blueprint.Phony,
- Output: name,
- Implicits: allInstalledFiles.Paths(),
- Default: !ctx.Config().EmbeddedInMake(),
- })
- deps = append(deps, name)
- m.installTarget = name
+ name := namespacePrefix + ctx.ModuleName() + "-install"
+ ctx.Phony(name, allInstalledFiles.Paths()...)
+ m.installTarget = PathForPhony(ctx, name)
+ deps = append(deps, m.installTarget)
}
if len(allCheckbuildFiles) > 0 {
- name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-checkbuild")
- ctx.Build(pctx, BuildParams{
- Rule: blueprint.Phony,
- Output: name,
- Implicits: allCheckbuildFiles,
- })
- deps = append(deps, name)
- m.checkbuildTarget = name
+ name := namespacePrefix + ctx.ModuleName() + "-checkbuild"
+ ctx.Phony(name, allCheckbuildFiles...)
+ m.checkbuildTarget = PathForPhony(ctx, name)
+ deps = append(deps, m.checkbuildTarget)
}
if len(deps) > 0 {
@@ -1121,12 +1117,7 @@
suffix = "-soong"
}
- name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+suffix)
- ctx.Build(pctx, BuildParams{
- Rule: blueprint.Phony,
- Outputs: []WritablePath{name},
- Implicits: deps,
- })
+ ctx.Phony(namespacePrefix+ctx.ModuleName()+suffix, deps...)
m.blueprintDir = ctx.ModuleDir()
}
@@ -1313,6 +1304,9 @@
m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
+ for k, v := range ctx.phonies {
+ m.phonies[k] = append(m.phonies[k], v...)
+ }
} else if ctx.Config().AllowMissingDependencies() {
// If the module is not enabled it will not create any build rules, nothing will call
// ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled
@@ -1460,6 +1454,7 @@
installFiles InstallPaths
checkbuildFiles Paths
module Module
+ phonies map[string]Paths
// For tests
buildParams []BuildParams
@@ -1574,6 +1569,11 @@
m.bp.Build(pctx.PackageContext, convertBuildParams(params))
}
+
+func (m *moduleContext) Phony(name string, deps ...Path) {
+ addPhony(m.config, name, deps...)
+}
+
func (m *moduleContext) GetMissingDependencies() []string {
var missingDeps []string
missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...)
@@ -2233,9 +2233,8 @@
func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
var checkbuildDeps Paths
- mmTarget := func(dir string) WritablePath {
- return PathForPhony(ctx,
- "MODULES-IN-"+strings.Replace(filepath.Clean(dir), "/", "-", -1))
+ mmTarget := func(dir string) string {
+ return "MODULES-IN-" + strings.Replace(filepath.Clean(dir), "/", "-", -1)
}
modulesInDir := make(map[string]Paths)
@@ -2261,11 +2260,7 @@
}
// Create a top-level checkbuild target that depends on all modules
- ctx.Build(pctx, BuildParams{
- Rule: blueprint.Phony,
- Output: PathForPhony(ctx, "checkbuild"+suffix),
- Implicits: checkbuildDeps,
- })
+ ctx.Phony("checkbuild"+suffix, checkbuildDeps...)
// Make will generate the MODULES-IN-* targets
if ctx.Config().EmbeddedInMake() {
@@ -2289,7 +2284,7 @@
for _, dir := range dirs {
p := parentDir(dir)
if p != "." && p != "/" {
- modulesInDir[p] = append(modulesInDir[p], mmTarget(dir))
+ modulesInDir[p] = append(modulesInDir[p], PathForPhony(ctx, mmTarget(dir)))
}
}
@@ -2297,14 +2292,7 @@
// depends on the MODULES-IN-* targets of all of its subdirectories that contain Android.bp
// files.
for _, dir := range dirs {
- ctx.Build(pctx, BuildParams{
- Rule: blueprint.Phony,
- Output: mmTarget(dir),
- Implicits: modulesInDir[dir],
- // HACK: checkbuild should be an optional build, but force it
- // enabled for now in standalone builds
- Default: !ctx.Config().EmbeddedInMake(),
- })
+ ctx.Phony(mmTarget(dir), modulesInDir[dir]...)
}
// Create (host|host-cross|target)-<OS> phony rules to build a reduced checkbuild.
@@ -2331,23 +2319,15 @@
continue
}
- name := PathForPhony(ctx, className+"-"+os.Name)
- osClass[className] = append(osClass[className], name)
+ name := className + "-" + os.Name
+ osClass[className] = append(osClass[className], PathForPhony(ctx, name))
- ctx.Build(pctx, BuildParams{
- Rule: blueprint.Phony,
- Output: name,
- Implicits: deps,
- })
+ ctx.Phony(name, deps...)
}
// Wrap those into host|host-cross|target phony rules
for _, class := range SortedStringKeys(osClass) {
- ctx.Build(pctx, BuildParams{
- Rule: blueprint.Phony,
- Output: PathForPhony(ctx, class),
- Implicits: osClass[class],
- })
+ ctx.Phony(class, osClass[class]...)
}
}
diff --git a/android/neverallow.go b/android/neverallow.go
index be3f712..26e42e6 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -166,7 +166,7 @@
}
func createJavaDeviceForHostRules() []Rule {
- javaDeviceForHostProjectsWhitelist := []string{
+ javaDeviceForHostProjectsAllowedList := []string{
"external/guava",
"external/robolectric-shadows",
"framework/layoutlib",
@@ -174,14 +174,14 @@
return []Rule{
NeverAllow().
- NotIn(javaDeviceForHostProjectsWhitelist...).
+ NotIn(javaDeviceForHostProjectsAllowedList...).
ModuleType("java_device_for_host", "java_host_for_device").
- Because("java_device_for_host can only be used in whitelisted projects"),
+ Because("java_device_for_host can only be used in allowed projects"),
}
}
func createCcSdkVariantRules() []Rule {
- sdkVersionOnlyWhitelist := []string{
+ sdkVersionOnlyAllowedList := []string{
// derive_sdk_prefer32 has stem: "derive_sdk" which conflicts with the derive_sdk.
// This sometimes works because the APEX modules that contain derive_sdk and
// derive_sdk_prefer32 suppress the platform installation rules, but fails when
@@ -193,7 +193,7 @@
"tools/test/graphicsbenchmark/functional_tests/java",
}
- platformVariantPropertiesWhitelist := []string{
+ platformVariantPropertiesAllowedList := []string{
// android_native_app_glue and libRSSupport use native_window.h but target old
// sdk versions (minimum and 9 respectively) where libnativewindow didn't exist,
// so they can't add libnativewindow to shared_libs to get the header directory
@@ -205,13 +205,13 @@
return []Rule{
NeverAllow().
- NotIn(sdkVersionOnlyWhitelist...).
+ NotIn(sdkVersionOnlyAllowedList...).
WithMatcher("sdk_variant_only", isSetMatcherInstance).
- Because("sdk_variant_only can only be used in whitelisted projects"),
+ Because("sdk_variant_only can only be used in allowed projects"),
NeverAllow().
- NotIn(platformVariantPropertiesWhitelist...).
+ NotIn(platformVariantPropertiesAllowedList...).
WithMatcher("platform.shared_libs", isSetMatcherInstance).
- Because("platform variant properties can only be used in whitelisted projects"),
+ Because("platform variant properties can only be used in allowed projects"),
}
}
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 85c8c59..45d36a6 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -212,7 +212,7 @@
}`),
},
expectedErrors: []string{
- "java_device_for_host can only be used in whitelisted projects",
+ "java_device_for_host can only be used in allowed projects",
},
},
// Libcore rule tests
@@ -261,46 +261,46 @@
},
// CC sdk rule tests
{
- name: `"sdk_variant_only" outside whitelist`,
+ name: `"sdk_variant_only" outside allowed list`,
fs: map[string][]byte{
"Android.bp": []byte(`
cc_library {
- name: "outside_whitelist",
+ name: "outside_allowed_list",
sdk_version: "current",
sdk_variant_only: true,
}`),
},
expectedErrors: []string{
- `module "outside_whitelist": violates neverallow`,
+ `module "outside_allowed_list": violates neverallow`,
},
},
{
- name: `"sdk_variant_only: false" outside whitelist`,
+ name: `"sdk_variant_only: false" outside allowed list`,
fs: map[string][]byte{
"Android.bp": []byte(`
cc_library {
- name: "outside_whitelist",
+ name: "outside_allowed_list",
sdk_version: "current",
sdk_variant_only: false,
}`),
},
expectedErrors: []string{
- `module "outside_whitelist": violates neverallow`,
+ `module "outside_allowed_list": violates neverallow`,
},
},
{
- name: `"platform" outside whitelist`,
+ name: `"platform" outside allowed list`,
fs: map[string][]byte{
"Android.bp": []byte(`
cc_library {
- name: "outside_whitelist",
+ name: "outside_allowed_list",
platform: {
shared_libs: ["libfoo"],
},
}`),
},
expectedErrors: []string{
- `module "outside_whitelist": violates neverallow`,
+ `module "outside_allowed_list": violates neverallow`,
},
},
{
diff --git a/android/override_module.go b/android/override_module.go
index 9f5127d..7e58890 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -208,7 +208,21 @@
// next phase.
func overrideModuleDepsMutator(ctx BottomUpMutatorContext) {
if module, ok := ctx.Module().(OverrideModule); ok {
- ctx.AddDependency(ctx.Module(), overrideBaseDepTag, *module.getOverrideModuleProperties().Base)
+ // Skip this overriding module if there's a prebuilt module that overrides it with prefer flag.
+ overriddenByPrebuilt := false
+ ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(dep Module) {
+ prebuilt, ok := dep.(PrebuiltInterface)
+ if !ok {
+ panic("PrebuiltDepTag leads to a non-prebuilt module " + dep.Name())
+ }
+ if prebuilt.Prebuilt().UsePrebuilt() {
+ overriddenByPrebuilt = true
+ return
+ }
+ })
+ if !overriddenByPrebuilt {
+ ctx.AddDependency(ctx.Module(), overrideBaseDepTag, *module.getOverrideModuleProperties().Base)
+ }
}
}
diff --git a/android/paths.go b/android/paths.go
index 3ad27ac..bed6f3f 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -405,7 +405,7 @@
p := pathForModuleSrc(ctx, s)
if exists, _, err := ctx.Config().fs.Exists(p.String()); err != nil {
reportPathErrorf(ctx, "%s: %s", p, err.Error())
- } else if !exists {
+ } else if !exists && !ctx.Config().testAllowNonExistentPaths {
reportPathErrorf(ctx, "module source path %q does not exist", p)
}
@@ -798,7 +798,7 @@
}
} else if exists, _, err := ctx.Config().fs.Exists(path.String()); err != nil {
reportPathErrorf(ctx, "%s: %s", path, err.Error())
- } else if !exists {
+ } else if !exists && !ctx.Config().testAllowNonExistentPaths {
reportPathErrorf(ctx, "source path %q does not exist", path)
}
return path
diff --git a/android/phony.go b/android/phony.go
new file mode 100644
index 0000000..f8e5a44
--- /dev/null
+++ b/android/phony.go
@@ -0,0 +1,75 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+ "sync"
+
+ "github.com/google/blueprint"
+)
+
+var phonyMapOnceKey = NewOnceKey("phony")
+
+type phonyMap map[string]Paths
+
+var phonyMapLock sync.Mutex
+
+func getPhonyMap(config Config) phonyMap {
+ return config.Once(phonyMapOnceKey, func() interface{} {
+ return make(phonyMap)
+ }).(phonyMap)
+}
+
+func addPhony(config Config, name string, deps ...Path) {
+ phonyMap := getPhonyMap(config)
+ phonyMapLock.Lock()
+ defer phonyMapLock.Unlock()
+ phonyMap[name] = append(phonyMap[name], deps...)
+}
+
+type phonySingleton struct {
+ phonyMap phonyMap
+ phonyList []string
+}
+
+var _ SingletonMakeVarsProvider = (*phonySingleton)(nil)
+
+func (p *phonySingleton) GenerateBuildActions(ctx SingletonContext) {
+ p.phonyMap = getPhonyMap(ctx.Config())
+ p.phonyList = SortedStringKeys(p.phonyMap)
+ for _, phony := range p.phonyList {
+ p.phonyMap[phony] = SortedUniquePaths(p.phonyMap[phony])
+ }
+
+ if !ctx.Config().EmbeddedInMake() {
+ for _, phony := range p.phonyList {
+ ctx.Build(pctx, BuildParams{
+ Rule: blueprint.Phony,
+ Outputs: []WritablePath{PathForPhony(ctx, phony)},
+ Implicits: p.phonyMap[phony],
+ })
+ }
+ }
+}
+
+func (p phonySingleton) MakeVars(ctx MakeVarsContext) {
+ for _, phony := range p.phonyList {
+ ctx.Phony(phony, p.phonyMap[phony]...)
+ }
+}
+
+func phonySingletonFactory() Singleton {
+ return &phonySingleton{}
+}
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index b568f78..8029b85 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -155,6 +155,44 @@
}`,
prebuilt: []OsClass{Host},
},
+ {
+ name: "prebuilt override not preferred",
+ modules: `
+ source {
+ name: "baz",
+ }
+
+ override_source {
+ name: "bar",
+ base: "baz",
+ }
+
+ prebuilt {
+ name: "bar",
+ prefer: false,
+ srcs: ["prebuilt_file"],
+ }`,
+ prebuilt: nil,
+ },
+ {
+ name: "prebuilt override preferred",
+ modules: `
+ source {
+ name: "baz",
+ }
+
+ override_source {
+ name: "bar",
+ base: "baz",
+ }
+
+ prebuilt {
+ name: "bar",
+ prefer: true,
+ srcs: ["prebuilt_file"],
+ }`,
+ prebuilt: []OsClass{Device, Host},
+ },
}
func TestPrebuilts(t *testing.T) {
@@ -256,8 +294,10 @@
func registerTestPrebuiltBuildComponents(ctx RegistrationContext) {
ctx.RegisterModuleType("prebuilt", newPrebuiltModule)
ctx.RegisterModuleType("source", newSourceModule)
+ ctx.RegisterModuleType("override_source", newOverrideSourceModule)
RegisterPrebuiltMutators(ctx)
+ ctx.PostDepsMutators(RegisterOverridePostDepsMutators)
}
type prebuiltModule struct {
@@ -300,11 +340,15 @@
}
}
+type sourceModuleProperties struct {
+ Deps []string `android:"path,arch_variant"`
+}
+
type sourceModule struct {
ModuleBase
- properties struct {
- Deps []string `android:"path,arch_variant"`
- }
+ OverridableModuleBase
+
+ properties sourceModuleProperties
dependsOnSourceModule, dependsOnPrebuiltModule bool
deps Paths
src Path
@@ -314,10 +358,11 @@
m := &sourceModule{}
m.AddProperties(&m.properties)
InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon)
+ InitOverridableModule(m, nil)
return m
}
-func (s *sourceModule) DepsMutator(ctx BottomUpMutatorContext) {
+func (s *sourceModule) OverridablePropertiesDepsMutator(ctx BottomUpMutatorContext) {
// s.properties.Deps are annotated with android:path, so they are
// automatically added to the dependency by pathDeps mutator
}
@@ -330,3 +375,20 @@
func (s *sourceModule) Srcs() Paths {
return Paths{s.src}
}
+
+type overrideSourceModule struct {
+ ModuleBase
+ OverrideModuleBase
+}
+
+func (o *overrideSourceModule) GenerateAndroidBuildActions(_ ModuleContext) {
+}
+
+func newOverrideSourceModule() Module {
+ m := &overrideSourceModule{}
+ m.AddProperties(&sourceModuleProperties{})
+
+ InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon)
+ InitOverrideModule(m)
+ return m
+}
diff --git a/android/register.go b/android/register.go
index ccfe01e..036a811 100644
--- a/android/register.go
+++ b/android/register.go
@@ -104,6 +104,9 @@
registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps)
+ // Register phony just before makevars so it can write out its phony rules as Make rules
+ ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(phonySingletonFactory))
+
// Register makevars after other singletons so they can export values through makevars
ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(makeVarsSingletonFunc))
diff --git a/android/singleton.go b/android/singleton.go
index 568398c..2c51c6c 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -36,6 +36,12 @@
Variable(pctx PackageContext, name, value string)
Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
Build(pctx PackageContext, params BuildParams)
+
+ // Phony creates a Make-style phony rule, a rule with no commands that can depend on other
+ // phony rules or real files. Phony can be called on the same name multiple times to add
+ // additional dependencies.
+ Phony(name string, deps ...Path)
+
RequireNinjaVersion(major, minor, micro int)
// SetNinjaBuildDir sets the value of the top-level "builddir" Ninja variable
@@ -156,6 +162,10 @@
}
+func (s *singletonContextAdaptor) Phony(name string, deps ...Path) {
+ addPhony(s.Config(), name, deps...)
+}
+
func (s *singletonContextAdaptor) SetNinjaBuildDir(pctx PackageContext, value string) {
s.SingletonContext.SetNinjaBuildDir(pctx.PackageContext, value)
}
diff --git a/android/variable.go b/android/variable.go
index 3c08405..863fe5a 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -266,15 +266,14 @@
SamplingPGO *bool `json:",omitempty"`
- NativeLineCoverage *bool `json:",omitempty"`
- Native_coverage *bool `json:",omitempty"`
- ClangCoverage *bool `json:",omitempty"`
- CoveragePaths []string `json:",omitempty"`
- CoverageExcludePaths []string `json:",omitempty"`
+ JavaCoveragePaths []string `json:",omitempty"`
+ JavaCoverageExcludePaths []string `json:",omitempty"`
- DevicePrefer32BitApps *bool `json:",omitempty"`
- DevicePrefer32BitExecutables *bool `json:",omitempty"`
- HostPrefer32BitExecutables *bool `json:",omitempty"`
+ NativeLineCoverage *bool `json:",omitempty"`
+ Native_coverage *bool `json:",omitempty"`
+ ClangCoverage *bool `json:",omitempty"`
+ NativeCoveragePaths []string `json:",omitempty"`
+ NativeCoverageExcludePaths []string `json:",omitempty"`
SanitizeHost []string `json:",omitempty"`
SanitizeDevice []string `json:",omitempty"`
@@ -323,7 +322,7 @@
PackageNameOverrides []string `json:",omitempty"`
EnforceSystemCertificate *bool `json:",omitempty"`
- EnforceSystemCertificateWhitelist []string `json:",omitempty"`
+ EnforceSystemCertificateAllowList []string `json:",omitempty"`
ProductHiddenAPIStubs []string `json:",omitempty"`
ProductHiddenAPIStubsSystem []string `json:",omitempty"`
diff --git a/android/writedocs.go b/android/writedocs.go
index 7262ad8..9e43e80 100644
--- a/android/writedocs.go
+++ b/android/writedocs.go
@@ -69,9 +69,5 @@
})
// Add a phony target for building the documentation
- ctx.Build(pctx, BuildParams{
- Rule: blueprint.Phony,
- Output: PathForPhony(ctx, "soong_docs"),
- Input: docsFile,
- })
+ ctx.Phony("soong_docs", docsFile)
}
diff --git a/androidmk/androidmk/androidmk.go b/androidmk/androidmk/androidmk.go
index 9d0c3ac..4aadbe8 100644
--- a/androidmk/androidmk/androidmk.go
+++ b/androidmk/androidmk/androidmk.go
@@ -124,6 +124,7 @@
var conds []*conditional
var assignmentCond *conditional
+ var tree *bpparser.File
for _, node := range nodes {
file.setMkPos(p.Unpack(node.Pos()), p.Unpack(node.End()))
@@ -200,24 +201,27 @@
}
}
- tree := &bpparser.File{
+ tree = &bpparser.File{
Defs: file.defs,
Comments: file.comments,
}
// check for common supported but undesirable structures and clean them up
fixer := bpfix.NewFixer(tree)
- tree, err := fixer.Fix(bpfix.NewFixRequest().AddAll())
- if err != nil {
- return "", []error{err}
+ fixedTree, fixerErr := fixer.Fix(bpfix.NewFixRequest().AddAll())
+ if fixerErr != nil {
+ errs = append(errs, fixerErr)
+ } else {
+ tree = fixedTree
}
out, err := bpparser.Print(tree)
if err != nil {
- return "", []error{err}
+ errs = append(errs, err)
+ return "", errs
}
- return string(out), nil
+ return string(out), errs
}
func handleAssignment(file *bpFile, assignment *mkparser.Assignment, c *conditional) {
diff --git a/androidmk/cmd/androidmk.go b/androidmk/cmd/androidmk.go
index 00488eb..d2f4324 100644
--- a/androidmk/cmd/androidmk.go
+++ b/androidmk/cmd/androidmk.go
@@ -45,12 +45,13 @@
}
output, errs := androidmk.ConvertFile(os.Args[1], bytes.NewBuffer(b))
+ if len(output) > 0 {
+ fmt.Print(output)
+ }
if len(errs) > 0 {
for _, err := range errs {
fmt.Fprintln(os.Stderr, "ERROR: ", err)
}
os.Exit(1)
}
-
- fmt.Print(output)
}
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 1b3a4ba..774b62d 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -180,13 +180,17 @@
}
switch fi.class {
case javaSharedLib:
- javaModule := fi.module.(java.Dependency)
// soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar Therefore
// we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
// we will have foo.jar.jar
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.Stem(), ".jar"))
- fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", javaModule.ImplementationAndResourcesJars()[0].String())
- fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", javaModule.HeaderJars()[0].String())
+ if javaModule, ok := fi.module.(java.Dependency); ok {
+ fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", javaModule.ImplementationAndResourcesJars()[0].String())
+ fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", javaModule.HeaderJars()[0].String())
+ } else {
+ fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", fi.builtFile.String())
+ fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", fi.builtFile.String())
+ }
fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", fi.builtFile.String())
fmt.Fprintln(w, "LOCAL_DEX_PREOPT := false")
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk")
diff --git a/apex/apex.go b/apex/apex.go
index 2f7b2e5..2e4a328 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -64,13 +64,14 @@
usesTag = dependencyTag{name: "uses"}
androidAppTag = dependencyTag{name: "androidApp", payload: true}
rroTag = dependencyTag{name: "rro", payload: true}
- apexAvailWl = makeApexAvailableWhitelist()
- inverseApexAvailWl = invertApexWhiteList(apexAvailWl)
+ apexAvailBaseline = makeApexAvailableBaseline()
+
+ inverseApexAvailBaseline = invertApexBaseline(apexAvailBaseline)
)
// Transform the map of apex -> modules to module -> apexes.
-func invertApexWhiteList(m map[string][]string) map[string][]string {
+func invertApexBaseline(m map[string][]string) map[string][]string {
r := make(map[string][]string)
for apex, modules := range m {
for _, module := range modules {
@@ -80,16 +81,16 @@
return r
}
-// Retrieve the while list of apexes to which the supplied module belongs.
-func WhitelistedApexAvailable(moduleName string) []string {
- return inverseApexAvailWl[normalizeModuleName(moduleName)]
+// Retrieve the baseline of apexes to which the supplied module belongs.
+func BaselineApexAvailable(moduleName string) []string {
+ return inverseApexAvailBaseline[normalizeModuleName(moduleName)]
}
// This is a map from apex to modules, which overrides the
// apex_available setting for that particular module to make
// it available for the apex regardless of its setting.
// TODO(b/147364041): remove this
-func makeApexAvailableWhitelist() map[string][]string {
+func makeApexAvailableBaseline() map[string][]string {
// The "Module separator"s below are employed to minimize merge conflicts.
m := make(map[string][]string)
//
@@ -177,12 +178,6 @@
//
// Module separator
//
- m["com.android.conscrypt"] = []string{
- "libnativehelper_header_only",
- }
- //
- // Module separator
- //
m["com.android.neuralnetworks"] = []string{
"android.hardware.neuralnetworks@1.0",
"android.hardware.neuralnetworks@1.1",
@@ -478,7 +473,6 @@
"libbase_ndk",
"libfuse",
"libfuse_jni",
- "libnativehelper_header_only",
}
//
// Module separator
@@ -560,7 +554,6 @@
"ipmemorystore-aidl-interfaces-java",
"libcgrouprc",
"libcgrouprc_format",
- "libnativehelper_compat_libc++",
"libtetherutilsjni",
"libvndksupport",
"net-utils-framework-common",
@@ -871,17 +864,17 @@
}
var (
- useVendorWhitelistKey = android.NewOnceKey("useVendorWhitelist")
+ useVendorAllowListKey = android.NewOnceKey("useVendorAllowList")
)
-// useVendorWhitelist returns the list of APEXes which are allowed to use_vendor.
+// useVendorAllowList returns the list of APEXes which are allowed to use_vendor.
// When use_vendor is used, native modules are built with __ANDROID_VNDK__ and __ANDROID_APEX__,
// which may cause compatibility issues. (e.g. libbinder)
// Even though libbinder restricts its availability via 'apex_available' property and relies on
// yet another macro __ANDROID_APEX_<NAME>__, we restrict usage of "use_vendor:" from other APEX modules
// to avoid similar problems.
-func useVendorWhitelist(config android.Config) []string {
- return config.Once(useVendorWhitelistKey, func() interface{} {
+func useVendorAllowList(config android.Config) []string {
+ return config.Once(useVendorAllowListKey, func() interface{} {
return []string{
// swcodec uses "vendor" variants for smaller size
"com.android.media.swcodec",
@@ -890,11 +883,11 @@
}).([]string)
}
-// setUseVendorWhitelistForTest overrides useVendorWhitelist and must be
-// called before the first call to useVendorWhitelist()
-func setUseVendorWhitelistForTest(config android.Config, whitelist []string) {
- config.Once(useVendorWhitelistKey, func() interface{} {
- return whitelist
+// setUseVendorAllowListForTest overrides useVendorAllowList and must be
+// called before the first call to useVendorAllowList()
+func setUseVendorAllowListForTest(config android.Config, allowList []string) {
+ config.Once(useVendorAllowListKey, func() interface{} {
+ return allowList
})
}
@@ -992,7 +985,7 @@
// List of providing APEXes' names so that this APEX can depend on provided shared libraries.
Uses []string
- // A txt file containing list of files that are whitelisted to be included in this APEX.
+ // A txt file containing list of files that are allowed to be included in this APEX.
Whitelisted_files *string
// package format of this apex variant; could be non-flattened, flattened, or zip.
@@ -1332,7 +1325,7 @@
}
func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
- if proptools.Bool(a.properties.Use_vendor) && !android.InList(a.Name(), useVendorWhitelist(ctx.Config())) {
+ if proptools.Bool(a.properties.Use_vendor) && !android.InList(a.Name(), useVendorAllowList(ctx.Config())) {
ctx.PropertyErrorf("use_vendor", "not allowed to set use_vendor: true")
}
@@ -1804,7 +1797,7 @@
return false
}
- if to.AvailableFor(apexName) || whitelistedApexAvailable(apexName, toName) {
+ if to.AvailableFor(apexName) || baselineApexAvailable(apexName, toName) {
return true
}
ctx.ModuleErrorf("%q requires %q that is not available for the APEX. Dependency path:%s", fromName, toName, ctx.GetPathString(true))
@@ -1953,8 +1946,10 @@
fi := apexFileForNativeLibrary(ctx, c, handleSpecialLibs)
fi.isJniLib = isJniLib
filesInfo = append(filesInfo, fi)
- // bootstrap bionic libs are treated as provided by system
- if c.HasStubsVariants() && !cc.InstallToBootstrap(c.BaseModuleName(), ctx.Config()) {
+ // Collect the list of stub-providing libs except:
+ // - VNDK libs are only for vendors
+ // - bootstrap bionic libs are treated as provided by system
+ if c.HasStubsVariants() && !a.vndkApex && !cc.InstallToBootstrap(c.BaseModuleName(), ctx.Config()) {
provideNativeLibs = append(provideNativeLibs, fi.Stem())
}
return true // track transitive dependencies
@@ -1980,7 +1975,7 @@
}
case javaLibTag:
switch child.(type) {
- case *java.Library, *java.SdkLibrary, *java.DexImport:
+ case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport:
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)
@@ -2243,16 +2238,16 @@
})
}
-func whitelistedApexAvailable(apex, moduleName string) bool {
+func baselineApexAvailable(apex, moduleName string) bool {
key := apex
moduleName = normalizeModuleName(moduleName)
- if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
+ if val, ok := apexAvailBaseline[key]; ok && android.InList(moduleName, val) {
return true
}
key = android.AvailableToAnyApex
- if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
+ if val, ok := apexAvailBaseline[key]; ok && android.InList(moduleName, val) {
return true
}
@@ -2280,9 +2275,6 @@
module.AddProperties(&module.properties)
module.AddProperties(&module.targetProperties)
module.AddProperties(&module.overridableProperties)
- module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
- return class == android.Device && ctx.Config().DevicePrefer32BitExecutables()
- })
android.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
android.InitSdkAwareModule(module)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index d6a5d09..a7a7765 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -66,7 +66,7 @@
func testApex(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
t.Helper()
ctx, config := testApexContext(t, bp, handlers...)
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ _, errs := ctx.ParseBlueprintsFiles(".")
android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
android.FailIfErrored(t, errs)
@@ -217,6 +217,11 @@
}
ctx := android.NewTestArchContext()
+
+ // from android package
+ android.RegisterPackageBuildComponents(ctx)
+ ctx.PreArchMutators(android.RegisterVisibilityRuleChecker)
+
ctx.RegisterModuleType("apex", BundleFactory)
ctx.RegisterModuleType("apex_test", testApexBundleFactory)
ctx.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
@@ -230,6 +235,12 @@
ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
cc.RegisterRequiredBuildComponentsForTest(ctx)
+
+ // Register this after the prebuilt mutators have been registered (in
+ // cc.RegisterRequiredBuildComponentsForTest) to match what happens at runtime.
+ ctx.PreArchMutators(android.RegisterVisibilityRuleGatherer)
+ ctx.PostDepsMutators(android.RegisterVisibilityRuleEnforcer)
+
ctx.RegisterModuleType("cc_test", cc.TestFactory)
ctx.RegisterModuleType("vndk_prebuilt_shared", cc.VndkPrebuiltSharedFactory)
ctx.RegisterModuleType("vndk_libraries_txt", cc.VndkLibrariesTxtFactory)
@@ -240,7 +251,8 @@
java.RegisterJavaBuildComponents(ctx)
java.RegisterSystemModulesBuildComponents(ctx)
java.RegisterAppBuildComponents(ctx)
- ctx.RegisterModuleType("java_sdk_library", java.SdkLibraryFactory)
+ java.RegisterSdkLibraryBuildComponents(ctx)
+ ctx.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
ctx.PreDepsMutators(RegisterPreDepsMutators)
ctx.PostDepsMutators(RegisterPostDepsMutators)
@@ -329,7 +341,7 @@
// Minimal test
func TestBasicApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx, config := testApex(t, `
apex_defaults {
name: "myapex-defaults",
manifest: ":myapex.manifest",
@@ -484,6 +496,16 @@
apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
+ // Make sure that Android.mk is created
+ ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
+ data := android.AndroidMkDataForTest(t, config, "", ab)
+ var builder strings.Builder
+ data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
+
+ androidMk := builder.String()
+ ensureContains(t, androidMk, "LOCAL_MODULE := mylib.myapex\n")
+ ensureNotContains(t, androidMk, "LOCAL_MODULE := mylib.com.android.myapex\n")
+
optFlags := apexRule.Args["opt_flags"]
ensureContains(t, optFlags, "--pubkey vendor/foo/devkeys/testkey.avbpubkey")
// Ensure that the NOTICE output is being packaged as an asset.
@@ -1133,7 +1155,7 @@
symbol_file: "",
}
`, func(fs map[string][]byte, config android.Config) {
- setUseVendorWhitelistForTest(config, []string{"myapex"})
+ setUseVendorAllowListForTest(config, []string{"myapex"})
}, withUnbundledBuild)
// Ensure that LLNDK dep is not included
@@ -1860,7 +1882,7 @@
apex_available: [ "myapex" ],
}
`, func(fs map[string][]byte, config android.Config) {
- setUseVendorWhitelistForTest(config, []string{"myapex"})
+ setUseVendorAllowListForTest(config, []string{"myapex"})
})
inputsList := []string{}
@@ -1893,9 +1915,9 @@
private_key: "testkey.pem",
}
`, func(fs map[string][]byte, config android.Config) {
- setUseVendorWhitelistForTest(config, []string{""})
+ setUseVendorAllowListForTest(config, []string{""})
})
- // no error with whitelist
+ // no error with allow list
testApex(t, `
apex {
name: "myapex",
@@ -1908,7 +1930,7 @@
private_key: "testkey.pem",
}
`, func(fs map[string][]byte, config android.Config) {
- setUseVendorWhitelistForTest(config, []string{"myapex"})
+ setUseVendorAllowListForTest(config, []string{"myapex"})
})
}
@@ -2806,6 +2828,40 @@
})
}
+func TestVndkApexShouldNotProvideNativeLibs(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex_vndk {
+ name: "myapex",
+ key: "myapex.key",
+ file_contexts: ":myapex-file_contexts",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libz",
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ },
+ stubs: {
+ symbol_file: "libz.map.txt",
+ versions: ["30"],
+ }
+ }
+ `+vndkLibrariesTxtFiles("current"), withFiles(map[string][]byte{
+ "libz.map.txt": nil,
+ }))
+
+ apexManifestRule := ctx.ModuleForTests("myapex", "android_common_image").Rule("apexManifestRule")
+ provideNativeLibs := names(apexManifestRule.Args["provideNativeLibs"])
+ ensureListEmpty(t, provideNativeLibs)
+}
+
func TestDependenciesInApexManifest(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -3673,7 +3729,7 @@
private_key: "testkey.pem",
}
`, func(fs map[string][]byte, config android.Config) {
- setUseVendorWhitelistForTest(config, []string{"myapex"})
+ setUseVendorAllowListForTest(config, []string{"myapex"})
})
}
@@ -4321,6 +4377,9 @@
"api/system-removed.txt": nil,
"api/test-current.txt": nil,
"api/test-removed.txt": nil,
+
+ // For java_sdk_library_import
+ "a.jar": nil,
}
func TestJavaSDKLibrary(t *testing.T) {
@@ -4447,6 +4506,117 @@
}
}
+func TestJavaSDKLibrary_ImportPreferred(t *testing.T) {
+ ctx, _ := testApex(t, ``,
+ withFiles(map[string][]byte{
+ "apex/a.java": nil,
+ "apex/apex_manifest.json": nil,
+ "apex/Android.bp": []byte(`
+ package {
+ default_visibility: ["//visibility:private"],
+ }
+
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ java_libs: ["foo", "bar"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["a.java"],
+ libs: ["foo"],
+ apex_available: ["myapex"],
+ sdk_version: "none",
+ system_modules: "none",
+ }
+`),
+ "source/a.java": nil,
+ "source/api/current.txt": nil,
+ "source/api/removed.txt": nil,
+ "source/Android.bp": []byte(`
+ package {
+ default_visibility: ["//visibility:private"],
+ }
+
+ java_sdk_library {
+ name: "foo",
+ visibility: ["//apex"],
+ srcs: ["a.java"],
+ api_packages: ["foo"],
+ apex_available: ["myapex"],
+ sdk_version: "none",
+ system_modules: "none",
+ public: {
+ enabled: true,
+ },
+ }
+`),
+ "prebuilt/a.jar": nil,
+ "prebuilt/Android.bp": []byte(`
+ package {
+ default_visibility: ["//visibility:private"],
+ }
+
+ java_sdk_library_import {
+ name: "foo",
+ visibility: ["//apex", "//source"],
+ apex_available: ["myapex"],
+ prefer: true,
+ public: {
+ jars: ["a.jar"],
+ },
+ }
+`),
+ }),
+ )
+
+ // java_sdk_library installs both impl jar and permission XML
+ ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+ "javalib/bar.jar",
+ "javalib/foo.jar",
+ "etc/permissions/foo.xml",
+ })
+
+ // The bar library should depend on the implementation jar.
+ barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac")
+ if expected, actual := `^-classpath /[^:]*/turbine-combined/foo\.impl\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ t.Errorf("expected %q, found %#q", expected, actual)
+ }
+}
+
+func TestJavaSDKLibrary_ImportOnly(t *testing.T) {
+ testApexError(t, `java_libs: "foo" is not configured to be compiled into dex`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ java_libs: ["foo"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_sdk_library_import {
+ name: "foo",
+ apex_available: ["myapex"],
+ prefer: true,
+ public: {
+ jars: ["a.jar"],
+ },
+ }
+
+ `, withFiles(filesForSdkLibrary))
+}
+
func TestCompatConfig(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -5186,6 +5356,46 @@
`)
}
+func TestApexKeysTxt(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ prebuilt_apex {
+ name: "myapex",
+ prefer: true,
+ arch: {
+ arm64: {
+ src: "myapex-arm64.apex",
+ },
+ arm: {
+ src: "myapex-arm.apex",
+ },
+ },
+ }
+
+ apex_set {
+ name: "myapex_set",
+ set: "myapex.apks",
+ filename: "myapex_set.apex",
+ overrides: ["myapex"],
+ }
+ `)
+
+ apexKeysText := ctx.SingletonForTests("apex_keys_text")
+ content := apexKeysText.MaybeDescription("apexkeys.txt").BuildParams.Args["content"]
+ ensureContains(t, content, `name="myapex_set.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
+ ensureNotContains(t, content, "myapex.apex")
+}
+
func TestMain(m *testing.M) {
run := func() int {
setUp()
diff --git a/apex/builder.go b/apex/builder.go
index 17eac1a..1293588 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -165,13 +165,13 @@
diffApexContentRule = pctx.StaticRule("diffApexContentRule", blueprint.RuleParams{
Command: `diff --unchanged-group-format='' \` +
`--changed-group-format='%<' \` +
- `${image_content_file} ${whitelisted_files_file} || (` +
+ `${image_content_file} ${allowed_files_file} || (` +
`echo -e "New unexpected files were added to ${apex_module_name}." ` +
` "To fix the build run following command:" && ` +
- `echo "system/apex/tools/update_whitelist.sh ${whitelisted_files_file} ${image_content_file}" && ` +
+ `echo "system/apex/tools/update_allowed_list.sh ${allowed_files_file} ${image_content_file}" && ` +
`exit 1); touch ${out}`,
- Description: "Diff ${image_content_file} and ${whitelisted_files_file}",
- }, "image_content_file", "whitelisted_files_file", "apex_module_name")
+ Description: "Diff ${image_content_file} and ${allowed_files_file}",
+ }, "image_content_file", "allowed_files_file", "apex_module_name")
)
func (a *apexBundle) buildManifest(ctx android.ModuleContext, provideNativeLibs, requireNativeLibs []string) {
@@ -402,7 +402,7 @@
},
})
implicitInputs = append(implicitInputs, imageContentFile)
- whitelistedFilesFile := android.PathForModuleSrc(ctx, proptools.String(a.properties.Whitelisted_files))
+ allowedFilesFile := android.PathForModuleSrc(ctx, proptools.String(a.properties.Whitelisted_files))
phonyOutput := android.PathForModuleOut(ctx, a.Name()+"-diff-phony-output")
ctx.Build(pctx, android.BuildParams{
@@ -411,9 +411,9 @@
Output: phonyOutput,
Description: "diff apex image content",
Args: map[string]string{
- "whitelisted_files_file": whitelistedFilesFile.String(),
- "image_content_file": imageContentFile.String(),
- "apex_module_name": a.Name(),
+ "allowed_files_file": allowedFilesFile.String(),
+ "image_content_file": imageContentFile.String(),
+ "apex_module_name": a.Name(),
},
})
diff --git a/apex/key.go b/apex/key.go
index 607cac5..a68f6e1 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -106,10 +106,36 @@
func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
s.output = android.PathForOutput(ctx, "apexkeys.txt")
- apexModulesMap := make(map[string]android.Module)
+ type apexKeyEntry struct {
+ name string
+ presigned bool
+ public_key string
+ private_key string
+ container_certificate string
+ container_private_key string
+ partition string
+ }
+ toString := func(e apexKeyEntry) string {
+ format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q\\n"
+ if e.presigned {
+ return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", e.partition)
+ } else {
+ return fmt.Sprintf(format, e.name, e.public_key, e.private_key, e.container_certificate, e.container_private_key, e.partition)
+ }
+ }
+
+ apexKeyMap := make(map[string]apexKeyEntry)
ctx.VisitAllModules(func(module android.Module) {
if m, ok := module.(*apexBundle); ok && m.Enabled() && m.installable() {
- apexModulesMap[m.Name()] = m
+ apexKeyMap[m.Name()] = apexKeyEntry{
+ name: m.Name() + ".apex",
+ presigned: false,
+ public_key: m.public_key_file.String(),
+ private_key: m.private_key_file.String(),
+ container_certificate: m.container_certificate_file.String(),
+ container_private_key: m.container_private_key_file.String(),
+ partition: m.PartitionTag(ctx.DeviceConfig()),
+ }
}
})
@@ -117,35 +143,43 @@
ctx.VisitAllModules(func(module android.Module) {
if m, ok := module.(*Prebuilt); ok && m.Enabled() && m.installable() &&
m.Prebuilt().UsePrebuilt() {
- apexModulesMap[m.BaseModuleName()] = m
+ apexKeyMap[m.BaseModuleName()] = apexKeyEntry{
+ name: m.InstallFilename(),
+ presigned: true,
+ partition: m.PartitionTag(ctx.DeviceConfig()),
+ }
+ }
+ })
+
+ // Find apex_set and let them override apexBundle or prebuilts. This is done in a separate pass
+ // so that apex_set are not overridden by prebuilts.
+ ctx.VisitAllModules(func(module android.Module) {
+ if m, ok := module.(*ApexSet); ok && m.Enabled() {
+ entry := apexKeyEntry{
+ name: m.InstallFilename(),
+ presigned: true,
+ partition: m.PartitionTag(ctx.DeviceConfig()),
+ }
+
+ for _, om := range m.Overrides() {
+ if _, ok := apexKeyMap[om]; ok {
+ delete(apexKeyMap, om)
+ }
+ }
+ apexKeyMap[m.BaseModuleName()] = entry
}
})
// iterating over map does not give consistent ordering in golang
var moduleNames []string
- for key, _ := range apexModulesMap {
+ for key, _ := range apexKeyMap {
moduleNames = append(moduleNames, key)
}
sort.Strings(moduleNames)
var filecontent strings.Builder
- for _, key := range moduleNames {
- module := apexModulesMap[key]
- if m, ok := module.(*apexBundle); ok {
- fmt.Fprintf(&filecontent,
- "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q\\n",
- m.Name()+".apex",
- m.public_key_file.String(),
- m.private_key_file.String(),
- m.container_certificate_file.String(),
- m.container_private_key_file.String(),
- m.PartitionTag(ctx.DeviceConfig()))
- } else if m, ok := module.(*Prebuilt); ok {
- fmt.Fprintf(&filecontent,
- "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q\\n",
- m.InstallFilename(),
- "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", m.PartitionTag(ctx.DeviceConfig()))
- }
+ for _, name := range moduleNames {
+ fmt.Fprintf(&filecontent, "%s", toString(apexKeyMap[name]))
}
ctx.Build(pctx, android.BuildParams{
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 03266c5..bf574dc 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -278,6 +278,10 @@
return a.prebuilt.Name(a.ModuleBase.Name())
}
+func (a *ApexSet) Overrides() []string {
+ return a.properties.Overrides
+}
+
// prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex.
func apexSetFactory() android.Module {
module := &ApexSet{}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 52480ea..b3ad610 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -457,6 +457,9 @@
entries.SetString("LOCAL_MODULE_PATH", path)
entries.SetString("LOCAL_MODULE_STEM", stem)
entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
+ if c.parsedCoverageXmlPath.String() != "" {
+ entries.SetString("SOONG_NDK_API_XML", "$(SOONG_NDK_API_XML) "+c.parsedCoverageXmlPath.String())
+ }
})
}
diff --git a/cc/builder.go b/cc/builder.go
index e571e5a..b4f9947 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -283,16 +283,19 @@
"cFlags")
)
+func PwdPrefix() string {
+ // Darwin doesn't have /proc
+ if runtime.GOOS != "darwin" {
+ return "PWD=/proc/self/cwd"
+ }
+ return ""
+}
+
func init() {
// We run gcc/clang with PWD=/proc/self/cwd to remove $TOP from the
// debug output. That way two builds in two different directories will
// create the same output.
- if runtime.GOOS != "darwin" {
- pctx.StaticVariable("relPwd", "PWD=/proc/self/cwd")
- } else {
- // Darwin doesn't have /proc
- pctx.StaticVariable("relPwd", "")
- }
+ pctx.StaticVariable("relPwd", PwdPrefix())
pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
pctx.Import("android/soong/remoteexec")
diff --git a/cc/cc.go b/cc/cc.go
index 8eabff5..f80c229 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -825,15 +825,8 @@
}
c.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
- switch class {
- case android.Device:
- return ctx.Config().DevicePrefer32BitExecutables()
- case android.HostCross:
- // Windows builds always prefer 32-bit
- return true
- default:
- return false
- }
+ // Windows builds always prefer 32-bit
+ return class == android.HostCross
})
android.InitAndroidArchModule(c, c.hod, c.multilib)
android.InitApexModule(c)
@@ -3230,12 +3223,7 @@
})
// TODO(asmundak): Perhaps emit a rule to output a warning if there were no xrefTargets
if len(xrefTargets) > 0 {
- ctx.Build(pctx, android.BuildParams{
- Rule: blueprint.Phony,
- Output: android.PathForPhony(ctx, "xref_cxx"),
- Inputs: xrefTargets,
- //Default: true,
- })
+ ctx.Phony("xref_cxx", xrefTargets...)
}
}
diff --git a/cc/compiler.go b/cc/compiler.go
index e7495da..b5f297c 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -514,7 +514,7 @@
flags.Local.CFlags = append(flags.Local.CFlags, "-fopenmp")
}
- // Exclude directories from manual binder interface whitelisting.
+ // Exclude directories from manual binder interface allowed list.
//TODO(b/145621474): Move this check into IInterface.h when clang-tidy no longer uses absolute paths.
if android.HasAnyPrefix(ctx.ModuleDir(), allowedManualInterfacePaths) {
flags.Local.CFlags = append(flags.Local.CFlags, "-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES")
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 9383463..62d8cc8 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -32,7 +32,7 @@
"-march=armv8-a",
},
"armv8-2a": []string{
- "-march=armv8.2a",
+ "-march=armv8.2-a",
},
}
diff --git a/cc/config/global.go b/cc/config/global.go
index 1dd8a2d..7b651bc 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -128,8 +128,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r383902"
- ClangDefaultShortVersion = "11.0.1"
+ ClangDefaultVersion = "clang-r383902b"
+ ClangDefaultShortVersion = "11.0.2"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
diff --git a/cc/coverage.go b/cc/coverage.go
index f885fcb..1a559a9 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -180,7 +180,7 @@
if needCoverageVariant {
// Coverage variant is actually built with coverage if enabled for its module path
- needCoverageBuild = ctx.DeviceConfig().CoverageEnabledForPath(ctx.ModuleDir())
+ needCoverageBuild = ctx.DeviceConfig().NativeCoverageEnabledForPath(ctx.ModuleDir())
}
}
diff --git a/cc/linker.go b/cc/linker.go
index 57a0c01..c9cbd9b 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -177,7 +177,10 @@
Version_script *string `android:"path,arch_variant"`
// list of static libs that should not be used to build this module
- Exclude_static_libs []string
+ Exclude_static_libs []string `android:"arch_variant"`
+
+ // list of shared libs that should not be used to build this module
+ Exclude_shared_libs []string `android:"arch_variant"`
}
func NewBaseLinker(sanitize *sanitize) *baseLinker {
@@ -223,6 +226,8 @@
deps.ReexportSharedLibHeaders = append(deps.ReexportSharedLibHeaders, linker.Properties.Export_shared_lib_headers...)
deps.ReexportGeneratedHeaders = append(deps.ReexportGeneratedHeaders, linker.Properties.Export_generated_headers...)
+ deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Exclude_shared_libs)
+ deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Exclude_static_libs)
deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Exclude_static_libs)
if Bool(linker.Properties.Use_version_lib) {
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 1597b88..5ef9a78 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -25,8 +25,12 @@
"android/soong/android"
)
+func init() {
+ pctx.HostBinToolVariable("ndk_api_coverage_parser", "ndk_api_coverage_parser")
+}
+
var (
- toolPath = pctx.SourcePathVariable("toolPath", "build/soong/cc/gen_stub_libs.py")
+ toolPath = pctx.SourcePathVariable("toolPath", "build/soong/cc/scriptlib/gen_stub_libs.py")
genStubSrc = pctx.AndroidStaticRule("genStubSrc",
blueprint.RuleParams{
@@ -35,6 +39,12 @@
CommandDeps: []string{"$toolPath"},
}, "arch", "apiLevel", "apiMap", "flags")
+ parseNdkApiRule = pctx.AndroidStaticRule("parseNdkApiRule",
+ blueprint.RuleParams{
+ Command: "$ndk_api_coverage_parser $in $out --api-map $apiMap",
+ CommandDeps: []string{"$ndk_api_coverage_parser"},
+ }, "apiMap")
+
ndkLibrarySuffix = ".ndk"
ndkPrebuiltSharedLibs = []string{
@@ -111,8 +121,9 @@
properties libraryProperties
- versionScriptPath android.ModuleGenPath
- installPath android.Path
+ versionScriptPath android.ModuleGenPath
+ parsedCoverageXmlPath android.ModuleOutPath
+ installPath android.Path
}
// OMG GO
@@ -308,14 +319,36 @@
return compileObjs(ctx, flagsToBuilderFlags(flags), subdir, srcs, nil, nil), versionScriptPath
}
+func parseSymbolFileForCoverage(ctx ModuleContext, symbolFile string) android.ModuleOutPath {
+ apiLevelsJson := android.GetApiLevelsJson(ctx)
+ symbolFilePath := android.PathForModuleSrc(ctx, symbolFile)
+ outputFileName := strings.Split(symbolFilePath.Base(), ".")[0]
+ parsedApiCoveragePath := android.PathForModuleOut(ctx, outputFileName+".xml")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: parseNdkApiRule,
+ Description: "parse ndk api symbol file for api coverage: " + symbolFilePath.Rel(),
+ Outputs: []android.WritablePath{parsedApiCoveragePath},
+ Input: symbolFilePath,
+ Implicits: []android.Path{apiLevelsJson},
+ Args: map[string]string{
+ "apiMap": apiLevelsJson.String(),
+ },
+ })
+ return parsedApiCoveragePath
+}
+
func (c *stubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
if !strings.HasSuffix(String(c.properties.Symbol_file), ".map.txt") {
ctx.PropertyErrorf("symbol_file", "must end with .map.txt")
}
- objs, versionScript := compileStubLibrary(ctx, flags, String(c.properties.Symbol_file),
+ symbolFile := String(c.properties.Symbol_file)
+ objs, versionScript := compileStubLibrary(ctx, flags, symbolFile,
c.properties.ApiLevel, "")
c.versionScriptPath = versionScript
+ if c.properties.ApiLevel == "current" && ctx.PrimaryArch() {
+ c.parsedCoverageXmlPath = parseSymbolFileForCoverage(ctx, symbolFile)
+ }
return objs
}
diff --git a/cc/scriptlib/Android.bp b/cc/scriptlib/Android.bp
new file mode 100644
index 0000000..ff9a2f0
--- /dev/null
+++ b/cc/scriptlib/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+python_test_host {
+ name: "test_ndk_api_coverage_parser",
+ main: "test_ndk_api_coverage_parser.py",
+ srcs: [
+ "test_ndk_api_coverage_parser.py",
+ ],
+}
+
+python_binary_host {
+ name: "ndk_api_coverage_parser",
+ main: "ndk_api_coverage_parser.py",
+ srcs: [
+ "gen_stub_libs.py",
+ "ndk_api_coverage_parser.py",
+ ],
+}
diff --git a/cc/scriptlib/__init__.py b/cc/scriptlib/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cc/scriptlib/__init__.py
diff --git a/cc/gen_stub_libs.py b/cc/scriptlib/gen_stub_libs.py
similarity index 99%
rename from cc/gen_stub_libs.py
rename to cc/scriptlib/gen_stub_libs.py
index 7deb804..d61dfbb 100755
--- a/cc/gen_stub_libs.py
+++ b/cc/scriptlib/gen_stub_libs.py
@@ -246,6 +246,7 @@
def __eq__(self, other):
return self.name == other.name and set(self.tags) == set(other.tags)
+
class SymbolFileParser(object):
"""Parses NDK symbol files."""
def __init__(self, input_file, api_map, arch, api, llndk, apex):
diff --git a/cc/scriptlib/ndk_api_coverage_parser.py b/cc/scriptlib/ndk_api_coverage_parser.py
new file mode 100755
index 0000000..d74035b
--- /dev/null
+++ b/cc/scriptlib/ndk_api_coverage_parser.py
@@ -0,0 +1,134 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Generates xml of NDK libraries used for API coverage analysis."""
+import argparse
+import json
+import os
+import sys
+
+from xml.etree.ElementTree import Element, SubElement, tostring
+from gen_stub_libs import ALL_ARCHITECTURES, FUTURE_API_LEVEL, MultiplyDefinedSymbolError, SymbolFileParser
+
+
+ROOT_ELEMENT_TAG = 'ndk-library'
+SYMBOL_ELEMENT_TAG = 'symbol'
+ARCHITECTURE_ATTRIBUTE_KEY = 'arch'
+DEPRECATED_ATTRIBUTE_KEY = 'is_deprecated'
+PLATFORM_ATTRIBUTE_KEY = 'is_platform'
+NAME_ATTRIBUTE_KEY = 'name'
+VARIABLE_TAG = 'var'
+EXPOSED_TARGET_TAGS = (
+ 'vndk',
+ 'apex',
+ 'llndk',
+)
+API_LEVEL_TAG_PREFIXES = (
+ 'introduced=',
+ 'introduced-',
+)
+
+
+def parse_tags(tags):
+ """Parses tags and save needed tags in the created attributes.
+
+ Return attributes dictionary.
+ """
+ attributes = {}
+ arch = []
+ for tag in tags:
+ if tag.startswith(tuple(API_LEVEL_TAG_PREFIXES)):
+ key, _, value = tag.partition('=')
+ attributes.update({key: value})
+ elif tag in ALL_ARCHITECTURES:
+ arch.append(tag)
+ elif tag in EXPOSED_TARGET_TAGS:
+ attributes.update({tag: 'True'})
+ attributes.update({ARCHITECTURE_ATTRIBUTE_KEY: ','.join(arch)})
+ return attributes
+
+
+class XmlGenerator(object):
+ """Output generator that writes parsed symbol file to a xml file."""
+ def __init__(self, output_file):
+ self.output_file = output_file
+
+ def convertToXml(self, versions):
+ """Writes all symbol data to the output file."""
+ root = Element(ROOT_ELEMENT_TAG)
+ for version in versions:
+ if VARIABLE_TAG in version.tags:
+ continue
+ version_attributes = parse_tags(version.tags)
+ _, _, postfix = version.name.partition('_')
+ is_platform = postfix == 'PRIVATE' or postfix == 'PLATFORM'
+ is_deprecated = postfix == 'DEPRECATED'
+ version_attributes.update({PLATFORM_ATTRIBUTE_KEY: str(is_platform)})
+ version_attributes.update({DEPRECATED_ATTRIBUTE_KEY: str(is_deprecated)})
+ for symbol in version.symbols:
+ if VARIABLE_TAG in symbol.tags:
+ continue
+ attributes = {NAME_ATTRIBUTE_KEY: symbol.name}
+ attributes.update(version_attributes)
+ # If same version tags already exist, it will be overwrite here.
+ attributes.update(parse_tags(symbol.tags))
+ SubElement(root, SYMBOL_ELEMENT_TAG, attributes)
+ return root
+
+ def write_xml_to_file(self, root):
+ """Write xml element root to output_file."""
+ parsed_data = tostring(root)
+ output_file = open(self.output_file, "wb")
+ output_file.write(parsed_data)
+
+ def write(self, versions):
+ root = self.convertToXml(versions)
+ self.write_xml_to_file(root)
+
+
+def parse_args():
+ """Parses and returns command line arguments."""
+ parser = argparse.ArgumentParser()
+
+ parser.add_argument('symbol_file', type=os.path.realpath, help='Path to symbol file.')
+ parser.add_argument(
+ 'output_file', type=os.path.realpath,
+ help='The output parsed api coverage file.')
+ parser.add_argument(
+ '--api-map', type=os.path.realpath, required=True,
+ help='Path to the API level map JSON file.')
+ return parser.parse_args()
+
+
+def main():
+ """Program entry point."""
+ args = parse_args()
+
+ with open(args.api_map) as map_file:
+ api_map = json.load(map_file)
+
+ with open(args.symbol_file) as symbol_file:
+ try:
+ versions = SymbolFileParser(symbol_file, api_map, "", FUTURE_API_LEVEL,
+ True, True).parse()
+ except MultiplyDefinedSymbolError as ex:
+ sys.exit('{}: error: {}'.format(args.symbol_file, ex))
+
+ generator = XmlGenerator(args.output_file)
+ generator.write(versions)
+
+if __name__ == '__main__':
+ main()
diff --git a/cc/test_gen_stub_libs.py b/cc/scriptlib/test_gen_stub_libs.py
similarity index 100%
rename from cc/test_gen_stub_libs.py
rename to cc/scriptlib/test_gen_stub_libs.py
diff --git a/cc/scriptlib/test_ndk_api_coverage_parser.py b/cc/scriptlib/test_ndk_api_coverage_parser.py
new file mode 100644
index 0000000..a3c9b70
--- /dev/null
+++ b/cc/scriptlib/test_ndk_api_coverage_parser.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 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.
+#
+"""Tests for ndk_api_coverage_parser.py."""
+import io
+import textwrap
+import unittest
+
+from xml.etree.ElementTree import tostring
+from gen_stub_libs import FUTURE_API_LEVEL, SymbolFileParser
+import ndk_api_coverage_parser as nparser
+
+
+# pylint: disable=missing-docstring
+
+
+class ApiCoverageSymbolFileParserTest(unittest.TestCase):
+ def test_parse(self):
+ input_file = io.StringIO(textwrap.dedent(u"""\
+ LIBLOG { # introduced-arm64=24 introduced-x86=24 introduced-x86_64=24
+ global:
+ android_name_to_log_id; # apex llndk introduced=23
+ android_log_id_to_name; # llndk arm
+ __android_log_assert; # introduced-x86=23
+ __android_log_buf_print; # var
+ __android_log_buf_write;
+ local:
+ *;
+ };
+
+ LIBLOG_PLATFORM {
+ android_fdtrack; # llndk
+ android_net; # introduced=23
+ };
+
+ LIBLOG_FOO { # var
+ android_var;
+ };
+ """))
+ parser = SymbolFileParser(input_file, {}, "", FUTURE_API_LEVEL, True, True)
+ generator = nparser.XmlGenerator(io.StringIO())
+ result = tostring(generator.convertToXml(parser.parse())).decode()
+ expected = '<ndk-library><symbol apex="True" arch="" introduced="23" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_name_to_log_id" /><symbol arch="arm" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_log_id_to_name" /><symbol arch="" introduced-arm64="24" introduced-x86="23" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_assert" /><symbol arch="" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_buf_write" /><symbol arch="" is_deprecated="False" is_platform="True" llndk="True" name="android_fdtrack" /><symbol arch="" introduced="23" is_deprecated="False" is_platform="True" name="android_net" /></ndk-library>'
+ self.assertEqual(expected, result)
+
+
+def main():
+ suite = unittest.TestLoader().loadTestsFromName(__name__)
+ unittest.TextTestRunner(verbosity=3).run(suite)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/cc/sdk.go b/cc/sdk.go
index d05a04a..a6f94af 100644
--- a/cc/sdk.go
+++ b/cc/sdk.go
@@ -43,6 +43,7 @@
if ctx.Config().UnbundledBuild() {
modules[0].(*Module).Properties.HideFromMake = true
+ modules[0].(*Module).Properties.PreventInstall = true
} else {
modules[1].(*Module).Properties.SdkAndPlatformVariantVisibleToMake = true
modules[1].(*Module).Properties.PreventInstall = true
diff --git a/cc/testing.go b/cc/testing.go
index edbb24d..479b424 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -467,15 +467,6 @@
}
func GatherRequiredFilesForTest(fs map[string][]byte) {
- fs["prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so"] = nil
- fs["prebuilts/ndk/current/platforms/android-27/arch-arm/usr/lib/crtbegin_so.o"] = nil
- fs["prebuilts/ndk/current/platforms/android-27/arch-arm/usr/lib/crtend_so.o"] = nil
- fs["prebuilts/ndk/current/platforms/android-27/arch-arm64/usr/lib/crtbegin_so.o"] = nil
- fs["prebuilts/ndk/current/platforms/android-27/arch-arm64/usr/lib/crtend_so.o"] = nil
- fs["prebuilts/ndk/current/platforms/android-27/arch-x86/usr/lib/crtbegin_so.o"] = nil
- fs["prebuilts/ndk/current/platforms/android-27/arch-x86/usr/lib/crtend_so.o"] = nil
- fs["prebuilts/ndk/current/platforms/android-27/arch-x86_64/usr/lib64/crtbegin_so.o"] = nil
- fs["prebuilts/ndk/current/platforms/android-27/arch-x86_64/usr/lib64/crtend_so.o"] = nil
}
func TestConfig(buildDir string, os android.OsType, env map[string]string,
@@ -484,20 +475,7 @@
// add some modules that are required by the compiler and/or linker
bp = bp + GatherRequiredDepsForTest(os)
- mockFS := map[string][]byte{
- "foo.c": nil,
- "foo.lds": nil,
- "bar.c": nil,
- "baz.c": nil,
- "baz.o": nil,
- "a.proto": nil,
- "b.aidl": nil,
- "sub/c.aidl": nil,
- "my_include": nil,
- "foo.map.txt": nil,
- "liba.so": nil,
- "libb.a": nil,
- }
+ mockFS := map[string][]byte{}
GatherRequiredFilesForTest(mockFS)
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index d0cad78..c965107 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -171,7 +171,7 @@
buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
- defer build.UploadMetrics(buildCtx, config, buildStartedMilli, buildErrorFile, rbeMetricsFile, soongMetricsFile)
+ defer build.UploadMetrics(buildCtx, config, c.forceDumbOutput, buildStartedMilli, buildErrorFile, rbeMetricsFile, soongMetricsFile)
os.MkdirAll(logsDir, 0777)
log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 3440f8e..bc44b21 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -123,10 +123,10 @@
ProfileIsTextListing bool
ProfileBootListing android.OptionalPath
- EnforceUsesLibraries bool
- PresentOptionalUsesLibraries []string
- UsesLibraries []string
- LibraryPaths LibraryPaths
+ EnforceUsesLibraries bool
+ OptionalUsesLibraries []string
+ UsesLibraries []string
+ LibraryPaths LibraryPaths
Archs []android.ArchType
DexPreoptImages []android.Path
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 57a9250..9cbe6e5 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -285,7 +285,7 @@
if module.EnforceUsesLibraries {
// Unconditional class loader context.
- usesLibs := append(copyOf(module.UsesLibraries), module.PresentOptionalUsesLibraries...)
+ usesLibs := append(copyOf(module.UsesLibraries), module.OptionalUsesLibraries...)
classLoaderContexts.addLibs(anySdkVersion, module, usesLibs...)
// Conditional class loader context for API version < 28.
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index d239993..ec31549 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -44,7 +44,7 @@
ProfileClassListing: android.OptionalPath{},
ProfileIsTextListing: false,
EnforceUsesLibraries: false,
- PresentOptionalUsesLibraries: nil,
+ OptionalUsesLibraries: nil,
UsesLibraries: nil,
LibraryPaths: nil,
Archs: []android.ArchType{android.Arm},
diff --git a/java/aar.go b/java/aar.go
index 7413c80..28e388a 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -734,6 +734,10 @@
return nil
}
+func (a *AARImport) DexJarInstallPath() android.Path {
+ return nil
+}
+
func (a *AARImport) AidlIncludeDirs() android.Paths {
return nil
}
diff --git a/java/app.go b/java/app.go
index 24dde79..74c92a6 100755
--- a/java/app.go
+++ b/java/app.go
@@ -133,7 +133,7 @@
// We are assuming here that the master file in the APK
// set has `.apk` suffix. If it doesn't the build will fail.
// APK sets containing APEX files are handled elsewhere.
- as.masterFile = ctx.ModuleName() + ".apk"
+ as.masterFile = as.BaseModuleName() + ".apk"
screenDensities := "all"
if dpis := ctx.Config().ProductAAPTPrebuiltDPI(); len(dpis) > 0 {
screenDensities = strings.ToUpper(strings.Join(dpis, ","))
@@ -691,9 +691,9 @@
systemCertPath := ctx.Config().DefaultAppCertificateDir(ctx).String()
if strings.HasPrefix(certPath, systemCertPath) {
enforceSystemCert := ctx.Config().EnforceSystemCertificate()
- whitelist := ctx.Config().EnforceSystemCertificateWhitelist()
+ allowed := ctx.Config().EnforceSystemCertificateAllowList()
- if enforceSystemCert && !inList(m.Name(), whitelist) {
+ if enforceSystemCert && !inList(m.Name(), allowed) {
ctx.PropertyErrorf("certificate", "The module in product partition cannot be signed with certificate in system.")
}
}
@@ -973,10 +973,6 @@
&module.overridableAppProperties,
&module.usesLibrary.usesLibraryProperties)
- module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
- return class == android.Device && ctx.Config().DevicePrefer32BitApps()
- })
-
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
android.InitOverridableModule(module, &module.appProperties.Overrides)
@@ -1887,16 +1883,22 @@
ctx.VisitDirectDepsWithTag(usesLibTag, func(m android.Module) {
dep := ctx.OtherModuleName(m)
if lib, ok := m.(Dependency); ok {
- if dexJar := lib.DexJarBuildPath(); dexJar != nil {
- usesLibPaths[dep] = &dexpreopt.LibraryPath{
- dexJar,
- // TODO(b/132357300): propagate actual install paths here.
- filepath.Join("/system/framework", dep+".jar"),
- }
- } else {
+ buildPath := lib.DexJarBuildPath()
+ if buildPath == nil {
ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must"+
" produce a dex jar, does it have installable: true?", dep)
+ return
}
+
+ var devicePath string
+ installPath := lib.DexJarInstallPath()
+ if installPath == nil {
+ devicePath = filepath.Join("/system/framework", dep+".jar")
+ } else {
+ devicePath = android.InstallPathToOnDevicePath(ctx, installPath.(android.InstallPath))
+ }
+
+ usesLibPaths[dep] = &dexpreopt.LibraryPath{buildPath, devicePath}
} else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{dep})
} else {
diff --git a/java/app_test.go b/java/app_test.go
index eeba161..e45ba70 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2657,7 +2657,7 @@
}
func TestEmbedNotice(t *testing.T) {
- ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
+ ctx, _ := testJavaWithFS(t, cc.GatherRequiredDepsForTest(android.Android)+`
android_app {
name: "foo",
srcs: ["a.java"],
@@ -2713,7 +2713,12 @@
srcs: ["b.java"],
notice: "TOOL_NOTICE",
}
- `)
+ `, map[string][]byte{
+ "APP_NOTICE": nil,
+ "GENRULE_NOTICE": nil,
+ "LIB_NOTICE": nil,
+ "TOOL_NOTICE": nil,
+ })
// foo has NOTICE files to process, and embed_notices is true.
foo := ctx.ModuleForTests("foo", "android_common")
diff --git a/java/config/config.go b/java/config/config.go
index edaed2a..bb5be3a 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -28,8 +28,9 @@
var (
pctx = android.NewPackageContext("android/soong/java/config")
- DefaultBootclasspathLibraries = []string{"core.platform.api.stubs", "core-lambda-stubs"}
- DefaultSystemModules = "core-platform-api-stubs-system-modules"
+ // TODO(b/157640067): Don't depend on the legacy API by default in the long term.
+ DefaultBootclasspathLibraries = []string{"legacy.core.platform.api.stubs", "core-lambda-stubs"}
+ DefaultSystemModules = "legacy-core-platform-api-stubs-system-modules"
DefaultLibraries = []string{"ext", "framework"}
DefaultLambdaStubsLibrary = "core-lambda-stubs"
SdkLambdaStubsPath = "prebuilts/sdk/tools/core-lambda-stubs.jar"
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 1ffb13f..9191a83 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -51,7 +51,7 @@
// java_device_for_host makes the classes.jar output of a device java_library module available to host
// java_library modules.
//
-// It is rarely necessary, and its usage is restricted to a few whitelisted projects.
+// It is rarely necessary, and its usage is restricted to a few allowed projects.
func DeviceForHostFactory() android.Module {
module := &DeviceForHost{}
@@ -68,7 +68,7 @@
// java_host_for_device makes the classes.jar output of a host java_library module available to device
// java_library modules.
//
-// It is rarely necessary, and its usage is restricted to a few whitelisted projects.
+// It is rarely necessary, and its usage is restricted to a few allowed projects.
func HostForDeviceFactory() android.Module {
module := &HostForDevice{}
@@ -154,6 +154,10 @@
return nil
}
+func (d *DeviceHostConverter) DexJarInstallPath() android.Path {
+ return nil
+}
+
func (d *DeviceHostConverter) AidlIncludeDirs() android.Paths {
return nil
}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 2911fd9..7f1afd6 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -77,10 +77,6 @@
return true
}
- if ctx.Config().UnbundledBuild() {
- return true
- }
-
if d.isTest {
return true
}
@@ -197,10 +193,10 @@
ProfileIsTextListing: profileIsTextListing,
ProfileBootListing: profileBootListing,
- EnforceUsesLibraries: d.enforceUsesLibs,
- PresentOptionalUsesLibraries: d.optionalUsesLibs,
- UsesLibraries: d.usesLibs,
- LibraryPaths: d.libraryPaths,
+ EnforceUsesLibraries: d.enforceUsesLibs,
+ OptionalUsesLibraries: d.optionalUsesLibs,
+ UsesLibraries: d.usesLibs,
+ LibraryPaths: d.libraryPaths,
Archs: archs,
DexPreoptImages: images,
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 9d93838..4120559 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -179,15 +179,7 @@
}
func skipDexpreoptBootJars(ctx android.PathContext) bool {
- if dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
- return true
- }
-
- if ctx.Config().UnbundledBuild() {
- return true
- }
-
- return false
+ return dexpreopt.GetGlobalConfig(ctx).DisablePreopt
}
type dexpreoptBootJars struct {
@@ -340,10 +332,12 @@
bootFrameworkProfileRule(ctx, image, missingDeps)
updatableBcpPackagesRule(ctx, image, missingDeps)
- var allFiles android.Paths
+ var zipFiles android.Paths
for _, variant := range image.variants {
files := buildBootImageVariant(ctx, variant, profile, missingDeps)
- allFiles = append(allFiles, files.Paths()...)
+ if variant.target.Os == android.Android {
+ zipFiles = append(zipFiles, files.Paths()...)
+ }
}
if image.zip != nil {
@@ -351,8 +345,8 @@
rule.Command().
BuiltTool(ctx, "soong_zip").
FlagWithOutput("-o ", image.zip).
- FlagWithArg("-C ", image.dir.String()).
- FlagWithInputList("-f ", allFiles, " -f ")
+ FlagWithArg("-C ", image.dir.Join(ctx, android.Android.String()).String()).
+ FlagWithInputList("-f ", zipFiles, " -f ")
rule.Build(pctx, ctx, "zip_"+image.name, "zip "+image.name+" image")
}
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index e9704dc..9670c7f 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -118,7 +118,7 @@
ctx := android.PathContextForTesting(testConfig(nil, "", nil))
expectedInputs := []string{}
- for _, target := range dexpreoptTargets(ctx) {
+ for _, target := range ctx.Config().Targets[android.Android] {
for _, ext := range []string{".art", ".oat", ".vdex"} {
for _, jar := range []string{"foo", "bar", "baz"} {
expectedInputs = append(expectedInputs,
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 4c3e112..68cfe9f 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1470,7 +1470,7 @@
FlagWithInput("@", srcJarList).
FlagWithOutput("--strict-input-files:warn ", android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"violations.txt"))
- if implicitsRsp.String() != "" {
+ if implicitsRsp != nil {
cmd.FlagWithArg("--strict-input-files-exempt ", "@"+implicitsRsp.String())
}
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 2f35798..bff591c 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -116,7 +116,7 @@
// Core Platform API stubs
corePlatformStubModules := []string{
- "core.platform.api.stubs",
+ "legacy.core.platform.api.stubs",
}
// Allow products to define their own stubs for custom product jars that apps can use.
diff --git a/java/java.go b/java/java.go
index 0ba1f5a..bd5f6b7 100644
--- a/java/java.go
+++ b/java/java.go
@@ -502,6 +502,7 @@
ResourceJars() android.Paths
ImplementationAndResourcesJars() android.Paths
DexJarBuildPath() android.Path
+ DexJarInstallPath() android.Path
AidlIncludeDirs() android.Paths
ExportedSdkLibs() []string
ExportedPlugins() (android.Paths, []string)
@@ -600,7 +601,9 @@
}
func (j *Module) shouldInstrument(ctx android.BaseModuleContext) bool {
- return j.properties.Instrument && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT")
+ return j.properties.Instrument &&
+ ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") &&
+ ctx.DeviceConfig().JavaCoverageEnabledForPath(ctx.ModuleDir())
}
func (j *Module) shouldInstrumentStatic(ctx android.BaseModuleContext) bool {
@@ -609,6 +612,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))
}
@@ -837,8 +855,9 @@
func (m *Module) getLinkType(name string) (ret linkType, stubs bool) {
switch name {
- case "core.current.stubs", "core.platform.api.stubs", "stub-annotations",
- "private-stub-annotations-jar", "core-lambda-stubs", "core-generated-annotation-stubs":
+ case "core.current.stubs", "legacy.core.platform.api.stubs", "stable.core.platform.api.stubs",
+ "stub-annotations", "private-stub-annotations-jar",
+ "core-lambda-stubs", "core-generated-annotation-stubs":
return javaCore, true
case "android_stubs_current":
return javaSdk, true
@@ -1148,9 +1167,9 @@
if flags.javaVersion.usesJavaModules() {
javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...)
}
- if ctx.Config().MinimizeJavaDebugInfo() {
- // Override the -g flag passed globally to remove local variable debug info to reduce
- // disk and memory usage.
+ if ctx.Config().MinimizeJavaDebugInfo() && !ctx.Host() {
+ // For non-host binaries, override the -g flag passed globally to remove
+ // local variable debug info to reduce disk and memory usage.
javacFlags = append(javacFlags, "-g:source,lines")
}
javacFlags = append(javacFlags, "-Xlint:-dep-ann")
@@ -1541,11 +1560,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
}
@@ -1748,6 +1763,10 @@
return j.dexJarFile
}
+func (j *Module) DexJarInstallPath() android.Path {
+ return j.installFile
+}
+
func (j *Module) ResourceJars() android.Paths {
if j.resourceJar == nil {
return nil
@@ -2574,6 +2593,10 @@
return nil
}
+func (j *Import) DexJarInstallPath() android.Path {
+ return nil
+}
+
func (j *Import) AidlIncludeDirs() android.Paths {
return j.exportAidlIncludeDirs
}
@@ -2753,8 +2776,10 @@
j.maybeStrippedDexJarFile = dexOutputFile
- ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
- j.Stem()+".jar", dexOutputFile)
+ if j.IsForPlatform() {
+ ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
+ j.Stem()+".jar", dexOutputFile)
+ }
}
func (j *DexImport) DexJarBuildPath() android.Path {
@@ -2862,11 +2887,7 @@
})
// TODO(asmundak): perhaps emit a rule to output a warning if there were no xrefTargets
if len(xrefTargets) > 0 {
- ctx.Build(pctx, android.BuildParams{
- Rule: blueprint.Phony,
- Output: android.PathForPhony(ctx, "xref_java"),
- Inputs: xrefTargets,
- })
+ ctx.Phony("xref_java", xrefTargets...)
}
}
diff --git a/java/java_test.go b/java/java_test.go
index 8ea34d9..1d07e70 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -142,9 +142,14 @@
return ctx, config
}
+func testJavaWithFS(t *testing.T, bp string, fs map[string][]byte) (*android.TestContext, android.Config) {
+ t.Helper()
+ return testJavaWithConfig(t, testConfig(nil, bp, fs))
+}
+
func testJava(t *testing.T, bp string) (*android.TestContext, android.Config) {
t.Helper()
- return testJavaWithConfig(t, testConfig(nil, bp, nil))
+ return testJavaWithFS(t, bp, nil)
}
func testJavaWithConfig(t *testing.T, config android.Config) (*android.TestContext, android.Config) {
@@ -461,7 +466,41 @@
t.Errorf("expected binary wrapper implicits [%q], got %v",
barJar, barWrapperDeps)
}
+}
+func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) {
+ bp := `
+ java_library {
+ name: "target_library",
+ srcs: ["a.java"],
+ }
+
+ java_binary_host {
+ name: "host_binary",
+ srcs: ["b.java"],
+ }
+ `
+ config := testConfig(nil, bp, nil)
+ config.TestProductVariables.MinimizeJavaDebugInfo = proptools.BoolPtr(true)
+
+ ctx, _ := testJavaWithConfig(t, config)
+
+ // first, sanity check that the -g flag is added to target modules
+ targetLibrary := ctx.ModuleForTests("target_library", "android_common")
+ targetJavaFlags := targetLibrary.Module().VariablesForTests()["javacFlags"]
+ if !strings.Contains(targetJavaFlags, "-g:source,lines") {
+ t.Errorf("target library javac flags %v should contain "+
+ "-g:source,lines override with MinimizeJavaDebugInfo", targetJavaFlags)
+ }
+
+ // check that -g is not overridden for host modules
+ buildOS := android.BuildOs.String()
+ hostBinary := ctx.ModuleForTests("host_binary", buildOS+"_common")
+ hostJavaFlags := hostBinary.Module().VariablesForTests()["javacFlags"]
+ if strings.Contains(hostJavaFlags, "-g:source,lines") {
+ t.Errorf("java_binary_host javac flags %v should not have "+
+ "-g:source,lines override with MinimizeJavaDebugInfo", hostJavaFlags)
+ }
}
func TestPrebuilts(t *testing.T) {
@@ -740,7 +779,7 @@
for _, test := range table {
t.Run(test.name, func(t *testing.T) {
- ctx, _ := testJava(t, `
+ ctx, _ := testJavaWithFS(t, `
java_library {
name: "foo",
srcs: [
@@ -750,7 +789,13 @@
],
`+test.prop+`,
}
- `+test.extra)
+ `+test.extra,
+ map[string][]byte{
+ "java-res/a/a": nil,
+ "java-res/b/b": nil,
+ "java-res2/a": nil,
+ },
+ )
foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar")
fooRes := ctx.ModuleForTests("foo", "android_common").Output("res/foo.jar")
@@ -769,7 +814,7 @@
}
func TestIncludeSrcs(t *testing.T) {
- ctx, _ := testJava(t, `
+ ctx, _ := testJavaWithFS(t, `
java_library {
name: "foo",
srcs: [
@@ -790,7 +835,11 @@
java_resource_dirs: ["java-res"],
include_srcs: true,
}
- `)
+ `, map[string][]byte{
+ "java-res/a/a": nil,
+ "java-res/b/b": nil,
+ "java-res2/a": nil,
+ })
// Test a library with include_srcs: true
foo := ctx.ModuleForTests("foo", "android_common").Output("withres/foo.jar")
@@ -832,7 +881,7 @@
}
func TestGeneratedSources(t *testing.T) {
- ctx, _ := testJava(t, `
+ ctx, _ := testJavaWithFS(t, `
java_library {
name: "foo",
srcs: [
@@ -847,7 +896,10 @@
tool_files: ["java-res/a"],
out: ["gen.java"],
}
- `)
+ `, map[string][]byte{
+ "a.java": nil,
+ "b.java": nil,
+ })
javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
genrule := ctx.ModuleForTests("gen", "").Rule("generator")
@@ -932,7 +984,7 @@
}
func TestDroiddoc(t *testing.T) {
- ctx, _ := testJava(t, `
+ ctx, _ := testJavaWithFS(t, `
droiddoc_exported_dir {
name: "droiddoc-templates-sdk",
path: ".",
@@ -945,7 +997,7 @@
droiddoc {
name: "bar-doc",
srcs: [
- "bar-doc/*.java",
+ "bar-doc/a.java",
"bar-doc/IFoo.aidl",
":bar-doc-aidl-srcs",
],
@@ -963,7 +1015,11 @@
todo_file: "libcore-docs-todo.html",
args: "-offlinemode -title \"libcore\"",
}
- `)
+ `,
+ map[string][]byte{
+ "bar-doc/a.java": nil,
+ "bar-doc/b.java": nil,
+ })
barDoc := ctx.ModuleForTests("bar-doc", "android_common").Rule("javadoc")
var javaSrcs []string
@@ -989,7 +1045,7 @@
droidstubs {
name: "stubs-source-system-modules",
srcs: [
- "bar-doc/*.java",
+ "bar-doc/a.java",
],
sdk_version: "none",
system_modules: "source-system-modules",
@@ -1010,7 +1066,7 @@
droidstubs {
name: "stubs-prebuilt-system-modules",
srcs: [
- "bar-doc/*.java",
+ "bar-doc/a.java",
],
sdk_version: "none",
system_modules: "prebuilt-system-modules",
@@ -1426,6 +1482,38 @@
`)
}
+func TestJavaSdkLibrary_ModuleLib(t *testing.T) {
+ testJava(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ system: {
+ enabled: true,
+ },
+ module_lib: {
+ enabled: true,
+ },
+ }
+ `)
+}
+
+func TestJavaSdkLibrary_SystemServer(t *testing.T) {
+ testJava(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ system: {
+ enabled: true,
+ },
+ system_server: {
+ enabled: true,
+ },
+ }
+ `)
+}
+
func TestJavaSdkLibrary_MissingScope(t *testing.T) {
testJavaError(t, `requires api scope module-lib from foo but it only has \[\] available`, `
java_sdk_library {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index de5ee03..503ad59 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -264,7 +264,7 @@
apiScopeModuleLib = initApiScope(&apiScope{
name: "module-lib",
extends: apiScopeSystem,
- // Module_lib scope is disabled by default in legacy mode.
+ // The module-lib scope is disabled by default in legacy mode.
//
// Enabling this would break existing usages.
legacyEnabledStatus: func(module *SdkLibrary) bool {
@@ -280,11 +280,34 @@
"--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES\\)",
},
})
+ apiScopeSystemServer = initApiScope(&apiScope{
+ name: "system-server",
+ extends: apiScopePublic,
+ // The system-server scope is disabled by default in legacy mode.
+ //
+ // Enabling this would break existing usages.
+ legacyEnabledStatus: func(module *SdkLibrary) bool {
+ return false
+ },
+ scopeSpecificProperties: func(module *SdkLibrary) *ApiScopeProperties {
+ return &module.sdkLibraryProperties.System_server
+ },
+ apiFilePrefix: "system-server-",
+ moduleSuffix: ".system_server",
+ sdkVersion: "system_server_current",
+ droidstubsArgs: []string{
+ "--show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.SYSTEM_SERVER\\) ",
+ "--hide-annotation android.annotation.Hide",
+ // com.android.* classes are okay in this interface"
+ "--hide InternalClasses",
+ },
+ })
allApiScopes = apiScopes{
apiScopePublic,
apiScopeSystem,
apiScopeTest,
apiScopeModuleLib,
+ apiScopeSystemServer,
}
)
@@ -429,12 +452,18 @@
// In non-legacy mode the test api scope is disabled by default.
Test ApiScopeProperties
- // The properties specific to the module_lib api scope
+ // The properties specific to the module-lib api scope
//
- // Unless explicitly specified by using test.enabled the module_lib api scope is
+ // Unless explicitly specified by using test.enabled the module-lib api scope is
// disabled by default.
Module_lib ApiScopeProperties
+ // The properties specific to the system-server api scope
+ //
+ // Unless explicitly specified by using test.enabled the module-lib api scope is
+ // disabled by default.
+ System_server ApiScopeProperties
+
// Determines if the stubs are preferred over the implementation library
// for linking, even when the client doesn't specify sdk_version. When this
// is set to true, such clients are provided with the widest API surface that
@@ -600,6 +629,16 @@
return true
}
+// Module name of the runtime implementation library
+func (c *commonToSdkLibraryAndImport) implLibraryModuleName() string {
+ return c.moduleBase.BaseModuleName() + ".impl"
+}
+
+// Module name of the XML file for the lib
+func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string {
+ return c.moduleBase.BaseModuleName() + sdkXmlFileSuffix
+}
+
// Name of the java_library module that compiles the stubs source.
func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string {
return c.namingScheme.stubsLibraryModuleName(apiScope, c.moduleBase.BaseModuleName())
@@ -743,6 +782,8 @@
apiScope = apiScopeModuleLib
case sdkTest:
apiScope = apiScopeTest
+ case sdkSystemServer:
+ apiScope = apiScopeSystemServer
default:
apiScope = apiScopePublic
}
@@ -827,7 +868,7 @@
var _ SdkLibraryComponentDependency = (*Library)(nil)
var _ SdkLibraryComponentDependency = (*Import)(nil)
var _ SdkLibraryComponentDependency = (*SdkLibrary)(nil)
-var _ SdkLibraryComponentDependency = (*sdkLibraryImport)(nil)
+var _ SdkLibraryComponentDependency = (*SdkLibraryImport)(nil)
// Provides access to sdk_version related header and implentation jars.
type SdkLibraryDependency interface {
@@ -913,16 +954,24 @@
return generatedScopes
}
-var xmlPermissionsFileTag = dependencyTag{name: "xml-permissions-file"}
+type sdkLibraryComponentTag struct {
+ blueprint.BaseDependencyTag
+ name string
+}
+
+// Mark this tag so dependencies that use it are excluded from visibility enforcement.
+func (t sdkLibraryComponentTag) ExcludeFromVisibilityEnforcement() {}
+
+var xmlPermissionsFileTag = sdkLibraryComponentTag{name: "xml-permissions-file"}
func IsXmlPermissionsFileDepTag(depTag blueprint.DependencyTag) bool {
- if dt, ok := depTag.(dependencyTag); ok {
+ if dt, ok := depTag.(sdkLibraryComponentTag); ok {
return dt == xmlPermissionsFileTag
}
return false
}
-var implLibraryTag = dependencyTag{name: "impl-library"}
+var implLibraryTag = sdkLibraryComponentTag{name: "impl-library"}
func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
for _, apiScope := range module.getGeneratedApiScopes(ctx) {
@@ -947,7 +996,7 @@
if module.sharedLibrary() {
// Add dependency to the rule for generating the xml permissions file
- ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlFileName())
+ ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlPermissionsModuleName())
}
// Only add the deps for the library if it is actually going to be built.
@@ -994,20 +1043,10 @@
}
entriesList := module.Library.AndroidMkEntries()
entries := &entriesList[0]
- entries.Required = append(entries.Required, module.xmlFileName())
+ entries.Required = append(entries.Required, module.xmlPermissionsModuleName())
return entriesList
}
-// Module name of the runtime implementation library
-func (module *SdkLibrary) implLibraryModuleName() string {
- return module.BaseModuleName() + ".impl"
-}
-
-// Module name of the XML file for the lib
-func (module *SdkLibrary) xmlFileName() string {
- return module.BaseModuleName() + sdkXmlFileSuffix
-}
-
// The dist path of the stub artifacts
func (module *SdkLibrary) apiDistPath(apiScope *apiScope) string {
if module.ModuleBase.Owner() != "" {
@@ -1298,7 +1337,7 @@
Lib_name *string
Apex_available []string
}{
- Name: proptools.StringPtr(module.xmlFileName()),
+ Name: proptools.StringPtr(module.xmlPermissionsModuleName()),
Lib_name: proptools.StringPtr(module.BaseModuleName()),
Apex_available: module.ApexProperties.Apex_available,
}
@@ -1346,7 +1385,7 @@
//
// If either this or the other module are on the platform then this will return
// false.
-func (module *SdkLibrary) withinSameApexAs(other android.Module) bool {
+func withinSameApexAs(module android.ApexModule, other android.Module) bool {
name := module.ApexName()
return name != "" && getApexNameForModule(other) == name
}
@@ -1367,7 +1406,7 @@
// Only allow access to the implementation library in the following condition:
// * No sdk_version specified on the referencing module.
// * The referencing module is in the same apex as this.
- if sdkVersion.kind == sdkPrivate || module.withinSameApexAs(ctx.Module()) {
+ if sdkVersion.kind == sdkPrivate || withinSameApexAs(module, ctx.Module()) {
if headerJars {
return module.HeaderJars()
} else {
@@ -1671,7 +1710,7 @@
Libs []string
}
-type sdkLibraryImport struct {
+type SdkLibraryImport struct {
android.ModuleBase
android.DefaultableModuleBase
prebuilt android.Prebuilt
@@ -1684,9 +1723,17 @@
scopeProperties map[*apiScope]*sdkLibraryScopeProperties
commonToSdkLibraryAndImport
+
+ // The reference to the implementation library created by the source module.
+ // Is nil if the source module does not exist.
+ implLibraryModule *Library
+
+ // The reference to the xml permissions module created by the source module.
+ // Is nil if the source module does not exist.
+ xmlPermissionsFileModule *sdkLibraryXml
}
-var _ SdkLibraryDependency = (*sdkLibraryImport)(nil)
+var _ SdkLibraryDependency = (*SdkLibraryImport)(nil)
// The type of a structure that contains a field of type sdkLibraryScopeProperties
// for each apiscope in allApiScopes, e.g. something like:
@@ -1728,7 +1775,7 @@
// java_sdk_library_import imports a prebuilt java_sdk_library.
func sdkLibraryImportFactory() android.Module {
- module := &sdkLibraryImport{}
+ module := &SdkLibraryImport{}
allScopeProperties, scopeToProperties := createPropertiesInstance()
module.scopeProperties = scopeToProperties
@@ -1750,15 +1797,15 @@
return module
}
-func (module *sdkLibraryImport) Prebuilt() *android.Prebuilt {
+func (module *SdkLibraryImport) Prebuilt() *android.Prebuilt {
return &module.prebuilt
}
-func (module *sdkLibraryImport) Name() string {
+func (module *SdkLibraryImport) Name() string {
return module.prebuilt.Name(module.ModuleBase.Name())
}
-func (module *sdkLibraryImport) createInternalModules(mctx android.DefaultableHookContext) {
+func (module *SdkLibraryImport) createInternalModules(mctx android.DefaultableHookContext) {
// If the build is configured to use prebuilts then force this to be preferred.
if mctx.Config().UnbundledBuildUsePrebuiltSdks() {
@@ -1783,7 +1830,7 @@
*javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
}
-func (module *sdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
// Creates a java import for the jar with ".stubs" suffix
props := struct {
Name *string
@@ -1805,7 +1852,7 @@
mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}
-func (module *sdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
props := struct {
Name *string
Srcs []string
@@ -1819,7 +1866,7 @@
props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
}
-func (module *sdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) {
+func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) {
for apiScope, scopeProperties := range module.scopeProperties {
if len(scopeProperties.Jars) == 0 {
continue
@@ -1833,13 +1880,35 @@
ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, module.stubsSourceModuleName(apiScope))
}
}
+
+ implName := module.implLibraryModuleName()
+ if ctx.OtherModuleExists(implName) {
+ ctx.AddVariationDependencies(nil, implLibraryTag, implName)
+
+ xmlPermissionsModuleName := module.xmlPermissionsModuleName()
+ if module.sharedLibrary() && ctx.OtherModuleExists(xmlPermissionsModuleName) {
+ // Add dependency to the rule for generating the xml permissions file
+ ctx.AddDependency(module, xmlPermissionsFileTag, xmlPermissionsModuleName)
+ }
+ }
}
-func (module *sdkLibraryImport) OutputFiles(tag string) (android.Paths, error) {
+func (module *SdkLibraryImport) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool {
+ depTag := mctx.OtherModuleDependencyTag(dep)
+ if depTag == xmlPermissionsFileTag {
+ return true
+ }
+
+ // None of the other dependencies of the java_sdk_library_import are in the same apex
+ // as the one that references this module.
+ return false
+}
+
+func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) {
return module.commonOutputFiles(tag)
}
-func (module *sdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Record the paths to the prebuilt stubs library and stubs source.
ctx.VisitDirectDeps(func(to android.Module) {
tag := ctx.OtherModuleDependencyTag(to)
@@ -1852,6 +1921,18 @@
// Extract information from the dependency. The exact information extracted
// is determined by the nature of the dependency which is determined by the tag.
scopeTag.extractDepInfo(ctx, to, scopePaths)
+ } else if tag == implLibraryTag {
+ if implLibrary, ok := to.(*Library); ok {
+ module.implLibraryModule = implLibrary
+ } else {
+ ctx.ModuleErrorf("implementation library must be of type *java.Library but was %T", to)
+ }
+ } else if tag == xmlPermissionsFileTag {
+ if xmlPermissionsFileModule, ok := to.(*sdkLibraryXml); ok {
+ module.xmlPermissionsFileModule = xmlPermissionsFileModule
+ } else {
+ ctx.ModuleErrorf("xml permissions file module must be of type *sdkLibraryXml but was %T", to)
+ }
}
})
@@ -1867,20 +1948,55 @@
}
}
-func (module *sdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
+func (module *SdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec, headerJars bool) android.Paths {
+
+ // For consistency with SdkLibrary make the implementation jar available to libraries that
+ // are within the same APEX.
+ implLibraryModule := module.implLibraryModule
+ if implLibraryModule != nil && withinSameApexAs(module, ctx.Module()) {
+ if headerJars {
+ return implLibraryModule.HeaderJars()
+ } else {
+ return implLibraryModule.ImplementationJars()
+ }
+ }
+
return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion)
}
// to satisfy SdkLibraryDependency interface
-func (module *sdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
+func (module *SdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
// This module is just a wrapper for the prebuilt stubs.
- return module.sdkJars(ctx, sdkVersion)
+ return module.sdkJars(ctx, sdkVersion, true)
}
// to satisfy SdkLibraryDependency interface
-func (module *sdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
+func (module *SdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
// This module is just a wrapper for the stubs.
- return module.sdkJars(ctx, sdkVersion)
+ return module.sdkJars(ctx, sdkVersion, false)
+}
+
+// to satisfy apex.javaDependency interface
+func (module *SdkLibraryImport) DexJarBuildPath() android.Path {
+ if module.implLibraryModule == nil {
+ return nil
+ } else {
+ return module.implLibraryModule.DexJarBuildPath()
+ }
+}
+
+// to satisfy apex.javaDependency interface
+func (module *SdkLibraryImport) JacocoReportClassesFile() android.Path {
+ if module.implLibraryModule == nil {
+ return nil
+ } else {
+ return module.implLibraryModule.JacocoReportClassesFile()
+ }
+}
+
+// to satisfy apex.javaDependency interface
+func (module *SdkLibraryImport) Stem() string {
+ return module.BaseModuleName()
}
//
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 52d2df5..e5d322c 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -156,9 +156,9 @@
{
name: "nostdlib system_modules",
- properties: `sdk_version: "none", system_modules: "core-platform-api-stubs-system-modules"`,
- system: "core-platform-api-stubs-system-modules",
- bootclasspath: []string{"core-platform-api-stubs-system-modules-lib"},
+ properties: `sdk_version: "none", system_modules: "legacy-core-platform-api-stubs-system-modules"`,
+ system: "legacy-core-platform-api-stubs-system-modules",
+ bootclasspath: []string{"legacy-core-platform-api-stubs-system-modules-lib"},
java8classpath: []string{},
},
{
diff --git a/java/testing.go b/java/testing.go
index faf4d32..6fc10da 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -25,35 +25,12 @@
bp += GatherRequiredDepsForTest()
mockFS := map[string][]byte{
- "a.java": nil,
- "b.java": nil,
- "c.java": nil,
- "b.kt": nil,
- "a.jar": nil,
- "b.jar": nil,
- "c.jar": nil,
- "APP_NOTICE": nil,
- "GENRULE_NOTICE": nil,
- "LIB_NOTICE": nil,
- "TOOL_NOTICE": nil,
- "AndroidTest.xml": nil,
- "java-res/a/a": nil,
- "java-res/b/b": nil,
- "java-res2/a": nil,
- "java-fg/a.java": nil,
- "java-fg/b.java": nil,
- "java-fg/c.java": nil,
"api/current.txt": nil,
"api/removed.txt": nil,
"api/system-current.txt": nil,
"api/system-removed.txt": nil,
"api/test-current.txt": nil,
"api/test-removed.txt": nil,
- "framework/aidl/a.aidl": nil,
- "aidl/foo/IFoo.aidl": nil,
- "aidl/bar/IBar.aidl": nil,
- "assets_a/a": nil,
- "assets_b/b": nil,
"prebuilts/sdk/14/public/android.jar": nil,
"prebuilts/sdk/14/public/framework.aidl": nil,
@@ -104,44 +81,12 @@
"prebuilts/sdk/tools/core-lambda-stubs.jar": nil,
"prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"],}`),
- "prebuilts/apk/app.apk": nil,
- "prebuilts/apk/app_arm.apk": nil,
- "prebuilts/apk/app_arm64.apk": nil,
- "prebuilts/apk/app_xhdpi.apk": nil,
- "prebuilts/apk/app_xxhdpi.apk": nil,
-
- "prebuilts/apks/app.apks": nil,
-
- // For framework-res, which is an implicit dependency for framework
- "AndroidManifest.xml": nil,
- "build/make/target/product/security/testkey": nil,
-
- "build/soong/scripts/jar-wrapper.sh": nil,
-
- "build/make/core/verify_uses_libraries.sh": nil,
-
- "build/make/core/proguard.flags": nil,
- "build/make/core/proguard_basic_keeps.flags": nil,
-
- "jdk8/jre/lib/jce.jar": nil,
- "jdk8/jre/lib/rt.jar": nil,
- "jdk8/lib/tools.jar": nil,
-
- "bar-doc/a.java": nil,
- "bar-doc/b.java": nil,
- "bar-doc/IFoo.aidl": nil,
- "bar-doc/IBar.aidl": nil,
- "bar-doc/known_oj_tags.txt": nil,
- "external/doclava/templates-sdk": nil,
-
- "cert/new_cert.x509.pem": nil,
- "cert/new_cert.pk8": nil,
- "lineage.bin": nil,
-
- "testdata/data": nil,
-
- "stubs-sources/foo/Foo.java": nil,
- "stubs/sources/foo/Foo.java": nil,
+ // For java_sdk_library
+ "api/module-lib-current.txt": nil,
+ "api/module-lib-removed.txt": nil,
+ "api/system-server-current.txt": nil,
+ "api/system-server-removed.txt": nil,
+ "build/soong/scripts/gen-java-current-api-files.sh": nil,
}
cc.GatherRequiredFilesForTest(mockFS)
@@ -173,7 +118,8 @@
"android_module_lib_stubs_current",
"android_system_server_stubs_current",
"core.current.stubs",
- "core.platform.api.stubs",
+ "legacy.core.platform.api.stubs",
+ "stable.core.platform.api.stubs",
"kotlin-stdlib",
"kotlin-stdlib-jdk7",
"kotlin-stdlib-jdk8",
@@ -186,7 +132,7 @@
name: "%s",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "core-platform-api-stubs-system-modules",
+ system_modules: "legacy-core-platform-api-stubs-system-modules",
}
`, extra)
}
@@ -196,7 +142,7 @@
name: "framework",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "core-platform-api-stubs-system-modules",
+ system_modules: "legacy-core-platform-api-stubs-system-modules",
aidl: {
export_include_dirs: ["framework/aidl"],
},
@@ -211,7 +157,7 @@
name: "android.hidl.base-V1.0-java",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "core-platform-api-stubs-system-modules",
+ system_modules: "legacy-core-platform-api-stubs-system-modules",
installable: true,
}
@@ -219,7 +165,7 @@
name: "android.hidl.manager-V1.0-java",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "core-platform-api-stubs-system-modules",
+ system_modules: "legacy-core-platform-api-stubs-system-modules",
installable: true,
}
@@ -227,7 +173,7 @@
name: "org.apache.http.legacy",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "core-platform-api-stubs-system-modules",
+ system_modules: "legacy-core-platform-api-stubs-system-modules",
installable: true,
}
@@ -235,7 +181,7 @@
name: "android.test.base",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "core-platform-api-stubs-system-modules",
+ system_modules: "legacy-core-platform-api-stubs-system-modules",
installable: true,
}
@@ -243,14 +189,14 @@
name: "android.test.mock",
srcs: ["a.java"],
sdk_version: "none",
- system_modules: "core-platform-api-stubs-system-modules",
+ system_modules: "legacy-core-platform-api-stubs-system-modules",
installable: true,
}
`
systemModules := []string{
"core-current-stubs-system-modules",
- "core-platform-api-stubs-system-modules",
+ "legacy-core-platform-api-stubs-system-modules",
}
for _, extra := range systemModules {
diff --git a/python/androidmk.go b/python/androidmk.go
index d293d52..247b80d 100644
--- a/python/androidmk.go
+++ b/python/androidmk.go
@@ -66,15 +66,9 @@
fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=",
strings.Join(p.binaryDecorator.binaryProperties.Test_suites, " "))
}
- // If the test config has an explicit config specified use it.
- if p.testProperties.Test_config != nil {
- fmt.Fprintln(w, "LOCAL_TEST_CONFIG :=",
- *p.testProperties.Test_config)
- } else {
- if p.testConfig != nil {
- fmt.Fprintln(w, "LOCAL_FULL_TEST_CONFIG :=",
- p.testConfig.String())
- }
+ if p.testConfig != nil {
+ fmt.Fprintln(w, "LOCAL_FULL_TEST_CONFIG :=",
+ p.testConfig.String())
}
if !BoolDefault(p.binaryProperties.Auto_gen_config, true) {
diff --git a/python/test.go b/python/test.go
index f684fd5..a669c73 100644
--- a/python/test.go
+++ b/python/test.go
@@ -29,11 +29,11 @@
type TestProperties struct {
// the name of the test configuration (for example "AndroidTest.xml") that should be
// installed with the module.
- Test_config *string `android:"arch_variant"`
+ Test_config *string `android:"path,arch_variant"`
// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
// should be installed with the module.
- Test_config_template *string `android:"arch_variant"`
+ Test_config_template *string `android:"path,arch_variant"`
}
type testDecorator struct {
diff --git a/rust/Android.bp b/rust/Android.bp
index 684db0b..b06ea8e 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -16,6 +16,7 @@
"library.go",
"prebuilt.go",
"proc_macro.go",
+ "project_json.go",
"rust.go",
"test.go",
"testing.go",
@@ -25,6 +26,7 @@
"compiler_test.go",
"coverage_test.go",
"library_test.go",
+ "project_json_test.go",
"rust_test.go",
"test_test.go",
],
diff --git a/rust/OWNERS b/rust/OWNERS
index 82713f9..afd06e4 100644
--- a/rust/OWNERS
+++ b/rust/OWNERS
@@ -1,5 +1,5 @@
# Additional owner/reviewers for rust rules, including parent directory owners.
per-file * = chh@google.com, ivanlozano@google.com, jeffv@google.com, srhines@google.com
-# Limited owners/reviewers of the whitelist.
-per-file whitelist.go = chh@google.com, ivanlozano@google.com, jeffv@google.com, jgalenson@google.com, srhines@google.com
+# Limited owners/reviewers of the allowed list.
+per-file allowed_list.go = chh@google.com, ivanlozano@google.com, jeffv@google.com, jgalenson@google.com, srhines@google.com
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 0e2bea3..69d0df5 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -99,7 +99,6 @@
func (test *testDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
test.binaryDecorator.AndroidMk(ctx, ret)
ret.Class = "NATIVE_TESTS"
- ret.SubName = test.getMutatedModuleSubName(ctx.Name())
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
if len(test.Properties.Test_suites) > 0 {
fmt.Fprintln(w, "LOCAL_COMPATIBILITY_SUITE :=",
diff --git a/rust/builder.go b/rust/builder.go
index fbe0e53..5069b07 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -21,6 +21,7 @@
"github.com/google/blueprint/pathtools"
"android/soong/android"
+ "android/soong/cc"
)
var (
@@ -161,11 +162,17 @@
if flags.Coverage {
var gcnoFile android.WritablePath
+ // Provide consistency with cc gcda output, see cc/builder.go init()
+ profileEmitArg := strings.TrimPrefix("PWD=", cc.PwdPrefix()) + "/"
if outputFile.Ext() != "" {
gcnoFile = android.PathForModuleOut(ctx, pathtools.ReplaceExtension(outputFile.Base(), "gcno"))
+ rustcFlags = append(rustcFlags, "-Z profile-emit="+profileEmitArg+android.PathForModuleOut(
+ ctx, pathtools.ReplaceExtension(outputFile.Base(), "gcda")).String())
} else {
gcnoFile = android.PathForModuleOut(ctx, outputFile.Base()+".gcno")
+ rustcFlags = append(rustcFlags, "-Z profile-emit="+profileEmitArg+android.PathForModuleOut(
+ ctx, outputFile.Base()+".gcda").String())
}
implicitOutputs = append(implicitOutputs, gcnoFile)
diff --git a/rust/config/Android.bp b/rust/config/Android.bp
index 1a10312..5026da3 100644
--- a/rust/config/Android.bp
+++ b/rust/config/Android.bp
@@ -10,7 +10,7 @@
"arm64_device.go",
"global.go",
"toolchain.go",
- "whitelist.go",
+ "allowed_list.go",
"x86_darwin_host.go",
"x86_linux_host.go",
"x86_device.go",
diff --git a/rust/config/whitelist.go b/rust/config/allowed_list.go
similarity index 100%
rename from rust/config/whitelist.go
rename to rust/config/allowed_list.go
diff --git a/rust/library.go b/rust/library.go
index 8aa033c..2e51266 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -329,12 +329,21 @@
return deps
}
+
+func (library *libraryDecorator) sharedLibFilename(ctx ModuleContext) string {
+ return library.getStem(ctx) + ctx.toolchain().SharedLibSuffix()
+}
+
func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
flags.RustFlags = append(flags.RustFlags, "-C metadata="+ctx.baseModuleName())
flags = library.baseCompiler.compilerFlags(ctx, flags)
if library.shared() || library.static() {
library.includeDirs = append(library.includeDirs, android.PathsForModuleSrc(ctx, library.Properties.Include_dirs)...)
}
+ if library.shared() {
+ flags.LinkFlags = append(flags.LinkFlags, "-Wl,-soname="+library.sharedLibFilename(ctx))
+ }
+
return flags
}
@@ -371,7 +380,7 @@
outputs := TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
library.coverageFile = outputs.coverageFile
} else if library.shared() {
- fileName := library.getStem(ctx) + ctx.toolchain().SharedLibSuffix()
+ fileName := library.sharedLibFilename(ctx)
outputFile = android.PathForModuleOut(ctx, fileName)
outputs := TransformSrctoShared(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
diff --git a/rust/library_test.go b/rust/library_test.go
index 9f9f374..37dd541 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -114,3 +114,17 @@
}`)
}
+
+func TestSharedLibraryFlags(t *testing.T) {
+ ctx := testRust(t, `
+ rust_library_host {
+ name: "libfoo",
+ srcs: ["foo.rs"],
+ crate_name: "foo",
+ }`)
+
+ libfooShared := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_shared").Output("libfoo.so")
+ if !strings.Contains(libfooShared.Args["linkFlags"], "-Wl,-soname=libfoo.so") {
+ t.Errorf("missing expected -Wl,-soname linker flag for libfoo shared lib, linkFlags: %#v", libfooShared.Args["linkFlags"])
+ }
+}
diff --git a/rust/project_json.go b/rust/project_json.go
new file mode 100644
index 0000000..909aebc
--- /dev/null
+++ b/rust/project_json.go
@@ -0,0 +1,161 @@
+// 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 rust
+
+import (
+ "encoding/json"
+ "fmt"
+ "path"
+
+ "android/soong/android"
+)
+
+// This singleton collects Rust crate definitions and generates a JSON file
+// (${OUT_DIR}/soong/rust-project.json) which can be use by external tools,
+// such as rust-analyzer. It does so when either make, mm, mma, mmm or mmma is
+// called. This singleton is enabled only if SOONG_GEN_RUST_PROJECT is set.
+// For example,
+//
+// $ SOONG_GEN_RUST_PROJECT=1 m nothing
+
+func init() {
+ android.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
+}
+
+func rustProjectGeneratorSingleton() android.Singleton {
+ return &projectGeneratorSingleton{}
+}
+
+type projectGeneratorSingleton struct{}
+
+const (
+ // Environment variables used to control the behavior of this singleton.
+ envVariableCollectRustDeps = "SOONG_GEN_RUST_PROJECT"
+ rustProjectJsonFileName = "rust-project.json"
+)
+
+// The format of rust-project.json is not yet finalized. A current description is available at:
+// https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/manual.adoc#non-cargo-based-projects
+type rustProjectDep struct {
+ Crate int `json:"crate"`
+ Name string `json:"name"`
+}
+
+type rustProjectCrate struct {
+ RootModule string `json:"root_module"`
+ Edition string `json:"edition,omitempty"`
+ Deps []rustProjectDep `json:"deps"`
+ Cfgs []string `json:"cfgs"`
+}
+
+type rustProjectJson struct {
+ Roots []string `json:"roots"`
+ Crates []rustProjectCrate `json:"crates"`
+}
+
+// crateInfo is used during the processing to keep track of the known crates.
+type crateInfo struct {
+ ID int
+ Deps map[string]int
+}
+
+func mergeDependencies(ctx android.SingletonContext, project *rustProjectJson,
+ knownCrates map[string]crateInfo, module android.Module,
+ crate *rustProjectCrate, deps map[string]int) {
+
+ //TODO(tweek): The stdlib dependencies do not appear here. We need to manually add them.
+ ctx.VisitDirectDeps(module, func(child android.Module) {
+ childId, childName, ok := appendLibraryAndDeps(ctx, project, knownCrates, child)
+ if !ok {
+ return
+ }
+ if _, ok = deps[childName]; ok {
+ return
+ }
+ crate.Deps = append(crate.Deps, rustProjectDep{Crate: childId, Name: childName})
+ deps[childName] = childId
+ })
+}
+
+// appendLibraryAndDeps creates a rustProjectCrate for the module argument and
+// appends it to the rustProjectJson struct. It visits the dependencies of the
+// module depth-first. If the current module is already in knownCrates, its
+// its dependencies are merged. Returns a tuple (id, crate_name, ok).
+func appendLibraryAndDeps(ctx android.SingletonContext, project *rustProjectJson,
+ knownCrates map[string]crateInfo, module android.Module) (int, string, bool) {
+ rModule, ok := module.(*Module)
+ if !ok {
+ return 0, "", false
+ }
+ if rModule.compiler == nil {
+ return 0, "", false
+ }
+ rustLib, ok := rModule.compiler.(*libraryDecorator)
+ if !ok {
+ return 0, "", false
+ }
+ crateName := rModule.CrateName()
+ if cInfo, ok := knownCrates[crateName]; ok {
+ // We have seen this crate already; merge any new dependencies.
+ crate := project.Crates[cInfo.ID]
+ mergeDependencies(ctx, project, knownCrates, module, &crate, cInfo.Deps)
+ return cInfo.ID, crateName, true
+ }
+ crate := rustProjectCrate{Deps: make([]rustProjectDep, 0), Cfgs: make([]string, 0)}
+ src := rustLib.Properties.Srcs[0]
+ crate.RootModule = path.Join(ctx.ModuleDir(rModule), src)
+ crate.Edition = getEdition(rustLib.baseCompiler)
+
+ deps := make(map[string]int)
+ mergeDependencies(ctx, project, knownCrates, module, &crate, deps)
+
+ id := len(project.Crates)
+ knownCrates[crateName] = crateInfo{ID: id, Deps: deps}
+ project.Crates = append(project.Crates, crate)
+ // rust-analyzer requires that all crates belong to at least one root:
+ // https://github.com/rust-analyzer/rust-analyzer/issues/4735.
+ project.Roots = append(project.Roots, path.Dir(crate.RootModule))
+ return id, crateName, true
+}
+
+func (r *projectGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ if !ctx.Config().IsEnvTrue(envVariableCollectRustDeps) {
+ return
+ }
+
+ project := rustProjectJson{}
+ knownCrates := make(map[string]crateInfo)
+ ctx.VisitAllModules(func(module android.Module) {
+ appendLibraryAndDeps(ctx, &project, knownCrates, module)
+ })
+
+ path := android.PathForOutput(ctx, rustProjectJsonFileName)
+ err := createJsonFile(project, path)
+ if err != nil {
+ ctx.Errorf(err.Error())
+ }
+}
+
+func createJsonFile(project rustProjectJson, rustProjectPath android.WritablePath) error {
+ buf, err := json.MarshalIndent(project, "", " ")
+ if err != nil {
+ return fmt.Errorf("JSON marshal of rustProjectJson failed: %s", err)
+ }
+ err = android.WriteFileToOutputDir(rustProjectPath, buf, 0666)
+ if err != nil {
+ return fmt.Errorf("Writing rust-project to %s failed: %s", rustProjectPath.String(), err)
+ }
+ return nil
+}
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
new file mode 100644
index 0000000..6786e72
--- /dev/null
+++ b/rust/project_json_test.go
@@ -0,0 +1,55 @@
+// 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 rust
+
+import (
+ "io/ioutil"
+ "path/filepath"
+ "testing"
+
+ "android/soong/android"
+ "android/soong/cc"
+)
+
+func TestProjectJson(t *testing.T) {
+ bp := `rust_library {
+ name: "liba",
+ srcs: ["src/lib.rs"],
+ crate_name: "a"
+ }` + GatherRequiredDepsForTest()
+ env := map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}
+ fs := map[string][]byte{
+ "foo.rs": nil,
+ "src/lib.rs": nil,
+ }
+
+ cc.GatherRequiredFilesForTest(fs)
+
+ config := android.TestArchConfig(buildDir, env, bp, fs)
+ ctx := CreateTestContext()
+ ctx.Register(config)
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ android.FailIfErrored(t, errs)
+
+ // The JSON file is generated via WriteFileToOutputDir. Therefore, it
+ // won't appear in the Output of the TestingSingleton. Manually verify
+ // it exists.
+ _, err := ioutil.ReadFile(filepath.Join(buildDir, "rust-project.json"))
+ if err != nil {
+ t.Errorf("rust-project.json has not been generated")
+ }
+}
diff --git a/rust/rust.go b/rust/rust.go
index 8cf2e6d..6671dd3 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -39,7 +39,6 @@
android.RegisterModuleType("rust_defaults", defaultsFactory)
android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
- ctx.BottomUp("rust_unit_tests", TestPerSrcMutator).Parallel()
ctx.BottomUp("rust_begin", BeginMutator).Parallel()
})
pctx.Import("android/soong/rust/config")
diff --git a/rust/rust_test.go b/rust/rust_test.go
index d658ee2..fe21e3a 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -89,7 +89,7 @@
if coverage {
config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
- config.TestProductVariables.CoveragePaths = []string{"*"}
+ config.TestProductVariables.NativeCoveragePaths = []string{"*"}
}
t.Helper()
diff --git a/rust/test.go b/rust/test.go
index 94568c1..f616c06 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -15,21 +15,23 @@
package rust
import (
- "path/filepath"
- "strings"
-
"android/soong/android"
"android/soong/tradefed"
)
type TestProperties struct {
+ // Disables the creation of a test-specific directory when used with
+ // relative_install_path. Useful if several tests need to be in the same
+ // directory, but test_per_src doesn't work.
+ No_named_install_directory *bool
+
// the name of the test configuration (for example "AndroidTest.xml") that should be
// installed with the module.
- Test_config *string `android:"arch_variant"`
+ Test_config *string `android:"path,arch_variant"`
// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
// should be installed with the module.
- Test_config_template *string `android:"arch_variant"`
+ Test_config_template *string `android:"path,arch_variant"`
// list of compatibility suites (for example "cts", "vts") that the module should be
// installed into.
@@ -64,7 +66,7 @@
}
module.compiler = test
-
+ module.AddProperties(&test.Properties)
return module, test
}
@@ -72,36 +74,21 @@
return append(test.binaryDecorator.compilerProps(), &test.Properties)
}
-func (test *testDecorator) getMutatedModuleSubName(moduleName string) string {
- stem := String(test.baseCompiler.Properties.Stem)
- if stem != "" && !strings.HasSuffix(moduleName, "_"+stem) {
- // Avoid repeated suffix in the module name.
- return "_" + stem
- }
- return ""
-}
-
func (test *testDecorator) install(ctx ModuleContext, file android.Path) {
- name := ctx.ModuleName()
- path := test.baseCompiler.relativeInstallPath()
- // on device, use mutated module name
- name = name + test.getMutatedModuleSubName(name)
- if !ctx.Device() { // on host, use mutated module name + arch type + stem name
- stem := String(test.baseCompiler.Properties.Stem)
- if stem == "" {
- stem = name
- }
- name = filepath.Join(name, ctx.Arch().ArchType.String(), stem)
- }
- test.testConfig = tradefed.AutoGenRustTestConfig(ctx, name,
+ test.testConfig = tradefed.AutoGenRustTestConfig(ctx,
test.Properties.Test_config,
test.Properties.Test_config_template,
test.Properties.Test_suites,
+ nil,
test.Properties.Auto_gen_config)
+
// default relative install path is module name
- if path == "" {
+ if !Bool(test.Properties.No_named_install_directory) {
test.baseCompiler.relative = ctx.ModuleName()
+ } else if String(test.baseCompiler.Properties.Relative_install_path) == "" {
+ ctx.PropertyErrorf("no_named_install_directory", "Module install directory may only be disabled if relative_install_path is set")
}
+
test.binaryDecorator.install(ctx, file)
}
@@ -126,64 +113,3 @@
module, _ := NewRustTest(android.HostSupported)
return module.Init()
}
-
-func (test *testDecorator) testPerSrc() bool {
- return true
-}
-
-func (test *testDecorator) srcs() []string {
- return test.binaryDecorator.Properties.Srcs
-}
-
-func (test *testDecorator) setSrc(name, src string) {
- test.binaryDecorator.Properties.Srcs = []string{src}
- test.baseCompiler.Properties.Stem = StringPtr(name)
-}
-
-func (test *testDecorator) unsetSrc() {
- test.binaryDecorator.Properties.Srcs = nil
- test.baseCompiler.Properties.Stem = StringPtr("")
-}
-
-type testPerSrc interface {
- testPerSrc() bool
- srcs() []string
- setSrc(string, string)
- unsetSrc()
-}
-
-var _ testPerSrc = (*testDecorator)(nil)
-
-func TestPerSrcMutator(mctx android.BottomUpMutatorContext) {
- if m, ok := mctx.Module().(*Module); ok {
- if test, ok := m.compiler.(testPerSrc); ok {
- numTests := len(test.srcs())
- if test.testPerSrc() && numTests > 0 {
- if duplicate, found := android.CheckDuplicate(test.srcs()); found {
- mctx.PropertyErrorf("srcs", "found a duplicate entry %q", duplicate)
- return
- }
- // Rust compiler always compiles one source file at a time and
- // uses the crate name as output file name.
- // Cargo uses the test source file name as default crate name,
- // but that can be redefined.
- // So when there are multiple source files, the source file names will
- // be the output file names, but when there is only one test file,
- // use the crate name.
- testNames := make([]string, numTests)
- for i, src := range test.srcs() {
- testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
- }
- crateName := m.compiler.crateName()
- if numTests == 1 && crateName != "" {
- testNames[0] = crateName
- }
- // TODO(chh): Add an "all tests" variation like cc/test.go?
- tests := mctx.CreateLocalVariations(testNames...)
- for i, src := range test.srcs() {
- tests[i].(*Module).compiler.(testPerSrc).setSrc(testNames[i], src)
- }
- }
- }
- }
-}
diff --git a/rust/test_test.go b/rust/test_test.go
index f131c6e..2382b18 100644
--- a/rust/test_test.go
+++ b/rust/test_test.go
@@ -19,45 +19,17 @@
"testing"
)
-// Check if rust_test_host accepts multiple source files and applies --test flag.
func TestRustTest(t *testing.T) {
ctx := testRust(t, `
rust_test_host {
name: "my_test",
- srcs: ["foo.rs", "src/bar.rs"],
- crate_name: "new_test", // not used for multiple source files
- relative_install_path: "rust/my-test",
- }`)
-
- for _, name := range []string{"foo", "bar"} {
- testingModule := ctx.ModuleForTests("my_test", "linux_glibc_x86_64_"+name)
- testingBuildParams := testingModule.Output(name)
- rustcFlags := testingBuildParams.Args["rustcFlags"]
- if !strings.Contains(rustcFlags, "--test") {
- t.Errorf("%v missing --test flag, rustcFlags: %#v", name, rustcFlags)
- }
- outPath := "/my_test/linux_glibc_x86_64_" + name + "/" + name
- if !strings.Contains(testingBuildParams.Output.String(), outPath) {
- t.Errorf("wrong output: %v expect: %v", testingBuildParams.Output, outPath)
- }
- }
-}
-
-// crate_name is output file name, when there is only one source file.
-func TestRustTestSingleFile(t *testing.T) {
- ctx := testRust(t, `
- rust_test_host {
- name: "my-test",
srcs: ["foo.rs"],
- crate_name: "new_test",
- relative_install_path: "my-pkg",
}`)
- name := "new_test"
- testingModule := ctx.ModuleForTests("my-test", "linux_glibc_x86_64_"+name)
- outPath := "/my-test/linux_glibc_x86_64_" + name + "/" + name
- testingBuildParams := testingModule.Output(name)
- if !strings.Contains(testingBuildParams.Output.String(), outPath) {
- t.Errorf("wrong output: %v expect: %v", testingBuildParams.Output, outPath)
+ testingModule := ctx.ModuleForTests("my_test", "linux_glibc_x86_64")
+ expectedOut := "my_test/linux_glibc_x86_64/my_test"
+ outPath := testingModule.Output("my_test").Output.String()
+ if !strings.Contains(outPath, expectedOut) {
+ t.Errorf("wrong output path: %v; expected: %v", outPath, expectedOut)
}
}
diff --git a/rust/testing.go b/rust/testing.go
index 09008a8..4e186d3 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -97,9 +97,9 @@
ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
// rust mutators
ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
- ctx.BottomUp("rust_unit_tests", TestPerSrcMutator).Parallel()
ctx.BottomUp("rust_begin", BeginMutator).Parallel()
})
+ ctx.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
return ctx
}
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index f836ea9..df763c8 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -20,6 +20,7 @@
conscrypt-module-test-exports
conscrypt-module-host-exports
runtime-module-sdk
+ runtime-module-host-exports
)
# We want to create apex modules for all supported architectures.
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index af792f2..77a4e94 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -34,6 +34,8 @@
"api/test-removed.txt": nil,
"api/module-lib-current.txt": nil,
"api/module-lib-removed.txt": nil,
+ "api/system-server-current.txt": nil,
+ "api/system-server-removed.txt": nil,
"build/soong/scripts/gen-java-current-api-files.sh": nil,
}
@@ -43,10 +45,10 @@
name: "core-current-stubs-system-modules",
}
java_system_modules_import {
- name: "core-platform-api-stubs-system-modules",
+ name: "legacy-core-platform-api-stubs-system-modules",
}
java_import {
- name: "core.platform.api.stubs",
+ name: "legacy.core.platform.api.stubs",
}
java_import {
name: "android_stubs_current",
@@ -61,6 +63,9 @@
name: "android_module_lib_stubs_current",
}
java_import {
+ name: "android_system_server_stubs_current",
+}
+java_import {
name: "core-lambda-stubs",
sdk_version: "none",
}
@@ -1398,6 +1403,93 @@
)
}
+func TestSnapshotWithJavaSdkLibrary_SystemServer(t *testing.T) {
+ result := testSdkWithJava(t, `
+ sdk {
+ name: "mysdk",
+ java_sdk_libs: ["myjavalib"],
+ }
+
+ java_sdk_library {
+ name: "myjavalib",
+ apex_available: ["//apex_available:anyapex"],
+ srcs: ["Test.java"],
+ sdk_version: "current",
+ public: {
+ enabled: true,
+ },
+ system_server: {
+ enabled: true,
+ },
+ }
+ `)
+
+ result.CheckSnapshot("mysdk", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_sdk_library_import {
+ name: "mysdk_myjavalib@current",
+ sdk_member_name: "myjavalib",
+ apex_available: ["//apex_available:anyapex"],
+ shared_library: true,
+ public: {
+ jars: ["sdk_library/public/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
+ sdk_version: "current",
+ },
+ system_server: {
+ jars: ["sdk_library/system-server/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/system-server/myjavalib_stub_sources"],
+ current_api: "sdk_library/system-server/myjavalib.txt",
+ removed_api: "sdk_library/system-server/myjavalib-removed.txt",
+ sdk_version: "system_server_current",
+ },
+}
+
+java_sdk_library_import {
+ name: "myjavalib",
+ prefer: false,
+ apex_available: ["//apex_available:anyapex"],
+ shared_library: true,
+ public: {
+ jars: ["sdk_library/public/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
+ sdk_version: "current",
+ },
+ system_server: {
+ jars: ["sdk_library/system-server/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/system-server/myjavalib_stub_sources"],
+ current_api: "sdk_library/system-server/myjavalib.txt",
+ removed_api: "sdk_library/system-server/myjavalib-removed.txt",
+ sdk_version: "system_server_current",
+ },
+}
+
+sdk_snapshot {
+ name: "mysdk@current",
+ java_sdk_libs: ["mysdk_myjavalib@current"],
+}
+`),
+ checkAllCopyRules(`
+.intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.system_server/android_common/javac/myjavalib.stubs.system_server.jar -> sdk_library/system-server/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source.system_server/android_common/myjavalib.stubs.source.system_server_api.txt -> sdk_library/system-server/myjavalib.txt
+.intermediates/myjavalib.stubs.source.system_server/android_common/myjavalib.stubs.source.system_server_removed.txt -> sdk_library/system-server/myjavalib-removed.txt
+`),
+ checkMergeZips(
+ ".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
+ ".intermediates/mysdk/common_os/tmp/sdk_library/system-server/myjavalib_stub_sources.zip",
+ ),
+ )
+}
+
func TestSnapshotWithJavaSdkLibrary_NamingScheme(t *testing.T) {
result := testSdkWithJava(t, `
sdk {
diff --git a/sdk/update.go b/sdk/update.go
index 1ba5806..8241151 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -22,6 +22,7 @@
"android/soong/apex"
"android/soong/cc"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -700,8 +701,8 @@
if apexAware, ok := variant.(interface{ ApexAvailable() []string }); ok {
apexAvailable := apexAware.ApexAvailable()
- // Add in any white listed apex available settings.
- apexAvailable = append(apexAvailable, apex.WhitelistedApexAvailable(member.Name())...)
+ // Add in any baseline apex available settings.
+ apexAvailable = append(apexAvailable, apex.BaselineApexAvailable(member.Name())...)
if len(apexAvailable) > 0 {
// Remove duplicates and sort.
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 9276a62..7bb267d 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -70,7 +70,7 @@
// the name of the test configuration (for example "AndroidTest.xml") that should be
// installed with the module.
- Test_config *string `android:"arch_variant"`
+ Test_config *string `android:"path,arch_variant"`
// list of files or filegroup modules that provide data that should be installed alongside
// the test.
@@ -231,12 +231,8 @@
s.customAndroidMkEntries(entries)
entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", s.testProperties.Test_suites...)
- if s.testProperties.Test_config != nil {
- entries.SetString("LOCAL_TEST_CONFIG", proptools.String(s.testProperties.Test_config))
- } else {
- if s.testConfig != nil {
- entries.SetString("LOCAL_FULL_TEST_CONFIG", s.testConfig.String())
- }
+ if s.testConfig != nil {
+ entries.SetPath("LOCAL_FULL_TEST_CONFIG", s.testConfig)
}
for _, d := range s.data {
rel := d.Rel()
@@ -260,9 +256,6 @@
// executable binary to <partition>/bin.
func ShBinaryFactory() android.Module {
module := &ShBinary{}
- module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
- return class == android.Device && ctx.Config().DevicePrefer32BitExecutables()
- })
InitShBinaryModule(module)
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibFirst)
return module
diff --git a/tradefed/autogen.go b/tradefed/autogen.go
index 2829146..1cb874d 100644
--- a/tradefed/autogen.go
+++ b/tradefed/autogen.go
@@ -112,7 +112,7 @@
}
func autogenTemplateWithName(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config) {
- autogenTemplateWithNameAndOutputFile(ctx, ctx.ModuleName(), output, template, configs, "")
+ autogenTemplateWithNameAndOutputFile(ctx, name, output, template, configs, "")
}
func autogenTemplateWithNameAndOutputFile(ctx android.ModuleContext, name string, output android.WritablePath, template string, configs []Config, outputFileName string) {
@@ -220,19 +220,20 @@
return path
}
-func AutoGenRustTestConfig(ctx android.ModuleContext, name string, testConfigProp *string,
- testConfigTemplateProp *string, testSuites []string, autoGenConfig *bool) android.Path {
+func AutoGenRustTestConfig(ctx android.ModuleContext, testConfigProp *string,
+ testConfigTemplateProp *string, testSuites []string, config []Config, autoGenConfig *bool) android.Path {
path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp)
if autogenPath != nil {
- templatePathString := "${RustHostTestConfigTemplate}"
- if ctx.Device() {
- templatePathString = "${RustDeviceTestConfigTemplate}"
- }
templatePath := getTestConfigTemplate(ctx, testConfigTemplateProp)
if templatePath.Valid() {
- templatePathString = templatePath.String()
+ autogenTemplate(ctx, autogenPath, templatePath.String(), config)
+ } else {
+ if ctx.Device() {
+ autogenTemplate(ctx, autogenPath, "${RustDeviceTestConfigTemplate}", config)
+ } else {
+ autogenTemplate(ctx, autogenPath, "${RustHostTestConfigTemplate}", config)
+ }
}
- autogenTemplateWithName(ctx, name, autogenPath, templatePathString, nil)
return autogenPath
}
return path
diff --git a/ui/build/config.go b/ui/build/config.go
index 49f506e..c4bbad7 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -592,6 +592,7 @@
c.environ.Set("TARGET_BUILD_VARIANT", variant)
c.environ.Set("TARGET_BUILD_TYPE", "release")
c.environ.Unset("TARGET_BUILD_APPS")
+ c.environ.Unset("TARGET_BUILD_UNBUNDLED")
}
// Tapas configures the environment to build one or more unbundled apps,
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index 7dc4915..e229856 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -143,6 +143,7 @@
"TARGET_BUILD_VARIANT",
"TARGET_BUILD_TYPE",
"TARGET_BUILD_APPS",
+ "TARGET_BUILD_UNBUNDLED",
"TARGET_ARCH",
"TARGET_ARCH_VARIANT",
"TARGET_CPU_VARIANT",
@@ -187,6 +188,7 @@
"TARGET_PRODUCT",
"TARGET_BUILD_VARIANT",
"TARGET_BUILD_APPS",
+ "TARGET_BUILD_UNBUNDLED",
// compiler wrappers set up by make
"CC_WRAPPER",
diff --git a/ui/build/upload.go b/ui/build/upload.go
index 75a5e2f..3a23a80 100644
--- a/ui/build/upload.go
+++ b/ui/build/upload.go
@@ -23,6 +23,7 @@
"path/filepath"
"time"
+ "android/soong/ui/metrics"
"github.com/golang/protobuf/proto"
upload_proto "android/soong/ui/metrics/upload_proto"
@@ -32,11 +33,21 @@
uploadPbFilename = ".uploader.pb"
)
+var (
+ // For testing purpose
+ getTmpDir = ioutil.TempDir
+)
+
// UploadMetrics uploads a set of metrics files to a server for analysis. An
// uploader full path is required to be specified in order to upload the set
// of metrics files. This is accomplished by defining the ANDROID_ENABLE_METRICS_UPLOAD
-// environment variable.
-func UploadMetrics(ctx Context, config Config, buildStartedMilli int64, files ...string) {
+// environment variable. The metrics files are copied to a temporary directory
+// and the uploader is then executed in the background to allow the user to continue
+// working.
+func UploadMetrics(ctx Context, config Config, forceDumbOutput bool, buildStartedMilli int64, files ...string) {
+ ctx.BeginTrace(metrics.RunSetupTool, "upload_metrics")
+ defer ctx.EndTrace()
+
uploader := config.MetricsUploaderApp()
// No metrics to upload if the path to the uploader was not specified.
if uploader == "" {
@@ -56,6 +67,22 @@
return
}
+ // The temporary directory cannot be deleted as the metrics uploader is started
+ // in the background and requires to exist until the operation is done. The
+ // uploader can delete the directory as it is specified in the upload proto.
+ tmpDir, err := getTmpDir("", "upload_metrics")
+ if err != nil {
+ ctx.Fatalf("failed to create a temporary directory to store the list of metrics files: %v\n", err)
+ }
+
+ for i, src := range metricsFiles {
+ dst := filepath.Join(tmpDir, filepath.Base(src))
+ if _, err := copyFile(src, dst); err != nil {
+ ctx.Fatalf("failed to copy %q to %q: %v\n", src, dst, err)
+ }
+ metricsFiles[i] = dst
+ }
+
// For platform builds, the branch and target name is hardcoded to specific
// values for later extraction of the metrics in the data metrics pipeline.
data, err := proto.Marshal(&upload_proto.Upload{
@@ -64,17 +91,23 @@
BranchName: proto.String("developer-metrics"),
TargetName: proto.String("platform-build-systems-metrics"),
MetricsFiles: metricsFiles,
+ DirectoriesToDelete: []string{tmpDir},
})
if err != nil {
ctx.Fatalf("failed to marshal metrics upload proto buffer message: %v\n", err)
}
- pbFile := filepath.Join(config.OutDir(), uploadPbFilename)
+ pbFile := filepath.Join(tmpDir, uploadPbFilename)
if err := ioutil.WriteFile(pbFile, data, 0644); err != nil {
ctx.Fatalf("failed to write the marshaled metrics upload protobuf to %q: %v\n", pbFile, err)
}
- // Remove the upload file as it's not longer needed after it has been processed by the uploader.
- defer os.Remove(pbFile)
- Command(ctx, config, "upload metrics", uploader, "--upload-metrics", pbFile).RunAndStreamOrFatal()
+ // Start the uploader in the background as it takes several milliseconds to start the uploader
+ // and prepare the metrics for upload. This affects small commands like "lunch".
+ cmd := Command(ctx, config, "upload metrics", uploader, "--upload-metrics", pbFile)
+ if forceDumbOutput {
+ cmd.RunOrFatal()
+ } else {
+ cmd.RunAndStreamOrFatal()
+ }
}
diff --git a/ui/build/upload_test.go b/ui/build/upload_test.go
index adaa08d..c812730 100644
--- a/ui/build/upload_test.go
+++ b/ui/build/upload_test.go
@@ -15,6 +15,7 @@
package build
import (
+ "errors"
"io/ioutil"
"os"
"path/filepath"
@@ -61,6 +62,22 @@
}
defer os.RemoveAll(outDir)
+ // Supply our own getTmpDir to delete the temp dir once the test is done.
+ orgGetTmpDir := getTmpDir
+ getTmpDir = func(string, string) (string, error) {
+ retDir := filepath.Join(outDir, "tmp_upload_dir")
+ if err := os.Mkdir(retDir, 0755); err != nil {
+ t.Fatalf("failed to create temporary directory %q: %v", retDir, err)
+ }
+ return retDir, nil
+ }
+ defer func() { getTmpDir = orgGetTmpDir }()
+
+ metricsUploadDir := filepath.Join(outDir, ".metrics_uploader")
+ if err := os.Mkdir(metricsUploadDir, 0755); err != nil {
+ t.Fatalf("failed to create %q directory for oauth valid check: %v", metricsUploadDir, err)
+ }
+
var metricsFiles []string
if tt.createFiles {
for _, f := range tt.files {
@@ -80,41 +97,62 @@
buildDateTime: strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10),
}}
- UploadMetrics(ctx, config, 1591031903, metricsFiles...)
-
- if _, err := os.Stat(filepath.Join(outDir, uploadPbFilename)); err == nil {
- t.Error("got true, want false for upload protobuf file to exist")
- }
+ UploadMetrics(ctx, config, false, 1591031903, metricsFiles...)
})
}
}
func TestUploadMetricsErrors(t *testing.T) {
- expectedErr := "failed to write the marshaled"
- defer logger.Recover(func(err error) {
- got := err.Error()
- if !strings.Contains(got, expectedErr) {
- t.Errorf("got %q, want %q to be contained in error", got, expectedErr)
- }
- })
+ ctx := testContext()
+ tests := []struct {
+ description string
+ tmpDir string
+ tmpDirErr error
+ expectedErr string
+ }{{
+ description: "getTmpDir returned error",
+ tmpDirErr: errors.New("getTmpDir failed"),
+ expectedErr: "getTmpDir failed",
+ }, {
+ description: "copyFile operation error",
+ tmpDir: "/fake_dir",
+ expectedErr: "failed to copy",
+ }}
- outDir, err := ioutil.TempDir("", "")
- if err != nil {
- t.Fatalf("failed to create out directory: %v", outDir)
+ for _, tt := range tests {
+ t.Run(tt.description, func(t *testing.T) {
+ defer logger.Recover(func(err error) {
+ got := err.Error()
+ if !strings.Contains(got, tt.expectedErr) {
+ t.Errorf("got %q, want %q to be contained in error", got, tt.expectedErr)
+ }
+ })
+
+ outDir, err := ioutil.TempDir("", "")
+ if err != nil {
+ t.Fatalf("failed to create out directory: %v", outDir)
+ }
+ defer os.RemoveAll(outDir)
+
+ orgGetTmpDir := getTmpDir
+ getTmpDir = func(string, string) (string, error) {
+ return tt.tmpDir, tt.tmpDirErr
+ }
+ defer func() { getTmpDir = orgGetTmpDir }()
+
+ metricsFile := filepath.Join(outDir, "metrics_file_1")
+ if err := ioutil.WriteFile(metricsFile, []byte("test file"), 0644); err != nil {
+ t.Fatalf("failed to create a fake metrics file %q for uploading: %v", metricsFile, err)
+ }
+
+ config := Config{&configImpl{
+ environ: &Environment{
+ "ANDROID_ENABLE_METRICS_UPLOAD=fake",
+ "OUT_DIR=/bad",
+ }}}
+
+ UploadMetrics(ctx, config, true, 1591031903, metricsFile)
+ t.Errorf("got nil, expecting %q as a failure", tt.expectedErr)
+ })
}
- defer os.RemoveAll(outDir)
-
- metricsFile := filepath.Join(outDir, "metrics_file_1")
- if err := ioutil.WriteFile(metricsFile, []byte("test file"), 0644); err != nil {
- t.Fatalf("failed to create a fake metrics file %q for uploading: %v", metricsFile, err)
- }
-
- config := Config{&configImpl{
- environ: &Environment{
- "ANDROID_ENABLE_METRICS_UPLOAD=fake",
- "OUT_DIR=/bad",
- }}}
-
- UploadMetrics(testContext(), config, 1591031903, metricsFile)
- t.Errorf("got nil, expecting %q as a failure", expectedErr)
}
diff --git a/ui/build/util.go b/ui/build/util.go
index 75e6753..d44cd6d 100644
--- a/ui/build/util.go
+++ b/ui/build/util.go
@@ -15,6 +15,7 @@
package build
import (
+ "io"
"os"
"path/filepath"
"strings"
@@ -124,3 +125,20 @@
}
return str[:idx], str[idx+1:], true
}
+
+// copyFile copies a file from src to dst. filepath.Dir(dst) must exist.
+func copyFile(src, dst string) (int64, error) {
+ source, err := os.Open(src)
+ if err != nil {
+ return 0, err
+ }
+ defer source.Close()
+
+ destination, err := os.Create(dst)
+ if err != nil {
+ return 0, err
+ }
+ defer destination.Close()
+
+ return io.Copy(destination, source)
+}
diff --git a/ui/build/util_test.go b/ui/build/util_test.go
index 89bfc77..b22e997 100644
--- a/ui/build/util_test.go
+++ b/ui/build/util_test.go
@@ -15,6 +15,7 @@
package build
import (
+ "bytes"
"io/ioutil"
"os"
"path/filepath"
@@ -49,3 +50,72 @@
ensureEmptyDirectoriesExist(ctx, filepath.Join(tmpDir, "a"))
}
+
+func TestCopyFile(t *testing.T) {
+ tmpDir, err := ioutil.TempDir("", "test_copy_file")
+ if err != nil {
+ t.Fatalf("failed to create temporary directory to hold test text files: %v", err)
+ }
+ defer os.Remove(tmpDir)
+
+ data := []byte("fake data")
+ src := filepath.Join(tmpDir, "src.txt")
+ if err := ioutil.WriteFile(src, data, 0755); err != nil {
+ t.Fatalf("failed to create a src file %q for copying: %v", src, err)
+ }
+
+ dst := filepath.Join(tmpDir, "dst.txt")
+
+ l, err := copyFile(src, dst)
+ if err != nil {
+ t.Fatalf("got %v, expecting nil error on copyFile operation", err)
+ }
+
+ if l != int64(len(data)) {
+ t.Errorf("got %d, expecting %d for copied bytes", l, len(data))
+ }
+
+ dstData, err := ioutil.ReadFile(dst)
+ if err != nil {
+ t.Fatalf("got %v, expecting nil error reading dst %q file", err, dst)
+ }
+
+ if bytes.Compare(data, dstData) != 0 {
+ t.Errorf("got %q, expecting data %q from dst %q text file", string(data), string(dstData), dst)
+ }
+}
+
+func TestCopyFileErrors(t *testing.T) {
+ tmpDir, err := ioutil.TempDir("", "test_copy_file_errors")
+ if err != nil {
+ t.Fatalf("failed to create temporary directory to hold test text files: %v", err)
+ }
+ defer os.Remove(tmpDir)
+
+ srcExists := filepath.Join(tmpDir, "src_exist.txt")
+ if err := ioutil.WriteFile(srcExists, []byte("fake data"), 0755); err != nil {
+ t.Fatalf("failed to create a src file %q for copying: %v", srcExists, err)
+ }
+
+ tests := []struct {
+ description string
+ src string
+ dst string
+ }{{
+ description: "src file does not exist",
+ src: "/src/not/exist",
+ dst: "/dst/not/exist",
+ }, {
+ description: "dst directory does not exist",
+ src: srcExists,
+ dst: "/dst/not/exist",
+ }}
+
+ for _, tt := range tests {
+ t.Run(tt.description, func(t *testing.T) {
+ if _, err := copyFile(tt.src, tt.dst); err == nil {
+ t.Errorf("got nil, expecting error")
+ }
+ })
+ }
+}
diff --git a/ui/metrics/upload_proto/upload.pb.go b/ui/metrics/upload_proto/upload.pb.go
index 1b1e5e8..614d4c7 100644
--- a/ui/metrics/upload_proto/upload.pb.go
+++ b/ui/metrics/upload_proto/upload.pb.go
@@ -30,7 +30,10 @@
// The target name.
TargetName *string `protobuf:"bytes,4,opt,name=target_name,json=targetName" json:"target_name,omitempty"`
// A list of metrics filepaths to upload.
- MetricsFiles []string `protobuf:"bytes,5,rep,name=metrics_files,json=metricsFiles" json:"metrics_files,omitempty"`
+ MetricsFiles []string `protobuf:"bytes,5,rep,name=metrics_files,json=metricsFiles" json:"metrics_files,omitempty"`
+ // A list of directories to delete after the copy of metrics files
+ // is completed for uploading.
+ DirectoriesToDelete []string `protobuf:"bytes,6,rep,name=directories_to_delete,json=directoriesToDelete" json:"directories_to_delete,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@@ -96,6 +99,13 @@
return nil
}
+func (m *Upload) GetDirectoriesToDelete() []string {
+ if m != nil {
+ return m.DirectoriesToDelete
+ }
+ return nil
+}
+
func init() {
proto.RegisterType((*Upload)(nil), "soong_metrics_upload.Upload")
}
@@ -105,18 +115,20 @@
}
var fileDescriptor_91b94b655bd2a7e5 = []byte{
- // 201 bytes of a gzipped FileDescriptorProto
- 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x2d, 0xc8, 0xc9,
- 0x4f, 0x4c, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x29, 0xce, 0xcf, 0xcf, 0x4b, 0x8f,
- 0xcf, 0x4d, 0x2d, 0x29, 0xca, 0x4c, 0x2e, 0x8e, 0x87, 0xc8, 0x29, 0xdd, 0x66, 0xe4, 0x62, 0x0b,
- 0x05, 0x33, 0x85, 0x8c, 0xb8, 0x44, 0x93, 0x8b, 0x52, 0x13, 0x4b, 0x32, 0xf3, 0xf3, 0xe2, 0x4b,
- 0x32, 0x73, 0x53, 0x8b, 0x4b, 0x12, 0x73, 0x0b, 0xe2, 0x73, 0x8b, 0x25, 0x18, 0x15, 0x18, 0x35,
- 0x58, 0x82, 0x84, 0x61, 0x92, 0x21, 0x30, 0x39, 0xdf, 0x62, 0x21, 0x33, 0x2e, 0xf1, 0xe4, 0xfc,
- 0xdc, 0x82, 0x9c, 0x54, 0x4c, 0x5d, 0x4c, 0x60, 0x5d, 0xa2, 0x08, 0x69, 0x64, 0x7d, 0xf2, 0x5c,
- 0xdc, 0x49, 0x45, 0x89, 0x79, 0xc9, 0x19, 0xf1, 0x79, 0x89, 0xb9, 0xa9, 0x12, 0xcc, 0x0a, 0x8c,
- 0x1a, 0x9c, 0x41, 0x5c, 0x10, 0x21, 0xbf, 0xc4, 0xdc, 0x54, 0x90, 0x82, 0x92, 0xc4, 0xa2, 0xf4,
- 0xd4, 0x12, 0x88, 0x02, 0x16, 0x88, 0x02, 0x88, 0x10, 0x58, 0x81, 0x32, 0x17, 0x2f, 0xcc, 0x2b,
- 0x69, 0x99, 0x39, 0xa9, 0xc5, 0x12, 0xac, 0x0a, 0xcc, 0x1a, 0x9c, 0x41, 0x3c, 0x50, 0x41, 0x37,
- 0x90, 0x98, 0x93, 0x4c, 0x94, 0x14, 0x36, 0x5f, 0xc7, 0x83, 0x43, 0x04, 0x10, 0x00, 0x00, 0xff,
- 0xff, 0xe2, 0x01, 0x74, 0x65, 0x20, 0x01, 0x00, 0x00,
+ // 230 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0xb1, 0x4a, 0x04, 0x31,
+ 0x10, 0x86, 0xd9, 0xbb, 0xf3, 0xe0, 0xe2, 0xd9, 0xec, 0x79, 0x18, 0x44, 0x70, 0xd1, 0x66, 0x2b,
+ 0x0b, 0x0b, 0x1f, 0x40, 0xc4, 0x4e, 0x8b, 0xe5, 0x6c, 0x6c, 0x86, 0x98, 0x1d, 0xd7, 0x40, 0x92,
+ 0x09, 0xc9, 0xf8, 0x1c, 0xbe, 0xb2, 0x6c, 0xe2, 0xe2, 0x82, 0x76, 0xc3, 0xff, 0x7d, 0x7f, 0x31,
+ 0xbf, 0xd8, 0x7e, 0x06, 0x4b, 0xaa, 0xbf, 0x09, 0x91, 0x98, 0xea, 0xd3, 0x44, 0xe4, 0x07, 0x70,
+ 0xc8, 0xd1, 0xe8, 0x04, 0x85, 0x5d, 0x7d, 0x2d, 0xc4, 0xfa, 0x25, 0x9f, 0xf5, 0xad, 0xd8, 0xeb,
+ 0x88, 0x8a, 0x0d, 0x79, 0x60, 0xe3, 0x30, 0xb1, 0x72, 0x01, 0x5c, 0x92, 0x55, 0x53, 0xb5, 0xab,
+ 0x6e, 0x37, 0xc1, 0xc3, 0xc4, 0x9e, 0x52, 0x7d, 0x27, 0xce, 0x34, 0xb9, 0x60, 0xf1, 0x6f, 0x6b,
+ 0x91, 0x5b, 0xfb, 0x5f, 0x3c, 0xef, 0x5d, 0x8a, 0xe3, 0xb7, 0xa8, 0xbc, 0xfe, 0x00, 0xaf, 0x1c,
+ 0xca, 0x65, 0x53, 0xb5, 0x9b, 0x4e, 0x94, 0xe8, 0x59, 0x39, 0x1c, 0x05, 0x56, 0x71, 0x40, 0x2e,
+ 0xc2, 0xaa, 0x08, 0x25, 0xca, 0xc2, 0xb5, 0x38, 0x99, 0x5e, 0x79, 0x37, 0x16, 0x93, 0x3c, 0x6a,
+ 0x96, 0xed, 0xa6, 0xdb, 0xfe, 0x84, 0x8f, 0x63, 0x36, 0xbe, 0xd4, 0x9b, 0x88, 0x9a, 0x29, 0x1a,
+ 0x4c, 0xc0, 0x04, 0x3d, 0x5a, 0x64, 0x94, 0xeb, 0x2c, 0xef, 0x66, 0xf0, 0x40, 0x0f, 0x19, 0xdd,
+ 0x5f, 0xbc, 0x9e, 0xff, 0xb7, 0x14, 0xe4, 0x15, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x64, 0x04,
+ 0xa8, 0xf4, 0x54, 0x01, 0x00, 0x00,
}
diff --git a/ui/metrics/upload_proto/upload.proto b/ui/metrics/upload_proto/upload.proto
index 7a9f080..bcd0ab2 100644
--- a/ui/metrics/upload_proto/upload.proto
+++ b/ui/metrics/upload_proto/upload.proto
@@ -32,4 +32,8 @@
// A list of metrics filepaths to upload.
repeated string metrics_files = 5;
+
+ // A list of directories to delete after the copy of metrics files
+ // is completed for uploading.
+ repeated string directories_to_delete = 6;
}