Merge "Call rblf.setDefault() when appending to a variable without +="
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..caa2a95
--- /dev/null
+++ b/METADATA
@@ -0,0 +1 @@
+name: "Android"
diff --git a/android/api_levels.go b/android/api_levels.go
index 926d297..de56625 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -321,6 +321,7 @@
"Q": 29,
"R": 30,
"S": 31,
+ "S-V2": 32,
}
// TODO: Differentiate "current" and "future".
@@ -364,6 +365,7 @@
"Q": 29,
"R": 30,
"S": 31,
+ "S-V2": 32,
}
for i, codename := range config.PlatformVersionActiveCodenames() {
apiLevelsMap[codename] = previewAPILevelBase + i
diff --git a/android/arch.go b/android/arch.go
index 0f07b26..a7c62a9 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -22,6 +22,7 @@
"strings"
"android/soong/bazel"
+ "android/soong/starlark_fmt"
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
@@ -1794,14 +1795,9 @@
}
}
- if a.ArchVariant == "" {
- // Set ArchFeatures from the default arch features.
- if featureMap, ok := defaultArchFeatureMap[os]; ok {
- a.ArchFeatures = featureMap[archType]
- }
- } else {
- // Set ArchFeatures from the arch type.
- if featureMap, ok := archFeatureMap[archType]; ok {
+ // Set ArchFeatures from the arch type. for Android OS, other os-es do not specify features
+ if os == Android {
+ if featureMap, ok := androidArchFeatureMap[archType]; ok {
a.ArchFeatures = featureMap[a.ArchVariant]
}
}
@@ -2183,6 +2179,16 @@
targetStructs := getTargetStructs(ctx, archProperties, targetField)
osArchStructs = append(osArchStructs, targetStructs...)
}
+ if os == LinuxMusl {
+ targetField := "Musl_" + arch.Name
+ targetStructs := getTargetStructs(ctx, archProperties, targetField)
+ osArchStructs = append(osArchStructs, targetStructs...)
+ }
+ if os == Linux {
+ targetField := "Glibc_" + arch.Name
+ targetStructs := getTargetStructs(ctx, archProperties, targetField)
+ osArchStructs = append(osArchStructs, targetStructs...)
+ }
targetField := GetCompoundTargetField(os, arch)
targetName := fmt.Sprintf("%s_%s", os.Name, arch.Name)
@@ -2239,3 +2245,40 @@
return value
}
+
+func printArchTypeStarlarkDict(dict map[ArchType][]string) string {
+ valDict := make(map[string]string, len(dict))
+ for k, v := range dict {
+ valDict[k.String()] = starlark_fmt.PrintStringList(v, 1)
+ }
+ return starlark_fmt.PrintDict(valDict, 0)
+}
+
+func printArchTypeNestedStarlarkDict(dict map[ArchType]map[string][]string) string {
+ valDict := make(map[string]string, len(dict))
+ for k, v := range dict {
+ valDict[k.String()] = starlark_fmt.PrintStringListDict(v, 1)
+ }
+ return starlark_fmt.PrintDict(valDict, 0)
+}
+
+func StarlarkArchConfigurations() string {
+ return fmt.Sprintf(`
+_arch_to_variants = %s
+
+_arch_to_cpu_variants = %s
+
+_arch_to_features = %s
+
+_android_arch_feature_for_arch_variant = %s
+
+arch_to_variants = _arch_to_variants
+arch_to_cpu_variants = _arch_to_cpu_variants
+arch_to_features = _arch_to_features
+android_arch_feature_for_arch_variants = _android_arch_feature_for_arch_variant
+`, printArchTypeStarlarkDict(archVariants),
+ printArchTypeStarlarkDict(cpuVariants),
+ printArchTypeStarlarkDict(archFeatures),
+ printArchTypeNestedStarlarkDict(androidArchFeatureMap),
+ )
+}
diff --git a/android/arch_list.go b/android/arch_list.go
index 79ad4af..cbf8e7a 100644
--- a/android/arch_list.go
+++ b/android/arch_list.go
@@ -14,8 +14,6 @@
package android
-import "fmt"
-
var archVariants = map[ArchType][]string{
Arm: {
"armv7-a",
@@ -128,7 +126,7 @@
},
}
-var archFeatureMap = map[ArchType]map[string][]string{
+var androidArchFeatureMap = map[ArchType]map[string][]string{
Arm: {
"armv7-a-neon": {
"neon",
@@ -279,6 +277,13 @@
},
},
X86_64: {
+ "" /*default */ : {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "popcnt",
+ },
"amberlake": {
"ssse3",
"sse4",
@@ -398,23 +403,3 @@
},
},
}
-
-var defaultArchFeatureMap = map[OsType]map[ArchType][]string{}
-
-// RegisterDefaultArchVariantFeatures is called by files that define Toolchains to specify the
-// arch features that are available for the default arch variant. It must be called from an
-// init() function.
-func RegisterDefaultArchVariantFeatures(os OsType, arch ArchType, features ...string) {
- checkCalledFromInit()
-
- for _, feature := range features {
- if !InList(feature, archFeatures[arch]) {
- panic(fmt.Errorf("Invalid feature %q for arch %q variant \"\"", feature, arch))
- }
- }
-
- if defaultArchFeatureMap[os] == nil {
- defaultArchFeatureMap[os] = make(map[ArchType][]string)
- }
- defaultArchFeatureMap[os][arch] = features
-}
diff --git a/android/arch_test.go b/android/arch_test.go
index a828321..7caf837 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -491,11 +491,9 @@
arch: {
arm: {
a: ["arm"],
- armv7_a_neon: { a: ["armv7_a_neon"] },
},
arm64: {
a: ["arm64"],
- armv8_a: { a: ["armv8_a"] },
},
x86: { a: ["x86"] },
x86_64: { a: ["x86_64"] },
@@ -552,12 +550,12 @@
{
module: "foo",
variant: "android_arm64_armv8-a",
- property: []string{"root", "linux", "bionic", "android", "android64", "arm64", "armv8_a", "lib64", "android_arm64"},
+ property: []string{"root", "linux", "bionic", "android", "android64", "arm64", "lib64", "android_arm64"},
},
{
module: "foo",
variant: "android_arm_armv7-a-neon",
- property: []string{"root", "linux", "bionic", "android", "android64", "arm", "armv7_a_neon", "lib32", "android_arm"},
+ property: []string{"root", "linux", "bionic", "android", "android64", "arm", "lib32", "android_arm"},
},
},
},
diff --git a/android/bazel.go b/android/bazel.go
index 7714f2c..342b840 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -208,6 +208,7 @@
"build/bazel/tests":/* recursive = */ true,
"build/bazel/platforms":/* recursive = */ true,
"build/bazel/product_variables":/* recursive = */ true,
+ "build/bazel/vendor/google":/* recursive = */ true,
"build/bazel_common_rules":/* recursive = */ true,
// build/make/tools/signapk BUILD file is generated, so build/make/tools is not recursive.
"build/make/tools":/* recursive = */ false,
@@ -225,8 +226,10 @@
"packages/apps/QuickSearchBox":/* recursive = */ true,
"packages/apps/WallpaperPicker":/* recursive = */ false,
+ "prebuilts/bundletool":/* recursive = */ true,
"prebuilts/gcc":/* recursive = */ true,
"prebuilts/build-tools":/* recursive = */ false,
+ "prebuilts/jdk/jdk11":/* recursive = */ false,
"prebuilts/sdk":/* recursive = */ false,
"prebuilts/sdk/current/extras/app-toolkit":/* recursive = */ false,
"prebuilts/sdk/current/support":/* recursive = */ false,
@@ -245,6 +248,7 @@
"build/bazel/examples/soong_config_variables": Bp2BuildDefaultTrueRecursively,
"build/bazel/examples/apex/minimal": Bp2BuildDefaultTrueRecursively,
"build/make/tools/signapk": Bp2BuildDefaultTrue,
+ "build/make/target/product/security": Bp2BuildDefaultTrue,
"build/soong": Bp2BuildDefaultTrue,
"build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir
"build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue,
@@ -289,12 +293,14 @@
"development/samples/WiFiDirectDemo": Bp2BuildDefaultTrue,
"development/sdk": Bp2BuildDefaultTrueRecursively,
"external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
+ "external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively,
"external/auto/common": Bp2BuildDefaultTrueRecursively,
"external/auto/service": Bp2BuildDefaultTrueRecursively,
"external/boringssl": Bp2BuildDefaultTrueRecursively,
"external/bouncycastle": Bp2BuildDefaultTrue,
"external/brotli": Bp2BuildDefaultTrue,
"external/conscrypt": Bp2BuildDefaultTrue,
+ "external/e2fsprogs/lib": Bp2BuildDefaultTrueRecursively,
"external/error_prone": Bp2BuildDefaultTrueRecursively,
"external/fmtlib": Bp2BuildDefaultTrueRecursively,
"external/google-benchmark": Bp2BuildDefaultTrueRecursively,
@@ -325,6 +331,7 @@
"external/zstd": Bp2BuildDefaultTrueRecursively,
"frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue,
"frameworks/base/startop/apps/test": Bp2BuildDefaultTrue,
+ "frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively,
"frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively,
"frameworks/native/opengl/tests/gl2_cameraeye": Bp2BuildDefaultTrue,
"frameworks/native/opengl/tests/gl2_java": Bp2BuildDefaultTrue,
@@ -380,8 +387,36 @@
}
// Per-module allowlist to always opt modules in of both bp2build and mixed builds.
+ // These modules are usually in directories with many other modules that are not ready for
+ // conversion.
+ //
+ // A module can either be in this list or its directory allowlisted entirely
+ // in bp2buildDefaultConfig, but not both at the same time.
bp2buildModuleAlwaysConvertList = []string{
"junit-params-assertj-core",
+
+ //external/avb
+ "avbtool",
+ "libavb",
+ "avb_headers",
+
+ //external/fec
+ "libfec_rs",
+
+ //system/core/libsparse
+ "libsparse",
+
+ //system/extras/ext4_utils
+ "libext4_utils",
+
+ //system/extras/libfec
+ "libfec",
+
+ //system/extras/squashfs_utils
+ "libsquashfs_utils",
+
+ //system/extras/verity/fec
+ "fec",
}
// Per-module denylist to always opt modules out of both bp2build and mixed builds.
@@ -676,14 +711,21 @@
}
packagePath := ctx.OtherModuleDir(module)
- config := ctx.Config().bp2buildPackageConfig
+ if alwaysConvert && ShouldKeepExistingBuildFileForDir(packagePath) {
+ ctx.(BaseModuleContext).ModuleErrorf("A module cannot be in a directory listed in bp2buildKeepExistingBuildFile"+
+ " and also be in bp2buildModuleAlwaysConvert. Directory: '%s'", packagePath)
+ return false
+ }
+
+ config := ctx.Config().bp2buildPackageConfig
// This is a tristate value: true, false, or unset.
propValue := b.bazelProperties.Bazel_module.Bp2build_available
if bp2buildDefaultTrueRecursively(packagePath, config) {
if alwaysConvert {
- ctx.(BaseModuleContext).ModuleErrorf("a module cannot be in a directory marked Bp2BuildDefaultTrue" +
- " or Bp2BuildDefaultTrueRecursively and also be in bp2buildModuleAlwaysConvert")
+ ctx.(BaseModuleContext).ModuleErrorf("A module cannot be in a directory marked Bp2BuildDefaultTrue"+
+ " or Bp2BuildDefaultTrueRecursively and also be in bp2buildModuleAlwaysConvert. Directory: '%s'",
+ packagePath)
}
// Allow modules to explicitly opt-out.
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 804a5fb..3d6babc 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -664,7 +664,12 @@
if err != nil {
return err
}
-
+ if metricsDir := context.paths.BazelMetricsDir(); metricsDir != "" {
+ err = os.MkdirAll(metricsDir, 0777)
+ if err != nil {
+ return err
+ }
+ }
err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666)
if err != nil {
return err
@@ -716,9 +721,9 @@
}
}
- for val, _ := range context.requests {
+ for val := range context.requests {
if cqueryResult, ok := cqueryResults[getCqueryId(val)]; ok {
- context.results[val] = string(cqueryResult)
+ context.results[val] = cqueryResult
} else {
return fmt.Errorf("missing result for bazel target %s. query output: [%s], cquery err: [%s]",
getCqueryId(val), cqueryOutput, cqueryErr)
diff --git a/android/config.go b/android/config.go
index 3d8bc31..e8ca84c 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1256,6 +1256,10 @@
return Bool(c.config.productVariables.ClangCoverage)
}
+func (c *deviceConfig) ClangCoverageContinuousMode() bool {
+ return Bool(c.config.productVariables.ClangCoverageContinuousMode)
+}
+
func (c *deviceConfig) GcovCoverageEnabled() bool {
return Bool(c.config.productVariables.GcovCoverage)
}
diff --git a/android/licenses.go b/android/licenses.go
index b51a06b..e60c7a2 100644
--- a/android/licenses.go
+++ b/android/licenses.go
@@ -333,4 +333,6 @@
ctx.Strict("HTMLNOTICE", ctx.Config().HostToolPath(ctx, "htmlnotice").String())
ctx.Strict("XMLNOTICE", ctx.Config().HostToolPath(ctx, "xmlnotice").String())
ctx.Strict("TEXTNOTICE", ctx.Config().HostToolPath(ctx, "textnotice").String())
+ ctx.Strict("COMPLIANCENOTICE_BOM", ctx.Config().HostToolPath(ctx, "compliancenotice_bom").String())
+ ctx.Strict("COMPLIANCENOTICE_SHIPPEDLIBS", ctx.Config().HostToolPath(ctx, "compliancenotice_shippedlibs").String())
}
diff --git a/android/variable.go b/android/variable.go
index 68f19b9..37037eb 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -306,10 +306,11 @@
JavaCoveragePaths []string `json:",omitempty"`
JavaCoverageExcludePaths []string `json:",omitempty"`
- GcovCoverage *bool `json:",omitempty"`
- ClangCoverage *bool `json:",omitempty"`
- NativeCoveragePaths []string `json:",omitempty"`
- NativeCoverageExcludePaths []string `json:",omitempty"`
+ GcovCoverage *bool `json:",omitempty"`
+ ClangCoverage *bool `json:",omitempty"`
+ NativeCoveragePaths []string `json:",omitempty"`
+ NativeCoverageExcludePaths []string `json:",omitempty"`
+ ClangCoverageContinuousMode *bool `json:",omitempty"`
// Set by NewConfig
Native_coverage *bool `json:",omitempty"`
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index 295b0e5..954f8d0 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -17,6 +17,7 @@
import (
"fmt"
"sort"
+ "strconv"
"strings"
mkparser "android/soong/androidmk/parser"
@@ -623,6 +624,16 @@
return err
}
+// Assigns a given boolean value to a given variable in the result bp file. See
+// setVariable documentation for more information about prefix and name.
+func makeBlueprintBoolAssignment(ctx variableAssignmentContext, prefix, name string, value bool) error {
+ expressionValue, err := stringToBoolValue(strconv.FormatBool(value))
+ if err == nil {
+ err = setVariable(ctx.file, false, prefix, name, expressionValue, true)
+ }
+ return err
+}
+
// If variable is a literal variable name, return the name, otherwise return ""
func varLiteralName(variable mkparser.Variable) string {
if len(variable.Name.Variables) == 0 {
@@ -647,7 +658,11 @@
varname := ""
fixed := ""
val := ctx.mkvalue
+
if len(val.Variables) == 1 && varLiteralName(val.Variables[0]) != "" && len(val.Strings) == 2 && val.Strings[0] == "" {
+ if varLiteralName(val.Variables[0]) == "PRODUCT_OUT" && val.Strings[1] == "/system/priv-app" {
+ return makeBlueprintBoolAssignment(ctx, "", "privileged", true)
+ }
fixed = val.Strings[1]
varname = val.Variables[0].Name.Strings[0]
// TARGET_OUT_OPTIONAL_EXECUTABLES puts the artifact in xbin, which is
diff --git a/androidmk/androidmk/androidmk.go b/androidmk/androidmk/androidmk.go
index b8316a3..aaafdc7 100644
--- a/androidmk/androidmk/androidmk.go
+++ b/androidmk/androidmk/androidmk.go
@@ -411,6 +411,24 @@
return exp, nil
}
+// If local is set to true, then the variable will be added as a part of the
+// variable at file.bpPos. For example, if file.bpPos references a module,
+// then calling this method will set a property on that module if local is set
+// to true. Otherwise, the Variable will be created at the root of the file.
+//
+// prefix should be populated with the top level value to be assigned, and
+// name with a sub-value. If prefix is empty, then name is the top level value.
+// For example, if prefix is "foo" and name is "bar" with a value of "baz", then
+// the following variable will be generated:
+//
+// foo {
+// bar: "baz"
+// }
+//
+// If prefix is the empty string and name is "foo" with a value of "bar", the
+// following variable will be generated (if it is a property):
+//
+// foo: "bar"
func setVariable(file *bpFile, plusequals bool, prefix, name string, value bpparser.Expression, local bool) error {
if prefix != "" {
name = prefix + "." + name
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index e8b6f78..2176361 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -1675,6 +1675,21 @@
}
`,
},
+ {
+ desc: "privileged app",
+ in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := foo
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/priv-app
+include $(BUILD_PACKAGE)
+ `,
+ expected: `
+android_app {
+ name: "foo",
+ privileged: true
+}
+`,
+ },
}
func TestEndToEnd(t *testing.T) {
diff --git a/androidmk/parser/make_strings.go b/androidmk/parser/make_strings.go
index aac4c4e..8030326 100644
--- a/androidmk/parser/make_strings.go
+++ b/androidmk/parser/make_strings.go
@@ -24,14 +24,24 @@
// A MakeString is a string that may contain variable substitutions in it.
// It can be considered as an alternating list of raw Strings and variable
// substitutions, where the first and last entries in the list must be raw
-// Strings (possibly empty). A MakeString that starts with a variable
-// will have an empty first raw string, and a MakeString that ends with a
-// variable will have an empty last raw string. Two sequential Variables
-// will have an empty raw string between them.
+// Strings (possibly empty). The entirety of the text before the first variable,
+// between two variables, and after the last variable will be considered a
+// single String value. A MakeString that starts with a variable will have an
+// empty first raw string, and a MakeString that ends with a variable will have
+// an empty last raw string. Two sequential Variables will have an empty raw
+// string between them.
//
// The MakeString is stored as two lists, a list of raw Strings and a list
// of Variables. The raw string list is always one longer than the variable
// list.
+//
+// For example, "$(FOO)/bar/baz" will be represented as the
+// following lists:
+//
+// {
+// Strings: ["", "/bar/baz"],
+// Variables: ["FOO"]
+// }
type MakeString struct {
StringPos Pos
Strings []string
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 8785ca0..059b4d7 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -373,8 +373,10 @@
}
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", name+stemSuffix)
fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !a.installable())
- fmt.Fprintln(w, "LOCAL_SOONG_INSTALLED_MODULE :=", a.installedFile.String())
- fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS :=", a.outputFile.String()+":"+a.installedFile.String())
+ if a.installable() {
+ fmt.Fprintln(w, "LOCAL_SOONG_INSTALLED_MODULE :=", a.installedFile.String())
+ fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS :=", a.outputFile.String()+":"+a.installedFile.String())
+ }
// Because apex writes .mk with Custom(), we need to write manually some common properties
// which are available via data.Entries
diff --git a/apex/apex.go b/apex/apex.go
index fe4c205..ac67fee 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -108,15 +108,6 @@
Multilib apexMultilibProperties
- // List of bootclasspath fragments that are embedded inside this APEX bundle.
- Bootclasspath_fragments []string
-
- // List of systemserverclasspath fragments that are embedded inside this APEX bundle.
- Systemserverclasspath_fragments []string
-
- // List of java libraries that are embedded inside this APEX bundle.
- Java_libs []string
-
// List of sh binaries that are embedded inside this APEX bundle.
Sh_binaries []string
@@ -316,6 +307,15 @@
// List of BPF programs inside this APEX bundle.
Bpfs []string
+ // List of bootclasspath fragments that are embedded inside this APEX bundle.
+ Bootclasspath_fragments []string
+
+ // List of systemserverclasspath fragments that are embedded inside this APEX bundle.
+ Systemserverclasspath_fragments []string
+
+ // List of java libraries that are embedded inside this APEX bundle.
+ Java_libs []string
+
// Names of modules to be overridden. Listed modules can only be other binaries (in Make or
// Soong). This does not completely prevent installation of the overridden binaries, but if
// both binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will
@@ -787,9 +787,6 @@
// Common-arch dependencies come next
commonVariation := ctx.Config().AndroidCommonTarget.Variations()
- ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.properties.Bootclasspath_fragments...)
- ctx.AddFarVariationDependencies(commonVariation, sscpfTag, a.properties.Systemserverclasspath_fragments...)
- ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
ctx.AddFarVariationDependencies(commonVariation, compatConfigTag, a.properties.Compat_configs...)
@@ -817,6 +814,9 @@
ctx.AddFarVariationDependencies(commonVariation, androidAppTag, a.overridableProperties.Apps...)
ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.overridableProperties.Bpfs...)
ctx.AddFarVariationDependencies(commonVariation, rroTag, a.overridableProperties.Rros...)
+ ctx.AddFarVariationDependencies(commonVariation, bcpfTag, a.overridableProperties.Bootclasspath_fragments...)
+ ctx.AddFarVariationDependencies(commonVariation, sscpfTag, a.overridableProperties.Systemserverclasspath_fragments...)
+ ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.overridableProperties.Java_libs...)
if prebuilts := a.overridableProperties.Prebuilts; len(prebuilts) > 0 {
// For prebuilt_etc, use the first variant (64 on 64/32bit device, 32 on 32bit device)
// regardless of the TARGET_PREFER_* setting. See b/144532908
@@ -1415,7 +1415,7 @@
for _, target := range ctx.MultiTargets() {
if target.Arch.ArchType.Multilib == "lib64" {
addDependenciesForNativeModules(ctx, ApexNativeDependencies{
- Native_shared_libs: []string{"libclang_rt.hwasan-aarch64-android"},
+ Native_shared_libs: []string{"libclang_rt.hwasan"},
Tests: nil,
Jni_libs: nil,
Binaries: nil,
@@ -2595,9 +2595,9 @@
// Collect information for opening IDE project files in java/jdeps.go.
func (a *apexBundle) IDEInfo(dpInfo *android.IdeInfo) {
- dpInfo.Deps = append(dpInfo.Deps, a.properties.Java_libs...)
- dpInfo.Deps = append(dpInfo.Deps, a.properties.Bootclasspath_fragments...)
- dpInfo.Deps = append(dpInfo.Deps, a.properties.Systemserverclasspath_fragments...)
+ dpInfo.Deps = append(dpInfo.Deps, a.overridableProperties.Java_libs...)
+ dpInfo.Deps = append(dpInfo.Deps, a.overridableProperties.Bootclasspath_fragments...)
+ dpInfo.Deps = append(dpInfo.Deps, a.overridableProperties.Systemserverclasspath_fragments...)
dpInfo.Paths = append(dpInfo.Paths, a.modulePaths...)
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index f6b840f..4f2a583 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -1415,13 +1415,14 @@
}
cc_prebuilt_library_shared {
- name: "libclang_rt.hwasan-aarch64-android",
+ name: "libclang_rt.hwasan",
no_libcrt: true,
nocrt: true,
stl: "none",
system_shared_libs: [],
srcs: [""],
stubs: { versions: ["1"] },
+ stem: "libclang_rt.hwasan-aarch64-android",
sanitize: {
never: true,
@@ -1434,7 +1435,7 @@
"lib64/bionic/libclang_rt.hwasan-aarch64-android.so",
})
- hwasan := ctx.ModuleForTests("libclang_rt.hwasan-aarch64-android", "android_arm64_armv8-a_shared")
+ hwasan := ctx.ModuleForTests("libclang_rt.hwasan", "android_arm64_armv8-a_shared")
installed := hwasan.Description("install libclang_rt.hwasan")
ensureContains(t, installed.Output.String(), "/system/lib64/bootstrap/libclang_rt.hwasan-aarch64-android.so")
@@ -1462,13 +1463,14 @@
}
cc_prebuilt_library_shared {
- name: "libclang_rt.hwasan-aarch64-android",
+ name: "libclang_rt.hwasan",
no_libcrt: true,
nocrt: true,
stl: "none",
system_shared_libs: [],
srcs: [""],
stubs: { versions: ["1"] },
+ stem: "libclang_rt.hwasan-aarch64-android",
sanitize: {
never: true,
@@ -1482,7 +1484,7 @@
"lib64/bionic/libclang_rt.hwasan-aarch64-android.so",
})
- hwasan := ctx.ModuleForTests("libclang_rt.hwasan-aarch64-android", "android_arm64_armv8-a_shared")
+ hwasan := ctx.ModuleForTests("libclang_rt.hwasan", "android_arm64_armv8-a_shared")
installed := hwasan.Description("install libclang_rt.hwasan")
ensureContains(t, installed.Output.String(), "/system/lib64/bootstrap/libclang_rt.hwasan-aarch64-android.so")
@@ -6091,6 +6093,9 @@
apps: ["app"],
bpfs: ["bpf"],
prebuilts: ["myetc"],
+ bootclasspath_fragments: ["mybootclasspath_fragment"],
+ systemserverclasspath_fragments: ["mysystemserverclasspath_fragment"],
+ java_libs: ["myjava_library"],
overrides: ["oldapex"],
updatable: false,
}
@@ -6101,6 +6106,9 @@
apps: ["override_app"],
bpfs: ["override_bpf"],
prebuilts: ["override_myetc"],
+ bootclasspath_fragments: ["override_bootclasspath_fragment"],
+ systemserverclasspath_fragments: ["override_systemserverclasspath_fragment"],
+ java_libs: ["override_java_library"],
overrides: ["unknownapex"],
logging_parent: "com.foo.bar",
package_name: "test.overridden.package",
@@ -6159,6 +6167,72 @@
name: "override_myetc",
src: "override_myprebuilt",
}
+
+ java_library {
+ name: "bcplib",
+ srcs: ["a.java"],
+ compile_dex: true,
+ apex_available: ["myapex"],
+ permitted_packages: ["bcp.lib"],
+ }
+
+ bootclasspath_fragment {
+ name: "mybootclasspath_fragment",
+ contents: ["bcplib"],
+ apex_available: ["myapex"],
+ }
+
+ java_library {
+ name: "override_bcplib",
+ srcs: ["a.java"],
+ compile_dex: true,
+ apex_available: ["myapex"],
+ permitted_packages: ["override.bcp.lib"],
+ }
+
+ bootclasspath_fragment {
+ name: "override_bootclasspath_fragment",
+ contents: ["override_bcplib"],
+ apex_available: ["myapex"],
+ }
+
+ java_library {
+ name: "systemserverlib",
+ srcs: ["a.java"],
+ apex_available: ["myapex"],
+ }
+
+ systemserverclasspath_fragment {
+ name: "mysystemserverclasspath_fragment",
+ standalone_contents: ["systemserverlib"],
+ apex_available: ["myapex"],
+ }
+
+ java_library {
+ name: "override_systemserverlib",
+ srcs: ["a.java"],
+ apex_available: ["myapex"],
+ }
+
+ systemserverclasspath_fragment {
+ name: "override_systemserverclasspath_fragment",
+ standalone_contents: ["override_systemserverlib"],
+ apex_available: ["myapex"],
+ }
+
+ java_library {
+ name: "myjava_library",
+ srcs: ["a.java"],
+ compile_dex: true,
+ apex_available: ["myapex"],
+ }
+
+ java_library {
+ name: "override_java_library",
+ srcs: ["a.java"],
+ compile_dex: true,
+ apex_available: ["myapex"],
+ }
`, withManifestPackageNameOverrides([]string{"myapex:com.android.myapex"}))
originalVariant := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(android.OverridableModule)
@@ -6193,6 +6267,13 @@
t.Errorf("override_myapex should have logging parent (com.foo.bar), but was %q.", apexBundle.overridableProperties.Logging_parent)
}
+ android.AssertArrayString(t, "Bootclasspath_fragments does not match",
+ []string{"override_bootclasspath_fragment"}, apexBundle.overridableProperties.Bootclasspath_fragments)
+ android.AssertArrayString(t, "Systemserverclasspath_fragments does not match",
+ []string{"override_systemserverclasspath_fragment"}, apexBundle.overridableProperties.Systemserverclasspath_fragments)
+ android.AssertArrayString(t, "Java_libs does not match",
+ []string{"override_java_library"}, apexBundle.overridableProperties.Java_libs)
+
optFlags := apexRule.Args["opt_flags"]
ensureContains(t, optFlags, "--override_apk_package_name test.overridden.package")
ensureContains(t, optFlags, "--pubkey testkey2.avbpubkey")
@@ -6207,12 +6288,18 @@
ensureContains(t, androidMk, "LOCAL_MODULE := override_app.override_myapex")
ensureContains(t, androidMk, "LOCAL_MODULE := override_bpf.o.override_myapex")
ensureContains(t, androidMk, "LOCAL_MODULE := apex_manifest.pb.override_myapex")
+ ensureContains(t, androidMk, "LOCAL_MODULE := override_bcplib.override_myapex")
+ ensureContains(t, androidMk, "LOCAL_MODULE := override_systemserverlib.override_myapex")
+ ensureContains(t, androidMk, "LOCAL_MODULE := override_java_library.override_myapex")
ensureContains(t, androidMk, "LOCAL_MODULE_STEM := override_myapex.apex")
ensureContains(t, androidMk, "LOCAL_OVERRIDES_MODULES := unknownapex myapex")
ensureNotContains(t, androidMk, "LOCAL_MODULE := app.myapex")
ensureNotContains(t, androidMk, "LOCAL_MODULE := bpf.myapex")
ensureNotContains(t, androidMk, "LOCAL_MODULE := override_app.myapex")
ensureNotContains(t, androidMk, "LOCAL_MODULE := apex_manifest.pb.myapex")
+ ensureNotContains(t, androidMk, "LOCAL_MODULE := override_bcplib.myapex")
+ ensureNotContains(t, androidMk, "LOCAL_MODULE := override_systemserverlib.myapex")
+ ensureNotContains(t, androidMk, "LOCAL_MODULE := override_java_library.pb.myapex")
ensureNotContains(t, androidMk, "LOCAL_MODULE_STEM := myapex.apex")
}
diff --git a/apex/builder.go b/apex/builder.go
index 183c215..8c5f99b 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -856,6 +856,10 @@
installSuffix = imageCapexSuffix
}
+ if !a.installable() {
+ a.SkipInstall()
+ }
+
// Install to $OUT/soong/{target,host}/.../apex.
a.installedFile = ctx.InstallFile(a.installDir, a.Name()+installSuffix, a.outputFile,
a.compatSymlinks.Paths()...)
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index b904c35..8a171d4 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -44,9 +44,16 @@
"cc_library_shared_conversion_test.go",
"cc_library_static_conversion_test.go",
"cc_object_conversion_test.go",
+ "cc_prebuilt_library_shared_test.go",
"conversion_test.go",
"filegroup_conversion_test.go",
"genrule_conversion_test.go",
+ "java_binary_host_conversion_test.go",
+ "java_import_conversion_test.go",
+ "java_library_conversion_test.go",
+ "java_library_host_conversion_test.go",
+ "java_plugin_conversion_test.go",
+ "java_proto_conversion_test.go",
"performance_test.go",
"prebuilt_etc_conversion_test.go",
"python_binary_conversion_test.go",
diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go
index 28de06c..42c1a54 100644
--- a/bp2build/android_app_conversion_test.go
+++ b/bp2build/android_app_conversion_test.go
@@ -51,6 +51,7 @@
"srcs": `["app.java"]`,
"manifest": `"AndroidManifest.xml"`,
"resource_files": `["res/res.png"]`,
+ "deps": `["//prebuilts/sdk:public_current_android_sdk_java_import"]`,
}),
}})
}
@@ -86,7 +87,10 @@
"resb/res.png",
]`,
"custom_package": `"com.google"`,
- "deps": `[":static_lib_dep"]`,
+ "deps": `[
+ "//prebuilts/sdk:public_current_android_sdk_java_import",
+ ":static_lib_dep",
+ ]`,
}),
}})
}
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 96c12d3..3ab846b 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -28,6 +28,8 @@
files = append(files, newFile("product_config", "soong_config_variables.bzl", cfg.Bp2buildSoongConfigDefinitions.String()))
+ files = append(files, newFile("product_config", "arch_configuration.bzl", android.StarlarkArchConfigurations()))
+
apiLevelsContent, err := json.Marshal(android.GetApiLevelsMap(cfg))
if err != nil {
panic(err)
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index 629ca9b..c94a923 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -103,6 +103,10 @@
basename: "soong_config_variables.bzl",
},
{
+ dir: "product_config",
+ basename: "arch_configuration.bzl",
+ },
+ {
dir: "api_levels",
basename: GeneratedBuildFileName,
},
diff --git a/bp2build/java_proto_conversion_test.go b/bp2build/java_proto_conversion_test.go
index 93b0677..61a398c 100644
--- a/bp2build/java_proto_conversion_test.go
+++ b/bp2build/java_proto_conversion_test.go
@@ -71,8 +71,7 @@
}`
protoLibrary := makeBazelTarget("proto_library", "java-protos_proto", attrNameToString{
- "srcs": `["a.proto"]`,
- "strip_import_prefix": `""`,
+ "srcs": `["a.proto"]`,
})
for _, tc := range testCases {
@@ -107,8 +106,7 @@
`,
expectedBazelTargets: []string{
makeBazelTarget("proto_library", "java-protos_proto", attrNameToString{
- "srcs": `["a.proto"]`,
- "strip_import_prefix": `""`,
+ "srcs": `["a.proto"]`,
}),
makeBazelTarget(
"java_lite_proto_library",
diff --git a/cc/cc.go b/cc/cc.go
index a8adb0c..58ab28c 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1383,7 +1383,7 @@
}
func InstallToBootstrap(name string, config android.Config) bool {
- if name == "libclang_rt.hwasan-aarch64-android" {
+ if name == "libclang_rt.hwasan" {
return true
}
return isBionic(name)
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 51a6a27..278efa1 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -2944,13 +2944,13 @@
// Check the shared version of lib2.
variant := "android_arm64_armv8-a_shared"
module := ctx.ModuleForTests("lib2", variant).Module().(*Module)
- checkStaticLibs(t, []string{"lib1", "libc++demangle", "libclang_rt.builtins-aarch64-android"}, module)
+ checkStaticLibs(t, []string{"lib1", "libc++demangle", "libclang_rt.builtins"}, module)
// Check the static version of lib2.
variant = "android_arm64_armv8-a_static"
module = ctx.ModuleForTests("lib2", variant).Module().(*Module)
// libc++_static is linked additionally.
- checkStaticLibs(t, []string{"lib1", "libc++_static", "libc++demangle", "libclang_rt.builtins-aarch64-android"}, module)
+ checkStaticLibs(t, []string{"lib1", "libc++_static", "libc++demangle", "libclang_rt.builtins"}, module)
}
var compilerFlagsTestCases = []struct {
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 979c825..4d0ae1a 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -104,19 +104,22 @@
exportStringListStaticVariable("Arm64Cflags", arm64Cflags)
exportStringListStaticVariable("Arm64Cppflags", arm64Cppflags)
- exportedStringListDictVars.Set("Arm64ArchVariantCflags", arm64ArchVariantCflags)
- exportedStringListDictVars.Set("Arm64CpuVariantCflags", arm64CpuVariantCflags)
+ exportedVariableReferenceDictVars.Set("Arm64ArchVariantCflags", arm64ArchVariantCflagsVar)
+ exportedVariableReferenceDictVars.Set("Arm64CpuVariantCflags", arm64CpuVariantCflagsVar)
+ exportedVariableReferenceDictVars.Set("Arm64CpuVariantLdflags", arm64CpuVariantLdflags)
- pctx.StaticVariable("Arm64Armv8ACflags", strings.Join(arm64ArchVariantCflags["armv8-a"], " "))
- pctx.StaticVariable("Arm64Armv8ABranchProtCflags", strings.Join(arm64ArchVariantCflags["armv8-a-branchprot"], " "))
- pctx.StaticVariable("Arm64Armv82ACflags", strings.Join(arm64ArchVariantCflags["armv8-2a"], " "))
- pctx.StaticVariable("Arm64Armv82ADotprodCflags", strings.Join(arm64ArchVariantCflags["armv8-2a-dotprod"], " "))
+ exportStringListStaticVariable("Arm64Armv8ACflags", arm64ArchVariantCflags["armv8-a"])
+ exportStringListStaticVariable("Arm64Armv8ABranchProtCflags", arm64ArchVariantCflags["armv8-a-branchprot"])
+ exportStringListStaticVariable("Arm64Armv82ACflags", arm64ArchVariantCflags["armv8-2a"])
+ exportStringListStaticVariable("Arm64Armv82ADotprodCflags", arm64ArchVariantCflags["armv8-2a-dotprod"])
- pctx.StaticVariable("Arm64CortexA53Cflags", strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))
- pctx.StaticVariable("Arm64CortexA55Cflags", strings.Join(arm64CpuVariantCflags["cortex-a55"], " "))
- pctx.StaticVariable("Arm64KryoCflags", strings.Join(arm64CpuVariantCflags["kryo"], " "))
- pctx.StaticVariable("Arm64ExynosM1Cflags", strings.Join(arm64CpuVariantCflags["exynos-m1"], " "))
- pctx.StaticVariable("Arm64ExynosM2Cflags", strings.Join(arm64CpuVariantCflags["exynos-m2"], " "))
+ exportStringListStaticVariable("Arm64CortexA53Cflags", arm64CpuVariantCflags["cortex-a53"])
+ exportStringListStaticVariable("Arm64CortexA55Cflags", arm64CpuVariantCflags["cortex-a55"])
+ exportStringListStaticVariable("Arm64KryoCflags", arm64CpuVariantCflags["kryo"])
+ exportStringListStaticVariable("Arm64ExynosM1Cflags", arm64CpuVariantCflags["exynos-m1"])
+ exportStringListStaticVariable("Arm64ExynosM2Cflags", arm64CpuVariantCflags["exynos-m2"])
+
+ exportStringListStaticVariable("Arm64FixCortexA53Ldflags", []string{"-Wl,--fix-cortex-a53-843419"})
}
var (
@@ -128,7 +131,6 @@
}
arm64CpuVariantCflagsVar = map[string]string{
- "": "",
"cortex-a53": "${config.Arm64CortexA53Cflags}",
"cortex-a55": "${config.Arm64CortexA55Cflags}",
"cortex-a72": "${config.Arm64CortexA53Cflags}",
@@ -140,6 +142,15 @@
"exynos-m1": "${config.Arm64ExynosM1Cflags}",
"exynos-m2": "${config.Arm64ExynosM2Cflags}",
}
+
+ arm64CpuVariantLdflags = map[string]string{
+ "cortex-a53": "${config.Arm64FixCortexA53Ldflags}",
+ "cortex-a72": "${config.Arm64FixCortexA53Ldflags}",
+ "cortex-a73": "${config.Arm64FixCortexA53Ldflags}",
+ "kryo": "${config.Arm64FixCortexA53Ldflags}",
+ "exynos-m1": "${config.Arm64FixCortexA53Ldflags}",
+ "exynos-m2": "${config.Arm64FixCortexA53Ldflags}",
+ }
)
type toolchainArm64 struct {
@@ -214,12 +225,7 @@
toolchainCflags = append(toolchainCflags,
variantOrDefault(arm64CpuVariantCflagsVar, arch.CpuVariant))
- var extraLdflags string
- switch arch.CpuVariant {
- case "cortex-a53", "cortex-a72", "cortex-a73", "kryo", "exynos-m1", "exynos-m2":
- extraLdflags = "-Wl,--fix-cortex-a53-843419"
- }
-
+ extraLdflags := variantOrDefault(arm64CpuVariantLdflags, arch.CpuVariant)
return &toolchainArm64{
ldflags: strings.Join([]string{
"${config.Arm64Ldflags}",
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index 0fe5e68..4466632 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -39,6 +39,10 @@
armLldflags = armLdflags
+ armFixCortexA8LdFlags = []string{"-Wl,--fix-cortex-a8"}
+
+ armNoFixCortexA8LdFlags = []string{"-Wl,--no-fix-cortex-a8"}
+
armArmCflags = []string{
"-fstrict-aliasing",
}
@@ -179,6 +183,9 @@
exportStringListStaticVariable("ArmLdflags", armLdflags)
exportStringListStaticVariable("ArmLldflags", armLldflags)
+ exportStringListStaticVariable("ArmFixCortexA8LdFlags", armFixCortexA8LdFlags)
+ exportStringListStaticVariable("ArmNoFixCortexA8LdFlags", armNoFixCortexA8LdFlags)
+
// Clang cflags
exportStringListStaticVariable("ArmToolchainCflags", armToolchainCflags)
exportStringListStaticVariable("ArmCflags", armCflags)
@@ -188,8 +195,8 @@
exportStringListStaticVariable("ArmArmCflags", armArmCflags)
exportStringListStaticVariable("ArmThumbCflags", armThumbCflags)
- exportedStringListDictVars.Set("ArmArchVariantCflags", armArchVariantCflags)
- exportedStringListDictVars.Set("ArmCpuVariantCflags", armCpuVariantCflags)
+ exportedVariableReferenceDictVars.Set("ArmArchVariantCflags", armArchVariantCflagsVar)
+ exportedVariableReferenceDictVars.Set("ArmCpuVariantCflags", armCpuVariantCflagsVar)
// Clang arch variant cflags
exportStringListStaticVariable("ArmArmv7ACflags", armArchVariantCflags["armv7-a"])
@@ -324,12 +331,12 @@
switch arch.CpuVariant {
case "cortex-a8", "":
// Generic ARM might be a Cortex A8 -- better safe than sorry
- fixCortexA8 = "-Wl,--fix-cortex-a8"
+ fixCortexA8 = "${config.ArmFixCortexA8LdFlags}"
default:
- fixCortexA8 = "-Wl,--no-fix-cortex-a8"
+ fixCortexA8 = "${config.ArmNoFixCortexA8LdFlags}"
}
case "armv7-a":
- fixCortexA8 = "-Wl,--fix-cortex-a8"
+ fixCortexA8 = "${config.ArmFixCortexA8LdFlags}"
case "armv8-a", "armv8-2a":
// Nothing extra for armv8-a/armv8-2a
default:
diff --git a/cc/config/bp2build.go b/cc/config/bp2build.go
index eca5161..73f65f5 100644
--- a/cc/config/bp2build.go
+++ b/cc/config/bp2build.go
@@ -38,6 +38,8 @@
exportedStringListVars = exportedStringListVariables{}
exportedStringVars = exportedStringVariables{}
exportedStringListDictVars = exportedStringListDictVariables{}
+ // Note: these can only contain references to other variables and must be printed last
+ exportedVariableReferenceDictVars = exportedVariableReferenceDictVariables{}
/// Maps containing variables that are dependent on the build config.
exportedConfigDependingVars = exportedConfigDependingVariables{}
@@ -62,6 +64,7 @@
type bazelConstant struct {
variableName string
internalDefinition string
+ sortLast bool
}
type exportedStringVariables map[string]string
@@ -168,6 +171,36 @@
return ret
}
+type exportedVariableReferenceDictVariables map[string]map[string]string
+
+func (m exportedVariableReferenceDictVariables) Set(k string, v map[string]string) {
+ m[k] = v
+}
+
+func (m exportedVariableReferenceDictVariables) asBazel(_ android.Config, _ exportedStringVariables,
+ _ exportedStringListVariables, _ exportedConfigDependingVariables) []bazelConstant {
+ ret := make([]bazelConstant, 0, len(m))
+ for n, dict := range m {
+ for k, v := range dict {
+ matches, err := variableReference(v)
+ if err != nil {
+ panic(err)
+ } else if !matches.matches {
+ panic(fmt.Errorf("Expected a variable reference, got %q", v))
+ } else if len(matches.fullVariableReference) != len(v) {
+ panic(fmt.Errorf("Expected only a variable reference, got %q", v))
+ }
+ dict[k] = "_" + matches.variable
+ }
+ ret = append(ret, bazelConstant{
+ variableName: n,
+ internalDefinition: starlark_fmt.PrintDict(dict, 0),
+ sortLast: true,
+ })
+ }
+ return ret
+}
+
// BazelCcToolchainVars generates bzl file content containing variables for
// Bazel's cc_toolchain configuration.
func BazelCcToolchainVars(config android.Config) string {
@@ -175,7 +208,8 @@
config,
exportedStringListDictVars,
exportedStringListVars,
- exportedStringVars)
+ exportedStringVars,
+ exportedVariableReferenceDictVars)
}
func bazelToolchainVars(config android.Config, vars ...bazelVarExporter) string {
@@ -186,7 +220,12 @@
results = append(results, v.asBazel(config, exportedStringVars, exportedStringListVars, exportedConfigDependingVars)...)
}
- sort.Slice(results, func(i, j int) bool { return results[i].variableName < results[j].variableName })
+ sort.Slice(results, func(i, j int) bool {
+ if results[i].sortLast != results[j].sortLast {
+ return !results[i].sortLast
+ }
+ return results[i].variableName < results[j].variableName
+ })
definitions := make([]string, 0, len(results))
constants := make([]string, 0, len(results))
@@ -207,6 +246,32 @@
return ret
}
+type match struct {
+ matches bool
+ fullVariableReference string
+ variable string
+}
+
+func variableReference(input string) (match, error) {
+ // e.g. "${ExternalCflags}"
+ r := regexp.MustCompile(`\${(?:config\.)?([a-zA-Z0-9_]+)}`)
+
+ matches := r.FindStringSubmatch(input)
+ if len(matches) == 0 {
+ return match{}, nil
+ }
+ if len(matches) != 2 {
+ return match{}, fmt.Errorf("Expected to only match 1 subexpression in %s, got %d", input, len(matches)-1)
+ }
+ return match{
+ matches: true,
+ fullVariableReference: matches[0],
+ // Index 1 of FindStringSubmatch contains the subexpression match
+ // (variable name) of the capture group.
+ variable: matches[1],
+ }, nil
+}
+
// expandVar recursively expand interpolated variables in the exportedVars scope.
//
// We're using a string slice to track the seen variables to avoid
@@ -216,8 +281,6 @@
// interpolation stacks are deep (n > 1).
func expandVar(config android.Config, toExpand string, stringScope exportedStringVariables,
stringListScope exportedStringListVariables, exportedVars exportedConfigDependingVariables) ([]string, error) {
- // e.g. "${ExternalCflags}"
- r := regexp.MustCompile(`\${([a-zA-Z0-9_]+)}`)
// Internal recursive function.
var expandVarInternal func(string, map[string]bool) (string, error)
@@ -225,20 +288,18 @@
var ret string
remainingString := toExpand
for len(remainingString) > 0 {
- matches := r.FindStringSubmatch(remainingString)
- if len(matches) == 0 {
+ matches, err := variableReference(remainingString)
+ if err != nil {
+ panic(err)
+ }
+ if !matches.matches {
return ret + remainingString, nil
}
- if len(matches) != 2 {
- panic(fmt.Errorf("Expected to only match 1 subexpression in %s, got %d", remainingString, len(matches)-1))
- }
- matchIndex := strings.Index(remainingString, matches[0])
+ matchIndex := strings.Index(remainingString, matches.fullVariableReference)
ret += remainingString[:matchIndex]
- remainingString = remainingString[matchIndex+len(matches[0]):]
+ remainingString = remainingString[matchIndex+len(matches.fullVariableReference):]
- // Index 1 of FindStringSubmatch contains the subexpression match
- // (variable name) of the capture group.
- variable := matches[1]
+ variable := matches.variable
// toExpand contains a variable.
if _, ok := seenVars[variable]; ok {
return ret, fmt.Errorf(
diff --git a/cc/config/bp2build_test.go b/cc/config/bp2build_test.go
index 4cbf0c6..9a8178a 100644
--- a/cc/config/bp2build_test.go
+++ b/cc/config/bp2build_test.go
@@ -48,6 +48,14 @@
expectedValues: []string{"bar"},
},
{
+ description: "single level expansion with short-name for string var",
+ stringScope: exportedStringVariables{
+ "foo": "bar",
+ },
+ toExpand: "${config.foo}",
+ expectedValues: []string{"bar"},
+ },
+ {
description: "single level expansion string list var",
stringListScope: exportedStringListVariables{
"foo": []string{"bar"},
@@ -224,7 +232,30 @@
)`,
},
{
- name: "sorts across types",
+ name: "exports dict with var refs",
+ vars: []bazelVarExporter{
+ exportedVariableReferenceDictVariables{
+ "a": map[string]string{"b1": "${b2}"},
+ "c": map[string]string{"d1": "${config.d2}"},
+ },
+ },
+ expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
+
+_a = {
+ "b1": _b2,
+}
+
+_c = {
+ "d1": _d2,
+}
+
+constants = struct(
+ a = _a,
+ c = _c,
+)`,
+ },
+ {
+ name: "sorts across types with variable references last",
vars: []bazelVarExporter{
exportedStringVariables{
"b": "b-val",
@@ -238,6 +269,10 @@
"a": map[string][]string{"a1": []string{"a2"}},
"f": map[string][]string{"f1": []string{"f2"}},
},
+ exportedVariableReferenceDictVariables{
+ "aa": map[string]string{"b1": "${b}"},
+ "cc": map[string]string{"d1": "${config.d}"},
+ },
},
expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
@@ -257,6 +292,14 @@
"f1": ["f2"],
}
+_aa = {
+ "b1": _b,
+}
+
+_cc = {
+ "d1": _d,
+}
+
constants = struct(
a = _a,
b = _b,
@@ -264,6 +307,8 @@
d = _d,
e = _e,
f = _f,
+ aa = _aa,
+ cc = _cc,
)`,
},
}
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index 6cede11..7175fdc 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -227,14 +227,7 @@
}
func LibclangRuntimeLibrary(t Toolchain, library string) string {
- arch := t.LibclangRuntimeLibraryArch()
- if arch == "" {
- return ""
- }
- if !t.Bionic() {
- return "libclang_rt." + library + "-" + arch
- }
- return "libclang_rt." + library + "-" + arch + "-android"
+ return "libclang_rt." + library
}
func BuiltinsRuntimeLibrary(t Toolchain) string {
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index 0da51cb..164e7a6 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -78,14 +78,6 @@
"popcnt": []string{"-mpopcnt"},
"aes_ni": []string{"-maes"},
}
-
- x86_64DefaultArchVariantFeatures = []string{
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "popcnt",
- }
)
const (
@@ -93,8 +85,6 @@
)
func init() {
- android.RegisterDefaultArchVariantFeatures(android.Android, android.X86_64, x86_64DefaultArchVariantFeatures...)
- exportedStringListVars.Set("X86_64DefaultArchVariantFeatures", x86_64DefaultArchVariantFeatures)
pctx.StaticVariable("x86_64GccVersion", x86_64GccVersion)
diff --git a/cc/coverage.go b/cc/coverage.go
index f2b5425..d0902ea 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -77,6 +77,10 @@
return deps
}
+func EnableContinuousCoverage(ctx android.BaseModuleContext) bool {
+ return ctx.DeviceConfig().ClangCoverageContinuousMode()
+}
+
func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) {
clangCoverage := ctx.DeviceConfig().ClangCoverageEnabled()
gcovCoverage := ctx.DeviceConfig().GcovCoverageEnabled()
@@ -101,6 +105,9 @@
// Override -Wframe-larger-than. We can expect frame size increase after
// coverage instrumentation.
flags.Local.CFlags = append(flags.Local.CFlags, "-Wno-frame-larger-than=")
+ if EnableContinuousCoverage(ctx) {
+ flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-mllvm", "-runtime-counter-relocation")
+ }
}
}
@@ -152,6 +159,9 @@
flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--wrap,getenv")
} else if clangCoverage {
flags.Local.LdFlags = append(flags.Local.LdFlags, profileInstrFlag)
+ if EnableContinuousCoverage(ctx) {
+ flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm=-runtime-counter-relocation")
+ }
coverage := ctx.GetDirectDepWithTag(getClangProfileLibraryName(ctx), CoverageDepTag).(*Module)
deps.WholeStaticLibs = append(deps.WholeStaticLibs, coverage.OutputFile().Path())
diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go
index 0070e40..c1ca034 100644
--- a/cc/sanitize_test.go
+++ b/cc/sanitize_test.go
@@ -24,11 +24,7 @@
var prepareForAsanTest = android.FixtureAddFile("asan/Android.bp", []byte(`
cc_library_shared {
- name: "libclang_rt.asan-aarch64-android",
- }
-
- cc_library_shared {
- name: "libclang_rt.asan-arm-android",
+ name: "libclang_rt.asan",
}
`))
diff --git a/cc/testing.go b/cc/testing.go
index a03d147..32f7c60 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -86,54 +86,20 @@
}
cc_prebuilt_library_static {
- name: "libclang_rt.builtins-arm-android",
- defaults: ["toolchain_libs_defaults"],
- native_bridge_supported: true,
- vendor_ramdisk_available: true,
- }
-
- cc_prebuilt_library_static {
- name: "libclang_rt.builtins-aarch64-android",
- defaults: ["toolchain_libs_defaults"],
- native_bridge_supported: true,
- vendor_ramdisk_available: true,
- }
-
- cc_prebuilt_library_static {
- name: "libclang_rt.builtins-x86_64",
+ name: "libclang_rt.builtins",
defaults: ["toolchain_libs_defaults"],
host_supported: true,
- }
-
- cc_prebuilt_library_static {
- name: "libclang_rt.builtins-i386",
- defaults: ["toolchain_libs_defaults"],
- host_supported: true,
+ vendor_available: true,
+ vendor_ramdisk_available: true,
+ native_bridge_supported: true,
}
cc_prebuilt_library_shared {
- name: "libclang_rt.hwasan-aarch64-android",
+ name: "libclang_rt.hwasan",
defaults: ["toolchain_libs_defaults"],
}
cc_prebuilt_library_static {
- name: "libclang_rt.builtins-i686-android",
- defaults: ["toolchain_libs_defaults"],
- vendor_ramdisk_available: true,
- native_bridge_supported: true,
- }
-
- cc_prebuilt_library_static {
- name: "libclang_rt.builtins-x86_64-android",
- defaults: [
- "linux_bionic_supported",
- "toolchain_libs_defaults",
- ],
- native_bridge_supported: true,
- vendor_ramdisk_available: true,
- }
-
- cc_prebuilt_library_static {
name: "libunwind",
defaults: [
"linux_bionic_supported",
@@ -144,30 +110,7 @@
}
cc_prebuilt_library_static {
- name: "libclang_rt.fuzzer-arm-android",
- defaults: ["toolchain_libs_defaults"],
- }
-
- cc_prebuilt_library_static {
- name: "libclang_rt.fuzzer-aarch64-android",
- defaults: ["toolchain_libs_defaults"],
- }
-
- cc_prebuilt_library_static {
- name: "libclang_rt.fuzzer-i686-android",
- defaults: ["toolchain_libs_defaults"],
- }
-
- cc_prebuilt_library_static {
- name: "libclang_rt.fuzzer-x86_64-android",
- defaults: [
- "linux_bionic_supported",
- "toolchain_libs_defaults",
- ],
- }
-
- cc_prebuilt_library_static {
- name: "libclang_rt.fuzzer-x86_64",
+ name: "libclang_rt.fuzzer",
defaults: [
"linux_bionic_supported",
"toolchain_libs_defaults",
@@ -176,17 +119,12 @@
// Needed for sanitizer
cc_prebuilt_library_shared {
- name: "libclang_rt.ubsan_standalone-aarch64-android",
+ name: "libclang_rt.ubsan_standalone",
defaults: ["toolchain_libs_defaults"],
}
cc_prebuilt_library_static {
- name: "libclang_rt.ubsan_minimal-aarch64-android",
- defaults: ["toolchain_libs_defaults"],
- }
-
- cc_prebuilt_library_static {
- name: "libclang_rt.ubsan_minimal-arm-android",
+ name: "libclang_rt.ubsan_minimal",
defaults: ["toolchain_libs_defaults"],
}
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 8a17e2e..e7c05ac 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -146,6 +146,7 @@
// binary flags
Symlinks []string `json:",omitempty"`
StaticExecutable bool `json:",omitempty"`
+ InstallInRoot bool `json:",omitempty"`
// dependencies
SharedLibs []string `json:",omitempty"`
@@ -320,6 +321,7 @@
// binary flags
prop.Symlinks = m.Symlinks()
prop.StaticExecutable = m.StaticExecutable()
+ prop.InstallInRoot = m.InstallInRoot()
prop.SharedLibs = m.SnapshotSharedLibs()
// static libs dependencies are required to collect the NOTICE files.
prop.StaticLibs = m.SnapshotStaticLibs()
diff --git a/cc/vndk.go b/cc/vndk.go
index c9c9f2c..bf6148b 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -450,7 +450,7 @@
// Therefore, by removing the library here, we cause it to only be installed if libc
// depends on it.
func llndkLibrariesTxtFactory() android.SingletonModule {
- return newVndkLibrariesWithMakeVarFilter(llndkLibraries, "LLNDK_LIBRARIES", "libclang_rt.hwasan-")
+ return newVndkLibrariesWithMakeVarFilter(llndkLibraries, "LLNDK_LIBRARIES", "libclang_rt.hwasan")
}
// vndksp_libraries_txt is a singleton module whose content is a list of VNDKSP libraries
diff --git a/dexpreopt/DEXPREOPT_IMPLEMENTATION.md b/dexpreopt/DEXPREOPT_IMPLEMENTATION.md
new file mode 100644
index 0000000..c3a1730
--- /dev/null
+++ b/dexpreopt/DEXPREOPT_IMPLEMENTATION.md
@@ -0,0 +1,258 @@
+## Dexpreopt implementation
+
+### Introduction
+
+All dexpreopted Java code falls into three categories:
+
+- bootclasspath
+- system server
+- apps and libraries
+
+Dexpreopt implementation for bootclasspath libraries (boot images) is located in
+[soong/java] (see e.g. [soong/java/dexpreopt_bootjars.go]), and install rules
+are in [make/core/dex_preopt.mk].
+
+Dexpreopt implementation for system server, libraries and apps is located in
+[soong/dexpreopt]. For the rest of this section we focus primarily on it (and
+not boot images).
+
+Dexpeopt implementation is split across the Soong part and the Make part. The
+core logic is in Soong, and Make only generates configs and scripts to pass
+information to Soong.
+
+### Global and module dexpreopt.config
+
+The build system generates a global JSON dexpreopt config that is populated from
+product variables. This is static configuration that is passed to both Soong and
+Make. The `$OUT/soong/dexpreopt.config` file is generated in
+[make/core/dex_preopt_config.mk]. Soong reads it in [soong/dexpreopt/config.go]
+and makes a device-specific copy (this is needed to ensure incremental build
+correctness). The global config contains lists of bootclasspath jars, system
+server jars, dex2oat options, global switches that enable and disable parts of
+dexpreopt and so on.
+
+The build system also generates a module config for each dexpreopted package. It
+contains package-specific configuration that is derived from the global
+configuration and Android.bp or Android.mk module for the package.
+
+Module configs for Make packages are generated in
+[make/core/dex_preopt_odex_install.mk]; they are materialized as per-package
+JSON dexpreopt.config files.
+
+Module configs in Soong are not materialized as dexpreopt.config files and exist
+as Go structures in memory, unless it is necessary to materialize them as a file
+for dependent Make packages or for post-dexpreopting. Module configs are defined
+in [soong/dexpreopt/config.go].
+
+### Dexpreopt in Soong
+
+The Soong implementation of dexpreopt consists roughly of the following steps:
+
+- Read global dexpreopt config passed from Make ([soong/dexpreopt/config.go]).
+
+- Construct a static boot image config ([soong/java/dexpreopt_config.go]).
+
+- During dependency mutator pass, for each suitable module:
+ - add uses-library dependencies (e.g. for apps: [soong/java/app.go:deps])
+
+- During rule generation pass, for each suitable module:
+ - compute transitive uses-library dependency closure
+ ([soong/java/java.go:addCLCFromDep])
+
+ - construct CLC from the dependency closure
+ ([soong/dexpreopt/class_loader_context.go])
+
+ - construct module config with CLC, boot image locations, etc.
+ ([soong/java/dexpreopt.go])
+
+ - generate build rules to verify build-time CLC against the manifest (e.g.
+ for apps: [soong/java/app.go:verifyUsesLibraries])
+
+ - generate dexpreopt build rule ([soong/dexpreopt/dexpreopt.go])
+
+- At the end of rule generation pass:
+ - generate build rules for boot images ([soong/java/dexpreopt_bootjars.go],
+ [soong/java/bootclasspath_fragment.go] and
+ [soong/java/platform_bootclasspath.go])
+
+### Dexpreopt in Make - dexpreopt_gen
+
+In order to reuse the same dexpreopt implementation for both Soong and Make
+packages, part of Soong is compiled into a standalone binary dexpreopt_gen. It
+runs during the Ninja stage of the build and generates shell scripts with
+dexpreopt build rules for Make packages, and then executes them.
+
+This setup causes many inconveniences. To name a few:
+
+- Errors in the build rules are only revealed at the late stage of the build.
+
+- These rules are not tested by the presubmit builds that run `m nothing` on
+ many build targets/products.
+
+- It is impossible to find dexpreopt build rules in the generated Ninja files.
+
+However all these issues are a lesser evil compared to having a duplicate
+dexpreopt implementation in Make. Also note that it would be problematic to
+reimplement the logic in Make anyway, because Android.mk modules are not
+processed in the order of uses-library dependencies and propagating dependency
+information from one module to another would require a similar workaround with
+a script.
+
+Dexpreopt for Make packages involves a few steps:
+
+- At Soong phase (during `m nothing`), see dexpreopt_gen:
+ - generate build rules for dexpreopt_gen binary
+
+- At Make/Kati phase (during `m nothing`), see
+ [make/core/dex_preopt_odex_install.mk]:
+ - generate build rules for module dexpreopt.config
+
+ - generate build rules for merging dependency dexpreopt.config files (see
+ [make/core/dex_preopt_config_merger.py])
+
+ - generate build rules for dexpreopt_gen invocation
+
+ - generate build rules for executing dexpreopt.sh scripts
+
+- At Ninja phase (during `m`):
+ - generate dexpreopt.config files
+
+ - execute dexpreopt_gen rules (generate dexpreopt.sh scripts)
+
+ - execute dexpreopt.sh scripts (this runs the actual dexpreopt)
+
+The Make/Kati phase adds all the necessary dependencies that trigger
+dexpreopt_gen and dexpreopt.sh rules. The real dexpreopt command (dex2oat
+invocation that will be executed to AOT-compile a package) is in the
+dexpreopt.sh script, which is generated close to the end of the build.
+
+### Indirect build rules
+
+The process described above for Make packages involves "indirect build rules",
+i.e. build rules that are generated not at the time when the build system is
+created (which is a small step at the very beginning of the build triggered with
+`m nothing`), but at the time when the actual build is done (`m` phase).
+
+Some build systems, such as Make, allow modifications of the build graph during
+the build. Other build systems, such as Soong, have a clear separation into the
+first "generation phase" (this is when build rules are created) and the second
+"build phase" (this is when the build rules are executed), and they do not allow
+modifications of the dependency graph during the second phase. The Soong
+approach is better from performance standpoint, because with the Make approach
+there are no guarantees regarding the time of the build --- recursive build
+graph modfications continue until fixpoint. However the Soong approach is also
+more restictive, as it can only generate build rules from the information that
+is passed to the build system via global configuration, Android.bp files or
+encoded in the Go code. Any other information (such as the contents of the Java
+manifest files) are not accessible and cannot be used to generate build rules.
+
+Hence the need for the "indirect build rules": during the generation phase only
+stubs of the build rules are generated, and the real rules are generated by the
+stub rules during the build phase (and executed immediately). Note that the
+build system still has to add all the necessary dependencies during the
+generation phase, because it will not be possible to change build order during
+the build phase.
+
+Indirect buils rules are used in a couple of places in dexpreopt:
+
+- [soong/scripts/manifest_check.py]: first to extract targetSdkVersion from the
+ manifest, and later to extract `<uses-library/>` tags from the manifest and
+ compare them to the uses-library list known to the build system
+
+- [soong/scripts/construct_context.py]: to trim compatibility libraries in CLC
+
+- [make/core/dex_preopt_config_merger.py]: to merge information from
+ dexpreopt.config files for uses-library dependencies into the dependent's
+ dexpreopt.config file (mostly the CLC)
+
+- autogenerated dexpreopt.sh scripts: to call dexpreopt_gen
+
+### Consistency check - manifest_check.py
+
+Because the information from the manifests has to be duplicated in the
+Android.bp/Android.mk files, there is a danger that it may get out of sync. To
+guard against that, the build system generates a rule that verifies
+uses-libraries: checks the metadata in the build files against the contents of a
+manifest. The manifest can be available as a source file, or as part of a
+prebuilt APK.
+
+The check is implemented in [soong/scripts/manifest_check.py].
+
+It is possible to turn off the check globally for a product by setting
+`PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true` in a product makefile, or for a
+particular build by setting `RELAX_USES_LIBRARY_CHECK=true`.
+
+### Compatibility libraries - construct_context.py
+
+Compatibility libraries are libraries that didn’t exist prior to a certain SDK
+version (say, `N`), but classes in them were in the bootclasspath jars, etc.,
+and in version `N` they have been separated into a standalone uses-library.
+Compatibility libraries should only be in the CLC of an app if its
+`targetSdkVersion` in the manifest is less than `N`.
+
+Currently compatibility libraries only affect apps (but not other libraries).
+
+The build system cannot see `targetSdkVersion` of an app at the time it
+generates dexpreopt build rules, so it doesn't know whether to add compatibility
+libaries to CLC or not. As a workaround, the build system includes all
+compatibility libraries regardless of the app version, and appends some extra
+logic to the dexpreopt rule that will extract `targetSdkVersion` from the
+manifest and filter CLC based on that version during Ninja stage of the build,
+immediately before executing the dexpreopt command (see the
+soong/scripts/construct_context.py script).
+
+As of the time of writing (January 2022), there are the following compatibility
+libraries:
+
+- org.apache.http.legacy (SDK 28)
+- android.hidl.base-V1.0-java (SDK 29)
+- android.hidl.manager-V1.0-java (SDK 29)
+- android.test.base (SDK 30)
+- android.test.mock (SDK 30)
+
+### Manifest fixer
+
+Sometimes uses-library tags are missing from the source manifest of a
+library/app. This may happen for example if one of the transitive dependencies
+of the library/app starts using another uses-library, and the library/app's
+manifest isn't updated to include it.
+
+Soong can compute some of the missing uses-library tags for a given library/app
+automatically as SDK libraries in the transitive dependency closure of the
+library/app. The closure is needed because a library/app may depend on a static
+library that may in turn depend on an SDK library (possibly transitively via
+another library).
+
+Not all uses-library tags can be computed in this way, because some of the
+uses-library dependencies are not SDK libraries, or they are not reachable via
+transitive dependency closure. But when possible, allowing Soong to calculate
+the manifest entries is less prone to errors and simplifies maintenance. For
+example, consider a situation when many apps use some static library that adds a
+new uses-library dependency -- all the apps will have to be updated. That is
+difficult to maintain.
+
+There is also a manifest merger, because sometimes the final manifest of an app
+is merged from a few dependency manifests, so the final manifest installed on
+devices contains a superset of uses-library tags of the source manifest of the
+app.
+
+
+[make/core/dex_preopt.mk]: https://cs.android.com/android/platform/superproject/+/master:build/make/core/dex_preopt.mk
+[make/core/dex_preopt_config.mk]: https://cs.android.com/android/platform/superproject/+/master:build/make/core/dex_preopt_config.mk
+[make/core/dex_preopt_config_merger.py]: https://cs.android.com/android/platform/superproject/+/master:build/make/core/dex_preopt_config_merger.py
+[make/core/dex_preopt_odex_install.mk]: https://cs.android.com/android/platform/superproject/+/master:build/make/core/dex_preopt_odex_install.mk
+[soong/dexpreopt]: https://cs.android.com/android/platform/superproject/+/master:build/soong/dexpreopt
+[soong/dexpreopt/class_loader_context.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/dexpreopt/class_loader_context.go
+[soong/dexpreopt/config.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/dexpreopt/config.go
+[soong/dexpreopt/dexpreopt.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/dexpreopt/dexpreopt.go
+[soong/java]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java
+[soong/java/app.go:deps]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/app.go?q=%22func%20\(u%20*usesLibrary\)%20deps%22
+[soong/java/app.go:verifyUsesLibraries]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/app.go?q=%22func%20\(u%20*usesLibrary\)%20verifyUsesLibraries%22
+[soong/java/bootclasspath_fragment.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/bootclasspath_fragment.go
+[soong/java/dexpreopt.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/dexpreopt.go
+[soong/java/dexpreopt_bootjars.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/dexpreopt_bootjars.go
+[soong/java/dexpreopt_config.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/dexpreopt_config.go
+[soong/java/java.go:addCLCFromDep]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/java.go?q=%22func%20addCLCfromDep%22
+[soong/java/platform_bootclasspath.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/platform_bootclasspath.go
+[soong/scripts/construct_context.py]: https://cs.android.com/android/platform/superproject/+/master:build/soong/scripts/construct_context.py
+[soong/scripts/manifest_check.py]: https://cs.android.com/android/platform/superproject/+/master:build/soong/scripts/manifest_check.py
diff --git a/docs/rbe.json b/docs/rbe.json
new file mode 100644
index 0000000..f6ff107
--- /dev/null
+++ b/docs/rbe.json
@@ -0,0 +1,24 @@
+{
+ "env": {
+ "USE_RBE": "1",
+
+ "RBE_R8_EXEC_STRATEGY": "remote_local_fallback",
+ "RBE_CXX_EXEC_STRATEGY": "remote_local_fallback",
+ "RBE_D8_EXEC_STRATEGY": "remote_local_fallback",
+ "RBE_JAVAC_EXEC_STRATEGY": "remote_local_fallback",
+ "RBE_JAVAC": "1",
+ "RBE_R8": "1",
+ "RBE_D8": "1",
+
+ "RBE_instance": "[replace with your RBE instance]",
+ "RBE_service": "[replace with your RBE service endpoint]",
+
+ "RBE_DIR": "prebuilts/remoteexecution-client/live",
+
+ "RBE_use_application_default_credentials": "true",
+
+ "RBE_log_dir": "/tmp",
+ "RBE_output_dir": "/tmp",
+ "RBE_proxy_log_dir": "/tmp"
+ }
+}
diff --git a/docs/rbe.md b/docs/rbe.md
new file mode 100644
index 0000000..cfe86d7
--- /dev/null
+++ b/docs/rbe.md
@@ -0,0 +1,70 @@
+# Build Android Platform on Remote Build Execution
+
+Soong is integrated with Google's Remote Build Execution(RBE) service, which
+implements the
+[Remote Executaion API](https://github.com/bazelbuild/remote-apis).
+
+With RBE enabled, it can speed up the Android Platform builds by distributing
+build actions through a worker pool sharing a central cache of build results.
+
+## Configuration
+
+To enable RBE, you need to set several environment variables before triggering
+the build. You can set them through a
+[environment variables config file](https://android.googlesource.com/platform/build/soong/+/master/README.md#environment-variables-config-file).
+As an example, [build/soong/docs/rbe.json](rbe.json) is a config that enables
+RBE in the build. Once the config file is created, you need to let Soong load
+the config file by specifying `ANDROID_BUILD_ENVIRONMENT_CONFIG_DIR` environment
+variable and `ANDROID_BUILD_ENVIRONMENT_CONFIG` environment variable. The
+following command starts Soong with [build/soong/docs/rbe.json](rbe.json)
+loaded:
+
+```shell
+ANDROID_BUILD_ENVIRONMENT_CONFIG=rbe \
+ANDROID_BUILD_ENVIRONMENT_CONFIG_DIR=build/soong/doc \
+ build/soong/soong_ui.bash
+```
+
+### Configuration Explanation
+
+Below a brief explanation of each field in
+[build/soong/docs/rbe.json](rbe.json):
+
+##### USE\_RBE:
+If set to 1, enable RBE for the build.
+
+##### RBE\_CXX\_EXEC\_STRATEGY / RBE\_JAVAC\_EXEC\_STRATEGY / RBE\_R8\_EXEC\_STRATEGY / RBE\_D8\_EXEC\_STRATEGY:
+
+Sets strategies for C++/javac/r8/d8 action types. Available options are
+(**Note**: all options will update the remote cache if the right permissions to
+update cache are given to the user.):
+
+* **local**: Only execute locally.
+* **remote**: Only execute remotely.
+* **remote_local_fallback**: Try executing remotely and fall back to local
+ execution if failed.
+* **racing**: Race remote execution and local execution and use the earlier
+ result.
+
+##### RBE\_JAVAC / RBE\_R8 / RBE\_D8
+
+If set to 1, enable javac/r8/d8 support. C++ compilation is enabled by default.
+
+##### RBE\_service / RBE\_instance
+
+The remote execution service endpoint and instance ID to target when calling
+remote execution via gRPC to execute actions.
+
+##### RBE\_DIR
+
+Where to find remote client binaries (rewrapper, reproxy)
+
+##### RBE\_use\_application\_default\_credentials
+
+reclient uses
+[application default credentials](https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login)
+for autentication, as generated by `gcloud auth application-default login`
+
+##### RBE\_log\_dir/RBE\_proxy\_log\_dir/RBE\_output\_dir
+
+Logs generated by rewrapper and reproxy will go here.
diff --git a/java/app.go b/java/app.go
index e4432ff..96fd61a 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1443,7 +1443,7 @@
props := bazel.BazelTargetModuleProperties{
Rule_class: "android_app_certificate",
- Bzl_load_location: "//build/bazel/rules:android_app_certificate.bzl",
+ Bzl_load_location: "//build/bazel/rules/android:android_app_certificate.bzl",
}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
@@ -1451,9 +1451,11 @@
type bazelAndroidAppAttributes struct {
*javaLibraryAttributes
- Manifest bazel.Label
- Custom_package *string
- Resource_files bazel.LabelListAttribute
+ Manifest bazel.Label
+ Custom_package *string
+ Resource_files bazel.LabelListAttribute
+ Certificate *bazel.Label
+ Certificate_name *string
}
// ConvertWithBp2build is used to convert android_app to Bazel.
@@ -1470,15 +1472,30 @@
resourceFiles.Includes = append(resourceFiles.Includes, files...)
}
+ var certificate *bazel.Label
+ certificateNamePtr := a.overridableAppProperties.Certificate
+ certificateName := proptools.StringDefault(certificateNamePtr, "")
+ certModule := android.SrcIsModule(certificateName)
+ if certModule != "" {
+ c := android.BazelLabelForModuleDepSingle(ctx, certificateName)
+ certificate = &c
+ certificateNamePtr = nil
+ }
+
attrs := &bazelAndroidAppAttributes{
libAttrs,
android.BazelLabelForModuleSrcSingle(ctx, manifest),
// TODO(b/209576404): handle package name override by product variable PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES
a.overridableAppProperties.Package_name,
bazel.MakeLabelListAttribute(resourceFiles),
+ certificate,
+ certificateNamePtr,
}
- props := bazel.BazelTargetModuleProperties{Rule_class: "android_binary",
- Bzl_load_location: "@rules_android//rules:rules.bzl"}
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "android_binary",
+ Bzl_load_location: "//build/bazel/rules/android:android_binary.bzl",
+ }
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: a.Name()}, attrs)
diff --git a/java/base.go b/java/base.go
index 8747039..9978a66 100644
--- a/java/base.go
+++ b/java/base.go
@@ -481,6 +481,8 @@
sdkVersion android.SdkSpec
minSdkVersion android.SdkSpec
maxSdkVersion android.SdkSpec
+
+ sourceExtensions []string
}
func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error {
@@ -982,6 +984,14 @@
return flags
}
+func (j *Module) AddJSONData(d *map[string]interface{}) {
+ (&j.ModuleBase).AddJSONData(d)
+ (*d)["Java"] = map[string]interface{}{
+ "SourceExtensions": j.sourceExtensions,
+ }
+
+}
+
func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
@@ -993,6 +1003,12 @@
}
srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
+ j.sourceExtensions = []string{}
+ for _, ext := range []string{".kt", ".proto", ".aidl", ".java", ".logtags"} {
+ if hasSrcExt(srcFiles.Strings(), ext) {
+ j.sourceExtensions = append(j.sourceExtensions, ext)
+ }
+ }
if hasSrcExt(srcFiles.Strings(), ".proto") {
flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags)
}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 5fe409e..eddcb61 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "io"
"path/filepath"
"reflect"
"strings"
@@ -588,6 +589,19 @@
// Provide the apex content info.
b.provideApexContentInfo(ctx, imageConfig, hiddenAPIOutput, bootImageFilesByArch)
}
+ } else {
+ // Versioned fragments are not needed by make.
+ b.HideFromMake()
+ }
+
+ // In order for information about bootclasspath_fragment modules to be added to module-info.json
+ // it is necessary to output an entry to Make. As bootclasspath_fragment modules are part of an
+ // APEX there can be multiple variants, including the default/platform variant and only one can
+ // be output to Make but it does not really matter which variant is output. The default/platform
+ // variant is the first (ctx.PrimaryModule()) and is usually hidden from make so this just picks
+ // the last variant (ctx.FinalModule()).
+ if ctx.Module() != ctx.FinalModule() {
+ b.HideFromMake()
}
}
@@ -849,7 +863,22 @@
}
func (b *BootclasspathFragmentModule) AndroidMkEntries() []android.AndroidMkEntries {
- var entriesList []android.AndroidMkEntries
+ // Use the generated classpath proto as the output.
+ outputFile := b.outputFilepath
+ // Create a fake entry that will cause this to be added to the module-info.json file.
+ entriesList := []android.AndroidMkEntries{{
+ Class: "FAKE",
+ OutputFile: android.OptionalPathForPath(outputFile),
+ Include: "$(BUILD_PHONY_PACKAGE)",
+ ExtraFooters: []android.AndroidMkExtraFootersFunc{
+ func(w io.Writer, name, prefix, moduleDir string) {
+ // Allow the bootclasspath_fragment to be built by simply passing its name on the command
+ // line.
+ fmt.Fprintln(w, ".PHONY:", b.Name())
+ fmt.Fprintln(w, b.Name()+":", outputFile.String())
+ },
+ },
+ }}
for _, install := range b.bootImageDeviceInstalls {
entriesList = append(entriesList, install.ToMakeEntries())
}
diff --git a/java/config/config.go b/java/config/config.go
index 39584cb..05dfde6 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -105,7 +105,12 @@
if override := ctx.Config().Getenv("OVERRIDE_JLINK_VERSION_NUMBER"); override != "" {
return override
}
- return "11"
+ switch ctx.Config().Getenv("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN") {
+ case "true":
+ return "17"
+ default:
+ return "11"
+ }
})
pctx.SourcePathVariable("JavaToolchain", "${JavaHome}/bin")
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 5dc7bc9..272cf1e 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -334,7 +334,11 @@
// TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
cmd.FlagWithArg("--hide ", "HiddenTypedefConstant").
FlagWithArg("--hide ", "SuperfluousPrefix").
- FlagWithArg("--hide ", "AnnotationExtraction")
+ FlagWithArg("--hide ", "AnnotationExtraction").
+ // b/222738070
+ FlagWithArg("--hide ", "BannedThrow").
+ // b/223382732
+ FlagWithArg("--hide ", "ChangedDefault")
}
}
diff --git a/java/java.go b/java/java.go
index d0f0abc..0a35908 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2030,6 +2030,11 @@
}
var deps bazel.LabelList
+ sdkVersion := m.SdkVersion(ctx)
+ if sdkVersion.Kind == android.SdkPublic && sdkVersion.ApiLevel == android.FutureApiLevel {
+ // TODO(b/220869005) remove forced dependency on current public android.jar
+ deps.Add(&bazel.Label{Label: "//prebuilts/sdk:public_current_android_sdk_java_import"})
+ }
if m.properties.Libs != nil {
deps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Libs))
}
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 7c1176b..d108a0d 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -465,17 +465,17 @@
return ctx
}
-func (ctx *parseContext) lastAssignment(name string) *assignmentNode {
+func (ctx *parseContext) lastAssignment(v variable) *assignmentNode {
for va := ctx.varAssignments; va != nil; va = va.outer {
- if v, ok := va.vars[name]; ok {
+ if v, ok := va.vars[v.name()]; ok {
return v
}
}
return nil
}
-func (ctx *parseContext) setLastAssignment(name string, asgn *assignmentNode) {
- ctx.varAssignments.vars[name] = asgn
+func (ctx *parseContext) setLastAssignment(v variable, asgn *assignmentNode) {
+ ctx.varAssignments.vars[v.name()] = asgn
}
func (ctx *parseContext) pushVarAssignments() {
@@ -532,7 +532,7 @@
if lhs == nil {
return []starlarkNode{ctx.newBadNode(a, "unknown variable %s", name)}
}
- _, isTraced := ctx.tracedVariables[name]
+ _, isTraced := ctx.tracedVariables[lhs.name()]
asgn := &assignmentNode{lhs: lhs, mkValue: a.Value, isTraced: isTraced, location: ctx.errorLocation(a)}
if lhs.valueType() == starlarkTypeUnknown {
// Try to divine variable type from the RHS
@@ -565,8 +565,8 @@
}
}
- asgn.previous = ctx.lastAssignment(name)
- ctx.setLastAssignment(name, asgn)
+ asgn.previous = ctx.lastAssignment(lhs)
+ ctx.setLastAssignment(lhs, asgn)
switch a.Type {
case "=", ":=":
asgn.flavor = asgnSet
@@ -807,20 +807,16 @@
if len(matchingPaths) > maxMatchingFiles {
return []starlarkNode{ctx.newBadNode(v, "there are >%d files matching the pattern, please rewrite it", maxMatchingFiles)}
}
- if len(matchingPaths) == 1 {
- res := inheritedStaticModule{ctx.newDependentModule(matchingPaths[0], loadAlways && ctx.ifNestLevel == 0), loadAlways}
- return []starlarkNode{processModule(res)}
- } else {
- needsWarning := pathPattern[0] == "" && len(ctx.includeTops) == 0
- res := inheritedDynamicModule{*varPath, []*moduleInfo{}, loadAlways, ctx.errorLocation(v), needsWarning}
- for _, p := range matchingPaths {
- // A product configuration files discovered dynamically may attempt to inherit
- // from another one which does not exist in this source tree. Prevent load errors
- // by always loading the dynamic files as optional.
- res.candidateModules = append(res.candidateModules, ctx.newDependentModule(p, true))
- }
- return []starlarkNode{processModule(res)}
+
+ needsWarning := pathPattern[0] == "" && len(ctx.includeTops) == 0
+ res := inheritedDynamicModule{*varPath, []*moduleInfo{}, loadAlways, ctx.errorLocation(v), needsWarning}
+ for _, p := range matchingPaths {
+ // A product configuration files discovered dynamically may attempt to inherit
+ // from another one which does not exist in this source tree. Prevent load errors
+ // by always loading the dynamic files as optional.
+ res.candidateModules = append(res.candidateModules, ctx.newDependentModule(p, true))
}
+ return []starlarkNode{processModule(res)}
}
func (ctx *parseContext) findMatchingPaths(pattern []string) []string {
@@ -1272,12 +1268,12 @@
args: []starlarkExpr{
&stringLiteralExpr{literal: substParts[0]},
&stringLiteralExpr{literal: substParts[1]},
- NewVariableRefExpr(v, ctx.lastAssignment(v.name()) != nil),
+ NewVariableRefExpr(v, ctx.lastAssignment(v) != nil),
},
}
}
if v := ctx.addVariable(refDump); v != nil {
- return NewVariableRefExpr(v, ctx.lastAssignment(v.name()) != nil)
+ return NewVariableRefExpr(v, ctx.lastAssignment(v) != nil)
}
return ctx.newBadExpr(node, "unknown variable %s", refDump)
}
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index ce1a1f9..556dcaa 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -65,6 +65,10 @@
PRODUCT_NAME := Pixel 3
PRODUCT_MODEL :=
local_var = foo
+local-var-with-dashes := bar
+$(warning local-var-with-dashes: $(local-var-with-dashes))
+GLOBAL-VAR-WITH-DASHES := baz
+$(warning GLOBAL-VAR-WITH-DASHES: $(GLOBAL-VAR-WITH-DASHES))
`,
expected: `load("//build/make/core:product_config.rbc", "rblf")
@@ -73,6 +77,10 @@
cfg["PRODUCT_NAME"] = "Pixel 3"
cfg["PRODUCT_MODEL"] = ""
_local_var = "foo"
+ _local_var_with_dashes = "bar"
+ rblf.mkwarning("pixel3.mk", "local-var-with-dashes: %s" % _local_var_with_dashes)
+ g["GLOBAL-VAR-WITH-DASHES"] = "baz"
+ rblf.mkwarning("pixel3.mk", "GLOBAL-VAR-WITH-DASHES: %s" % g["GLOBAL-VAR-WITH-DASHES"])
`,
},
{
@@ -1082,7 +1090,13 @@
def init(g, handle):
cfg = rblf.cfg(handle)
g["MY_PATH"] = "foo"
- rblf.inherit(handle, "vendor/foo1/cfg", _cfg_init)
+ _entry = {
+ "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
+ }.get("%s/cfg.mk" % g["MY_PATH"])
+ (_varmod, _varmod_init) = _entry if _entry else (None, None)
+ if not _varmod_init:
+ rblf.mkerror("product.mk", "Cannot find %s" % ("%s/cfg.mk" % g["MY_PATH"]))
+ rblf.inherit(handle, _varmod, _varmod_init)
`,
},
{
@@ -1102,8 +1116,20 @@
def init(g, handle):
cfg = rblf.cfg(handle)
g["MY_PATH"] = "foo"
- rblf.inherit(handle, "vendor/foo1/cfg", _cfg_init)
- rblf.inherit(handle, "vendor/foo1/cfg", _cfg_init)
+ _entry = {
+ "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
+ }.get("%s/cfg.mk" % g["MY_PATH"])
+ (_varmod, _varmod_init) = _entry if _entry else (None, None)
+ if not _varmod_init:
+ rblf.mkerror("product.mk", "Cannot find %s" % ("%s/cfg.mk" % g["MY_PATH"]))
+ rblf.inherit(handle, _varmod, _varmod_init)
+ _entry = {
+ "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
+ }.get("%s/cfg.mk" % g["MY_PATH"])
+ (_varmod, _varmod_init) = _entry if _entry else (None, None)
+ if not _varmod_init:
+ rblf.mkerror("product.mk", "Cannot find %s" % ("%s/cfg.mk" % g["MY_PATH"]))
+ rblf.inherit(handle, _varmod, _varmod_init)
`,
},
{
@@ -1127,9 +1153,21 @@
def init(g, handle):
cfg = rblf.cfg(handle)
- rblf.inherit(handle, "foo/font", _font_init)
+ _entry = {
+ "foo/font.mk": ("foo/font", _font_init),
+ }.get("%s/font.mk" % g.get("MY_VAR", ""))
+ (_varmod, _varmod_init) = _entry if _entry else (None, None)
+ if not _varmod_init:
+ rblf.mkerror("product.mk", "Cannot find %s" % ("%s/font.mk" % g.get("MY_VAR", "")))
+ rblf.inherit(handle, _varmod, _varmod_init)
# There's some space and even this comment between the include_top and the inherit-product
- rblf.inherit(handle, "foo/font", _font_init)
+ _entry = {
+ "foo/font.mk": ("foo/font", _font_init),
+ }.get("%s/font.mk" % g.get("MY_VAR", ""))
+ (_varmod, _varmod_init) = _entry if _entry else (None, None)
+ if not _varmod_init:
+ rblf.mkerror("product.mk", "Cannot find %s" % ("%s/font.mk" % g.get("MY_VAR", "")))
+ rblf.inherit(handle, _varmod, _varmod_init)
rblf.mkwarning("product.mk:11", "Please avoid starting an include path with a variable. See https://source.android.com/setup/build/bazel/product_config/issues/includes for details.")
_entry = {
"foo/font.mk": ("foo/font", _font_init),
diff --git a/mk2rbc/variable.go b/mk2rbc/variable.go
index 73afd19..6805744 100644
--- a/mk2rbc/variable.go
+++ b/mk2rbc/variable.go
@@ -291,6 +291,14 @@
// addVariable returns a variable with a given name. A variable is
// added if it does not exist yet.
func (ctx *parseContext) addVariable(name string) variable {
+ // Heuristics: if variable's name is all lowercase, consider it local
+ // string variable.
+ isLocalVariable := name == strings.ToLower(name)
+ // Local variables can't have special characters in them, because they
+ // will be used as starlark identifiers
+ if isLocalVariable {
+ name = strings.ReplaceAll(strings.TrimSpace(name), "-", "_")
+ }
v, found := ctx.variables[name]
if !found {
_, preset := presetVariables[name]
@@ -301,9 +309,7 @@
case VarClassSoong:
v = &otherGlobalVariable{baseVariable{nam: name, typ: vi.valueType, preset: preset}}
}
- } else if name == strings.ToLower(name) {
- // Heuristics: if variable's name is all lowercase, consider it local
- // string variable.
+ } else if isLocalVariable {
v = &localVariable{baseVariable{nam: name, typ: starlarkTypeUnknown}}
} else {
vt := starlarkTypeUnknown
diff --git a/rust/compiler.go b/rust/compiler.go
index c5d40f4..19499fa 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -121,6 +121,12 @@
// include all of the static libraries symbols in any dylibs or binaries which use this rlib as well.
Whole_static_libs []string `android:"arch_variant"`
+ // list of Rust system library dependencies.
+ //
+ // This is usually only needed when `no_stdlibs` is true, in which case it can be used to depend on system crates
+ // like `core` and `alloc`.
+ Stdlibs []string `android:"arch_variant"`
+
// crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider
// modules which create library variants (rust_bindgen). This must be the expected extern crate name used in
// source, and is required to conform to an enforced format matching library output files (if the output file is
@@ -360,6 +366,7 @@
deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...)
deps.WholeStaticLibs = append(deps.WholeStaticLibs, compiler.Properties.Whole_static_libs...)
deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs...)
+ deps.Stdlibs = append(deps.Stdlibs, compiler.Properties.Stdlibs...)
if !Bool(compiler.Properties.No_stdlibs) {
for _, stdlib := range config.Stdlibs {
diff --git a/rust/config/global.go b/rust/config/global.go
index c1ce13f..1cf773e 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
var pctx = android.NewPackageContext("android/soong/rust/config")
var (
- RustDefaultVersion = "1.58.1"
+ RustDefaultVersion = "1.59.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2021"
Stdlibs = []string{
@@ -49,7 +49,7 @@
"-C overflow-checks=on",
"-C force-unwind-tables=yes",
// Use v0 mangling to distinguish from C++ symbols
- "-Z symbol-mangling-version=v0",
+ "-C symbol-mangling-version=v0",
}
deviceGlobalRustFlags = []string{
diff --git a/rust/config/toolchain.go b/rust/config/toolchain.go
index a769f12..9c9d572 100644
--- a/rust/config/toolchain.go
+++ b/rust/config/toolchain.go
@@ -121,14 +121,7 @@
}
func LibclangRuntimeLibrary(t Toolchain, library string) string {
- arch := t.LibclangRuntimeLibraryArch()
- if arch == "" {
- return ""
- }
- if !t.Bionic() {
- return "libclang_rt." + library + "-" + arch
- }
- return "libclang_rt." + library + "-" + arch + "-android"
+ return "libclang_rt." + library
}
func LibRustRuntimeLibrary(t Toolchain, library string) string {
diff --git a/rust/coverage.go b/rust/coverage.go
index 050b811..651ce6e 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -22,6 +22,7 @@
var CovLibraryName = "libprofile-clang-extras"
+// Add '%c' to default specifier after we resolve http://b/210012154
const profileInstrFlag = "-fprofile-instr-generate=/data/misc/trace/clang-%p-%m.profraw"
type coverage struct {
@@ -59,6 +60,10 @@
flags.LinkFlags = append(flags.LinkFlags,
profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open")
deps.StaticLibs = append(deps.StaticLibs, coverage.OutputFile().Path())
+ if cc.EnableContinuousCoverage(ctx) {
+ flags.RustFlags = append(flags.RustFlags, "-C llvm-args=--runtime-counter-relocation")
+ flags.LinkFlags = append(flags.LinkFlags, "-Wl,-mllvm,-runtime-counter-relocation")
+ }
}
return flags, deps
diff --git a/rust/fuzz_test.go b/rust/fuzz_test.go
index 98be7c2..865665e 100644
--- a/rust/fuzz_test.go
+++ b/rust/fuzz_test.go
@@ -47,17 +47,17 @@
// Check that compiler flags are set appropriately .
fuzz_libtest := ctx.ModuleForTests("fuzz_libtest", "android_arm64_armv8-a_fuzzer").Rule("rustc")
if !strings.Contains(fuzz_libtest.Args["rustcFlags"], "-Z sanitizer=hwaddress") ||
- !strings.Contains(fuzz_libtest.Args["rustcFlags"], "-C passes='sancov'") ||
+ !strings.Contains(fuzz_libtest.Args["rustcFlags"], "-C passes='sancov-module'") ||
!strings.Contains(fuzz_libtest.Args["rustcFlags"], "--cfg fuzzing") {
- t.Errorf("rust_fuzz module does not contain the expected flags (sancov, cfg fuzzing, hwaddress sanitizer).")
+ t.Errorf("rust_fuzz module does not contain the expected flags (sancov-module, cfg fuzzing, hwaddress sanitizer).")
}
// Check that dependencies have 'fuzzer' variants produced for them as well.
libtest_fuzzer := ctx.ModuleForTests("libtest_fuzzing", "android_arm64_armv8-a_rlib_rlib-std_fuzzer").Output("libtest_fuzzing.rlib")
if !strings.Contains(libtest_fuzzer.Args["rustcFlags"], "-Z sanitizer=hwaddress") ||
- !strings.Contains(libtest_fuzzer.Args["rustcFlags"], "-C passes='sancov'") ||
+ !strings.Contains(libtest_fuzzer.Args["rustcFlags"], "-C passes='sancov-module'") ||
!strings.Contains(libtest_fuzzer.Args["rustcFlags"], "--cfg fuzzing") {
- t.Errorf("rust_fuzz dependent library does not contain the expected flags (sancov, cfg fuzzing, hwaddress sanitizer).")
+ t.Errorf("rust_fuzz dependent library does not contain the expected flags (sancov-module, cfg fuzzing, hwaddress sanitizer).")
}
}
diff --git a/rust/image.go b/rust/image.go
index 5d57f15..dfc7f74 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -149,6 +149,10 @@
return mod.ModuleBase.InRecovery() || mod.ModuleBase.InstallInRecovery()
}
+func (mod *Module) InRamdisk() bool {
+ return mod.ModuleBase.InRamdisk() || mod.ModuleBase.InstallInRamdisk()
+}
+
func (mod *Module) InVendorRamdisk() bool {
return mod.ModuleBase.InVendorRamdisk() || mod.ModuleBase.InstallInVendorRamdisk()
}
diff --git a/rust/rust.go b/rust/rust.go
index f40f1a8..1c718a4 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -968,6 +968,7 @@
deps.ProcMacros = android.LastUniqueStrings(deps.ProcMacros)
deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs)
deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs)
+ deps.Stdlibs = android.LastUniqueStrings(deps.Stdlibs)
deps.WholeStaticLibs = android.LastUniqueStrings(deps.WholeStaticLibs)
return deps
diff --git a/rust/sanitize.go b/rust/sanitize.go
index be9dc42..39aaf33 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -57,7 +57,7 @@
}
var fuzzerFlags = []string{
- "-C passes='sancov'",
+ "-C passes='sancov-module'",
"--cfg fuzzing",
"-C llvm-args=-sanitizer-coverage-level=3",
@@ -70,7 +70,7 @@
"-C link-dead-code",
// Sancov breaks with lto
- // TODO: Remove when https://bugs.llvm.org/show_bug.cgi?id=41734 is resolved and sancov works with LTO
+ // TODO: Remove when https://bugs.llvm.org/show_bug.cgi?id=41734 is resolved and sancov-module works with LTO
"-C lto=no",
}
diff --git a/rust/testing.go b/rust/testing.go
index 1b34dfe..cb98bed 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -88,13 +88,13 @@
export_include_dirs: ["libprotobuf-cpp-full-includes"],
}
cc_library {
- name: "libclang_rt.asan-aarch64-android",
+ name: "libclang_rt.asan",
no_libcrt: true,
nocrt: true,
system_shared_libs: [],
}
cc_library {
- name: "libclang_rt.hwasan_static-aarch64-android",
+ name: "libclang_rt.hwasan_static",
no_libcrt: true,
nocrt: true,
system_shared_libs: [],
diff --git a/rust/vendor_snapshot_test.go b/rust/vendor_snapshot_test.go
index 03bd867..7be0042 100644
--- a/rust/vendor_snapshot_test.go
+++ b/rust/vendor_snapshot_test.go
@@ -561,7 +561,7 @@
static_libs: [
"libvendor",
"libvndk",
- "libclang_rt.builtins-aarch64-android",
+ "libclang_rt.builtins",
"note_memtag_heap_sync",
],
shared_libs: [
@@ -589,7 +589,7 @@
static_libs: [
"libvendor",
"libvndk",
- "libclang_rt.builtins-arm-android",
+ "libclang_rt.builtins",
],
shared_libs: [
"libvendor_available",
@@ -731,19 +731,7 @@
}
vendor_snapshot_static {
- name: "libclang_rt.builtins-aarch64-android",
- version: "30",
- target_arch: "arm64",
- vendor: true,
- arch: {
- arm64: {
- src: "libclang_rt.builtins-aarch64-android.a",
- },
- },
- }
-
- vendor_snapshot_static {
- name: "libclang_rt.builtins-arm-android",
+ name: "libclang_rt.builtins",
version: "30",
target_arch: "arm64",
vendor: true,
@@ -751,6 +739,9 @@
arm: {
src: "libclang_rt.builtins-arm-android.a",
},
+ arm64: {
+ src: "libclang_rt.builtins-aarch64-android.a",
+ },
},
}
@@ -967,7 +958,7 @@
}
libclientAndroidMkStaticLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkStaticLibs
- if g, w := libclientAndroidMkStaticLibs, []string{"libvendor", "libvendor_without_snapshot", "libclang_rt.builtins-aarch64-android.vendor"}; !reflect.DeepEqual(g, w) {
+ if g, w := libclientAndroidMkStaticLibs, []string{"libvendor", "libvendor_without_snapshot", "libclang_rt.builtins.vendor"}; !reflect.DeepEqual(g, w) {
t.Errorf("wanted libclient AndroidMkStaticLibs %q, got %q", w, g)
}
@@ -1024,7 +1015,7 @@
}
memtagStaticLibs := ctx.ModuleForTests("memtag_binary", "android_vendor.30_arm64_armv8-a").Module().(*Module).Properties.AndroidMkStaticLibs
- if g, w := memtagStaticLibs, []string{"libclang_rt.builtins-aarch64-android.vendor", "note_memtag_heap_sync.vendor"}; !reflect.DeepEqual(g, w) {
+ if g, w := memtagStaticLibs, []string{"libclang_rt.builtins.vendor", "note_memtag_heap_sync.vendor"}; !reflect.DeepEqual(g, w) {
t.Errorf("wanted memtag_binary AndroidMkStaticLibs %q, got %q", w, g)
}
}
diff --git a/ui/build/config.go b/ui/build/config.go
index 1dd948c..01fe8fa 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -35,10 +35,10 @@
)
const (
- envConfigDir = "vendor/google/tools/soong_config"
- jsonSuffix = "json"
+ envConfigDir = "vendor/google/tools/soong_config"
+ jsonSuffix = "json"
- configFetcher = "vendor/google/tools/soong/expconfigfetcher"
+ configFetcher = "vendor/google/tools/soong/expconfigfetcher"
envConfigFetchTimeout = 10 * time.Second
)
@@ -62,6 +62,7 @@
jsonModuleGraph bool
bp2build bool
queryview bool
+ reportMkMetrics bool // Collect and report mk2bp migration progress metrics.
soongDocs bool
skipConfig bool
skipKati bool
@@ -155,7 +156,7 @@
}
configExists := false
- outConfigFilePath := filepath.Join(config.OutDir(), envConfigName + jsonSuffix)
+ outConfigFilePath := filepath.Join(config.OutDir(), envConfigName+jsonSuffix)
if _, err := os.Stat(outConfigFilePath); err == nil {
configExists = true
}
@@ -367,10 +368,14 @@
java8Home := filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
java9Home := filepath.Join("prebuilts/jdk/jdk9", ret.HostPrebuiltTag())
java11Home := filepath.Join("prebuilts/jdk/jdk11", ret.HostPrebuiltTag())
+ java17Home := filepath.Join("prebuilts/jdk/jdk17", ret.HostPrebuiltTag())
javaHome := func() string {
if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
return override
}
+ if ret.environ.IsEnvTrue("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN") {
+ return java17Home
+ }
if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN is no longer supported. An OpenJDK 11 toolchain is now the global default.")
}
@@ -711,6 +716,8 @@
c.skipConfig = true
} else if arg == "--skip-soong-tests" {
c.skipSoongTests = true
+ } else if arg == "--mk-metrics" {
+ c.reportMkMetrics = true
} else if len(arg) > 0 && arg[0] == '-' {
parseArgNum := func(def int) int {
if len(arg) > 2 {
@@ -1381,6 +1388,11 @@
return filepath.Join(c.LogsDir(), "bazel_metrics")
}
+// MkFileMetrics returns the file path for make-related metrics.
+func (c *configImpl) MkMetrics() string {
+ return filepath.Join(c.LogsDir(), "mk_metrics.pb")
+}
+
func (c *configImpl) SetEmptyNinjaFile(v bool) {
c.emptyNinjaFile = v
}
diff --git a/ui/build/finder.go b/ui/build/finder.go
index 68efe21..262de3d 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -138,6 +138,17 @@
ctx.Fatalf("Could not export module list: %v", err)
}
+ // Gate collecting/reporting mk metrics on builds that specifically request
+ // it, as identifying the total number of mk files adds 4-5ms onto null
+ // builds.
+ if config.reportMkMetrics {
+ androidMksTotal := f.FindNamedAt(".", "Android.mk")
+
+ ctx.Metrics.SetToplevelMakefiles(len(androidMks))
+ ctx.Metrics.SetTotalMakefiles(len(androidMksTotal))
+ ctx.Metrics.DumpMkMetrics(config.MkMetrics())
+ }
+
// Stop searching a subdirectory recursively after finding a CleanSpec.mk.
cleanSpecs := f.FindFirstNamedAt(".", "CleanSpec.mk")
err = dumpListToFile(ctx, config, cleanSpecs, filepath.Join(dumpDir, "CleanSpec.mk.list"))
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 81c500d..831a80f 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -91,6 +91,7 @@
"pstree": Allowed,
"rsync": Allowed,
"sh": Allowed,
+ "stubby": Allowed,
"tr": Allowed,
"unzip": Allowed,
"zip": Allowed,
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 117a2a5..1b993e1 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -507,6 +507,9 @@
if shouldCollectBuildSoongMetrics(config) && ctx.Metrics != nil {
ctx.Metrics.SetSoongBuildMetrics(soongBuildMetrics)
}
+ if config.JsonModuleGraph() {
+ distGzipFile(ctx, config, config.ModuleGraphFile(), "soong")
+ }
}
func runMicrofactory(ctx Context, config Config, name string, pkg string, mapping map[string]string) {
diff --git a/ui/metrics/Android.bp b/ui/metrics/Android.bp
index 3ba3907..05db1d7 100644
--- a/ui/metrics/Android.bp
+++ b/ui/metrics/Android.bp
@@ -21,9 +21,10 @@
pkgPath: "android/soong/ui/metrics",
deps: [
"golang-protobuf-proto",
+ "soong-ui-bp2build_metrics_proto",
"soong-ui-metrics_upload_proto",
"soong-ui-metrics_proto",
- "soong-ui-bp2build_metrics_proto",
+ "soong-ui-mk_metrics_proto",
"soong-ui-tracer",
"soong-shared",
],
@@ -71,3 +72,15 @@
"bp2build_metrics_proto/bp2build_metrics.pb.go",
],
}
+
+bootstrap_go_package {
+ name: "soong-ui-mk_metrics_proto",
+ pkgPath: "android/soong/ui/metrics/mk_metrics_proto",
+ deps: [
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ ],
+ srcs: [
+ "mk_metrics_proto/mk_metrics.pb.go",
+ ],
+}
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index 80f8c1a..6f1ed60 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -41,6 +41,7 @@
"google.golang.org/protobuf/proto"
soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
+ mk_metrics_proto "android/soong/ui/metrics/mk_metrics_proto"
)
const (
@@ -62,14 +63,22 @@
Total = "total"
)
-// Metrics is a struct that stores collected metrics during the course
-// of a build which later is dumped to a MetricsBase protobuf file.
-// See ui/metrics/metrics_proto/metrics.proto for further details
-// on what information is collected.
+// Metrics is a struct that stores collected metrics during the course of a
+// build. It is later dumped to protobuf files. See underlying metrics protos
+// for further details on what information is collected.
type Metrics struct {
- // The protobuf message that is later written to the file.
+ // Protobuf containing various top-level build metrics. These include:
+ // 1. Build identifiers (ex: branch ID, requested product, hostname,
+ // originating command)
+ // 2. Per-subprocess top-level metrics (ex: ninja process IO and runtime).
+ // Note that, since these metrics are reported by soong_ui, there is little
+ // insight that can be provided into performance breakdowns of individual
+ // subprocesses.
metrics soong_metrics_proto.MetricsBase
+ // Protobuf containing metrics pertaining to number of makefiles in a build.
+ mkMetrics mk_metrics_proto.MkMetrics
+
// A list of pending build events.
EventTracer *EventTracer
}
@@ -78,11 +87,24 @@
func New() (metrics *Metrics) {
m := &Metrics{
metrics: soong_metrics_proto.MetricsBase{},
+ mkMetrics: mk_metrics_proto.MkMetrics{},
EventTracer: &EventTracer{},
}
return m
}
+func (m *Metrics) SetTotalMakefiles(total int) {
+ m.mkMetrics.TotalMakefiles = uint32(total)
+}
+
+func (m *Metrics) SetToplevelMakefiles(total int) {
+ m.mkMetrics.ToplevelMakefiles = uint32(total)
+}
+
+func (m *Metrics) DumpMkMetrics(outPath string) {
+ shared.Save(&m.mkMetrics, outPath)
+}
+
// SetTimeMetrics stores performance information from an executed block of
// code.
func (m *Metrics) SetTimeMetrics(perf soong_metrics_proto.PerfInfo) {
diff --git a/ui/metrics/mk_metrics_proto/mk_metrics.pb.go b/ui/metrics/mk_metrics_proto/mk_metrics.pb.go
new file mode 100644
index 0000000..32e136a
--- /dev/null
+++ b/ui/metrics/mk_metrics_proto/mk_metrics.pb.go
@@ -0,0 +1,177 @@
+// Copyright 2022 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.27.1
+// protoc v3.9.1
+// source: mk_metrics.proto
+
+package mk_metrics_proto
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// Contains metrics pertaining to makefiles.
+type MkMetrics struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Total number of mk files present in the workspace.
+ TotalMakefiles uint32 `protobuf:"varint,1,opt,name=totalMakefiles,proto3" json:"totalMakefiles,omitempty"`
+ // Number of top-level mk files present in the workspace.
+ // A mk file is "top level" if there are no mk files in its parent
+ // direrctories.
+ // This value is equivalent to the number of entries in Android.mk.list.
+ ToplevelMakefiles uint32 `protobuf:"varint,2,opt,name=toplevelMakefiles,proto3" json:"toplevelMakefiles,omitempty"`
+}
+
+func (x *MkMetrics) Reset() {
+ *x = MkMetrics{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_mk_metrics_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *MkMetrics) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*MkMetrics) ProtoMessage() {}
+
+func (x *MkMetrics) ProtoReflect() protoreflect.Message {
+ mi := &file_mk_metrics_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use MkMetrics.ProtoReflect.Descriptor instead.
+func (*MkMetrics) Descriptor() ([]byte, []int) {
+ return file_mk_metrics_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *MkMetrics) GetTotalMakefiles() uint32 {
+ if x != nil {
+ return x.TotalMakefiles
+ }
+ return 0
+}
+
+func (x *MkMetrics) GetToplevelMakefiles() uint32 {
+ if x != nil {
+ return x.ToplevelMakefiles
+ }
+ return 0
+}
+
+var File_mk_metrics_proto protoreflect.FileDescriptor
+
+var file_mk_metrics_proto_rawDesc = []byte{
+ 0x0a, 0x10, 0x6d, 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x12, 0x16, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
+ 0x6d, 0x6b, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x61, 0x0a, 0x09, 0x4d, 0x6b,
+ 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c,
+ 0x4d, 0x61, 0x6b, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52,
+ 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x4d, 0x61, 0x6b, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12,
+ 0x2c, 0x0a, 0x11, 0x74, 0x6f, 0x70, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x4d, 0x61, 0x6b, 0x65, 0x66,
+ 0x69, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x74, 0x6f, 0x70, 0x6c,
+ 0x65, 0x76, 0x65, 0x6c, 0x4d, 0x61, 0x6b, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x2b, 0x5a,
+ 0x29, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75,
+ 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x6b, 0x5f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x33,
+}
+
+var (
+ file_mk_metrics_proto_rawDescOnce sync.Once
+ file_mk_metrics_proto_rawDescData = file_mk_metrics_proto_rawDesc
+)
+
+func file_mk_metrics_proto_rawDescGZIP() []byte {
+ file_mk_metrics_proto_rawDescOnce.Do(func() {
+ file_mk_metrics_proto_rawDescData = protoimpl.X.CompressGZIP(file_mk_metrics_proto_rawDescData)
+ })
+ return file_mk_metrics_proto_rawDescData
+}
+
+var file_mk_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_mk_metrics_proto_goTypes = []interface{}{
+ (*MkMetrics)(nil), // 0: soong_build_mk_metrics.MkMetrics
+}
+var file_mk_metrics_proto_depIdxs = []int32{
+ 0, // [0:0] is the sub-list for method output_type
+ 0, // [0:0] is the sub-list for method input_type
+ 0, // [0:0] is the sub-list for extension type_name
+ 0, // [0:0] is the sub-list for extension extendee
+ 0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_mk_metrics_proto_init() }
+func file_mk_metrics_proto_init() {
+ if File_mk_metrics_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_mk_metrics_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*MkMetrics); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_mk_metrics_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 1,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_mk_metrics_proto_goTypes,
+ DependencyIndexes: file_mk_metrics_proto_depIdxs,
+ MessageInfos: file_mk_metrics_proto_msgTypes,
+ }.Build()
+ File_mk_metrics_proto = out.File
+ file_mk_metrics_proto_rawDesc = nil
+ file_mk_metrics_proto_goTypes = nil
+ file_mk_metrics_proto_depIdxs = nil
+}
diff --git a/ui/metrics/mk_metrics_proto/mk_metrics.proto b/ui/metrics/mk_metrics_proto/mk_metrics.proto
new file mode 100644
index 0000000..df7bca3
--- /dev/null
+++ b/ui/metrics/mk_metrics_proto/mk_metrics.proto
@@ -0,0 +1,30 @@
+// Copyright 2022 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.
+
+syntax = "proto3";
+
+package soong_build_mk_metrics;
+option go_package = "android/soong/ui/metrics/mk_metrics_proto";
+
+// Contains metrics pertaining to makefiles.
+message MkMetrics {
+ // Total number of mk files present in the workspace.
+ uint32 totalMakefiles = 1;
+
+ // Number of top-level mk files present in the workspace.
+ // A mk file is "top level" if there are no mk files in its parent
+ // direrctories.
+ // This value is equivalent to the number of entries in Android.mk.list.
+ uint32 toplevelMakefiles = 2;
+}
diff --git a/ui/metrics/mk_metrics_proto/regen.sh b/ui/metrics/mk_metrics_proto/regen.sh
new file mode 100755
index 0000000..64018d4
--- /dev/null
+++ b/ui/metrics/mk_metrics_proto/regen.sh
@@ -0,0 +1,29 @@
+#!/bin/bash -e
+
+# Copyright 2022 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.
+
+# Generates the golang source file of the mk_metrics.proto protobuf file.
+
+function die() { echo "ERROR: $1" >&2; exit 1; }
+
+readonly error_msg="Maybe you need to run 'lunch aosp_arm-eng && m aprotoc blueprint_tools'?"
+
+if ! hash aprotoc &>/dev/null; then
+ die "could not find aprotoc. ${error_msg}"
+fi
+
+if ! aprotoc --go_out=paths=source_relative:. mk_metrics.proto; then
+ die "build failed. ${error_msg}"
+fi