Merge "Add tidy_timeout_srcs property"
diff --git a/android/bazel.go b/android/bazel.go
index 4a96918..f4fc038 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -540,6 +540,31 @@
"libadb_pairing_connection",
"libadb_pairing_connection_static",
"libadb_pairing_server", "libadb_pairing_server_static",
+
+ // TODO(b/204811222) support suffix in cc_binary
+ "acvp_modulewrapper",
+ "android.hardware.media.c2@1.0-service-v4l2",
+ "app_process",
+ "bar_test",
+ "bench_cxa_atexit",
+ "bench_noop",
+ "bench_noop_nostl",
+ "bench_noop_static",
+ "boringssl_self_test",
+ "boringssl_self_test_vendor",
+ "bssl",
+ "cavp",
+ "crash_dump",
+ "crasher",
+ "libcxx_test_template",
+ "linker",
+ "memory_replay",
+ "native_bridge_guest_linker",
+ "native_bridge_stub_library_defaults",
+ "noop",
+ "simpleperf_ndk",
+ "toybox-static",
+ "zlib_bench",
}
// Used for quicker lookups
diff --git a/android/util.go b/android/util.go
index 0ee253e..47c4583 100644
--- a/android/util.go
+++ b/android/util.go
@@ -65,21 +65,55 @@
return buf.String()
}
-// SorterStringKeys returns the keys of the given string-keyed map in the ascending order
+// SorterStringKeys returns the keys of the given string-keyed map in the ascending order.
func SortedStringKeys(m interface{}) []string {
v := reflect.ValueOf(m)
if v.Kind() != reflect.Map {
panic(fmt.Sprintf("%#v is not a map", m))
}
- keys := v.MapKeys()
- s := make([]string, 0, len(keys))
- for _, key := range keys {
- s = append(s, key.String())
+ if v.Len() == 0 {
+ return nil
+ }
+ iter := v.MapRange()
+ s := make([]string, 0, v.Len())
+ for iter.Next() {
+ s = append(s, iter.Key().String())
}
sort.Strings(s)
return s
}
+// stringValues returns the values of the given string-valued map in randomized map order.
+func stringValues(m interface{}) []string {
+ v := reflect.ValueOf(m)
+ if v.Kind() != reflect.Map {
+ panic(fmt.Sprintf("%#v is not a map", m))
+ }
+ if v.Len() == 0 {
+ return nil
+ }
+ iter := v.MapRange()
+ s := make([]string, 0, v.Len())
+ for iter.Next() {
+ s = append(s, iter.Value().String())
+ }
+ return s
+}
+
+// SortedStringValues returns the values of the given string-valued map in the ascending order.
+func SortedStringValues(m interface{}) []string {
+ s := stringValues(m)
+ sort.Strings(s)
+ return s
+}
+
+// SortedUniqueStringValues returns the values of the given string-valued map in the ascending order
+// with duplicates removed.
+func SortedUniqueStringValues(m interface{}) []string {
+ s := stringValues(m)
+ return SortedUniqueStrings(s)
+}
+
// IndexList returns the index of the first occurrence of the given string in the list or -1
func IndexList(s string, list []string) int {
for i, l := range list {
diff --git a/android/util_test.go b/android/util_test.go
index 09bec01..9b9253b 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -640,3 +640,117 @@
})
}
}
+
+func TestSortedStringKeys(t *testing.T) {
+ testCases := []struct {
+ name string
+ in interface{}
+ expected []string
+ }{
+ {
+ name: "nil",
+ in: map[string]string(nil),
+ expected: nil,
+ },
+ {
+ name: "empty",
+ in: map[string]string{},
+ expected: nil,
+ },
+ {
+ name: "simple",
+ in: map[string]string{"a": "foo", "b": "bar"},
+ expected: []string{"a", "b"},
+ },
+ {
+ name: "interface values",
+ in: map[string]interface{}{"a": nil, "b": nil},
+ expected: []string{"a", "b"},
+ },
+ }
+
+ for _, tt := range testCases {
+ t.Run(tt.name, func(t *testing.T) {
+ got := SortedStringKeys(tt.in)
+ if g, w := got, tt.expected; !reflect.DeepEqual(g, w) {
+ t.Errorf("wanted %q, got %q", w, g)
+ }
+ })
+ }
+}
+
+func TestSortedStringValues(t *testing.T) {
+ testCases := []struct {
+ name string
+ in interface{}
+ expected []string
+ }{
+ {
+ name: "nil",
+ in: map[string]string(nil),
+ expected: nil,
+ },
+ {
+ name: "empty",
+ in: map[string]string{},
+ expected: nil,
+ },
+ {
+ name: "simple",
+ in: map[string]string{"foo": "a", "bar": "b"},
+ expected: []string{"a", "b"},
+ },
+ {
+ name: "duplicates",
+ in: map[string]string{"foo": "a", "bar": "b", "baz": "b"},
+ expected: []string{"a", "b", "b"},
+ },
+ }
+
+ for _, tt := range testCases {
+ t.Run(tt.name, func(t *testing.T) {
+ got := SortedStringValues(tt.in)
+ if g, w := got, tt.expected; !reflect.DeepEqual(g, w) {
+ t.Errorf("wanted %q, got %q", w, g)
+ }
+ })
+ }
+}
+
+func TestSortedUniqueStringValues(t *testing.T) {
+ testCases := []struct {
+ name string
+ in interface{}
+ expected []string
+ }{
+ {
+ name: "nil",
+ in: map[string]string(nil),
+ expected: nil,
+ },
+ {
+ name: "empty",
+ in: map[string]string{},
+ expected: nil,
+ },
+ {
+ name: "simple",
+ in: map[string]string{"foo": "a", "bar": "b"},
+ expected: []string{"a", "b"},
+ },
+ {
+ name: "duplicates",
+ in: map[string]string{"foo": "a", "bar": "b", "baz": "b"},
+ expected: []string{"a", "b"},
+ },
+ }
+
+ for _, tt := range testCases {
+ t.Run(tt.name, func(t *testing.T) {
+ got := SortedUniqueStringValues(tt.in)
+ if g, w := got, tt.expected; !reflect.DeepEqual(g, w) {
+ t.Errorf("wanted %q, got %q", w, g)
+ }
+ })
+ }
+}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 7154905..9290272 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -399,6 +399,9 @@
}
entries.SetBoolIfTrue("LOCAL_COMPATIBILITY_PER_TESTCASE_DIRECTORY", Bool(test.Properties.Per_testcase_directory))
+ if len(test.Properties.Data_bins) > 0 {
+ entries.AddStrings("LOCAL_TEST_DATA_BINS", test.Properties.Data_bins...)
+ }
})
AndroidMkWriteTestData(test.data, entries)
diff --git a/cc/binary.go b/cc/binary.go
index 54fd339..6c7d581 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -70,6 +70,7 @@
// cc_binary produces a binary that is runnable on a device.
func BinaryFactory() android.Module {
module, _ := newBinary(android.HostAndDeviceSupported, true)
+ module.bazelHandler = &ccBinaryBazelHandler{module: module}
return module.Init()
}
@@ -556,6 +557,28 @@
})
}
+type ccBinaryBazelHandler struct {
+ android.BazelHandler
+
+ module *Module
+}
+
+func (handler *ccBinaryBazelHandler) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool {
+ bazelCtx := ctx.Config().BazelContext
+ filePaths, ok := bazelCtx.GetOutputFiles(label, android.GetConfigKey(ctx))
+ if ok {
+ if len(filePaths) != 1 {
+ ctx.ModuleErrorf("expected exactly one output file for '%s', but got %s", label, filePaths)
+ return false
+ }
+ outputFilePath := android.PathForBazelOut(ctx, filePaths[0])
+ handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
+ // TODO(b/220164721): We need to decide if we should return the stripped as the unstripped.
+ handler.module.linker.(*binaryDecorator).unstrippedOutputFile = outputFilePath
+ }
+ return ok
+}
+
func binaryBp2build(ctx android.TopDownMutatorContext, m *Module, typ string) {
baseAttrs := bp2BuildParseBaseProps(ctx, m)
binaryLinkerAttrs := bp2buildBinaryLinkerProps(ctx, m)
diff --git a/cc/binary_test.go b/cc/binary_test.go
new file mode 100644
index 0000000..8ec3871
--- /dev/null
+++ b/cc/binary_test.go
@@ -0,0 +1,51 @@
+// 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.
+
+package cc
+
+import (
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestCcBinaryWithBazel(t *testing.T) {
+ bp := `
+cc_binary {
+ name: "foo",
+ srcs: ["foo.cc"],
+ bazel_module: { label: "//foo/bar:bar" },
+}`
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: "outputbase",
+ LabelToOutputFiles: map[string][]string{
+ "//foo/bar:bar": []string{"foo"},
+ },
+ }
+ ctx := testCcWithConfig(t, config)
+
+ binMod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module()
+ producer := binMod.(android.OutputFileProducer)
+ outputFiles, err := producer.OutputFiles("")
+ if err != nil {
+ t.Errorf("Unexpected error getting cc_binary outputfiles %s", err)
+ }
+ expectedOutputFiles := []string{"outputbase/execroot/__main__/foo"}
+ android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
+
+ unStrippedFilePath := binMod.(*Module).UnstrippedOutputFile()
+ expectedUnStrippedFile := "outputbase/execroot/__main__/foo"
+ android.AssertStringEquals(t, "Unstripped output file", expectedUnStrippedFile, unStrippedFilePath.String())
+}
diff --git a/cc/makevars.go b/cc/makevars.go
index 1ad71ec..6752f8c 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -255,14 +255,43 @@
}, " "))
if target.Os.Class == android.Device {
- ctx.Strict(secondPrefix+"ADDRESS_SANITIZER_RUNTIME_LIBRARY", strings.TrimSuffix(config.AddressSanitizerRuntimeLibrary(toolchain), ".so"))
- ctx.Strict(secondPrefix+"HWADDRESS_SANITIZER_RUNTIME_LIBRARY", strings.TrimSuffix(config.HWAddressSanitizerRuntimeLibrary(toolchain), ".so"))
- ctx.Strict(secondPrefix+"HWADDRESS_SANITIZER_STATIC_LIBRARY", strings.TrimSuffix(config.HWAddressSanitizerStaticLibrary(toolchain), ".a"))
- ctx.Strict(secondPrefix+"UBSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain), ".so"))
- ctx.Strict(secondPrefix+"UBSAN_MINIMAL_RUNTIME_LIBRARY", strings.TrimSuffix(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain), ".a"))
- ctx.Strict(secondPrefix+"TSAN_RUNTIME_LIBRARY", strings.TrimSuffix(config.ThreadSanitizerRuntimeLibrary(toolchain), ".so"))
- ctx.Strict(secondPrefix+"SCUDO_RUNTIME_LIBRARY", strings.TrimSuffix(config.ScudoRuntimeLibrary(toolchain), ".so"))
- ctx.Strict(secondPrefix+"SCUDO_MINIMAL_RUNTIME_LIBRARY", strings.TrimSuffix(config.ScudoMinimalRuntimeLibrary(toolchain), ".so"))
+ sanitizerVariables := map[string]string{
+ "ADDRESS_SANITIZER_RUNTIME_LIBRARY": config.AddressSanitizerRuntimeLibrary(toolchain),
+ "HWADDRESS_SANITIZER_RUNTIME_LIBRARY": config.HWAddressSanitizerRuntimeLibrary(toolchain),
+ "HWADDRESS_SANITIZER_STATIC_LIBRARY": config.HWAddressSanitizerStaticLibrary(toolchain),
+ "UBSAN_RUNTIME_LIBRARY": config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain),
+ "UBSAN_MINIMAL_RUNTIME_LIBRARY": config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain),
+ "TSAN_RUNTIME_LIBRARY": config.ThreadSanitizerRuntimeLibrary(toolchain),
+ "SCUDO_RUNTIME_LIBRARY": config.ScudoRuntimeLibrary(toolchain),
+ "SCUDO_MINIMAL_RUNTIME_LIBRARY": config.ScudoMinimalRuntimeLibrary(toolchain),
+ }
+
+ for variable, value := range sanitizerVariables {
+ ctx.Strict(secondPrefix+variable, value)
+ }
+
+ sanitizerLibs := android.SortedStringValues(sanitizerVariables)
+ var sanitizerLibStems []string
+ ctx.VisitAllModules(func(m android.Module) {
+ if !m.Enabled() {
+ return
+ }
+
+ ccModule, _ := m.(*Module)
+ if ccModule == nil || ccModule.library == nil || !ccModule.library.shared() {
+ return
+ }
+
+ if android.InList(strings.TrimPrefix(ctx.ModuleName(m), "prebuilt_"), sanitizerLibs) &&
+ m.Target().Os == target.Os && m.Target().Arch.ArchType == target.Arch.ArchType {
+ outputFile := ccModule.outputFile
+ if outputFile.Valid() {
+ sanitizerLibStems = append(sanitizerLibStems, outputFile.Path().Base())
+ }
+ }
+ })
+ sanitizerLibStems = android.SortedUniqueStrings(sanitizerLibStems)
+ ctx.Strict(secondPrefix+"SANITIZER_STEMS", strings.Join(sanitizerLibStems, " "))
}
// This is used by external/gentoo/...
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 1db2219..f8661a6 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -42,6 +42,7 @@
"-fno-omit-frame-pointer",
"-Wno-frame-larger-than=",
"-fsanitize-hwaddress-abi=platform",
+ "-mllvm", "-hwasan-use-after-scope=1",
}
// ThinLTO performs codegen during link time, thus these flags need to
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 4e58632..2361e03 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -106,6 +106,9 @@
}
entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(test.Properties.Auto_gen_config, true))
entries.SetBoolIfTrue("LOCAL_IS_UNIT_TEST", Bool(test.Properties.Test_options.Unit_test))
+ if test.Properties.Data_bins != nil {
+ entries.AddStrings("LOCAL_TEST_DATA_BINS", test.Properties.Data_bins...)
+ }
})
cc.AndroidMkWriteTestData(test.data, ret)
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 2ab784d..4190e84 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -458,6 +458,9 @@
dir := strings.TrimSuffix(s.dataModules[relPath].String(), relPath)
entries.AddStrings("LOCAL_TEST_DATA", dir+":"+relPath)
}
+ if s.testProperties.Data_bins != nil {
+ entries.AddStrings("LOCAL_TEST_DATA_BINS", s.testProperties.Data_bins...)
+ }
if Bool(s.testProperties.Test_options.Unit_test) {
entries.SetBool("LOCAL_IS_UNIT_TEST", true)
}