diff options
52 files changed, 861 insertions, 287 deletions
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go index d320599e1..974245e2a 100644 --- a/android/allowlists/allowlists.go +++ b/android/allowlists/allowlists.go @@ -931,9 +931,6 @@ var ( "test_fips", // depends on unconverted modules: adb "timezone-host", // depends on unconverted modules: art.module.api.annotations - // '//bionic/libc:libc_bp2build_cc_library_static' is duplicated in the 'deps' attribute of rule - "toybox-static", - // aidl files not created "overlayable_policy_aidl_interface", diff --git a/android/bazel_handler.go b/android/bazel_handler.go index 5d93f06b8..4d91cc839 100644 --- a/android/bazel_handler.go +++ b/android/bazel_handler.go @@ -16,6 +16,8 @@ package android import ( "bytes" + "crypto/sha1" + "encoding/hex" "fmt" "os" "path" @@ -1222,7 +1224,11 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) { ctx.AddNinjaFileDeps(file) } + depsetHashToDepset := map[string]bazel.AqueryDepset{} + for _, depset := range ctx.Config().BazelContext.AqueryDepsets() { + depsetHashToDepset[depset.ContentHash] = depset + var outputs []Path var orderOnlies []Path for _, depsetDepHash := range depset.TransitiveDepSetHashes { @@ -1257,7 +1263,30 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) { } if len(buildStatement.Command) > 0 { rule := NewRuleBuilder(pctx, ctx) - createCommand(rule.Command(), buildStatement, executionRoot, bazelOutDir, ctx) + intermediateDir, intermediateDirHash := intermediatePathForSboxMixedBuildAction(ctx, buildStatement) + if buildStatement.ShouldRunInSbox { + // Create a rule to build the output inside a sandbox + // This will create two changes of working directory + // 1. From ANDROID_BUILD_TOP to sbox top + // 2. From sbox top to a a synthetic mixed build execution root relative to it + // Finally, the outputs will be copied to intermediateDir + rule.Sbox(intermediateDir, + PathForOutput(ctx, "mixed_build_sbox_intermediates", intermediateDirHash+".textproto")). + SandboxInputs(). + // Since we will cd to mixed build execution root, set sbox's out subdir to empty + // Without this, we will try to copy from $SBOX_SANDBOX_DIR/out/out/bazel/output/execroot/__main__/... + SetSboxOutDirDirAsEmpty() + + // Create another set of rules to copy files from the intermediate dir to mixed build execution root + for _, outputPath := range buildStatement.OutputPaths { + ctx.Build(pctx, BuildParams{ + Rule: CpIfChanged, + Input: intermediateDir.Join(ctx, executionRoot, outputPath), + Output: PathForBazelOut(ctx, outputPath), + }) + } + } + createCommand(rule.Command(), buildStatement, executionRoot, bazelOutDir, ctx, depsetHashToDepset) desc := fmt.Sprintf("%s: %s", buildStatement.Mnemonic, buildStatement.OutputPaths) rule.Build(fmt.Sprintf("bazel %d", index), desc) continue @@ -1304,10 +1333,25 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) { } } +// Returns a out dir path for a sandboxed mixed build action +func intermediatePathForSboxMixedBuildAction(ctx PathContext, statement *bazel.BuildStatement) (OutputPath, string) { + // An artifact can be generated by a single buildstatement. + // Use the hash of the first artifact to create a unique path + uniqueDir := sha1.New() + uniqueDir.Write([]byte(statement.OutputPaths[0])) + uniqueDirHashString := hex.EncodeToString(uniqueDir.Sum(nil)) + return PathForOutput(ctx, "mixed_build_sbox_intermediates", uniqueDirHashString), uniqueDirHashString +} + // Register bazel-owned build statements (obtained from the aquery invocation). -func createCommand(cmd *RuleBuilderCommand, buildStatement *bazel.BuildStatement, executionRoot string, bazelOutDir string, ctx BuilderContext) { +func createCommand(cmd *RuleBuilderCommand, buildStatement *bazel.BuildStatement, executionRoot string, bazelOutDir string, ctx BuilderContext, depsetHashToDepset map[string]bazel.AqueryDepset) { // executionRoot is the action cwd. - cmd.Text(fmt.Sprintf("cd '%s' &&", executionRoot)) + if buildStatement.ShouldRunInSbox { + // mkdir -p ensures that the directory exists when run via sbox + cmd.Text(fmt.Sprintf("mkdir -p '%s' && cd '%s' &&", executionRoot, executionRoot)) + } else { + cmd.Text(fmt.Sprintf("cd '%s' &&", executionRoot)) + } // Remove old outputs, as some actions might not rerun if the outputs are detected. if len(buildStatement.OutputPaths) > 0 { @@ -1334,14 +1378,33 @@ func createCommand(cmd *RuleBuilderCommand, buildStatement *bazel.BuildStatement } for _, outputPath := range buildStatement.OutputPaths { - cmd.ImplicitOutput(PathForBazelOut(ctx, outputPath)) + if buildStatement.ShouldRunInSbox { + // The full path has three components that get joined together + // 1. intermediate output dir that `sbox` will place the artifacts at + // 2. mixed build execution root + // 3. artifact path returned by aquery + intermediateDir, _ := intermediatePathForSboxMixedBuildAction(ctx, buildStatement) + cmd.ImplicitOutput(intermediateDir.Join(ctx, executionRoot, outputPath)) + } else { + cmd.ImplicitOutput(PathForBazelOut(ctx, outputPath)) + } + } + for _, inputPath := range buildStatement.OrderOnlyInputs { + cmd.OrderOnly(PathForBazelOut(ctx, inputPath)) } for _, inputPath := range buildStatement.InputPaths { cmd.Implicit(PathForBazelOut(ctx, inputPath)) } for _, inputDepsetHash := range buildStatement.InputDepsetHashes { - otherDepsetName := bazelDepsetName(inputDepsetHash) - cmd.Implicit(PathForPhony(ctx, otherDepsetName)) + if buildStatement.ShouldRunInSbox { + // Bazel depsets are phony targets that are used to group files. + // We need to copy the grouped files into the sandbox + ds, _ := depsetHashToDepset[inputDepsetHash] + cmd.Implicits(PathsForBazelOut(ctx, ds.DirectArtifacts)) + } else { + otherDepsetName := bazelDepsetName(inputDepsetHash) + cmd.Implicit(PathForPhony(ctx, otherDepsetName)) + } } if depfile := buildStatement.Depfile; depfile != nil { diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go index 65cd5a836..e08a4718a 100644 --- a/android/bazel_handler_test.go +++ b/android/bazel_handler_test.go @@ -181,13 +181,62 @@ func TestInvokeBazelPopulatesBuildStatements(t *testing.T) { cmd := RuleBuilderCommand{} ctx := builderContextForTests{PathContextForTesting(TestConfig("out", nil, "", nil))} - createCommand(&cmd, got[0], "test/exec_root", "test/bazel_out", ctx) + createCommand(&cmd, got[0], "test/exec_root", "test/bazel_out", ctx, map[string]bazel.AqueryDepset{}) if actual, expected := cmd.buf.String(), testCase.command; expected != actual { t.Errorf("expected: [%s], actual: [%s]", expected, actual) } } } +func TestMixedBuildSandboxedAction(t *testing.T) { + input := `{ + "artifacts": [ + { "id": 1, "path_fragment_id": 1 }, + { "id": 2, "path_fragment_id": 2 }], + "actions": [{ + "target_Id": 1, + "action_Key": "x", + "mnemonic": "x", + "arguments": ["touch", "foo"], + "input_dep_set_ids": [1], + "output_Ids": [1], + "primary_output_id": 1 + }], + "dep_set_of_files": [ + { "id": 1, "direct_artifact_ids": [1, 2] }], + "path_fragments": [ + { "id": 1, "label": "one" }, + { "id": 2, "label": "two" }] +}` + data, err := JsonToActionGraphContainer(input) + if err != nil { + t.Error(err) + } + bazelContext, _ := testBazelContext(t, map[bazelCommand]string{aqueryCmd: string(data)}) + + err = bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{}) + if err != nil { + t.Fatalf("TestMixedBuildSandboxedAction did not expect error invoking Bazel, but got %s", err) + } + + statement := bazelContext.BuildStatementsToRegister()[0] + statement.ShouldRunInSbox = true + + cmd := RuleBuilderCommand{} + ctx := builderContextForTests{PathContextForTesting(TestConfig("out", nil, "", nil))} + createCommand(&cmd, statement, "test/exec_root", "test/bazel_out", ctx, map[string]bazel.AqueryDepset{}) + // Assert that the output is generated in an intermediate directory + // fe05bcdcdc4928012781a5f1a2a77cbb5398e106 is the sha1 checksum of "one" + if actual, expected := cmd.outputs[0].String(), "out/soong/mixed_build_sbox_intermediates/fe05bcdcdc4928012781a5f1a2a77cbb5398e106/test/exec_root/one"; expected != actual { + t.Errorf("expected: [%s], actual: [%s]", expected, actual) + } + + // Assert the actual command remains unchanged inside the sandbox + if actual, expected := cmd.buf.String(), "mkdir -p 'test/exec_root' && cd 'test/exec_root' && rm -rf 'one' && touch foo"; expected != actual { + t.Errorf("expected: [%s], actual: [%s]", expected, actual) + } +} + func TestCoverageFlagsAfterInvokeBazel(t *testing.T) { testConfig.productVariables.ClangCoverage = boolPtr(true) diff --git a/android/config.go b/android/config.go index fa439625d..9cfbc9e4f 100644 --- a/android/config.go +++ b/android/config.go @@ -202,10 +202,10 @@ type VendorConfig soongconfig.SoongConfig // product configuration values are read from Kati-generated soong.variables. type config struct { // Options configurable with soong.variables - productVariables productVariables + productVariables ProductVariables // Only available on configs created by TestConfig - TestProductVariables *productVariables + TestProductVariables *ProductVariables // A specialized context object for Bazel/Soong mixed builds and migration // purposes. @@ -321,7 +321,7 @@ func loadConfig(config *config) error { // loadFromConfigFile loads and decodes configuration options from a JSON file // in the current working directory. -func loadFromConfigFile(configurable *productVariables, filename string) error { +func loadFromConfigFile(configurable *ProductVariables, filename string) error { // Try to open the file configFileReader, err := os.Open(filename) defer configFileReader.Close() @@ -373,7 +373,7 @@ func loadFromConfigFile(configurable *productVariables, filename string) error { // atomically writes the config file in case two copies of soong_build are running simultaneously // (for example, docs generation and ninja manifest generation) -func saveToConfigFile(config *productVariables, filename string) error { +func saveToConfigFile(config *ProductVariables, filename string) error { data, err := json.MarshalIndent(&config, "", " ") if err != nil { return fmt.Errorf("cannot marshal config data: %s", err.Error()) @@ -402,7 +402,7 @@ func saveToConfigFile(config *productVariables, filename string) error { return nil } -func saveToBazelConfigFile(config *productVariables, outDir string) error { +func saveToBazelConfigFile(config *ProductVariables, outDir string) error { dir := filepath.Join(outDir, bazel.SoongInjectionDirName, "product_config") err := createDirIfNonexistent(dir, os.ModePerm) if err != nil { @@ -1355,6 +1355,10 @@ func (c *config) BazelModulesForceEnabledByFlag() map[string]struct{} { return c.bazelForceEnabledModules } +func (c *config) IsVndkDeprecated() bool { + return !Bool(c.productVariables.KeepVndk) +} + func (c *deviceConfig) Arches() []Arch { var arches []Arch for _, target := range c.config.Targets[Android] { diff --git a/android/config_test.go b/android/config_test.go index 9df5288a1..7d327a27e 100644 --- a/android/config_test.go +++ b/android/config_test.go @@ -75,7 +75,7 @@ Did you mean to use an annotation of ",omitempty"? // run validateConfigAnnotations against each type that might have json annotations func TestProductConfigAnnotations(t *testing.T) { - err := validateConfigAnnotations(&productVariables{}) + err := validateConfigAnnotations(&ProductVariables{}) if err != nil { t.Errorf(err.Error()) } @@ -88,7 +88,7 @@ func TestMissingVendorConfig(t *testing.T) { } } -func verifyProductVariableMarshaling(t *testing.T, v productVariables) { +func verifyProductVariableMarshaling(t *testing.T, v ProductVariables) { dir := t.TempDir() path := filepath.Join(dir, "test.variables") err := saveToConfigFile(&v, path) @@ -96,20 +96,20 @@ func verifyProductVariableMarshaling(t *testing.T, v productVariables) { t.Errorf("Couldn't save default product config: %q", err) } - var v2 productVariables + var v2 ProductVariables err = loadFromConfigFile(&v2, path) if err != nil { t.Errorf("Couldn't load default product config: %q", err) } } func TestDefaultProductVariableMarshaling(t *testing.T) { - v := productVariables{} + v := ProductVariables{} v.SetDefaultConfig() verifyProductVariableMarshaling(t, v) } func TestBootJarsMarshaling(t *testing.T) { - v := productVariables{} + v := ProductVariables{} v.SetDefaultConfig() v.BootJars = ConfiguredJarList{ apexes: []string{"apex"}, diff --git a/android/configured_jars_test.go b/android/configured_jars_test.go index 32c3613f7..4b586e4d7 100644 --- a/android/configured_jars_test.go +++ b/android/configured_jars_test.go @@ -21,7 +21,7 @@ import ( func TestOverrideConfiguredJarLocationFor(t *testing.T) { cfg := NullConfig("", "") - cfg.productVariables = productVariables{ + cfg.productVariables = ProductVariables{ ConfiguredJarLocationOverrides: []string{ "platform:libfoo-old:com.android.foo:libfoo-new", "com.android.bar:libbar-old:platform:libbar-new", diff --git a/android/fixture.go b/android/fixture.go index dbc3bc5e0..6660afd65 100644 --- a/android/fixture.go +++ b/android/fixture.go @@ -369,7 +369,7 @@ func FixtureModifyEnv(mutator func(env map[string]string)) FixturePreparer { // Allow access to the product variables when preparing the fixture. type FixtureProductVariables struct { - *productVariables + *ProductVariables } // Modify product variables. diff --git a/android/rule_builder.go b/android/rule_builder.go index 0438eb8c7..777c1cfc3 100644 --- a/android/rule_builder.go +++ b/android/rule_builder.go @@ -53,6 +53,7 @@ type RuleBuilder struct { remoteable RemoteRuleSupports rbeParams *remoteexec.REParams outDir WritablePath + sboxOutSubDir string sboxTools bool sboxInputs bool sboxManifestPath WritablePath @@ -65,9 +66,18 @@ func NewRuleBuilder(pctx PackageContext, ctx BuilderContext) *RuleBuilder { pctx: pctx, ctx: ctx, temporariesSet: make(map[WritablePath]bool), + sboxOutSubDir: sboxOutSubDir, } } +// SetSboxOutDirDirAsEmpty sets the out subdirectory to an empty string +// This is useful for sandboxing actions that change the execution root to a path in out/ (e.g mixed builds) +// For such actions, SetSboxOutDirDirAsEmpty ensures that the path does not become $SBOX_SANDBOX_DIR/out/out/bazel/output/execroot/__main__/... +func (rb *RuleBuilder) SetSboxOutDirDirAsEmpty() *RuleBuilder { + rb.sboxOutSubDir = "" + return rb +} + // RuleBuilderInstall is a tuple of install from and to locations. type RuleBuilderInstall struct { From Path @@ -585,7 +595,7 @@ func (r *RuleBuilder) Build(name string, desc string) { for _, output := range outputs { rel := Rel(r.ctx, r.outDir.String(), output.String()) command.CopyAfter = append(command.CopyAfter, &sbox_proto.Copy{ - From: proto.String(filepath.Join(sboxOutSubDir, rel)), + From: proto.String(filepath.Join(r.sboxOutSubDir, rel)), To: proto.String(output.String()), }) } diff --git a/android/sdk_version_test.go b/android/sdk_version_test.go index ea99c4d62..30bd002c2 100644 --- a/android/sdk_version_test.go +++ b/android/sdk_version_test.go @@ -75,7 +75,7 @@ func TestSdkSpecFrom(t *testing.T) { config := NullConfig("", "") - config.productVariables = productVariables{ + config.productVariables = ProductVariables{ Platform_sdk_version: intPtr(31), Platform_sdk_codename: stringPtr("Tiramisu"), Platform_version_active_codenames: []string{"Tiramisu"}, diff --git a/android/test_config.go b/android/test_config.go index 28d9ec403..2a59d9228 100644 --- a/android/test_config.go +++ b/android/test_config.go @@ -35,7 +35,7 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string envCopy["PATH"] = os.Getenv("PATH") config := &config{ - productVariables: productVariables{ + productVariables: ProductVariables{ DeviceName: stringPtr("test_device"), DeviceProduct: stringPtr("test_product"), Platform_sdk_version: intPtr(30), diff --git a/android/util.go b/android/util.go index e17d7b213..5375373a6 100644 --- a/android/util.go +++ b/android/util.go @@ -137,19 +137,17 @@ func SortedUniqueStringValues(m interface{}) []string { } // IndexList returns the index of the first occurrence of the given string in the list or -1 -func IndexList(s string, list []string) int { +func IndexList[T comparable](t T, list []T) int { for i, l := range list { - if l == s { + if l == t { return i } } - return -1 } -// InList checks if the string belongs to the list -func InList(s string, list []string) bool { - return IndexList(s, list) != -1 +func InList[T comparable](t T, list []T) bool { + return IndexList(t, list) != -1 } func setFromList[T comparable](l []T) map[T]bool { diff --git a/android/variable.go b/android/variable.go index 4442a09eb..1c81f3c3d 100644 --- a/android/variable.go +++ b/android/variable.go @@ -185,7 +185,7 @@ type variableProperties struct { var defaultProductVariables interface{} = variableProperties{} -type productVariables struct { +type ProductVariables struct { // Suffix to add to generated Makefiles Make_suffix *string `json:",omitempty"` @@ -475,6 +475,8 @@ type productVariables struct { ReleaseVersion string `json:",omitempty"` ReleaseAconfigValueSets []string `json:",omitempty"` + + KeepVndk *bool `json:",omitempty"` } func boolPtr(v bool) *bool { @@ -489,8 +491,8 @@ func stringPtr(v string) *string { return &v } -func (v *productVariables) SetDefaultConfig() { - *v = productVariables{ +func (v *ProductVariables) SetDefaultConfig() { + *v = ProductVariables{ BuildNumberFile: stringPtr("build_number.txt"), Platform_version_name: stringPtr("S"), diff --git a/apex/apex_test.go b/apex/apex_test.go index f7a4dea72..df138e054 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -10553,6 +10553,7 @@ func TestTrimmedApex(t *testing.T) { src: "libc.so", min_sdk_version: "29", recovery_available: true, + vendor_available: true, } api_imports { name: "api_imports", diff --git a/bazel/aquery.go b/bazel/aquery.go index 480158c11..186a4945b 100644 --- a/bazel/aquery.go +++ b/bazel/aquery.go @@ -115,7 +115,11 @@ type BuildStatement struct { // input path string, but not both. InputDepsetHashes []string InputPaths []string + OrderOnlyInputs []string FileContents string + // If ShouldRunInSbox is true, Soong will use sbox to created an isolated environment + // and run the mixed build action there + ShouldRunInSbox bool } // A helper type for aquery processing which facilitates retrieval of path IDs from their @@ -134,6 +138,8 @@ type aqueryArtifactHandler struct { depsetHashToArtifactPathsCache sync.Map // Maps artifact ids to fully expanded paths. artifactIdToPath map[artifactId]string + + extraBuildStatements []*BuildStatement } // The tokens should be substituted with the value specified here, instead of the @@ -163,13 +169,29 @@ func newAqueryHandler(aqueryResult *analysis_v2_proto.ActionGraphContainer) (*aq return pathFragmentId(pf.Id) }) + var extraBuildStatements []*BuildStatement artifactIdToPath := make(map[artifactId]string, len(aqueryResult.Artifacts)) for _, artifact := range aqueryResult.Artifacts { artifactPath, err := expandPathFragment(pathFragmentId(artifact.PathFragmentId), pathFragments) if err != nil { return nil, err } - artifactIdToPath[artifactId(artifact.Id)] = artifactPath + if strings.HasSuffix(artifactPath, "DumpPlatformClassPath.java") { + // TODO(b/291828210): This is a workaround for the fact that DumpPlatformClassPath.java + // has a timestamp in 2033. We'll copy it to a new file using a order-only dep, so that + // the file is not recopied every build. Technically the order-only dep would produce + // incremental build issues if this was a regular file produced as part of the build, + // but this file is actually created by bazel during analysis, so it's not an issue. + outputPath := "hack_for_b291828210/DumpPlatformClassPath.java" + extraBuildStatements = append(extraBuildStatements, &BuildStatement{ + Command: fmt.Sprintf("cp %s %s", artifactPath, outputPath), + OutputPaths: []string{outputPath}, + OrderOnlyInputs: []string{artifactPath}, + }) + artifactIdToPath[artifactId(artifact.Id)] = outputPath + } else { + artifactIdToPath[artifactId(artifact.Id)] = artifactPath + } } // Map middleman artifact ContentHash to input artifact depset ID. @@ -196,6 +218,7 @@ func newAqueryHandler(aqueryResult *analysis_v2_proto.ActionGraphContainer) (*aq depsetHashToArtifactPathsCache: sync.Map{}, emptyDepsetIds: make(map[depsetId]struct{}, 0), artifactIdToPath: artifactIdToPath, + extraBuildStatements: extraBuildStatements, } // Validate and adjust aqueryResult.DepSetOfFiles values. @@ -369,6 +392,7 @@ func AqueryBuildStatements(aqueryJsonProto []byte, eventHandler *metrics.EventHa if err != nil { return nil, nil, err } + buildStatements = append(buildStatements, aqueryHandler.extraBuildStatements...) depsetsByHash := map[string]AqueryDepset{} depsets := make([]AqueryDepset, 0, len(aqueryHandler.depsetIdToAqueryDepset)) @@ -496,6 +520,12 @@ func (a *aqueryArtifactHandler) normalActionBuildStatement(actionEntry *analysis Env: actionEntry.EnvironmentVariables, Mnemonic: actionEntry.Mnemonic, } + if buildStatement.Mnemonic == "GoToolchainBinaryBuild" { + // Unlike b's execution root, mixed build execution root contains a symlink to prebuilts/go + // This causes issues for `GOCACHE=$(mktemp -d) go build ...` + // To prevent this, sandbox this action in mixed builds as well + buildStatement.ShouldRunInSbox = true + } return buildStatement, nil } diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go index b22cb2861..cfe52db47 100644 --- a/bp2build/bp2build.go +++ b/bp2build/bp2build.go @@ -80,6 +80,12 @@ func Codegen(ctx *CodegenContext) *CodegenMetrics { os.Exit(1) } bp2buildFiles := CreateBazelFiles(ctx.Config(), nil, res.buildFileToTargets, ctx.mode) + injectionFiles, additionalBp2buildFiles, err := CreateSoongInjectionDirFiles(ctx, res.metrics) + if err != nil { + fmt.Printf("%s\n", err.Error()) + os.Exit(1) + } + bp2buildFiles = append(bp2buildFiles, additionalBp2buildFiles...) writeFiles(ctx, bp2buildDir, bp2buildFiles) // Delete files under the bp2build root which weren't just written. An // alternative would have been to delete the whole directory and write these @@ -88,11 +94,6 @@ func Codegen(ctx *CodegenContext) *CodegenMetrics { // performance implications. deleteFilesExcept(ctx, bp2buildDir, bp2buildFiles) - injectionFiles, err := CreateSoongInjectionDirFiles(ctx, res.metrics) - if err != nil { - fmt.Printf("%s\n", err.Error()) - os.Exit(1) - } writeFiles(ctx, android.PathForOutput(ctx, bazel.SoongInjectionDirName), injectionFiles) starlarkDeps, err := starlark_import.GetNinjaDeps() if err != nil { @@ -107,20 +108,20 @@ func Codegen(ctx *CodegenContext) *CodegenMetrics { // This includes // 1. config value(s) that are hardcoded in Soong // 2. product_config variables -func CreateSoongInjectionDirFiles(ctx *CodegenContext, metrics CodegenMetrics) ([]BazelFile, error) { +func CreateSoongInjectionDirFiles(ctx *CodegenContext, metrics CodegenMetrics) ([]BazelFile, []BazelFile, error) { var ret []BazelFile - productConfigFiles, err := CreateProductConfigFiles(ctx) + productConfigInjectionFiles, productConfigBp2BuildDirFiles, err := CreateProductConfigFiles(ctx) if err != nil { - return nil, err + return nil, nil, err } - ret = append(ret, productConfigFiles...) + ret = append(ret, productConfigInjectionFiles...) injectionFiles, err := soongInjectionFiles(ctx.Config(), metrics) if err != nil { - return nil, err + return nil, nil, err } - ret = append(ret, injectionFiles...) - return ret, nil + ret = append(injectionFiles, ret...) + return ret, productConfigBp2BuildDirFiles, nil } // Get the output directory and create it if it doesn't exist. diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go index 72244961d..8d5c99c28 100644 --- a/bp2build/bp2build_product_config.go +++ b/bp2build/bp2build_product_config.go @@ -1,14 +1,20 @@ package bp2build import ( + "android/soong/android" + "android/soong/starlark_import" + "encoding/json" "fmt" "os" "path/filepath" "strings" + + "github.com/google/blueprint/proptools" + "go.starlark.net/starlark" ) func CreateProductConfigFiles( - ctx *CodegenContext) ([]BazelFile, error) { + ctx *CodegenContext) ([]BazelFile, []BazelFile, error) { cfg := &ctx.config targetProduct := "unknown" if cfg.HasDeviceProduct() { @@ -25,9 +31,14 @@ func CreateProductConfigFiles( if !strings.HasPrefix(productVariablesFileName, "/") { productVariablesFileName = filepath.Join(ctx.topDir, productVariablesFileName) } - bytes, err := os.ReadFile(productVariablesFileName) + productVariablesBytes, err := os.ReadFile(productVariablesFileName) + if err != nil { + return nil, nil, err + } + productVariables := android.ProductVariables{} + err = json.Unmarshal(productVariablesBytes, &productVariables) if err != nil { - return nil, err + return nil, nil, err } // TODO(b/249685973): the name is product_config_platforms because product_config @@ -39,11 +50,16 @@ func CreateProductConfigFiles( "{VARIANT}", targetBuildVariant, "{PRODUCT_FOLDER}", currentProductFolder) - result := []BazelFile{ + platformMappingContent, err := platformMappingContent(productReplacer.Replace("@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}"), &productVariables) + if err != nil { + return nil, nil, err + } + + injectionDirFiles := []BazelFile{ newFile( currentProductFolder, "soong.variables.bzl", - `variables = json.decode("""`+strings.ReplaceAll(string(bytes), "\\", "\\\\")+`""")`), + `variables = json.decode("""`+strings.ReplaceAll(string(productVariablesBytes), "\\", "\\\\")+`""")`), newFile( currentProductFolder, "BUILD", @@ -99,6 +115,7 @@ product_labels = [ "product_config_platforms", "common.bazelrc", productReplacer.Replace(` +build --platform_mappings=platform_mappings build --platforms @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64 build:android --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT} @@ -120,6 +137,48 @@ build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_lin build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_darwin_x86_64 `)), } + bp2buildDirFiles := []BazelFile{ + newFile( + "", + "platform_mappings", + platformMappingContent), + } + return injectionDirFiles, bp2buildDirFiles, nil +} + +func platformMappingContent(mainProductLabel string, mainProductVariables *android.ProductVariables) (string, error) { + productsForTesting, err := starlark_import.GetStarlarkValue[map[string]map[string]starlark.Value]("products_for_testing") + if err != nil { + return "", err + } + result := "platforms:\n" + result += platformMappingSingleProduct(mainProductLabel, mainProductVariables) + for product, productVariablesStarlark := range productsForTesting { + productVariables, err := starlarkMapToProductVariables(productVariablesStarlark) + if err != nil { + return "", err + } + result += platformMappingSingleProduct("@//build/bazel/tests/products:"+product, &productVariables) + } + return result, nil +} + +func platformMappingSingleProduct(label string, productVariables *android.ProductVariables) string { + buildSettings := "" + buildSettings += fmt.Sprintf(" --//build/bazel/product_config:apex_global_min_sdk_version_override=%s\n", proptools.String(productVariables.ApexGlobalMinSdkVersionOverride)) + result := "" + for _, extension := range []string{"", "_linux_x86_64", "_linux_bionic_x86_64", "_linux_musl_x86", "_linux_musl_x86_64"} { + result += " " + label + extension + "\n" + buildSettings + } + return result +} +func starlarkMapToProductVariables(in map[string]starlark.Value) (android.ProductVariables, error) { + var err error + result := android.ProductVariables{} + result.ApexGlobalMinSdkVersionOverride, err = starlark_import.NoneableString(in["ApexGlobalMinSdkVersionOverride"]) + if err != nil { + return result, err + } return result, nil } diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go index a817386ac..0e6596bf7 100644 --- a/bp2build/build_conversion.go +++ b/bp2build/build_conversion.go @@ -471,17 +471,6 @@ func generateBazelTargetsGoBinary(ctx *android.Context, g *bootstrap.GoBinary, g return []BazelTarget{binTarget}, nil } -var ( - // TODO - b/284483729: Remove this denyilst - // Temporary denylist of go binaries that are currently used in mixed builds - // This denylist allows us to rollout bp2build converters for go targets without affecting mixed builds - goBinaryDenylist = []string{ - "soong_zip", - "zip2zip", - "bazel_notice_gen", - } -) - func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (conversionResults, []error) { buildFileToTargets := make(map[string]BazelTargets) @@ -574,7 +563,7 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers targets, targetErrs = generateBazelTargetsGoPackage(bpCtx, glib, nameToGoLibMap) errs = append(errs, targetErrs...) metrics.IncrementRuleClassCount("go_library") - } else if gbin, ok := m.(*bootstrap.GoBinary); ok && !android.InList(m.Name(), goBinaryDenylist) { + } else if gbin, ok := m.(*bootstrap.GoBinary); ok { targets, targetErrs = generateBazelTargetsGoBinary(bpCtx, gbin, nameToGoLibMap) errs = append(errs, targetErrs...) metrics.IncrementRuleClassCount("go_binary") diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go index 4b36cc70a..d9a786069 100644 --- a/bp2build/cc_binary_conversion_test.go +++ b/bp2build/cc_binary_conversion_test.go @@ -1214,3 +1214,82 @@ func TestCCBinaryRscriptSrc(t *testing.T) { }, }) } + +func TestCcBinaryStatic_SystemSharedLibUsedAsDep(t *testing.T) { + runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{ + description: "cc_library_static system_shared_lib empty for linux_bionic variant", + blueprint: soongCcLibraryStaticPreamble + + simpleModuleDoNotConvertBp2build("cc_library", "libc") + ` + +cc_library { + name: "libm", + bazel_module: { bp2build_available: false }, +} + +cc_binary { + name: "used_in_bionic_oses", + target: { + android: { + static_libs: ["libc"], + }, + linux_bionic: { + static_libs: ["libc"], + }, + }, + include_build_directory: false, + static_executable: true, +} + +cc_binary { + name: "all", + static_libs: ["libc"], + include_build_directory: false, + static_executable: true, +} + +cc_binary { + name: "keep_for_empty_system_shared_libs", + static_libs: ["libc"], + system_shared_libs: [], + include_build_directory: false, + static_executable: true, +} + +cc_binary { + name: "used_with_stubs", + static_libs: ["libm"], + include_build_directory: false, + static_executable: true, +} + +cc_binary { + name: "keep_with_stubs", + static_libs: ["libm"], + system_shared_libs: [], + include_build_directory: false, + static_executable: true, +} +`, + targets: []testBazelTarget{ + {"cc_binary", "all", AttrNameToString{ + "linkshared": "False", + }}, + {"cc_binary", "keep_for_empty_system_shared_libs", AttrNameToString{ + "deps": `[":libc_bp2build_cc_library_static"]`, + "system_deps": `[]`, + "linkshared": "False", + }}, + {"cc_binary", "keep_with_stubs", AttrNameToString{ + "linkshared": "False", + "deps": `[":libm_bp2build_cc_library_static"]`, + "system_deps": `[]`, + }}, + {"cc_binary", "used_in_bionic_oses", AttrNameToString{ + "linkshared": "False", + }}, + {"cc_binary", "used_with_stubs", AttrNameToString{ + "linkshared": "False", + }}, + }, + }) +} diff --git a/cc/bp2build.go b/cc/bp2build.go index 85a228488..6e00aa828 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -1139,6 +1139,7 @@ type linkerAttributes struct { wholeArchiveDeps bazel.LabelListAttribute implementationWholeArchiveDeps bazel.LabelListAttribute systemDynamicDeps bazel.LabelListAttribute + usedSystemDynamicDepAsStaticDep map[string]bool usedSystemDynamicDepAsDynamicDep map[string]bool useVersionLib bazel.BoolAttribute @@ -1201,6 +1202,18 @@ func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversion // https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=247-249;drc=088b53577dde6e40085ffd737a1ae96ad82fc4b0 la.wholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, wholeStaticLibs, props.Exclude_static_libs)) + if isBinary && module.StaticExecutable() { + usedSystemStatic := android.FilterListPred(staticLibs, func(s string) bool { + return android.InList(s, soongSystemSharedLibs) && !android.InList(s, props.Exclude_static_libs) + }) + + for _, el := range usedSystemStatic { + if la.usedSystemDynamicDepAsStaticDep == nil { + la.usedSystemDynamicDepAsStaticDep = map[string]bool{} + } + la.usedSystemDynamicDepAsStaticDep[el] = true + } + } staticDeps := maybePartitionExportedAndImplementationsDepsExcludes( ctx, !isBinary, @@ -1233,6 +1246,7 @@ func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversion usedSystem := android.FilterListPred(sharedLibs, func(s string) bool { return android.InList(s, soongSystemSharedLibs) && !android.InList(s, excludeSharedLibs) }) + for _, el := range usedSystem { if la.usedSystemDynamicDepAsDynamicDep == nil { la.usedSystemDynamicDepAsDynamicDep = map[string]bool{} @@ -1625,6 +1639,15 @@ func (la *linkerAttributes) finalize(ctx android.BazelConversionPathContext) { } la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.AndroidPlatform, bazel.MakeLabelList(stubsToRemove)) } + if la.systemDynamicDeps.IsNil() && len(la.usedSystemDynamicDepAsStaticDep) > 0 { + toRemove := bazelLabelForStaticDeps(ctx, android.SortedKeys(la.usedSystemDynamicDepAsStaticDep)) + la.deps.Exclude(bazel.NoConfigAxis, "", toRemove) + la.deps.Exclude(bazel.OsConfigurationAxis, "android", toRemove) + la.deps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove) + la.implementationDeps.Exclude(bazel.NoConfigAxis, "", toRemove) + la.implementationDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove) + la.implementationDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove) + } la.deps.ResolveExcludes() la.implementationDeps.ResolveExcludes() @@ -42,6 +42,7 @@ import ( func init() { RegisterCCBuildComponents(android.InitRegistrationContext) + pctx.Import("android/soong/android") pctx.Import("android/soong/cc/config") } @@ -1079,6 +1080,10 @@ func (c *Module) CcLibraryInterface() bool { return false } +func (c *Module) RlibStd() bool { + panic(fmt.Errorf("RlibStd called on non-Rust module: %q", c.BaseModuleName())) +} + func (c *Module) RustLibraryInterface() bool { return false } @@ -1367,7 +1372,7 @@ func (c *Module) isPgoCompile() bool { func (c *Module) isCfi() bool { if sanitize := c.sanitize; sanitize != nil { - return Bool(sanitize.Properties.Sanitize.Cfi) + return Bool(sanitize.Properties.SanitizeMutated.Cfi) } return false } diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go index a0ef57595..62f75d1bd 100644 --- a/cc/config/toolchain.go +++ b/cc/config/toolchain.go @@ -261,5 +261,3 @@ func LibFuzzerRuntimeLibrary(t Toolchain) string { func LibFuzzerRuntimeInterceptors(t Toolchain) string { return LibclangRuntimeLibrary(t, "fuzzer_interceptors") } - -var inList = android.InList diff --git a/cc/fuzz.go b/cc/fuzz.go index 636ad855b..7f0a5021b 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -258,25 +258,29 @@ func (fuzzBin *fuzzBinary) install(ctx ModuleContext, file android.Path) { 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") + + // Create one rule per file to avoid MAX_ARG_STRLEN hardlimit. for _, entry := range fuzzPackagedModule.Corpus { - builder.Command().Text("cp"). - Input(entry). - Output(intermediateDir.Join(ctx, entry.Base())) + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Output: intermediateDir.Join(ctx, entry.Base()), + Input: entry, + }) } - 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") + + // Create one rule per file to avoid MAX_ARG_STRLEN hardlimit. for _, entry := range fuzzPackagedModule.Data { - builder.Command().Text("cp"). - Input(entry). - Output(intermediateDir.Join(ctx, entry.Rel())) + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Output: intermediateDir.Join(ctx, entry.Rel()), + Input: entry, + }) } - builder.Build("copy_data", "copy data") fuzzPackagedModule.DataIntermediateDir = intermediateDir if fuzzPackagedModule.FuzzProperties.Dictionary != nil { diff --git a/cc/library.go b/cc/library.go index aec6433d8..266fa7511 100644 --- a/cc/library.go +++ b/cc/library.go @@ -1963,6 +1963,10 @@ func (library *libraryDecorator) optInAbiDiff(ctx android.ModuleContext, referen libName := strings.TrimSuffix(baseName, filepath.Ext(baseName)) errorMessage := "error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l " + libName + " -ref-dump-dir $$ANDROID_BUILD_TOP/" + refDumpDir + // Most opt-in libraries do not have dumps for all default architectures. + if ctx.Config().HasDeviceProduct() { + errorMessage += " -products " + ctx.Config().DeviceProduct() + } library.sourceAbiDiff(ctx, referenceDump, baseName, nameExt, isLlndkOrNdk, false /* allowExtensions */, "current", errorMessage) @@ -2271,7 +2275,7 @@ func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) { // do not install vndk libs // vndk libs are packaged into VNDK APEX - if ctx.isVndk() && !ctx.IsVndkExt() { + if ctx.isVndk() && !ctx.IsVndkExt() && !ctx.Config().IsVndkDeprecated() { return } } else if library.hasStubsVariants() && !ctx.Host() && ctx.directlyInAnyApex() { diff --git a/cc/linkable.go b/cc/linkable.go index 19e6501de..209939916 100644 --- a/cc/linkable.go +++ b/cc/linkable.go @@ -87,6 +87,12 @@ type Snapshottable interface { // SnapshotStaticLibs returns the list of static library dependencies for this module. SnapshotStaticLibs() []string + // SnapshotDylibs returns the list of dylib library dependencies for this module. + SnapshotDylibs() []string + + // SnapshotRlibs returns the list of rlib library dependencies for this module. + SnapshotRlibs() []string + // IsSnapshotPrebuilt returns true if this module is a snapshot prebuilt. IsSnapshotPrebuilt() bool } @@ -239,6 +245,9 @@ type LinkableInterface interface { // Dylib returns true if this is an dylib module. Dylib() bool + // RlibStd returns true if this is an rlib which links against an rlib libstd. + RlibStd() bool + // Static returns true if this is a static library module. Static() bool diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go index 0cf21b65a..feb388037 100644 --- a/cc/ndk_sysroot.go +++ b/cc/ndk_sysroot.go @@ -58,7 +58,6 @@ import ( func init() { RegisterNdkModuleTypes(android.InitRegistrationContext) - pctx.Import("android/soong/android") } func RegisterNdkModuleTypes(ctx android.RegistrationContext) { diff --git a/cc/sanitize.go b/cc/sanitize.go index 62e31d1ca..626005b44 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -646,10 +646,6 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { if (ctx.Arch().ArchType != android.Arm64 && ctx.Arch().ArchType != android.Riscv64) || !ctx.toolchain().Bionic() { s.Scs = nil } - // ...but temporarily globally disabled on riscv64 (http://b/277909695). - if ctx.Arch().ArchType == android.Riscv64 { - s.Scs = nil - } // Memtag_heap is only implemented on AArch64. // Memtag ABI is Android specific for now, so disable for host. diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go index a5729dfc0..bb1331051 100644 --- a/cc/snapshot_prebuilt.go +++ b/cc/snapshot_prebuilt.go @@ -100,6 +100,7 @@ const ( snapshotBinarySuffix = "_binary." snapshotObjectSuffix = "_object." SnapshotRlibSuffix = "_rlib." + SnapshotDylibSuffix = "_dylib." ) type SnapshotProperties struct { @@ -107,6 +108,7 @@ type SnapshotProperties struct { Static_libs []string `android:"arch_variant"` Shared_libs []string `android:"arch_variant"` Rlibs []string `android:"arch_variant"` + Dylibs []string `android:"arch_variant"` Vndk_libs []string `android:"arch_variant"` Binaries []string `android:"arch_variant"` Objects []string `android:"arch_variant"` @@ -186,6 +188,7 @@ func (s *snapshotModule) DepsMutator(ctx android.BottomUpMutatorContext) { staticLibs := collectSnapshotMap(s.properties.Static_libs, snapshotSuffix, SnapshotStaticSuffix) sharedLibs := collectSnapshotMap(s.properties.Shared_libs, snapshotSuffix, SnapshotSharedSuffix) rlibs := collectSnapshotMap(s.properties.Rlibs, snapshotSuffix, SnapshotRlibSuffix) + dylibs := collectSnapshotMap(s.properties.Dylibs, snapshotSuffix, SnapshotDylibSuffix) vndkLibs := collectSnapshotMap(s.properties.Vndk_libs, "", vndkSuffix) for k, v := range vndkLibs { sharedLibs[k] = v @@ -198,11 +201,12 @@ func (s *snapshotModule) DepsMutator(ctx android.BottomUpMutatorContext) { StaticLibs: staticLibs, SharedLibs: sharedLibs, Rlibs: rlibs, + Dylibs: dylibs, }) } type SnapshotInfo struct { - HeaderLibs, Binaries, Objects, StaticLibs, SharedLibs, Rlibs map[string]string + HeaderLibs, Binaries, Objects, StaticLibs, SharedLibs, Rlibs, Dylibs map[string]string } var SnapshotInfoProvider = blueprint.NewMutatorProvider(SnapshotInfo{}, "deps") diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go index cf4617da3..1ee120eb8 100644 --- a/cc/snapshot_utils.go +++ b/cc/snapshot_utils.go @@ -57,6 +57,14 @@ func (m *Module) SnapshotStaticLibs() []string { return m.Properties.SnapshotStaticLibs } +func (m *Module) SnapshotRlibs() []string { + return []string{} +} + +func (m *Module) SnapshotDylibs() []string { + return []string{} +} + // snapshotLibraryInterface is an interface for libraries captured to VNDK / vendor snapshots. type snapshotLibraryInterface interface { libraryInterface diff --git a/cc/util.go b/cc/util.go index 6d8ac435f..c93646b98 100644 --- a/cc/util.go +++ b/cc/util.go @@ -28,8 +28,8 @@ func includeDirsToFlags(dirs android.Paths) string { return android.JoinWithPrefix(dirs.Strings(), "-I") } -var indexList = android.IndexList -var inList = android.InList +var indexList = android.IndexList[string] +var inList = android.InList[string] var filterList = android.FilterList var removeListFromList = android.RemoveListFromList var removeFromList = android.RemoveFromList diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index d2531c03d..9ea337b8d 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -108,10 +108,10 @@ func isSnapshotAware(cfg android.DeviceConfig, m LinkableInterface, inProprietar return false } } - if sanitizable.Static() { + if sanitizable.Static() || sanitizable.Rlib() { return sanitizable.OutputFile().Valid() && !isPrivate(image, m) } - if sanitizable.Shared() || sanitizable.Rlib() { + if sanitizable.Shared() || sanitizable.Dylib() { if !sanitizable.OutputFile().Valid() { return false } @@ -153,6 +153,8 @@ type snapshotJsonFlags struct { SharedLibs []string `json:",omitempty"` StaticLibs []string `json:",omitempty"` RuntimeLibs []string `json:",omitempty"` + Dylibs []string `json:",omitempty"` + Rlibs []string `json:",omitempty"` // extra config files InitRc []string `json:",omitempty"` @@ -283,8 +285,17 @@ var ccSnapshotAction snapshot.GenerateSnapshotAction = func(s snapshot.SnapshotS if m.Shared() { prop.SharedLibs = m.SnapshotSharedLibs() } - // static libs dependencies are required to collect the NOTICE files. + + // dylibs collect both shared and dylib dependencies. + if m.Dylib() { + prop.SharedLibs = m.SnapshotSharedLibs() + prop.Dylibs = m.SnapshotDylibs() + } + + // static and rlib libs dependencies are required to collect the NOTICE files. prop.StaticLibs = m.SnapshotStaticLibs() + prop.Rlibs = m.SnapshotRlibs() + if sanitizable, ok := m.(PlatformSanitizeable); ok { if sanitizable.Static() && sanitizable.SanitizePropDefined() { prop.SanitizeMinimalDep = sanitizable.MinimalRuntimeDep() || sanitizable.MinimalRuntimeNeeded() @@ -299,13 +310,15 @@ var ccSnapshotAction snapshot.GenerateSnapshotAction = func(s snapshot.SnapshotS libType = "shared" } else if m.Rlib() { libType = "rlib" + } else if m.Dylib() { + libType = "dylib" } else { libType = "header" } var stem string - // install .a or .so + // install .a, .rlib, .dylib.so, or .so if libType != "header" { libPath := m.OutputFile().Path() stem = libPath.Base() @@ -328,6 +341,12 @@ var ccSnapshotAction snapshot.GenerateSnapshotAction = func(s snapshot.SnapshotS } } } + if m.Rlib() && m.RlibStd() { + // rlibs produce both rlib-std and dylib-std variants + ext := filepath.Ext(stem) + stem = strings.TrimSuffix(stem, ext) + ".rlib-std" + ext + prop.ModuleName += ".rlib-std" + } snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, m.RelativeInstallPath(), stem) ret = append(ret, copyFile(ctx, libPath, snapshotLibOut, fake)) } else { @@ -341,8 +360,12 @@ var ccSnapshotAction snapshot.GenerateSnapshotAction = func(s snapshot.SnapshotS prop.StaticExecutable = m.StaticExecutable() prop.InstallInRoot = m.InstallInRoot() prop.SharedLibs = m.SnapshotSharedLibs() - // static libs dependencies are required to collect the NOTICE files. + prop.Dylibs = m.SnapshotDylibs() + + // static and rlib dependencies are required to collect the NOTICE files. prop.StaticLibs = m.SnapshotStaticLibs() + prop.Rlibs = m.SnapshotRlibs() + // install bin binPath := m.OutputFile().Path() snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base()) diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go index 22d64a2ed..5ea84bcba 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -225,7 +225,7 @@ func runApiBp2build(ctx *android.Context, extraNinjaDeps []string) string { ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...) // Create soong_injection repository - soongInjectionFiles, err := bp2build.CreateSoongInjectionDirFiles(codegenContext, bp2build.CreateCodegenMetrics()) + soongInjectionFiles, workspaceFiles, err := bp2build.CreateSoongInjectionDirFiles(codegenContext, bp2build.CreateCodegenMetrics()) maybeQuit(err, "") absoluteSoongInjectionDir := shared.JoinPath(topDir, ctx.Config().SoongOutDir(), bazel.SoongInjectionDirName) for _, file := range soongInjectionFiles { @@ -236,6 +236,9 @@ func runApiBp2build(ctx *android.Context, extraNinjaDeps []string) string { // to allow users to edit/experiment in the synthetic workspace. writeReadWriteFile(absoluteSoongInjectionDir, file) } + for _, file := range workspaceFiles { + writeReadWriteFile(absoluteApiBp2buildDir, file) + } workspace := shared.JoinPath(ctx.Config().SoongOutDir(), "api_bp2build") // Create the symlink forest diff --git a/cmd/zip2zip/BUILD.bazel b/cmd/zip2zip/BUILD.bazel deleted file mode 100644 index 1915a2dbf..000000000 --- a/cmd/zip2zip/BUILD.bazel +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (C) 2022 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -alias( - name = "zip2zip", - actual = "//prebuilts/build-tools:linux-x86/bin/zip2zip", -) diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go index ada47128c..94b795f4d 100644 --- a/fuzz/fuzz_common.go +++ b/fuzz/fuzz_common.go @@ -371,6 +371,8 @@ type FuzzConfig struct { // Specifies whether fuzz target should check presubmitted code changes for crashes. // Defaults to false. Use_for_presubmit *bool `json:"use_for_presubmit,omitempty"` + // Specify which paths to exclude from fuzzing coverage reports + Exclude_paths_from_reports []string `json:"exclude_paths_from_reports,omitempty"` } type FuzzFrameworks struct { diff --git a/java/aar.go b/java/aar.go index 01bd10302..c9e08e2b5 100644 --- a/java/aar.go +++ b/java/aar.go @@ -611,6 +611,8 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() + a.stem = proptools.StringDefault(a.overridableDeviceProperties.Stem, ctx.ModuleName()) + ctx.CheckbuildFile(a.proguardOptionsFile) ctx.CheckbuildFile(a.exportPackage) ctx.CheckbuildFile(a.aaptSrcJar) diff --git a/java/androidmk.go b/java/androidmk.go index 13cc96a88..784fa29b5 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -455,11 +455,6 @@ func (a *AndroidApp) getOverriddenPackages() []string { if len(a.overridableAppProperties.Overrides) > 0 { overridden = append(overridden, a.overridableAppProperties.Overrides...) } - // When APK name is overridden via PRODUCT_PACKAGE_NAME_OVERRIDES - // ensure that the original name is overridden. - if a.Stem() != a.installApkName { - overridden = append(overridden, a.Stem()) - } return overridden } diff --git a/java/app.go b/java/app.go index 25909ec9d..8e4efd2b2 100755 --- a/java/app.go +++ b/java/app.go @@ -666,8 +666,17 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx) a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex) + // Unlike installApkName, a.stem should respect base module name for override_android_app. + // Therefore, use ctx.ModuleName() instead of a.Name(). + a.stem = proptools.StringDefault(a.overridableDeviceProperties.Stem, ctx.ModuleName()) + // Check if the install APK name needs to be overridden. - a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Stem()) + // Both android_app and override_android_app module are expected to possess + // its module bound apk path. However, override_android_app inherits ctx.ModuleName() + // from the base module. Therefore, use a.Name() which represents + // the module name for both android_app and override_android_app. + a.installApkName = ctx.DeviceConfig().OverridePackageNameFor( + proptools.StringDefault(a.overridableDeviceProperties.Stem, a.Name())) if ctx.ModuleName() == "framework-res" { // framework-res.apk is installed as system/framework/framework-res.apk diff --git a/java/base.go b/java/base.go index cb08ef380..8db716256 100644 --- a/java/base.go +++ b/java/base.go @@ -21,6 +21,7 @@ import ( "strings" "android/soong/ui/metrics/bp2build_metrics_proto" + "github.com/google/blueprint/pathtools" "github.com/google/blueprint/proptools" @@ -502,6 +503,11 @@ type Module struct { sourceExtensions []string annoSrcJars android.Paths + + // output file name based on Stem property. + // This should be set in every ModuleWithStem's GenerateAndroidBuildActions + // or the module should override Stem(). + stem string } func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error { @@ -1099,7 +1105,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { j.expandJarjarRules = android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules) } - jarName := ctx.ModuleName() + ".jar" + jarName := j.Stem() + ".jar" var uniqueJavaFiles android.Paths set := make(map[string]bool) @@ -1897,7 +1903,10 @@ func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersi } func (j *Module) Stem() string { - return proptools.StringDefault(j.overridableDeviceProperties.Stem, j.Name()) + if j.stem == "" { + panic("Stem() called before stem property was set") + } + return j.stem } func (j *Module) JacocoReportClassesFile() android.Path { diff --git a/java/java.go b/java/java.go index 011dc1c54..6388d13e3 100644 --- a/java/java.go +++ b/java/java.go @@ -676,6 +676,8 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.minSdkVersion = j.MinSdkVersion(ctx) j.maxSdkVersion = j.MaxSdkVersion(ctx) + j.stem = proptools.StringDefault(j.overridableDeviceProperties.Stem, ctx.ModuleName()) + apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo) if !apexInfo.IsForPlatform() { j.hideApexVariantFromMake = true @@ -1468,6 +1470,8 @@ func (j *Binary) HostToolPath() android.OptionalPath { } func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) { + j.stem = proptools.StringDefault(j.overridableDeviceProperties.Stem, ctx.ModuleName()) + if ctx.Arch().ArchType == android.Common { // Compile the jar if j.binaryProperties.Main_class != nil { @@ -2653,7 +2657,7 @@ func (ks *kytheExtractJavaSingleton) GenerateBuildActions(ctx android.SingletonC var Bool = proptools.Bool var BoolDefault = proptools.BoolDefault var String = proptools.String -var inList = android.InList +var inList = android.InList[string] // Add class loader context (CLC) of a given dependency to the current CLC. func addCLCFromDep(ctx android.ModuleContext, depModule android.Module, diff --git a/java/java_test.go b/java/java_test.go index 473830464..dd9867704 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -2351,3 +2351,22 @@ func TestJavaExcludeStaticLib(t *testing.T) { `stable.core.platform.api.stubs`, }) } + +func TestJavaLibraryWithResourcesStem(t *testing.T) { + ctx, _ := testJavaWithFS(t, ` + java_library { + name: "foo", + java_resource_dirs: ["test-jar"], + stem: "test", + } + `, + map[string][]byte{ + "test-jar/test/resource.txt": nil, + }) + + m := ctx.ModuleForTests("foo", "android_common") + outputs := fmt.Sprint(m.AllOutputs()) + if !strings.Contains(outputs, "test.jar") { + t.Errorf("Module output does not contain expected jar %s", "test.jar") + } +} diff --git a/rust/binary.go b/rust/binary.go index 2de92c17f..e6f153996 100644 --- a/rust/binary.go +++ b/rust/binary.go @@ -158,9 +158,6 @@ func (binary *binaryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoD // Binaries default to dylib dependencies for device, rlib for host. if binary.preferRlib() { return rlibAutoDep - } else if mod, ok := ctx.Module().(*Module); ok && mod.InVendor() { - // Vendor Rust binaries should prefer rlibs. - return rlibAutoDep } else if ctx.Device() { return dylibAutoDep } else { @@ -171,8 +168,6 @@ func (binary *binaryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoD func (binary *binaryDecorator) stdLinkage(ctx *depsContext) RustLinkage { if binary.preferRlib() { return RlibLinkage - } else if ctx.RustModule().InVendor() { - return RlibLinkage } return binary.baseCompiler.stdLinkage(ctx) } diff --git a/rust/bindgen.go b/rust/bindgen.go index 7dc1b4b10..59585aaf8 100644 --- a/rust/bindgen.go +++ b/rust/bindgen.go @@ -29,7 +29,7 @@ var ( defaultBindgenFlags = []string{""} // bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures. - bindgenClangVersion = "clang-r487747c" + bindgenClangVersion = "clang-r498229" _ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string { if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" { diff --git a/rust/image.go b/rust/image.go index 50bf02a4a..53fb5c023 100644 --- a/rust/image.go +++ b/rust/image.go @@ -220,9 +220,6 @@ func (mod *Module) SetImageVariation(ctx android.BaseModuleContext, variant stri } func (mod *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { - // Rust does not support installing to the product image yet. - vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific() - if Bool(mod.VendorProperties.Double_loadable) { mctx.PropertyErrorf("double_loadable", "Rust modules do not yet support double loading") @@ -232,11 +229,6 @@ func (mod *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { mctx.PropertyErrorf("vendor_ramdisk_available", "cannot be set for rust_ffi or rust_ffi_shared modules.") } } - if vendorSpecific { - if lib, ok := mod.compiler.(libraryInterface); ok && lib.buildDylib() { - mctx.PropertyErrorf("vendor", "Vendor-only dylibs are not yet supported, use rust_library_rlib.") - } - } if mctx.ProductSpecific() { if lib, ok := mod.compiler.(libraryInterface); ok && lib.buildDylib() { mctx.PropertyErrorf("product", "Product-only dylibs are not yet supported, use rust_library_rlib.") diff --git a/rust/library.go b/rust/library.go index 331763a50..3f480a259 100644 --- a/rust/library.go +++ b/rust/library.go @@ -21,7 +21,6 @@ import ( "android/soong/android" "android/soong/cc" - "android/soong/snapshot" ) var ( @@ -236,10 +235,7 @@ func (library *libraryDecorator) setSource() { } func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep { - if ctx.Module().(*Module).InVendor() { - // Vendor modules should statically link libstd. - return rlibAutoDep - } else if library.preferRlib() { + if library.preferRlib() { return rlibAutoDep } else if library.rlib() || library.static() { return rlibAutoDep @@ -251,10 +247,7 @@ func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) aut } func (library *libraryDecorator) stdLinkage(ctx *depsContext) RustLinkage { - if ctx.RustModule().InVendor() { - // Vendor modules should statically link libstd. - return RlibLinkage - } else if library.static() || library.MutatedProperties.VariantIsStaticStd { + if library.static() || library.MutatedProperties.VariantIsStaticStd { return RlibLinkage } else if library.baseCompiler.preferRlib() { return RlibLinkage @@ -693,24 +686,6 @@ func LibraryMutator(mctx android.BottomUpMutatorContext) { v.(*Module).Disable() } - variation := v.(*Module).ModuleBase.ImageVariation().Variation - if strings.HasPrefix(variation, cc.VendorVariationPrefix) { - // TODO(b/204303985) - // Disable vendor dylibs until they are supported - v.(*Module).Disable() - } - - if strings.HasPrefix(variation, cc.VendorVariationPrefix) && - m.HasVendorVariant() && - !snapshot.IsVendorProprietaryModule(mctx) && - strings.TrimPrefix(variation, cc.VendorVariationPrefix) == mctx.DeviceConfig().VndkVersion() { - - // cc.MutateImage runs before LibraryMutator, so vendor variations which are meant for rlibs only are - // produced for Dylibs; however, dylibs should not be enabled for boardVndkVersion for - // non-vendor proprietary modules. - v.(*Module).Disable() - } - case "source": v.(*Module).compiler.(libraryInterface).setSource() // The source variant does not produce any library. @@ -747,10 +722,9 @@ func LibstdMutator(mctx android.BottomUpMutatorContext) { dylib := modules[1].(*Module) rlib.compiler.(libraryInterface).setRlibStd() dylib.compiler.(libraryInterface).setDylibStd() - if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation || - strings.HasPrefix(dylib.ModuleBase.ImageVariation().Variation, cc.VendorVariationPrefix) { + if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation { // TODO(b/165791368) - // Disable rlibs that link against dylib-std on vendor and vendor ramdisk variations until those dylib + // Disable rlibs that link against dylib-std on vendor ramdisk variations until those dylib // variants are properly supported. dylib.Disable() } diff --git a/rust/rust.go b/rust/rust.go index e524c9fb6..05fceee36 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -43,6 +43,7 @@ func init() { android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel() }) + pctx.Import("android/soong/android") pctx.Import("android/soong/rust/config") pctx.ImportAs("cc_config", "android/soong/cc/config") android.InitRegistrationContext.RegisterParallelSingletonType("kythe_rust_extract", kytheExtractRustFactory) @@ -91,6 +92,8 @@ type BaseProperties struct { // Used by vendor snapshot to record dependencies from snapshot modules. SnapshotSharedLibs []string `blueprint:"mutated"` SnapshotStaticLibs []string `blueprint:"mutated"` + SnapshotRlibs []string `blueprint:"mutated"` + SnapshotDylibs []string `blueprint:"mutated"` // Make this module available when building for ramdisk. // On device without a dedicated recovery partition, the module is only @@ -258,6 +261,15 @@ func (mod *Module) Dylib() bool { return false } +func (mod *Module) RlibStd() bool { + if mod.compiler != nil { + if library, ok := mod.compiler.(libraryInterface); ok && library.rlib() { + return library.rlibStd() + } + } + panic(fmt.Errorf("RlibStd() called on non-rlib module: %q", mod.BaseModuleName())) +} + func (mod *Module) Rlib() bool { if mod.compiler != nil { if library, ok := mod.compiler.(libraryInterface); ok { @@ -1225,6 +1237,8 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } directDylibDeps = append(directDylibDeps, rustDep) mod.Properties.AndroidMkDylibs = append(mod.Properties.AndroidMkDylibs, makeLibName) + mod.Properties.SnapshotDylibs = append(mod.Properties.SnapshotDylibs, cc.BaseLibName(depName)) + case rlibDepTag: rlib, ok := rustDep.compiler.(libraryInterface) @@ -1234,6 +1248,8 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } directRlibDeps = append(directRlibDeps, rustDep) mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, makeLibName) + mod.Properties.SnapshotRlibs = append(mod.Properties.SnapshotRlibs, cc.BaseLibName(depName)) + case procMacroDepTag: directProcMacroDeps = append(directProcMacroDeps, rustDep) mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName) @@ -1518,10 +1534,10 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { } // dylibs - actx.AddVariationDependencies( - append(commonDepVariations, []blueprint.Variation{ - {Mutator: "rust_libraries", Variation: dylibVariation}}...), - dylibDepTag, deps.Dylibs...) + dylibDepVariations := append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: dylibVariation}) + for _, lib := range deps.Dylibs { + addDylibDependency(actx, lib, mod, &snapshotInfo, dylibDepVariations, dylibDepTag) + } // rustlibs if deps.Rustlibs != nil && !mod.compiler.Disabled() { @@ -1536,8 +1552,11 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { // otherwise select the rlib variant. autoDepVariations := append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation}) - if actx.OtherModuleDependencyVariantExists(autoDepVariations, lib) { - actx.AddVariationDependencies(autoDepVariations, autoDep.depTag, lib) + + replacementLib := cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Dylibs) + + if actx.OtherModuleDependencyVariantExists(autoDepVariations, replacementLib) { + addDylibDependency(actx, lib, mod, &snapshotInfo, autoDepVariations, autoDep.depTag) } else { // If there's no dylib dependency available, try to add the rlib dependency instead. addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations) @@ -1549,16 +1568,14 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { if deps.Stdlibs != nil { if mod.compiler.stdLinkage(ctx) == RlibLinkage { for _, lib := range deps.Stdlibs { - depTag := rlibDepTag lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs) - actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}...), - depTag, lib) + rlibDepTag, lib) } } else { - actx.AddVariationDependencies( - append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: "dylib"}), - dylibDepTag, deps.Stdlibs...) + for _, lib := range deps.Stdlibs { + addDylibDependency(actx, lib, mod, &snapshotInfo, dylibDepVariations, dylibDepTag) + } } } @@ -1636,6 +1653,11 @@ func addRlibDependency(actx android.BottomUpMutatorContext, lib string, mod *Mod actx.AddVariationDependencies(variations, rlibDepTag, lib) } +func addDylibDependency(actx android.BottomUpMutatorContext, lib string, mod *Module, snapshotInfo **cc.SnapshotInfo, variations []blueprint.Variation, depTag dependencyTag) { + lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, snapshotInfo, actx).Dylibs) + actx.AddVariationDependencies(variations, depTag, lib) +} + func BeginMutator(ctx android.BottomUpMutatorContext) { if mod, ok := ctx.Module().(*Module); ok && mod.Enabled() { mod.beginMutator(ctx) diff --git a/rust/rust_test.go b/rust/rust_test.go index 64f90b6e0..3f4e29676 100644 --- a/rust/rust_test.go +++ b/rust/rust_test.go @@ -79,14 +79,18 @@ func testRustVndk(t *testing.T, bp string) *android.TestContext { } const ( - sharedVendorVariant = "android_vendor.29_arm64_armv8-a_shared" - rlibVendorVariant = "android_vendor.29_arm64_armv8-a_rlib_rlib-std" - sharedRecoveryVariant = "android_recovery_arm64_armv8-a_shared" - rlibRecoveryVariant = "android_recovery_arm64_armv8-a_rlib_rlib-std" - binaryCoreVariant = "android_arm64_armv8-a" - binaryVendorVariant = "android_vendor.29_arm64_armv8-a" - binaryProductVariant = "android_product.29_arm64_armv8-a" - binaryRecoveryVariant = "android_recovery_arm64_armv8-a" + sharedVendorVariant = "android_vendor.29_arm64_armv8-a_shared" + rlibVendorVariant = "android_vendor.29_arm64_armv8-a_rlib_rlib-std" + rlibDylibStdVendorVariant = "android_vendor.29_arm64_armv8-a_rlib_rlib-std" + dylibVendorVariant = "android_vendor.29_arm64_armv8-a_dylib" + sharedRecoveryVariant = "android_recovery_arm64_armv8-a_shared" + rlibRecoveryVariant = "android_recovery_arm64_armv8-a_rlib_dylib-std" + rlibRlibStdRecoveryVariant = "android_recovery_arm64_armv8-a_rlib_rlib-std" + dylibRecoveryVariant = "android_recovery_arm64_armv8-a_dylib" + binaryCoreVariant = "android_arm64_armv8-a" + binaryVendorVariant = "android_vendor.29_arm64_armv8-a" + binaryProductVariant = "android_product.29_arm64_armv8-a" + binaryRecoveryVariant = "android_recovery_arm64_armv8-a" ) func testRustVndkFs(t *testing.T, bp string, fs android.MockFS) *android.TestContext { diff --git a/rust/snapshot_prebuilt.go b/rust/snapshot_prebuilt.go index 2f79cc5c3..32d391629 100644 --- a/rust/snapshot_prebuilt.go +++ b/rust/snapshot_prebuilt.go @@ -21,10 +21,6 @@ import ( "github.com/google/blueprint/proptools" ) -const ( - snapshotRlibSuffix = "_rlib." -) - type snapshotLibraryDecorator struct { cc.BaseSnapshotDecorator *libraryDecorator @@ -44,6 +40,8 @@ func init() { func registerRustSnapshotModules(ctx android.RegistrationContext) { cc.VendorSnapshotImageSingleton.RegisterAdditionalModule(ctx, "vendor_snapshot_rlib", VendorSnapshotRlibFactory) + cc.VendorSnapshotImageSingleton.RegisterAdditionalModule(ctx, + "vendor_snapshot_dylib", VendorSnapshotDylibFactory) cc.RecoverySnapshotImageSingleton.RegisterAdditionalModule(ctx, "recovery_snapshot_rlib", RecoverySnapshotRlibFactory) } @@ -77,12 +75,11 @@ func (library *snapshotLibraryDecorator) compile(ctx ModuleContext, flags Flags, variant = cc.SnapshotSharedSuffix } else if library.rlib() { variant = cc.SnapshotRlibSuffix + } else if library.dylib() { + variant = cc.SnapshotDylibSuffix } - if !library.dylib() { - // TODO(184042776): Remove this check when dylibs are supported in snapshots. - library.SetSnapshotAndroidMkSuffix(ctx, variant) - } + library.SetSnapshotAndroidMkSuffix(ctx, variant) if !library.MatchesWithDevice(ctx.DeviceConfig()) { return buildOutput{} @@ -107,6 +104,17 @@ func VendorSnapshotRlibFactory() android.Module { return module.Init() } +// vendor_snapshot_dylib is a special prebuilt dylib library which is auto-generated by +// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_dylib +// overrides the vendor variant of the rust dylib library with the same name, if BOARD_VNDK_VERSION +// is set. +func VendorSnapshotDylibFactory() android.Module { + module, prebuilt := snapshotLibraryFactory(cc.VendorSnapshotImageSingleton, cc.SnapshotDylibSuffix) + prebuilt.libraryDecorator.BuildOnlyDylib() + prebuilt.libraryDecorator.setNoStdlibs() + return module.Init() +} + func RecoverySnapshotRlibFactory() android.Module { module, prebuilt := snapshotLibraryFactory(cc.RecoverySnapshotImageSingleton, cc.SnapshotRlibSuffix) prebuilt.libraryDecorator.BuildOnlyRlib() diff --git a/rust/snapshot_utils.go b/rust/snapshot_utils.go index 8dabd9bf6..55c85e668 100644 --- a/rust/snapshot_utils.go +++ b/rust/snapshot_utils.go @@ -42,8 +42,7 @@ func (mod *Module) ExcludeFromRecoverySnapshot() bool { func (mod *Module) IsSnapshotLibrary() bool { if lib, ok := mod.compiler.(libraryInterface); ok { - // Rust-native dylibs are not snapshot supported yet. Only snapshot the rlib-std variants of rlibs. - return lib.shared() || lib.static() || (lib.rlib() && lib.rlibStd()) + return lib.shared() || lib.static() || lib.rlib() || lib.dylib() } return false } @@ -61,6 +60,14 @@ func (mod *Module) SnapshotStaticLibs() []string { return mod.Properties.SnapshotStaticLibs } +func (mod *Module) SnapshotRlibs() []string { + return mod.Properties.SnapshotRlibs +} + +func (mod *Module) SnapshotDylibs() []string { + return mod.Properties.SnapshotDylibs +} + func (mod *Module) Symlinks() []string { // TODO update this to return the list of symlinks when Rust supports defining symlinks return nil diff --git a/rust/vendor_snapshot_test.go b/rust/vendor_snapshot_test.go index 2e7a33027..387d17043 100644 --- a/rust/vendor_snapshot_test.go +++ b/rust/vendor_snapshot_test.go @@ -48,15 +48,13 @@ func TestVendorSnapshotCapture(t *testing.T) { crate_name: "rustvendor_available", srcs: ["lib.rs"], vendor_available: true, - include_dirs: ["rust_headers/"], } - rust_library_rlib { + rust_library { name: "librustvendor", crate_name: "rustvendor", srcs: ["lib.rs"], vendor: true, - include_dirs: ["rust_headers/"], } rust_binary { @@ -116,7 +114,7 @@ func TestVendorSnapshotCapture(t *testing.T) { filepath.Join(staticDir, "libffivendor.a.json")) // For rlib libraries, all vendor:true and vendor_available modules (including VNDK) are captured. - rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant) + rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_dylib-std", archType, archVariant) rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib") cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib", rlibDir, rlibVariant) cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.rlib", rlibDir, rlibVariant) @@ -125,6 +123,25 @@ func TestVendorSnapshotCapture(t *testing.T) { jsonFiles = append(jsonFiles, filepath.Join(rlibDir, "librustvendor.rlib.json")) + // For rlib libraries, all rlib-std variants vendor:true and vendor_available modules (including VNDK) are captured. + rlibStdVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib-std.rlib", rlibDir, rlibStdVariant) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.rlib-std.rlib", rlibDir, rlibStdVariant) + jsonFiles = append(jsonFiles, + filepath.Join(rlibDir, "librustvendor_available.rlib.json")) + jsonFiles = append(jsonFiles, + filepath.Join(rlibDir, "librustvendor.rlib.json")) + + // For dylib libraries, all vendor:true and vendor_available modules (including VNDK) are captured. + dylibVariant := fmt.Sprintf("android_vendor.29_%s_%s_dylib", archType, archVariant) + dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib") + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.dylib.so", dylibDir, dylibVariant) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.dylib.so", dylibDir, dylibVariant) + jsonFiles = append(jsonFiles, + filepath.Join(dylibDir, "librustvendor_available.dylib.so.json")) + jsonFiles = append(jsonFiles, + filepath.Join(dylibDir, "librustvendor.dylib.so.json")) + // For binary executables, all vendor:true and vendor_available modules are captured. if archType == "arm64" { binaryVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant) @@ -209,21 +226,32 @@ func TestVendorSnapshotDirected(t *testing.T) { archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant) sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant) - rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant) + rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_dylib-std", archType, archVariant) + rlibRlibStdVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant) sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared") rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib") + dylibVariant := fmt.Sprintf("android_vendor.29_%s_%s_dylib", archType, archVariant) + dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib") // Included modules cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib", rlibDir, rlibVariant) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib-std.rlib", rlibDir, rlibRlibStdVariant) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.dylib.so", dylibDir, dylibVariant) cc.CheckSnapshot(t, ctx, snapshotSingleton, "libffivendor_available", "libffivendor_available.so", sharedDir, sharedVariant) includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_available.rlib.json")) + includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_available.rlib-std.rlib.json")) + includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librustvendor_available.dylib.so.json")) includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libffivendor_available.so.json")) // Excluded modules. Modules not included in the directed vendor snapshot // are still include as fake modules. cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.rlib", rlibDir, rlibVariant) + cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.rlib-std.rlib", rlibDir, rlibRlibStdVariant) + cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.dylib.so", dylibDir, dylibVariant) cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "libffivendor_exclude", "libffivendor_exclude.so", sharedDir, sharedVariant) includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_exclude.rlib.json")) + includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_exclude.rlib-std.rlib.json")) + includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librustvendor_exclude.dylib.so.json")) includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libffivendor_exclude.so.json")) } @@ -274,7 +302,7 @@ func TestVendorSnapshotExclude(t *testing.T) { vendor_available: true, } - rust_library_rlib { + rust_library { name: "librust_exclude", crate_name: "rust_exclude", srcs: ["exclude.rs"], @@ -308,6 +336,14 @@ func TestVendorSnapshotExclude(t *testing.T) { cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, rlibVendorVariant) cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, rlibVendorVariant) + cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_include", false, rlibDylibStdVendorVariant) + cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, rlibDylibStdVendorVariant) + cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, rlibDylibStdVendorVariant) + + cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_include", false, dylibVendorVariant) + cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, dylibVendorVariant) + cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, dylibVendorVariant) + // Verify the content of the vendor snapshot. snapshotDir := "vendor-snapshot" @@ -327,14 +363,22 @@ func TestVendorSnapshotExclude(t *testing.T) { sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant) sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared") - rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant) + + rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_dylib-std", archType, archVariant) + rlibRlibStdVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant) rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib") + dylibVariant := fmt.Sprintf("android_vendor.29_%s_%s_dylib", archType, archVariant) + dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib") // Included modules cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant) includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json")) cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.rlib", rlibDir, rlibVariant) includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librust_include.rlib.json")) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.rlib-std.rlib", rlibDir, rlibRlibStdVariant) + includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librust_include.rlib-std.rlib.json")) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.dylib.so", dylibDir, dylibVariant) + includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librust_include.dylib.so.json")) // Excluded modules cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant) @@ -345,6 +389,12 @@ func TestVendorSnapshotExclude(t *testing.T) { excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_exclude.rlib.json")) cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.rlib", rlibDir, rlibVariant) excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_available_exclude.rlib.json")) + cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.rlib-std.rlib", rlibDir, rlibRlibStdVariant) + excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_available_exclude.rlib.rlib-std.json")) + cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_exclude", "librust_exclude.dylib.so", dylibDir, dylibVariant) + excludeJsonFiles = append(excludeJsonFiles, filepath.Join(dylibDir, "librust_exclude.dylib.so.json")) + cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.dylib.so", dylibDir, dylibVariant) + excludeJsonFiles = append(excludeJsonFiles, filepath.Join(dylibDir, "librust_available_exclude.dylib.so.json")) } // Verify that each json file for an included module has a rule. @@ -525,7 +575,7 @@ func TestVendorSnapshotUse(t *testing.T) { srcs: ["client.rs"], } - rust_library_rlib { + rust_library { name: "libclient_rust", crate_name: "client_rust", vendor: true, @@ -572,6 +622,11 @@ func TestVendorSnapshotUse(t *testing.T) { rlibs: [ "libstd", "librust_vendor_available", + "librust_vendor_available.rlib-std" + ], + dylibs: [ + "libstd", + "librust_vendor_available", ], binaries: [ "bin", @@ -600,6 +655,10 @@ func TestVendorSnapshotUse(t *testing.T) { "libstd", "librust_vendor_available", ], + dylibs: [ + "libstd", + "librust_vendor_available", + ], binaries: [ "bin32", ], @@ -679,6 +738,52 @@ func TestVendorSnapshotUse(t *testing.T) { }, } + vendor_snapshot_rlib { + name: "librust_vendor_available.rlib-std", + version: "30", + target_arch: "arm64", + vendor: true, + arch: { + arm64: { + src: "librust_vendor_available.rlib-std.rlib", + }, + arm: { + src: "librust_vendor_available.rlib-std.rlib", + }, + }, + } + + vendor_snapshot_dylib { + name: "libstd", + version: "30", + target_arch: "arm64", + vendor: true, + sysroot: true, + arch: { + arm64: { + src: "libstd.dylib.so", + }, + arm: { + src: "libstd.dylib.so", + }, + }, + } + + vendor_snapshot_dylib { + name: "librust_vendor_available", + version: "30", + target_arch: "arm64", + vendor: true, + arch: { + arm64: { + src: "librust_vendor_available.dylib.so", + }, + arm: { + src: "librust_vendor_available.dylib.so", + }, + }, + } + vendor_snapshot_object { name: "crtend_android", version: "30", @@ -921,6 +1026,9 @@ func TestVendorSnapshotUse(t *testing.T) { "vendor/liblog.so": nil, "vendor/libstd.rlib": nil, "vendor/librust_vendor_available.rlib": nil, + "vendor/librust_vendor_available.rlib-std.rlib": nil, + "vendor/libstd.dylib.so": nil, + "vendor/librust_vendor_available.dylib.so": nil, "vendor/crtbegin_so.o": nil, "vendor/crtend_so.o": nil, "vendor/libclang_rt.builtins-aarch64-android.a": nil, @@ -931,7 +1039,9 @@ func TestVendorSnapshotUse(t *testing.T) { } sharedVariant := "android_vendor.30_arm64_armv8-a_shared" - rlibVariant := "android_vendor.30_arm64_armv8-a_rlib_rlib-std" + rlibVariant := "android_vendor.30_arm64_armv8-a_rlib_dylib-std" + rlibRlibStdVariant := "android_vendor.30_arm64_armv8-a_rlib_rlib-std" + dylibVariant := "android_vendor.30_arm64_armv8-a_dylib" staticVariant := "android_vendor.30_arm64_armv8-a_static" binaryVariant := "android_vendor.30_arm64_armv8-a" @@ -963,14 +1073,9 @@ func TestVendorSnapshotUse(t *testing.T) { t.Errorf("wanted libclient AndroidMkStaticLibs %q, got %q", w, g) } - libclientAndroidMkRlibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkRlibs - if g, w := libclientAndroidMkRlibs, []string{"librust_vendor_available.vendor.rlib-std", "libstd.vendor"}; !reflect.DeepEqual(g, w) { - t.Errorf("wanted libclient libclientAndroidMkRlibs %q, got %q", w, g) - } - libclientAndroidMkDylibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkDylibs - if len(libclientAndroidMkDylibs) > 0 { - t.Errorf("wanted libclient libclientAndroidMkDylibs [], got %q", libclientAndroidMkDylibs) + if g, w := libclientAndroidMkDylibs, []string{"librust_vendor_available.vendor", "libstd.vendor"}; !reflect.DeepEqual(g, w) { + t.Errorf("wanted libclient libclientAndroidMkDylibs %q, got %q", w, libclientAndroidMkDylibs) } libclient32AndroidMkSharedLibs := ctx.ModuleForTests("libclient", shared32Variant).Module().(*Module).Properties.AndroidMkSharedLibs @@ -979,22 +1084,39 @@ func TestVendorSnapshotUse(t *testing.T) { } libclientRustAndroidMkRlibs := ctx.ModuleForTests("libclient_rust", rlibVariant).Module().(*Module).Properties.AndroidMkRlibs - if g, w := libclientRustAndroidMkRlibs, []string{"librust_vendor_available.vendor.rlib-std", "libstd.vendor"}; !reflect.DeepEqual(g, w) { - t.Errorf("wanted libclient libclientAndroidMkRlibs %q, got %q", w, g) + if g, w := libclientRustAndroidMkRlibs, []string{"librust_vendor_available.vendor"}; !reflect.DeepEqual(g, w) { + t.Errorf("wanted rlib libclient libclientAndroidMkRlibs %q, got %q", w, g) + } + + libclientRlibStdRustAndroidMkRlibs := ctx.ModuleForTests("libclient_rust", rlibRlibStdVariant).Module().(*Module).Properties.AndroidMkRlibs + if g, w := libclientRlibStdRustAndroidMkRlibs, []string{"librust_vendor_available.vendor.rlib-std", "libstd.vendor"}; !reflect.DeepEqual(g, w) { + t.Errorf("wanted rlib libclient libclientAndroidMkRlibs %q, got %q", w, g) + } + + libclientRustDylibAndroidMkDylibs := ctx.ModuleForTests("libclient_rust", dylibVariant).Module().(*Module).Properties.AndroidMkDylibs + if g, w := libclientRustDylibAndroidMkDylibs, []string{"librust_vendor_available.vendor", "libstd.vendor"}; !reflect.DeepEqual(g, w) { + t.Errorf("wanted dylib libclient libclientRustDylibAndroidMkDylibs %q, got %q", w, g) } // rust vendor snapshot must have ".vendor" suffix in AndroidMk librustVendorAvailableSnapshotModule := ctx.ModuleForTests("librust_vendor_available.vendor_rlib.30.arm64", rlibVariant).Module() librustVendorSnapshotMkName := android.AndroidMkEntriesForTest(t, ctx, librustVendorAvailableSnapshotModule)[0].EntryMap["LOCAL_MODULE"][0] - expectedRustVendorSnapshotName := "librust_vendor_available.vendor.rlib-std" + expectedRustVendorSnapshotName := "librust_vendor_available.vendor" if librustVendorSnapshotMkName != expectedRustVendorSnapshotName { t.Errorf("Unexpected rust vendor snapshot name in AndroidMk: %q, expected: %q\n", librustVendorSnapshotMkName, expectedRustVendorSnapshotName) } + librustVendorAvailableDylibSnapshotModule := ctx.ModuleForTests("librust_vendor_available.vendor_dylib.30.arm64", dylibVariant).Module() + librustVendorSnapshotDylibMkName := android.AndroidMkEntriesForTest(t, ctx, librustVendorAvailableDylibSnapshotModule)[0].EntryMap["LOCAL_MODULE"][0] + expectedRustVendorDylibSnapshotName := "librust_vendor_available.vendor" + if librustVendorSnapshotDylibMkName != expectedRustVendorDylibSnapshotName { + t.Errorf("Unexpected rust vendor snapshot name in AndroidMk: %q, expected: %q\n", librustVendorSnapshotDylibMkName, expectedRustVendorDylibSnapshotName) + } + rustVendorBinModule := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Module() - rustVendorBinMkRlibName := android.AndroidMkEntriesForTest(t, ctx, rustVendorBinModule)[0].EntryMap["LOCAL_RLIB_LIBRARIES"][0] - if rustVendorBinMkRlibName != expectedRustVendorSnapshotName { - t.Errorf("Unexpected rust rlib name in AndroidMk: %q, expected: %q\n", rustVendorBinMkRlibName, expectedRustVendorSnapshotName) + rustVendorBinMkDylibName := android.AndroidMkEntriesForTest(t, ctx, rustVendorBinModule)[0].EntryMap["LOCAL_DYLIB_LIBRARIES"][0] + if rustVendorBinMkDylibName != expectedRustVendorSnapshotName { + t.Errorf("Unexpected rust rlib name in AndroidMk: %q, expected: %q\n", rustVendorBinMkDylibName, expectedRustVendorSnapshotName) } binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("rustLink").Args["linkFlags"] @@ -1051,18 +1173,18 @@ func TestRecoverySnapshotCapture(t *testing.T) { crate_name: "recovery_available", } - rust_library_rlib { - name: "librecovery_rlib", + rust_library { + name: "librecovery_rustlib", recovery: true, srcs: ["foo.rs"], - crate_name: "recovery_rlib", + crate_name: "recovery_rustlib", } - rust_library_rlib { - name: "librecovery_available_rlib", + rust_library { + name: "librecovery_available_rustlib", recovery_available: true, srcs: ["foo.rs"], - crate_name: "recovery_available_rlib", + crate_name: "recovery_available_rustlib", } rust_binary { @@ -1113,13 +1235,29 @@ func TestRecoverySnapshotCapture(t *testing.T) { filepath.Join(staticDir, "librecovery_available.a.json")) // For rlib libraries, all recovery:true and recovery_available modules are captured. - rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant) + rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_dylib-std", archType, archVariant) rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib") - cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rlib", "librecovery_rlib.rlib", rlibDir, rlibVariant) - cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rlib", "librecovery_available_rlib.rlib", rlibDir, rlibVariant) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib", rlibDir, rlibVariant) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib", rlibDir, rlibVariant) jsonFiles = append(jsonFiles, - filepath.Join(rlibDir, "librecovery_rlib.rlib.json"), - filepath.Join(rlibDir, "librecovery_available_rlib.rlib.json")) + filepath.Join(rlibDir, "librecovery_rustlib.rlib.json"), + filepath.Join(rlibDir, "librecovery_available_rustlib.rlib.json")) + + rlibRlibStdVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant) + jsonFiles = append(jsonFiles, + filepath.Join(rlibDir, "librecovery_rustlib.rlib-std.rlib.json"), + filepath.Join(rlibDir, "librecovery_available_rustlib.rlib-std.rlib.json")) + + // For dylib libraries, all recovery:true and recovery_available modules are captured. + dylibVariant := fmt.Sprintf("android_recovery_%s_%s_dylib", archType, archVariant) + dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib") + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.dylib.so", dylibDir, dylibVariant) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.dylib.so", dylibDir, dylibVariant) + jsonFiles = append(jsonFiles, + filepath.Join(dylibDir, "librecovery_rustlib.dylib.so.json"), + filepath.Join(dylibDir, "librecovery_available_rustlib.dylib.so.json")) // For binary executables, all recovery:true and recovery_available modules are captured. if archType == "arm64" { @@ -1169,25 +1307,25 @@ func TestRecoverySnapshotExclude(t *testing.T) { exclude_from_recovery_snapshot: true, crate_name: "available_exclude", } - rust_library_rlib { - name: "libinclude_rlib", + rust_library { + name: "libinclude_rustlib", srcs: ["src/include.rs"], recovery_available: true, - crate_name: "include_rlib", + crate_name: "include_rustlib", } - rust_library_rlib { - name: "libexclude_rlib", + rust_library { + name: "libexclude_rustlib", srcs: ["src/exclude.rs"], recovery: true, exclude_from_recovery_snapshot: true, - crate_name: "exclude_rlib", + crate_name: "exclude_rustlib", } - rust_library_rlib { - name: "libavailable_exclude_rlib", + rust_library { + name: "libavailable_exclude_rustlib", srcs: ["src/exclude.rs"], recovery_available: true, exclude_from_recovery_snapshot: true, - crate_name: "available_exclude_rlib", + crate_name: "available_exclude_rustlib", } ` @@ -1198,11 +1336,11 @@ func TestRecoverySnapshotExclude(t *testing.T) { recovery: true, crate_name: "recovery", } - rust_library_rlib { - name: "librecovery_rlib", + rust_library { + name: "librecovery_rustlib", srcs: ["recovery.rs"], recovery: true, - crate_name: "recovery_rlib", + crate_name: "recovery_rustlib", } ` @@ -1220,14 +1358,25 @@ func TestRecoverySnapshotExclude(t *testing.T) { cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude", false, sharedRecoveryVariant) cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude", true, sharedRecoveryVariant) cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude", true, sharedRecoveryVariant) - cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rlib", false, rlibRecoveryVariant) - cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rlib", true, rlibRecoveryVariant) - cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rlib", true, rlibRecoveryVariant) + + cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rustlib", false, rlibRecoveryVariant) + cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rustlib", true, rlibRecoveryVariant) + cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rustlib", true, rlibRlibStdRecoveryVariant) + + cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rustlib", false, rlibRlibStdRecoveryVariant) + cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rustlib", true, rlibRlibStdRecoveryVariant) + cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rustlib", true, rlibRlibStdRecoveryVariant) + + cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude_rustlib", false, dylibRecoveryVariant) + cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude_rustlib", true, dylibRecoveryVariant) + cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude_rustlib", true, dylibRecoveryVariant) // A recovery module is excluded, but by its path not the exclude_from_recovery_snapshot property // ('device/' and 'vendor/' are default excluded). See snapshot/recovery_snapshot.go for more detail. cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery", false, sharedRecoveryVariant) - cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rlib", false, rlibRecoveryVariant) + cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rustlib", false, rlibRecoveryVariant) + cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rustlib", false, rlibRlibStdRecoveryVariant) + cc.AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery_rustlib", false, dylibRecoveryVariant) // Verify the content of the recovery snapshot. @@ -1246,15 +1395,21 @@ func TestRecoverySnapshotExclude(t *testing.T) { archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant) sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant) - rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant) + rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_dylib-std", archType, archVariant) + rlibRlibStdVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant) + dylibVariant := fmt.Sprintf("android_recovery_%s_%s_dylib", archType, archVariant) sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared") rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib") + dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib") // Included modules + cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant) includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json")) - cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude_rlib", "libinclude_rlib.rlib", rlibDir, rlibVariant) - includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "libinclude_rlib.rlib.json")) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude_rustlib", "libinclude_rustlib.rlib", rlibDir, rlibVariant) + includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "libinclude_rustlib.rlib.json")) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude_rustlib", "libinclude_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant) + includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "libinclude_rustlib.rlib-std.rlib.json")) // Excluded modules cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant) @@ -1263,12 +1418,27 @@ func TestRecoverySnapshotExclude(t *testing.T) { excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json")) cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant) excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json")) - cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rlib", "libexclude_rlib.rlib", rlibDir, rlibVariant) - excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rlib.rlib.json")) - cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rlib", "librecovery_rlib.rlib", rlibDir, rlibVariant) - excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rlib.rlib.json")) - cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rlib", "libavailable_exclude_rlib.rlib", rlibDir, rlibVariant) - excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rlib.rlib.json")) + + cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rustlib", "libexclude_rustlib.rlib", rlibDir, rlibVariant) + excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rustlib.rlib.json")) + cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib", rlibDir, rlibVariant) + excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib.json")) + cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rustlib", "libavailable_exclude_rustlib.rlib", rlibDir, rlibVariant) + excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rustlib.rlib.json")) + + cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rustlib", "libexclude_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant) + excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rustlib.rlib-std.rlib.json")) + cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant) + excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib-std.rlib.json")) + cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rustlib", "libavailable_exclude_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant) + excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rustlib.rlib-std.rlib.json")) + + cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude_rustlib", "libexclude_rustlib.dylib.so", dylibDir, dylibVariant) + excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libexclude_rustlib.dylib.so.json")) + cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.dylib.so", dylibDir, dylibVariant) + excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.dylib.so.json")) + cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude_rustlib", "libavailable_exclude_rustlib.dylib.so", dylibDir, dylibVariant) + excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "libavailable_exclude_rustlib.dylib.so.json")) } // Verify that each json file for an included module has a rule. @@ -1302,15 +1472,15 @@ func TestRecoverySnapshotDirected(t *testing.T) { srcs: ["foo.rs"], } - rust_library_rlib { - name: "librecovery_rlib", + rust_library { + name: "librecovery_rustlib", recovery: true, crate_name: "recovery", srcs: ["foo.rs"], } - rust_library_rlib { - name: "librecovery_available_rlib", + rust_library { + name: "librecovery_available_rustlib", recovery_available: true, crate_name: "recovery_available", srcs: ["foo.rs"], @@ -1335,7 +1505,7 @@ func TestRecoverySnapshotDirected(t *testing.T) { ctx := testRustRecoveryFsVersions(t, bp, rustMockedFiles, "current", "29", "current") ctx.Config().TestProductVariables.RecoverySnapshotModules = make(map[string]bool) ctx.Config().TestProductVariables.RecoverySnapshotModules["librecovery"] = true - ctx.Config().TestProductVariables.RecoverySnapshotModules["librecovery_rlib"] = true + ctx.Config().TestProductVariables.RecoverySnapshotModules["librecovery_rustlib"] = true ctx.Config().TestProductVariables.DirectedRecoverySnapshot = true // Check recovery snapshot output. @@ -1353,15 +1523,22 @@ func TestRecoverySnapshotDirected(t *testing.T) { archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant) sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant) - rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant) + rlibVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_dylib-std", archType, archVariant) + rlibRlibStdVariant := fmt.Sprintf("android_recovery_%s_%s_rlib_rlib-std", archType, archVariant) + dylibVariant := fmt.Sprintf("android_recovery_%s_%s_dylib", archType, archVariant) sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared") rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib") + dylibDir := filepath.Join(snapshotVariantPath, archDir, "dylib") // Included modules cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant) includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json")) - cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rlib", "librecovery_rlib.rlib", rlibDir, rlibVariant) - includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_rlib.rlib.json")) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib", rlibDir, rlibVariant) + includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib.json")) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant) + includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_rustlib.rlib-std.rlib.json")) + cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_rustlib", "librecovery_rustlib.dylib.so", dylibDir, dylibVariant) + includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librecovery_rustlib.dylib.so.json")) // TODO: When Rust supports the "prefer" property for prebuilts, perform this check. /* @@ -1374,8 +1551,12 @@ func TestRecoverySnapshotDirected(t *testing.T) { // are still included as fake modules. cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant) includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery_available.so.json")) - cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rlib", "librecovery_available_rlib.rlib", rlibDir, rlibVariant) - includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_available_rlib.rlib.json")) + cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib", rlibDir, rlibVariant) + includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_available_rustlib.rlib.json")) + cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.rlib-std.rlib", rlibDir, rlibRlibStdVariant) + includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librecovery_available_rustlib.rlib-std.rlib.json")) + cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available_rustlib", "librecovery_available_rustlib.dylib.so", dylibDir, dylibVariant) + includeJsonFiles = append(includeJsonFiles, filepath.Join(dylibDir, "librecovery_available_rustlib.dylib.so.json")) } // Verify that each json file for an included module has a rule. diff --git a/starlark_import/unmarshal.go b/starlark_import/unmarshal.go index 1b5443782..0e6f13030 100644 --- a/starlark_import/unmarshal.go +++ b/starlark_import/unmarshal.go @@ -25,12 +25,14 @@ import ( ) func Unmarshal[T any](value starlark.Value) (T, error) { - var zero T - x, err := UnmarshalReflect(value, reflect.TypeOf(zero)) + x, err := UnmarshalReflect(value, reflect.TypeOf((*T)(nil)).Elem()) return x.Interface().(T), err } func UnmarshalReflect(value starlark.Value, ty reflect.Type) (reflect.Value, error) { + if ty == reflect.TypeOf((*starlark.Value)(nil)).Elem() { + return reflect.ValueOf(value), nil + } zero := reflect.Zero(ty) var result reflect.Value if ty.Kind() == reflect.Interface { @@ -286,3 +288,17 @@ func typeOfStarlarkValue(value starlark.Value) (reflect.Type, error) { return nil, fmt.Errorf("unimplemented starlark type: %s", value.Type()) } } + +// NoneableString converts a starlark.Value to a string pointer. If the starlark.Value is NoneType, +// a nil pointer will be returned instead. All other types of starlark values are errors. +func NoneableString(value starlark.Value) (*string, error) { + switch v := value.(type) { + case starlark.String: + result := v.GoString() + return &result, nil + case starlark.NoneType: + return nil, nil + default: + return nil, fmt.Errorf("expected string or none, got %q", value.Type()) + } +} diff --git a/starlark_import/unmarshal_test.go b/starlark_import/unmarshal_test.go index ee7a9e340..bc0ea4c49 100644 --- a/starlark_import/unmarshal_test.go +++ b/starlark_import/unmarshal_test.go @@ -30,7 +30,7 @@ func createStarlarkValue(t *testing.T, code string) starlark.Value { return result["x"] } -func TestUnmarshallConcreteType(t *testing.T) { +func TestUnmarshalConcreteType(t *testing.T) { x, err := Unmarshal[string](createStarlarkValue(t, `"foo"`)) if err != nil { t.Error(err) @@ -41,7 +41,7 @@ func TestUnmarshallConcreteType(t *testing.T) { } } -func TestUnmarshallConcreteTypeWithInterfaces(t *testing.T) { +func TestUnmarshalConcreteTypeWithInterfaces(t *testing.T) { x, err := Unmarshal[map[string]map[string]interface{}](createStarlarkValue(t, `{"foo": {"foo2": "foo3"}, "bar": {"bar2": ["bar3"]}}`)) if err != nil { @@ -57,7 +57,22 @@ func TestUnmarshallConcreteTypeWithInterfaces(t *testing.T) { } } -func TestUnmarshall(t *testing.T) { +func TestUnmarshalToStarlarkValue(t *testing.T) { + x, err := Unmarshal[map[string]starlark.Value](createStarlarkValue(t, + `{"foo": "Hi", "bar": None}`)) + if err != nil { + t.Error(err) + return + } + if x["foo"].(starlark.String).GoString() != "Hi" { + t.Errorf("Expected \"Hi\", got: %q", x["foo"].(starlark.String).GoString()) + } + if x["bar"].Type() != "NoneType" { + t.Errorf("Expected \"NoneType\", got: %q", x["bar"].Type()) + } +} + +func TestUnmarshal(t *testing.T) { testCases := []struct { input string expected interface{} diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh index 43a9f0fed..48f654e1c 100755 --- a/tests/run_integration_tests.sh +++ b/tests/run_integration_tests.sh @@ -10,7 +10,7 @@ TOP="$(readlink -f "$(dirname "$0")"/../../..)" "$TOP/build/soong/tests/persistent_bazel_test.sh" "$TOP/build/soong/tests/soong_test.sh" "$TOP/build/soong/tests/stale_metrics_files_test.sh" -"$TOP/build/bazel/ci/rbc_regression_test.sh" aosp_arm64-userdebug +"$TOP/prebuilts/build-tools/linux-x86/bin/py3-cmd" "$TOP/build/bazel/ci/rbc_dashboard.py" aosp_arm64-userdebug # The following tests build against the full source tree and don't rely on the # mock client. diff --git a/zip/cmd/BUILD.bazel b/zip/cmd/BUILD.bazel deleted file mode 100644 index e04a1e10d..000000000 --- a/zip/cmd/BUILD.bazel +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (C) 2022 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# TODO(b/194644518): Switch to the source version when Bazel can build go -# binaries. -alias( - name = "soong_zip", - actual = "//prebuilts/build-tools:linux-x86/bin/soong_zip", -) |