summaryrefslogtreecommitdiff
path: root/bp2build
diff options
context:
space:
mode:
Diffstat (limited to 'bp2build')
-rw-r--r--bp2build/Android.bp4
-rw-r--r--bp2build/bp2build.go14
-rw-r--r--bp2build/build_conversion.go14
-rw-r--r--bp2build/bzl_conversion_test.go2
-rw-r--r--bp2build/cc_library_shared_conversion_test.go55
-rw-r--r--bp2build/conversion.go15
-rw-r--r--bp2build/conversion_test.go11
-rw-r--r--bp2build/linker_config_conversion_test.go59
-rw-r--r--bp2build/metrics.go2
-rw-r--r--bp2build/symlink_forest.go27
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)
}