Merge "cc bp2build for sysprop_library modules"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index ccd4a77..661dcf5 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -134,6 +134,7 @@
"external/libjpeg-turbo": Bp2BuildDefaultTrueRecursively,
"external/libmpeg2": Bp2BuildDefaultTrueRecursively,
"external/libpng": Bp2BuildDefaultTrueRecursively,
+ "external/libvpx": Bp2BuildDefaultTrueRecursively,
"external/libyuv": Bp2BuildDefaultTrueRecursively,
"external/lz4/lib": Bp2BuildDefaultTrue,
"external/lzma/C": Bp2BuildDefaultTrueRecursively,
@@ -459,7 +460,6 @@
"libactivitymanager_aidl", // TODO(b/207426160): Unsupported use of aidl sources (via Dactivity_manager_procstate_aidl) in a cc_library
// TODO(b/198619163) module has same name as source
- "gen-kotlin-build-file.py",
"logtagd.rc",
"libgtest_ndk_c++", "libgtest_main_ndk_c++", // TODO(b/201816222): Requires sdk_version support.
@@ -471,9 +471,7 @@
"KernelLibcutilsTest",
"linker", // TODO(b/228316882): cc_binary uses link_crt
- "libdebuggerd", // TODO(b/228314770): support product variable-specific header_libs
"versioner", // TODO(b/228313961): depends on prebuilt shared library libclang-cpp_host as a shared library, which does not supply expected providers for a shared library
- "libvpx", // TODO(b/240756936): Arm neon variant not supported
"art_libartbase_headers", // TODO(b/236268577): Header libraries do not support export_shared_libs_headers
"apexer_test", // Requires aapt2
"apexer_test_host_tools",
@@ -547,6 +545,7 @@
"libartbased-art-gtest", // depends on unconverted modules: libgtest_isolated, libartd, libartd-compiler, libdexfiled, libprofiled
"libartd", // depends on unconverted modules: art_operator_srcs, libcpu_features, libodrstatslog, libelffiled, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfiled, libnativebridge, libnativeloader, libsigchain, libartbased, libprofiled, cpp-define-generator-asm-support, apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api
"libartd-runtime-gtest", // depends on unconverted modules: libgtest_isolated, libartd-compiler, libdexfiled, libprofiled, libartbased, libartbased-art-gtest
+ "libdebuggerd", // depends on unconverted module: libdexfile
"libdebuggerd_handler", // depends on unconverted module libdebuggerd_handler_core
"libdebuggerd_handler_core", "libdebuggerd_handler_fallback", // depends on unconverted module libdebuggerd
"libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette
diff --git a/android/arch.go b/android/arch.go
index 1952b17..9bc9d89 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -19,6 +19,7 @@
"fmt"
"reflect"
"runtime"
+ "sort"
"strings"
"android/soong/bazel"
@@ -2084,13 +2085,22 @@
// For each arch type (x86, arm64, etc.)
for _, arch := range ArchTypeList() {
// Arch properties are sometimes sharded (see createArchPropTypeDesc() ).
- // Iterate over ever shard and extract a struct with the same type as the
+ // Iterate over every shard and extract a struct with the same type as the
// input one that contains the data specific to that arch.
propertyStructs := make([]reflect.Value, 0)
+ archFeaturePropertyStructs := make(map[string][]reflect.Value, 0)
for _, archProperty := range archProperties {
archTypeStruct, ok := getArchTypeStruct(ctx, archProperty, arch)
if ok {
propertyStructs = append(propertyStructs, archTypeStruct)
+
+ // For each feature this arch supports (arm: neon, x86: ssse3, sse4, ...)
+ for _, feature := range archFeatures[arch] {
+ prefix := "arch." + arch.Name + "." + feature
+ if featureProperties, ok := getChildPropertyStruct(ctx, archTypeStruct, feature, prefix); ok {
+ archFeaturePropertyStructs[feature] = append(archFeaturePropertyStructs[feature], featureProperties)
+ }
+ }
}
multilibStruct, ok := getMultilibStruct(ctx, archProperty, arch)
if ok {
@@ -2098,10 +2108,31 @@
}
}
- // Create a new instance of the requested property set
- value := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
+ archToProp[arch.Name] = mergeStructs(ctx, propertyStructs, propertySet)
- archToProp[arch.Name] = mergeStructs(ctx, propertyStructs, value)
+ // In soong, if multiple features match the current configuration, they're
+ // all used. In bazel, we have to have unambiguous select() statements, so
+ // we can't have two features that are both active in the same select().
+ // One alternative is to split out each feature into a separate select(),
+ // but then it's difficult to support exclude_srcs, which may need to
+ // exclude things from the regular arch select() statement if a certain
+ // feature is active. Instead, keep the features in the same select
+ // statement as the arches, but emit the power set of all possible
+ // combinations of features, so that bazel can match the most precise one.
+ allFeatures := make([]string, 0, len(archFeaturePropertyStructs))
+ for feature := range archFeaturePropertyStructs {
+ allFeatures = append(allFeatures, feature)
+ }
+ for _, features := range bazel.PowerSetWithoutEmptySet(allFeatures) {
+ sort.Strings(features)
+ propsForCurrentFeatureSet := make([]reflect.Value, 0)
+ propsForCurrentFeatureSet = append(propsForCurrentFeatureSet, propertyStructs...)
+ for _, feature := range features {
+ propsForCurrentFeatureSet = append(propsForCurrentFeatureSet, archFeaturePropertyStructs[feature]...)
+ }
+ archToProp[arch.Name+"-"+strings.Join(features, "-")] =
+ mergeStructs(ctx, propsForCurrentFeatureSet, propertySet)
+ }
}
axisToProps[bazel.ArchConfigurationAxis] = archToProp
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 49a5d2a..d6803f6 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -8846,6 +8846,16 @@
android.FixtureMergeEnv(map[string]string{
"EMMA_INSTRUMENT": "true",
}),
+ // need to mock jacocoagent here to satisfy dependency added for
+ // instrumented libraries at build time
+ android.FixtureAddFile("jacocoagent/Android.bp", []byte(`
+ java_library {
+ name: "jacocoagent",
+ srcs: ["Test.java"],
+ system_modules: "none",
+ sdk_version: "none",
+ }
+ `)),
).RunTest(t)
// Make sure jacoco ran on both mylib and mybootclasspathlib
diff --git a/bazel/configurability.go b/bazel/configurability.go
index d9b0a12..e1cdd4a 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -16,6 +16,8 @@
import (
"fmt"
+ "math"
+ "sort"
"strings"
)
@@ -69,6 +71,71 @@
AndroidAndNonApex = "android-non_apex"
)
+func PowerSetWithoutEmptySet[T any](items []T) [][]T {
+ resultSize := int(math.Pow(2, float64(len(items))))
+ powerSet := make([][]T, 0, resultSize-1)
+ for i := 1; i < resultSize; i++ {
+ combination := make([]T, 0)
+ for j := 0; j < len(items); j++ {
+ if (i>>j)%2 == 1 {
+ combination = append(combination, items[j])
+ }
+ }
+ powerSet = append(powerSet, combination)
+ }
+ return powerSet
+}
+
+func createPlatformArchMap() map[string]string {
+ // Copy of archFeatures from android/arch_list.go because the bazel
+ // package can't access the android package
+ archFeatures := map[string][]string{
+ "arm": {
+ "neon",
+ },
+ "arm64": {
+ "dotprod",
+ },
+ "x86": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "aes_ni",
+ "avx",
+ "avx2",
+ "avx512",
+ "popcnt",
+ "movbe",
+ },
+ "x86_64": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "aes_ni",
+ "avx",
+ "avx2",
+ "avx512",
+ "popcnt",
+ },
+ }
+ result := make(map[string]string)
+ for arch, allFeatures := range archFeatures {
+ result[arch] = "//build/bazel/platforms/arch:" + arch
+ // Sometimes we want to select on multiple features being active, so
+ // add the power set of all possible features to the map. More details
+ // in android.ModuleBase.GetArchVariantProperties
+ for _, features := range PowerSetWithoutEmptySet(allFeatures) {
+ sort.Strings(features)
+ archFeaturesName := arch + "-" + strings.Join(features, "-")
+ result[archFeaturesName] = "//build/bazel/platforms/arch/variants:" + archFeaturesName
+ }
+ }
+ result[ConditionsDefaultConfigKey] = ConditionsDefaultSelectKey
+ return result
+}
+
var (
// These are the list of OSes and architectures with a Bazel config_setting
// and constraint value equivalent. These exist in arch.go, but the android
@@ -77,13 +144,7 @@
// A map of architectures to the Bazel label of the constraint_value
// for the @platforms//cpu:cpu constraint_setting
- platformArchMap = map[string]string{
- archArm: "//build/bazel/platforms/arch:arm",
- archArm64: "//build/bazel/platforms/arch:arm64",
- archX86: "//build/bazel/platforms/arch:x86",
- archX86_64: "//build/bazel/platforms/arch:x86_64",
- ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of as arch select map.
- }
+ platformArchMap = createPlatformArchMap()
// A map of target operating systems to the Bazel label of the
// constraint_value for the @platforms//os:os constraint_setting
diff --git a/bazel/properties.go b/bazel/properties.go
index 13e36b5..d82fa64 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -725,7 +725,7 @@
case noConfig:
return lla.Value
case arch, os, osArch, productVariables, osAndInApex:
- return (lla.ConfigurableValues[axis][config])
+ return lla.ConfigurableValues[axis][config]
default:
panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 45f15bf..5117c62 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -1199,6 +1199,40 @@
)
}
+func TestCcLibraryProductVariablesHeaderLibs(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Filesystem: map[string]string{},
+ Blueprint: soongCcLibraryStaticPreamble + `
+cc_library {
+ name: "foo_static",
+ srcs: ["common.c"],
+ product_variables: {
+ malloc_not_svelte: {
+ header_libs: ["malloc_not_svelte_header_lib"],
+ },
+ },
+ include_build_directory: false,
+}
+
+cc_library {
+ name: "malloc_not_svelte_header_lib",
+ bazel_module: { bp2build_available: false },
+}
+`,
+ ExpectedBazelTargets: makeCcLibraryTargets("foo_static", AttrNameToString{
+ "implementation_deps": `select({
+ "//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_header_lib"],
+ "//conditions:default": [],
+ })`,
+ "srcs_c": `["common.c"]`,
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ }),
+ },
+ )
+}
+
func TestCCLibraryNoCrtTrue(t *testing.T) {
runCcLibraryTestCase(t, Bp2buildTestCase{
Description: "cc_library - nocrt: true emits attribute",
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 0e47ee8..0637ba2 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -1419,13 +1419,7 @@
}
`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "all", AttrNameToString{
- "implementation_dynamic_deps": `select({
- "//build/bazel/platforms/os:android": [],
- "//build/bazel/platforms/os:linux_bionic": [],
- "//conditions:default": [":libc"],
- })`,
- }),
+ MakeBazelTarget("cc_library_static", "all", AttrNameToString{}),
MakeBazelTarget("cc_library_static", "keep_for_empty_system_shared_libs", AttrNameToString{
"implementation_dynamic_deps": `[":libc"]`,
"system_dynamic_deps": `[]`,
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index 4a4da18..74e2dbd 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -534,3 +534,118 @@
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
})
}
+
+func TestConvertArmNeonVariant(t *testing.T) {
+ t.Helper()
+ RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
+ Description: "Android Library - simple arch feature",
+ ModuleTypeUnderTest: "android_library",
+ ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
+ Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
+android_library {
+ name: "TestLib",
+ manifest: "manifest/AndroidManifest.xml",
+ srcs: ["lib.java"],
+ arch: {
+ arm: {
+ neon: {
+ srcs: ["arm_neon.java"],
+ },
+ },
+ },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget(
+ "android_library",
+ "TestLib",
+ AttrNameToString{
+ "srcs": `["lib.java"] + select({
+ "//build/bazel/platforms/arch/variants:arm-neon": ["arm_neon.java"],
+ "//conditions:default": [],
+ })`,
+ "manifest": `"manifest/AndroidManifest.xml"`,
+ "resource_files": `[]`,
+ }),
+ }})
+}
+
+func TestConvertMultipleArchFeatures(t *testing.T) {
+ t.Helper()
+ RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
+ Description: "Android Library - multiple arch features",
+ ModuleTypeUnderTest: "android_library",
+ ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
+ Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
+android_library {
+ name: "TestLib",
+ manifest: "manifest/AndroidManifest.xml",
+ srcs: ["lib.java"],
+ arch: {
+ x86: {
+ ssse3: {
+ srcs: ["ssse3.java"],
+ },
+ sse4_1: {
+ srcs: ["sse4_1.java"],
+ },
+ },
+ },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget(
+ "android_library",
+ "TestLib",
+ AttrNameToString{
+ "srcs": `["lib.java"] + select({
+ "//build/bazel/platforms/arch/variants:x86-sse4_1": ["sse4_1.java"],
+ "//build/bazel/platforms/arch/variants:x86-sse4_1-ssse3": [
+ "sse4_1.java",
+ "ssse3.java",
+ ],
+ "//build/bazel/platforms/arch/variants:x86-ssse3": ["ssse3.java"],
+ "//conditions:default": [],
+ })`,
+ "manifest": `"manifest/AndroidManifest.xml"`,
+ "resource_files": `[]`,
+ }),
+ }})
+}
+
+func TestConvertExcludeSrcsArchFeature(t *testing.T) {
+ t.Helper()
+ RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
+ Description: "Android Library - exclude_srcs with arch feature",
+ ModuleTypeUnderTest: "android_library",
+ ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
+ Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
+android_library {
+ name: "TestLib",
+ manifest: "manifest/AndroidManifest.xml",
+ srcs: ["lib.java"],
+ arch: {
+ arm: {
+ srcs: ["arm_non_neon.java"],
+ neon: {
+ exclude_srcs: ["arm_non_neon.java"],
+ },
+ },
+ },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget(
+ "android_library",
+ "TestLib",
+ AttrNameToString{
+ "srcs": `["lib.java"] + select({
+ "//build/bazel/platforms/arch/variants:arm-neon": [],
+ "//build/bazel/platforms/arch:arm": ["arm_non_neon.java"],
+ "//conditions:default": [],
+ })`,
+ "manifest": `"manifest/AndroidManifest.xml"`,
+ "resource_files": `[]`,
+ }),
+ }})
+}
diff --git a/bp2build/prebuilt_etc_conversion_test.go b/bp2build/prebuilt_etc_conversion_test.go
index 6738b4b..b1e70dc 100644
--- a/bp2build/prebuilt_etc_conversion_test.go
+++ b/bp2build/prebuilt_etc_conversion_test.go
@@ -181,3 +181,87 @@
"dir": `"etc"`,
})}})
}
+
+func TestFilenameAsProperty(t *testing.T) {
+ runPrebuiltEtcTestCase(t, Bp2buildTestCase{
+ Description: "prebuilt_etc - filename is specified as a property ",
+ Filesystem: map[string]string{},
+ Blueprint: `
+prebuilt_etc {
+ name: "foo",
+ src: "fooSrc",
+ filename: "fooFileName",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("prebuilt_file", "foo", AttrNameToString{
+ "filename": `"fooFileName"`,
+ "src": `"fooSrc"`,
+ "dir": `"etc"`,
+ })}})
+}
+
+func TestFileNameFromSrc(t *testing.T) {
+ runPrebuiltEtcTestCase(t, Bp2buildTestCase{
+ Description: "prebuilt_etc - filename_from_src is true ",
+ Filesystem: map[string]string{},
+ Blueprint: `
+prebuilt_etc {
+ name: "foo",
+ filename_from_src: true,
+ src: "fooSrc",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("prebuilt_file", "foo", AttrNameToString{
+ "filename": `"fooSrc"`,
+ "src": `"fooSrc"`,
+ "dir": `"etc"`,
+ })}})
+}
+
+func TestFileNameFromSrcMultipleSrcs(t *testing.T) {
+ runPrebuiltEtcTestCase(t, Bp2buildTestCase{
+ Description: "prebuilt_etc - filename_from_src is true but there are multiple srcs",
+ Filesystem: map[string]string{},
+ Blueprint: `
+prebuilt_etc {
+ name: "foo",
+ filename_from_src: true,
+ arch: {
+ arm: {
+ src: "barSrc",
+ },
+ arm64: {
+ src: "bazSrc",
+ },
+ }
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("prebuilt_file", "foo", AttrNameToString{
+ "filename_from_src": `True`,
+ "dir": `"etc"`,
+ "src": `select({
+ "//build/bazel/platforms/arch:arm": "barSrc",
+ "//build/bazel/platforms/arch:arm64": "bazSrc",
+ "//conditions:default": None,
+ })`,
+ })}})
+}
+
+func TestFilenameFromModuleName(t *testing.T) {
+ runPrebuiltEtcTestCase(t, Bp2buildTestCase{
+ Description: "prebuilt_etc - neither filename nor filename_from_src are specified ",
+ Filesystem: map[string]string{},
+ Blueprint: `
+prebuilt_etc {
+ name: "foo",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("prebuilt_file", "foo", AttrNameToString{
+ "filename": `"foo"`,
+ "dir": `"etc"`,
+ })}})
+}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 77aaec1..c1a3bef 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -1026,11 +1026,17 @@
depResolutionFunc func(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList
}
+ // an intermediate attribute that holds Header_libs info, and will be appended to
+ // implementationDeps at the end, to solve the confliction that both header_libs
+ // and static_libs use implementationDeps.
+ var headerDeps bazel.LabelListAttribute
+
productVarToDepFields := map[string]productVarDep{
// product variables do not support exclude_shared_libs
"Shared_libs": {attribute: &la.implementationDynamicDeps, depResolutionFunc: bazelLabelForSharedDepsExcludes},
"Static_libs": {"Exclude_static_libs", &la.implementationDeps, bazelLabelForStaticDepsExcludes},
"Whole_static_libs": {"Exclude_static_libs", &la.wholeArchiveDeps, bazelLabelForWholeDepsExcludes},
+ "Header_libs": {attribute: &headerDeps, depResolutionFunc: bazelLabelForHeaderDepsExcludes},
}
for name, dep := range productVarToDepFields {
@@ -1072,14 +1078,18 @@
)
}
}
+ la.implementationDeps.Append(headerDeps)
}
func (la *linkerAttributes) finalize(ctx android.BazelConversionPathContext) {
// if system dynamic deps have the default value, any use of a system dynamic library used will
// result in duplicate library errors for bionic OSes. Here, we explicitly exclude those libraries
- // from bionic OSes.
+ // from bionic OSes and the no config case as these libraries only build for bionic OSes.
if la.systemDynamicDeps.IsNil() && len(la.usedSystemDynamicDepAsDynamicDep) > 0 {
toRemove := bazelLabelForSharedDeps(ctx, android.SortedStringKeys(la.usedSystemDynamicDepAsDynamicDep))
+ la.dynamicDeps.Exclude(bazel.NoConfigAxis, "", toRemove)
+ la.implementationDynamicDeps.Exclude(bazel.NoConfigAxis, "", toRemove)
+ la.implementationDynamicDeps.Exclude(bazel.NoConfigAxis, "", toRemove)
la.dynamicDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
la.dynamicDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove)
la.implementationDynamicDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
@@ -1200,6 +1210,12 @@
return bazelLabelForSharedDeps(ctx, modules)
}
+func bazelLabelForHeaderDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
+ // This is only used when product_variable header_libs is processed, to follow
+ // the pattern of depResolutionFunc
+ return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForSharedModule)
+}
+
func bazelLabelForSharedDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForSharedModule)
}
diff --git a/cc/cc.go b/cc/cc.go
index 0ed9bb6..3129160 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -485,6 +485,7 @@
static() bool
staticBinary() bool
testBinary() bool
+ testLibrary() bool
header() bool
binary() bool
object() bool
@@ -1486,6 +1487,10 @@
return ctx.mod.testBinary()
}
+func (ctx *moduleContextImpl) testLibrary() bool {
+ return ctx.mod.testLibrary()
+}
+
func (ctx *moduleContextImpl) header() bool {
return ctx.mod.Header()
}
diff --git a/cc/config/bionic.go b/cc/config/bionic.go
index e87f571..a1e3851 100644
--- a/cc/config/bionic.go
+++ b/cc/config/bionic.go
@@ -15,6 +15,7 @@
package config
type toolchainBionic struct {
+ toolchainBase
}
var (
@@ -29,6 +30,12 @@
func (toolchainBionic) DefaultSharedLibraries() []string { return bionicDefaultSharedLibraries }
+func (toolchainBionic) ShlibSuffix() string { return ".so" }
+
+func (toolchainBionic) ExecutableSuffix() string { return "" }
+
+func (toolchainBionic) AvailableLibraries() []string { return nil }
+
func (toolchainBionic) CrtBeginStaticBinary() []string { return bionicCrtBeginStaticBinary }
func (toolchainBionic) CrtBeginSharedBinary() []string { return bionicCrtBeginSharedBinary }
func (toolchainBionic) CrtBeginSharedLibrary() []string { return bionicCrtBeginSharedLibrary }
diff --git a/cc/config/darwin_host.go b/cc/config/darwin_host.go
index 5e3f7c7..01b1e63 100644
--- a/cc/config/darwin_host.go
+++ b/cc/config/darwin_host.go
@@ -176,6 +176,8 @@
type toolchainDarwin struct {
cFlags, ldFlags string
toolchain64Bit
+ toolchainNoCrt
+ toolchainBase
}
type toolchainDarwinX86 struct {
@@ -254,6 +256,10 @@
return ".dylib"
}
+func (t *toolchainDarwin) ExecutableSuffix() string {
+ return ""
+}
+
func (t *toolchainDarwin) AvailableLibraries() []string {
return darwinAvailableLibraries
}
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index 253bb06..d9eaf53 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -140,14 +140,6 @@
return ""
}
-func (toolchainBase) ShlibSuffix() string {
- return ".so"
-}
-
-func (toolchainBase) ExecutableSuffix() string {
- return ""
-}
-
func (toolchainBase) Asflags() string {
return ""
}
@@ -160,16 +152,14 @@
return ""
}
-func (toolchainBase) AvailableLibraries() []string {
- return nil
-}
+type toolchainNoCrt struct{}
-func (toolchainBase) CrtBeginStaticBinary() []string { return nil }
-func (toolchainBase) CrtBeginSharedBinary() []string { return nil }
-func (toolchainBase) CrtBeginSharedLibrary() []string { return nil }
-func (toolchainBase) CrtEndStaticBinary() []string { return nil }
-func (toolchainBase) CrtEndSharedBinary() []string { return nil }
-func (toolchainBase) CrtEndSharedLibrary() []string { return nil }
+func (toolchainNoCrt) CrtBeginStaticBinary() []string { return nil }
+func (toolchainNoCrt) CrtBeginSharedBinary() []string { return nil }
+func (toolchainNoCrt) CrtBeginSharedLibrary() []string { return nil }
+func (toolchainNoCrt) CrtEndStaticBinary() []string { return nil }
+func (toolchainNoCrt) CrtEndSharedBinary() []string { return nil }
+func (toolchainNoCrt) CrtEndSharedLibrary() []string { return nil }
func (toolchainBase) DefaultSharedLibraries() []string {
return nil
@@ -188,7 +178,6 @@
}
type toolchain64Bit struct {
- toolchainBase
}
func (toolchain64Bit) Is64Bit() bool {
@@ -196,7 +185,6 @@
}
type toolchain32Bit struct {
- toolchainBase
}
func (toolchain32Bit) Is64Bit() bool {
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 4e8fd77..1b126de 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -158,6 +158,7 @@
}
type toolchainLinux struct {
+ toolchainBase
cFlags, ldFlags string
}
@@ -247,9 +248,18 @@
return linuxAvailableLibraries
}
+func (toolchainLinux) ShlibSuffix() string {
+ return ".so"
+}
+
+func (toolchainLinux) ExecutableSuffix() string {
+ return ""
+}
+
// glibc specialization of the linux toolchain
type toolchainGlibc struct {
+ toolchainNoCrt
}
func (toolchainGlibc) Glibc() bool { return true }
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index 2c83211..a33606f 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -153,6 +153,8 @@
type toolchainWindows struct {
cFlags, ldFlags string
+ toolchainBase
+ toolchainNoCrt
}
type toolchainWindowsX86 struct {
diff --git a/cc/lto.go b/cc/lto.go
index 455ff7e..5d2fba0 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -140,12 +140,13 @@
lib32 := ctx.Arch().ArchType.Multilib == "lib32"
// CFI enables full LTO.
cfi := ctx.isCfi()
- // Performance and binary size are less important for host binaries.
+ // Performance and binary size are less important for host binaries and tests.
host := ctx.Host()
+ test := ctx.testBinary() || ctx.testLibrary()
// FIXME: ThinLTO for VNDK produces different output.
// b/169217596
vndk := ctx.isVndk()
- return GlobalThinLTO(ctx) && !lto.Never() && !lib32 && !cfi && !host && !vndk
+ return GlobalThinLTO(ctx) && !lto.Never() && !lib32 && !cfi && !host && !test && !vndk
}
func (lto *lto) FullLTO() bool {
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 86472a2..edff059 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -77,6 +77,7 @@
"-fno-sanitize-recover=integer,undefined"}
hwasanGlobalOptions = []string{"heap_history_size=1023", "stack_history_size=512",
"export_memory_stats=0", "max_malloc_fill_size=4096", "malloc_fill_byte=0"}
+ memtagStackCommonFlags = []string{"-march=armv8-a+memtag"}
)
type SanitizerType int
@@ -89,6 +90,7 @@
scs
Fuzzer
Memtag_heap
+ Memtag_stack
cfi // cfi is last to prevent it running before incompatible mutators
)
@@ -100,6 +102,7 @@
scs,
Fuzzer,
Memtag_heap,
+ Memtag_stack,
cfi, // cfi is last to prevent it running before incompatible mutators
}
@@ -120,6 +123,8 @@
return "scs"
case Memtag_heap:
return "memtag_heap"
+ case Memtag_stack:
+ return "memtag_stack"
case Fuzzer:
return "fuzzer"
default:
@@ -136,6 +141,8 @@
return "hwaddress"
case Memtag_heap:
return "memtag_heap"
+ case Memtag_stack:
+ return "memtag_stack"
case tsan:
return "thread"
case intOverflow:
@@ -157,7 +164,7 @@
sanitizer := &sanitizerSplitMutator{t}
ctx.TopDown(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator)
ctx.Transition(t.variationName(), sanitizer)
- case Memtag_heap, intOverflow:
+ case Memtag_heap, Memtag_stack, intOverflow:
// do nothing
default:
panic(fmt.Errorf("unknown SanitizerType %d", t))
@@ -182,6 +189,8 @@
return true
case Memtag_heap:
return true
+ case Memtag_stack:
+ return true
default:
return false
}
@@ -233,6 +242,9 @@
// Memory-tagging, only available on arm64
// if diag.memtag unset or false, enables async memory tagging
Memtag_heap *bool `android:"arch_variant"`
+ // Memory-tagging stack instrumentation, only available on arm64
+ // Adds instrumentation to detect stack buffer overflows and use-after-scope using MTE.
+ Memtag_stack *bool `android:"arch_variant"`
// A modifier for ASAN and HWASAN for write only instrumentation
Writeonly *bool `android:"arch_variant"`
@@ -318,7 +330,7 @@
return
}
- // cc_test targets default to SYNC MemTag unless explicitly set to ASYNC (via diag: {memtag_heap}).
+ // cc_test targets default to SYNC MemTag unless explicitly set to ASYNC (via diag: {memtag_heap: false}).
if ctx.testBinary() {
if s.Memtag_heap == nil {
s.Memtag_heap = proptools.BoolPtr(true)
@@ -404,6 +416,10 @@
}
}
+ if found, globalSanitizers = removeFromList("memtag_stack", globalSanitizers); found && s.Memtag_stack == nil {
+ s.Memtag_stack = proptools.BoolPtr(true)
+ }
+
if len(globalSanitizers) > 0 {
ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0])
}
@@ -470,14 +486,19 @@
}
// Memtag_heap is only implemented on AArch64.
- if ctx.Arch().ArchType != android.Arm64 || !ctx.toolchain().Bionic() {
+ // Memtag ABI is Android specific for now, so disable for host.
+ if ctx.Arch().ArchType != android.Arm64 || !ctx.toolchain().Bionic() || ctx.Host() {
s.Memtag_heap = nil
+ s.Memtag_stack = nil
}
// Also disable CFI if ASAN is enabled.
if Bool(s.Address) || Bool(s.Hwaddress) {
s.Cfi = nil
s.Diag.Cfi = nil
+ // HWASAN and ASAN win against MTE.
+ s.Memtag_heap = nil
+ s.Memtag_stack = nil
}
// Disable sanitizers that depend on the UBSan runtime for windows/darwin builds.
@@ -534,7 +555,7 @@
if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) ||
Bool(s.Fuzzer) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 ||
- Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs) || Bool(s.Memtag_heap)) {
+ Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs) || Bool(s.Memtag_heap) || Bool(s.Memtag_stack)) {
sanitize.Properties.SanitizerEnabled = true
}
@@ -691,6 +712,20 @@
}
}
+ if Bool(sanitize.Properties.Sanitize.Memtag_stack) {
+ flags.Local.CFlags = append(flags.Local.CFlags, memtagStackCommonFlags...)
+ flags.Local.AsFlags = append(flags.Local.AsFlags, memtagStackCommonFlags...)
+ flags.Local.LdFlags = append(flags.Local.LdFlags, memtagStackCommonFlags...)
+ }
+
+ if (Bool(sanitize.Properties.Sanitize.Memtag_heap) || Bool(sanitize.Properties.Sanitize.Memtag_stack)) && ctx.binary() {
+ if Bool(sanitize.Properties.Sanitize.Diag.Memtag_heap) {
+ flags.Local.LdFlags = append(flags.Local.LdFlags, "-fsanitize-memtag-mode=sync")
+ } else {
+ flags.Local.LdFlags = append(flags.Local.LdFlags, "-fsanitize-memtag-mode=async")
+ }
+ }
+
if Bool(sanitize.Properties.Sanitize.Integer_overflow) {
flags.Local.CFlags = append(flags.Local.CFlags, intOverflowCflags...)
}
@@ -804,6 +839,8 @@
return sanitize.Properties.Sanitize.Scs
case Memtag_heap:
return sanitize.Properties.Sanitize.Memtag_heap
+ case Memtag_stack:
+ return sanitize.Properties.Sanitize.Memtag_stack
case Fuzzer:
return sanitize.Properties.Sanitize.Fuzzer
default:
@@ -819,6 +856,7 @@
!sanitize.isSanitizerEnabled(cfi) &&
!sanitize.isSanitizerEnabled(scs) &&
!sanitize.isSanitizerEnabled(Memtag_heap) &&
+ !sanitize.isSanitizerEnabled(Memtag_stack) &&
!sanitize.isSanitizerEnabled(Fuzzer)
}
@@ -850,6 +888,8 @@
sanitize.Properties.Sanitize.Scs = bPtr
case Memtag_heap:
sanitize.Properties.Sanitize.Memtag_heap = bPtr
+ case Memtag_stack:
+ sanitize.Properties.Sanitize.Memtag_stack = bPtr
case Fuzzer:
sanitize.Properties.Sanitize.Fuzzer = bPtr
default:
@@ -1311,23 +1351,11 @@
}
if Bool(c.sanitize.Properties.Sanitize.Memtag_heap) && c.Binary() {
- noteDep := "note_memtag_heap_async"
- if Bool(c.sanitize.Properties.Sanitize.Diag.Memtag_heap) {
- noteDep = "note_memtag_heap_sync"
- }
- // If we're using snapshots, redirect to snapshot whenever possible
- // TODO(b/178470649): clean manual snapshot redirections
- snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo)
- if lib, ok := snapshot.StaticLibs[noteDep]; ok {
- noteDep = lib
- }
- depTag := StaticDepTag(true)
- variations := append(mctx.Target().Variations(),
- blueprint.Variation{Mutator: "link", Variation: "static"})
- if c.Device() {
- variations = append(variations, c.ImageVariation())
- }
- mctx.AddFarVariationDependencies(variations, depTag, noteDep)
+ sanitizers = append(sanitizers, "memtag-heap")
+ }
+
+ if Bool(c.sanitize.Properties.Sanitize.Memtag_stack) {
+ sanitizers = append(sanitizers, "memtag-stack")
}
if Bool(c.sanitize.Properties.Sanitize.Fuzzer) {
diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go
index 5d7e7d8..48ac650 100644
--- a/cc/sanitize_test.go
+++ b/cc/sanitize_test.go
@@ -344,19 +344,13 @@
func checkHasMemtagNote(t *testing.T, m android.TestingModule, expected MemtagNoteType) {
t.Helper()
- note_async := "note_memtag_heap_async"
- note_sync := "note_memtag_heap_sync"
found := None
- implicits := m.Rule("ld").Implicits
- for _, lib := range implicits {
- if strings.Contains(lib.Rel(), note_async) {
- found = Async
- break
- } else if strings.Contains(lib.Rel(), note_sync) {
- found = Sync
- break
- }
+ ldFlags := m.Rule("ld").Args["ldFlags"]
+ if strings.Contains(ldFlags, "-fsanitize-memtag-mode=async") {
+ found = Async
+ } else if strings.Contains(ldFlags, "-fsanitize-memtag-mode=sync") {
+ found = Sync
}
if found != expected {
diff --git a/cc/test.go b/cc/test.go
index 3e85e2d..28a0e5e 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -643,7 +643,6 @@
Gtest bool
Isolated bool
- Data bazel.LabelListAttribute
}
// testBinaryBp2build is the bp2build converter for cc_test modules. A cc_test's
@@ -659,6 +658,8 @@
var testBinaryAttrs testBinaryAttributes
testBinaryAttrs.binaryAttributes = binaryBp2buildAttrs(ctx, m)
+ var data bazel.LabelListAttribute
+
testBinaryProps := m.GetArchVariantProperties(ctx, &TestBinaryProperties{})
for axis, configToProps := range testBinaryProps {
for config, props := range configToProps {
@@ -668,7 +669,7 @@
combinedData.Append(android.BazelLabelForModuleSrc(ctx, p.Data))
combinedData.Append(android.BazelLabelForModuleDeps(ctx, p.Data_bins))
combinedData.Append(android.BazelLabelForModuleDeps(ctx, p.Data_libs))
- testBinaryAttrs.Data.SetSelectValue(axis, config, combinedData)
+ data.SetSelectValue(axis, config, combinedData)
}
}
}
@@ -686,6 +687,9 @@
Rule_class: "cc_test",
Bzl_load_location: "//build/bazel/rules/cc:cc_test.bzl",
},
- android.CommonAttributes{Name: m.Name()},
+ android.CommonAttributes{
+ Name: m.Name(),
+ Data: data,
+ },
&testBinaryAttrs)
}
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 719771f..b2361ce 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -670,10 +670,11 @@
// For Bazel / bp2build
type bazelPrebuiltFileAttributes struct {
- Src bazel.LabelAttribute
- Filename string
- Dir string
- Installable bazel.BoolAttribute
+ Src bazel.LabelAttribute
+ Filename bazel.LabelAttribute
+ Dir string
+ Installable bazel.BoolAttribute
+ Filename_from_src bazel.BoolAttribute
}
// ConvertWithBp2build performs bp2build conversion of PrebuiltEtc
@@ -694,8 +695,18 @@
}
var filename string
- if module.properties.Filename != nil {
- filename = *module.properties.Filename
+ var filenameFromSrc bool
+ moduleProps := module.properties
+
+ if moduleProps.Filename != nil && *moduleProps.Filename != "" {
+ filename = *moduleProps.Filename
+ } else if moduleProps.Filename_from_src != nil && *moduleProps.Filename_from_src {
+ if moduleProps.Src != nil {
+ filename = *moduleProps.Src
+ }
+ filenameFromSrc = true
+ } else {
+ filename = ctx.ModuleName()
}
var dir = module.installDirBase
@@ -714,11 +725,16 @@
attrs := &bazelPrebuiltFileAttributes{
Src: src,
- Filename: filename,
Dir: dir,
Installable: installable,
}
+ if filename != "" {
+ attrs.Filename = bazel.LabelAttribute{Value: &bazel.Label{Label: filename}}
+ } else if filenameFromSrc {
+ attrs.Filename_from_src = bazel.BoolAttribute{Value: moduleProps.Filename_from_src}
+ }
+
props := bazel.BazelTargetModuleProperties{
Rule_class: "prebuilt_file",
Bzl_load_location: "//build/bazel/rules:prebuilt_file.bzl",
diff --git a/java/base.go b/java/base.go
index cf3b3d5..53f0f52 100644
--- a/java/base.go
+++ b/java/base.go
@@ -169,6 +169,8 @@
Output_params []string
}
+ // If true, then jacocoagent is automatically added as a libs dependency so that
+ // r8 will not strip instrumentation classes out of dexed libraries.
Instrument bool `blueprint:"mutated"`
// If true, then the module supports statically including the jacocoagent
// into the library.
@@ -787,6 +789,9 @@
} else if j.shouldInstrumentStatic(ctx) {
ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent")
}
+ if j.shouldInstrument(ctx) {
+ ctx.AddVariationDependencies(nil, libTag, "jacocoagent")
+ }
if j.useCompose() {
ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag,
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index f95c83f..2bfb255 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -96,10 +96,22 @@
}
func TestBootclasspathFragment_Coverage(t *testing.T) {
- prepareForTestWithFrameworkCoverage := android.FixtureMergeEnv(map[string]string{
- "EMMA_INSTRUMENT": "true",
- "EMMA_INSTRUMENT_FRAMEWORK": "true",
- })
+ prepareForTestWithFrameworkCoverage := android.GroupFixturePreparers(
+ android.FixtureMergeEnv(map[string]string{
+ "EMMA_INSTRUMENT": "true",
+ "EMMA_INSTRUMENT_FRAMEWORK": "true",
+ }),
+ // need to mock jacocoagent here to satisfy dependency added for
+ // instrumented libraries at build time
+ android.FixtureAddFile("jacocoagent/Android.bp", []byte(`
+ java_library {
+ name: "jacocoagent",
+ srcs: ["Test.java"],
+ system_modules: "none",
+ sdk_version: "none",
+ }
+ `)),
+ )
prepareWithBp := android.FixtureWithRootAndroidBp(`
bootclasspath_fragment {
diff --git a/java/config/config.go b/java/config/config.go
index 3ca9bad..422f860 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -148,7 +148,7 @@
pctx.SourcePathVariable("JavaKytheExtractorJar", "prebuilts/build-tools/common/framework/javac_extractor.jar")
pctx.SourcePathVariable("Ziptime", "prebuilts/build-tools/${hostPrebuiltTag}/bin/ziptime")
- pctx.HostBinToolVariable("GenKotlinBuildFileCmd", "gen-kotlin-build-file.py")
+ pctx.HostBinToolVariable("GenKotlinBuildFileCmd", "gen-kotlin-build-file")
pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh")
pctx.SourcePathVariable("PackageCheckCmd", "build/soong/scripts/package-check.sh")
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 814bd57..b5b588b 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -168,7 +168,7 @@
}
python_binary_host {
- name: "gen-kotlin-build-file.py",
+ name: "gen-kotlin-build-file",
main: "gen-kotlin-build-file.py",
srcs: [
"gen-kotlin-build-file.py",
diff --git a/symbol_inject/cmd/symbol_inject.go b/symbol_inject/cmd/symbol_inject.go
index 1397b37..89b3619 100644
--- a/symbol_inject/cmd/symbol_inject.go
+++ b/symbol_inject/cmd/symbol_inject.go
@@ -94,4 +94,13 @@
os.Remove(*output)
os.Exit(5)
}
+
+ if file.IsMachoFile {
+ err = symbol_inject.CodeSignMachoFile(*output)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Remove(*output)
+ os.Exit(6)
+ }
+ }
}
diff --git a/symbol_inject/macho.go b/symbol_inject/macho.go
index 6ee3f4f..9946d34 100644
--- a/symbol_inject/macho.go
+++ b/symbol_inject/macho.go
@@ -18,6 +18,7 @@
"debug/macho"
"fmt"
"io"
+ "os/exec"
"sort"
"strings"
)
@@ -40,7 +41,7 @@
return symbols[i].Value < symbols[j].Value
})
- file := &File{}
+ file := &File{IsMachoFile: true}
for _, section := range machoFile.Sections {
file.Sections = append(file.Sections, &Section{
@@ -95,3 +96,8 @@
return nil
}
+
+func CodeSignMachoFile(path string) error {
+ cmd := exec.Command("/usr/bin/codesign", "--force", "-s", "-", path)
+ return cmd.Run()
+}
diff --git a/symbol_inject/symbol_inject.go b/symbol_inject/symbol_inject.go
index 2a3d67e..77aff6f 100644
--- a/symbol_inject/symbol_inject.go
+++ b/symbol_inject/symbol_inject.go
@@ -161,9 +161,10 @@
}
type File struct {
- r io.ReaderAt
- Symbols []*Symbol
- Sections []*Section
+ r io.ReaderAt
+ Symbols []*Symbol
+ Sections []*Section
+ IsMachoFile bool
}
type Symbol struct {