Merge "Convert apex_available (for supported modules) to bazel tags."
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 5658503..e7bd920 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -387,8 +387,11 @@
"prebuilts/sdk":/* recursive = */ false,
"prebuilts/sdk/tools":/* recursive = */ false,
"prebuilts/r8":/* recursive = */ false,
+ "prebuilts/runtime":/* recursive = */ false,
- "tools/asuite/atest/":/* recursive = */ true,
+ // not recursive due to conflicting workspace paths in tools/atest/bazel/rules
+ "tools/asuite/atest":/* recursive = */ false,
+ "tools/asuite/atest/bazel/reporter":/* recursive = */ true,
}
Bp2buildModuleAlwaysConvertList = []string{
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index acb81a4..cf74b9c 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -18,7 +18,6 @@
"bytes"
"errors"
"fmt"
- "io/ioutil"
"os"
"os/exec"
"path"
@@ -260,11 +259,11 @@
return result, nil
}
-func (m MockBazelContext) InvokeBazel(_ Config, ctx *Context) error {
+func (m MockBazelContext) InvokeBazel(_ Config, _ *Context) error {
panic("unimplemented")
}
-func (m MockBazelContext) BazelAllowlisted(moduleName string) bool {
+func (m MockBazelContext) BazelAllowlisted(_ string) bool {
return true
}
@@ -356,7 +355,7 @@
panic("implement me")
}
-func (n noopBazelContext) InvokeBazel(_ Config, ctx *Context) error {
+func (n noopBazelContext) InvokeBazel(_ Config, _ *Context) error {
panic("unimplemented")
}
@@ -364,7 +363,7 @@
return ""
}
-func (n noopBazelContext) BazelAllowlisted(moduleName string) bool {
+func (n noopBazelContext) BazelAllowlisted(_ string) bool {
return false
}
@@ -403,7 +402,7 @@
// Don't use partially-converted cc_library targets in mixed builds,
// since mixed builds would generally rely on both static and shared
// variants of a cc_library.
- for staticOnlyModule, _ := range GetBp2BuildAllowList().ccLibraryStaticOnly {
+ for staticOnlyModule := range GetBp2BuildAllowList().ccLibraryStaticOnly {
disabledModules[staticOnlyModule] = true
}
for _, disabledDevModule := range allowlists.MixedBuildsDisabledList {
@@ -509,7 +508,7 @@
extraFlags []string
}
-func (r *mockBazelRunner) createBazelCommand(paths *bazelPaths, runName bazel.RunName,
+func (r *mockBazelRunner) createBazelCommand(_ *bazelPaths, _ bazel.RunName,
command bazelCommand, extraFlags ...string) *exec.Cmd {
r.commands = append(r.commands, command)
r.extraFlags = append(r.extraFlags, strings.Join(extraFlags, " "))
@@ -534,13 +533,13 @@
// 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) {
stderr := &bytes.Buffer{}
bazelCmd.Stderr = stderr
if output, err := bazelCmd.Output(); err != nil {
return "", string(stderr.Bytes()),
- fmt.Errorf("bazel command failed. command: [%s], env: [%s], error [%s]", bazelCmd, bazelCmd.Env, stderr)
+ fmt.Errorf("bazel command failed: %s\n---command---\n%s\n---env---\n%s\n---stderr---\n%s---",
+ err, bazelCmd, strings.Join(bazelCmd.Env, "\n"), stderr)
} else {
return string(output), string(stderr.Bytes()), nil
}
@@ -916,17 +915,17 @@
return err
}
}
- if err := ioutil.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil {
+ if err := os.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil {
return err
}
- if err := ioutil.WriteFile(filepath.Join(mixedBuildsPath, "main.bzl"), context.mainBzlFileContents(), 0666); err != nil {
+ if err := os.WriteFile(filepath.Join(mixedBuildsPath, "main.bzl"), context.mainBzlFileContents(), 0666); err != nil {
return err
}
- if err := ioutil.WriteFile(filepath.Join(mixedBuildsPath, "BUILD.bazel"), context.mainBuildFileContents(), 0666); err != nil {
+ if err := os.WriteFile(filepath.Join(mixedBuildsPath, "BUILD.bazel"), context.mainBuildFileContents(), 0666); err != nil {
return err
}
cqueryFileRelpath := filepath.Join(context.paths.injectedFilesDir(), "buildroot.cquery")
- if err := ioutil.WriteFile(absolutePath(cqueryFileRelpath), context.cqueryStarlarkFileContents(), 0666); err != nil {
+ if err := os.WriteFile(absolutePath(cqueryFileRelpath), context.cqueryStarlarkFileContents(), 0666); err != nil {
return err
}
@@ -937,7 +936,7 @@
return cqueryErr
}
cqueryCommandPrint := fmt.Sprintf("cquery command line:\n %s \n\n\n", printableCqueryCommand(cqueryCommandWithFlag))
- if err := ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"), []byte(cqueryCommandPrint+cqueryOutput), 0666); err != nil {
+ if err := os.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"), []byte(cqueryCommandPrint+cqueryOutput), 0666); err != nil {
return err
}
cqueryResults := map[string]string{}
@@ -972,7 +971,7 @@
extraFlags = append(extraFlags, "--collect_code_coverage")
paths := make([]string, 0, 2)
if p := config.productVariables.NativeCoveragePaths; len(p) > 0 {
- for i, _ := range p {
+ for i := range p {
// TODO(b/259404593) convert path wildcard to regex values
if p[i] == "*" {
p[i] = ".*"
@@ -1039,7 +1038,7 @@
filepath.Dir(ctx.Config().moduleListFile), "bazel.list"))
ctx.AddNinjaFileDeps(bazelBuildList)
- data, err := ioutil.ReadFile(bazelBuildList)
+ data, err := os.ReadFile(bazelBuildList)
if err != nil {
ctx.Errorf(err.Error())
}
diff --git a/android/testing.go b/android/testing.go
index 8fcf440..29af71f 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -203,6 +203,10 @@
ctx.PreArchMutators(f)
}
+func (ctx *TestContext) ModuleProvider(m blueprint.Module, p blueprint.ProviderKey) interface{} {
+ return ctx.Context.ModuleProvider(m, p)
+}
+
func (ctx *TestContext) PreDepsMutators(f RegisterMutatorFunc) {
ctx.preDeps = append(ctx.preDeps, f)
}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index aaf21e9..ce35b5c 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -530,8 +530,10 @@
entries.SubName = ""
- if c.sanitizerProperties.CfiEnabled {
+ if c.isSanitizerEnabled(cfi) {
entries.SubName += ".cfi"
+ } else if c.isSanitizerEnabled(Hwasan) {
+ entries.SubName += ".hwasan"
}
entries.SubName += c.baseProperties.Androidmk_suffix
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 64bb7dd..3da7651 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -301,7 +301,6 @@
baseInstallerPath := "fuzz"
binary.baseInstaller = NewBaseInstaller(baseInstallerPath, baseInstallerPath, InstallInData)
- module.sanitize.SetSanitizer(Fuzzer, true)
fuzzBin := &fuzzBinary{
binaryDecorator: binary,
@@ -315,7 +314,11 @@
// The fuzzer runtime is not present for darwin host modules, disable cc_fuzz modules when targeting darwin.
android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- disableDarwinAndLinuxBionic := struct {
+
+ extraProps := struct {
+ Sanitize struct {
+ Fuzzer *bool
+ }
Target struct {
Darwin struct {
Enabled *bool
@@ -325,9 +328,10 @@
}
}
}{}
- disableDarwinAndLinuxBionic.Target.Darwin.Enabled = BoolPtr(false)
- disableDarwinAndLinuxBionic.Target.Linux_bionic.Enabled = BoolPtr(false)
- ctx.AppendProperties(&disableDarwinAndLinuxBionic)
+ extraProps.Sanitize.Fuzzer = BoolPtr(true)
+ extraProps.Target.Darwin.Enabled = BoolPtr(false)
+ extraProps.Target.Linux_bionic.Enabled = BoolPtr(false)
+ ctx.AppendProperties(&extraProps)
targetFramework := fuzz.GetFramework(ctx, fuzz.Cc)
if !fuzz.IsValidFrameworkForModule(targetFramework, fuzz.Cc, fuzzBin.fuzzPackagedModule.FuzzProperties.Fuzzing_frameworks) {
diff --git a/cc/genrule.go b/cc/genrule.go
index 4ef990c..d1c4c2a 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -48,6 +48,8 @@
//
// CC_NATIVE_BRIDGE the name of the subdirectory that native bridge libraries are stored in if
// the architecture has native bridge enabled, empty if it is disabled.
+//
+// CC_OS the name of the OS the command is being executed for.
func GenRuleFactory() android.Module {
module := genrule.NewGenRule()
@@ -68,8 +70,9 @@
func genruleCmdModifier(ctx android.ModuleContext, cmd string) string {
target := ctx.Target()
arch := target.Arch.ArchType
- return fmt.Sprintf("CC_ARCH=%s CC_NATIVE_BRIDGE=%s CC_MULTILIB=%s && %s",
- arch.Name, target.NativeBridgeRelativePath, arch.Multilib, cmd)
+ osName := target.Os.Name
+ return fmt.Sprintf("CC_ARCH=%s CC_NATIVE_BRIDGE=%s CC_MULTILIB=%s CC_OS=%s && %s",
+ arch.Name, target.NativeBridgeRelativePath, arch.Multilib, osName, cmd)
}
var _ android.ImageInterface = (*GenruleExtraProperties)(nil)
diff --git a/cc/library_stub.go b/cc/library_stub.go
index 22e61a7..c61e2d1 100644
--- a/cc/library_stub.go
+++ b/cc/library_stub.go
@@ -172,7 +172,7 @@
// Copy LLDNK properties to cc_api_library module
d.libraryDecorator.flagExporter.Properties.Export_include_dirs = append(
d.libraryDecorator.flagExporter.Properties.Export_include_dirs,
- variantMod.exportProperties.Export_headers...)
+ variantMod.exportProperties.Export_include_dirs...)
// Export headers as system include dirs if specified. Mostly for libc
if Bool(variantMod.exportProperties.Export_headers_as_system) {
@@ -203,7 +203,7 @@
// Copy NDK properties to cc_api_library module
d.libraryDecorator.flagExporter.Properties.Export_include_dirs = append(
d.libraryDecorator.flagExporter.Properties.Export_include_dirs,
- variantMod.exportProperties.Export_headers...)
+ variantMod.exportProperties.Export_include_dirs...)
}
}
}
@@ -362,7 +362,7 @@
type variantExporterProperties struct {
// Header directory to export
- Export_headers []string `android:"arch_variant"`
+ Export_include_dirs []string `android:"arch_variant"`
// Export all headers as system include
Export_headers_as_system *bool
diff --git a/cc/library_stub_test.go b/cc/library_stub_test.go
index e372860..868447a 100644
--- a/cc/library_stub_test.go
+++ b/cc/library_stub_test.go
@@ -308,7 +308,7 @@
name: "libbar",
variant: "llndk",
src: "libbar_llndk.so",
- export_headers: ["libbar_llndk_include"]
+ export_include_dirs: ["libbar_llndk_include"]
}
api_imports {
@@ -370,7 +370,7 @@
variant: "ndk",
version: "29",
src: "libbar_ndk_29.so",
- export_headers: ["libbar_ndk_29_include"]
+ export_include_dirs: ["libbar_ndk_29_include"]
}
cc_api_variant {
@@ -378,7 +378,7 @@
variant: "ndk",
version: "30",
src: "libbar_ndk_30.so",
- export_headers: ["libbar_ndk_30_include"]
+ export_include_dirs: ["libbar_ndk_30_include"]
}
cc_api_variant {
@@ -386,7 +386,7 @@
variant: "ndk",
version: "current",
src: "libbar_ndk_current.so",
- export_headers: ["libbar_ndk_current_include"]
+ export_include_dirs: ["libbar_ndk_current_include"]
}
api_imports {
@@ -458,7 +458,7 @@
variant: "ndk",
version: "29",
src: "libbar_ndk_29.so",
- export_headers: ["libbar_ndk_29_include"]
+ export_include_dirs: ["libbar_ndk_29_include"]
}
cc_api_variant {
@@ -466,7 +466,7 @@
variant: "ndk",
version: "30",
src: "libbar_ndk_30.so",
- export_headers: ["libbar_ndk_30_include"]
+ export_include_dirs: ["libbar_ndk_30_include"]
}
cc_api_variant {
@@ -474,14 +474,14 @@
variant: "ndk",
version: "current",
src: "libbar_ndk_current.so",
- export_headers: ["libbar_ndk_current_include"]
+ export_include_dirs: ["libbar_ndk_current_include"]
}
cc_api_variant {
name: "libbar",
variant: "llndk",
src: "libbar_llndk.so",
- export_headers: ["libbar_llndk_include"]
+ export_include_dirs: ["libbar_llndk_include"]
}
api_imports {
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 2730052..9fbf879 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -763,10 +763,10 @@
if sanitize == nil {
return nil
}
- if Bool(sanitize.Properties.Sanitize.Address) && sanitized.Address.Srcs != nil {
+ if sanitize.isSanitizerEnabled(Asan) && sanitized.Address.Srcs != nil {
return sanitized.Address.Srcs
}
- if Bool(sanitize.Properties.Sanitize.Hwaddress) && sanitized.Hwaddress.Srcs != nil {
+ if sanitize.isSanitizerEnabled(Hwasan) && sanitized.Hwaddress.Srcs != nil {
return sanitized.Hwaddress.Srcs
}
return sanitized.None.Srcs
diff --git a/cc/sanitize.go b/cc/sanitize.go
index d3fc221..eba709b 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -171,6 +171,20 @@
}
}
+// shouldPropagateToSharedLibraryDeps returns whether a sanitizer type should propagate to share
+// dependencies. In most cases, sanitizers only propagate to static dependencies; however, some
+// sanitizers also must be enabled for shared libraries for linking.
+func (t SanitizerType) shouldPropagateToSharedLibraryDeps() bool {
+ switch t {
+ case Fuzzer:
+ // Typically, shared libs are not split. However, for fuzzer, we split even for shared libs
+ // because a library sanitized for fuzzer can't be linked from a library that isn't sanitized
+ // for fuzzer.
+ return true
+ default:
+ return false
+ }
+}
func (*Module) SanitizerSupported(t SanitizerType) bool {
switch t {
case Asan:
@@ -286,15 +300,72 @@
Blocklist *string
}
+type sanitizeMutatedProperties struct {
+ // Whether sanitizers can be enabled on this module
+ Never *bool `blueprint:"mutated"`
+
+ // Whether ASan (Address sanitizer) is enabled for this module.
+ // Hwaddress sanitizer takes precedence over this sanitizer.
+ Address *bool `blueprint:"mutated"`
+ // Whether TSan (Thread sanitizer) is enabled for this module
+ Thread *bool `blueprint:"mutated"`
+ // Whether HWASan (Hardware Address sanitizer) is enabled for this module
+ Hwaddress *bool `blueprint:"mutated"`
+
+ // Whether Undefined behavior sanitizer is enabled for this module
+ All_undefined *bool `blueprint:"mutated"`
+ // Whether undefined behavior sanitizer subset is enabled for this module
+ Undefined *bool `blueprint:"mutated"`
+ // List of specific undefined behavior sanitizers enabled for this module
+ Misc_undefined []string `blueprint:"mutated"`
+ // Whether Fuzzeris enabled for this module
+ Fuzzer *bool `blueprint:"mutated"`
+ // whether safe-stack sanitizer is enabled for this module
+ Safestack *bool `blueprint:"mutated"`
+ // Whether cfi sanitizer is enabled for this module
+ Cfi *bool `blueprint:"mutated"`
+ // Whether signed/unsigned integer overflow sanitizer is enabled for this module
+ Integer_overflow *bool `blueprint:"mutated"`
+ // Whether scudo sanitizer is enabled for this module
+ Scudo *bool `blueprint:"mutated"`
+ // Whether shadow-call-stack sanitizer is enabled for this module.
+ Scs *bool `blueprint:"mutated"`
+ // Whether Memory-tagging is enabled for this module
+ Memtag_heap *bool `blueprint:"mutated"`
+ // Whether Memory-tagging stack instrumentation is enabled for this module
+ Memtag_stack *bool `blueprint:"mutated"`
+
+ // Whether a modifier for ASAN and HWASAN for write only instrumentation is enabled for this
+ // module
+ Writeonly *bool `blueprint:"mutated"`
+
+ // Sanitizers to run in the diagnostic mode (as opposed to the release mode).
+ Diag struct {
+ // Whether Undefined behavior sanitizer, diagnostic mode is enabled for this module
+ Undefined *bool `blueprint:"mutated"`
+ // Whether cfi sanitizer, diagnostic mode is enabled for this module
+ Cfi *bool `blueprint:"mutated"`
+ // Whether signed/unsigned integer overflow sanitizer, diagnostic mode is enabled for this
+ // module
+ Integer_overflow *bool `blueprint:"mutated"`
+ // Whether Memory-tagging, diagnostic mode is enabled for this module
+ Memtag_heap *bool `blueprint:"mutated"`
+ // List of specific undefined behavior sanitizers enabled in diagnostic mode
+ Misc_undefined []string `blueprint:"mutated"`
+ } `blueprint:"mutated"`
+}
+
type SanitizeProperties struct {
- Sanitize SanitizeUserProps `android:"arch_variant"`
- SanitizerEnabled bool `blueprint:"mutated"`
- MinimalRuntimeDep bool `blueprint:"mutated"`
- BuiltinsDep bool `blueprint:"mutated"`
- UbsanRuntimeDep bool `blueprint:"mutated"`
- InSanitizerDir bool `blueprint:"mutated"`
- Sanitizers []string `blueprint:"mutated"`
- DiagSanitizers []string `blueprint:"mutated"`
+ Sanitize SanitizeUserProps `android:"arch_variant"`
+ SanitizeMutated sanitizeMutatedProperties `blueprint:"mutated"`
+
+ SanitizerEnabled bool `blueprint:"mutated"`
+ MinimalRuntimeDep bool `blueprint:"mutated"`
+ BuiltinsDep bool `blueprint:"mutated"`
+ UbsanRuntimeDep bool `blueprint:"mutated"`
+ InSanitizerDir bool `blueprint:"mutated"`
+ Sanitizers []string `blueprint:"mutated"`
+ DiagSanitizers []string `blueprint:"mutated"`
}
type sanitize struct {
@@ -317,8 +388,42 @@
return []interface{}{&sanitize.Properties}
}
+func (p *sanitizeMutatedProperties) copyUserPropertiesToMutated(userProps *SanitizeUserProps) {
+ p.Never = userProps.Never
+ p.Address = userProps.Address
+ p.All_undefined = userProps.All_undefined
+ p.Cfi = userProps.Cfi
+ p.Fuzzer = userProps.Fuzzer
+ p.Hwaddress = userProps.Hwaddress
+ p.Integer_overflow = userProps.Integer_overflow
+ p.Memtag_heap = userProps.Memtag_heap
+ p.Memtag_stack = userProps.Memtag_stack
+ p.Safestack = userProps.Safestack
+ p.Scs = userProps.Scs
+ p.Scudo = userProps.Scudo
+ p.Thread = userProps.Thread
+ p.Undefined = userProps.Undefined
+ p.Writeonly = userProps.Writeonly
+
+ p.Misc_undefined = make([]string, 0, len(userProps.Misc_undefined))
+ for _, v := range userProps.Misc_undefined {
+ p.Misc_undefined = append(p.Misc_undefined, v)
+ }
+
+ p.Diag.Cfi = userProps.Diag.Cfi
+ p.Diag.Integer_overflow = userProps.Diag.Integer_overflow
+ p.Diag.Memtag_heap = userProps.Diag.Memtag_heap
+ p.Diag.Undefined = userProps.Diag.Undefined
+
+ p.Diag.Misc_undefined = make([]string, 0, len(userProps.Diag.Misc_undefined))
+ for _, v := range userProps.Diag.Misc_undefined {
+ p.Diag.Misc_undefined = append(p.Diag.Misc_undefined, v)
+ }
+}
+
func (sanitize *sanitize) begin(ctx BaseModuleContext) {
- s := &sanitize.Properties.Sanitize
+ s := &sanitize.Properties.SanitizeMutated
+ s.copyUserPropertiesToMutated(&sanitize.Properties.Sanitize)
// Don't apply sanitizers to NDK code.
if ctx.useSdk() {
@@ -614,20 +719,13 @@
return false
}
-func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
- if !sanitize.Properties.SanitizerEnabled && !sanitize.Properties.UbsanRuntimeDep {
+func (s *sanitize) flags(ctx ModuleContext, flags Flags) Flags {
+ if !s.Properties.SanitizerEnabled && !s.Properties.UbsanRuntimeDep {
return flags
}
+ sanProps := &s.Properties.SanitizeMutated
- // Currently unwinding through tagged frames for exceptions is broken, so disable memtag stack
- // in that case, so we don't end up tagging those.
- // TODO(b/174878242): Remove once https://r.android.com/2251926 is included in toolchain.
- if android.InList("-fexceptions", flags.Local.CFlags) || android.InList("-fexceptions", flags.Global.CFlags) {
- sanitize.Properties.Sanitize.Memtag_stack = nil
- _, sanitize.Properties.Sanitizers = android.RemoveFromList("memtag-stack", sanitize.Properties.Sanitizers)
- }
-
- if Bool(sanitize.Properties.Sanitize.Address) {
+ if Bool(sanProps.Address) {
if ctx.Arch().ArchType == android.Arm {
// Frame pointer based unwinder in ASan requires ARM frame setup.
// TODO: put in flags?
@@ -636,7 +734,7 @@
flags.Local.CFlags = append(flags.Local.CFlags, asanCflags...)
flags.Local.LdFlags = append(flags.Local.LdFlags, asanLdflags...)
- if Bool(sanitize.Properties.Sanitize.Writeonly) {
+ if Bool(sanProps.Writeonly) {
flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-asan-instrument-reads=0")
}
@@ -657,7 +755,7 @@
}
}
- if Bool(sanitize.Properties.Sanitize.Hwaddress) {
+ if Bool(sanProps.Hwaddress) {
flags.Local.CFlags = append(flags.Local.CFlags, hwasanCflags...)
for _, flag := range hwasanCommonflags {
@@ -667,12 +765,12 @@
flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,"+flag)
}
- if Bool(sanitize.Properties.Sanitize.Writeonly) {
+ if Bool(sanProps.Writeonly) {
flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-hwasan-instrument-reads=0")
}
}
- if Bool(sanitize.Properties.Sanitize.Fuzzer) {
+ if Bool(sanProps.Fuzzer) {
flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize=fuzzer-no-link")
// TODO(b/131771163): LTO and Fuzzer support is mutually incompatible.
@@ -701,7 +799,7 @@
flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN`)
}
- if Bool(sanitize.Properties.Sanitize.Cfi) {
+ if Bool(sanProps.Cfi) {
if ctx.Arch().ArchType == android.Arm {
// __cfi_check needs to be built as Thumb (see the code in linker_cfi.cpp). LLVM is not set up
// to do this on a function basis, so force Thumb on the entire module.
@@ -710,7 +808,7 @@
flags.Local.CFlags = append(flags.Local.CFlags, cfiCflags...)
flags.Local.AsFlags = append(flags.Local.AsFlags, cfiAsflags...)
- if Bool(sanitize.Properties.Sanitize.Config.Cfi_assembly_support) {
+ if Bool(s.Properties.Sanitize.Config.Cfi_assembly_support) {
flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-cfi-canonical-jump-tables")
}
// Only append the default visibility flag if -fvisibility has not already been set
@@ -726,7 +824,7 @@
}
}
- if Bool(sanitize.Properties.Sanitize.Memtag_stack) {
+ if Bool(sanProps.Memtag_stack) {
flags.Local.CFlags = append(flags.Local.CFlags, memtagStackCommonFlags...)
// TODO(fmayer): remove -Wno-error once https://reviews.llvm.org/D127917 is in Android toolchain.
flags.Local.CFlags = append(flags.Local.CFlags, "-Wno-error=frame-larger-than")
@@ -737,20 +835,20 @@
flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--no-fatal-warnings")
}
- if (Bool(sanitize.Properties.Sanitize.Memtag_heap) || Bool(sanitize.Properties.Sanitize.Memtag_stack)) && ctx.binary() {
- if Bool(sanitize.Properties.Sanitize.Diag.Memtag_heap) {
+ if (Bool(sanProps.Memtag_heap) || Bool(sanProps.Memtag_stack)) && ctx.binary() {
+ if Bool(sanProps.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) {
+ if Bool(sanProps.Integer_overflow) {
flags.Local.CFlags = append(flags.Local.CFlags, intOverflowCflags...)
}
- if len(sanitize.Properties.Sanitizers) > 0 {
- sanitizeArg := "-fsanitize=" + strings.Join(sanitize.Properties.Sanitizers, ",")
+ if len(s.Properties.Sanitizers) > 0 {
+ sanitizeArg := "-fsanitize=" + strings.Join(s.Properties.Sanitizers, ",")
flags.Local.CFlags = append(flags.Local.CFlags, sanitizeArg)
flags.Local.AsFlags = append(flags.Local.AsFlags, sanitizeArg)
flags.Local.LdFlags = append(flags.Local.LdFlags, sanitizeArg)
@@ -774,7 +872,7 @@
flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=vptr,function")
}
- if Bool(sanitize.Properties.Sanitize.Fuzzer) {
+ if Bool(sanProps.Fuzzer) {
// When fuzzing, we wish to crash with diagnostics on any bug.
flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-trap=all", "-fno-sanitize-recover=all")
} else if ctx.Host() {
@@ -783,7 +881,7 @@
flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-trap=all", "-ftrap-function=abort")
}
- if enableMinimalRuntime(sanitize) {
+ if enableMinimalRuntime(s) {
flags.Local.CFlags = append(flags.Local.CFlags, strings.Join(minimalRuntimeFlags, " "))
}
@@ -797,22 +895,22 @@
}
}
- if len(sanitize.Properties.DiagSanitizers) > 0 {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-trap="+strings.Join(sanitize.Properties.DiagSanitizers, ","))
+ if len(s.Properties.DiagSanitizers) > 0 {
+ flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-trap="+strings.Join(s.Properties.DiagSanitizers, ","))
}
// FIXME: enable RTTI if diag + (cfi or vptr)
- if sanitize.Properties.Sanitize.Recover != nil {
+ if s.Properties.Sanitize.Recover != nil {
flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-recover="+
- strings.Join(sanitize.Properties.Sanitize.Recover, ","))
+ strings.Join(s.Properties.Sanitize.Recover, ","))
}
- if sanitize.Properties.Sanitize.Diag.No_recover != nil {
+ if s.Properties.Sanitize.Diag.No_recover != nil {
flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-recover="+
- strings.Join(sanitize.Properties.Sanitize.Diag.No_recover, ","))
+ strings.Join(s.Properties.Sanitize.Diag.No_recover, ","))
}
- blocklist := android.OptionalPathForModuleSrc(ctx, sanitize.Properties.Sanitize.Blocklist)
+ blocklist := android.OptionalPathForModuleSrc(ctx, s.Properties.Sanitize.Blocklist)
if blocklist.Valid() {
flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-ignorelist="+blocklist.String())
flags.CFlagsDeps = append(flags.CFlagsDeps, blocklist.Path())
@@ -821,47 +919,47 @@
return flags
}
-func (sanitize *sanitize) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
+func (s *sanitize) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
// Add a suffix for cfi/hwasan/scs-enabled static/header libraries to allow surfacing
// both the sanitized and non-sanitized variants to make without a name conflict.
if entries.Class == "STATIC_LIBRARIES" || entries.Class == "HEADER_LIBRARIES" {
- if Bool(sanitize.Properties.Sanitize.Cfi) {
+ if Bool(s.Properties.SanitizeMutated.Cfi) {
entries.SubName += ".cfi"
}
- if Bool(sanitize.Properties.Sanitize.Hwaddress) {
+ if Bool(s.Properties.SanitizeMutated.Hwaddress) {
entries.SubName += ".hwasan"
}
- if Bool(sanitize.Properties.Sanitize.Scs) {
+ if Bool(s.Properties.SanitizeMutated.Scs) {
entries.SubName += ".scs"
}
}
}
-func (sanitize *sanitize) inSanitizerDir() bool {
- return sanitize.Properties.InSanitizerDir
+func (s *sanitize) inSanitizerDir() bool {
+ return s.Properties.InSanitizerDir
}
// getSanitizerBoolPtr returns the SanitizerTypes associated bool pointer from SanitizeProperties.
-func (sanitize *sanitize) getSanitizerBoolPtr(t SanitizerType) *bool {
+func (s *sanitize) getSanitizerBoolPtr(t SanitizerType) *bool {
switch t {
case Asan:
- return sanitize.Properties.Sanitize.Address
+ return s.Properties.SanitizeMutated.Address
case Hwasan:
- return sanitize.Properties.Sanitize.Hwaddress
+ return s.Properties.SanitizeMutated.Hwaddress
case tsan:
- return sanitize.Properties.Sanitize.Thread
+ return s.Properties.SanitizeMutated.Thread
case intOverflow:
- return sanitize.Properties.Sanitize.Integer_overflow
+ return s.Properties.SanitizeMutated.Integer_overflow
case cfi:
- return sanitize.Properties.Sanitize.Cfi
+ return s.Properties.SanitizeMutated.Cfi
case scs:
- return sanitize.Properties.Sanitize.Scs
+ return s.Properties.SanitizeMutated.Scs
case Memtag_heap:
- return sanitize.Properties.Sanitize.Memtag_heap
+ return s.Properties.SanitizeMutated.Memtag_heap
case Memtag_stack:
- return sanitize.Properties.Sanitize.Memtag_stack
+ return s.Properties.SanitizeMutated.Memtag_stack
case Fuzzer:
- return sanitize.Properties.Sanitize.Fuzzer
+ return s.Properties.SanitizeMutated.Fuzzer
default:
panic(fmt.Errorf("unknown SanitizerType %d", t))
}
@@ -894,28 +992,28 @@
}
switch t {
case Asan:
- sanitize.Properties.Sanitize.Address = bPtr
+ sanitize.Properties.SanitizeMutated.Address = bPtr
// For ASAN variant, we need to disable Memtag_stack
- sanitize.Properties.Sanitize.Memtag_stack = nil
+ sanitize.Properties.SanitizeMutated.Memtag_stack = nil
case Hwasan:
- sanitize.Properties.Sanitize.Hwaddress = bPtr
+ sanitize.Properties.SanitizeMutated.Hwaddress = bPtr
// For HWAsan variant, we need to disable Memtag_stack
- sanitize.Properties.Sanitize.Memtag_stack = nil
+ sanitize.Properties.SanitizeMutated.Memtag_stack = nil
case tsan:
- sanitize.Properties.Sanitize.Thread = bPtr
+ sanitize.Properties.SanitizeMutated.Thread = bPtr
case intOverflow:
- sanitize.Properties.Sanitize.Integer_overflow = bPtr
+ sanitize.Properties.SanitizeMutated.Integer_overflow = bPtr
case cfi:
- sanitize.Properties.Sanitize.Cfi = bPtr
+ sanitize.Properties.SanitizeMutated.Cfi = bPtr
case scs:
- sanitize.Properties.Sanitize.Scs = bPtr
+ sanitize.Properties.SanitizeMutated.Scs = bPtr
case Memtag_heap:
- sanitize.Properties.Sanitize.Memtag_heap = bPtr
+ sanitize.Properties.SanitizeMutated.Memtag_heap = bPtr
case Memtag_stack:
- sanitize.Properties.Sanitize.Memtag_stack = bPtr
+ sanitize.Properties.SanitizeMutated.Memtag_stack = bPtr
// We do not need to disable ASAN or HWASan here, as there is no Memtag_stack variant.
case Fuzzer:
- sanitize.Properties.Sanitize.Fuzzer = bPtr
+ sanitize.Properties.SanitizeMutated.Fuzzer = bPtr
default:
panic(fmt.Errorf("unknown SanitizerType %d", t))
}
@@ -1065,7 +1163,7 @@
//TODO: When Rust modules have vendor support, enable this path for PlatformSanitizeable
// Check if it's a snapshot module supporting sanitizer
- if ss, ok := c.linker.(snapshotSanitizer); ok && ss.isSanitizerEnabled(s.sanitizer) {
+ if ss, ok := c.linker.(snapshotSanitizer); ok && ss.isSanitizerAvailable(s.sanitizer) {
return []string{"", s.sanitizer.variationName()}
} else {
return []string{""}
@@ -1097,7 +1195,7 @@
func (s *sanitizerSplitMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
if d, ok := ctx.Module().(PlatformSanitizeable); ok {
if dm, ok := ctx.Module().(*Module); ok {
- if ss, ok := dm.linker.(snapshotSanitizer); ok && ss.isSanitizerEnabled(s.sanitizer) {
+ if ss, ok := dm.linker.(snapshotSanitizer); ok && ss.isSanitizerAvailable(s.sanitizer) {
return incomingVariation
}
}
@@ -1127,7 +1225,8 @@
return s.sanitizer.variationName()
}
- if s.sanitizer == cfi || s.sanitizer == Hwasan || s.sanitizer == scs || s.sanitizer == Asan {
+ // Some sanitizers do not propagate to shared dependencies
+ if !s.sanitizer.shouldPropagateToSharedLibraryDeps() {
return ""
}
}
@@ -1212,14 +1311,23 @@
sanitizeable.AddSanitizerDependencies(mctx, s.sanitizer.name())
}
} else if c, ok := mctx.Module().(*Module); ok {
- if ss, ok := c.linker.(snapshotSanitizer); ok && ss.isSanitizerEnabled(s.sanitizer) {
+ if ss, ok := c.linker.(snapshotSanitizer); ok && ss.isSanitizerAvailable(s.sanitizer) {
+ if !ss.isUnsanitizedVariant() {
+ // Snapshot sanitizer may have only one variantion.
+ // Skip exporting the module if it already has a sanitizer variation.
+ c.SetPreventInstall()
+ c.SetHideFromMake()
+ return
+ }
c.linker.(snapshotSanitizer).setSanitizerVariation(s.sanitizer, sanitizerVariation)
// Export the static lib name to make
if c.static() && c.ExportedToMake() {
+ // use BaseModuleName which is the name for Make.
if s.sanitizer == cfi {
- // use BaseModuleName which is the name for Make.
cfiStaticLibs(mctx.Config()).add(c, c.BaseModuleName())
+ } else if s.sanitizer == Hwasan {
+ hwasanStaticLibs(mctx.Config()).add(c, c.BaseModuleName())
}
}
}
@@ -1227,7 +1335,7 @@
}
func (c *Module) SanitizeNever() bool {
- return Bool(c.sanitize.Properties.Sanitize.Never)
+ return Bool(c.sanitize.Properties.SanitizeMutated.Never)
}
func (c *Module) IsSanitizerExplicitlyDisabled(t SanitizerType) bool {
@@ -1295,10 +1403,12 @@
var sanitizers []string
var diagSanitizers []string
- if Bool(c.sanitize.Properties.Sanitize.All_undefined) {
+ sanProps := &c.sanitize.Properties.SanitizeMutated
+
+ if Bool(sanProps.All_undefined) {
sanitizers = append(sanitizers, "undefined")
} else {
- if Bool(c.sanitize.Properties.Sanitize.Undefined) {
+ if Bool(sanProps.Undefined) {
sanitizers = append(sanitizers,
"bool",
"integer-divide-by-zero",
@@ -1323,66 +1433,66 @@
// "object-size",
)
}
- sanitizers = append(sanitizers, c.sanitize.Properties.Sanitize.Misc_undefined...)
+ sanitizers = append(sanitizers, sanProps.Misc_undefined...)
}
- if Bool(c.sanitize.Properties.Sanitize.Diag.Undefined) {
+ if Bool(sanProps.Diag.Undefined) {
diagSanitizers = append(diagSanitizers, "undefined")
}
- diagSanitizers = append(diagSanitizers, c.sanitize.Properties.Sanitize.Diag.Misc_undefined...)
+ diagSanitizers = append(diagSanitizers, sanProps.Diag.Misc_undefined...)
- if Bool(c.sanitize.Properties.Sanitize.Address) {
+ if Bool(sanProps.Address) {
sanitizers = append(sanitizers, "address")
diagSanitizers = append(diagSanitizers, "address")
}
- if Bool(c.sanitize.Properties.Sanitize.Hwaddress) {
+ if Bool(sanProps.Hwaddress) {
sanitizers = append(sanitizers, "hwaddress")
}
- if Bool(c.sanitize.Properties.Sanitize.Thread) {
+ if Bool(sanProps.Thread) {
sanitizers = append(sanitizers, "thread")
}
- if Bool(c.sanitize.Properties.Sanitize.Safestack) {
+ if Bool(sanProps.Safestack) {
sanitizers = append(sanitizers, "safe-stack")
}
- if Bool(c.sanitize.Properties.Sanitize.Cfi) {
+ if Bool(sanProps.Cfi) {
sanitizers = append(sanitizers, "cfi")
- if Bool(c.sanitize.Properties.Sanitize.Diag.Cfi) {
+ if Bool(sanProps.Diag.Cfi) {
diagSanitizers = append(diagSanitizers, "cfi")
}
}
- if Bool(c.sanitize.Properties.Sanitize.Integer_overflow) {
+ if Bool(sanProps.Integer_overflow) {
sanitizers = append(sanitizers, "unsigned-integer-overflow")
sanitizers = append(sanitizers, "signed-integer-overflow")
- if Bool(c.sanitize.Properties.Sanitize.Diag.Integer_overflow) {
+ if Bool(sanProps.Diag.Integer_overflow) {
diagSanitizers = append(diagSanitizers, "unsigned-integer-overflow")
diagSanitizers = append(diagSanitizers, "signed-integer-overflow")
}
}
- if Bool(c.sanitize.Properties.Sanitize.Scudo) {
+ if Bool(sanProps.Scudo) {
sanitizers = append(sanitizers, "scudo")
}
- if Bool(c.sanitize.Properties.Sanitize.Scs) {
+ if Bool(sanProps.Scs) {
sanitizers = append(sanitizers, "shadow-call-stack")
}
- if Bool(c.sanitize.Properties.Sanitize.Memtag_heap) && c.Binary() {
+ if Bool(sanProps.Memtag_heap) && c.Binary() {
sanitizers = append(sanitizers, "memtag-heap")
}
- if Bool(c.sanitize.Properties.Sanitize.Memtag_stack) {
+ if Bool(sanProps.Memtag_stack) {
sanitizers = append(sanitizers, "memtag-stack")
}
- if Bool(c.sanitize.Properties.Sanitize.Fuzzer) {
+ if Bool(sanProps.Fuzzer) {
sanitizers = append(sanitizers, "fuzzer-no-link")
}
@@ -1401,27 +1511,27 @@
alwaysStaticRuntime := false
var extraStaticDeps []string
toolchain := c.toolchain(mctx)
- if Bool(c.sanitize.Properties.Sanitize.Address) {
+ if Bool(sanProps.Address) {
runtimeLibrary = config.AddressSanitizerRuntimeLibrary(toolchain)
- } else if Bool(c.sanitize.Properties.Sanitize.Hwaddress) {
+ } else if Bool(sanProps.Hwaddress) {
if c.staticBinary() {
runtimeLibrary = config.HWAddressSanitizerStaticLibrary(toolchain)
extraStaticDeps = []string{"libdl"}
} else {
runtimeLibrary = config.HWAddressSanitizerRuntimeLibrary(toolchain)
}
- } else if Bool(c.sanitize.Properties.Sanitize.Thread) {
+ } else if Bool(sanProps.Thread) {
runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(toolchain)
- } else if Bool(c.sanitize.Properties.Sanitize.Scudo) {
+ } else if Bool(sanProps.Scudo) {
if len(diagSanitizers) == 0 && !c.sanitize.Properties.UbsanRuntimeDep {
runtimeLibrary = config.ScudoMinimalRuntimeLibrary(toolchain)
} else {
runtimeLibrary = config.ScudoRuntimeLibrary(toolchain)
}
} else if len(diagSanitizers) > 0 || c.sanitize.Properties.UbsanRuntimeDep ||
- Bool(c.sanitize.Properties.Sanitize.Fuzzer) ||
- Bool(c.sanitize.Properties.Sanitize.Undefined) ||
- Bool(c.sanitize.Properties.Sanitize.All_undefined) {
+ Bool(sanProps.Fuzzer) ||
+ Bool(sanProps.Undefined) ||
+ Bool(sanProps.All_undefined) {
runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)
if c.staticBinary() || toolchain.Musl() {
// Use a static runtime for static binaries.
@@ -1632,21 +1742,27 @@
}
func enableMinimalRuntime(sanitize *sanitize) bool {
- if !Bool(sanitize.Properties.Sanitize.Address) &&
- !Bool(sanitize.Properties.Sanitize.Hwaddress) &&
- !Bool(sanitize.Properties.Sanitize.Fuzzer) &&
- (Bool(sanitize.Properties.Sanitize.Integer_overflow) ||
- len(sanitize.Properties.Sanitize.Misc_undefined) > 0 ||
- Bool(sanitize.Properties.Sanitize.Undefined) ||
- Bool(sanitize.Properties.Sanitize.All_undefined)) &&
- !(Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
- Bool(sanitize.Properties.Sanitize.Diag.Cfi) ||
- Bool(sanitize.Properties.Sanitize.Diag.Undefined) ||
- len(sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0) {
-
- return true
+ if sanitize.isSanitizerEnabled(Asan) {
+ return false
+ } else if sanitize.isSanitizerEnabled(Hwasan) {
+ return false
+ } else if sanitize.isSanitizerEnabled(Fuzzer) {
+ return false
}
- return false
+
+ if enableUbsanRuntime(sanitize) {
+ return false
+ }
+
+ sanitizeProps := &sanitize.Properties.SanitizeMutated
+ if Bool(sanitizeProps.Diag.Cfi) {
+ return false
+ }
+
+ return Bool(sanitizeProps.Integer_overflow) ||
+ len(sanitizeProps.Misc_undefined) > 0 ||
+ Bool(sanitizeProps.Undefined) ||
+ Bool(sanitizeProps.All_undefined)
}
func (m *Module) UbsanRuntimeNeeded() bool {
@@ -1658,9 +1774,10 @@
}
func enableUbsanRuntime(sanitize *sanitize) bool {
- return Bool(sanitize.Properties.Sanitize.Diag.Integer_overflow) ||
- Bool(sanitize.Properties.Sanitize.Diag.Undefined) ||
- len(sanitize.Properties.Sanitize.Diag.Misc_undefined) > 0
+ sanitizeProps := &sanitize.Properties.SanitizeMutated
+ return Bool(sanitizeProps.Diag.Integer_overflow) ||
+ Bool(sanitizeProps.Diag.Undefined) ||
+ len(sanitizeProps.Diag.Misc_undefined) > 0
}
func cfiMakeVarsProvider(ctx android.MakeVarsContext) {
diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go
index 2393f3e..580adfa 100644
--- a/cc/sanitize_test.go
+++ b/cc/sanitize_test.go
@@ -21,6 +21,8 @@
"testing"
"android/soong/android"
+
+ "github.com/google/blueprint"
)
var prepareForAsanTest = android.FixtureAddFile("asan/Android.bp", []byte(`
@@ -29,6 +31,60 @@
}
`))
+var prepareForTsanTest = android.FixtureAddFile("tsan/Android.bp", []byte(`
+ cc_library_shared {
+ name: "libclang_rt.tsan",
+ }
+`))
+
+type providerInterface interface {
+ ModuleProvider(blueprint.Module, blueprint.ProviderKey) interface{}
+}
+
+// expectSharedLinkDep verifies that the from module links against the to module as a
+// shared library.
+func expectSharedLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
+ t.Helper()
+ fromLink := from.Description("link")
+ toInfo := ctx.ModuleProvider(to.Module(), SharedLibraryInfoProvider).(SharedLibraryInfo)
+
+ if g, w := fromLink.OrderOnly.Strings(), toInfo.SharedLibrary.RelativeToTop().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.
+func expectStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
+ t.Helper()
+ fromLink := from.Description("link")
+ toInfo := ctx.ModuleProvider(to.Module(), StaticLibraryInfoProvider).(StaticLibraryInfo)
+
+ if g, w := fromLink.Implicits.Strings(), toInfo.StaticLibrary.RelativeToTop().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.
+func expectInstallDep(t *testing.T, 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)
+ }
+}
+
func TestAsan(t *testing.T) {
bp := `
cc_binary {
@@ -111,6 +167,7 @@
).RunTestWithBp(t, bp)
check := func(t *testing.T, result *android.TestResult, variant string) {
+ ctx := result.TestContext
asanVariant := variant + "_asan"
sharedVariant := variant + "_shared"
sharedAsanVariant := sharedVariant + "_asan"
@@ -140,85 +197,355 @@
libStaticAsan := result.ModuleForTests("libstatic_asan", staticAsanVariant)
libStaticAsanNoAsanVariant := result.ModuleForTests("libstatic_asan", 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")
+ expectSharedLinkDep(t, ctx, binWithAsan, libShared)
+ expectSharedLinkDep(t, ctx, binWithAsan, libAsan)
+ expectSharedLinkDep(t, ctx, libShared, libTransitive)
+ expectSharedLinkDep(t, ctx, libAsan, libTransitive)
- 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(t, ctx, binWithAsan, libStaticAsanVariant)
+ expectStaticLinkDep(t, ctx, binWithAsan, libNoAsan)
+ expectStaticLinkDep(t, ctx, binWithAsan, libStaticAsan)
- // 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")
+ expectInstallDep(t, binWithAsan, libShared)
+ expectInstallDep(t, binWithAsan, libAsan)
+ expectInstallDep(t, binWithAsan, libTransitive)
+ expectInstallDep(t, libShared, libTransitive)
+ expectInstallDep(t, libAsan, libTransitive)
- 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)
- }
+ expectSharedLinkDep(t, ctx, binNoAsan, libShared)
+ expectSharedLinkDep(t, ctx, binNoAsan, libAsan)
+ expectSharedLinkDep(t, ctx, libShared, libTransitive)
+ expectSharedLinkDep(t, ctx, libAsan, libTransitive)
- }
+ expectStaticLinkDep(t, ctx, binNoAsan, libStaticNoAsanVariant)
+ expectStaticLinkDep(t, ctx, binNoAsan, libNoAsan)
+ expectStaticLinkDep(t, ctx, binNoAsan, libStaticAsanNoAsanVariant)
- // 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)
- expectStaticLinkDep(binWithAsan, libStaticAsan)
-
- 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)
- expectStaticLinkDep(binNoAsan, libStaticAsanNoAsanVariant)
-
- expectInstallDep(binNoAsan, libShared)
- expectInstallDep(binNoAsan, libAsan)
- expectInstallDep(binNoAsan, libTransitive)
- expectInstallDep(libShared, libTransitive)
- expectInstallDep(libAsan, libTransitive)
+ expectInstallDep(t, binNoAsan, libShared)
+ expectInstallDep(t, binNoAsan, libAsan)
+ expectInstallDep(t, binNoAsan, libTransitive)
+ expectInstallDep(t, libShared, libTransitive)
+ expectInstallDep(t, 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") })
}
+func TestTsan(t *testing.T) {
+ bp := `
+ cc_binary {
+ name: "bin_with_tsan",
+ host_supported: true,
+ shared_libs: [
+ "libshared",
+ "libtsan",
+ ],
+ sanitize: {
+ thread: true,
+ }
+ }
+
+ cc_binary {
+ name: "bin_no_tsan",
+ host_supported: true,
+ shared_libs: [
+ "libshared",
+ "libtsan",
+ ],
+ }
+
+ cc_library_shared {
+ name: "libshared",
+ host_supported: true,
+ shared_libs: ["libtransitive"],
+ }
+
+ cc_library_shared {
+ name: "libtsan",
+ host_supported: true,
+ shared_libs: ["libtransitive"],
+ sanitize: {
+ thread: true,
+ }
+ }
+
+ cc_library_shared {
+ name: "libtransitive",
+ host_supported: true,
+ }
+`
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ prepareForTsanTest,
+ ).RunTestWithBp(t, bp)
+
+ check := func(t *testing.T, result *android.TestResult, variant string) {
+ ctx := result.TestContext
+ tsanVariant := variant + "_tsan"
+ sharedVariant := variant + "_shared"
+ sharedTsanVariant := sharedVariant + "_tsan"
+
+ // The binaries, one with tsan and one without
+ binWithTsan := result.ModuleForTests("bin_with_tsan", tsanVariant)
+ binNoTsan := result.ModuleForTests("bin_no_tsan", variant)
+
+ // Shared libraries that don't request tsan
+ libShared := result.ModuleForTests("libshared", sharedVariant)
+ libTransitive := result.ModuleForTests("libtransitive", sharedVariant)
+
+ // Shared library that requests tsan
+ libTsan := result.ModuleForTests("libtsan", sharedTsanVariant)
+
+ expectSharedLinkDep(t, ctx, binWithTsan, libShared)
+ expectSharedLinkDep(t, ctx, binWithTsan, libTsan)
+ expectSharedLinkDep(t, ctx, libShared, libTransitive)
+ expectSharedLinkDep(t, ctx, libTsan, libTransitive)
+
+ expectSharedLinkDep(t, ctx, binNoTsan, libShared)
+ expectSharedLinkDep(t, ctx, binNoTsan, libTsan)
+ expectSharedLinkDep(t, ctx, libShared, libTransitive)
+ expectSharedLinkDep(t, ctx, libTsan, 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") })
+}
+
+func TestMiscUndefined(t *testing.T) {
+ bp := `
+ cc_binary {
+ name: "bin_with_ubsan",
+ srcs: ["src.cc"],
+ host_supported: true,
+ static_libs: [
+ "libstatic",
+ "libubsan",
+ ],
+ sanitize: {
+ misc_undefined: ["integer"],
+ }
+ }
+
+ cc_binary {
+ name: "bin_no_ubsan",
+ host_supported: true,
+ srcs: ["src.cc"],
+ static_libs: [
+ "libstatic",
+ "libubsan",
+ ],
+ }
+
+ cc_library_static {
+ name: "libstatic",
+ host_supported: true,
+ srcs: ["src.cc"],
+ static_libs: ["libtransitive"],
+ }
+
+ cc_library_static {
+ name: "libubsan",
+ host_supported: true,
+ srcs: ["src.cc"],
+ whole_static_libs: ["libtransitive"],
+ sanitize: {
+ misc_undefined: ["integer"],
+ }
+ }
+
+ cc_library_static {
+ name: "libtransitive",
+ host_supported: true,
+ srcs: ["src.cc"],
+ }
+`
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ ).RunTestWithBp(t, bp)
+
+ check := func(t *testing.T, result *android.TestResult, variant string) {
+ ctx := result.TestContext
+ staticVariant := variant + "_static"
+
+ // The binaries, one with ubsan and one without
+ binWithUbsan := result.ModuleForTests("bin_with_ubsan", variant)
+ binNoUbsan := result.ModuleForTests("bin_no_ubsan", variant)
+
+ // Static libraries that don't request ubsan
+ libStatic := result.ModuleForTests("libstatic", staticVariant)
+ libTransitive := result.ModuleForTests("libtransitive", staticVariant)
+
+ libUbsan := result.ModuleForTests("libubsan", staticVariant)
+
+ libUbsanMinimal := result.ModuleForTests("libclang_rt.ubsan_minimal", staticVariant)
+
+ expectStaticLinkDep(t, ctx, binWithUbsan, libStatic)
+ expectStaticLinkDep(t, ctx, binWithUbsan, libUbsan)
+ expectStaticLinkDep(t, ctx, binWithUbsan, libUbsanMinimal)
+
+ miscUndefinedSanFlag := "-fsanitize=integer"
+ binWithUbsanCflags := binWithUbsan.Rule("cc").Args["cFlags"]
+ if !strings.Contains(binWithUbsanCflags, miscUndefinedSanFlag) {
+ t.Errorf("'bin_with_ubsan' Expected %q to be in flags %q, was not", miscUndefinedSanFlag, binWithUbsanCflags)
+ }
+ libStaticCflags := libStatic.Rule("cc").Args["cFlags"]
+ if strings.Contains(libStaticCflags, miscUndefinedSanFlag) {
+ t.Errorf("'libstatic' Expected %q to NOT be in flags %q, was", miscUndefinedSanFlag, binWithUbsanCflags)
+ }
+ libUbsanCflags := libUbsan.Rule("cc").Args["cFlags"]
+ if !strings.Contains(libUbsanCflags, miscUndefinedSanFlag) {
+ t.Errorf("'libubsan' Expected %q to be in flags %q, was not", miscUndefinedSanFlag, binWithUbsanCflags)
+ }
+ libTransitiveCflags := libTransitive.Rule("cc").Args["cFlags"]
+ if strings.Contains(libTransitiveCflags, miscUndefinedSanFlag) {
+ t.Errorf("'libtransitive': Expected %q to NOT be in flags %q, was", miscUndefinedSanFlag, binWithUbsanCflags)
+ }
+
+ expectStaticLinkDep(t, ctx, binNoUbsan, libStatic)
+ expectStaticLinkDep(t, ctx, binNoUbsan, libUbsan)
+ }
+
+ 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") })
+}
+
+func TestFuzz(t *testing.T) {
+ bp := `
+ cc_binary {
+ name: "bin_with_fuzzer",
+ host_supported: true,
+ shared_libs: [
+ "libshared",
+ "libfuzzer",
+ ],
+ static_libs: [
+ "libstatic",
+ "libnofuzzer",
+ "libstatic_fuzzer",
+ ],
+ sanitize: {
+ fuzzer: true,
+ }
+ }
+
+ cc_binary {
+ name: "bin_no_fuzzer",
+ host_supported: true,
+ shared_libs: [
+ "libshared",
+ "libfuzzer",
+ ],
+ static_libs: [
+ "libstatic",
+ "libnofuzzer",
+ "libstatic_fuzzer",
+ ],
+ }
+
+ cc_library_shared {
+ name: "libshared",
+ host_supported: true,
+ shared_libs: ["libtransitive"],
+ }
+
+ cc_library_shared {
+ name: "libfuzzer",
+ host_supported: true,
+ shared_libs: ["libtransitive"],
+ sanitize: {
+ fuzzer: true,
+ }
+ }
+
+ cc_library_shared {
+ name: "libtransitive",
+ host_supported: true,
+ }
+
+ cc_library_static {
+ name: "libstatic",
+ host_supported: true,
+ }
+
+ cc_library_static {
+ name: "libnofuzzer",
+ host_supported: true,
+ sanitize: {
+ fuzzer: false,
+ }
+ }
+
+ cc_library_static {
+ name: "libstatic_fuzzer",
+ host_supported: true,
+ }
+
+ `
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ ).RunTestWithBp(t, bp)
+
+ check := func(t *testing.T, result *android.TestResult, variant string) {
+ ctx := result.TestContext
+ fuzzerVariant := variant + "_fuzzer"
+ sharedVariant := variant + "_shared"
+ sharedFuzzerVariant := sharedVariant + "_fuzzer"
+ staticVariant := variant + "_static"
+ staticFuzzerVariant := staticVariant + "_fuzzer"
+
+ // The binaries, one with fuzzer and one without
+ binWithFuzzer := result.ModuleForTests("bin_with_fuzzer", fuzzerVariant)
+ binNoFuzzer := result.ModuleForTests("bin_no_fuzzer", variant)
+
+ // Shared libraries that don't request fuzzer
+ libShared := result.ModuleForTests("libshared", sharedVariant)
+ libTransitive := result.ModuleForTests("libtransitive", sharedVariant)
+
+ // Shared libraries that don't request fuzzer
+ libSharedFuzzer := result.ModuleForTests("libshared", sharedFuzzerVariant)
+ libTransitiveFuzzer := result.ModuleForTests("libtransitive", sharedFuzzerVariant)
+
+ // Shared library that requests fuzzer
+ libFuzzer := result.ModuleForTests("libfuzzer", sharedFuzzerVariant)
+
+ // Static library that uses an fuzzer variant for bin_with_fuzzer and a non-fuzzer variant
+ // for bin_no_fuzzer.
+ libStaticFuzzerVariant := result.ModuleForTests("libstatic", staticFuzzerVariant)
+ libStaticNoFuzzerVariant := result.ModuleForTests("libstatic", staticVariant)
+
+ // Static library that never uses fuzzer.
+ libNoFuzzer := result.ModuleForTests("libnofuzzer", staticVariant)
+
+ // Static library that specifies fuzzer
+ libStaticFuzzer := result.ModuleForTests("libstatic_fuzzer", staticFuzzerVariant)
+ libStaticFuzzerNoFuzzerVariant := result.ModuleForTests("libstatic_fuzzer", staticVariant)
+
+ expectSharedLinkDep(t, ctx, binWithFuzzer, libSharedFuzzer)
+ expectSharedLinkDep(t, ctx, binWithFuzzer, libFuzzer)
+ expectSharedLinkDep(t, ctx, libSharedFuzzer, libTransitiveFuzzer)
+ expectSharedLinkDep(t, ctx, libFuzzer, libTransitiveFuzzer)
+
+ expectStaticLinkDep(t, ctx, binWithFuzzer, libStaticFuzzerVariant)
+ expectStaticLinkDep(t, ctx, binWithFuzzer, libNoFuzzer)
+ expectStaticLinkDep(t, ctx, binWithFuzzer, libStaticFuzzer)
+
+ expectSharedLinkDep(t, ctx, binNoFuzzer, libShared)
+ expectSharedLinkDep(t, ctx, binNoFuzzer, libFuzzer)
+ expectSharedLinkDep(t, ctx, libShared, libTransitive)
+ expectSharedLinkDep(t, ctx, libFuzzer, libTransitiveFuzzer)
+
+ expectStaticLinkDep(t, ctx, binNoFuzzer, libStaticNoFuzzerVariant)
+ expectStaticLinkDep(t, ctx, binNoFuzzer, libNoFuzzer)
+ expectStaticLinkDep(t, ctx, binNoFuzzer, libStaticFuzzerNoFuzzerVariant)
+ }
+
+ t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") })
+}
+
func TestUbsan(t *testing.T) {
if runtime.GOOS != "linux" {
t.Skip("requires linux")
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index 792ffe3..570300b 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -18,6 +18,7 @@
// snapshot mutators and snapshot information maps which are also defined in this file.
import (
+ "fmt"
"strings"
"android/soong/android"
@@ -399,8 +400,10 @@
}
type snapshotSanitizer interface {
- isSanitizerEnabled(t SanitizerType) bool
+ isSanitizerAvailable(t SanitizerType) bool
setSanitizerVariation(t SanitizerType, enabled bool)
+ isSanitizerEnabled(t SanitizerType) bool
+ isUnsanitizedVariant() bool
}
type snapshotLibraryDecorator struct {
@@ -408,10 +411,13 @@
*libraryDecorator
properties SnapshotLibraryProperties
sanitizerProperties struct {
- CfiEnabled bool `blueprint:"mutated"`
+ SanitizerVariation SanitizerType `blueprint:"mutated"`
// Library flags for cfi variant.
Cfi SnapshotLibraryProperties `android:"arch_variant"`
+
+ // Library flags for hwasan variant.
+ Hwasan SnapshotLibraryProperties `android:"arch_variant"`
}
}
@@ -450,8 +456,10 @@
return p.libraryDecorator.link(ctx, flags, deps, objs)
}
- if p.sanitizerProperties.CfiEnabled {
+ if p.isSanitizerEnabled(cfi) {
p.properties = p.sanitizerProperties.Cfi
+ } else if p.isSanitizerEnabled(Hwasan) {
+ p.properties = p.sanitizerProperties.Hwasan
}
if !p.MatchesWithDevice(ctx.DeviceConfig()) {
@@ -514,25 +522,34 @@
return false
}
-func (p *snapshotLibraryDecorator) isSanitizerEnabled(t SanitizerType) bool {
+func (p *snapshotLibraryDecorator) isSanitizerAvailable(t SanitizerType) bool {
switch t {
case cfi:
return p.sanitizerProperties.Cfi.Src != nil
+ case Hwasan:
+ return p.sanitizerProperties.Hwasan.Src != nil
default:
return false
}
}
func (p *snapshotLibraryDecorator) setSanitizerVariation(t SanitizerType, enabled bool) {
- if !enabled {
+ if !enabled || p.isSanitizerEnabled(t) {
return
}
- switch t {
- case cfi:
- p.sanitizerProperties.CfiEnabled = true
- default:
- return
+ if !p.isUnsanitizedVariant() {
+ panic(fmt.Errorf("snapshot Sanitizer must be one of Cfi or Hwasan but not both"))
}
+ p.sanitizerProperties.SanitizerVariation = t
+}
+
+func (p *snapshotLibraryDecorator) isSanitizerEnabled(t SanitizerType) bool {
+ return p.sanitizerProperties.SanitizerVariation == t
+}
+
+func (p *snapshotLibraryDecorator) isUnsanitizedVariant() bool {
+ return !p.isSanitizerEnabled(Asan) &&
+ !p.isSanitizerEnabled(Hwasan)
}
func snapshotLibraryFactory(image SnapshotImage, moduleSuffix string) (*Module, *snapshotLibraryDecorator) {
diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go
index 6a98778..79405e9 100644
--- a/cc/vendor_snapshot_test.go
+++ b/cc/vendor_snapshot_test.go
@@ -1053,6 +1053,7 @@
},
},
}
+
vendor_snapshot_static {
name: "libsnapshot",
vendor: true,
@@ -1063,7 +1064,10 @@
src: "libsnapshot.a",
cfi: {
src: "libsnapshot.cfi.a",
- }
+ },
+ hwasan: {
+ src: "libsnapshot.hwasan.a",
+ },
},
},
}
@@ -1098,6 +1102,7 @@
"vendor/libc++demangle.a": nil,
"vendor/libsnapshot.a": nil,
"vendor/libsnapshot.cfi.a": nil,
+ "vendor/libsnapshot.hwasan.a": nil,
"vendor/note_memtag_heap_sync.a": nil,
}
@@ -1106,15 +1111,25 @@
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
ctx := testCcWithConfig(t, config)
- // Check non-cfi and cfi variant.
+ // Check non-cfi, cfi and hwasan variant.
staticVariant := "android_vendor.28_arm64_armv8-a_static"
staticCfiVariant := "android_vendor.28_arm64_armv8-a_static_cfi"
+ staticHwasanVariant := "android_vendor.28_arm64_armv8-a_static_hwasan"
+ staticHwasanCfiVariant := "android_vendor.28_arm64_armv8-a_static_hwasan_cfi"
staticModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticVariant).Module().(*Module)
assertString(t, staticModule.outputFile.Path().Base(), "libsnapshot.a")
staticCfiModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticCfiVariant).Module().(*Module)
assertString(t, staticCfiModule.outputFile.Path().Base(), "libsnapshot.cfi.a")
+
+ staticHwasanModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticHwasanVariant).Module().(*Module)
+ assertString(t, staticHwasanModule.outputFile.Path().Base(), "libsnapshot.hwasan.a")
+
+ staticHwasanCfiModule := ctx.ModuleForTests("libsnapshot.vendor_static.28.arm64", staticHwasanCfiVariant).Module().(*Module)
+ if !staticHwasanCfiModule.HiddenFromMake() || !staticHwasanCfiModule.PreventInstall() {
+ t.Errorf("Hwasan and Cfi cannot enabled at the same time.")
+ }
}
func TestVendorSnapshotExclude(t *testing.T) {
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 3bc311b..029bbb4 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -629,40 +629,41 @@
// symlink tree creation binary. Then the latter would not need to depend on
// the very heavy-weight machinery of soong_build .
func runSymlinkForestCreation(configuration android.Config, ctx *android.Context, extraNinjaDeps []string, metricsDir string) string {
- var ninjaDeps []string
- ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
-
- generatedRoot := shared.JoinPath(configuration.SoongOutDir(), "bp2build")
- workspaceRoot := shared.JoinPath(configuration.SoongOutDir(), "workspace")
-
- excludes := bazelArtifacts()
-
- if outDir[0] != '/' {
- excludes = append(excludes, outDir)
- }
-
- existingBazelRelatedFiles, err := getExistingBazelRelatedFiles(topDir)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error determining existing Bazel-related files: %s\n", err)
- os.Exit(1)
- }
-
- pathsToIgnoredBuildFiles := getPathsToIgnoredBuildFiles(configuration.Bp2buildPackageConfig, topDir, existingBazelRelatedFiles, configuration.IsEnvTrue("BP2BUILD_VERBOSE"))
- excludes = append(excludes, pathsToIgnoredBuildFiles...)
- excludes = append(excludes, getTemporaryExcludes()...)
-
- // PlantSymlinkForest() returns all the directories that were readdir()'ed.
- // Such a directory SHOULD be added to `ninjaDeps` so that a child directory
- // or file created/deleted under it would trigger an update of the symlink
- // forest.
ctx.EventHandler.Do("symlink_forest", func() {
- symlinkForestDeps := bp2build.PlantSymlinkForest(
- configuration.IsEnvTrue("BP2BUILD_VERBOSE"), topDir, workspaceRoot, generatedRoot, excludes)
- ninjaDeps = append(ninjaDeps, symlinkForestDeps...)
- })
+ var ninjaDeps []string
+ ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
- writeDepFile(symlinkForestMarker, ctx.EventHandler, ninjaDeps)
- touch(shared.JoinPath(topDir, symlinkForestMarker))
+ generatedRoot := shared.JoinPath(configuration.SoongOutDir(), "bp2build")
+ workspaceRoot := shared.JoinPath(configuration.SoongOutDir(), "workspace")
+
+ excludes := bazelArtifacts()
+
+ if outDir[0] != '/' {
+ excludes = append(excludes, outDir)
+ }
+
+ existingBazelRelatedFiles, err := getExistingBazelRelatedFiles(topDir)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error determining existing Bazel-related files: %s\n", err)
+ os.Exit(1)
+ }
+
+ pathsToIgnoredBuildFiles := getPathsToIgnoredBuildFiles(configuration.Bp2buildPackageConfig, topDir, existingBazelRelatedFiles, configuration.IsEnvTrue("BP2BUILD_VERBOSE"))
+ excludes = append(excludes, pathsToIgnoredBuildFiles...)
+ excludes = append(excludes, getTemporaryExcludes()...)
+
+ // PlantSymlinkForest() returns all the directories that were readdir()'ed.
+ // Such a directory SHOULD be added to `ninjaDeps` so that a child directory
+ // or file created/deleted under it would trigger an update of the symlink forest.
+ ctx.EventHandler.Do("plant", func() {
+ symlinkForestDeps := bp2build.PlantSymlinkForest(
+ configuration.IsEnvTrue("BP2BUILD_VERBOSE"), topDir, workspaceRoot, generatedRoot, excludes)
+ ninjaDeps = append(ninjaDeps, symlinkForestDeps...)
+ })
+
+ writeDepFile(symlinkForestMarker, ctx.EventHandler, ninjaDeps)
+ touch(shared.JoinPath(topDir, symlinkForestMarker))
+ })
codegenMetrics := bp2build.ReadCodegenMetrics(metricsDir)
if codegenMetrics == nil {
m := bp2build.CreateCodegenMetrics()