diff options
Diffstat (limited to 'bp2build')
| -rw-r--r-- | bp2build/Android.bp | 4 | ||||
| -rw-r--r-- | bp2build/bp2build.go | 14 | ||||
| -rw-r--r-- | bp2build/build_conversion.go | 14 | ||||
| -rw-r--r-- | bp2build/bzl_conversion_test.go | 2 | ||||
| -rw-r--r-- | bp2build/cc_library_shared_conversion_test.go | 55 | ||||
| -rw-r--r-- | bp2build/conversion.go | 15 | ||||
| -rw-r--r-- | bp2build/conversion_test.go | 11 | ||||
| -rw-r--r-- | bp2build/linker_config_conversion_test.go | 59 | ||||
| -rw-r--r-- | bp2build/metrics.go | 2 | ||||
| -rw-r--r-- | bp2build/symlink_forest.go | 27 |
10 files changed, 171 insertions, 32 deletions
diff --git a/bp2build/Android.bp b/bp2build/Android.bp index 34548ed95..07557d604 100644 --- a/bp2build/Android.bp +++ b/bp2build/Android.bp @@ -20,15 +20,16 @@ bootstrap_go_package { "soong-android", "soong-android-allowlists", "soong-android-soongconfig", - "soong-shared", "soong-apex", "soong-bazel", "soong-cc", "soong-cc-config", "soong-etc", "soong-genrule", + "soong-linkerconfig", "soong-python", "soong-sh", + "soong-shared", "soong-starlark-format", "soong-ui-metrics", ], @@ -58,6 +59,7 @@ bootstrap_go_package { "java_library_host_conversion_test.go", "java_plugin_conversion_test.go", "java_proto_conversion_test.go", + "linker_config_conversion_test.go", "performance_test.go", "prebuilt_etc_conversion_test.go", "python_binary_conversion_test.go", diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go index b0c3899ba..0e3d2a5f9 100644 --- a/bp2build/bp2build.go +++ b/bp2build/bp2build.go @@ -29,7 +29,9 @@ import ( func Codegen(ctx *CodegenContext) CodegenMetrics { // This directory stores BUILD files that could be eventually checked-in. bp2buildDir := android.PathForOutput(ctx, "bp2build") - android.RemoveAllOutputDir(bp2buildDir) + if err := android.RemoveAllOutputDir(bp2buildDir); err != nil { + fmt.Printf("ERROR: Encountered error while cleaning %s: %s", bp2buildDir, err.Error()) + } res, errs := GenerateBazelTargets(ctx, true) if len(errs) > 0 { @@ -40,7 +42,7 @@ func Codegen(ctx *CodegenContext) CodegenMetrics { fmt.Printf("ERROR: Encountered %d error(s): \nERROR: %s", len(errs), strings.Join(errMsgs, "\n")) os.Exit(1) } - bp2buildFiles := CreateBazelFiles(nil, res.buildFileToTargets, ctx.mode) + bp2buildFiles := CreateBazelFiles(ctx.Config(), nil, res.buildFileToTargets, ctx.mode) writeFiles(ctx, bp2buildDir, bp2buildFiles) soongInjectionDir := android.PathForOutput(ctx, bazel.SoongInjectionDirName) @@ -52,7 +54,9 @@ func Codegen(ctx *CodegenContext) CodegenMetrics { // Get the output directory and create it if it doesn't exist. func getOrCreateOutputDir(outputDir android.OutputPath, ctx android.PathContext, dir string) android.OutputPath { dirPath := outputDir.Join(ctx, dir) - android.CreateOutputDirIfNonexistent(dirPath, os.ModePerm) + if err := android.CreateOutputDirIfNonexistent(dirPath, os.ModePerm); err != nil { + fmt.Printf("ERROR: path %s: %s", dirPath, err.Error()) + } return dirPath } @@ -60,13 +64,13 @@ func getOrCreateOutputDir(outputDir android.OutputPath, ctx android.PathContext, func writeFiles(ctx android.PathContext, outputDir android.OutputPath, files []BazelFile) { for _, f := range files { p := getOrCreateOutputDir(outputDir, ctx, f.Dir).Join(ctx, f.Basename) - if err := writeFile(ctx, p, f.Contents); err != nil { + if err := writeFile(p, f.Contents); err != nil { panic(fmt.Errorf("Failed to write %q (dir %q) due to %q", f.Basename, f.Dir, err)) } } } -func writeFile(ctx android.PathContext, pathToFile android.OutputPath, content string) error { +func writeFile(pathToFile android.OutputPath, content string) error { // These files are made editable to allow users to modify and iterate on them // in the source tree. return android.WriteFileToOutputDir(pathToFile, []byte(content), 0644) diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go index a96a3fc7b..415becb84 100644 --- a/bp2build/build_conversion.go +++ b/bp2build/build_conversion.go @@ -161,22 +161,22 @@ type CodegenContext struct { unconvertedDepMode unconvertedDepsMode } -func (c *CodegenContext) Mode() CodegenMode { - return c.mode +func (ctx *CodegenContext) Mode() CodegenMode { + return ctx.mode } // CodegenMode is an enum to differentiate code-generation modes. type CodegenMode int const ( - // Bp2Build: generate BUILD files with targets buildable by Bazel directly. + // Bp2Build - generate BUILD files with targets buildable by Bazel directly. // // This mode is used for the Soong->Bazel build definition conversion. Bp2Build CodegenMode = iota - // QueryView: generate BUILD files with targets representing fully mutated + // QueryView - generate BUILD files with targets representing fully mutated // Soong modules, representing the fully configured Soong module graph with - // variants and dependency endges. + // variants and dependency edges. // // This mode is used for discovering and introspecting the existing Soong // module graph. @@ -470,13 +470,13 @@ func generateSoongModuleTarget(ctx bpToBuildContext, m blueprint.Module) BazelTa }) } - for p, _ := range ignoredPropNames { + for p := range ignoredPropNames { delete(props.Attrs, p) } attributes := propsToAttributes(props.Attrs) depLabelList := "[\n" - for depLabel, _ := range depLabels { + for depLabel := range depLabels { depLabelList += fmt.Sprintf(" %q,\n", depLabel) } depLabelList += " ]" diff --git a/bp2build/bzl_conversion_test.go b/bp2build/bzl_conversion_test.go index f3345a6ae..6cb9509ed 100644 --- a/bp2build/bzl_conversion_test.go +++ b/bp2build/bzl_conversion_test.go @@ -189,7 +189,7 @@ func TestGenerateSoongModuleBzl(t *testing.T) { content: "irrelevant", }, } - files := CreateBazelFiles(ruleShims, make(map[string]BazelTargets), QueryView) + files := CreateBazelFiles(android.NullConfig("out", "out/soong"), ruleShims, make(map[string]BazelTargets), QueryView) var actualSoongModuleBzl BazelFile for _, f := range files { diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go index be096168c..74729e4e1 100644 --- a/bp2build/cc_library_shared_conversion_test.go +++ b/bp2build/cc_library_shared_conversion_test.go @@ -569,3 +569,58 @@ func TestCcLibrarySharedConvertLex(t *testing.T) { }, }) } + +func TestCcLibrarySharedClangUnknownFlags(t *testing.T) { + runCcLibrarySharedTestCase(t, bp2buildTestCase{ + blueprint: soongCcProtoPreamble + `cc_library_shared { + name: "foo", + conlyflags: ["-a", "-finline-functions"], + cflags: ["-b","-finline-functions"], + cppflags: ["-c", "-finline-functions"], + ldflags: ["-d","-finline-functions", "-e"], + include_build_directory: false, +}`, + expectedBazelTargets: []string{ + makeBazelTarget("cc_library_shared", "foo", attrNameToString{ + "conlyflags": `["-a"]`, + "copts": `["-b"]`, + "cppflags": `["-c"]`, + "linkopts": `[ + "-d", + "-e", + ]`, + }), + }, + }) +} + +func TestCCLibraryFlagSpaceSplitting(t *testing.T) { + runCcLibrarySharedTestCase(t, bp2buildTestCase{ + blueprint: soongCcProtoPreamble + `cc_library_shared { + name: "foo", + conlyflags: [ "-include header.h"], + cflags: ["-include header.h"], + cppflags: ["-include header.h"], + version_script: "version_script", + include_build_directory: false, +}`, + expectedBazelTargets: []string{ + makeBazelTarget("cc_library_shared", "foo", attrNameToString{ + "additional_linker_inputs": `["version_script"]`, + "conlyflags": `[ + "-include", + "header.h", + ]`, + "copts": `[ + "-include", + "header.h", + ]`, + "cppflags": `[ + "-include", + "header.h", + ]`, + "linkopts": `["-Wl,--version-script,$(location version_script)"]`, + }), + }, + }) +} diff --git a/bp2build/conversion.go b/bp2build/conversion.go index 4b013d913..8cf9beaf4 100644 --- a/bp2build/conversion.go +++ b/bp2build/conversion.go @@ -10,6 +10,8 @@ import ( cc_config "android/soong/cc/config" java_config "android/soong/java/config" + "android/soong/apex" + "github.com/google/blueprint/proptools" ) @@ -28,6 +30,9 @@ func CreateSoongInjectionFiles(cfg android.Config, metrics CodegenMetrics) []Baz files = append(files, newFile("java_toolchain", GeneratedBuildFileName, "")) // Creates a //java_toolchain package. files = append(files, newFile("java_toolchain", "constants.bzl", java_config.BazelJavaToolchainVars(cfg))) + files = append(files, newFile("apex_toolchain", GeneratedBuildFileName, "")) // Creates a //apex_toolchain package. + files = append(files, newFile("apex_toolchain", "constants.bzl", apex.BazelApexToolchainVars())) + files = append(files, newFile("metrics", "converted_modules.txt", strings.Join(metrics.convertedModules, "\n"))) files = append(files, newFile("product_config", "soong_config_variables.bzl", cfg.Bp2buildSoongConfigDefinitions.String())) @@ -50,6 +55,7 @@ func convertedModules(convertedModules []string) string { } func CreateBazelFiles( + cfg android.Config, ruleShims map[string]RuleShim, buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile { @@ -74,16 +80,19 @@ func CreateBazelFiles( files = append(files, newFile(bazelRulesSubDir, "soong_module.bzl", generateSoongModuleBzl(ruleShims))) } - files = append(files, createBuildFiles(buildToTargets, mode)...) + files = append(files, createBuildFiles(cfg, buildToTargets, mode)...) return files } -func createBuildFiles(buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile { +func createBuildFiles(cfg android.Config, buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile { files := make([]BazelFile, 0, len(buildToTargets)) + warnNotWriting := cfg.IsEnvTrue("BP2BUILD_VERBOSE") for _, dir := range android.SortedStringKeys(buildToTargets) { if mode == Bp2Build && android.ShouldKeepExistingBuildFileForDir(dir) { - fmt.Printf("[bp2build] Not writing generated BUILD file for dir: '%s'\n", dir) + if warnNotWriting { + fmt.Printf("[bp2build] Not writing generated BUILD file for dir: '%s'\n", dir) + } continue } targets := buildToTargets[dir] diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go index e49d8553b..0cb711ca5 100644 --- a/bp2build/conversion_test.go +++ b/bp2build/conversion_test.go @@ -27,7 +27,8 @@ type bazelFilepath struct { } func TestCreateBazelFiles_QueryView_AddsTopLevelFiles(t *testing.T) { - files := CreateBazelFiles(map[string]RuleShim{}, map[string]BazelTargets{}, QueryView) + files := CreateBazelFiles(android.NullConfig("out", "out/soong"), + map[string]RuleShim{}, map[string]BazelTargets{}, QueryView) expectedFilePaths := []bazelFilepath{ { dir: "", @@ -103,6 +104,14 @@ func TestCreateBazelFiles_Bp2Build_CreatesDefaultFiles(t *testing.T) { basename: "constants.bzl", }, { + dir: "apex_toolchain", + basename: GeneratedBuildFileName, + }, + { + dir: "apex_toolchain", + basename: "constants.bzl", + }, + { dir: "metrics", basename: "converted_modules.txt", }, diff --git a/bp2build/linker_config_conversion_test.go b/bp2build/linker_config_conversion_test.go new file mode 100644 index 000000000..4662af4c1 --- /dev/null +++ b/bp2build/linker_config_conversion_test.go @@ -0,0 +1,59 @@ +// Copyright 2022 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bp2build + +import ( + "fmt" + "testing" + + "android/soong/linkerconfig" +) + +func runLinkerConfigTestCase(t *testing.T, tc bp2buildTestCase) { + t.Helper() + (&tc).moduleTypeUnderTest = "linker_config" + (&tc).moduleTypeUnderTestFactory = linkerconfig.LinkerConfigFactory + runBp2BuildTestCaseSimple(t, tc) +} + +func TestLinkerConfigConvertsSrc(t *testing.T) { + runLinkerConfigTestCase(t, + bp2buildTestCase{ + blueprint: ` +linker_config { + name: "foo", + src: "a.json", +} +`, + expectedBazelTargets: []string{makeBazelTarget("linker_config", "foo", attrNameToString{ + "src": `"a.json"`, + })}, + }) + +} + +func TestLinkerConfigNoSrc(t *testing.T) { + runLinkerConfigTestCase(t, + bp2buildTestCase{ + blueprint: ` +linker_config { + name: "foo", +} +`, + expectedBazelTargets: []string{}, + expectedErr: fmt.Errorf("Android.bp:2:1: module \"foo\": src: empty src is not supported"), + }) + +} diff --git a/bp2build/metrics.go b/bp2build/metrics.go index 04fac441e..3a21c3454 100644 --- a/bp2build/metrics.go +++ b/bp2build/metrics.go @@ -116,8 +116,6 @@ func (metrics *CodegenMetrics) Write(dir string) { } if _, err := os.Stat(metricsFile); err != nil { fail(err, "MISSING BP2BUILD METRICS OUTPUT: Failed to `stat` %s", metricsFile) - } else { - fmt.Printf("\nWrote bp2build metrics to: %s\n", metricsFile) } } diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go index 818d7aece..78e7b0e75 100644 --- a/bp2build/symlink_forest.go +++ b/bp2build/symlink_forest.go @@ -1,6 +1,7 @@ package bp2build import ( + "android/soong/android" "fmt" "io/ioutil" "os" @@ -21,7 +22,7 @@ type node struct { children map[string]*node } -// Ensures that the a node for the given path exists in the tree and returns it. +// Ensures that the node for the given path exists in the tree and returns it. func ensureNodeExists(root *node, path string) *node { if path == "" { return root @@ -114,7 +115,7 @@ func isDir(path string, fi os.FileInfo) bool { // contain every file in buildFilesDir and srcDir excluding the files in // exclude. Collects every directory encountered during the traversal of srcDir // into acc. -func plantSymlinkForestRecursive(topdir string, forestDir string, buildFilesDir string, srcDir string, exclude *node, acc *[]string, okay *bool) { +func plantSymlinkForestRecursive(cfg android.Config, topdir string, forestDir string, buildFilesDir string, srcDir string, exclude *node, acc *[]string, okay *bool) { if exclude != nil && exclude.excluded { // This directory is not needed, bail out return @@ -125,11 +126,11 @@ func plantSymlinkForestRecursive(topdir string, forestDir string, buildFilesDir buildFilesMap := readdirToMap(shared.JoinPath(topdir, buildFilesDir)) allEntries := make(map[string]bool) - for n, _ := range srcDirMap { + for n := range srcDirMap { allEntries[n] = true } - for n, _ := range buildFilesMap { + for n := range buildFilesMap { allEntries[n] = true } @@ -139,7 +140,7 @@ func plantSymlinkForestRecursive(topdir string, forestDir string, buildFilesDir os.Exit(1) } - for f, _ := range allEntries { + for f := range allEntries { if f[0] == '.' { continue // Ignore dotfiles } @@ -179,7 +180,7 @@ func plantSymlinkForestRecursive(topdir string, forestDir string, buildFilesDir if bDir && excludeChild != nil { // Not in the source tree, but we have to exclude something from under // this subtree, so descend - plantSymlinkForestRecursive(topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay) + plantSymlinkForestRecursive(cfg, topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay) } else { // Not in the source tree, symlink BUILD file symlinkIntoForest(topdir, forestChild, buildFilesChild) @@ -188,19 +189,21 @@ func plantSymlinkForestRecursive(topdir string, forestDir string, buildFilesDir if sDir && excludeChild != nil { // Not in the build file tree, but we have to exclude something from // under this subtree, so descend - plantSymlinkForestRecursive(topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay) + plantSymlinkForestRecursive(cfg, topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay) } else { // Not in the build file tree, symlink source tree, carry on symlinkIntoForest(topdir, forestChild, srcChild) } } else if sDir && bDir { // Both are directories. Descend. - plantSymlinkForestRecursive(topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay) + plantSymlinkForestRecursive(cfg, topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay) } else if !sDir && !bDir { // Neither is a directory. Prioritize BUILD files generated by bp2build // over any BUILD file imported into external/. - fmt.Fprintf(os.Stderr, "Both '%s' and '%s' exist, symlinking the former to '%s'\n", - buildFilesChild, srcChild, forestChild) + if cfg.IsEnvTrue("BP2BUILD_VERBOSE") { + fmt.Fprintf(os.Stderr, "Both '%s' and '%s' exist, symlinking the former to '%s'\n", + buildFilesChild, srcChild, forestChild) + } symlinkIntoForest(topdir, forestChild, buildFilesChild) } else { // Both exist and one is a file. This is an error. @@ -216,12 +219,12 @@ func plantSymlinkForestRecursive(topdir string, forestDir string, buildFilesDir // "srcDir" while excluding paths listed in "exclude". Returns the set of paths // under srcDir on which readdir() had to be called to produce the symlink // forest. -func PlantSymlinkForest(topdir string, forest string, buildFiles string, srcDir string, exclude []string) []string { +func PlantSymlinkForest(cfg android.Config, topdir string, forest string, buildFiles string, srcDir string, exclude []string) []string { deps := make([]string, 0) os.RemoveAll(shared.JoinPath(topdir, forest)) excludeTree := treeFromExcludePathList(exclude) okay := true - plantSymlinkForestRecursive(topdir, forest, buildFiles, srcDir, excludeTree, &deps, &okay) + plantSymlinkForestRecursive(cfg, topdir, forest, buildFiles, srcDir, excludeTree, &deps, &okay) if !okay { os.Exit(1) } |