diff options
author | Daniel Norman <danielnorman@google.com> | 2021-06-18 20:06:44 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2021-06-18 20:06:44 +0000 |
commit | e1a058ad0bad84b928a729ff51574484fedc38b5 (patch) | |
tree | ee928945aef22bd1210de129c7e134b27c46ca0a /cc | |
parent | fc87495728540b3cadd017cf3fd531f584702c9d (diff) | |
parent | 891a3695965b82ed7dd8048117413518f9a12850 (diff) |
Merge "Merge SP1A.210604.001" into s-keystone-qcom-dev
Diffstat (limited to 'cc')
-rw-r--r-- | cc/Android.bp | 1 | ||||
-rw-r--r-- | cc/bp2build.go | 2 | ||||
-rw-r--r-- | cc/builder.go | 1 | ||||
-rw-r--r-- | cc/cc.go | 17 | ||||
-rw-r--r-- | cc/config/Android.bp | 2 | ||||
-rw-r--r-- | cc/config/bp2build.go | 148 | ||||
-rw-r--r-- | cc/config/bp2build_test.go | 91 | ||||
-rw-r--r-- | cc/config/clang.go | 20 | ||||
-rw-r--r-- | cc/config/global.go | 47 | ||||
-rw-r--r-- | cc/config/vndk.go | 3 | ||||
-rw-r--r-- | cc/coverage.go | 3 | ||||
-rw-r--r-- | cc/linker.go | 21 | ||||
-rw-r--r-- | cc/sanitize.go | 4 | ||||
-rw-r--r-- | cc/sanitize_test.go | 204 | ||||
-rw-r--r-- | cc/test.go | 36 |
15 files changed, 541 insertions, 59 deletions
diff --git a/cc/Android.bp b/cc/Android.bp index c32cca8b8..1fc8d9f68 100644 --- a/cc/Android.bp +++ b/cc/Android.bp @@ -92,6 +92,7 @@ bootstrap_go_package { "object_test.go", "prebuilt_test.go", "proto_test.go", + "sanitize_test.go", "test_data_test.go", "vendor_public_library_test.go", "vendor_snapshot_test.go", diff --git a/cc/bp2build.go b/cc/bp2build.go index 4c01de562..9f9143b37 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -190,7 +190,7 @@ func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Modul // Parse the list of copts. parseCopts := func(baseCompilerProps *BaseCompilerProperties) []string { var copts []string - for _, flag := range baseCompilerProps.Cflags { + for _, flag := range append(baseCompilerProps.Cflags, baseCompilerProps.Cppflags...) { // Soong's cflags can contain spaces, like `-include header.h`. For // Bazel's copts, split them up to be compatible with the // no_copts_tokenization feature. diff --git a/cc/builder.go b/cc/builder.go index 52b2a79c3..667d766a8 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -821,6 +821,7 @@ func transformObjToDynamicBinary(ctx android.ModuleContext, ImplicitOutputs: implicitOutputs, Inputs: objFiles, Implicits: deps, + OrderOnly: sharedLibs, Args: args, }) } @@ -733,12 +733,6 @@ var ( llndkStubDepTag = dependencyTag{name: "llndk stub"} ) -type copyDirectlyInAnyApexDependencyTag dependencyTag - -func (copyDirectlyInAnyApexDependencyTag) CopyDirectlyInAnyApex() {} - -var _ android.CopyDirectlyInAnyApexTag = copyDirectlyInAnyApexDependencyTag{} - func IsSharedDepTag(depTag blueprint.DependencyTag) bool { ccLibDepTag, ok := depTag.(libraryDependencyTag) return ok && ccLibDepTag.shared() @@ -2851,7 +2845,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // Add the dependency to the APEX(es) providing the library so that // m <module> can trigger building the APEXes as well. depApexInfo := ctx.OtherModuleProvider(dep, android.ApexInfoProvider).(android.ApexInfo) - for _, an := range depApexInfo.InApexes { + for _, an := range depApexInfo.InApexVariants { c.Properties.ApexesProvidingSharedLibs = append( c.Properties.ApexesProvidingSharedLibs, an) } @@ -3248,6 +3242,9 @@ func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu return false } } + if cc.IsLlndk() { + return false + } if isLibDepTag && c.static() && libDepTag.shared() { // shared_lib dependency from a static lib is considered as crossing // the APEX boundary because the dependency doesn't actually is @@ -3314,6 +3311,12 @@ func (c *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, return nil } +// Implements android.ApexModule +func (c *Module) AlwaysRequiresPlatformApexVariant() bool { + // stub libraries and native bridge libraries are always available to platform + return c.IsStubs() || c.Target().NativeBridge == android.NativeBridgeEnabled +} + // // Defaults // diff --git a/cc/config/Android.bp b/cc/config/Android.bp index 5ef247df9..e4a8b6203 100644 --- a/cc/config/Android.bp +++ b/cc/config/Android.bp @@ -10,6 +10,7 @@ bootstrap_go_package { "soong-remoteexec", ], srcs: [ + "bp2build.go", "clang.go", "global.go", "tidy.go", @@ -31,6 +32,7 @@ bootstrap_go_package { "arm64_linux_host.go", ], testSrcs: [ + "bp2build_test.go", "tidy_test.go", ], } diff --git a/cc/config/bp2build.go b/cc/config/bp2build.go new file mode 100644 index 000000000..16892e654 --- /dev/null +++ b/cc/config/bp2build.go @@ -0,0 +1,148 @@ +// Copyright 2021 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 config + +import ( + "android/soong/android" + "fmt" + "regexp" + "strings" +) + +// Helpers for exporting cc configuration information to Bazel. + +var ( + // Map containing toolchain variables that are independent of the + // environment variables of the build. + exportedVars = exportedVariablesMap{} +) + +// variableValue is a string slice because the exported variables are all lists +// of string, and it's simpler to manipulate string lists before joining them +// into their final string representation. +type variableValue []string + +// envDependentVariable is a toolchain variable computed based on an environment variable. +type exportedVariablesMap map[string]variableValue + +func (m exportedVariablesMap) Set(k string, v variableValue) { + m[k] = v +} + +// Convenience function to declare a static variable and export it to Bazel's cc_toolchain. +func staticVariableExportedToBazel(name string, value []string) { + pctx.StaticVariable(name, strings.Join(value, " ")) + exportedVars.Set(name, variableValue(value)) +} + +// BazelCcToolchainVars generates bzl file content containing variables for +// Bazel's cc_toolchain configuration. +func BazelCcToolchainVars() string { + ret := "# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.\n\n" + + // Ensure that string s has no invalid characters to be generated into the bzl file. + validateCharacters := func(s string) string { + for _, c := range []string{`\n`, `"`, `\`} { + if strings.Contains(s, c) { + panic(fmt.Errorf("%s contains illegal character %s", s, c)) + } + } + return s + } + + // For each exported variable, recursively expand elements in the variableValue + // list to ensure that interpolated variables are expanded according to their values + // in the exportedVars scope. + for _, k := range android.SortedStringKeys(exportedVars) { + variableValue := exportedVars[k] + var expandedVars []string + for _, v := range variableValue { + expandedVars = append(expandedVars, expandVar(v, exportedVars)...) + } + // Build the list for this variable. + list := "[" + for _, flag := range expandedVars { + list += fmt.Sprintf("\n \"%s\",", validateCharacters(flag)) + } + list += "\n]" + // Assign the list as a bzl-private variable; this variable will be exported + // out through a constants struct later. + ret += fmt.Sprintf("_%s = %s\n", k, list) + ret += "\n" + } + + // Build the exported constants struct. + ret += "constants = struct(\n" + for _, k := range android.SortedStringKeys(exportedVars) { + ret += fmt.Sprintf(" %s = _%s,\n", k, k) + } + ret += ")" + return ret +} + +// expandVar recursively expand interpolated variables in the exportedVars scope. +// +// We're using a string slice to track the seen variables to avoid +// stackoverflow errors with infinite recursion. it's simpler to use a +// string slice than to handle a pass-by-referenced map, which would make it +// quite complex to track depth-first interpolations. It's also unlikely the +// interpolation stacks are deep (n > 1). +func expandVar(toExpand string, exportedVars map[string]variableValue) []string { + // e.g. "${ClangExternalCflags}" + r := regexp.MustCompile(`\${([a-zA-Z0-9_]+)}`) + + // Internal recursive function. + var expandVarInternal func(string, map[string]bool) []string + expandVarInternal = func(toExpand string, seenVars map[string]bool) []string { + var ret []string + for _, v := range strings.Split(toExpand, " ") { + matches := r.FindStringSubmatch(v) + if len(matches) == 0 { + return []string{v} + } + + if len(matches) != 2 { + panic(fmt.Errorf( + "Expected to only match 1 subexpression in %s, got %d", + v, + len(matches)-1)) + } + + // Index 1 of FindStringSubmatch contains the subexpression match + // (variable name) of the capture group. + variable := matches[1] + // toExpand contains a variable. + if _, ok := seenVars[variable]; ok { + panic(fmt.Errorf( + "Unbounded recursive interpolation of variable: %s", variable)) + } + // A map is passed-by-reference. Create a new map for + // this scope to prevent variables seen in one depth-first expansion + // to be also treated as "seen" in other depth-first traversals. + newSeenVars := map[string]bool{} + for k := range seenVars { + newSeenVars[k] = true + } + newSeenVars[variable] = true + unexpandedVars := exportedVars[variable] + for _, unexpandedVar := range unexpandedVars { + ret = append(ret, expandVarInternal(unexpandedVar, newSeenVars)...) + } + } + return ret + } + + return expandVarInternal(toExpand, map[string]bool{}) +} diff --git a/cc/config/bp2build_test.go b/cc/config/bp2build_test.go new file mode 100644 index 000000000..7744b4bfa --- /dev/null +++ b/cc/config/bp2build_test.go @@ -0,0 +1,91 @@ +// Copyright 2021 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 config + +import ( + "testing" +) + +func TestExpandVars(t *testing.T) { + testCases := []struct { + description string + exportedVars map[string]variableValue + toExpand string + expectedValues []string + }{ + { + description: "single level expansion", + exportedVars: map[string]variableValue{ + "foo": variableValue([]string{"bar"}), + }, + toExpand: "${foo}", + expectedValues: []string{"bar"}, + }, + { + description: "double level expansion", + exportedVars: map[string]variableValue{ + "foo": variableValue([]string{"${bar}"}), + "bar": variableValue([]string{"baz"}), + }, + toExpand: "${foo}", + expectedValues: []string{"baz"}, + }, + { + description: "double level expansion with a literal", + exportedVars: map[string]variableValue{ + "a": variableValue([]string{"${b}", "c"}), + "b": variableValue([]string{"d"}), + }, + toExpand: "${a}", + expectedValues: []string{"d", "c"}, + }, + { + description: "double level expansion, with two variables in a string", + exportedVars: map[string]variableValue{ + "a": variableValue([]string{"${b} ${c}"}), + "b": variableValue([]string{"d"}), + "c": variableValue([]string{"e"}), + }, + toExpand: "${a}", + expectedValues: []string{"d", "e"}, + }, + { + description: "triple level expansion with two variables in a string", + exportedVars: map[string]variableValue{ + "a": variableValue([]string{"${b} ${c}"}), + "b": variableValue([]string{"${c}", "${d}"}), + "c": variableValue([]string{"${d}"}), + "d": variableValue([]string{"foo"}), + }, + toExpand: "${a}", + expectedValues: []string{"foo", "foo", "foo"}, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.description, func(t *testing.T) { + output := expandVar(testCase.toExpand, testCase.exportedVars) + if len(output) != len(testCase.expectedValues) { + t.Errorf("Expected %d values, got %d", len(testCase.expectedValues), len(output)) + } + for i, actual := range output { + expectedValue := testCase.expectedValues[i] + if actual != expectedValue { + t.Errorf("Actual value '%s' doesn't match expected value '%s'", actual, expectedValue) + } + } + }) + } +} diff --git a/cc/config/clang.go b/cc/config/clang.go index 5e46d5ac0..4fbb9c33e 100644 --- a/cc/config/clang.go +++ b/cc/config/clang.go @@ -98,7 +98,7 @@ var ClangTidyDisableChecks = []string{ } func init() { - pctx.StaticVariable("ClangExtraCflags", strings.Join([]string{ + staticVariableExportedToBazel("ClangExtraCflags", []string{ "-D__compiler_offsetof=__builtin_offsetof", // Emit address-significance table which allows linker to perform safe ICF. Clang does @@ -151,9 +151,9 @@ func init() { // This macro allows the bionic versioning.h to indirectly determine whether the // option -Wunguarded-availability is on or not. "-D__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__", - }, " ")) + }) - pctx.StaticVariable("ClangExtraCppflags", strings.Join([]string{ + staticVariableExportedToBazel("ClangExtraCppflags", []string{ // -Wimplicit-fallthrough is not enabled by -Wall. "-Wimplicit-fallthrough", @@ -162,13 +162,11 @@ func init() { // libc++'s math.h has an #include_next outside of system_headers. "-Wno-gnu-include-next", - }, " ")) + }) - pctx.StaticVariable("ClangExtraTargetCflags", strings.Join([]string{ - "-nostdlibinc", - }, " ")) + staticVariableExportedToBazel("ClangExtraTargetCflags", []string{"-nostdlibinc"}) - pctx.StaticVariable("ClangExtraNoOverrideCflags", strings.Join([]string{ + staticVariableExportedToBazel("ClangExtraNoOverrideCflags", []string{ "-Werror=address-of-temporary", // Bug: http://b/29823425 Disable -Wnull-dereference until the // new cases detected by this warning in Clang r271374 are @@ -203,11 +201,11 @@ func init() { "-Wno-non-c-typedef-for-linkage", // http://b/161304145 // New warnings to be fixed after clang-r407598 "-Wno-string-concatenation", // http://b/175068488 - }, " ")) + }) // Extra cflags for external third-party projects to disable warnings that // are infeasible to fix in all the external projects and their upstream repos. - pctx.StaticVariable("ClangExtraExternalCflags", strings.Join([]string{ + staticVariableExportedToBazel("ClangExtraExternalCflags", []string{ "-Wno-enum-compare", "-Wno-enum-compare-switch", @@ -228,7 +226,7 @@ func init() { // http://b/165945989 "-Wno-psabi", - }, " ")) + }) } func ClangFilterUnknownCflags(cflags []string) []string { diff --git a/cc/config/global.go b/cc/config/global.go index f6f2b7fa5..4c2d783dd 100644 --- a/cc/config/global.go +++ b/cc/config/global.go @@ -195,13 +195,26 @@ func init() { } } - pctx.StaticVariable("CommonGlobalConlyflags", strings.Join(commonGlobalConlyflags, " ")) - pctx.StaticVariable("DeviceGlobalCppflags", strings.Join(deviceGlobalCppflags, " ")) - pctx.StaticVariable("DeviceGlobalLdflags", strings.Join(deviceGlobalLdflags, " ")) - pctx.StaticVariable("DeviceGlobalLldflags", strings.Join(deviceGlobalLldflags, " ")) - pctx.StaticVariable("HostGlobalCppflags", strings.Join(hostGlobalCppflags, " ")) - pctx.StaticVariable("HostGlobalLdflags", strings.Join(hostGlobalLdflags, " ")) - pctx.StaticVariable("HostGlobalLldflags", strings.Join(hostGlobalLldflags, " ")) + + staticVariableExportedToBazel("CommonGlobalConlyflags", commonGlobalConlyflags) + staticVariableExportedToBazel("DeviceGlobalCppflags", deviceGlobalCppflags) + staticVariableExportedToBazel("DeviceGlobalLdflags", deviceGlobalLdflags) + staticVariableExportedToBazel("DeviceGlobalLldflags", deviceGlobalLldflags) + staticVariableExportedToBazel("HostGlobalCppflags", hostGlobalCppflags) + staticVariableExportedToBazel("HostGlobalLdflags", hostGlobalLdflags) + staticVariableExportedToBazel("HostGlobalLldflags", hostGlobalLldflags) + + // Export the static default CommonClangGlobalCflags to Bazel. + // TODO(187086342): handle cflags that are set in VariableFuncs. + commonClangGlobalCFlags := append( + ClangFilterUnknownCflags(commonGlobalCflags), + []string{ + "${ClangExtraCflags}", + // Default to zero initialization. + "-ftrivial-auto-var-init=zero", + "-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang", + }...) + exportedVars.Set("CommonClangGlobalCflags", variableValue(commonClangGlobalCFlags)) pctx.VariableFunc("CommonClangGlobalCflags", func(ctx android.PackageVarContext) string { flags := ClangFilterUnknownCflags(commonGlobalCflags) @@ -220,26 +233,26 @@ func init() { // Default to zero initialization. flags = append(flags, "-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang") } - return strings.Join(flags, " ") }) + // Export the static default DeviceClangGlobalCflags to Bazel. + // TODO(187086342): handle cflags that are set in VariableFuncs. + deviceClangGlobalCflags := append(ClangFilterUnknownCflags(deviceGlobalCflags), "${ClangExtraTargetCflags}") + exportedVars.Set("DeviceClangGlobalCflags", variableValue(deviceClangGlobalCflags)) + pctx.VariableFunc("DeviceClangGlobalCflags", func(ctx android.PackageVarContext) string { if ctx.Config().Fuchsia() { return strings.Join(ClangFilterUnknownCflags(deviceGlobalCflags), " ") } else { - return strings.Join(append(ClangFilterUnknownCflags(deviceGlobalCflags), "${ClangExtraTargetCflags}"), " ") + return strings.Join(deviceClangGlobalCflags, " ") } }) - pctx.StaticVariable("HostClangGlobalCflags", - strings.Join(ClangFilterUnknownCflags(hostGlobalCflags), " ")) - pctx.StaticVariable("NoOverrideClangGlobalCflags", - strings.Join(append(ClangFilterUnknownCflags(noOverrideGlobalCflags), "${ClangExtraNoOverrideCflags}"), " ")) - - pctx.StaticVariable("CommonClangGlobalCppflags", - strings.Join(append(ClangFilterUnknownCflags(commonGlobalCppflags), "${ClangExtraCppflags}"), " ")) - pctx.StaticVariable("ClangExternalCflags", "${ClangExtraExternalCflags}") + staticVariableExportedToBazel("HostClangGlobalCflags", ClangFilterUnknownCflags(hostGlobalCflags)) + staticVariableExportedToBazel("NoOverrideClangGlobalCflags", append(ClangFilterUnknownCflags(noOverrideGlobalCflags), "${ClangExtraNoOverrideCflags}")) + staticVariableExportedToBazel("CommonClangGlobalCppflags", append(ClangFilterUnknownCflags(commonGlobalCppflags), "${ClangExtraCppflags}")) + staticVariableExportedToBazel("ClangExternalCflags", []string{"${ClangExtraExternalCflags}"}) // Everything in these lists is a crime against abstraction and dependency tracking. // Do not add anything to this list. diff --git a/cc/config/vndk.go b/cc/config/vndk.go index 07f21a1fb..31cccf4a2 100644 --- a/cc/config/vndk.go +++ b/cc/config/vndk.go @@ -33,6 +33,7 @@ var VndkMustUseVendorVariantList = []string{ "android.hardware.light-V1-ndk_platform", "android.hardware.light-ndk_platform", "android.hardware.identity-V2-ndk_platform", + "android.hardware.identity-V3-ndk_platform", "android.hardware.identity-ndk_platform", "android.hardware.nfc@1.2", "android.hardware.memtrack-V1-ndk_platform", @@ -42,6 +43,7 @@ var VndkMustUseVendorVariantList = []string{ "android.hardware.oemlock-ndk_platform", "android.hardware.oemlock-unstable-ndk_platform", "android.hardware.power-V1-ndk_platform", + "android.hardware.power-V2-ndk_platform", "android.hardware.power-ndk_platform", "android.hardware.power.stats-V1-ndk_platform", "android.hardware.power.stats-ndk_platform", @@ -58,6 +60,7 @@ var VndkMustUseVendorVariantList = []string{ "android.hardware.security.sharedsecret-ndk_platform", "android.hardware.security.sharedsecret-unstable-ndk_platform", "android.hardware.vibrator-V1-ndk_platform", + "android.hardware.vibrator-V2-ndk_platform", "android.hardware.vibrator-ndk_platform", "android.hardware.weaver-V1-ndk_platform", "android.hardware.weaver-ndk_platform", diff --git a/cc/coverage.go b/cc/coverage.go index b2788ecc6..baf422637 100644 --- a/cc/coverage.go +++ b/cc/coverage.go @@ -96,7 +96,8 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags // flags that the module may use. flags.Local.CFlags = append(flags.Local.CFlags, "-Wno-frame-larger-than=", "-O0") } else if clangCoverage { - flags.Local.CommonFlags = append(flags.Local.CommonFlags, profileInstrFlag, "-fcoverage-mapping", "-Wno-pass-failed") + flags.Local.CommonFlags = append(flags.Local.CommonFlags, profileInstrFlag, + "-fcoverage-mapping", "-Wno-pass-failed", "-D__ANDROID_CLANG_COVERAGE__") } } diff --git a/cc/linker.go b/cc/linker.go index a9930ada0..5bd21eda3 100644 --- a/cc/linker.go +++ b/cc/linker.go @@ -18,7 +18,6 @@ import ( "android/soong/android" "android/soong/cc/config" "fmt" - "strconv" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -390,17 +389,17 @@ func (linker *baseLinker) useClangLld(ctx ModuleContext) bool { } // Check whether the SDK version is not older than the specific one -func CheckSdkVersionAtLeast(ctx ModuleContext, SdkVersion int) bool { - if ctx.sdkVersion() == "current" { +func CheckSdkVersionAtLeast(ctx ModuleContext, SdkVersion android.ApiLevel) bool { + if ctx.minSdkVersion() == "current" { return true } - parsedSdkVersion, err := strconv.Atoi(ctx.sdkVersion()) + parsedSdkVersion, err := nativeApiLevelFromUser(ctx, ctx.minSdkVersion()) if err != nil { - ctx.PropertyErrorf("sdk_version", - "Invalid sdk_version value (must be int or current): %q", - ctx.sdkVersion()) + ctx.PropertyErrorf("min_sdk_version", + "Invalid min_sdk_version value (must be int or current): %q", + ctx.minSdkVersion()) } - if parsedSdkVersion < SdkVersion { + if parsedSdkVersion.LessThan(SdkVersion) { return false } return true @@ -425,13 +424,13 @@ func (linker *baseLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags { // ANDROID_RELR relocations were supported at API level >= 28. // Relocation packer was supported at API level >= 23. // Do the best we can... - if !ctx.useSdk() || CheckSdkVersionAtLeast(ctx, 30) { + if (!ctx.useSdk() && ctx.minSdkVersion() == "") || CheckSdkVersionAtLeast(ctx, android.FirstShtRelrVersion) { flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=android+relr") - } else if CheckSdkVersionAtLeast(ctx, 28) { + } else if CheckSdkVersionAtLeast(ctx, android.FirstAndroidRelrVersion) { flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=android+relr", "-Wl,--use-android-relr-tags") - } else if CheckSdkVersionAtLeast(ctx, 23) { + } else if CheckSdkVersionAtLeast(ctx, android.FirstPackedRelocationsVersion) { flags.Global.LdFlags = append(flags.Global.LdFlags, "-Wl,--pack-dyn-relocs=android") } } diff --git a/cc/sanitize.go b/cc/sanitize.go index 7a17906e7..af9ff1e3e 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -939,7 +939,7 @@ func sanitizerDepsMutator(t SanitizerType) func(android.TopDownMutatorContext) { if d, ok := child.(PlatformSanitizeable); ok && d.SanitizePropDefined() && !d.SanitizeNever() && !d.IsSanitizerExplicitlyDisabled(t) { - if t == cfi || t == Hwasan || t == scs { + if t == cfi || t == Hwasan || t == scs || t == Asan { if d.StaticallyLinked() && d.SanitizerSupported(t) { // Rust does not support some of these sanitizers, so we need to check if it's // supported before setting this true. @@ -1298,7 +1298,7 @@ func sanitizerMutator(t SanitizerType) func(android.BottomUpMutatorContext) { modules[0].(PlatformSanitizeable).SetSanitizer(t, true) } else if c.IsSanitizerEnabled(t) || c.SanitizeDep() { isSanitizerEnabled := c.IsSanitizerEnabled(t) - if c.StaticallyLinked() || c.Header() || t == Asan || t == Fuzzer { + if c.StaticallyLinked() || c.Header() || t == Fuzzer { // Static and header libs are split into non-sanitized and sanitized variants. // Shared libs are not split. However, for asan and fuzzer, we split even for shared // libs because a library sanitized for asan/fuzzer can't be linked from a library diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go new file mode 100644 index 000000000..f12634678 --- /dev/null +++ b/cc/sanitize_test.go @@ -0,0 +1,204 @@ +// Copyright 2021 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" +) + +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", + } +`)) + +func TestAsan(t *testing.T) { + bp := ` + cc_binary { + name: "bin_with_asan", + host_supported: true, + shared_libs: [ + "libshared", + "libasan", + ], + static_libs: [ + "libstatic", + "libnoasan", + ], + sanitize: { + address: true, + } + } + + cc_binary { + name: "bin_no_asan", + host_supported: true, + shared_libs: [ + "libshared", + "libasan", + ], + static_libs: [ + "libstatic", + "libnoasan", + ], + } + + cc_library_shared { + name: "libshared", + host_supported: true, + shared_libs: ["libtransitive"], + } + + cc_library_shared { + name: "libasan", + host_supported: true, + shared_libs: ["libtransitive"], + sanitize: { + address: true, + } + } + + cc_library_shared { + name: "libtransitive", + host_supported: true, + } + + cc_library_static { + name: "libstatic", + host_supported: true, + } + + cc_library_static { + name: "libnoasan", + host_supported: true, + sanitize: { + address: false, + } + } + ` + + result := android.GroupFixturePreparers( + prepareForCcTest, + prepareForAsanTest, + ).RunTestWithBp(t, bp) + + check := func(t *testing.T, result *android.TestResult, variant string) { + asanVariant := variant + "_asan" + sharedVariant := variant + "_shared" + sharedAsanVariant := sharedVariant + "_asan" + staticVariant := variant + "_static" + staticAsanVariant := staticVariant + "_asan" + + // The binaries, one with asan and one without + binWithAsan := result.ModuleForTests("bin_with_asan", asanVariant) + binNoAsan := result.ModuleForTests("bin_no_asan", variant) + + // Shared libraries that don't request asan + libShared := result.ModuleForTests("libshared", sharedVariant) + libTransitive := result.ModuleForTests("libtransitive", sharedVariant) + + // Shared library that requests asan + libAsan := result.ModuleForTests("libasan", sharedAsanVariant) + + // Static library that uses an asan variant for bin_with_asan and a non-asan variant + // for bin_no_asan. + libStaticAsanVariant := result.ModuleForTests("libstatic", staticAsanVariant) + libStaticNoAsanVariant := result.ModuleForTests("libstatic", staticVariant) + + // Static library that never uses asan. + libNoAsan := result.ModuleForTests("libnoasan", staticVariant) + + // expectSharedLinkDep verifies that the from module links against the to module as a + // shared library. + expectSharedLinkDep := func(from, to android.TestingModule) { + t.Helper() + fromLink := from.Description("link") + toLink := to.Description("strip") + + if g, w := fromLink.OrderOnly.Strings(), toLink.Output.String(); !android.InList(w, g) { + t.Errorf("%s should link against %s, expected %q, got %q", + from.Module(), to.Module(), w, g) + } + } + + // expectStaticLinkDep verifies that the from module links against the to module as a + // static library. + expectStaticLinkDep := func(from, to android.TestingModule) { + t.Helper() + fromLink := from.Description("link") + toLink := to.Description("static link") + + if g, w := fromLink.Implicits.Strings(), toLink.Output.String(); !android.InList(w, g) { + t.Errorf("%s should link against %s, expected %q, got %q", + from.Module(), to.Module(), w, g) + } + + } + + // expectInstallDep verifies that the install rule of the from module depends on the + // install rule of the to module. + expectInstallDep := func(from, to android.TestingModule) { + t.Helper() + fromInstalled := from.Description("install") + toInstalled := to.Description("install") + + // combine implicits and order-only dependencies, host uses implicit but device uses + // order-only. + got := append(fromInstalled.Implicits.Strings(), fromInstalled.OrderOnly.Strings()...) + want := toInstalled.Output.String() + if !android.InList(want, got) { + t.Errorf("%s installation should depend on %s, expected %q, got %q", + from.Module(), to.Module(), want, got) + } + } + + expectSharedLinkDep(binWithAsan, libShared) + expectSharedLinkDep(binWithAsan, libAsan) + expectSharedLinkDep(libShared, libTransitive) + expectSharedLinkDep(libAsan, libTransitive) + + expectStaticLinkDep(binWithAsan, libStaticAsanVariant) + expectStaticLinkDep(binWithAsan, libNoAsan) + + expectInstallDep(binWithAsan, libShared) + expectInstallDep(binWithAsan, libAsan) + expectInstallDep(binWithAsan, libTransitive) + expectInstallDep(libShared, libTransitive) + expectInstallDep(libAsan, libTransitive) + + expectSharedLinkDep(binNoAsan, libShared) + expectSharedLinkDep(binNoAsan, libAsan) + expectSharedLinkDep(libShared, libTransitive) + expectSharedLinkDep(libAsan, libTransitive) + + expectStaticLinkDep(binNoAsan, libStaticNoAsanVariant) + expectStaticLinkDep(binNoAsan, libNoAsan) + + expectInstallDep(binNoAsan, libShared) + expectInstallDep(binNoAsan, libAsan) + expectInstallDep(binNoAsan, libTransitive) + expectInstallDep(libShared, libTransitive) + expectInstallDep(libAsan, libTransitive) + } + + t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) }) + t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") }) +} diff --git a/cc/test.go b/cc/test.go index d4c23d7bf..047a69e3e 100644 --- a/cc/test.go +++ b/cc/test.go @@ -48,12 +48,19 @@ type TestOptions struct { Unit_test *bool // Add ShippingApiLevelModuleController to auto generated test config. If the device properties - // for the shipping api level is less than the test_min_api_level, skip this module. - Test_min_api_level *int64 + // for the shipping api level is less than the min_shipping_api_level, skip this module. + Min_shipping_api_level *int64 + + // Add ShippingApiLevelModuleController to auto generated test config. If any of the device + // shipping api level and vendor api level properties are less than the + // vsr_min_shipping_api_level, skip this module. + // As this includes the shipping api level check, it is not allowed to define + // min_shipping_api_level at the same time with this property. + Vsr_min_shipping_api_level *int64 // Add MinApiLevelModuleController with ro.vndk.version property. If ro.vndk.version has an - // integer value and the value is less than the test_min_vndk_version, skip this module. - Test_min_vndk_version *int64 + // integer value and the value is less than the min_vndk_version, skip this module. + Min_vndk_version *int64 } type TestBinaryProperties struct { @@ -97,7 +104,7 @@ type TestBinaryProperties struct { // Add ShippingApiLevelModuleController to auto generated test config. If the device properties // for the shipping api level is less than the test_min_api_level, skip this module. - // Deprecated (b/187258404). Use test_options.test_min_api_level instead. + // Deprecated (b/187258404). Use test_options.min_shipping_api_level instead. Test_min_api_level *int64 // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml @@ -404,19 +411,30 @@ func (test *testBinary) install(ctx ModuleContext, file android.Path) { for _, tag := range test.Properties.Test_options.Test_suite_tag { configs = append(configs, tradefed.Option{Name: "test-suite-tag", Value: tag}) } - if test.Properties.Test_options.Test_min_api_level != nil { + if test.Properties.Test_options.Min_shipping_api_level != nil { + if test.Properties.Test_options.Vsr_min_shipping_api_level != nil { + ctx.PropertyErrorf("test_options.min_shipping_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.") + } var options []tradefed.Option - options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Test_min_api_level), 10)}) + options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Min_shipping_api_level), 10)}) configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options}) } else if test.Properties.Test_min_api_level != nil { // TODO: (b/187258404) Remove test.Properties.Test_min_api_level + if test.Properties.Test_options.Vsr_min_shipping_api_level != nil { + ctx.PropertyErrorf("test_min_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.") + } var options []tradefed.Option options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_min_api_level), 10)}) configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options}) } - if test.Properties.Test_options.Test_min_vndk_version != nil { + if test.Properties.Test_options.Vsr_min_shipping_api_level != nil { + var options []tradefed.Option + options = append(options, tradefed.Option{Name: "vsr-min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Vsr_min_shipping_api_level), 10)}) + configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options}) + } + if test.Properties.Test_options.Min_vndk_version != nil { var options []tradefed.Option - options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Test_min_vndk_version), 10)}) + options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Min_vndk_version), 10)}) options = append(options, tradefed.Option{Name: "api-level-prop", Value: "ro.vndk.version"}) configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.MinApiLevelModuleController", options}) } |