Merge "Allow android tests to specify a mainline package name"
diff --git a/android/bazel.go b/android/bazel.go
index 10e9251..52f50c5 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -526,3 +526,15 @@
return "", errors.New("Main-Class is not found.")
}
+
+func AttachValidationActions(ctx ModuleContext, outputFilePath Path, validations Paths) ModuleOutPath {
+ validatedOutputFilePath := PathForModuleOut(ctx, "validated", outputFilePath.Base())
+ ctx.Build(pctx, BuildParams{
+ Rule: CpNoPreserveSymlink,
+ Description: "run validations " + outputFilePath.Base(),
+ Output: validatedOutputFilePath,
+ Input: outputFilePath,
+ Validations: validations,
+ })
+ return validatedOutputFilePath
+}
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index ac4ced8..9ff6b52 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -29,6 +29,7 @@
"android/soong/android/allowlists"
"android/soong/bazel/cquery"
"android/soong/shared"
+ "android/soong/starlark_fmt"
"github.com/google/blueprint"
@@ -43,6 +44,27 @@
Description: "",
CommandDeps: []string{"${bazelBuildRunfilesTool}"},
}, "outDir")
+ allowedBazelEnvironmentVars = []string{
+ "ALLOW_LOCAL_TIDY_TRUE",
+ "DEFAULT_TIDY_HEADER_DIRS",
+ "TIDY_TIMEOUT",
+ "WITH_TIDY",
+ "WITH_TIDY_FLAGS",
+ "SKIP_ABI_CHECKS",
+ "UNSAFE_DISABLE_APEX_ALLOWED_DEPS_CHECK",
+ "AUTO_ZERO_INITIALIZE",
+ "AUTO_PATTERN_INITIALIZE",
+ "AUTO_UNINITIALIZE",
+ "USE_CCACHE",
+ "LLVM_NEXT",
+ "ALLOW_UNKNOWN_WARNING_OPTION",
+
+ // Overrides the version in the apex_manifest.json. The version is unique for
+ // each branch (internal, aosp, mainline releases, dessert releases). This
+ // enables modules built on an older branch to be installed against a newer
+ // device for development purposes.
+ "OVERRIDE_APEX_MANIFEST_DEFAULT_VERSION",
+ }
)
func init() {
@@ -165,7 +187,7 @@
}
type bazelRunner interface {
- createBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand, extraFlags ...string) *exec.Cmd
+ createBazelCommand(config Config, paths *bazelPaths, runName bazel.RunName, command bazelCommand, extraFlags ...string) *exec.Cmd
issueBazelCommand(bazelCmd *exec.Cmd) (output string, errorMessage string, error error)
}
@@ -183,9 +205,11 @@
// and their results after the requests have been made.
type mixedBuildBazelContext struct {
bazelRunner
- paths *bazelPaths
- requests map[cqueryKey]bool // cquery requests that have not yet been issued to Bazel
- requestMutex sync.Mutex // requests can be written in parallel
+ paths *bazelPaths
+ // cquery requests that have not yet been issued to Bazel. This list is maintained
+ // in a sorted state, and is guaranteed to have no duplicates.
+ requests []cqueryKey
+ requestMutex sync.Mutex // requests can be written in parallel
results map[cqueryKey]string // Results of cquery requests after Bazel invocations
@@ -296,7 +320,29 @@
key := makeCqueryKey(label, requestType, cfgKey)
bazelCtx.requestMutex.Lock()
defer bazelCtx.requestMutex.Unlock()
- bazelCtx.requests[key] = true
+
+ // Insert key into requests, maintaining the sort, and only if it's not duplicate.
+ keyString := key.String()
+ foundEqual := false
+ notLessThanKeyString := func(i int) bool {
+ s := bazelCtx.requests[i].String()
+ v := strings.Compare(s, keyString)
+ if v == 0 {
+ foundEqual = true
+ }
+ return v >= 0
+ }
+ targetIndex := sort.Search(len(bazelCtx.requests), notLessThanKeyString)
+ if foundEqual {
+ return
+ }
+
+ if targetIndex == len(bazelCtx.requests) {
+ bazelCtx.requests = append(bazelCtx.requests, key)
+ } else {
+ bazelCtx.requests = append(bazelCtx.requests[:targetIndex+1], bazelCtx.requests[targetIndex:]...)
+ bazelCtx.requests[targetIndex] = key
+ }
}
func (bazelCtx *mixedBuildBazelContext) GetOutputFiles(label string, cfgKey configKey) ([]string, error) {
@@ -487,7 +533,6 @@
return &mixedBuildBazelContext{
bazelRunner: &builtinBazelRunner{},
paths: &paths,
- requests: make(map[cqueryKey]bool),
modulesDefaultToBazel: c.BuildMode == BazelDevMode,
bazelEnabledModules: enabledModules,
bazelDisabledModules: disabledModules,
@@ -535,7 +580,7 @@
extraFlags []string
}
-func (r *mockBazelRunner) createBazelCommand(_ *bazelPaths, _ bazel.RunName,
+func (r *mockBazelRunner) createBazelCommand(_ Config, _ *bazelPaths, _ bazel.RunName,
command bazelCommand, extraFlags ...string) *exec.Cmd {
r.commands = append(r.commands, command)
r.extraFlags = append(r.extraFlags, strings.Join(extraFlags, " "))
@@ -572,7 +617,7 @@
}
}
-func (r *builtinBazelRunner) createBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand,
+func (r *builtinBazelRunner) createBazelCommand(config Config, paths *bazelPaths, runName bazel.RunName, command bazelCommand,
extraFlags ...string) *exec.Cmd {
cmdFlags := []string{
"--output_base=" + absolutePath(paths.outputBase),
@@ -616,6 +661,13 @@
// explicitly in BUILD files.
"BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1",
}
+ for _, envvar := range allowedBazelEnvironmentVars {
+ val := config.Getenv(envvar)
+ if val == "" {
+ continue
+ }
+ extraEnv = append(extraEnv, fmt.Sprintf("%s=%s", envvar, val))
+ }
bazelCmd.Env = append(os.Environ(), extraEnv...)
return bazelCmd
@@ -727,14 +779,23 @@
configNodesSection := ""
labelsByConfig := map[string][]string{}
- for val := range context.requests {
+
+ for _, val := range context.requests {
labelString := fmt.Sprintf("\"@%s\"", val.label)
configString := getConfigString(val)
labelsByConfig[configString] = append(labelsByConfig[configString], labelString)
}
+ // Configs need to be sorted to maintain determinism of the BUILD file.
+ sortedConfigs := make([]string, 0, len(labelsByConfig))
+ for val := range labelsByConfig {
+ sortedConfigs = append(sortedConfigs, val)
+ }
+ sort.Slice(sortedConfigs, func(i, j int) bool { return sortedConfigs[i] < sortedConfigs[j] })
+
allLabels := []string{}
- for configString, labels := range labelsByConfig {
+ for _, configString := range sortedConfigs {
+ labels := labelsByConfig[configString]
configTokens := strings.Split(configString, "|")
if len(configTokens) != 2 {
panic(fmt.Errorf("Unexpected config string format: %s", configString))
@@ -765,7 +826,7 @@
// request type.
func (context *mixedBuildBazelContext) cqueryStarlarkFileContents() []byte {
requestTypeToCqueryIdEntries := map[cqueryRequest][]string{}
- for val := range context.requests {
+ for _, val := range context.requests {
cqueryId := getCqueryId(val)
mapEntryString := fmt.Sprintf("%q : True", cqueryId)
requestTypeToCqueryIdEntries[val.requestType] =
@@ -933,22 +994,22 @@
}
}
context.results = make(map[cqueryKey]string)
- if err := context.runCquery(ctx); err != nil {
+ if err := context.runCquery(config, ctx); err != nil {
return err
}
if err := context.runAquery(config, ctx); err != nil {
return err
}
- if err := context.generateBazelSymlinks(ctx); err != nil {
+ if err := context.generateBazelSymlinks(config, ctx); err != nil {
return err
}
// Clear requests.
- context.requests = map[cqueryKey]bool{}
+ context.requests = []cqueryKey{}
return nil
}
-func (context *mixedBuildBazelContext) runCquery(ctx *Context) error {
+func (context *mixedBuildBazelContext) runCquery(config Config, ctx *Context) error {
if ctx != nil {
ctx.EventHandler.Begin("cquery")
defer ctx.EventHandler.End("cquery")
@@ -961,21 +1022,21 @@
return err
}
}
- if err := os.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil {
+ if err := writeFileBytesIfChanged(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil {
return err
}
- if err := os.WriteFile(filepath.Join(mixedBuildsPath, "main.bzl"), context.mainBzlFileContents(), 0666); err != nil {
+ if err := writeFileBytesIfChanged(filepath.Join(mixedBuildsPath, "main.bzl"), context.mainBzlFileContents(), 0666); err != nil {
return err
}
- if err := os.WriteFile(filepath.Join(mixedBuildsPath, "BUILD.bazel"), context.mainBuildFileContents(), 0666); err != nil {
+ if err := writeFileBytesIfChanged(filepath.Join(mixedBuildsPath, "BUILD.bazel"), context.mainBuildFileContents(), 0666); err != nil {
return err
}
cqueryFileRelpath := filepath.Join(context.paths.injectedFilesDir(), "buildroot.cquery")
- if err := os.WriteFile(absolutePath(cqueryFileRelpath), context.cqueryStarlarkFileContents(), 0666); err != nil {
+ if err := writeFileBytesIfChanged(absolutePath(cqueryFileRelpath), context.cqueryStarlarkFileContents(), 0666); err != nil {
return err
}
- cqueryCommandWithFlag := context.createBazelCommand(context.paths, bazel.CqueryBuildRootRunName, cqueryCmd,
+ cqueryCommandWithFlag := context.createBazelCommand(config, context.paths, bazel.CqueryBuildRootRunName, cqueryCmd,
"--output=starlark", "--starlark:file="+absolutePath(cqueryFileRelpath))
cqueryOutput, cqueryErrorMessage, cqueryErr := context.issueBazelCommand(cqueryCommandWithFlag)
if cqueryErr != nil {
@@ -992,7 +1053,7 @@
cqueryResults[splitLine[0]] = splitLine[1]
}
}
- for val := range context.requests {
+ for _, val := range context.requests {
if cqueryResult, ok := cqueryResults[getCqueryId(val)]; ok {
context.results[val] = cqueryResult
} else {
@@ -1003,6 +1064,14 @@
return nil
}
+func writeFileBytesIfChanged(path string, contents []byte, perm os.FileMode) error {
+ oldContents, err := os.ReadFile(path)
+ if err != nil || !bytes.Equal(contents, oldContents) {
+ err = os.WriteFile(path, contents, perm)
+ }
+ return nil
+}
+
func (context *mixedBuildBazelContext) runAquery(config Config, ctx *Context) error {
if ctx != nil {
ctx.EventHandler.Begin("aquery")
@@ -1032,7 +1101,7 @@
extraFlags = append(extraFlags, "--instrumentation_filter="+strings.Join(paths, ","))
}
}
- aqueryOutput, _, err := context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.AqueryBuildRootRunName, aqueryCmd,
+ aqueryOutput, _, err := context.issueBazelCommand(context.createBazelCommand(config, context.paths, bazel.AqueryBuildRootRunName, aqueryCmd,
extraFlags...))
if err != nil {
return err
@@ -1041,7 +1110,7 @@
return err
}
-func (context *mixedBuildBazelContext) generateBazelSymlinks(ctx *Context) error {
+func (context *mixedBuildBazelContext) generateBazelSymlinks(config Config, ctx *Context) error {
if ctx != nil {
ctx.EventHandler.Begin("symlinks")
defer ctx.EventHandler.End("symlinks")
@@ -1049,7 +1118,7 @@
// Issue a build command of the phony root to generate symlink forests for dependencies of the
// Bazel build. This is necessary because aquery invocations do not generate this symlink forest,
// but some of symlinks may be required to resolve source dependencies of the build.
- _, _, err := context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd))
+ _, _, err := context.issueBazelCommand(context.createBazelCommand(config, context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd))
return err
}
@@ -1259,3 +1328,13 @@
func bazelDepsetName(contentHash string) string {
return fmt.Sprintf("bazel_depset_%s", contentHash)
}
+
+func EnvironmentVarsFile(config Config) string {
+ return fmt.Sprintf(bazel.GeneratedBazelFileWarning+`
+_env = %s
+
+env = _env
+`,
+ starlark_fmt.PrintStringList(allowedBazelEnvironmentVars, 0),
+ )
+}
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index 013e19c..d971802 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -168,6 +168,32 @@
}
}
+func TestBazelRequestsSorted(t *testing.T) {
+ bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
+
+ bazelContext.QueueBazelRequest("zzz", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
+ bazelContext.QueueBazelRequest("ccc", cquery.GetApexInfo, configKey{"arm64_armv8-a", Android})
+ bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
+ bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
+ bazelContext.QueueBazelRequest("xxx", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Linux})
+ bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
+ bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, configKey{"otherarch", Android})
+ bazelContext.QueueBazelRequest("bbb", cquery.GetOutputFiles, configKey{"otherarch", Android})
+
+ if len(bazelContext.requests) != 7 {
+ t.Error("Expected 7 request elements, but got", len(bazelContext.requests))
+ }
+
+ lastString := ""
+ for _, val := range bazelContext.requests {
+ thisString := val.String()
+ if thisString <= lastString {
+ t.Errorf("Requests are not ordered correctly. '%s' came before '%s'", lastString, thisString)
+ }
+ lastString = thisString
+ }
+}
+
func verifyExtraFlags(t *testing.T, config Config, expected string) string {
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
@@ -204,7 +230,6 @@
return &mixedBuildBazelContext{
bazelRunner: runner,
paths: &p,
- requests: map[cqueryKey]bool{},
}, p.soongOutDir
}
diff --git a/android/config.go b/android/config.go
index c305114..600fda0 100644
--- a/android/config.go
+++ b/android/config.go
@@ -725,10 +725,6 @@
return value == "0" || value == "n" || value == "no" || value == "off" || value == "false"
}
-func (c *config) TargetsJava17() bool {
- return c.IsEnvTrue("EXPERIMENTAL_TARGET_JAVA_VERSION_17")
-}
-
// EnvDeps returns the environment variables this build depends on. The first
// call to this function blocks future reads from the environment.
func (c *config) EnvDeps() map[string]string {
diff --git a/android/defaults.go b/android/defaults.go
index 7906e94..925eafc 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -55,7 +55,7 @@
d.hook = hook
}
-func (d *DefaultableModuleBase) callHookIfAvailable(ctx DefaultableHookContext) {
+func (d *DefaultableModuleBase) CallHookIfAvailable(ctx DefaultableHookContext) {
if d.hook != nil {
d.hook(ctx)
}
@@ -82,7 +82,7 @@
SetDefaultableHook(hook DefaultableHook)
// Call the hook if specified.
- callHookIfAvailable(context DefaultableHookContext)
+ CallHookIfAvailable(context DefaultableHookContext)
}
type DefaultableModule interface {
@@ -630,6 +630,6 @@
defaultable.applyDefaults(ctx, defaultsList)
}
- defaultable.callHookIfAvailable(ctx)
+ defaultable.CallHookIfAvailable(ctx)
}
}
diff --git a/android/defs.go b/android/defs.go
index 6e5bb05..18eed2d 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -58,6 +58,14 @@
},
"cpFlags", "extraCmds")
+ // A copy rule that doesn't preserve symlinks.
+ CpNoPreserveSymlink = pctx.AndroidStaticRule("CpNoPreserveSymlink",
+ blueprint.RuleParams{
+ Command: "rm -f $out && cp $cpFlags $in $out$extraCmds",
+ Description: "cp $out",
+ },
+ "cpFlags", "extraCmds")
+
// A copy rule that only updates the output if it changed.
CpIfChanged = pctx.AndroidStaticRule("CpIfChanged",
blueprint.RuleParams{
diff --git a/android/paths.go b/android/paths.go
index 0fc39df..2c50104 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1868,10 +1868,14 @@
return ret
}
-// validateSafePath validates a path that we trust (may contain ninja variables).
-// Ensures that each path component does not attempt to leave its component.
-func validateSafePath(pathComponents ...string) (string, error) {
+// validatePathInternal ensures that a path does not leave its component, and
+// optionally doesn't contain Ninja variables.
+func validatePathInternal(allowNinjaVariables bool, pathComponents ...string) (string, error) {
for _, path := range pathComponents {
+ if !allowNinjaVariables && strings.Contains(path, "$") {
+ return "", fmt.Errorf("Path contains invalid character($): %s", path)
+ }
+
path := filepath.Clean(path)
if path == ".." || strings.HasPrefix(path, "../") || strings.HasPrefix(path, "/") {
return "", fmt.Errorf("Path is outside directory: %s", path)
@@ -1883,16 +1887,18 @@
return filepath.Join(pathComponents...), nil
}
+// validateSafePath validates a path that we trust (may contain ninja
+// variables). Ensures that each path component does not attempt to leave its
+// component. Returns a joined version of each path component.
+func validateSafePath(pathComponents ...string) (string, error) {
+ return validatePathInternal(true, pathComponents...)
+}
+
// validatePath validates that a path does not include ninja variables, and that
// each path component does not attempt to leave its component. Returns a joined
// version of each path component.
func validatePath(pathComponents ...string) (string, error) {
- for _, path := range pathComponents {
- if strings.Contains(path, "$") {
- return "", fmt.Errorf("Path contains invalid character($): %s", path)
- }
- }
- return validateSafePath(pathComponents...)
+ return validatePathInternal(false, pathComponents...)
}
func PathForPhony(ctx PathContext, phony string) WritablePath {
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 7babd45..7f03621 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -23,8 +23,7 @@
"android/soong/android"
"android/soong/cc"
"android/soong/java"
-
- "github.com/google/blueprint/proptools"
+ "android/soong/rust"
)
func (a *apexBundle) AndroidMk() android.AndroidMkData {
@@ -73,12 +72,15 @@
return fi.androidMkModuleName + "." + apexBundleName + a.suffix
}
-func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, moduleDir string,
+func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, moduleDir string,
apexAndroidMkData android.AndroidMkData) []string {
- // apexBundleName comes from the 'name' property; apexName comes from 'apex_name' property.
+ // apexBundleName comes from the 'name' property or soong module.
+ // apexName comes from 'name' property of apex_manifest.
// An apex is installed to /system/apex/<apexBundleName> and is activated at /apex/<apexName>
// In many cases, the two names are the same, but could be different in general.
+ // However, symbol files for apex files are installed under /apex/<apexBundleName> to avoid
+ // conflicts between two apexes with the same apexName.
moduleNames := []string{}
apexType := a.properties.ApexType
@@ -89,25 +91,6 @@
return moduleNames
}
- // b/162366062. Prevent GKI APEXes to emit make rules to avoid conflicts.
- if strings.HasPrefix(apexName, "com.android.gki.") && apexType != flattenedApex {
- return moduleNames
- }
-
- // b/140136207. When there are overriding APEXes for a VNDK APEX, the symbols file for the overridden
- // APEX and the overriding APEX will have the same installation paths at /apex/com.android.vndk.v<ver>
- // as their apexName will be the same. To avoid the path conflicts, skip installing the symbol files
- // for the overriding VNDK APEXes.
- symbolFilesNotNeeded := a.vndkApex && len(a.overridableProperties.Overrides) > 0
- if symbolFilesNotNeeded && apexType != flattenedApex {
- return moduleNames
- }
-
- // Avoid creating duplicate build rules for multi-installed APEXes.
- if proptools.BoolDefault(a.properties.Multi_install_skip_symbol_files, false) {
- return moduleNames
- }
-
seenDataOutPaths := make(map[string]bool)
for _, fi := range a.filesInfo {
@@ -144,15 +127,15 @@
if fi.module != nil && fi.module.Owner() != "" {
fmt.Fprintln(w, "LOCAL_MODULE_OWNER :=", fi.module.Owner())
}
- // /apex/<apex_name>/{lib|framework|...}
- pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex", apexName, fi.installDir)
+ // /apex/<apexBundleName>/{lib|framework|...}
+ pathForSymbol := filepath.Join("$(PRODUCT_OUT)", "apex", apexBundleName, fi.installDir)
var modulePath string
if apexType == flattenedApex {
- // /system/apex/<name>/{lib|framework|...}
+ // /system/apex/<apexBundleName>/{lib|framework|...}
modulePath = filepath.Join(a.installDir.String(), apexBundleName, fi.installDir)
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", modulePath)
- if a.primaryApexType && !symbolFilesNotNeeded {
- fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathWhenActivated)
+ if a.primaryApexType {
+ fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathForSymbol)
}
android.AndroidMkEmitAssignList(w, "LOCAL_MODULE_SYMLINKS", fi.symlinks)
newDataPaths := []android.DataPath{}
@@ -165,8 +148,8 @@
}
android.AndroidMkEmitAssignList(w, "LOCAL_TEST_DATA", android.AndroidMkDataPaths(newDataPaths))
} else {
- modulePath = pathWhenActivated
- fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", pathWhenActivated)
+ modulePath = pathForSymbol
+ fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", modulePath)
// For non-flattend APEXes, the merged notice file is attached to the APEX itself.
// We don't need to have notice file for the individual modules in it. Otherwise,
@@ -256,6 +239,10 @@
if ccMod.CoverageOutputFile().Valid() {
fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", ccMod.CoverageOutputFile().String())
}
+ } else if rustMod, ok := fi.module.(*rust.Module); ok {
+ if rustMod.UnstrippedOutputFile() != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", rustMod.UnstrippedOutputFile().String())
+ }
}
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk")
default:
@@ -320,8 +307,7 @@
moduleNames := []string{}
apexType := a.properties.ApexType
if a.installable() {
- apexName := proptools.StringDefault(a.properties.Apex_name, name)
- moduleNames = a.androidMkForFiles(w, name, apexName, moduleDir, data)
+ moduleNames = a.androidMkForFiles(w, name, moduleDir, data)
}
if apexType == flattenedApex {
diff --git a/apex/apex.go b/apex/apex.go
index a9c8afc..bc2a136 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -94,10 +94,6 @@
// a default one is automatically generated.
AndroidManifest *string `android:"path"`
- // Canonical name of this APEX bundle. Used to determine the path to the activated APEX on
- // device (/apex/<apex_name>). If unspecified, follows the name property.
- Apex_name *string
-
// Determines the file contexts file for setting the security contexts to files in this APEX
// bundle. For platform APEXes, this should points to a file under /system/sepolicy Default:
// /system/sepolicy/apex/<module_name>_file_contexts.
@@ -149,16 +145,6 @@
// Should be only used in non-system apexes (e.g. vendor: true). Default is false.
Use_vndk_as_stable *bool
- // Whether this is multi-installed APEX should skip installing symbol files.
- // Multi-installed APEXes share the same apex_name and are installed at the same time.
- // Default is false.
- //
- // Should be set to true for all multi-installed APEXes except the singular
- // default version within the multi-installed group.
- // Only the default version can install symbol files in $(PRODUCT_OUT}/apex,
- // or else conflicting build rules may be created.
- Multi_install_skip_symbol_files *bool
-
// The type of APEX to build. Controls what the APEX payload is. Either 'image', 'zip' or
// 'both'. When set to image, contents are stored in a filesystem image inside a zip
// container. When set to zip, contents are stored in a zip container directly. This type is
@@ -1047,7 +1033,7 @@
// This is the main part of this mutator. Mark the collected dependencies that they need to
// be built for this apexBundle.
- apexVariationName := proptools.StringDefault(a.properties.Apex_name, mctx.ModuleName()) // could be com.android.foo
+ apexVariationName := mctx.ModuleName() // could be com.android.foo
a.properties.ApexVariationName = apexVariationName
apexInfo := android.ApexInfo{
ApexVariationName: apexVariationName,
@@ -1781,6 +1767,18 @@
return af
}
+func apexFileForJavaModuleProfile(ctx android.BaseModuleContext, module javaModule) *apexFile {
+ if dexpreopter, ok := module.(java.DexpreopterInterface); ok {
+ if profilePathOnHost := dexpreopter.ProfilePathOnHost(); profilePathOnHost != nil {
+ dirInApex := "javalib"
+ af := newApexFile(ctx, profilePathOnHost, module.BaseModuleName()+"-profile", dirInApex, etc, nil)
+ af.customStem = module.Stem() + ".jar.prof"
+ return &af
+ }
+ }
+ return nil
+}
+
// androidApp is an interface to handle all app modules (android_app, android_app_import, etc.) in
// the same way.
type androidApp interface {
@@ -1964,6 +1962,11 @@
}
a.outputFile = a.outputApexFile
+ if len(outputs.TidyFiles) > 0 {
+ tidyFiles := android.PathsForBazelOut(ctx, outputs.TidyFiles)
+ a.outputFile = android.AttachValidationActions(ctx, a.outputFile, tidyFiles)
+ }
+
// TODO(b/257829940): These are used by the apex_keys_text singleton; would probably be a clearer
// interface if these were set in a provider rather than the module itself
a.publicKeyFile = android.PathForBazelOut(ctx, outputs.BundleKeyInfo[0])
@@ -2475,6 +2478,9 @@
case *java.Library, *java.SdkLibrary:
af := apexFileForJavaModule(ctx, child.(javaModule))
vctx.filesInfo = append(vctx.filesInfo, af)
+ if profileAf := apexFileForJavaModuleProfile(ctx, child.(javaModule)); profileAf != nil {
+ vctx.filesInfo = append(vctx.filesInfo, *profileAf)
+ }
return true // track transitive dependencies
default:
ctx.PropertyErrorf("systemserverclasspath_fragments",
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 31e848e..8b69f2c 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -3806,11 +3806,9 @@
}`+vndkLibrariesTxtFiles("28", "current"))
assertApexName := func(expected, moduleName string) {
- bundle := ctx.ModuleForTests(moduleName, "android_common_image").Module().(*apexBundle)
- actual := proptools.String(bundle.properties.Apex_name)
- if !reflect.DeepEqual(actual, expected) {
- t.Errorf("Got '%v', expected '%v'", actual, expected)
- }
+ module := ctx.ModuleForTests(moduleName, "android_common_image")
+ apexManifestRule := module.Rule("apexManifestRule")
+ ensureContains(t, apexManifestRule.Args["opt"], "-v name "+expected)
}
assertApexName("com.android.vndk.v29", "com.android.vndk.current")
@@ -4107,57 +4105,11 @@
ensureListEmpty(t, requireNativeLibs)
}
-func TestApexName(t *testing.T) {
- ctx := testApex(t, `
- apex {
- name: "myapex",
- key: "myapex.key",
- apex_name: "com.android.myapex",
- native_shared_libs: ["mylib"],
- updatable: false,
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "mylib",
- srcs: ["mylib.cpp"],
- system_shared_libs: [],
- stl: "none",
- apex_available: [
- "//apex_available:platform",
- "myapex",
- ],
- }
- `)
-
- module := ctx.ModuleForTests("myapex", "android_common_com.android.myapex_image")
- apexManifestRule := module.Rule("apexManifestRule")
- ensureContains(t, apexManifestRule.Args["opt"], "-v name com.android.myapex")
- apexRule := module.Rule("apexRule")
- ensureContains(t, apexRule.Args["opt_flags"], "--do_not_check_keyname")
-
- apexBundle := module.Module().(*apexBundle)
- data := android.AndroidMkDataForTest(t, ctx, apexBundle)
- name := apexBundle.BaseModuleName()
- prefix := "TARGET_"
- var builder strings.Builder
- data.Custom(&builder, name, prefix, "", data)
- androidMk := builder.String()
- ensureContains(t, androidMk, "LOCAL_MODULE := mylib.myapex\n")
- ensureNotContains(t, androidMk, "LOCAL_MODULE := mylib.com.android.myapex\n")
-}
-
func TestOverrideApexManifestDefaultVersion(t *testing.T) {
ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
- apex_name: "com.android.myapex",
native_shared_libs: ["mylib"],
updatable: false,
}
@@ -4182,7 +4134,7 @@
"OVERRIDE_APEX_MANIFEST_DEFAULT_VERSION": "1234",
}))
- module := ctx.ModuleForTests("myapex", "android_common_com.android.myapex_image")
+ module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
apexManifestRule := module.Rule("apexManifestRule")
ensureContains(t, apexManifestRule.Args["default_version"], "1234")
}
diff --git a/apex/builder.go b/apex/builder.go
index 4331d3e..93ff80d 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -241,10 +241,11 @@
provideNativeLibs = android.SortedUniqueStrings(provideNativeLibs)
requireNativeLibs = android.SortedUniqueStrings(android.RemoveListFromList(requireNativeLibs, provideNativeLibs))
- // APEX name can be overridden
+ // VNDK APEX name is determined at runtime, so update "name" in apex_manifest
optCommands := []string{}
- if a.properties.Apex_name != nil {
- optCommands = append(optCommands, "-v name "+*a.properties.Apex_name)
+ if a.vndkApex {
+ apexName := vndkApexNamePrefix + a.vndkVersion(ctx.DeviceConfig())
+ optCommands = append(optCommands, "-v name "+apexName)
}
// Collect jniLibs. Notice that a.filesInfo is already sorted
@@ -445,7 +446,7 @@
func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
apexType := a.properties.ApexType
suffix := apexType.suffix()
- apexName := proptools.StringDefault(a.properties.Apex_name, a.BaseModuleName())
+ apexName := a.BaseModuleName()
////////////////////////////////////////////////////////////////////////////////////////////
// Step 1: copy built files to appropriate directories under the image directory
@@ -454,26 +455,13 @@
installSymbolFiles := (!ctx.Config().KatiEnabled() || a.ExportedToMake()) && a.installable()
- // b/140136207. When there are overriding APEXes for a VNDK APEX, the symbols file for the overridden
- // APEX and the overriding APEX will have the same installation paths at /apex/com.android.vndk.v<ver>
- // as their apexName will be the same. To avoid the path conflicts, skip installing the symbol files
- // for the overriding VNDK APEXes.
- if a.vndkApex && len(a.overridableProperties.Overrides) > 0 {
- installSymbolFiles = false
- }
-
- // Avoid creating duplicate build rules for multi-installed APEXes.
- if proptools.BoolDefault(a.properties.Multi_install_skip_symbol_files, false) {
- installSymbolFiles = false
-
- }
// set of dependency module:location mappings
installMapSet := make(map[string]bool)
// TODO(jiyong): use the RuleBuilder
var copyCommands []string
var implicitInputs []android.Path
- pathWhenActivated := android.PathForModuleInPartitionInstall(ctx, "apex", apexName)
+ apexDir := android.PathForModuleInPartitionInstall(ctx, "apex", apexName)
for _, fi := range a.filesInfo {
destPath := imageDir.Join(ctx, fi.path()).String()
// Prepare the destination path
@@ -503,12 +491,12 @@
fmt.Sprintf("unzip -qDD -d %s %s", destPathDir,
fi.module.(*java.AndroidAppSet).PackedAdditionalOutputs().String()))
if installSymbolFiles {
- installedPath = ctx.InstallFileWithExtraFilesZip(pathWhenActivated.Join(ctx, fi.installDir),
+ installedPath = ctx.InstallFileWithExtraFilesZip(apexDir.Join(ctx, fi.installDir),
fi.stem(), fi.builtFile, fi.module.(*java.AndroidAppSet).PackedAdditionalOutputs())
}
} else {
if installSymbolFiles {
- installedPath = ctx.InstallFile(pathWhenActivated.Join(ctx, fi.installDir), fi.stem(), fi.builtFile)
+ installedPath = ctx.InstallFile(apexDir.Join(ctx, fi.installDir), fi.stem(), fi.builtFile)
}
}
implicitInputs = append(implicitInputs, fi.builtFile)
@@ -522,7 +510,7 @@
symlinkDest := imageDir.Join(ctx, symlinkPath).String()
copyCommands = append(copyCommands, "ln -sfn "+filepath.Base(destPath)+" "+symlinkDest)
if installSymbolFiles {
- installedSymlink := ctx.InstallSymlink(pathWhenActivated.Join(ctx, filepath.Dir(symlinkPath)), filepath.Base(symlinkPath), installedPath)
+ installedSymlink := ctx.InstallSymlink(apexDir.Join(ctx, filepath.Dir(symlinkPath)), filepath.Base(symlinkPath), installedPath)
implicitInputs = append(implicitInputs, installedSymlink)
}
}
@@ -549,8 +537,8 @@
}
implicitInputs = append(implicitInputs, a.manifestPbOut)
if installSymbolFiles {
- installedManifest := ctx.InstallFile(pathWhenActivated, "apex_manifest.pb", a.manifestPbOut)
- installedKey := ctx.InstallFile(pathWhenActivated, "apex_pubkey", a.publicKeyFile)
+ installedManifest := ctx.InstallFile(apexDir, "apex_manifest.pb", a.manifestPbOut)
+ installedKey := ctx.InstallFile(apexDir, "apex_pubkey", a.publicKeyFile)
implicitInputs = append(implicitInputs, installedManifest, installedKey)
}
@@ -706,12 +694,6 @@
optFlags = append(optFlags, "--unsigned_payload")
}
- if a.properties.Apex_name != nil {
- // If apex_name is set, apexer can skip checking if key name matches with
- // apex name. Note that apex_manifest is also mended.
- optFlags = append(optFlags, "--do_not_check_keyname")
- }
-
if moduleMinSdkVersion == android.SdkVersion_Android10 {
implicitInputs = append(implicitInputs, a.manifestJsonOut)
optFlags = append(optFlags, "--manifest_json "+a.manifestJsonOut.String())
@@ -1018,7 +1000,7 @@
if a.vndkApex {
overrideName, overridden := ctx.DeviceConfig().OverrideManifestPackageNameFor(vndkApexName)
if overridden {
- return strings.Replace(*a.properties.Apex_name, vndkApexName, overrideName, 1)
+ return overrideName + ".v" + a.vndkVersion(ctx.DeviceConfig())
}
return ""
}
diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go
index d037664..c404a2e 100644
--- a/apex/systemserver_classpath_fragment_test.go
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -31,7 +31,7 @@
result := android.GroupFixturePreparers(
prepareForTestWithSystemserverclasspathFragment,
prepareForTestWithMyapex,
- dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
+ dexpreopt.FixtureSetApexSystemServerJars("myapex:foo", "myapex:bar"),
).RunTestWithBp(t, `
apex {
name: "myapex",
@@ -57,10 +57,23 @@
],
}
+ java_library {
+ name: "bar",
+ srcs: ["c.java"],
+ installable: true,
+ dex_preopt: {
+ profile: "bar-art-profile",
+ },
+ apex_available: [
+ "myapex",
+ ],
+ }
+
systemserverclasspath_fragment {
name: "mysystemserverclasspathfragment",
contents: [
"foo",
+ "bar",
],
apex_available: [
"myapex",
@@ -71,6 +84,8 @@
ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
"etc/classpaths/systemserverclasspath.pb",
"javalib/foo.jar",
+ "javalib/bar.jar",
+ "javalib/bar.jar.prof",
})
java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
@@ -236,7 +251,7 @@
result := android.GroupFixturePreparers(
prepareForTestWithSystemserverclasspathFragment,
prepareForTestWithMyapex,
- dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo"),
+ dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo", "myapex:bar"),
).RunTestWithBp(t, `
apex {
name: "myapex",
@@ -262,10 +277,23 @@
],
}
+ java_library {
+ name: "bar",
+ srcs: ["c.java"],
+ dex_preopt: {
+ profile: "bar-art-profile",
+ },
+ installable: true,
+ apex_available: [
+ "myapex",
+ ],
+ }
+
systemserverclasspath_fragment {
name: "mysystemserverclasspathfragment",
standalone_contents: [
"foo",
+ "bar",
],
apex_available: [
"myapex",
@@ -276,6 +304,8 @@
ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
"etc/classpaths/systemserverclasspath.pb",
"javalib/foo.jar",
+ "javalib/bar.jar",
+ "javalib/bar.jar.prof",
})
}
diff --git a/apex/vndk.go b/apex/vndk.go
index 80560cf..c0be753 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -65,10 +65,6 @@
}
vndkVersion := ab.vndkVersion(mctx.DeviceConfig())
-
- // Ensure VNDK APEX mount point is formatted as com.android.vndk.v###
- ab.properties.Apex_name = proptools.StringPtr(vndkApexNamePrefix + vndkVersion)
-
apiLevel, err := android.ApiLevelFromUser(mctx, vndkVersion)
if err != nil {
mctx.PropertyErrorf("vndk_version", "%s", err.Error())
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index 6654191..0c8247a 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -180,7 +180,7 @@
tidy_files = []
clang_tidy_info = p.get("//build/bazel/rules/cc:clang_tidy.bzl%ClangTidyInfo")
if clang_tidy_info:
- tidy_files = [v.path for v in clang_tidy_info.tidy_files.to_list()]
+ tidy_files = [v.path for v in clang_tidy_info.transitive_tidy_files.to_list()]
abi_diff_files = []
abi_diff_info = p.get("//build/bazel/rules/abi:abi_dump.bzl%AbiDiffInfo")
@@ -207,7 +207,7 @@
"Headers": headers,
"RootStaticArchives": rootStaticArchives,
"RootDynamicLibraries": rootSharedLibraries,
- "TidyFiles": tidy_files,
+ "TidyFiles": [t for t in tidy_files],
"TocFile": toc_file,
"UnstrippedOutput": unstripped,
"AbiDiffFiles": abi_diff_files,
@@ -261,6 +261,11 @@
if not mk_info:
fail("%s did not provide ApexMkInfo" % id_string)
+tidy_files = []
+clang_tidy_info = providers(target).get("//build/bazel/rules/cc:clang_tidy.bzl%ClangTidyInfo")
+if clang_tidy_info:
+ tidy_files = [v.path for v in clang_tidy_info.transitive_tidy_files.to_list()]
+
return json_encode({
"signed_output": info.signed_output.path,
"signed_compressed_output": signed_compressed_output,
@@ -276,6 +281,7 @@
"bundle_file": info.base_with_config_zip.path,
"installed_files": info.installed_files.path,
"make_modules_to_install": mk_info.make_modules_to_install,
+ "tidy_files": [t for t in tidy_files],
})`
}
@@ -294,6 +300,7 @@
BackingLibs string `json:"backing_libs"`
BundleFile string `json:"bundle_file"`
InstalledFiles string `json:"installed_files"`
+ TidyFiles []string `json:"tidy_files"`
// From the ApexMkInfo provider
MakeModulesToInstall []string `json:"make_modules_to_install"`
@@ -338,12 +345,18 @@
local_whole_static_libs = androidmk_info.local_whole_static_libs
local_shared_libs = androidmk_info.local_shared_libs
+tidy_files = []
+clang_tidy_info = p.get("//build/bazel/rules/cc:clang_tidy.bzl%ClangTidyInfo")
+if clang_tidy_info:
+ tidy_files = [v.path for v in clang_tidy_info.transitive_tidy_files.to_list()]
+
return json_encode({
"OutputFile": output_path,
"UnstrippedOutput": unstripped,
"LocalStaticLibs": [l for l in local_static_libs],
"LocalWholeStaticLibs": [l for l in local_whole_static_libs],
"LocalSharedLibs": [l for l in local_shared_libs],
+ "TidyFiles": [t for t in tidy_files],
})
`
}
@@ -361,6 +374,7 @@
CcAndroidMkInfo
OutputFile string
UnstrippedOutput string
+ TidyFiles []string
}
// splitOrEmpty is a modification of strings.Split() that returns an empty list
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index c43fbd8..5b3e19f 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -58,6 +58,8 @@
files = append(files, newFile("api_levels", "api_levels.json", string(apiLevelsContent)))
files = append(files, newFile("api_levels", "api_levels.bzl", android.StarlarkApiLevelConfigs(cfg)))
+ files = append(files, newFile("allowlists", GeneratedBuildFileName, ""))
+ files = append(files, newFile("allowlists", "env.bzl", android.EnvironmentVarsFile(cfg)))
// TODO(b/262781701): Create an alternate soong_build entrypoint for writing out these files only when requested
files = append(files, newFile("allowlists", "mixed_build_prod_allowlist.txt", strings.Join(android.GetBazelEnabledModules(android.BazelProdMode), "\n")+"\n"))
files = append(files, newFile("allowlists", "mixed_build_staging_allowlist.txt", strings.Join(android.GetBazelEnabledModules(android.BazelStagingMode), "\n")+"\n"))
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index b9c06bc..8c24093 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -153,6 +153,14 @@
},
{
dir: "allowlists",
+ basename: GeneratedBuildFileName,
+ },
+ {
+ dir: "allowlists",
+ basename: "env.bzl",
+ },
+ {
+ dir: "allowlists",
basename: "mixed_build_prod_allowlist.txt",
},
{
diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go
index 37188f1..183eb12 100644
--- a/bp2build/symlink_forest.go
+++ b/bp2build/symlink_forest.go
@@ -15,9 +15,7 @@
package bp2build
import (
- "errors"
"fmt"
- "io/fs"
"io/ioutil"
"os"
"path/filepath"
@@ -53,59 +51,6 @@
symlinkCount atomic.Uint64
}
-// A simple thread pool to limit concurrency on system calls.
-// Necessary because Go spawns a new OS-level thread for each blocking system
-// call. This means that if syscalls are too slow and there are too many of
-// them, the hard limit on OS-level threads can be exhausted.
-type syscallPool struct {
- shutdownCh []chan<- struct{}
- workCh chan syscall
-}
-
-type syscall struct {
- work func()
- done chan<- struct{}
-}
-
-func createSyscallPool(count int) *syscallPool {
- result := &syscallPool{
- shutdownCh: make([]chan<- struct{}, count),
- workCh: make(chan syscall),
- }
-
- for i := 0; i < count; i++ {
- shutdownCh := make(chan struct{})
- result.shutdownCh[i] = shutdownCh
- go result.worker(shutdownCh)
- }
-
- return result
-}
-
-func (p *syscallPool) do(work func()) {
- doneCh := make(chan struct{})
- p.workCh <- syscall{work, doneCh}
- <-doneCh
-}
-
-func (p *syscallPool) shutdown() {
- for _, ch := range p.shutdownCh {
- ch <- struct{}{} // Blocks until the value is received
- }
-}
-
-func (p *syscallPool) worker(shutdownCh <-chan struct{}) {
- for {
- select {
- case <-shutdownCh:
- return
- case work := <-p.workCh:
- work.work()
- work.done <- struct{}{}
- }
- }
-}
-
// Ensures that the node for the given path exists in the tree and returns it.
func ensureNodeExists(root *instructionsNode, path string) *instructionsNode {
if path == "" {
@@ -217,12 +162,35 @@
}
// Creates a symbolic link at dst pointing to src
-func symlinkIntoForest(topdir, dst, src string) {
- err := os.Symlink(shared.JoinPath(topdir, src), shared.JoinPath(topdir, dst))
- if err != nil {
+func symlinkIntoForest(topdir, dst, src string) uint64 {
+ srcPath := shared.JoinPath(topdir, src)
+ dstPath := shared.JoinPath(topdir, dst)
+
+ // Check if a symlink already exists.
+ if dstInfo, err := os.Lstat(dstPath); err != nil {
+ if !os.IsNotExist(err) {
+ fmt.Fprintf(os.Stderr, "Failed to lstat '%s': %s", dst, err)
+ os.Exit(1)
+ }
+ } else {
+ if dstInfo.Mode()&os.ModeSymlink != 0 {
+ // Assume that the link's target is correct, i.e. no manual tampering.
+ // E.g. OUT_DIR could have been previously used with a different source tree check-out!
+ return 0
+ } else {
+ if err := os.RemoveAll(dstPath); err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to remove '%s': %s", dst, err)
+ os.Exit(1)
+ }
+ }
+ }
+
+ // Create symlink.
+ if err := os.Symlink(srcPath, dstPath); err != nil {
fmt.Fprintf(os.Stderr, "Cannot create symlink at '%s' pointing to '%s': %s", dst, src, err)
os.Exit(1)
}
+ return 1
}
func isDir(path string, fi os.FileInfo) bool {
@@ -253,8 +221,9 @@
defer context.wg.Done()
if instructions != nil && instructions.excluded {
- // This directory is not needed, bail out
- return
+ // Excluded paths are skipped at the level of the non-excluded parent.
+ fmt.Fprintf(os.Stderr, "may not specify a root-level exclude directory '%s'", srcDir)
+ os.Exit(1)
}
// We don't add buildFilesDir here because the bp2build files marker files is
@@ -272,6 +241,12 @@
renamingBuildFile = true
srcDirMap["BUILD.bazel"] = srcDirMap["BUILD"]
delete(srcDirMap, "BUILD")
+ if instructions != nil {
+ if _, ok := instructions.children["BUILD"]; ok {
+ instructions.children["BUILD.bazel"] = instructions.children["BUILD"]
+ delete(instructions.children, "BUILD")
+ }
+ }
}
}
}
@@ -288,17 +263,41 @@
// Tests read the error messages generated, so ensure their order is deterministic
sort.Strings(allEntries)
- err := os.MkdirAll(shared.JoinPath(context.topdir, forestDir), 0777)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Cannot mkdir '%s': %s\n", forestDir, err)
- os.Exit(1)
+ fullForestPath := shared.JoinPath(context.topdir, forestDir)
+ createForestDir := false
+ if fi, err := os.Lstat(fullForestPath); err != nil {
+ if os.IsNotExist(err) {
+ createForestDir = true
+ } else {
+ fmt.Fprintf(os.Stderr, "Could not read info for '%s': %s\n", forestDir, err)
+ }
+ } else if fi.Mode()&os.ModeDir == 0 {
+ if err := os.RemoveAll(fullForestPath); err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to remove '%s': %s", forestDir, err)
+ os.Exit(1)
+ }
+ createForestDir = true
}
- context.mkdirCount.Add(1)
+ if createForestDir {
+ if err := os.MkdirAll(fullForestPath, 0777); err != nil {
+ fmt.Fprintf(os.Stderr, "Could not mkdir '%s': %s\n", forestDir, err)
+ os.Exit(1)
+ }
+ context.mkdirCount.Add(1)
+ }
+
+ // Start with a list of items that already exist in the forest, and remove
+ // each element as it is processed in allEntries. Any remaining items in
+ // forestMapForDeletion must be removed. (This handles files which were
+ // removed since the previous forest generation).
+ forestMapForDeletion := readdirToMap(shared.JoinPath(context.topdir, forestDir))
for _, f := range allEntries {
if f[0] == '.' {
continue // Ignore dotfiles
}
+ delete(forestMapForDeletion, f)
+ // todo add deletionCount metric
// The full paths of children in the input trees and in the output tree
forestChild := shared.JoinPath(forestDir, f)
@@ -309,13 +308,9 @@
buildFilesChild := shared.JoinPath(buildFilesDir, f)
// Descend in the instruction tree if it exists
- var instructionsChild *instructionsNode = nil
+ var instructionsChild *instructionsNode
if instructions != nil {
- if f == "BUILD.bazel" && renamingBuildFile {
- instructionsChild = instructions.children["BUILD"]
- } else {
- instructionsChild = instructions.children[f]
- }
+ instructionsChild = instructions.children[f]
}
srcChildEntry, sExists := srcDirMap[f]
@@ -323,8 +318,7 @@
if instructionsChild != nil && instructionsChild.excluded {
if bExists {
- symlinkIntoForest(context.topdir, forestChild, buildFilesChild)
- context.symlinkCount.Add(1)
+ context.symlinkCount.Add(symlinkIntoForest(context.topdir, forestChild, buildFilesChild))
}
continue
}
@@ -340,8 +334,7 @@
go plantSymlinkForestRecursive(context, instructionsChild, forestChild, buildFilesChild, srcChild)
} else {
// Not in the source tree, symlink BUILD file
- symlinkIntoForest(context.topdir, forestChild, buildFilesChild)
- context.symlinkCount.Add(1)
+ context.symlinkCount.Add(symlinkIntoForest(context.topdir, forestChild, buildFilesChild))
}
} else if !bExists {
if sDir && instructionsChild != nil {
@@ -351,8 +344,7 @@
go plantSymlinkForestRecursive(context, instructionsChild, forestChild, buildFilesChild, srcChild)
} else {
// Not in the build file tree, symlink source tree, carry on
- symlinkIntoForest(context.topdir, forestChild, srcChild)
- context.symlinkCount.Add(1)
+ context.symlinkCount.Add(symlinkIntoForest(context.topdir, forestChild, srcChild))
}
} else if sDir && bDir {
// Both are directories. Descend.
@@ -365,8 +357,7 @@
// The Android.bp file that codegen used to produce `buildFilesChild` is
// already a dependency, we can ignore `buildFilesChild`.
context.depCh <- srcChild
- err = mergeBuildFiles(shared.JoinPath(context.topdir, forestChild), srcBuildFile, generatedBuildFile, context.verbose)
- if err != nil {
+ if err := mergeBuildFiles(shared.JoinPath(context.topdir, forestChild), srcBuildFile, generatedBuildFile, context.verbose); err != nil {
fmt.Fprintf(os.Stderr, "Error merging %s and %s: %s",
srcBuildFile, generatedBuildFile, err)
os.Exit(1)
@@ -379,51 +370,27 @@
os.Exit(1)
}
}
-}
-func removeParallelRecursive(pool *syscallPool, path string, fi os.FileInfo, wg *sync.WaitGroup) {
- defer wg.Done()
-
- if fi.IsDir() {
- children := readdirToMap(path)
- childrenWg := &sync.WaitGroup{}
- childrenWg.Add(len(children))
-
- for child, childFi := range children {
- go removeParallelRecursive(pool, shared.JoinPath(path, child), childFi, childrenWg)
+ // Remove all files in the forest that exist in neither the source
+ // tree nor the build files tree. (This handles files which were removed
+ // since the previous forest generation).
+ for f := range forestMapForDeletion {
+ var instructionsChild *instructionsNode
+ if instructions != nil {
+ instructionsChild = instructions.children[f]
}
- childrenWg.Wait()
- }
-
- pool.do(func() {
- if err := os.Remove(path); err != nil {
- fmt.Fprintf(os.Stderr, "Cannot unlink '%s': %s\n", path, err)
+ if instructionsChild != nil && instructionsChild.excluded {
+ // This directory may be excluded because bazel writes to it under the
+ // forest root. Thus this path is intentionally left alone.
+ continue
+ }
+ forestChild := shared.JoinPath(context.topdir, forestDir, f)
+ if err := os.RemoveAll(forestChild); err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to remove '%s/%s': %s", forestDir, f, err)
os.Exit(1)
}
- })
-}
-
-func removeParallel(path string) {
- fi, err := os.Lstat(path)
- if err != nil {
- if errors.Is(err, fs.ErrNotExist) {
- return
- }
-
- fmt.Fprintf(os.Stderr, "Cannot lstat '%s': %s\n", path, err)
- os.Exit(1)
}
-
- wg := &sync.WaitGroup{}
- wg.Add(1)
-
- // Random guess as to the best number of syscalls to run in parallel
- pool := createSyscallPool(100)
- removeParallelRecursive(pool, path, fi, wg)
- pool.shutdown()
-
- wg.Wait()
}
// PlantSymlinkForest Creates a symlink forest by merging the directory tree at "buildFiles" and
@@ -439,8 +406,6 @@
symlinkCount: atomic.Uint64{},
}
- removeParallel(shared.JoinPath(topdir, forest))
-
instructions := instructionsFromExcludePathList(exclude)
go func() {
context.wg.Add(1)
diff --git a/cc/binary.go b/cc/binary.go
index 2f8ee7f..a04b174 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -588,7 +588,11 @@
return
}
- outputFilePath := android.PathForBazelOut(ctx, info.OutputFile)
+ var outputFilePath android.Path = android.PathForBazelOut(ctx, info.OutputFile)
+ if len(info.TidyFiles) > 0 {
+ handler.module.tidyFiles = android.PathsForBazelOut(ctx, info.TidyFiles)
+ outputFilePath = android.AttachValidationActions(ctx, outputFilePath, handler.module.tidyFiles)
+ }
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
handler.module.linker.(*binaryDecorator).unstrippedOutputFile = android.PathForBazelOut(ctx, info.UnstrippedOutput)
diff --git a/cc/binary_test.go b/cc/binary_test.go
index 43aff5c..e0b5b5d 100644
--- a/cc/binary_test.go
+++ b/cc/binary_test.go
@@ -55,6 +55,47 @@
android.AssertStringEquals(t, "Unstripped output file", expectedUnStrippedFile, unStrippedFilePath.String())
}
+func TestCcBinaryWithBazelValidations(t *testing.T) {
+ t.Parallel()
+ bp := `
+cc_binary {
+ name: "foo",
+ srcs: ["foo.cc"],
+ bazel_module: { label: "//foo/bar:bar" },
+ tidy: true,
+}`
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: "outputbase",
+ LabelToCcBinary: map[string]cquery.CcUnstrippedInfo{
+ "//foo/bar:bar": cquery.CcUnstrippedInfo{
+ OutputFile: "foo",
+ UnstrippedOutput: "foo.unstripped",
+ TidyFiles: []string{"foo.c.tidy"},
+ },
+ },
+ }
+ ctx := android.GroupFixturePreparers(
+ prepareForCcTest,
+ android.FixtureMergeEnv(map[string]string{
+ "ALLOW_LOCAL_TIDY_TRUE": "1",
+ }),
+ ).RunTestWithConfig(t, config).TestContext
+
+ binMod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module()
+ producer := binMod.(android.OutputFileProducer)
+ outputFiles, err := producer.OutputFiles("")
+ if err != nil {
+ t.Errorf("Unexpected error getting cc_binary outputfiles %s", err)
+ }
+ expectedOutputFiles := []string{"out/soong/.intermediates/foo/android_arm64_armv8-a/validated/foo"}
+ android.AssertPathsRelativeToTopEquals(t, "output files", expectedOutputFiles, outputFiles)
+
+ unStrippedFilePath := binMod.(*Module).UnstrippedOutputFile()
+ expectedUnStrippedFile := "outputbase/execroot/__main__/foo.unstripped"
+ android.AssertStringEquals(t, "Unstripped output file", expectedUnStrippedFile, unStrippedFilePath.String())
+}
+
func TestBinaryLinkerScripts(t *testing.T) {
t.Parallel()
result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, `
diff --git a/cc/cc.go b/cc/cc.go
index c33c5e3..c81160d 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1066,6 +1066,31 @@
return false
}
+func (c *Module) IsFuzzModule() bool {
+ if _, ok := c.compiler.(*fuzzBinary); ok {
+ return true
+ }
+ return false
+}
+
+func (c *Module) FuzzModuleStruct() fuzz.FuzzModule {
+ return c.FuzzModule
+}
+
+func (c *Module) FuzzPackagedModule() fuzz.FuzzPackagedModule {
+ if fuzzer, ok := c.compiler.(*fuzzBinary); ok {
+ return fuzzer.fuzzPackagedModule
+ }
+ panic(fmt.Errorf("FuzzPackagedModule called on non-fuzz module: %q", c.BaseModuleName()))
+}
+
+func (c *Module) FuzzSharedLibraries() android.Paths {
+ if fuzzer, ok := c.compiler.(*fuzzBinary); ok {
+ return fuzzer.sharedLibraries
+ }
+ panic(fmt.Errorf("FuzzSharedLibraries called on non-fuzz module: %q", c.BaseModuleName()))
+}
+
func (c *Module) NonCcVariants() bool {
return false
}
@@ -1888,12 +1913,6 @@
func (c *Module) ProcessBazelQueryResponse(ctx android.ModuleContext) {
bazelModuleLabel := c.getBazelModuleLabel(ctx)
-
- bazelCtx := ctx.Config().BazelContext
- if ccInfo, err := bazelCtx.GetCcInfo(bazelModuleLabel, android.GetConfigKey(ctx)); err == nil {
- c.tidyFiles = android.PathsForBazelOut(ctx, ccInfo.TidyFiles)
- }
-
c.bazelHandler.ProcessBazelQueryResponse(ctx, bazelModuleLabel)
c.Properties.SubName = GetSubnameProperty(ctx, c)
diff --git a/cc/config/global.go b/cc/config/global.go
index d557c0b..3fd1b10 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -279,7 +279,6 @@
// http://b/145211477
"-Wno-pointer-compare",
- // http://b/145211022
"-Wno-final-dtor-non-final-class",
// http://b/165945989
@@ -293,6 +292,9 @@
// http://b/239661264
"-Wno-deprecated-non-prototype",
+
+ // http://b/191699019
+ "-Wno-format-insufficient-args",
}
llvmNextExtraCommonGlobalCflags = []string{
@@ -432,7 +434,7 @@
pctx.StaticVariable("ClangBin", "${ClangPath}/bin")
pctx.StaticVariableWithEnvOverride("ClangShortVersion", "LLVM_RELEASE_VERSION", ClangDefaultShortVersion)
- pctx.StaticVariable("ClangAsanLibDir", "${ClangBase}/linux-x86/${ClangVersion}/lib64/clang/${ClangShortVersion}/lib/linux")
+ pctx.StaticVariable("ClangAsanLibDir", "${ClangBase}/linux-x86/${ClangVersion}/lib/clang/${ClangShortVersion}/lib/linux")
// These are tied to the version of LLVM directly in external/llvm, so they might trail the host prebuilts
// being used for the rest of the build process.
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 7113d87..7aa8b91 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -212,7 +212,7 @@
return true
}
-func sharedLibraryInstallLocation(
+func SharedLibraryInstallLocation(
libraryPath android.Path, isHost bool, fuzzDir string, archString string) string {
installLocation := "$(PRODUCT_OUT)/data"
if isHost {
@@ -224,7 +224,7 @@
}
// Get the device-only shared library symbols install directory.
-func sharedLibrarySymbolsInstallLocation(libraryPath android.Path, fuzzDir string, archString string) string {
+func SharedLibrarySymbolsInstallLocation(libraryPath android.Path, fuzzDir string, archString string) string {
return filepath.Join("$(PRODUCT_OUT)/symbols/data/", fuzzDir, archString, "/lib/", libraryPath.Base())
}
@@ -237,59 +237,64 @@
installBase, ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
fuzzBin.binaryDecorator.baseInstaller.install(ctx, file)
- fuzzBin.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzzBin.fuzzPackagedModule.FuzzProperties.Corpus)
- builder := android.NewRuleBuilder(pctx, ctx)
- intermediateDir := android.PathForModuleOut(ctx, "corpus")
- for _, entry := range fuzzBin.fuzzPackagedModule.Corpus {
- builder.Command().Text("cp").
- Input(entry).
- Output(intermediateDir.Join(ctx, entry.Base()))
- }
- builder.Build("copy_corpus", "copy corpus")
- fuzzBin.fuzzPackagedModule.CorpusIntermediateDir = intermediateDir
-
- fuzzBin.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzzBin.fuzzPackagedModule.FuzzProperties.Data)
- builder = android.NewRuleBuilder(pctx, ctx)
- intermediateDir = android.PathForModuleOut(ctx, "data")
- for _, entry := range fuzzBin.fuzzPackagedModule.Data {
- builder.Command().Text("cp").
- Input(entry).
- Output(intermediateDir.Join(ctx, entry.Rel()))
- }
- builder.Build("copy_data", "copy data")
- fuzzBin.fuzzPackagedModule.DataIntermediateDir = intermediateDir
-
- if fuzzBin.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
- fuzzBin.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzzBin.fuzzPackagedModule.FuzzProperties.Dictionary)
- if fuzzBin.fuzzPackagedModule.Dictionary.Ext() != ".dict" {
- ctx.PropertyErrorf("dictionary",
- "Fuzzer dictionary %q does not have '.dict' extension",
- fuzzBin.fuzzPackagedModule.Dictionary.String())
- }
- }
-
- if fuzzBin.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
- configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
- android.WriteFileRule(ctx, configPath, fuzzBin.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
- fuzzBin.fuzzPackagedModule.Config = configPath
- }
+ fuzzBin.fuzzPackagedModule = PackageFuzzModule(ctx, fuzzBin.fuzzPackagedModule, pctx)
// Grab the list of required shared libraries.
fuzzBin.sharedLibraries, _ = CollectAllSharedDependencies(ctx)
for _, lib := range fuzzBin.sharedLibraries {
fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
- sharedLibraryInstallLocation(
+ SharedLibraryInstallLocation(
lib, ctx.Host(), installBase, ctx.Arch().ArchType.String()))
// Also add the dependency on the shared library symbols dir.
if !ctx.Host() {
fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
- sharedLibrarySymbolsInstallLocation(lib, installBase, ctx.Arch().ArchType.String()))
+ SharedLibrarySymbolsInstallLocation(lib, installBase, ctx.Arch().ArchType.String()))
}
}
}
+func PackageFuzzModule(ctx android.ModuleContext, fuzzPackagedModule fuzz.FuzzPackagedModule, pctx android.PackageContext) fuzz.FuzzPackagedModule {
+ fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Corpus)
+ builder := android.NewRuleBuilder(pctx, ctx)
+ intermediateDir := android.PathForModuleOut(ctx, "corpus")
+ for _, entry := range fuzzPackagedModule.Corpus {
+ builder.Command().Text("cp").
+ Input(entry).
+ Output(intermediateDir.Join(ctx, entry.Base()))
+ }
+ builder.Build("copy_corpus", "copy corpus")
+ fuzzPackagedModule.CorpusIntermediateDir = intermediateDir
+
+ fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Data)
+ builder = android.NewRuleBuilder(pctx, ctx)
+ intermediateDir = android.PathForModuleOut(ctx, "data")
+ for _, entry := range fuzzPackagedModule.Data {
+ builder.Command().Text("cp").
+ Input(entry).
+ Output(intermediateDir.Join(ctx, entry.Rel()))
+ }
+ builder.Build("copy_data", "copy data")
+ fuzzPackagedModule.DataIntermediateDir = intermediateDir
+
+ if fuzzPackagedModule.FuzzProperties.Dictionary != nil {
+ fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzzPackagedModule.FuzzProperties.Dictionary)
+ if fuzzPackagedModule.Dictionary.Ext() != ".dict" {
+ ctx.PropertyErrorf("dictionary",
+ "Fuzzer dictionary %q does not have '.dict' extension",
+ fuzzPackagedModule.Dictionary.String())
+ }
+ }
+
+ if fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
+ configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
+ android.WriteFileRule(ctx, configPath, fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
+ fuzzPackagedModule.Config = configPath
+ }
+ return fuzzPackagedModule
+}
+
func NewFuzzer(hod android.HostOrDeviceSupported) *Module {
module, binary := newBinary(hod, false)
baseInstallerPath := "fuzz"
@@ -344,7 +349,7 @@
// Responsible for generating GNU Make rules that package fuzz targets into
// their architecture & target/host specific zip file.
-type ccFuzzPackager struct {
+type ccRustFuzzPackager struct {
fuzz.FuzzPackager
fuzzPackagingArchModules string
fuzzTargetSharedDepsInstallPairs string
@@ -353,7 +358,7 @@
func fuzzPackagingFactory() android.Singleton {
- fuzzPackager := &ccFuzzPackager{
+ fuzzPackager := &ccRustFuzzPackager{
fuzzPackagingArchModules: "SOONG_FUZZ_PACKAGING_ARCH_MODULES",
fuzzTargetSharedDepsInstallPairs: "FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
allFuzzTargetsName: "ALL_FUZZ_TARGETS",
@@ -361,7 +366,7 @@
return fuzzPackager
}
-func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
+func (s *ccRustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
// Map between each architecture + host/device combination, and the files that
// need to be packaged (in the tuple of {source file, destination folder in
// archive}).
@@ -376,19 +381,18 @@
sharedLibraryInstalled := make(map[string]bool)
ctx.VisitAllModules(func(module android.Module) {
- ccModule, ok := module.(*Module)
- if !ok || ccModule.Properties.PreventInstall {
+ ccModule, ok := module.(LinkableInterface)
+ if !ok || ccModule.PreventInstall() {
return
}
// Discard non-fuzz targets.
- if ok := fuzz.IsValid(ccModule.FuzzModule); !ok {
+ if ok := fuzz.IsValid(ccModule.FuzzModuleStruct()); !ok {
return
}
sharedLibsInstallDirPrefix := "lib"
- fuzzModule, ok := ccModule.compiler.(*fuzzBinary)
- if !ok {
+ if !ccModule.IsFuzzModule() {
return
}
@@ -399,12 +403,12 @@
fpm := fuzz.FuzzPackagedModule{}
if ok {
- fpm = fuzzModule.fuzzPackagedModule
+ fpm = ccModule.FuzzPackagedModule()
}
intermediatePath := "fuzz"
- archString := ccModule.Arch().ArchType.String()
+ archString := ccModule.Target().Arch.ArchType.String()
archDir := android.PathForIntermediates(ctx, intermediatePath, hostOrTargetString, archString)
archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
@@ -415,7 +419,7 @@
files = s.PackageArtifacts(ctx, module, fpm, archDir, builder)
// Package shared libraries
- files = append(files, GetSharedLibsToZip(fuzzModule.sharedLibraries, ccModule, &s.FuzzPackager, archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...)
+ files = append(files, GetSharedLibsToZip(ccModule.FuzzSharedLibraries(), ccModule, &s.FuzzPackager, archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...)
// The executable.
files = append(files, fuzz.FileToZip{android.OutputFileForModule(ctx, ccModule, "unstripped"), ""})
@@ -429,7 +433,7 @@
s.CreateFuzzPackage(ctx, archDirs, fuzz.Cc, pctx)
}
-func (s *ccFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
+func (s *ccRustFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
packages := s.Packages.Strings()
sort.Strings(packages)
sort.Strings(s.FuzzPackager.SharedLibInstallStrings)
@@ -460,7 +464,7 @@
// For each architecture-specific shared library dependency, we need to
// install it to the output directory. Setup the install destination here,
// which will be used by $(copy-many-files) in the Make backend.
- installDestination := sharedLibraryInstallLocation(
+ installDestination := SharedLibraryInstallLocation(
library, module.Host(), fuzzDir, archString)
if (*sharedLibraryInstalled)[installDestination] {
continue
@@ -479,7 +483,7 @@
// we want symbolization tools (like `stack`) to be able to find the symbols
// in $ANDROID_PRODUCT_OUT/symbols automagically.
if !module.Host() {
- symbolsInstallDestination := sharedLibrarySymbolsInstallLocation(library, fuzzDir, archString)
+ symbolsInstallDestination := SharedLibrarySymbolsInstallLocation(library, fuzzDir, archString)
symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$")
s.SharedLibInstallStrings = append(s.SharedLibInstallStrings,
library.String()+":"+symbolsInstallDestination)
diff --git a/cc/library.go b/cc/library.go
index b644728..9421007 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -845,7 +845,11 @@
ctx.ModuleErrorf("expected exactly one root archive file for '%s', but got %s", label, rootStaticArchives)
return
}
- outputFilePath := android.PathForBazelOut(ctx, rootStaticArchives[0])
+ var outputFilePath android.Path = android.PathForBazelOut(ctx, rootStaticArchives[0])
+ if len(ccInfo.TidyFiles) > 0 {
+ handler.module.tidyFiles = android.PathsForBazelOut(ctx, ccInfo.TidyFiles)
+ outputFilePath = android.AttachValidationActions(ctx, outputFilePath, handler.module.tidyFiles)
+ }
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
objPaths := ccInfo.CcObjectFiles
@@ -881,9 +885,13 @@
ctx.ModuleErrorf("expected exactly one root dynamic library file for '%s', but got %s", label, rootDynamicLibraries)
return
}
- outputFilePath := android.PathForBazelOut(ctx, rootDynamicLibraries[0])
- handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
+ var outputFilePath android.Path = android.PathForBazelOut(ctx, rootDynamicLibraries[0])
+ if len(ccInfo.TidyFiles) > 0 {
+ handler.module.tidyFiles = android.PathsForBazelOut(ctx, ccInfo.TidyFiles)
+ outputFilePath = android.AttachValidationActions(ctx, outputFilePath, handler.module.tidyFiles)
+ }
+ handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
handler.module.linker.(*libraryDecorator).unstrippedOutputFile = android.PathForBazelOut(ctx, ccInfo.UnstrippedOutput)
var tocFile android.OptionalPath
diff --git a/cc/library_headers.go b/cc/library_headers.go
index 6440ee2..32ea1d4 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -76,7 +76,11 @@
return
}
- outputPath := android.PathForBazelOut(ctx, outputPaths[0])
+ var outputPath android.Path = android.PathForBazelOut(ctx, outputPaths[0])
+ if len(ccInfo.TidyFiles) > 0 {
+ h.module.tidyFiles = android.PathsForBazelOut(ctx, ccInfo.TidyFiles)
+ outputPath = android.AttachValidationActions(ctx, outputPath, h.module.tidyFiles)
+ }
h.module.outputFile = android.OptionalPathForPath(outputPath)
// HeaderLibraryInfo is an empty struct to indicate to dependencies that this is a header library
diff --git a/cc/library_test.go b/cc/library_test.go
index dab5bb8..de3db99 100644
--- a/cc/library_test.go
+++ b/cc/library_test.go
@@ -308,6 +308,75 @@
android.AssertPathsRelativeToTopEquals(t, "deps", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.Deps)
}
+func TestCcLibraryWithBazelValidations(t *testing.T) {
+ t.Parallel()
+ bp := `
+cc_library {
+ name: "foo",
+ srcs: ["foo.cc"],
+ bazel_module: { label: "//foo/bar:bar" },
+ tidy: true,
+}`
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: "outputbase",
+ LabelToCcInfo: map[string]cquery.CcInfo{
+ "//foo/bar:bar": cquery.CcInfo{
+ CcObjectFiles: []string{"foo.o"},
+ Includes: []string{"include"},
+ SystemIncludes: []string{"system_include"},
+ Headers: []string{"foo.h"},
+ RootDynamicLibraries: []string{"foo.so"},
+ UnstrippedOutput: "foo_unstripped.so",
+ },
+ "//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{
+ CcObjectFiles: []string{"foo.o"},
+ Includes: []string{"include"},
+ SystemIncludes: []string{"system_include"},
+ Headers: []string{"foo.h"},
+ RootStaticArchives: []string{"foo.a"},
+ TidyFiles: []string{"foo.c.tidy"},
+ },
+ },
+ }
+ ctx := android.GroupFixturePreparers(
+ prepareForCcTest,
+ android.FixtureMergeEnv(map[string]string{
+ "ALLOW_LOCAL_TIDY_TRUE": "1",
+ }),
+ ).RunTestWithConfig(t, config).TestContext
+
+ staticFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_static").Module()
+ outputFiles, err := staticFoo.(android.OutputFileProducer).OutputFiles("")
+ if err != nil {
+ t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
+ }
+
+ expectedOutputFiles := []string{"out/soong/.intermediates/foo/android_arm_armv7-a-neon_static/validated/foo.a"}
+ android.AssertPathsRelativeToTopEquals(t, "output files", expectedOutputFiles, outputFiles)
+
+ flagExporter := ctx.ModuleProvider(staticFoo, FlagExporterInfoProvider).(FlagExporterInfo)
+ android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs)
+ android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs)
+ android.AssertPathsRelativeToTopEquals(t, "exported headers", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.GeneratedHeaders)
+ android.AssertPathsRelativeToTopEquals(t, "deps", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.Deps)
+
+ sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
+ outputFiles, err = sharedFoo.(android.OutputFileProducer).OutputFiles("")
+ if err != nil {
+ t.Errorf("Unexpected error getting cc_library outputfiles %s", err)
+ }
+ expectedOutputFiles = []string{"outputbase/execroot/__main__/foo.so"}
+ android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
+
+ android.AssertStringEquals(t, "unstripped shared library", "outputbase/execroot/__main__/foo_unstripped.so", sharedFoo.(*Module).linker.unstrippedOutputFilePath().String())
+ flagExporter = ctx.ModuleProvider(sharedFoo, FlagExporterInfoProvider).(FlagExporterInfo)
+ android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs)
+ android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs)
+ android.AssertPathsRelativeToTopEquals(t, "exported headers", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.GeneratedHeaders)
+ android.AssertPathsRelativeToTopEquals(t, "deps", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.Deps)
+}
+
func TestLibraryVersionScript(t *testing.T) {
t.Parallel()
result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, `
@@ -344,6 +413,59 @@
}
+func TestCcLibrarySharedWithBazelValidations(t *testing.T) {
+ t.Parallel()
+ bp := `
+cc_library_shared {
+ name: "foo",
+ srcs: ["foo.cc"],
+ bazel_module: { label: "//foo/bar:bar" },
+ tidy: true,
+}`
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: "outputbase",
+ LabelToCcInfo: map[string]cquery.CcInfo{
+ "//foo/bar:bar": cquery.CcInfo{
+ CcObjectFiles: []string{"foo.o"},
+ Includes: []string{"include"},
+ SystemIncludes: []string{"system_include"},
+ RootDynamicLibraries: []string{"foo.so"},
+ TocFile: "foo.so.toc",
+ TidyFiles: []string{"foo.c.tidy"},
+ },
+ },
+ }
+ ctx := android.GroupFixturePreparers(
+ prepareForCcTest,
+ android.FixtureMergeEnv(map[string]string{
+ "ALLOW_LOCAL_TIDY_TRUE": "1",
+ }),
+ ).RunTestWithConfig(t, config).TestContext
+
+ sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
+ producer := sharedFoo.(android.OutputFileProducer)
+ outputFiles, err := producer.OutputFiles("")
+ if err != nil {
+ t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
+ }
+ expectedOutputFiles := []string{"out/soong/.intermediates/foo/android_arm_armv7-a-neon_shared/validated/foo.so"}
+ android.AssertPathsRelativeToTopEquals(t, "output files", expectedOutputFiles, outputFiles)
+
+ tocFilePath := sharedFoo.(*Module).Toc()
+ if !tocFilePath.Valid() {
+ t.Errorf("Invalid tocFilePath: %s", tocFilePath)
+ }
+ tocFile := tocFilePath.Path()
+ expectedToc := "outputbase/execroot/__main__/foo.so.toc"
+ android.AssertStringEquals(t, "toc file", expectedToc, tocFile.String())
+
+ entries := android.AndroidMkEntriesForTest(t, ctx, sharedFoo)[0]
+ expectedFlags := []string{"-Ioutputbase/execroot/__main__/include", "-isystem outputbase/execroot/__main__/system_include"}
+ gotFlags := entries.EntryMap["LOCAL_EXPORT_CFLAGS"]
+ android.AssertDeepEquals(t, "androidmk exported cflags", expectedFlags, gotFlags)
+}
+
func TestCcLibrarySharedWithBazel(t *testing.T) {
t.Parallel()
bp := `
diff --git a/cc/linkable.go b/cc/linkable.go
index 0522fc6..9578807 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -3,6 +3,7 @@
import (
"android/soong/android"
"android/soong/bazel/cquery"
+ "android/soong/fuzz"
"android/soong/snapshot"
"github.com/google/blueprint"
@@ -120,6 +121,17 @@
IsPrebuilt() bool
Toc() android.OptionalPath
+ // IsFuzzModule returns true if this a *_fuzz module.
+ IsFuzzModule() bool
+
+ // FuzzPackagedModule returns the fuzz.FuzzPackagedModule for this module.
+ // Expects that IsFuzzModule returns true.
+ FuzzPackagedModule() fuzz.FuzzPackagedModule
+
+ // FuzzSharedLibraries returns the shared library dependencies for this module.
+ // Expects that IsFuzzModule returns true.
+ FuzzSharedLibraries() android.Paths
+
Device() bool
Host() bool
@@ -256,6 +268,9 @@
// Partition returns the partition string for this module.
Partition() string
+
+ // FuzzModule returns the fuzz.FuzzModule associated with the module.
+ FuzzModuleStruct() fuzz.FuzzModule
}
var (
diff --git a/cc/lto_test.go b/cc/lto_test.go
index fbd91be..ff2eddc 100644
--- a/cc/lto_test.go
+++ b/cc/lto_test.go
@@ -15,10 +15,11 @@
package cc
import (
- "android/soong/android"
"strings"
"testing"
+ "android/soong/android"
+
"github.com/google/blueprint"
)
@@ -177,3 +178,35 @@
t.Errorf("'baz' expected to have flags %q, but got %q", w, libFooCFlags)
}
}
+
+func TestLtoDisabledButEnabledForArch(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library {
+ name: "libfoo",
+ srcs: ["foo.c"],
+ host_supported:true,
+ lto: {
+ never: true,
+ },
+ target: {
+ android: {
+ lto: {
+ never: false,
+ thin: true,
+ },
+ },
+ },
+ }`
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ ).RunTestWithBp(t, bp)
+
+ libFooWithLto := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld")
+ libFooWithoutLto := result.ModuleForTests("libfoo", "linux_glibc_x86_64_shared").Rule("ld")
+
+ android.AssertStringDoesContain(t, "missing flag for LTO in variant that expects it",
+ libFooWithLto.Args["ldFlags"], "-flto=thin")
+ android.AssertStringDoesNotContain(t, "got flag for LTO in variant that doesn't expect it",
+ libFooWithoutLto.Args["ldFlags"], "-flto=thin")
+}
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 9e62bf8..03a600a 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -488,13 +488,17 @@
return true
}
- out := android.PathForBazelOut(ctx, staticLibs[0])
- h.module.outputFile = android.OptionalPathForPath(out)
+ var outputPath android.Path = android.PathForBazelOut(ctx, staticLibs[0])
+ if len(ccInfo.TidyFiles) > 0 {
+ h.module.tidyFiles = android.PathsForBazelOut(ctx, ccInfo.TidyFiles)
+ outputPath = android.AttachValidationActions(ctx, outputPath, h.module.tidyFiles)
+ }
- depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(out).Build()
+ h.module.outputFile = android.OptionalPathForPath(outputPath)
+
+ depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(outputPath).Build()
ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
- StaticLibrary: out,
-
+ StaticLibrary: outputPath,
TransitiveStaticLibrariesForOrdering: depSet,
})
@@ -518,21 +522,26 @@
return true
}
- out := android.PathForBazelOut(ctx, sharedLibs[0])
- h.module.outputFile = android.OptionalPathForPath(out)
+ var outputPath android.Path = android.PathForBazelOut(ctx, sharedLibs[0])
+ if len(ccInfo.TidyFiles) > 0 {
+ h.module.tidyFiles = android.PathsForBazelOut(ctx, ccInfo.TidyFiles)
+ outputPath = android.AttachValidationActions(ctx, outputPath, h.module.tidyFiles)
+ }
+
+ h.module.outputFile = android.OptionalPathForPath(outputPath)
// FIXME(b/214600441): We don't yet strip prebuilt shared libraries
- h.library.unstrippedOutputFile = out
+ h.library.unstrippedOutputFile = outputPath
var toc android.Path
if len(ccInfo.TocFile) > 0 {
toc = android.PathForBazelOut(ctx, ccInfo.TocFile)
} else {
- toc = out // Just reuse `out` so ninja still gets an input but won't matter
+ toc = outputPath // Just reuse `out` so ninja still gets an input but won't matter
}
info := SharedLibraryInfo{
- SharedLibrary: out,
+ SharedLibrary: outputPath,
TableOfContents: android.OptionalPathForPath(toc),
Target: ctx.Target(),
}
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 95fa99e..405680c 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -443,6 +443,75 @@
expectedStaticOutputFiles, staticOutputFiles.Strings())
}
+func TestPrebuiltLibraryWithBazelValidations(t *testing.T) {
+ const bp = `
+cc_prebuilt_library {
+ name: "foo",
+ shared: {
+ srcs: ["foo.so"],
+ },
+ static: {
+ srcs: ["foo.a"],
+ },
+ bazel_module: { label: "//foo/bar:bar" },
+ tidy: true,
+}`
+ outBaseDir := "outputbase"
+ result := android.GroupFixturePreparers(
+ prepareForPrebuiltTest,
+ android.FixtureMergeEnv(map[string]string{
+ "ALLOW_LOCAL_TIDY_TRUE": "1",
+ }),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: outBaseDir,
+ LabelToCcInfo: map[string]cquery.CcInfo{
+ "//foo/bar:bar": cquery.CcInfo{
+ CcSharedLibraryFiles: []string{"foo.so"},
+ TidyFiles: []string{"foo.c.tidy"},
+ },
+ "//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{
+ CcStaticLibraryFiles: []string{"foo.a"},
+ TidyFiles: []string{"foo.c.tidy"},
+ },
+ },
+ }
+ }),
+ ).RunTestWithBp(t, bp)
+ sharedFoo := result.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
+
+ expectedOutputFile := "out/soong/.intermediates/foo/android_arm_armv7-a-neon_shared/validated/foo.so"
+ sharedInfo := result.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
+ android.AssertPathRelativeToTopEquals(t,
+ "prebuilt library shared target path did not exist or did not match expected. If the base path is what does not match, it is likely that Soong built this module instead of Bazel.",
+ expectedOutputFile, sharedInfo.SharedLibrary)
+
+ outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
+ if err != nil {
+ t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
+ }
+ expectedOutputFiles := []string{expectedOutputFile}
+ android.AssertPathsRelativeToTopEquals(t,
+ "prebuilt library shared target output files did not match expected.",
+ expectedOutputFiles, outputFiles)
+
+ staticFoo := result.ModuleForTests("foo", "android_arm_armv7-a-neon_static").Module()
+ staticInfo := result.ModuleProvider(staticFoo, StaticLibraryInfoProvider).(StaticLibraryInfo)
+ expectedStaticOutputFile := "out/soong/.intermediates/foo/android_arm_armv7-a-neon_static/validated/foo.a"
+ android.AssertPathRelativeToTopEquals(t,
+ "prebuilt library static target path did not exist or did not match expected. If the base path is what does not match, it is likely that Soong built this module instead of Bazel.",
+ expectedStaticOutputFile, staticInfo.StaticLibrary)
+
+ staticOutputFiles, err := staticFoo.(android.OutputFileProducer).OutputFiles("")
+ if err != nil {
+ t.Errorf("Unexpected error getting cc_object staticOutputFiles %s", err)
+ }
+ expectedStaticOutputFiles := []string{expectedStaticOutputFile}
+ android.AssertPathsRelativeToTopEquals(t,
+ "prebuilt library static target output files did not match expected.",
+ expectedStaticOutputFiles, staticOutputFiles)
+}
+
func TestPrebuiltLibraryWithBazelStaticDisabled(t *testing.T) {
const bp = `
cc_prebuilt_library {
diff --git a/cc/stl.go b/cc/stl.go
index 6353a4a..f1433ef 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -38,9 +38,9 @@
func getNdkStlFamilyAndLinkType(m LinkableInterface) (string, string) {
stl := m.SelectedStl()
switch stl {
- case "ndk_libc++_shared":
+ case "ndk_libc++_shared", "libc++":
return "libc++", "shared"
- case "ndk_libc++_static":
+ case "ndk_libc++_static", "libc++_static":
return "libc++", "static"
case "ndk_system":
return "system", "shared"
@@ -80,7 +80,8 @@
return ""
}
s = deduplicateStlInput(s)
- if ctx.useSdk() && ctx.Device() {
+ archHasNDKStl := ctx.Arch().ArchType != android.Riscv64
+ if ctx.useSdk() && ctx.Device() && archHasNDKStl {
switch s {
case "", "system":
return "ndk_system"
diff --git a/cc/test.go b/cc/test.go
index 5c4d548..27de06b 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -649,7 +649,11 @@
return
}
- outputFilePath := android.PathForBazelOut(ctx, info.OutputFile)
+ var outputFilePath android.Path = android.PathForBazelOut(ctx, info.OutputFile)
+ if len(info.TidyFiles) > 0 {
+ handler.module.tidyFiles = android.PathsForBazelOut(ctx, info.TidyFiles)
+ outputFilePath = android.AttachValidationActions(ctx, outputFilePath, handler.module.tidyFiles)
+ }
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
handler.module.linker.(*testBinary).unstrippedOutputFile = android.PathForBazelOut(ctx, info.UnstrippedOutput)
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 29a6f95..c005f7c 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -447,6 +447,7 @@
"bazel-genfiles",
"bazel-out",
"bazel-testlogs",
+ "bazel-workspace",
"bazel-" + filepath.Base(topDir),
}
}
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 661bd5d..fd718c2 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -218,12 +218,12 @@
trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
- c.run(buildCtx, config, args)
-
- defer met.Dump(soongMetricsFile)
if !config.SkipMetricsUpload() {
defer build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, bazelProfileFile, bazelMetricsFile, metricsFiles...)
}
+ defer met.Dump(soongMetricsFile)
+
+ c.run(buildCtx, config, args)
}
diff --git a/compliance/OWNERS b/compliance/OWNERS
new file mode 100644
index 0000000..f52e201
--- /dev/null
+++ b/compliance/OWNERS
@@ -0,0 +1,8 @@
+# OSEP Build
+bbadour@google.com
+kanouche@google.com
+napier@google.com
+
+# Open Source Compliance Tools
+rtp@google.com
+austinyuan@google.com
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index e3404a5..a590c72 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -101,6 +101,10 @@
}
func dexpreoptDisabled(ctx android.PathContext, global *GlobalConfig, module *ModuleConfig) bool {
+ if ctx.Config().UnbundledBuild() {
+ return true
+ }
+
if contains(global.DisablePreoptModules, module.Name) {
return true
}
diff --git a/java/app.go b/java/app.go
index dc28ef8..1731970 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1532,7 +1532,6 @@
appAttrs.javaCommonAttributes = commonAttrs
appAttrs.bazelAapt = aapt
appAttrs.Deps = deps
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: a.Name()}, appAttrs)
} else {
ktName := a.Name() + "_kt"
commonAttrs.Common_srcs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, a.properties.Common_srcs))
@@ -1553,11 +1552,12 @@
appAttrs.bazelAapt = &bazelAapt{Manifest: aapt.Manifest}
appAttrs.Deps = bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + ktName})
- ctx.CreateBazelTargetModule(
- props,
- android.CommonAttributes{Name: a.Name()},
- appAttrs,
- )
}
+ ctx.CreateBazelTargetModule(
+ props,
+ android.CommonAttributes{Name: a.Name()},
+ appAttrs,
+ )
+
}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 77cbe9c..c4b0af4 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -27,6 +27,7 @@
dexpreoptDisabled(ctx android.BaseModuleContext) bool
DexpreoptBuiltInstalledForApex() []dexpreopterInstall
AndroidMkEntriesForApex() []android.AndroidMkEntries
+ ProfilePathOnHost() android.Path
}
type dexpreopterInstall struct {
@@ -103,6 +104,9 @@
// - Dexpreopt post-processing (using dexpreopt artifacts from a prebuilt system image to incrementally
// dexpreopt another partition).
configPath android.WritablePath
+
+ // The path to the profile on host.
+ profilePathOnHost android.Path
}
type DexpreoptProperties struct {
@@ -180,9 +184,8 @@
isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx))
if isApexVariant(ctx) {
- // Don't preopt APEX variant module unless the module is an APEX system server jar and we are
- // building the entire system image.
- if !isApexSystemServerJar || ctx.Config().UnbundledBuild() {
+ // Don't preopt APEX variant module unless the module is an APEX system server jar.
+ if !isApexSystemServerJar {
return true
}
} else {
@@ -368,21 +371,29 @@
installBase := filepath.Base(install.To)
arch := filepath.Base(installDir)
installPath := android.PathForModuleInPartitionInstall(ctx, "", installDir)
+ isProfile := strings.HasSuffix(installBase, ".prof")
+
+ if isProfile {
+ d.profilePathOnHost = install.From
+ }
if isApexSystemServerJar {
- // APEX variants of java libraries are hidden from Make, so their dexpreopt
- // outputs need special handling. Currently, for APEX variants of java
- // libraries, only those in the system server classpath are handled here.
- // Preopting of boot classpath jars in the ART APEX are handled in
- // java/dexpreopt_bootjars.go, and other APEX jars are not preopted.
- // The installs will be handled by Make as sub-modules of the java library.
- d.builtInstalledForApex = append(d.builtInstalledForApex, dexpreopterInstall{
- name: arch + "-" + installBase,
- moduleName: moduleName(ctx),
- outputPathOnHost: install.From,
- installDirOnDevice: installPath,
- installFileOnDevice: installBase,
- })
+ // Profiles are handled separately because they are installed into the APEX.
+ if !isProfile {
+ // APEX variants of java libraries are hidden from Make, so their dexpreopt
+ // outputs need special handling. Currently, for APEX variants of java
+ // libraries, only those in the system server classpath are handled here.
+ // Preopting of boot classpath jars in the ART APEX are handled in
+ // java/dexpreopt_bootjars.go, and other APEX jars are not preopted.
+ // The installs will be handled by Make as sub-modules of the java library.
+ d.builtInstalledForApex = append(d.builtInstalledForApex, dexpreopterInstall{
+ name: arch + "-" + installBase,
+ moduleName: moduleName(ctx),
+ outputPathOnHost: install.From,
+ installDirOnDevice: installPath,
+ installFileOnDevice: installBase,
+ })
+ }
} else if !d.preventInstall {
ctx.InstallFile(installPath, installBase, install.From)
}
@@ -404,3 +415,7 @@
}
return entries
}
+
+func (d *dexpreopter) ProfilePathOnHost() android.Path {
+ return d.profilePathOnHost
+}
diff --git a/java/java.go b/java/java.go
index 659f98a..874f935 100644
--- a/java/java.go
+++ b/java/java.go
@@ -517,14 +517,8 @@
return normalizeJavaVersion(ctx, javaVersion)
} else if ctx.Device() {
return defaultJavaLanguageVersion(ctx, sdkContext.SdkVersion(ctx))
- } else if ctx.Config().TargetsJava17() {
- // Temporary experimental flag to be able to try and build with
- // java version 17 options. The flag, if used, just sets Java
- // 17 as the default version, leaving any components that
- // target an older version intact.
- return JAVA_VERSION_17
} else {
- return JAVA_VERSION_11
+ return JAVA_VERSION_17
}
}
diff --git a/java/sdk.go b/java/sdk.go
index b0da5af..10ae3f6 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -57,14 +57,10 @@
return JAVA_VERSION_8
} else if sdk.FinalOrFutureInt() <= 31 {
return JAVA_VERSION_9
- } else if ctx.Config().TargetsJava17() {
- // Temporary experimental flag to be able to try and build with
- // java version 17 options. The flag, if used, just sets Java
- // 17 as the default version, leaving any components that
- // target an older version intact.
- return JAVA_VERSION_17
- } else {
+ } else if sdk.FinalOrFutureInt() <= 32 {
return JAVA_VERSION_11
+ } else {
+ return JAVA_VERSION_17
}
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index b872365..a2295f4 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1749,7 +1749,7 @@
}
}
- mctx.CreateModule(DroidstubsFactory, &props)
+ mctx.CreateModule(DroidstubsFactory, &props).(*Droidstubs).CallHookIfAvailable(mctx)
}
func (module *SdkLibrary) compareAgainstLatestApi(apiScope *apiScope) bool {
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 210bfc3..1d0c13d 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -120,6 +120,7 @@
result.ModuleForTests(apiScopePublic.stubsSourceModuleName("foo"), "android_common")
result.ModuleForTests(apiScopeSystem.stubsSourceModuleName("foo"), "android_common")
result.ModuleForTests(apiScopeTest.stubsSourceModuleName("foo"), "android_common")
+ result.ModuleForTests(apiScopePublic.stubsSourceModuleName("foo")+".api.contribution", "")
result.ModuleForTests("foo"+sdkXmlFileSuffix, "android_common")
result.ModuleForTests("foo.api.public.28", "")
result.ModuleForTests("foo.api.system.28", "")
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 32c746e..20e9919 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -205,8 +205,8 @@
})
}
-func (fuzz *fuzzDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
- ctx.SubAndroidMk(entries, fuzz.binaryDecorator)
+func (fuzz *fuzzDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
+ ctx.SubAndroidMk(ret, fuzz.binaryDecorator)
var fuzzFiles []string
for _, d := range fuzz.fuzzPackagedModule.Corpus {
@@ -229,11 +229,14 @@
filepath.Dir(fuzz.fuzzPackagedModule.Config.String())+":config.json")
}
- entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext,
+ ret.ExtraEntries = append(ret.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext,
entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_IS_FUZZ_TARGET", true)
if len(fuzzFiles) > 0 {
entries.AddStrings("LOCAL_TEST_DATA", fuzzFiles...)
}
+ if fuzz.installedSharedDeps != nil {
+ entries.AddStrings("LOCAL_FUZZ_INSTALLED_SHARED_DEPS", fuzz.installedSharedDeps...)
+ }
})
}
diff --git a/rust/bindgen.go b/rust/bindgen.go
index e81ec6b..878f896 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -52,7 +52,7 @@
if ctx.Config().UseHostMusl() {
return "musl/lib/"
} else {
- return "lib64/"
+ return "lib/"
}
})
_ = pctx.SourcePathVariable("bindgenClang",
diff --git a/rust/config/x86_linux_bionic_host.go b/rust/config/x86_linux_bionic_host.go
index b1a2c17..79c40ce 100644
--- a/rust/config/x86_linux_bionic_host.go
+++ b/rust/config/x86_linux_bionic_host.go
@@ -21,7 +21,9 @@
)
var (
- LinuxBionicRustFlags = []string{}
+ LinuxBionicRustFlags = []string{
+ "-C panic=abort",
+ }
LinuxBionicRustLinkFlags = []string{
"-B${cc_config.ClangBin}",
"-fuse-ld=lld",
diff --git a/rust/fuzz.go b/rust/fuzz.go
index 6faf55c..d7e7ddf 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -16,8 +16,6 @@
import (
"path/filepath"
- "sort"
- "strings"
"android/soong/android"
"android/soong/cc"
@@ -27,14 +25,14 @@
func init() {
android.RegisterModuleType("rust_fuzz", RustFuzzFactory)
- android.RegisterSingletonType("rust_fuzz_packaging", rustFuzzPackagingFactory)
}
type fuzzDecorator struct {
*binaryDecorator
- fuzzPackagedModule fuzz.FuzzPackagedModule
- sharedLibraries android.Paths
+ fuzzPackagedModule fuzz.FuzzPackagedModule
+ sharedLibraries android.Paths
+ installedSharedDeps []string
}
var _ compiler = (*fuzzDecorator)(nil)
@@ -64,9 +62,14 @@
flags = fuzzer.binaryDecorator.compilerFlags(ctx, flags)
// `../lib` for installed fuzz targets (both host and device), and `./lib` for fuzz target packages.
- flags.LinkFlags = append(flags.LinkFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
flags.LinkFlags = append(flags.LinkFlags, `-Wl,-rpath,\$$ORIGIN/lib`)
+ if ctx.InstallInVendor() {
+ flags.LinkFlags = append(flags.LinkFlags, `-Wl,-rpath,\$$ORIGIN/../../lib`)
+ } else {
+ flags.LinkFlags = append(flags.LinkFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
+
+ }
return flags
}
@@ -88,10 +91,8 @@
}
func (fuzzer *fuzzDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
- out := fuzzer.binaryDecorator.compile(ctx, flags, deps)
- // Grab the list of required shared libraries.
- fuzzer.sharedLibraries, _ = cc.CollectAllSharedDependencies(ctx)
+ out := fuzzer.binaryDecorator.compile(ctx, flags, deps)
return out
}
@@ -104,83 +105,6 @@
return rlibAutoDep
}
-// Responsible for generating GNU Make rules that package fuzz targets into
-// their architecture & target/host specific zip file.
-type rustFuzzPackager struct {
- fuzz.FuzzPackager
-}
-
-func rustFuzzPackagingFactory() android.Singleton {
- return &rustFuzzPackager{}
-}
-
-func (s *rustFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
- // Map between each architecture + host/device combination.
- archDirs := make(map[fuzz.ArchOs][]fuzz.FileToZip)
-
- // List of individual fuzz targets.
- s.FuzzTargets = make(map[string]bool)
-
- // Map tracking whether each shared library has an install rule to avoid duplicate install rules from
- // multiple fuzzers that depend on the same shared library.
- sharedLibraryInstalled := make(map[string]bool)
-
- ctx.VisitAllModules(func(module android.Module) {
- // Discard non-fuzz targets.
- rustModule, ok := module.(*Module)
- if !ok {
- return
- }
-
- if ok := fuzz.IsValid(rustModule.FuzzModule); !ok || rustModule.Properties.PreventInstall {
- return
- }
-
- fuzzModule, ok := rustModule.compiler.(*fuzzDecorator)
- if !ok {
- return
- }
-
- hostOrTargetString := "target"
- if rustModule.Host() {
- hostOrTargetString = "host"
- }
-
- archString := rustModule.Arch().ArchType.String()
- archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
- archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
-
- var files []fuzz.FileToZip
- builder := android.NewRuleBuilder(pctx, ctx)
-
- // Package the artifacts (data, corpus, config and dictionary into a zipfile.
- files = s.PackageArtifacts(ctx, module, fuzzModule.fuzzPackagedModule, archDir, builder)
-
- // The executable.
- files = append(files, fuzz.FileToZip{rustModule.UnstrippedOutputFile(), ""})
-
- // Package shared libraries
- files = append(files, cc.GetSharedLibsToZip(fuzzModule.sharedLibraries, rustModule, &s.FuzzPackager, archString, "lib", &sharedLibraryInstalled)...)
-
- archDirs[archOs], ok = s.BuildZipFile(ctx, module, fuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
- if !ok {
- return
- }
-
- })
- s.CreateFuzzPackage(ctx, archDirs, fuzz.Rust, pctx)
-}
-
-func (s *rustFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
- packages := s.Packages.Strings()
- sort.Strings(packages)
-
- ctx.Strict("SOONG_RUST_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
-
- // Preallocate the slice of fuzz targets to minimize memory allocations.
- s.PreallocateSlice(ctx, "ALL_RUST_FUZZ_TARGETS")
-}
-
func (fuzz *fuzzDecorator) install(ctx ModuleContext) {
fuzz.binaryDecorator.baseCompiler.dir = filepath.Join(
"fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
@@ -188,13 +112,22 @@
"fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
fuzz.binaryDecorator.baseCompiler.install(ctx)
- if fuzz.fuzzPackagedModule.FuzzProperties.Corpus != nil {
- fuzz.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzz.fuzzPackagedModule.FuzzProperties.Corpus)
- }
- if fuzz.fuzzPackagedModule.FuzzProperties.Data != nil {
- fuzz.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzz.fuzzPackagedModule.FuzzProperties.Data)
- }
- if fuzz.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
- fuzz.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzz.fuzzPackagedModule.FuzzProperties.Dictionary)
+ fuzz.fuzzPackagedModule = cc.PackageFuzzModule(ctx, fuzz.fuzzPackagedModule, pctx)
+
+ installBase := "fuzz"
+
+ // Grab the list of required shared libraries.
+ fuzz.sharedLibraries, _ = cc.CollectAllSharedDependencies(ctx)
+
+ for _, lib := range fuzz.sharedLibraries {
+ fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
+ cc.SharedLibraryInstallLocation(
+ lib, ctx.Host(), installBase, ctx.Arch().ArchType.String()))
+
+ // Also add the dependency on the shared library symbols dir.
+ if !ctx.Host() {
+ fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
+ cc.SharedLibrarySymbolsInstallLocation(lib, installBase, ctx.Arch().ArchType.String()))
+ }
}
}
diff --git a/rust/rust.go b/rust/rust.go
index 28a300b..67e0d7c 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -208,6 +208,11 @@
}
return android.Paths{}, nil
}
+ case "unstripped":
+ if mod.compiler != nil {
+ return android.PathsIfNonNil(mod.compiler.unstrippedOutputFilePath()), nil
+ }
+ return nil, nil
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
@@ -619,6 +624,31 @@
return false
}
+func (mod *Module) IsFuzzModule() bool {
+ if _, ok := mod.compiler.(*fuzzDecorator); ok {
+ return true
+ }
+ return false
+}
+
+func (mod *Module) FuzzModuleStruct() fuzz.FuzzModule {
+ return mod.FuzzModule
+}
+
+func (mod *Module) FuzzPackagedModule() fuzz.FuzzPackagedModule {
+ if fuzzer, ok := mod.compiler.(*fuzzDecorator); ok {
+ return fuzzer.fuzzPackagedModule
+ }
+ panic(fmt.Errorf("FuzzPackagedModule called on non-fuzz module: %q", mod.BaseModuleName()))
+}
+
+func (mod *Module) FuzzSharedLibraries() android.Paths {
+ if fuzzer, ok := mod.compiler.(*fuzzDecorator); ok {
+ return fuzzer.sharedLibraries
+ }
+ panic(fmt.Errorf("FuzzSharedLibraries called on non-fuzz module: %q", mod.BaseModuleName()))
+}
+
func (mod *Module) UnstrippedOutputFile() android.Path {
if mod.compiler != nil {
return mod.compiler.unstrippedOutputFilePath()
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
index 6477dac..878b4a1 100755
--- a/tests/bp2build_bazel_test.sh
+++ b/tests/bp2build_bazel_test.sh
@@ -140,7 +140,7 @@
# NOTE: We don't actually use the extra BUILD file for anything here
run_bazel build --config=android --config=bp2build --config=ci //foo/...
- local the_answer_file="$(find -L bazel-out -name the_answer.txt)"
+ local -r the_answer_file="$(find -L bazel-out -name the_answer.txt)"
if [[ ! -f "${the_answer_file}" ]]; then
fail "Expected the_answer.txt to be generated, but was missing"
fi
@@ -156,6 +156,49 @@
eval "${_save_trap}"
}
+function test_bp2build_symlinks_files {
+ setup
+ mkdir -p foo
+ touch foo/BLANK1
+ touch foo/BLANK2
+ touch foo/F2D
+ touch foo/BUILD
+
+ run_soong bp2build
+
+ if [[ -e "./out/soong/workspace/foo/BUILD" ]]; then
+ fail "./out/soong/workspace/foo/BUILD should be omitted"
+ fi
+ for file in BLANK1 BLANK2 F2D
+ do
+ if [[ ! -L "./out/soong/workspace/foo/$file" ]]; then
+ fail "./out/soong/workspace/foo/$file should exist"
+ fi
+ done
+ local -r BLANK1_BEFORE=$(stat -c %y "./out/soong/workspace/foo/BLANK1")
+
+ rm foo/BLANK2
+ rm foo/F2D
+ mkdir foo/F2D
+ touch foo/F2D/BUILD
+
+ run_soong bp2build
+
+ if [[ -e "./out/soong/workspace/foo/BUILD" ]]; then
+ fail "./out/soong/workspace/foo/BUILD should be omitted"
+ fi
+ local -r BLANK1_AFTER=$(stat -c %y "./out/soong/workspace/foo/BLANK1")
+ if [[ "$BLANK1_AFTER" != "$BLANK1_BEFORE" ]]; then
+ fail "./out/soong/workspace/foo/BLANK1 should be untouched"
+ fi
+ if [[ -e "./out/soong/workspace/foo/BLANK2" ]]; then
+ fail "./out/soong/workspace/foo/BLANK2 should be removed"
+ fi
+ if [[ -L "./out/soong/workspace/foo/F2D" ]] || [[ ! -d "./out/soong/workspace/foo/F2D" ]]; then
+ fail "./out/soong/workspace/foo/F2D should be a dir"
+ fi
+}
+
function test_cc_correctness {
setup