Merge "Fix typo"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 4fc6ae3..0647f53 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -143,6 +143,7 @@
"external/javassist": Bp2BuildDefaultTrueRecursively,
"external/jemalloc_new": Bp2BuildDefaultTrueRecursively,
"external/jsoncpp": Bp2BuildDefaultTrueRecursively,
+ "external/jsr305": Bp2BuildDefaultTrueRecursively,
"external/junit": Bp2BuildDefaultTrueRecursively,
"external/libaom": Bp2BuildDefaultTrueRecursively,
"external/libavc": Bp2BuildDefaultTrueRecursively,
@@ -369,7 +370,6 @@
"external/bazelbuild-kotlin-rules":/* recursive = */ true,
"external/bazel-skylib":/* recursive = */ true,
"external/guava":/* recursive = */ true,
- "external/jsr305":/* recursive = */ true,
"external/protobuf":/* recursive = */ false,
"external/python/absl-py":/* recursive = */ true,
@@ -379,8 +379,8 @@
"frameworks/base/tools/codegen":/* recursive = */ true,
"frameworks/ex/common":/* recursive = */ true,
+ // Building manually due to b/179889880: resource files cross package boundary
"packages/apps/Music":/* recursive = */ true,
- "packages/apps/QuickSearchBox":/* recursive = */ true,
"prebuilts/abi-dumps/platform":/* recursive = */ true,
"prebuilts/abi-dumps/ndk":/* recursive = */ true,
@@ -679,6 +679,9 @@
// kotlin srcs in android_library
"renderscript_toolkit",
+
+ //kotlin srcs in android_binary
+ "MusicKotlin",
}
Bp2buildModuleTypeAlwaysConvertList = []string{
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 9ff6b52..8c34c92 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -32,6 +32,7 @@
"android/soong/starlark_fmt"
"github.com/google/blueprint"
+ "github.com/google/blueprint/metrics"
"android/soong/bazel"
)
@@ -45,11 +46,14 @@
CommandDeps: []string{"${bazelBuildRunfilesTool}"},
}, "outDir")
allowedBazelEnvironmentVars = []string{
+ // clang-tidy
"ALLOW_LOCAL_TIDY_TRUE",
"DEFAULT_TIDY_HEADER_DIRS",
"TIDY_TIMEOUT",
"WITH_TIDY",
"WITH_TIDY_FLAGS",
+ "TIDY_EXTERNAL_VENDOR",
+
"SKIP_ABI_CHECKS",
"UNSAFE_DISABLE_APEX_ALLOWED_DEPS_CHECK",
"AUTO_ZERO_INITIALIZE",
@@ -132,6 +136,10 @@
return fmt.Sprintf("cquery(%s,%s,%s)", c.label, c.requestType.Name(), c.configKey)
}
+type invokeBazelContext interface {
+ GetEventHandler() *metrics.EventHandler
+}
+
// BazelContext is a context object useful for interacting with Bazel during
// the course of a build. Use of Bazel to evaluate part of the build graph
// is referred to as a "mixed build". (Some modules are managed by Soong,
@@ -168,7 +176,7 @@
// Issues commands to Bazel to receive results for all cquery requests
// queued in the BazelContext. The ctx argument is optional and is only
// used for performance data collection
- InvokeBazel(config Config, ctx *Context) error
+ InvokeBazel(config Config, ctx invokeBazelContext) error
// Returns true if Bazel handling is enabled for the module with the given name.
// Note that this only implies "bazel mixed build" allowlisting. The caller
@@ -188,7 +196,7 @@
type bazelRunner interface {
createBazelCommand(config Config, paths *bazelPaths, runName bazel.RunName, command bazelCommand, extraFlags ...string) *exec.Cmd
- issueBazelCommand(bazelCmd *exec.Cmd) (output string, errorMessage string, error error)
+ issueBazelCommand(bazelCmd *exec.Cmd, eventHandler *metrics.EventHandler) (output string, errorMessage string, error error)
}
type bazelPaths struct {
@@ -296,7 +304,7 @@
return result, nil
}
-func (m MockBazelContext) InvokeBazel(_ Config, _ *Context) error {
+func (m MockBazelContext) InvokeBazel(_ Config, _ invokeBazelContext) error {
panic("unimplemented")
}
@@ -414,7 +422,7 @@
panic("implement me")
}
-func (n noopBazelContext) InvokeBazel(_ Config, _ *Context) error {
+func (n noopBazelContext) InvokeBazel(_ Config, _ invokeBazelContext) error {
panic("unimplemented")
}
@@ -592,7 +600,7 @@
return cmd
}
-func (r *mockBazelRunner) issueBazelCommand(bazelCmd *exec.Cmd) (string, string, error) {
+func (r *mockBazelRunner) issueBazelCommand(bazelCmd *exec.Cmd, _ *metrics.EventHandler) (string, string, error) {
if command, ok := r.tokens[bazelCmd]; ok {
return r.bazelCommandResults[command], "", nil
}
@@ -605,7 +613,9 @@
// Returns (stdout, stderr, error). The first and second return values are strings
// containing the stdout and stderr of the run command, and an error is returned if
// the invocation returned an error code.
-func (r *builtinBazelRunner) issueBazelCommand(bazelCmd *exec.Cmd) (string, string, error) {
+func (r *builtinBazelRunner) issueBazelCommand(bazelCmd *exec.Cmd, eventHandler *metrics.EventHandler) (string, string, error) {
+ eventHandler.Begin("bazel command")
+ defer eventHandler.End("bazel command")
stderr := &bytes.Buffer{}
bazelCmd.Stderr = stderr
if output, err := bazelCmd.Output(); err != nil {
@@ -982,11 +992,10 @@
// Issues commands to Bazel to receive results for all cquery requests
// queued in the BazelContext.
-func (context *mixedBuildBazelContext) InvokeBazel(config Config, ctx *Context) error {
- if ctx != nil {
- ctx.EventHandler.Begin("bazel")
- defer ctx.EventHandler.End("bazel")
- }
+func (context *mixedBuildBazelContext) InvokeBazel(config Config, ctx invokeBazelContext) error {
+ eventHandler := ctx.GetEventHandler()
+ eventHandler.Begin("bazel")
+ defer eventHandler.End("bazel")
if metricsDir := context.paths.BazelMetricsDir(); metricsDir != "" {
if err := os.MkdirAll(metricsDir, 0777); err != nil {
@@ -1009,11 +1018,10 @@
return nil
}
-func (context *mixedBuildBazelContext) runCquery(config Config, ctx *Context) error {
- if ctx != nil {
- ctx.EventHandler.Begin("cquery")
- defer ctx.EventHandler.End("cquery")
- }
+func (context *mixedBuildBazelContext) runCquery(config Config, ctx invokeBazelContext) error {
+ eventHandler := ctx.GetEventHandler()
+ eventHandler.Begin("cquery")
+ defer eventHandler.End("cquery")
soongInjectionPath := absolutePath(context.paths.injectedFilesDir())
mixedBuildsPath := filepath.Join(soongInjectionPath, "mixed_builds")
if _, err := os.Stat(mixedBuildsPath); os.IsNotExist(err) {
@@ -1038,7 +1046,7 @@
cqueryCommandWithFlag := context.createBazelCommand(config, context.paths, bazel.CqueryBuildRootRunName, cqueryCmd,
"--output=starlark", "--starlark:file="+absolutePath(cqueryFileRelpath))
- cqueryOutput, cqueryErrorMessage, cqueryErr := context.issueBazelCommand(cqueryCommandWithFlag)
+ cqueryOutput, cqueryErrorMessage, cqueryErr := context.issueBazelCommand(cqueryCommandWithFlag, eventHandler)
if cqueryErr != nil {
return cqueryErr
}
@@ -1072,11 +1080,10 @@
return nil
}
-func (context *mixedBuildBazelContext) runAquery(config Config, ctx *Context) error {
- if ctx != nil {
- ctx.EventHandler.Begin("aquery")
- defer ctx.EventHandler.End("aquery")
- }
+func (context *mixedBuildBazelContext) runAquery(config Config, ctx invokeBazelContext) error {
+ eventHandler := ctx.GetEventHandler()
+ eventHandler.Begin("aquery")
+ defer eventHandler.End("aquery")
// Issue an aquery command to retrieve action information about the bazel build tree.
//
// Use jsonproto instead of proto; actual proto parsing would require a dependency on Bazel's
@@ -1102,23 +1109,22 @@
}
}
aqueryOutput, _, err := context.issueBazelCommand(context.createBazelCommand(config, context.paths, bazel.AqueryBuildRootRunName, aqueryCmd,
- extraFlags...))
+ extraFlags...), eventHandler)
if err != nil {
return err
}
- context.buildStatements, context.depsets, err = bazel.AqueryBuildStatements([]byte(aqueryOutput))
+ context.buildStatements, context.depsets, err = bazel.AqueryBuildStatements([]byte(aqueryOutput), eventHandler)
return err
}
-func (context *mixedBuildBazelContext) generateBazelSymlinks(config Config, ctx *Context) error {
- if ctx != nil {
- ctx.EventHandler.Begin("symlinks")
- defer ctx.EventHandler.End("symlinks")
- }
+func (context *mixedBuildBazelContext) generateBazelSymlinks(config Config, ctx invokeBazelContext) error {
+ eventHandler := ctx.GetEventHandler()
+ eventHandler.Begin("symlinks")
+ defer eventHandler.End("symlinks")
// Issue a build command of the phony root to generate symlink forests for dependencies of the
// Bazel build. This is necessary because aquery invocations do not generate this symlink forest,
// but some of symlinks may be required to resolve source dependencies of the build.
- _, _, err := context.issueBazelCommand(context.createBazelCommand(config, context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd))
+ _, _, err := context.issueBazelCommand(context.createBazelCommand(config, context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd), eventHandler)
return err
}
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index d971802..4a4ecb5 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -11,11 +11,18 @@
"android/soong/bazel/cquery"
analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
+ "github.com/google/blueprint/metrics"
"google.golang.org/protobuf/proto"
)
var testConfig = TestConfig("out", nil, "", nil)
+type testInvokeBazelContext struct{}
+
+func (t *testInvokeBazelContext) GetEventHandler() *metrics.EventHandler {
+ return &metrics.EventHandler{}
+}
+
func TestRequestResultsAfterInvokeBazel(t *testing.T) {
label := "@//foo:bar"
cfg := configKey{"arm64_armv8-a", Android}
@@ -23,7 +30,7 @@
bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: `@//foo:bar|arm64_armv8-a|android>>out/foo/bar.txt`,
})
bazelContext.QueueBazelRequest(label, cquery.GetOutputFiles, cfg)
- err := bazelContext.InvokeBazel(testConfig, nil)
+ err := bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
if err != nil {
t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
}
@@ -37,7 +44,7 @@
func TestInvokeBazelWritesBazelFiles(t *testing.T) {
bazelContext, baseDir := testBazelContext(t, map[bazelCommand]string{})
- err := bazelContext.InvokeBazel(testConfig, nil)
+ err := bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
if err != nil {
t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
}
@@ -118,7 +125,7 @@
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: string(data)})
- err = bazelContext.InvokeBazel(testConfig, nil)
+ err = bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
if err != nil {
t.Fatalf("testCase #%d: did not expect error invoking Bazel, but got %s", i+1, err)
}
@@ -197,7 +204,7 @@
func verifyExtraFlags(t *testing.T, config Config, expected string) string {
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
- err := bazelContext.InvokeBazel(config, nil)
+ err := bazelContext.InvokeBazel(config, &testInvokeBazelContext{})
if err != nil {
t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
}
diff --git a/android/config.go b/android/config.go
index bb3cc97..c0f84c8 100644
--- a/android/config.go
+++ b/android/config.go
@@ -727,6 +727,10 @@
return value == "0" || value == "n" || value == "no" || value == "off" || value == "false"
}
+func (c *config) TargetsJava17() bool {
+ return c.IsEnvTrue("EXPERIMENTAL_TARGET_JAVA_VERSION_17")
+}
+
// EnvDeps returns the environment variables this build depends on. The first
// call to this function blocks future reads from the environment.
func (c *config) EnvDeps() map[string]string {
diff --git a/android/mutator.go b/android/mutator.go
index 4e55609..4dacb8d 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -709,24 +709,29 @@
// module and returns it as a list of keyed tags.
func ApexAvailableTags(mod Module) bazel.StringListAttribute {
attr := bazel.StringListAttribute{}
- tags := []string{}
// Transform specific attributes into tags.
if am, ok := mod.(ApexModule); ok {
// TODO(b/218841706): hidl_interface has the apex_available prop, but it's
// defined directly as a prop and not via ApexModule, so this doesn't
// pick those props up.
- // TODO(b/260694842): This does not pick up aidl_interface.backend.ndk.apex_available.
- for _, a := range am.apexModuleBase().ApexAvailable() {
- tags = append(tags, "apex_available="+a)
- }
- }
- if len(tags) > 0 {
- // This avoids creating a tags attr with an empty list if there are no tags.
- attr.Value = tags
+ attr.Value = ConvertApexAvailableToTags(am.apexModuleBase().ApexAvailable())
}
return attr
}
+func ConvertApexAvailableToTags(apexAvailable []string) []string {
+ if len(apexAvailable) == 0 {
+ // We need nil specifically to make bp2build not add the tags property at all,
+ // instead of adding it with an empty list
+ return nil
+ }
+ result := make([]string, 0, len(apexAvailable))
+ for _, a := range apexAvailable {
+ result = append(result, "apex_available="+a)
+ }
+ return result
+}
+
func (t *topDownMutatorContext) createBazelTargetModule(
bazelProps bazel.BazelTargetModuleProperties,
commonAttrs CommonAttributes,
diff --git a/android/mutator_test.go b/android/mutator_test.go
index 21eebd2..dbdfa33 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "reflect"
"strings"
"testing"
@@ -267,3 +268,22 @@
FixtureWithRootAndroidBp(`test {name: "foo"}`),
).RunTest(t)
}
+
+func TestConvertApexAvailableToTags(t *testing.T) {
+ input := []string{
+ "com.android.adbd",
+ "//apex_available:platform",
+ }
+ actual := ConvertApexAvailableToTags(input)
+ expected := []string{
+ "apex_available=com.android.adbd",
+ "apex_available=//apex_available:platform",
+ }
+ if !reflect.DeepEqual(actual, expected) {
+ t.Errorf("Expected: %v, actual: %v", expected, actual)
+ }
+
+ if ConvertApexAvailableToTags(nil) != nil {
+ t.Errorf("Expected providing nil to return nil")
+ }
+}
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index 6faed70..1581949 100644
--- a/apex/apex_singleton.go
+++ b/apex/apex_singleton.go
@@ -55,17 +55,17 @@
touch ${out};
else
echo -e "\n******************************";
- echo "ERROR: go/apex-allowed-deps-error";
+ echo "ERROR: go/apex-allowed-deps-error contains more information";
echo "******************************";
echo "Detected changes to allowed dependencies in updatable modules.";
echo "To fix and update packages/modules/common/build/allowed_deps.txt, please run:";
echo -e "$$ (croot && packages/modules/common/build/update-apex-allowed-deps.sh)\n";
echo "When submitting the generated CL, you must include the following information";
echo "in the commit message if you are adding a new dependency:";
- echo "Apex-Size-Increase:";
- echo "Previous-Platform-Support:";
- echo "Aosp-First:";
- echo "Test-Info:";
+ echo "Apex-Size-Increase: Expected binary size increase for affected APEXes (or the size of the .jar / .so file of the new library)";
+ echo "Previous-Platform-Support: Are the maintainers of the new dependency committed to supporting previous platform releases?";
+ echo "Aosp-First: Is the new dependency being developed AOSP-first or internal?";
+ echo "Test-Info: What’s the testing strategy for the new dependency? Does it have its own tests, and are you adding integration tests? How/when are the tests run?";
echo "You do not need OWNERS approval to submit the change, but mainline-modularization@";
echo "will periodically review additions and may require changes.";
echo -e "******************************\n";
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 80cf70a..6af472a 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -23,9 +23,11 @@
"sort"
"strings"
+ analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
+
+ "github.com/google/blueprint/metrics"
"github.com/google/blueprint/proptools"
"google.golang.org/protobuf/proto"
- analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
)
type artifactId int
@@ -313,7 +315,7 @@
// action graph, as described by the given action graph json proto.
// BuildStatements are one-to-one with actions in the given action graph, and AqueryDepsets
// are one-to-one with Bazel's depSetOfFiles objects.
-func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, []AqueryDepset, error) {
+func AqueryBuildStatements(aqueryJsonProto []byte, eventHandler *metrics.EventHandler) ([]BuildStatement, []AqueryDepset, error) {
aqueryProto := &analysis_v2_proto.ActionGraphContainer{}
err := proto.Unmarshal(aqueryJsonProto, aqueryProto)
if err != nil {
@@ -387,74 +389,92 @@
ParentId: pathFragmentId(protoPathFragments.ParentId)})
}
- aqueryHandler, err := newAqueryHandler(aqueryResult)
- if err != nil {
- return nil, nil, err
- }
- var buildStatements []BuildStatement
- for _, actionEntry := range aqueryResult.Actions {
- if shouldSkipAction(actionEntry) {
- continue
- }
-
- var buildStatement BuildStatement
- if actionEntry.isSymlinkAction() {
- buildStatement, err = aqueryHandler.symlinkActionBuildStatement(actionEntry)
- } else if actionEntry.isTemplateExpandAction() && len(actionEntry.Arguments) < 1 {
- buildStatement, err = aqueryHandler.templateExpandActionBuildStatement(actionEntry)
- } else if actionEntry.isFileWriteAction() {
- buildStatement, err = aqueryHandler.fileWriteActionBuildStatement(actionEntry)
- } else if actionEntry.isSymlinkTreeAction() {
- buildStatement, err = aqueryHandler.symlinkTreeActionBuildStatement(actionEntry)
- } else if len(actionEntry.Arguments) < 1 {
- return nil, nil, fmt.Errorf("received action with no command: [%s]", actionEntry.Mnemonic)
- } else {
- buildStatement, err = aqueryHandler.normalActionBuildStatement(actionEntry)
- }
-
+ var aqueryHandler *aqueryArtifactHandler
+ {
+ eventHandler.Begin("init_handler")
+ defer eventHandler.End("init_handler")
+ aqueryHandler, err = newAqueryHandler(aqueryResult)
if err != nil {
return nil, nil, err
}
- buildStatements = append(buildStatements, buildStatement)
+ }
+
+ var buildStatements []BuildStatement
+ {
+ eventHandler.Begin("build_statements")
+ defer eventHandler.End("build_statements")
+ for _, actionEntry := range aqueryResult.Actions {
+ if shouldSkipAction(actionEntry) {
+ continue
+ }
+
+ var buildStatement BuildStatement
+ if actionEntry.isSymlinkAction() {
+ buildStatement, err = aqueryHandler.symlinkActionBuildStatement(actionEntry)
+ } else if actionEntry.isTemplateExpandAction() && len(actionEntry.Arguments) < 1 {
+ buildStatement, err = aqueryHandler.templateExpandActionBuildStatement(actionEntry)
+ } else if actionEntry.isFileWriteAction() {
+ buildStatement, err = aqueryHandler.fileWriteActionBuildStatement(actionEntry)
+ } else if actionEntry.isSymlinkTreeAction() {
+ buildStatement, err = aqueryHandler.symlinkTreeActionBuildStatement(actionEntry)
+ } else if len(actionEntry.Arguments) < 1 {
+ err = fmt.Errorf("received action with no command: [%s]", actionEntry.Mnemonic)
+ } else {
+ buildStatement, err = aqueryHandler.normalActionBuildStatement(actionEntry)
+ }
+
+ if err != nil {
+ return nil, nil, err
+ }
+ buildStatements = append(buildStatements, buildStatement)
+ }
}
depsetsByHash := map[string]AqueryDepset{}
var depsets []AqueryDepset
- for _, aqueryDepset := range aqueryHandler.depsetIdToAqueryDepset {
- if prevEntry, hasKey := depsetsByHash[aqueryDepset.ContentHash]; hasKey {
- // Two depsets collide on hash. Ensure that their contents are identical.
- if !reflect.DeepEqual(aqueryDepset, prevEntry) {
- return nil, nil, fmt.Errorf("two different depsets have the same hash: %v, %v", prevEntry, aqueryDepset)
+ {
+ eventHandler.Begin("depsets")
+ defer eventHandler.End("depsets")
+ for _, aqueryDepset := range aqueryHandler.depsetIdToAqueryDepset {
+ if prevEntry, hasKey := depsetsByHash[aqueryDepset.ContentHash]; hasKey {
+ // Two depsets collide on hash. Ensure that their contents are identical.
+ if !reflect.DeepEqual(aqueryDepset, prevEntry) {
+ return nil, nil, fmt.Errorf("two different depsets have the same hash: %v, %v", prevEntry, aqueryDepset)
+ }
+ } else {
+ depsetsByHash[aqueryDepset.ContentHash] = aqueryDepset
+ depsets = append(depsets, aqueryDepset)
}
- } else {
- depsetsByHash[aqueryDepset.ContentHash] = aqueryDepset
- depsets = append(depsets, aqueryDepset)
}
}
- // Build Statements and depsets must be sorted by their content hash to
- // preserve determinism between builds (this will result in consistent ninja file
- // output). Note they are not sorted by their original IDs nor their Bazel ordering,
- // as Bazel gives nondeterministic ordering / identifiers in aquery responses.
- sort.Slice(buildStatements, func(i, j int) bool {
- // For build statements, compare output lists. In Bazel, each output file
- // may only have one action which generates it, so this will provide
- // a deterministic ordering.
- outputs_i := buildStatements[i].OutputPaths
- outputs_j := buildStatements[j].OutputPaths
- if len(outputs_i) != len(outputs_j) {
- return len(outputs_i) < len(outputs_j)
- }
- if len(outputs_i) == 0 {
- // No outputs for these actions, so compare commands.
- return buildStatements[i].Command < buildStatements[j].Command
- }
- // There may be multiple outputs, but the output ordering is deterministic.
- return outputs_i[0] < outputs_j[0]
+ eventHandler.Do("build_statement_sort", func() {
+ // Build Statements and depsets must be sorted by their content hash to
+ // preserve determinism between builds (this will result in consistent ninja file
+ // output). Note they are not sorted by their original IDs nor their Bazel ordering,
+ // as Bazel gives nondeterministic ordering / identifiers in aquery responses.
+ sort.Slice(buildStatements, func(i, j int) bool {
+ // For build statements, compare output lists. In Bazel, each output file
+ // may only have one action which generates it, so this will provide
+ // a deterministic ordering.
+ outputs_i := buildStatements[i].OutputPaths
+ outputs_j := buildStatements[j].OutputPaths
+ if len(outputs_i) != len(outputs_j) {
+ return len(outputs_i) < len(outputs_j)
+ }
+ if len(outputs_i) == 0 {
+ // No outputs for these actions, so compare commands.
+ return buildStatements[i].Command < buildStatements[j].Command
+ }
+ // There may be multiple outputs, but the output ordering is deterministic.
+ return outputs_i[0] < outputs_j[0]
+ })
})
- sort.Slice(depsets, func(i, j int) bool {
- return depsets[i].ContentHash < depsets[j].ContentHash
+ eventHandler.Do("depset_sort", func() {
+ sort.Slice(depsets, func(i, j int) bool {
+ return depsets[i].ContentHash < depsets[j].ContentHash
+ })
})
return buildStatements, depsets, nil
}
@@ -651,17 +671,18 @@
return replacer.Replace(actionEntry.TemplateContent)
}
+// \->\\, $->\$, `->\`, "->\", \n->\\n, '->'"'"'
+var commandLineArgumentReplacer = strings.NewReplacer(
+ `\`, `\\`,
+ `$`, `\$`,
+ "`", "\\`",
+ `"`, `\"`,
+ "\n", "\\n",
+ `'`, `'"'"'`,
+)
+
func escapeCommandlineArgument(str string) string {
- // \->\\, $->\$, `->\`, "->\", \n->\\n, '->'"'"'
- replacer := strings.NewReplacer(
- `\`, `\\`,
- `$`, `\$`,
- "`", "\\`",
- `"`, `\"`,
- "\n", "\\n",
- `'`, `'"'"'`,
- )
- return replacer.Replace(str)
+ return commandLineArgumentReplacer.Replace(str)
}
func (a action) isSymlinkAction() bool {
diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go
index 4d1503e..c6b139e 100644
--- a/bazel/aquery_test.go
+++ b/bazel/aquery_test.go
@@ -21,8 +21,10 @@
"sort"
"testing"
- "google.golang.org/protobuf/proto"
analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
+
+ "github.com/google/blueprint/metrics"
+ "google.golang.org/protobuf/proto"
)
func TestAqueryMultiArchGenrule(t *testing.T) {
@@ -136,7 +138,7 @@
t.Error(err)
return
}
- actualbuildStatements, actualDepsets, _ := AqueryBuildStatements(data)
+ actualbuildStatements, actualDepsets, _ := AqueryBuildStatements(data, &metrics.EventHandler{})
var expectedBuildStatements []BuildStatement
for _, arch := range []string{"arm", "arm64", "x86", "x86_64"} {
expectedBuildStatements = append(expectedBuildStatements,
@@ -195,7 +197,7 @@
t.Error(err)
return
}
- _, _, err = AqueryBuildStatements(data)
+ _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
assertError(t, err, "undefined outputId 3")
}
@@ -226,7 +228,7 @@
t.Error(err)
return
}
- _, _, err = AqueryBuildStatements(data)
+ _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
assertError(t, err, "undefined (not even empty) input depsetId 2")
}
@@ -257,7 +259,7 @@
t.Error(err)
return
}
- _, _, err = AqueryBuildStatements(data)
+ _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
assertError(t, err, "undefined input depsetId 42 (referenced by depsetId 1)")
}
@@ -288,7 +290,7 @@
t.Error(err)
return
}
- _, _, err = AqueryBuildStatements(data)
+ _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
assertError(t, err, "undefined input artifactId 3")
}
@@ -319,7 +321,7 @@
t.Error(err)
return
}
- _, _, err = AqueryBuildStatements(data)
+ _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
assertError(t, err, "undefined path fragment id 3")
}
@@ -352,7 +354,7 @@
t.Error(err)
return
}
- actual, _, err := AqueryBuildStatements(data)
+ actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -402,7 +404,7 @@
t.Error(err)
return
}
- _, _, err = AqueryBuildStatements(data)
+ _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
assertError(t, err, `found multiple potential depfiles "two.d", "other.d"`)
}
@@ -483,7 +485,7 @@
t.Error(err)
return
}
- actualbuildStatements, actualDepsets, _ := AqueryBuildStatements(data)
+ actualbuildStatements, actualDepsets, _ := AqueryBuildStatements(data, &metrics.EventHandler{})
expectedBuildStatements := []BuildStatement{
{
@@ -538,7 +540,7 @@
t.Error(err)
return
}
- actual, _, err := AqueryBuildStatements(data)
+ actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -594,7 +596,7 @@
t.Error(err)
return
}
- actualBuildStatements, actualDepsets, _ := AqueryBuildStatements(data)
+ actualBuildStatements, actualDepsets, _ := AqueryBuildStatements(data, &metrics.EventHandler{})
if len(actualDepsets) != 1 {
t.Errorf("expected 1 depset but found %#v", actualDepsets)
return
@@ -681,7 +683,7 @@
t.Error(err)
return
}
- actualBuildStatements, actualDepsets, _ := AqueryBuildStatements(data)
+ actualBuildStatements, actualDepsets, _ := AqueryBuildStatements(data, &metrics.EventHandler{})
if len(actualDepsets) != 0 {
t.Errorf("expected 0 depsets but found %#v", actualDepsets)
return
@@ -748,7 +750,7 @@
t.Error(err)
return
}
- actualBuildStatements, actualDepsets, err := AqueryBuildStatements(data)
+ actualBuildStatements, actualDepsets, err := AqueryBuildStatements(data, &metrics.EventHandler{})
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -845,7 +847,7 @@
t.Error(err)
return
}
- actual, _, err := AqueryBuildStatements(data)
+ actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
if err != nil {
t.Errorf("Unexpected error %q", err)
@@ -894,7 +896,7 @@
t.Error(err)
return
}
- actual, _, err := AqueryBuildStatements(data)
+ actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -940,7 +942,7 @@
t.Error(err)
return
}
- _, _, err = AqueryBuildStatements(data)
+ _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
assertError(t, err, `Expect 1 input and 1 output to symlink action, got: input ["file" "other_file"], output ["symlink"]`)
}
@@ -971,7 +973,7 @@
t.Error(err)
return
}
- _, _, err = AqueryBuildStatements(data)
+ _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
assertError(t, err, "undefined outputId 2")
}
@@ -1004,7 +1006,7 @@
t.Error(err)
return
}
- actual, _, err := AqueryBuildStatements(data)
+ actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -1046,7 +1048,7 @@
t.Error(err)
return
}
- _, _, err = AqueryBuildStatements(data)
+ _, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
assertError(t, err, `Expect 1 output to template expand action, got: output []`)
}
@@ -1074,7 +1076,7 @@
t.Error(err)
return
}
- actual, _, err := AqueryBuildStatements(data)
+ actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -1111,7 +1113,7 @@
t.Error(err)
return
}
- actual, _, err := AqueryBuildStatements(data)
+ actual, _, err := AqueryBuildStatements(data, &metrics.EventHandler{})
if err != nil {
t.Errorf("Unexpected error %q", err)
}
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
index 67208b2..b3619c8 100644
--- a/cc/config/riscv64_device.go
+++ b/cc/config/riscv64_device.go
@@ -35,7 +35,9 @@
}
riscv64Lldflags = append(riscv64Ldflags,
- "-Wl,-z,max-page-size=4096")
+ "-Wl,-z,max-page-size=4096",
+ "-Wl,-plugin-opt,-emulated-tls=0",
+ )
riscv64Cppflags = []string{}
diff --git a/cc/lto.go b/cc/lto.go
index 1afa1dd..581856b 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -91,11 +91,6 @@
return flags
}
- // TODO(b/254713216): LTO doesn't work on riscv64 yet.
- if ctx.Arch().ArchType == android.Riscv64 {
- return flags
- }
-
if lto.LTO(ctx) {
var ltoCFlag string
var ltoLdFlag string
diff --git a/cc/lto_test.go b/cc/lto_test.go
index cee5aa3..4220f32 100644
--- a/cc/lto_test.go
+++ b/cc/lto_test.go
@@ -209,3 +209,33 @@
android.AssertStringDoesNotContain(t, "got flag for LTO in variant that doesn't expect it",
libFooWithoutLto.Args["ldFlags"], "-flto=thin")
}
+
+func TestLtoDoesNotPropagateToRuntimeLibs(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library {
+ name: "runtime_libbar",
+ srcs: ["bar.c"],
+ }
+
+ cc_library {
+ name: "libfoo",
+ srcs: ["foo.c"],
+ runtime_libs: ["runtime_libbar"],
+ lto: {
+ thin: true,
+ },
+ }`
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ ).RunTestWithBp(t, bp)
+
+ libFoo := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
+ libBar := result.ModuleForTests("runtime_libbar", "android_arm_armv7-a-neon_shared").Rule("ld")
+
+ android.AssertStringDoesContain(t, "missing flag for LTO in LTO enabled library",
+ libFoo.Args["ldFlags"], "-flto=thin")
+ android.AssertStringDoesNotContain(t, "got flag for LTO in runtime_lib",
+ libBar.Args["ldFlags"], "-flto=thin")
+}
diff --git a/java/java.go b/java/java.go
index 874f935..659f98a 100644
--- a/java/java.go
+++ b/java/java.go
@@ -517,8 +517,14 @@
return normalizeJavaVersion(ctx, javaVersion)
} else if ctx.Device() {
return defaultJavaLanguageVersion(ctx, sdkContext.SdkVersion(ctx))
- } else {
+ } else if ctx.Config().TargetsJava17() {
+ // Temporary experimental flag to be able to try and build with
+ // java version 17 options. The flag, if used, just sets Java
+ // 17 as the default version, leaving any components that
+ // target an older version intact.
return JAVA_VERSION_17
+ } else {
+ return JAVA_VERSION_11
}
}
diff --git a/java/robolectric.go b/java/robolectric.go
index 68f27b8..008b8b1 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -302,6 +302,9 @@
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", "robolectric-tests")
+ if r.testConfig != nil {
+ entries.SetPath("LOCAL_FULL_TEST_CONFIG", r.testConfig)
+ }
})
entries.ExtraFooters = []android.AndroidMkExtraFootersFunc{
diff --git a/java/sdk.go b/java/sdk.go
index 10ae3f6..b0da5af 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -57,10 +57,14 @@
return JAVA_VERSION_8
} else if sdk.FinalOrFutureInt() <= 31 {
return JAVA_VERSION_9
- } else if sdk.FinalOrFutureInt() <= 32 {
- return JAVA_VERSION_11
- } else {
+ } else if ctx.Config().TargetsJava17() {
+ // Temporary experimental flag to be able to try and build with
+ // java version 17 options. The flag, if used, just sets Java
+ // 17 as the default version, leaving any components that
+ // target an older version intact.
return JAVA_VERSION_17
+ } else {
+ return JAVA_VERSION_11
}
}
diff --git a/rust/compiler.go b/rust/compiler.go
index 8ec42f0..31acd49 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -208,6 +208,10 @@
panic("baseCompiler does not implement SetDisabled()")
}
+func (compiler *baseCompiler) noStdlibs() bool {
+ return Bool(compiler.Properties.No_stdlibs)
+}
+
func (compiler *baseCompiler) coverageOutputZipPath() android.OptionalPath {
panic("baseCompiler does not implement coverageOutputZipPath()")
}
diff --git a/rust/config/global.go b/rust/config/global.go
index 50ac1f7..ef428b8 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.65.0.p1"
+ RustDefaultVersion = "1.66.1"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2021"
Stdlibs = []string{
diff --git a/rust/coverage.go b/rust/coverage.go
index 5ea481f..bc6504d 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -21,6 +21,7 @@
)
var CovLibraryName = "libprofile-clang-extras"
+var ProfilerBuiltins = "libprofiler_builtins.rust_sysroot"
// Add '%c' to default specifier after we resolve http://b/210012154
const profileInstrFlag = "-fprofile-instr-generate=/data/misc/trace/clang-%p-%m.profraw"
@@ -41,6 +42,11 @@
ctx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
}, cc.CoverageDepTag, CovLibraryName)
+
+ // no_std modules are missing libprofiler_builtins which provides coverage, so we need to add it as a dependency.
+ if rustModule, ok := ctx.Module().(*Module); ok && rustModule.compiler.noStdlibs() {
+ ctx.AddVariationDependencies([]blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}, rlibDepTag, ProfilerBuiltins)
+ }
}
return deps
@@ -60,6 +66,13 @@
flags.LinkFlags = append(flags.LinkFlags,
profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open")
deps.StaticLibs = append(deps.StaticLibs, coverage.OutputFile().Path())
+
+ // no_std modules are missing libprofiler_builtins which provides coverage, so we need to add it as a dependency.
+ if rustModule, ok := ctx.Module().(*Module); ok && rustModule.compiler.noStdlibs() {
+ profiler_builtins := ctx.GetDirectDepWithTag(ProfilerBuiltins, rlibDepTag).(*Module)
+ deps.RLibs = append(deps.RLibs, RustLibrary{Path: profiler_builtins.OutputFile().Path(), CrateName: profiler_builtins.CrateName()})
+ }
+
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")
diff --git a/rust/rust.go b/rust/rust.go
index 67e0d7c..e4cf671 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -490,6 +490,7 @@
SetDisabled()
stdLinkage(ctx *depsContext) RustLinkage
+ noStdlibs() bool
unstrippedOutputFilePath() android.Path
strippedOutputFilePath() android.OptionalPath
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index f3bad73..fda5ca0 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -803,7 +803,6 @@
setup
mkdir -p "a/${GENERATED_BUILD_FILE_NAME}"
- touch a/a.txt
cat > a/Android.bp <<EOF
filegroup {
name: "a",
@@ -813,7 +812,6 @@
EOF
mkdir -p "b/${GENERATED_BUILD_FILE_NAME}"
- touch b/b.txt
cat > b/Android.bp <<EOF
filegroup {
name: "b",
@@ -826,8 +824,8 @@
fail "Build should have failed"
fi
- grep -q "a/${GENERATED_BUILD_FILE_NAME}' exist" "$MOCK_TOP/errors" || fail "Error for a/${GENERATED_BUILD_FILE_NAME} not found"
- grep -q -v "b/${GENERATED_BUILD_FILE_NAME}' exist" "$MOCK_TOP/errors" || fail "Error for b/${GENERATED_BUILD_FILE_NAME} found but not expected"
+ # we should expect at least one error
+ grep -q -E "(a|b)/${GENERATED_BUILD_FILE_NAME}' exist" "$MOCK_TOP/errors" || fail "Error for ${GENERATED_BUILD_FILE_NAME} not found"
}
function test_bp2build_back_and_forth_null_build {