Merge "Silence unpack-prebuilt-apex"
diff --git a/android/androidmk.go b/android/androidmk.go
index 9025a74..0adc2a6 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -114,7 +114,7 @@
// If true, the module is skipped and does not appear on the final Android-<product name>.mk
// file. Useful when a module needs to be skipped conditionally.
Disabled bool
- // The postprocessing mk file to include, e.g. $(BUILD_SYSTEM)/soong_cc_prebuilt.mk
+ // The postprocessing mk file to include, e.g. $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk
// If not set, $(BUILD_SYSTEM)/prebuilt.mk is used.
Include string
// Required modules that need to be built and included in the final build output when building
diff --git a/android/bazel.go b/android/bazel.go
index 32963b3..bf214a5 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -32,6 +32,10 @@
Bazel_module bazel.BazelModuleProperties
}
+// namespacedVariableProperties is a map from a string representing a Soong
+// config variable namespace, like "android" or "vendor_name" to a struct
+// pointer representing the soong_config_variables property of a module created
+// by a soong_config_module_type or soong_config_module_type_import.
type namespacedVariableProperties map[string]interface{}
// BazelModuleBase contains the property structs with metadata for modules which can be converted to
@@ -328,12 +332,11 @@
// Per-module denylist to opt modules out of mixed builds. Such modules will
// still be generated via bp2build.
mixedBuildsDisabledList = []string{
- "libbrotli", // http://b/198585397, ld.lld: error: bionic/libc/arch-arm64/generic/bionic/memmove.S:95:(.text+0x10): relocation R_AARCH64_CONDBR19 out of range: -1404176 is not in [-1048576, 1048575]; references __memcpy
- "func_to_syscall_nrs", // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module.
- "libseccomp_policy_app_zygote_sources", // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module.
- "libseccomp_policy_app_sources", // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module.
- "libseccomp_policy_system_sources", // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module.
- "minijail_constants_json", // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module.
+ "libbrotli", // http://b/198585397, ld.lld: error: bionic/libc/arch-arm64/generic/bionic/memmove.S:95:(.text+0x10): relocation R_AARCH64_CONDBR19 out of range: -1404176 is not in [-1048576, 1048575]; references __memcpy
+ "minijail_constants_json", // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module.
+
+ "cap_names.h", // TODO(b/204913827) runfiles need to be handled in mixed builds
+ "libcap", // TODO(b/204913827) runfiles need to be handled in mixed builds
}
// Used for quicker lookups
diff --git a/android/defs.go b/android/defs.go
index c8e2e9b..362b382 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -52,10 +52,10 @@
// A copy rule.
Cp = pctx.AndroidStaticRule("Cp",
blueprint.RuleParams{
- Command: "rm -f $out && cp $cpPreserveSymlinks $cpFlags $in $out",
+ Command: "rm -f $out && cp $cpPreserveSymlinks $cpFlags $in $out$extraCmds",
Description: "cp $out",
},
- "cpFlags")
+ "cpFlags", "extraCmds")
// A copy rule that only updates the output if it changed.
CpIfChanged = pctx.AndroidStaticRule("CpIfChanged",
@@ -68,10 +68,10 @@
CpExecutable = pctx.AndroidStaticRule("CpExecutable",
blueprint.RuleParams{
- Command: "rm -f $out && cp $cpPreserveSymlinks $cpFlags $in $out && chmod +x $out",
+ Command: "rm -f $out && cp $cpPreserveSymlinks $cpFlags $in $out && chmod +x $out$extraCmds",
Description: "cp $out",
},
- "cpFlags")
+ "cpFlags", "extraCmds")
// A timestamp touch rule.
Touch = pctx.AndroidStaticRule("Touch",
diff --git a/android/makevars.go b/android/makevars.go
index 665d576..ece7091 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -456,6 +456,9 @@
for _, dep := range install.implicitDeps {
fmt.Fprintf(buf, " %s", dep.String())
}
+ if extraFiles := install.extraFiles; extraFiles != nil {
+ fmt.Fprintf(buf, " %s", extraFiles.zip.String())
+ }
if len(install.orderOnlyDeps) > 0 {
fmt.Fprintf(buf, " |")
}
@@ -463,12 +466,14 @@
fmt.Fprintf(buf, " %s", dep.String())
}
fmt.Fprintln(buf)
-
- fmt.Fprintf(buf, "\trm -f $@ && cp -f %s $< $@", preserveSymlinksFlag)
+ fmt.Fprintln(buf, "\t@echo \"Install $@\"")
+ fmt.Fprintf(buf, "\trm -f $@ && cp -f %s $< $@\n", preserveSymlinksFlag)
if install.executable {
- fmt.Fprintf(buf, " && chmod +x $@")
+ fmt.Fprintf(buf, "\tchmod +x $@\n")
}
- fmt.Fprintln(buf)
+ if extraFiles := install.extraFiles; extraFiles != nil {
+ fmt.Fprintf(buf, "\tunzip -qDD -d '%s' '%s'\n", extraFiles.dir.String(), extraFiles.zip.String())
+ }
fmt.Fprintln(buf)
}
@@ -504,6 +509,7 @@
fromStr = symlink.absFrom
}
+ fmt.Fprintln(buf, "\t@echo \"Symlink $@\"")
fmt.Fprintf(buf, "\trm -f $@ && ln -sfn %s $@", fromStr)
fmt.Fprintln(buf)
fmt.Fprintln(buf)
diff --git a/android/module.go b/android/module.go
index c778078..e100330 100644
--- a/android/module.go
+++ b/android/module.go
@@ -381,6 +381,16 @@
// for which IsInstallDepNeeded returns true.
InstallFile(installPath InstallPath, name string, srcPath Path, deps ...Path) InstallPath
+ // InstallFileWithExtraFilesZip creates a rule to copy srcPath to name in the installPath
+ // directory, and also unzip a zip file containing extra files to install into the same
+ // directory.
+ //
+ // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
+ // installed file will be returned by PackagingSpecs() on this module or by
+ // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
+ // for which IsInstallDepNeeded returns true.
+ InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path, extraZip Path, deps ...Path) InstallPath
+
// InstallSymlink creates a rule to create a symlink from src srcPath to name in the installPath
// directory.
//
@@ -2235,10 +2245,16 @@
implicitDeps Paths
orderOnlyDeps Paths
executable bool
+ extraFiles *extraFilesZip
absFrom string
}
+type extraFilesZip struct {
+ zip Path
+ dir InstallPath
+}
+
type katiInstalls []katiInstall
// BuiltInstalled returns the katiInstalls in the form used by $(call copy-many-files) in Make, a
@@ -2852,12 +2868,20 @@
func (m *moduleContext) InstallFile(installPath InstallPath, name string, srcPath Path,
deps ...Path) InstallPath {
- return m.installFile(installPath, name, srcPath, deps, false)
+ return m.installFile(installPath, name, srcPath, deps, false, nil)
}
func (m *moduleContext) InstallExecutable(installPath InstallPath, name string, srcPath Path,
deps ...Path) InstallPath {
- return m.installFile(installPath, name, srcPath, deps, true)
+ return m.installFile(installPath, name, srcPath, deps, true, nil)
+}
+
+func (m *moduleContext) InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path,
+ extraZip Path, deps ...Path) InstallPath {
+ return m.installFile(installPath, name, srcPath, deps, false, &extraFilesZip{
+ zip: extraZip,
+ dir: installPath,
+ })
}
func (m *moduleContext) PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec {
@@ -2878,7 +2902,8 @@
return spec
}
-func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path, deps []Path, executable bool) InstallPath {
+func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path, deps []Path,
+ executable bool, extraZip *extraFilesZip) InstallPath {
fullInstallPath := installPath.Join(m, name)
m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
@@ -2906,6 +2931,7 @@
implicitDeps: implicitDeps,
orderOnlyDeps: orderOnlyDeps,
executable: executable,
+ extraFiles: extraZip,
})
} else {
rule := Cp
@@ -2913,6 +2939,13 @@
rule = CpExecutable
}
+ extraCmds := ""
+ if extraZip != nil {
+ extraCmds += fmt.Sprintf(" && unzip -qDD -d '%s' '%s'",
+ extraZip.dir.String(), extraZip.zip.String())
+ implicitDeps = append(implicitDeps, extraZip.zip)
+ }
+
m.Build(pctx, BuildParams{
Rule: rule,
Description: "install " + fullInstallPath.Base(),
@@ -2921,6 +2954,9 @@
Implicits: implicitDeps,
OrderOnly: orderOnlyDeps,
Default: !m.Config().KatiEnabled(),
+ Args: map[string]string{
+ "extraCmds": extraCmds,
+ },
})
}
diff --git a/android/neverallow.go b/android/neverallow.go
index 04366d3..b36bf04 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -214,8 +214,11 @@
return []Rule{
NeverAllow().
ModuleType("makefile_goal").
+ // TODO(b/33691272): remove this after migrating seapp to Soong
+ Without("product_out_path", "obj/ETC/plat_seapp_contexts_intermediates/plat_seapp_contexts").
+ Without("product_out_path", "obj/ETC/plat_seapp_neverallows_intermediates/plat_seapp_neverallows").
WithoutMatcher("product_out_path", Regexp("^boot[0-9a-zA-Z.-]*[.]img$")).
- Because("Only boot images may be imported as a makefile goal."),
+ Because("Only boot images and seapp contexts may be imported as a makefile goal."),
}
}
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 35aadd8..edda244 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -293,7 +293,7 @@
`),
},
expectedErrors: []string{
- "Only boot images may be imported as a makefile goal.",
+ "Only boot images and seapp contexts may be imported as a makefile goal.",
},
},
}
diff --git a/android/variable.go b/android/variable.go
index 6ad58c3..89cd59e 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -491,11 +491,11 @@
type ProductConfigProperty struct {
// The name of the product variable, e.g. "safestack", "malloc_not_svelte",
// "board"
- ProductConfigVariable string
+ Name string
// Namespace of the variable, if this is a soong_config_module_type variable
- // e.g. "acme", "ANDROID", "vendor_nae"
- Namespace string // for soong config variables
+ // e.g. "acme", "ANDROID", "vendor_name"
+ Namespace string
// Unique configuration to identify this product config property (i.e. a
// primary key), as just using the product variable name is not sufficient.
@@ -562,9 +562,6 @@
// "acme__board__soc_a", "acme__board__soc_b", and
// "acme__board__conditions_default"
FullConfig string
-
- // The actual property value: list, bool, string..
- Property interface{}
}
func (p *ProductConfigProperty) ConfigurationAxis() bazel.ConfigurationAxis {
@@ -573,14 +570,43 @@
} else {
// Soong config variables can be uniquely identified by the namespace
// (e.g. acme, android) and the product variable name (e.g. board, size)
- return bazel.ProductVariableConfigurationAxis(p.Namespace + "__" + p.ProductConfigVariable)
+ return bazel.ProductVariableConfigurationAxis(p.Namespace + "__" + p.Name)
}
}
-// ProductConfigProperties is a map of property name to a slice of
-// ProductConfigProperty such that all product variable-specific versions of a
-// property are easily accessed together
-type ProductConfigProperties map[string]map[string]ProductConfigProperty
+// SelectKey returns the literal string that represents this variable in a BUILD
+// select statement.
+func (p *ProductConfigProperty) SelectKey() string {
+ if p.Namespace == "" {
+ return strings.ToLower(p.FullConfig)
+ }
+
+ if p.FullConfig == bazel.ConditionsDefaultConfigKey {
+ return bazel.ConditionsDefaultConfigKey
+ }
+
+ value := p.FullConfig
+ if value == p.Name {
+ value = "enabled"
+ }
+ // e.g. acme__feature1__enabled, android__board__soc_a
+ return strings.ToLower(strings.Join([]string{p.Namespace, p.Name, value}, "__"))
+}
+
+// ProductConfigProperties is a map of maps to group property values according
+// their property name and the product config variable they're set under.
+//
+// The outer map key is the name of the property, like "cflags".
+//
+// The inner map key is a ProductConfigProperty, which is a struct of product
+// variable name, namespace, and the "full configuration" of the product
+// variable.
+//
+// e.g. product variable name: board, namespace: acme, full config: vendor_chip_foo
+//
+// The value of the map is the interface{} representing the value of the
+// property, like ["-DDEFINES"] for cflags.
+type ProductConfigProperties map[string]map[ProductConfigProperty]interface{}
// ProductVariableProperties returns a ProductConfigProperties containing only the properties which
// have been set for the module in the given context.
@@ -630,19 +656,16 @@
func (p *ProductConfigProperties) AddProductConfigProperty(
propertyName, namespace, productVariableName, config string, property interface{}) {
if (*p)[propertyName] == nil {
- (*p)[propertyName] = make(map[string]ProductConfigProperty)
+ (*p)[propertyName] = make(map[ProductConfigProperty]interface{})
}
- // Normalize config to be all lowercase. It's the "primary key" of this
- // unique property value. This can be the conditions_default value of the
- // product variable as well.
- config = strings.ToLower(config)
- (*p)[propertyName][config] = ProductConfigProperty{
- Namespace: namespace, // e.g. acme, android
- ProductConfigVariable: productVariableName, // e.g. size, feature1, feature2, FEATURE3, board
- FullConfig: config, // e.g. size, feature1-x86, size__conditions_default
- Property: property, // e.g. ["-O3"]
+ productConfigProp := ProductConfigProperty{
+ Namespace: namespace, // e.g. acme, android
+ Name: productVariableName, // e.g. size, feature1, feature2, FEATURE3, board
+ FullConfig: config, // e.g. size, feature1-x86, size__conditions_default
}
+
+ (*p)[propertyName][productConfigProp] = property
}
var (
@@ -783,8 +806,8 @@
if field.Field(k).IsZero() {
continue
}
- productVariableValue := proptools.PropertyNameForField(propertyName)
- config := strings.Join([]string{namespace, productVariableName, productVariableValue}, "__")
+ // config can also be "conditions_default".
+ config := proptools.PropertyNameForField(propertyName)
actualPropertyName := field.Type().Field(k).Name
productConfigProperties.AddProductConfigProperty(
@@ -799,9 +822,6 @@
// Not a conditions_default or a struct prop, i.e. regular
// product variables, or not a string-typed config var.
config := productVariableName + suffix
- if namespace != "" {
- config = namespace + "__" + config
- }
productConfigProperties.AddProductConfigProperty(
propertyName,
namespace,
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index f3ad152..1045ca6 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -58,6 +58,7 @@
"LOCAL_MODULE_STEM": stem,
"LOCAL_MODULE_HOST_OS": hostOs,
"LOCAL_RESOURCE_DIR": localizePathList("resource_dirs"),
+ "LOCAL_NOTICE_FILE": localizePathList("android_license_files"),
"LOCAL_SANITIZE": sanitize(""),
"LOCAL_SANITIZE_DIAG": sanitize("diag."),
"LOCAL_STRIP_MODULE": strip(),
@@ -111,7 +112,6 @@
"LOCAL_PROTOC_OPTIMIZE_TYPE": "proto.type",
"LOCAL_MODULE_OWNER": "owner",
"LOCAL_RENDERSCRIPT_TARGET_API": "renderscript.target_api",
- "LOCAL_NOTICE_FILE": "notice",
"LOCAL_JAVA_LANGUAGE_VERSION": "java_version",
"LOCAL_INSTRUMENTATION_FOR": "instrumentation_for",
"LOCAL_MANIFEST_FILE": "manifest",
@@ -185,6 +185,12 @@
"LOCAL_JACK_COVERAGE_EXCLUDE_FILTER": "jacoco.exclude_filter",
"LOCAL_FULL_LIBS_MANIFEST_FILES": "additional_manifests",
+
+ // will be rewrite later to "license_kinds:" by byfix
+ "LOCAL_LICENSE_KINDS": "android_license_kinds",
+ // will be removed later by byfix
+ // TODO: does this property matter in the license module?
+ "LOCAL_LICENSE_CONDITIONS": "android_license_conditions",
})
addStandardProperties(bpparser.BoolType,
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 775a9a8..ca40aaa 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -1516,7 +1516,8 @@
],
}
`,
- }, {
+ },
+ {
desc: "Obsolete LOCAL_MODULE_PATH",
in: `
include $(CLEAR_VARS)
@@ -1532,7 +1533,37 @@
name: "foo",
}
-`},
+`,
+ },
+ {
+ desc: "LOCAL_LICENSE_KINDS, LOCAL_LICENSE_CONDITIONS, LOCAL_NOTICE_FILE",
+ // TODO(b/205615944): When valid "android_license_files" exists, the test requires an Android.mk
+ // file (and an Android.bp file is required as well if the license files locates outside the current
+ // directory). So plan to use a mock file system to mock the Android.mk and Android.bp files.
+ in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := foo
+LOCAL_LICENSE_KINDS := license_kind
+LOCAL_LICENSE_CONDITIONS := license_condition
+LOCAL_NOTICE_FILE := license_notice
+include $(BUILD_PACKAGE)
+`,
+ expected: `
+package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "Android-Apache-2.0",
+ ],
+}
+
+android_app {
+ name: "foo",
+ // ANDROIDMK TRANSLATION ERROR: Only $(LOCAL_PATH)/.. values are allowed
+ // LOCAL_NOTICE_FILE := license_notice
+
+}
+`,
+ },
}
func TestEndToEnd(t *testing.T) {
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 4f37fc3..2048429 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -103,6 +103,11 @@
return moduleNames
}
+ // Avoid creating duplicate build rules for multi-installed APEXes.
+ if proptools.BoolDefault(a.properties.Multi_install_skip_symbol_files, false) {
+ return moduleNames
+ }
+
var postInstallCommands []string
for _, fi := range a.filesInfo {
if a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform() {
@@ -258,7 +263,7 @@
if !ok {
panic(fmt.Sprintf("Expected %s to be AndroidAppSet", fi.module))
}
- fmt.Fprintln(w, "LOCAL_APK_SET_INSTALL_FILE :=", as.InstallFile())
+ fmt.Fprintln(w, "LOCAL_APK_SET_INSTALL_FILE :=", as.PackedAdditionalOutputs().String())
fmt.Fprintln(w, "LOCAL_APKCERTS_FILE :=", as.APKCertsFile().String())
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_android_app_set.mk")
case nativeSharedLib, nativeExecutable, nativeTest:
@@ -272,7 +277,7 @@
fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", ccMod.CoverageOutputFile().String())
}
}
- fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_prebuilt.mk")
+ fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk")
default:
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.stem())
if fi.builtFile == a.manifestPbOut && apexType == flattenedApex {
diff --git a/apex/apex.go b/apex/apex.go
index 20660d3..378efe6 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -145,6 +145,16 @@
// Should be only used in non-system apexes (e.g. vendor: true). Default is false.
Use_vndk_as_stable *bool
+ // Whether this is multi-installed APEX should skip installing symbol files.
+ // Multi-installed APEXes share the same apex_name and are installed at the same time.
+ // Default is false.
+ //
+ // Should be set to true for all multi-installed APEXes except the singular
+ // default version within the multi-installed group.
+ // Only the default version can install symbol files in $(PRODUCT_OUT}/apex,
+ // or else conflicting build rules may be created.
+ Multi_install_skip_symbol_files *bool
+
// List of SDKs that are used to build this APEX. A reference to an SDK should be either
// `name#version` or `name` which is an alias for `name#current`. If left empty,
// `platform#current` is implied. This value affects all modules included in this APEX. In
diff --git a/apex/builder.go b/apex/builder.go
index 2e21ddf..3599c5d 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -442,7 +442,8 @@
} else {
if fi.class == appSet {
copyCommands = append(copyCommands,
- fmt.Sprintf("unzip -qDD -d %s %s", destPathDir, fi.builtFile.String()))
+ fmt.Sprintf("unzip -qDD -d %s %s", destPathDir,
+ fi.module.(*java.AndroidAppSet).PackedAdditionalOutputs().String()))
} else {
copyCommands = append(copyCommands, "cp -f "+fi.builtFile.String()+" "+destPath)
}
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 6d96b1c..fd8cf67 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -18,6 +18,7 @@
"encoding/json"
"fmt"
"path/filepath"
+ "regexp"
"strings"
"github.com/google/blueprint/proptools"
@@ -59,6 +60,8 @@
InputDepSetIds []int
Mnemonic string
OutputIds []int
+ TemplateContent string
+ Substitutions []KeyValuePair
}
// actionGraphContainer contains relevant portions of Bazel's aquery proto, ActionGraphContainer.
@@ -100,6 +103,20 @@
artifactIdToPath map[int]string
}
+// The tokens should be substituted with the value specified here, instead of the
+// one returned in 'substitutions' of TemplateExpand action.
+var TemplateActionOverriddenTokens = map[string]string{
+ // Uses "python3" for %python_binary% instead of the value returned by aquery
+ // which is "py3wrapper.sh". See removePy3wrapperScript.
+ "%python_binary%": "python3",
+}
+
+// This pattern matches the MANIFEST file created for a py_binary target.
+var manifestFilePattern = regexp.MustCompile(".*/.+\\.runfiles/MANIFEST$")
+
+// The file name of py3wrapper.sh, which is used by py_binary targets.
+var py3wrapperFileName = "/py3wrapper.sh"
+
func newAqueryHandler(aqueryResult actionGraphContainer) (*aqueryArtifactHandler, error) {
pathFragments := map[int]pathFragment{}
for _, pathFragment := range aqueryResult.PathFragments {
@@ -163,7 +180,31 @@
}
}
}
- return inputPaths, nil
+
+ // TODO(b/197135294): Clean up this custom runfiles handling logic when
+ // SourceSymlinkManifest and SymlinkTree actions are supported.
+ filteredInputPaths := filterOutPy3wrapperAndManifestFileFromInputPaths(inputPaths)
+
+ return filteredInputPaths, nil
+}
+
+// See go/python-binary-host-mixed-build for more details.
+// 1) For py3wrapper.sh, there is no action for creating py3wrapper.sh in the aquery output of
+// Bazel py_binary targets, so there is no Ninja build statements generated for creating it.
+// 2) For MANIFEST file, SourceSymlinkManifest action is in aquery output of Bazel py_binary targets,
+// but it doesn't contain sufficient information so no Ninja build statements are generated
+// for creating it.
+// So in mixed build mode, when these two are used as input of some Ninja build statement,
+// since there is no build statement to create them, they should be removed from input paths.
+func filterOutPy3wrapperAndManifestFileFromInputPaths(inputPaths []string) []string {
+ filteredInputPaths := []string{}
+ for _, path := range inputPaths {
+ if strings.HasSuffix(path, py3wrapperFileName) || manifestFilePattern.MatchString(path) {
+ continue
+ }
+ filteredInputPaths = append(filteredInputPaths, path)
+ }
+ return filteredInputPaths
}
func (a *aqueryArtifactHandler) artifactIdsFromDepsetId(depsetId int) ([]int, error) {
@@ -230,7 +271,7 @@
}
buildStatement := BuildStatement{
- Command: strings.Join(proptools.ShellEscapeList(actionEntry.Arguments), " "),
+ Command: strings.Join(proptools.ShellEscapeListIncludingSpaces(actionEntry.Arguments), " "),
Depfile: depfile,
OutputPaths: outputPaths,
InputPaths: inputPaths,
@@ -249,6 +290,45 @@
// Use absolute paths, because some soong actions don't play well with relative paths (for example, `cp -d`).
buildStatement.Command = fmt.Sprintf("mkdir -p %[1]s && rm -f %[2]s && ln -sf %[3]s %[2]s", outDir, out, in)
buildStatement.SymlinkPaths = outputPaths[:]
+ } else if isTemplateExpandAction(actionEntry) && len(actionEntry.Arguments) < 1 {
+ if len(outputPaths) != 1 {
+ return nil, fmt.Errorf("Expect 1 output to template expand action, got: output %q", outputPaths)
+ }
+ expandedTemplateContent := expandTemplateContent(actionEntry)
+ // The expandedTemplateContent is escaped for being used in double quotes and shell unescape,
+ // and the new line characters (\n) are also changed to \\n which avoids some Ninja escape on \n, which might
+ // change \n to space and mess up the format of Python programs.
+ // sed is used to convert \\n back to \n before saving to output file.
+ // See go/python-binary-host-mixed-build for more details.
+ command := fmt.Sprintf(`/bin/bash -c 'echo "%[1]s" | sed "s/\\\\n/\\n/g" > %[2]s && chmod a+x %[2]s'`,
+ escapeCommandlineArgument(expandedTemplateContent), outputPaths[0])
+ buildStatement.Command = command
+ } else if isPythonZipperAction(actionEntry) {
+ if len(inputPaths) < 1 || len(outputPaths) != 1 {
+ return nil, fmt.Errorf("Expect 1+ input and 1 output to python zipper action, got: input %q, output %q", inputPaths, outputPaths)
+ }
+ buildStatement.InputPaths, buildStatement.Command = removePy3wrapperScript(buildStatement)
+ buildStatement.Command = addCommandForPyBinaryRunfilesDir(buildStatement, inputPaths[0], outputPaths[0])
+ // Add the python zip file as input of the corresponding python binary stub script in Ninja build statements.
+ // In Ninja build statements, the outputs of dependents of a python binary have python binary stub script as input,
+ // which is not sufficient without the python zip file from which runfiles directory is created for py_binary.
+ //
+ // The following logic relies on that Bazel aquery output returns actions in the order that
+ // PythonZipper is after TemplateAction of creating Python binary stub script. If later Bazel doesn't return actions
+ // in that order, the following logic might not find the build statement generated for Python binary
+ // stub script and the build might fail. So the check of pyBinaryFound is added to help debug in case later Bazel might change aquery output.
+ // See go/python-binary-host-mixed-build for more details.
+ pythonZipFilePath := outputPaths[0]
+ pyBinaryFound := false
+ for i, _ := range buildStatements {
+ if len(buildStatements[i].OutputPaths) == 1 && buildStatements[i].OutputPaths[0]+".zip" == pythonZipFilePath {
+ buildStatements[i].InputPaths = append(buildStatements[i].InputPaths, pythonZipFilePath)
+ pyBinaryFound = true
+ }
+ }
+ if !pyBinaryFound {
+ return nil, fmt.Errorf("Could not find the correspondinging Python binary stub script of PythonZipper: %q", outputPaths)
+ }
} else if len(actionEntry.Arguments) < 1 {
return nil, fmt.Errorf("received action with no command: [%v]", buildStatement)
}
@@ -258,10 +338,85 @@
return buildStatements, nil
}
+// expandTemplateContent substitutes the tokens in a template.
+func expandTemplateContent(actionEntry action) string {
+ replacerString := []string{}
+ for _, pair := range actionEntry.Substitutions {
+ value := pair.Value
+ if val, ok := TemplateActionOverriddenTokens[pair.Key]; ok {
+ value = val
+ }
+ replacerString = append(replacerString, pair.Key, value)
+ }
+ replacer := strings.NewReplacer(replacerString...)
+ return replacer.Replace(actionEntry.TemplateContent)
+}
+
+func escapeCommandlineArgument(str string) string {
+ // \->\\, $->\$, `->\`, "->\", \n->\\n, '->'"'"'
+ replacer := strings.NewReplacer(
+ `\`, `\\`,
+ `$`, `\$`,
+ "`", "\\`",
+ `"`, `\"`,
+ "\n", "\\n",
+ `'`, `'"'"'`,
+ )
+ return replacer.Replace(str)
+}
+
+// removePy3wrapperScript removes py3wrapper.sh from the input paths and command of the action of
+// creating python zip file in mixed build mode. py3wrapper.sh is returned as input by aquery but
+// there is no action returned by aquery for creating it. So in mixed build "python3" is used
+// as the PYTHON_BINARY in python binary stub script, and py3wrapper.sh is not needed and should be
+// removed from input paths and command of creating python zip file.
+// See go/python-binary-host-mixed-build for more details.
+// TODO(b/205879240) remove this after py3wrapper.sh could be created in the mixed build mode.
+func removePy3wrapperScript(bs BuildStatement) (newInputPaths []string, newCommand string) {
+ // Remove from inputs
+ filteredInputPaths := []string{}
+ for _, path := range bs.InputPaths {
+ if !strings.HasSuffix(path, py3wrapperFileName) {
+ filteredInputPaths = append(filteredInputPaths, path)
+ }
+ }
+ newInputPaths = filteredInputPaths
+
+ // Remove from command line
+ var re = regexp.MustCompile(`\S*` + py3wrapperFileName)
+ newCommand = re.ReplaceAllString(bs.Command, "")
+ return
+}
+
+// addCommandForPyBinaryRunfilesDir adds commands creating python binary runfiles directory.
+// runfiles directory is created by using MANIFEST file and MANIFEST file is the output of
+// SourceSymlinkManifest action is in aquery output of Bazel py_binary targets,
+// but since SourceSymlinkManifest doesn't contain sufficient information
+// so MANIFEST file could not be created, which also blocks the creation of runfiles directory.
+// See go/python-binary-host-mixed-build for more details.
+// TODO(b/197135294) create runfiles directory from MANIFEST file once it can be created from SourceSymlinkManifest action.
+func addCommandForPyBinaryRunfilesDir(bs BuildStatement, zipperCommandPath, zipFilePath string) string {
+ // Unzip the zip file, zipFilePath looks like <python_binary>.zip
+ runfilesDirName := zipFilePath[0:len(zipFilePath)-4] + ".runfiles"
+ command := fmt.Sprintf("%s x %s -d %s", zipperCommandPath, zipFilePath, runfilesDirName)
+ // Create a symbolic link in <python_binary>.runfiles/, which is the expected structure
+ // when running the python binary stub script.
+ command += fmt.Sprintf(" && ln -sf runfiles/__main__ %s", runfilesDirName)
+ return bs.Command + " && " + command
+}
+
func isSymlinkAction(a action) bool {
return a.Mnemonic == "Symlink" || a.Mnemonic == "SolibSymlink"
}
+func isTemplateExpandAction(a action) bool {
+ return a.Mnemonic == "TemplateExpand"
+}
+
+func isPythonZipperAction(a action) bool {
+ return a.Mnemonic == "PythonZipper"
+}
+
func shouldSkipAction(a action) bool {
// TODO(b/180945121): Handle complex symlink actions.
if a.Mnemonic == "SymlinkTree" || a.Mnemonic == "SourceSymlinkManifest" {
diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go
index 69f1115..68e50c2 100644
--- a/bazel/aquery_test.go
+++ b/bazel/aquery_test.go
@@ -709,7 +709,7 @@
}
expectedBuildStatements := []BuildStatement{
BuildStatement{
- Command: "/bin/bash -c touch bazel-out/sourceroot/k8-fastbuild/bin/testpkg/test_out",
+ Command: "/bin/bash -c 'touch bazel-out/sourceroot/k8-fastbuild/bin/testpkg/test_out'",
OutputPaths: []string{"bazel-out/sourceroot/k8-fastbuild/bin/testpkg/test_out"},
InputPaths: inputPaths,
Mnemonic: "Action",
@@ -1015,6 +1015,355 @@
assertError(t, err, `Expect 1 input and 1 output to symlink action, got: input ["file"], output ["symlink" "other_symlink"]`)
}
+func TestTemplateExpandActionSubstitutions(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [{
+ "id": 1,
+ "pathFragmentId": 1
+ }],
+ "actions": [{
+ "targetId": 1,
+ "actionKey": "x",
+ "mnemonic": "TemplateExpand",
+ "configurationId": 1,
+ "outputIds": [1],
+ "primaryOutputId": 1,
+ "executionPlatform": "//build/bazel/platforms:linux_x86_64",
+ "templateContent": "Test template substitutions: %token1%, %python_binary%",
+ "substitutions": [{
+ "key": "%token1%",
+ "value": "abcd"
+ },{
+ "key": "%python_binary%",
+ "value": "python3"
+ }]
+ }],
+ "pathFragments": [{
+ "id": 1,
+ "label": "template_file"
+ }]
+}`
+
+ actual, err := AqueryBuildStatements([]byte(inputString))
+
+ if err != nil {
+ t.Errorf("Unexpected error %q", err)
+ }
+
+ expectedBuildStatements := []BuildStatement{
+ BuildStatement{
+ Command: "/bin/bash -c 'echo \"Test template substitutions: abcd, python3\" | sed \"s/\\\\\\\\n/\\\\n/g\" > template_file && " +
+ "chmod a+x template_file'",
+ OutputPaths: []string{"template_file"},
+ Mnemonic: "TemplateExpand",
+ },
+ }
+ assertBuildStatements(t, expectedBuildStatements, actual)
+}
+
+func TestTemplateExpandActionNoOutput(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [{
+ "id": 1,
+ "pathFragmentId": 1
+ }],
+ "actions": [{
+ "targetId": 1,
+ "actionKey": "x",
+ "mnemonic": "TemplateExpand",
+ "configurationId": 1,
+ "primaryOutputId": 1,
+ "executionPlatform": "//build/bazel/platforms:linux_x86_64",
+ "templateContent": "Test template substitutions: %token1%, %python_binary%",
+ "substitutions": [{
+ "key": "%token1%",
+ "value": "abcd"
+ },{
+ "key": "%python_binary%",
+ "value": "python3"
+ }]
+ }],
+ "pathFragments": [{
+ "id": 1,
+ "label": "template_file"
+ }]
+}`
+
+ _, err := AqueryBuildStatements([]byte(inputString))
+ assertError(t, err, `Expect 1 output to template expand action, got: output []`)
+}
+
+func TestPythonZipperActionSuccess(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [{
+ "id": 1,
+ "pathFragmentId": 1
+ },{
+ "id": 2,
+ "pathFragmentId": 2
+ },{
+ "id": 3,
+ "pathFragmentId": 3
+ },{
+ "id": 4,
+ "pathFragmentId": 4
+ },{
+ "id": 5,
+ "pathFragmentId": 10
+ },{
+ "id": 10,
+ "pathFragmentId": 20
+ }],
+ "actions": [{
+ "targetId": 1,
+ "actionKey": "x",
+ "mnemonic": "TemplateExpand",
+ "configurationId": 1,
+ "outputIds": [1],
+ "primaryOutputId": 1,
+ "executionPlatform": "//build/bazel/platforms:linux_x86_64",
+ "templateContent": "Test template substitutions: %token1%, %python_binary%",
+ "substitutions": [{
+ "key": "%token1%",
+ "value": "abcd"
+ },{
+ "key": "%python_binary%",
+ "value": "python3"
+ }]
+ },{
+ "targetId": 1,
+ "actionKey": "x",
+ "mnemonic": "PythonZipper",
+ "configurationId": 1,
+ "arguments": ["../bazel_tools/tools/zip/zipper/zipper", "cC", "python_binary.zip", "__main__.py\u003dbazel-out/k8-fastbuild/bin/python_binary.temp", "__init__.py\u003d", "runfiles/__main__/__init__.py\u003d", "runfiles/__main__/python_binary.py\u003dpython_binary.py", "runfiles/bazel_tools/tools/python/py3wrapper.sh\u003dbazel-out/bazel_tools/k8-fastbuild/bin/tools/python/py3wrapper.sh"],
+ "outputIds": [2],
+ "inputDepSetIds": [1],
+ "primaryOutputId": 2
+ }],
+ "depSetOfFiles": [{
+ "id": 1,
+ "directArtifactIds": [4, 3, 5]
+ }],
+ "pathFragments": [{
+ "id": 1,
+ "label": "python_binary"
+ },{
+ "id": 2,
+ "label": "python_binary.zip"
+ },{
+ "id": 3,
+ "label": "python_binary.py"
+ },{
+ "id": 9,
+ "label": ".."
+ }, {
+ "id": 8,
+ "label": "bazel_tools",
+ "parentId": 9
+ }, {
+ "id": 7,
+ "label": "tools",
+ "parentId": 8
+ }, {
+ "id": 6,
+ "label": "zip",
+ "parentId": 7
+ }, {
+ "id": 5,
+ "label": "zipper",
+ "parentId": 6
+ }, {
+ "id": 4,
+ "label": "zipper",
+ "parentId": 5
+ },{
+ "id": 16,
+ "label": "bazel-out"
+ },{
+ "id": 15,
+ "label": "bazel_tools",
+ "parentId": 16
+ }, {
+ "id": 14,
+ "label": "k8-fastbuild",
+ "parentId": 15
+ }, {
+ "id": 13,
+ "label": "bin",
+ "parentId": 14
+ }, {
+ "id": 12,
+ "label": "tools",
+ "parentId": 13
+ }, {
+ "id": 11,
+ "label": "python",
+ "parentId": 12
+ }, {
+ "id": 10,
+ "label": "py3wrapper.sh",
+ "parentId": 11
+ },{
+ "id": 20,
+ "label": "python_binary"
+ }]
+}`
+ actual, err := AqueryBuildStatements([]byte(inputString))
+
+ if err != nil {
+ t.Errorf("Unexpected error %q", err)
+ }
+
+ expectedBuildStatements := []BuildStatement{
+ BuildStatement{
+ Command: "/bin/bash -c 'echo \"Test template substitutions: abcd, python3\" | sed \"s/\\\\\\\\n/\\\\n/g\" > python_binary && " +
+ "chmod a+x python_binary'",
+ InputPaths: []string{"python_binary.zip"},
+ OutputPaths: []string{"python_binary"},
+ Mnemonic: "TemplateExpand",
+ },
+ BuildStatement{
+ Command: "../bazel_tools/tools/zip/zipper/zipper cC python_binary.zip __main__.py=bazel-out/k8-fastbuild/bin/python_binary.temp " +
+ "__init__.py= runfiles/__main__/__init__.py= runfiles/__main__/python_binary.py=python_binary.py && " +
+ "../bazel_tools/tools/zip/zipper/zipper x python_binary.zip -d python_binary.runfiles && ln -sf runfiles/__main__ python_binary.runfiles",
+ InputPaths: []string{"../bazel_tools/tools/zip/zipper/zipper", "python_binary.py"},
+ OutputPaths: []string{"python_binary.zip"},
+ Mnemonic: "PythonZipper",
+ },
+ }
+ assertBuildStatements(t, expectedBuildStatements, actual)
+}
+
+func TestPythonZipperActionNoInput(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [{
+ "id": 1,
+ "pathFragmentId": 1
+ },{
+ "id": 2,
+ "pathFragmentId": 2
+ }],
+ "actions": [{
+ "targetId": 1,
+ "actionKey": "x",
+ "mnemonic": "PythonZipper",
+ "configurationId": 1,
+ "arguments": ["../bazel_tools/tools/zip/zipper/zipper", "cC", "python_binary.zip", "__main__.py\u003dbazel-out/k8-fastbuild/bin/python_binary.temp", "__init__.py\u003d", "runfiles/__main__/__init__.py\u003d", "runfiles/__main__/python_binary.py\u003dpython_binary.py", "runfiles/bazel_tools/tools/python/py3wrapper.sh\u003dbazel-out/bazel_tools/k8-fastbuild/bin/tools/python/py3wrapper.sh"],
+ "outputIds": [2],
+ "primaryOutputId": 2
+ }],
+ "pathFragments": [{
+ "id": 1,
+ "label": "python_binary"
+ },{
+ "id": 2,
+ "label": "python_binary.zip"
+ }]
+}`
+ _, err := AqueryBuildStatements([]byte(inputString))
+ assertError(t, err, `Expect 1+ input and 1 output to python zipper action, got: input [], output ["python_binary.zip"]`)
+}
+
+func TestPythonZipperActionNoOutput(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [{
+ "id": 1,
+ "pathFragmentId": 1
+ },{
+ "id": 2,
+ "pathFragmentId": 2
+ },{
+ "id": 3,
+ "pathFragmentId": 3
+ },{
+ "id": 4,
+ "pathFragmentId": 4
+ },{
+ "id": 5,
+ "pathFragmentId": 10
+ }],
+ "actions": [{
+ "targetId": 1,
+ "actionKey": "x",
+ "mnemonic": "PythonZipper",
+ "configurationId": 1,
+ "arguments": ["../bazel_tools/tools/zip/zipper/zipper", "cC", "python_binary.zip", "__main__.py\u003dbazel-out/k8-fastbuild/bin/python_binary.temp", "__init__.py\u003d", "runfiles/__main__/__init__.py\u003d", "runfiles/__main__/python_binary.py\u003dpython_binary.py", "runfiles/bazel_tools/tools/python/py3wrapper.sh\u003dbazel-out/bazel_tools/k8-fastbuild/bin/tools/python/py3wrapper.sh"],
+ "inputDepSetIds": [1]
+ }],
+ "depSetOfFiles": [{
+ "id": 1,
+ "directArtifactIds": [4, 3, 5]
+ }],
+ "pathFragments": [{
+ "id": 1,
+ "label": "python_binary"
+ },{
+ "id": 2,
+ "label": "python_binary.zip"
+ },{
+ "id": 3,
+ "label": "python_binary.py"
+ },{
+ "id": 9,
+ "label": ".."
+ }, {
+ "id": 8,
+ "label": "bazel_tools",
+ "parentId": 9
+ }, {
+ "id": 7,
+ "label": "tools",
+ "parentId": 8
+ }, {
+ "id": 6,
+ "label": "zip",
+ "parentId": 7
+ }, {
+ "id": 5,
+ "label": "zipper",
+ "parentId": 6
+ }, {
+ "id": 4,
+ "label": "zipper",
+ "parentId": 5
+ },{
+ "id": 16,
+ "label": "bazel-out"
+ },{
+ "id": 15,
+ "label": "bazel_tools",
+ "parentId": 16
+ }, {
+ "id": 14,
+ "label": "k8-fastbuild",
+ "parentId": 15
+ }, {
+ "id": 13,
+ "label": "bin",
+ "parentId": 14
+ }, {
+ "id": 12,
+ "label": "tools",
+ "parentId": 13
+ }, {
+ "id": 11,
+ "label": "python",
+ "parentId": 12
+ }, {
+ "id": 10,
+ "label": "py3wrapper.sh",
+ "parentId": 11
+ }]
+}`
+ _, err := AqueryBuildStatements([]byte(inputString))
+ assertError(t, err, `Expect 1+ input and 1 output to python zipper action, got: input ["../bazel_tools/tools/zip/zipper/zipper" "python_binary.py"], output []`)
+}
+
func assertError(t *testing.T, err error, expected string) {
t.Helper()
if err == nil {
@@ -1029,7 +1378,7 @@
func assertBuildStatements(t *testing.T, expected []BuildStatement, actual []BuildStatement) {
t.Helper()
if len(expected) != len(actual) {
- t.Errorf("expected %d build statements, but got %d,\n expected: %v,\n actual: %v",
+ t.Errorf("expected %d build statements, but got %d,\n expected: %#v,\n actual: %#v",
len(expected), len(actual), expected, actual)
return
}
@@ -1040,7 +1389,7 @@
continue ACTUAL_LOOP
}
}
- t.Errorf("unexpected build statement %v.\n expected: %v",
+ t.Errorf("unexpected build statement %#v.\n expected: %#v",
actualStatement, expected)
return
}
diff --git a/bp2build/android_app_certificate_conversion_test.go b/bp2build/android_app_certificate_conversion_test.go
index 022c687..6a53b00 100644
--- a/bp2build/android_app_certificate_conversion_test.go
+++ b/bp2build/android_app_certificate_conversion_test.go
@@ -42,8 +42,9 @@
certificate: "chamber_of_secrets_dir",
}
`,
- expectedBazelTargets: []string{`android_app_certificate(
- name = "com.android.apogee.cert",
- certificate = "chamber_of_secrets_dir",
-)`}})
+ expectedBazelTargets: []string{
+ makeBazelTarget("android_app_certificate", "com.android.apogee.cert", attrNameToString{
+ "certificate": `"chamber_of_secrets_dir"`,
+ }),
+ }})
}
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
index 456f18a..1a23db7 100644
--- a/bp2build/apex_conversion_test.go
+++ b/bp2build/apex_conversion_test.go
@@ -113,29 +113,30 @@
],
}
`,
- expectedBazelTargets: []string{`apex(
- name = "com.android.apogee",
- android_manifest = "ApogeeAndroidManifest.xml",
- binaries = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("apex", "com.android.apogee", attrNameToString{
+ "android_manifest": `"ApogeeAndroidManifest.xml"`,
+ "binaries": `[
"binary_1",
"binary_2",
- ],
- certificate = ":com.android.apogee.certificate",
- file_contexts = ":com.android.apogee-file_contexts",
- installable = False,
- key = ":com.android.apogee.key",
- manifest = "apogee_manifest.json",
- min_sdk_version = "29",
- native_shared_libs = [
+ ]`,
+ "certificate": `":com.android.apogee.certificate"`,
+ "file_contexts": `":com.android.apogee-file_contexts"`,
+ "installable": "False",
+ "key": `":com.android.apogee.key"`,
+ "manifest": `"apogee_manifest.json"`,
+ "min_sdk_version": `"29"`,
+ "native_shared_libs": `[
":native_shared_lib_1",
":native_shared_lib_2",
- ],
- prebuilts = [
+ ]`,
+ "prebuilts": `[
":pretend_prebuilt_1",
":pretend_prebuilt_2",
- ],
- updatable = False,
-)`}})
+ ]`,
+ "updatable": "False",
+ }),
+ }})
}
func TestApexBundleDefaultPropertyValues(t *testing.T) {
@@ -151,10 +152,10 @@
manifest: "apogee_manifest.json",
}
`,
- expectedBazelTargets: []string{`apex(
- name = "com.android.apogee",
- manifest = "apogee_manifest.json",
-)`}})
+ expectedBazelTargets: []string{makeBazelTarget("apex", "com.android.apogee", attrNameToString{
+ "manifest": `"apogee_manifest.json"`,
+ }),
+ }})
}
func TestApexBundleHasBazelModuleProps(t *testing.T) {
@@ -171,8 +172,8 @@
bazel_module: { bp2build_available: true },
}
`,
- expectedBazelTargets: []string{`apex(
- name = "apogee",
- manifest = "manifest.json",
-)`}})
+ expectedBazelTargets: []string{makeBazelTarget("apex", "apogee", attrNameToString{
+ "manifest": `"manifest.json"`,
+ }),
+ }})
}
diff --git a/bp2build/apex_key_conversion_test.go b/bp2build/apex_key_conversion_test.go
index 8e1aa09..17f79a6 100644
--- a/bp2build/apex_key_conversion_test.go
+++ b/bp2build/apex_key_conversion_test.go
@@ -43,9 +43,9 @@
private_key: "com.android.apogee.pem",
}
`,
- expectedBazelTargets: []string{`apex_key(
- name = "com.android.apogee.key",
- private_key = "com.android.apogee.pem",
- public_key = "com.android.apogee.avbpubkey",
-)`}})
+ expectedBazelTargets: []string{makeBazelTarget("apex_key", "com.android.apogee.key", attrNameToString{
+ "private_key": `"com.android.apogee.pem"`,
+ "public_key": `"com.android.apogee.avbpubkey"`,
+ }),
+ }})
}
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index ee1d862..983604b 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -230,32 +230,32 @@
string_prop: "a",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`custom(
- name = "foo",
- string_list_prop = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("custom", "foo", attrNameToString{
+ "string_list_prop": `[
"a",
"b",
- ],
- string_prop = "a",
-)`,
+ ]`,
+ "string_prop": `"a"`,
+ }),
},
},
{
description: "control characters",
blueprint: `custom {
- name: "control_characters",
+ name: "foo",
string_list_prop: ["\t", "\n"],
string_prop: "a\t\n\r",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`custom(
- name = "control_characters",
- string_list_prop = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("custom", "foo", attrNameToString{
+ "string_list_prop": `[
"\t",
"\n",
- ],
- string_prop = "a\t\n\r",
-)`,
+ ]`,
+ "string_prop": `"a\t\n\r"`,
+ }),
},
},
{
@@ -271,14 +271,13 @@
arch_paths: ["abc"],
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`custom(
- name = "dep",
- arch_paths = ["abc"],
-)`,
- `custom(
- name = "has_dep",
- arch_paths = [":dep"],
-)`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("custom", "dep", attrNameToString{
+ "arch_paths": `["abc"]`,
+ }),
+ makeBazelTarget("custom", "has_dep", attrNameToString{
+ "arch_paths": `[":dep"]`,
+ }),
},
},
{
@@ -311,9 +310,9 @@
},
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`custom(
- name = "arch_paths",
- arch_paths = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("custom", "arch_paths", attrNameToString{
+ "arch_paths": `select({
"//build/bazel/platforms/arch:arm": [
"arm.txt",
"lib32.txt",
@@ -368,8 +367,8 @@
"windows.txt",
],
"//conditions:default": [],
- }),
-)`,
+ })`,
+ }),
},
},
{
@@ -389,17 +388,16 @@
arch_paths: ["abc"],
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`custom(
- name = "dep",
- arch_paths = ["abc"],
-)`,
- `custom(
- name = "has_dep",
- arch_paths = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("custom", "dep", attrNameToString{
+ "arch_paths": `["abc"]`,
+ }),
+ makeBazelTarget("custom", "has_dep", attrNameToString{
+ "arch_paths": `select({
"//build/bazel/platforms/arch:x86": [":dep"],
"//conditions:default": [],
- }),
-)`,
+ })`,
+ }),
},
},
{
@@ -409,10 +407,10 @@
embedded_prop: "abc",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`custom(
- name = "embedded_props",
- embedded_attr = "abc",
-)`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("custom", "embedded_props", attrNameToString{
+ "embedded_attr": `"abc"`,
+ }),
},
},
{
@@ -422,10 +420,10 @@
other_embedded_prop: "abc",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`custom(
- name = "ptr_to_embedded_props",
- other_embedded_attr = "abc",
-)`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("custom", "ptr_to_embedded_props", attrNameToString{
+ "other_embedded_attr": `"abc"`,
+ }),
},
},
}
@@ -649,9 +647,7 @@
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []string{
- `filegroup(
- name = "fg_foo",
-)`,
+ makeBazelTarget("filegroup", "fg_foo", map[string]string{}),
},
},
{
@@ -665,9 +661,7 @@
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []string{
- `filegroup(
- name = "fg_foo",
-)`,
+ makeBazelTarget("filegroup", "fg_foo", map[string]string{}),
},
},
{
@@ -680,13 +674,13 @@
srcs: ["a", "b"],
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`filegroup(
- name = "fg_foo",
- srcs = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
"a",
"b",
- ],
-)`,
+ ]`,
+ }),
},
},
{
@@ -700,10 +694,10 @@
exclude_srcs: ["a"],
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`filegroup(
- name = "fg_foo",
- srcs = ["b"],
-)`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("filegroup", "fg_foo", map[string]string{
+ "srcs": `["b"]`,
+ }),
},
},
{
@@ -712,18 +706,18 @@
moduleTypeUnderTestFactory: android.FileGroupFactory,
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
blueprint: `filegroup {
- name: "foo",
+ name: "fg_foo",
srcs: ["**/*.txt"],
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`filegroup(
- name = "foo",
- srcs = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
"other/a.txt",
"other/b.txt",
"other/subdir/a.txt",
- ],
-)`,
+ ]`,
+ }),
},
filesystem: map[string]string{
"other/a.txt": "",
@@ -737,21 +731,8 @@
moduleTypeUnderTest: "filegroup",
moduleTypeUnderTestFactory: android.FileGroupFactory,
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
- blueprint: `filegroup {
- name: "foo",
- srcs: ["a.txt"],
- bazel_module: { bp2build_available: true },
-}`,
- dir: "other",
- expectedBazelTargets: []string{`filegroup(
- name = "fg_foo",
- srcs = [
- "a.txt",
- "b.txt",
- "subdir/a.txt",
- ],
-)`,
- },
+ blueprint: ``,
+ dir: "other",
filesystem: map[string]string{
"other/Android.bp": `filegroup {
name: "fg_foo",
@@ -763,6 +744,15 @@
"other/subdir/a.txt": "",
"other/file": "",
},
+ expectedBazelTargets: []string{
+ makeBazelTarget("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a.txt",
+ "b.txt",
+ "subdir/a.txt",
+ ]`,
+ }),
+ },
},
{
description: "depends_on_other_dir_module",
@@ -770,21 +760,13 @@
moduleTypeUnderTestFactory: android.FileGroupFactory,
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
blueprint: `filegroup {
- name: "foobar",
+ name: "fg_foo",
srcs: [
":foo",
"c",
],
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`filegroup(
- name = "foobar",
- srcs = [
- "//other:foo",
- "c",
- ],
-)`,
- },
filesystem: map[string]string{
"other/Android.bp": `filegroup {
name: "foo",
@@ -792,6 +774,14 @@
bazel_module: { bp2build_available: true },
}`,
},
+ expectedBazelTargets: []string{
+ makeBazelTarget("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "//other:foo",
+ "c",
+ ]`,
+ }),
+ },
},
{
description: "depends_on_other_unconverted_module_error",
@@ -799,21 +789,21 @@
moduleTypeUnderTestFactory: android.FileGroupFactory,
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
unconvertedDepsMode: errorModulesUnconvertedDeps,
- blueprint: `filegroup {
- name: "foobar",
- srcs: [
- ":foo",
- "c",
- ],
- bazel_module: { bp2build_available: true },
-}`,
- expectedErr: fmt.Errorf(`"foobar" depends on unconverted modules: foo`),
filesystem: map[string]string{
"other/Android.bp": `filegroup {
name: "foo",
srcs: ["a", "b"],
}`,
},
+ blueprint: `filegroup {
+ name: "fg_foo",
+ srcs: [
+ ":foo",
+ "c",
+ ],
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedErr: fmt.Errorf(`"fg_foo" depends on unconverted modules: foo`),
},
}
@@ -1088,9 +1078,8 @@
"other/BUILD.bazel": `// definition for fg_bar`,
},
expectedBazelTargets: []string{
- `filegroup(
- name = "fg_foo",
-)`, `// definition for fg_bar`,
+ makeBazelTarget("filegroup", "fg_foo", map[string]string{}),
+ `// definition for fg_bar`,
},
},
{
@@ -1098,6 +1087,9 @@
moduleTypeUnderTest: "filegroup",
moduleTypeUnderTestFactory: android.FileGroupFactory,
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ filesystem: map[string]string{
+ "other/BUILD.bazel": `// BUILD file`,
+ },
blueprint: `filegroup {
name: "fg_foo",
bazel_module: {
@@ -1112,14 +1104,9 @@
},
}`,
expectedBazelTargets: []string{
- `filegroup(
- name = "fg_bar",
-)`,
+ makeBazelTarget("filegroup", "fg_bar", map[string]string{}),
`// BUILD file`,
},
- filesystem: map[string]string{
- "other/BUILD.bazel": `// BUILD file`,
- },
},
}
@@ -1195,16 +1182,6 @@
exclude_srcs: ["c.txt"],
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`filegroup(
- name = "fg_foo",
- srcs = [
- "a.txt",
- "b.txt",
- "//dir:e.txt",
- "//dir:f.txt",
- ],
-)`,
- },
filesystem: map[string]string{
"a.txt": "",
"b.txt": "",
@@ -1213,6 +1190,16 @@
"dir/e.txt": "",
"dir/f.txt": "",
},
+ expectedBazelTargets: []string{
+ makeBazelTarget("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a.txt",
+ "b.txt",
+ "//dir:e.txt",
+ "//dir:f.txt",
+ ]`,
+ }),
+ },
},
{
description: "filegroup in subdir exclude_srcs",
@@ -1235,66 +1222,22 @@
"dir/subdir/e.txt": "",
"dir/subdir/f.txt": "",
},
- expectedBazelTargets: []string{`filegroup(
- name = "fg_foo",
- srcs = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
"a.txt",
"//dir/subdir:e.txt",
"//dir/subdir:f.txt",
- ],
-)`,
+ ]`,
+ }),
},
},
}
- dir := "."
for _, testCase := range testCases {
- fs := make(map[string][]byte)
- toParse := []string{
- "Android.bp",
- }
- for f, content := range testCase.filesystem {
- if strings.HasSuffix(f, "Android.bp") {
- toParse = append(toParse, f)
- }
- fs[f] = []byte(content)
- }
- config := android.TestConfig(buildDir, nil, testCase.blueprint, fs)
- ctx := android.NewTestContext(config)
- ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
- ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
- ctx.RegisterForBazelConversion()
-
- _, errs := ctx.ParseFileList(dir, toParse)
- if errored(t, testCase, errs) {
- continue
- }
- _, errs = ctx.ResolveDependencies(config)
- if errored(t, testCase, errs) {
- continue
- }
-
- checkDir := dir
- if testCase.dir != "" {
- checkDir = testCase.dir
- }
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
- bazelTargets, err := generateBazelTargetsForDir(codegenCtx, checkDir)
- android.FailIfErrored(t, err)
- if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
- t.Errorf("%s: Expected %d bazel target, got %d\n%s", testCase.description, expectedCount, actualCount, bazelTargets)
- } else {
- for i, target := range bazelTargets {
- if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
- t.Errorf(
- "%s: Expected generated Bazel target to be '%s', got '%s'",
- testCase.description,
- w,
- g,
- )
- }
- }
- }
+ t.Run(testCase.description, func(t *testing.T) {
+ runBp2BuildTestCaseSimple(t, testCase)
+ })
}
}
@@ -1305,22 +1248,16 @@
moduleTypeUnderTest: "filegroup",
moduleTypeUnderTestFactory: android.FileGroupFactory,
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
- blueprint: `filegroup {
- name: "reqd",
-}
-
+ blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + `
filegroup {
name: "fg_foo",
required: ["reqd"],
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`filegroup(
- name = "fg_foo",
- data = [":reqd"],
-)`,
- `filegroup(
- name = "reqd",
-)`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("filegroup", "fg_foo", map[string]string{
+ "data": `[":reqd"]`,
+ }),
},
},
{
@@ -1328,16 +1265,8 @@
moduleTypeUnderTest: "python_library",
moduleTypeUnderTestFactory: python.PythonLibraryFactory,
moduleTypeUnderTestBp2BuildMutator: python.PythonLibraryBp2Build,
- blueprint: `python_library {
- name: "reqdx86",
- bazel_module: { bp2build_available: false, },
-}
-
-python_library {
- name: "reqdarm",
- bazel_module: { bp2build_available: false, },
-}
-
+ blueprint: simpleModuleDoNotConvertBp2build("python_library", "reqdx86") +
+ simpleModuleDoNotConvertBp2build("python_library", "reqdarm") + `
python_library {
name: "fg_foo",
arch: {
@@ -1350,15 +1279,15 @@
},
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`py_library(
- name = "fg_foo",
- data = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("py_library", "fg_foo", map[string]string{
+ "data": `select({
"//build/bazel/platforms/arch:arm": [":reqdarm"],
"//build/bazel/platforms/arch:x86": [":reqdx86"],
"//conditions:default": [],
- }),
- srcs_version = "PY3",
-)`,
+ })`,
+ "srcs_version": `"PY3"`,
+ }),
},
},
{
@@ -1366,11 +1295,11 @@
moduleTypeUnderTest: "python_library",
moduleTypeUnderTestFactory: python.PythonLibraryFactory,
moduleTypeUnderTestBp2BuildMutator: python.PythonLibraryBp2Build,
- blueprint: `python_library {
- name: "reqd",
- srcs: ["src.py"],
-}
-
+ filesystem: map[string]string{
+ "data.bin": "",
+ "src.py": "",
+ },
+ blueprint: simpleModuleDoNotConvertBp2build("python_library", "reqd") + `
python_library {
name: "fg_foo",
data: ["data.bin"],
@@ -1378,23 +1307,13 @@
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []string{
- `py_library(
- name = "fg_foo",
- data = [
+ makeBazelTarget("py_library", "fg_foo", map[string]string{
+ "data": `[
"data.bin",
":reqd",
- ],
- srcs_version = "PY3",
-)`,
- `py_library(
- name = "reqd",
- srcs = ["src.py"],
- srcs_version = "PY3",
-)`,
- },
- filesystem: map[string]string{
- "data.bin": "",
- "src.py": "",
+ ]`,
+ "srcs_version": `"PY3"`,
+ }),
},
},
{
@@ -1402,28 +1321,23 @@
moduleTypeUnderTest: "filegroup",
moduleTypeUnderTestFactory: android.FileGroupFactory,
moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
- blueprint: `filegroup {
- name: "reqd"
-}
+ blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + `
filegroup {
name: "fg_foo",
required: ["reqd"],
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []string{
- `filegroup(
- name = "fg_foo",
- data = [":reqd"],
-)`,
- `filegroup(
- name = "reqd",
-)`,
+ makeBazelTarget("filegroup", "fg_foo", map[string]string{
+ "data": `[":reqd"]`,
+ }),
},
- filesystem: map[string]string{},
},
}
- for _, test := range testCases {
- runBp2BuildTestCaseSimple(t, test)
+ for _, tc := range testCases {
+ t.Run(tc.description, func(t *testing.T) {
+ runBp2BuildTestCaseSimple(t, tc)
+ })
}
}
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index 0b71d89..f9abcba 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -28,6 +28,26 @@
compatibleWithPlaceHolder = "{target_compatible_with}"
)
+type testBazelTarget struct {
+ typ string
+ name string
+ attrs attrNameToString
+}
+
+func generateBazelTargetsForTest(targets []testBazelTarget) []string {
+ ret := make([]string, 0, len(targets))
+ for _, t := range targets {
+ ret = append(ret, makeBazelTarget(t.typ, t.name, t.attrs))
+ }
+ return ret
+}
+
+type ccBinaryBp2buildTestCase struct {
+ description string
+ blueprint string
+ targets []testBazelTarget
+}
+
func registerCcBinaryModuleTypes(ctx android.RegistrationContext) {
cc.RegisterCCBuildComponents(ctx)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
@@ -36,55 +56,56 @@
ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
}
-var binaryReplacer = strings.NewReplacer(ccBinaryTypePlaceHolder, "cc_binary", compatibleWithPlaceHolder, "")
-var hostBinaryReplacer = strings.NewReplacer(ccBinaryTypePlaceHolder, "cc_binary_host", compatibleWithPlaceHolder, `
- target_compatible_with = select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- }),`)
+var binaryReplacer = strings.NewReplacer(ccBinaryTypePlaceHolder, "cc_binary")
+var hostBinaryReplacer = strings.NewReplacer(ccBinaryTypePlaceHolder, "cc_binary_host")
-func runCcBinaryTests(t *testing.T, tc bp2buildTestCase) {
+func runCcBinaryTests(t *testing.T, tc ccBinaryBp2buildTestCase) {
t.Helper()
runCcBinaryTestCase(t, tc)
runCcHostBinaryTestCase(t, tc)
}
-func runCcBinaryTestCase(t *testing.T, tc bp2buildTestCase) {
+func runCcBinaryTestCase(t *testing.T, tc ccBinaryBp2buildTestCase) {
t.Helper()
- testCase := tc
- testCase.expectedBazelTargets = append([]string{}, tc.expectedBazelTargets...)
- testCase.moduleTypeUnderTest = "cc_binary"
- testCase.moduleTypeUnderTestFactory = cc.BinaryFactory
- testCase.moduleTypeUnderTestBp2BuildMutator = cc.BinaryBp2build
- testCase.description = fmt.Sprintf("%s %s", testCase.moduleTypeUnderTest, testCase.description)
- testCase.blueprint = binaryReplacer.Replace(testCase.blueprint)
- for i, et := range testCase.expectedBazelTargets {
- testCase.expectedBazelTargets[i] = binaryReplacer.Replace(et)
+ moduleTypeUnderTest := "cc_binary"
+ testCase := bp2buildTestCase{
+ expectedBazelTargets: generateBazelTargetsForTest(tc.targets),
+ moduleTypeUnderTest: moduleTypeUnderTest,
+ moduleTypeUnderTestFactory: cc.BinaryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.BinaryBp2build,
+ description: fmt.Sprintf("%s %s", moduleTypeUnderTest, tc.description),
+ blueprint: binaryReplacer.Replace(tc.blueprint),
}
t.Run(testCase.description, func(t *testing.T) {
runBp2BuildTestCase(t, registerCcBinaryModuleTypes, testCase)
})
}
-func runCcHostBinaryTestCase(t *testing.T, tc bp2buildTestCase) {
+func runCcHostBinaryTestCase(t *testing.T, tc ccBinaryBp2buildTestCase) {
t.Helper()
testCase := tc
- testCase.expectedBazelTargets = append([]string{}, tc.expectedBazelTargets...)
- testCase.moduleTypeUnderTest = "cc_binary_host"
- testCase.moduleTypeUnderTestFactory = cc.BinaryHostFactory
- testCase.moduleTypeUnderTestBp2BuildMutator = cc.BinaryHostBp2build
- testCase.description = fmt.Sprintf("%s %s", testCase.moduleTypeUnderTest, testCase.description)
- testCase.blueprint = hostBinaryReplacer.Replace(testCase.blueprint)
- for i, et := range testCase.expectedBazelTargets {
- testCase.expectedBazelTargets[i] = hostBinaryReplacer.Replace(et)
+ for i, t := range testCase.targets {
+ t.attrs["target_compatible_with"] = `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`
+ testCase.targets[i] = t
}
+ moduleTypeUnderTest := "cc_binary_host"
t.Run(testCase.description, func(t *testing.T) {
- runBp2BuildTestCase(t, registerCcBinaryModuleTypes, testCase)
+ runBp2BuildTestCase(t, registerCcBinaryModuleTypes, bp2buildTestCase{
+ expectedBazelTargets: generateBazelTargetsForTest(testCase.targets),
+ moduleTypeUnderTest: moduleTypeUnderTest,
+ moduleTypeUnderTestFactory: cc.BinaryHostFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.BinaryHostBp2build,
+ description: fmt.Sprintf("%s %s", moduleTypeUnderTest, tc.description),
+ blueprint: hostBinaryReplacer.Replace(testCase.blueprint),
+ })
})
}
func TestBasicCcBinary(t *testing.T) {
- runCcBinaryTests(t, bp2buildTestCase{
+ runCcBinaryTests(t, ccBinaryBp2buildTestCase{
description: "basic -- properties -> attrs with little/no transformation",
blueprint: `
{rule_name} {
@@ -107,33 +128,35 @@
},
}
`,
- expectedBazelTargets: []string{`cc_binary(
- name = "foo",
- absolute_includes = ["absolute_dir"],
- asflags = ["-Dasflag"],
- conlyflags = ["-Dconlyflag"],
- copts = ["-Dcopt"],
- cppflags = ["-Dcppflag"],
- linkopts = ["ld-flag"],
- local_includes = [
+ targets: []testBazelTarget{
+ {"cc_binary", "foo", attrNameToString{
+ "absolute_includes": `["absolute_dir"]`,
+ "asflags": `["-Dasflag"]`,
+ "conlyflags": `["-Dconlyflag"]`,
+ "copts": `["-Dcopt"]`,
+ "cppflags": `["-Dcppflag"]`,
+ "linkopts": `["ld-flag"]`,
+ "local_includes": `[
"dir",
".",
- ],
- rtti = True,
- srcs = ["a.cc"],
- strip = {
+ ]`,
+ "rtti": `True`,
+ "srcs": `["a.cc"]`,
+ "strip": `{
"all": True,
"keep_symbols": True,
"keep_symbols_and_debug_frame": True,
"keep_symbols_list": ["symbol"],
"none": True,
- },{target_compatible_with}
-)`},
+ }`,
+ },
+ },
+ },
})
}
func TestCcBinaryWithSharedLdflagDisableFeature(t *testing.T) {
- runCcBinaryTests(t, bp2buildTestCase{
+ runCcBinaryTests(t, ccBinaryBp2buildTestCase{
description: `ldflag "-shared" disables static_flag feature`,
blueprint: `
{rule_name} {
@@ -142,16 +165,18 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_binary(
- name = "foo",
- features = ["-static_flag"],
- linkopts = ["-shared"],{target_compatible_with}
-)`},
+ targets: []testBazelTarget{
+ {"cc_binary", "foo", attrNameToString{
+ "features": `["-static_flag"]`,
+ "linkopts": `["-shared"]`,
+ },
+ },
+ },
})
}
func TestCcBinaryWithLinkStatic(t *testing.T) {
- runCcBinaryTests(t, bp2buildTestCase{
+ runCcBinaryTests(t, ccBinaryBp2buildTestCase{
description: "link static",
blueprint: `
{rule_name} {
@@ -160,15 +185,17 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_binary(
- name = "foo",
- linkshared = False,{target_compatible_with}
-)`},
+ targets: []testBazelTarget{
+ {"cc_binary", "foo", attrNameToString{
+ "linkshared": `False`,
+ },
+ },
+ },
})
}
func TestCcBinaryVersionScript(t *testing.T) {
- runCcBinaryTests(t, bp2buildTestCase{
+ runCcBinaryTests(t, ccBinaryBp2buildTestCase{
description: `version script`,
blueprint: `
{rule_name} {
@@ -177,16 +204,18 @@
version_script: "vs",
}
`,
- expectedBazelTargets: []string{`cc_binary(
- name = "foo",
- additional_linker_inputs = ["vs"],
- linkopts = ["-Wl,--version-script,$(location vs)"],{target_compatible_with}
-)`},
+ targets: []testBazelTarget{
+ {"cc_binary", "foo", attrNameToString{
+ "additional_linker_inputs": `["vs"]`,
+ "linkopts": `["-Wl,--version-script,$(location vs)"]`,
+ },
+ },
+ },
})
}
func TestCcBinarySplitSrcsByLang(t *testing.T) {
- runCcHostBinaryTestCase(t, bp2buildTestCase{
+ runCcHostBinaryTestCase(t, ccBinaryBp2buildTestCase{
description: "split srcs by lang",
blueprint: `
{rule_name} {
@@ -200,26 +229,28 @@
include_build_directory: false,
}
` + simpleModuleDoNotConvertBp2build("filegroup", "fg_foo"),
- expectedBazelTargets: []string{`cc_binary(
- name = "foo",
- srcs = [
+ targets: []testBazelTarget{
+ {"cc_binary", "foo", attrNameToString{
+ "srcs": `[
"cpponly.cpp",
":fg_foo_cpp_srcs",
- ],
- srcs_as = [
+ ]`,
+ "srcs_as": `[
"asonly.S",
":fg_foo_as_srcs",
- ],
- srcs_c = [
+ ]`,
+ "srcs_c": `[
"conly.c",
":fg_foo_c_srcs",
- ],{target_compatible_with}
-)`},
+ ]`,
+ },
+ },
+ },
})
}
func TestCcBinaryDoNotDistinguishBetweenDepsAndImplementationDeps(t *testing.T) {
- runCcBinaryTestCase(t, bp2buildTestCase{
+ runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
description: "no implementation deps",
blueprint: `
genrule {
@@ -251,26 +282,28 @@
simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep") +
simpleModuleDoNotConvertBp2build("cc_library", "shared_dep") +
simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep"),
- expectedBazelTargets: []string{`cc_binary(
- name = "foo",
- deps = [
+ targets: []testBazelTarget{
+ {"cc_binary", "foo", attrNameToString{
+ "deps": `[
":implementation_static_dep",
":static_dep",
- ],
- dynamic_deps = [
+ ]`,
+ "dynamic_deps": `[
":implementation_shared_dep",
":shared_dep",
- ],
- srcs = [
+ ]`,
+ "srcs": `[
"foo.cpp",
":generated_hdr",
":export_generated_hdr",
- ],{target_compatible_with}
- whole_archive_deps = [
+ ]`,
+ "whole_archive_deps": `[
":not_explicitly_exported_whole_static_dep",
":whole_static_dep",
- ],
-)`},
+ ]`,
+ },
+ },
+ },
})
}
@@ -278,19 +311,21 @@
baseTestCases := []struct {
description string
soongProperty string
- bazelAttr string
+ bazelAttr attrNameToString
}{
{
description: "nocrt: true",
soongProperty: `nocrt: true,`,
- bazelAttr: ` link_crt = False,`,
+ bazelAttr: attrNameToString{"link_crt": `False`},
},
{
description: "nocrt: false",
soongProperty: `nocrt: false,`,
+ bazelAttr: attrNameToString{},
},
{
description: "nocrt: not set",
+ bazelAttr: attrNameToString{},
},
}
@@ -300,24 +335,16 @@
}
`
- baseBazelTarget := `cc_binary(
- name = "foo",%s{target_compatible_with}
-)`
-
for _, btc := range baseTestCases {
prop := btc.soongProperty
if len(prop) > 0 {
prop = "\n" + prop
}
- attr := btc.bazelAttr
- if len(attr) > 0 {
- attr = "\n" + attr
- }
- runCcBinaryTests(t, bp2buildTestCase{
+ runCcBinaryTests(t, ccBinaryBp2buildTestCase{
description: btc.description,
blueprint: fmt.Sprintf(baseBlueprint, prop),
- expectedBazelTargets: []string{
- fmt.Sprintf(baseBazelTarget, attr),
+ targets: []testBazelTarget{
+ {"cc_binary", "foo", btc.bazelAttr},
},
})
}
@@ -327,20 +354,21 @@
baseTestCases := []struct {
description string
soongProperty string
- bazelAttr string
+ bazelAttr attrNameToString
}{
{
description: "no_libcrt: true",
soongProperty: `no_libcrt: true,`,
- bazelAttr: ` use_libcrt = False,`,
+ bazelAttr: attrNameToString{"use_libcrt": `False`},
},
{
description: "no_libcrt: false",
soongProperty: `no_libcrt: false,`,
- bazelAttr: ` use_libcrt = True,`,
+ bazelAttr: attrNameToString{"use_libcrt": `True`},
},
{
description: "no_libcrt: not set",
+ bazelAttr: attrNameToString{},
},
}
@@ -350,24 +378,16 @@
}
`
- baseBazelTarget := `cc_binary(
- name = "foo",{target_compatible_with}%s
-)`
-
for _, btc := range baseTestCases {
prop := btc.soongProperty
if len(prop) > 0 {
prop = "\n" + prop
}
- attr := btc.bazelAttr
- if len(attr) > 0 {
- attr = "\n" + attr
- }
- runCcBinaryTests(t, bp2buildTestCase{
+ runCcBinaryTests(t, ccBinaryBp2buildTestCase{
description: btc.description,
blueprint: fmt.Sprintf(baseBlueprint, prop),
- expectedBazelTargets: []string{
- fmt.Sprintf(baseBazelTarget, attr),
+ targets: []testBazelTarget{
+ {"cc_binary", "foo", btc.bazelAttr},
},
})
}
@@ -377,31 +397,35 @@
baseTestCases := []struct {
description string
soongProperty string
- bazelAttr string
+ bazelAttr attrNameToString
}{
{
description: "pack_relocation: true",
soongProperty: `pack_relocations: true,`,
+ bazelAttr: attrNameToString{},
},
{
description: "pack_relocations: false",
soongProperty: `pack_relocations: false,`,
- bazelAttr: ` features = ["disable_pack_relocations"],`,
+ bazelAttr: attrNameToString{"features": `["disable_pack_relocations"]`},
},
{
description: "pack_relocations: not set",
+ bazelAttr: attrNameToString{},
},
{
description: "pack_relocation: true",
soongProperty: `allow_undefined_symbols: true,`,
- bazelAttr: ` features = ["-no_undefined_symbols"],`,
+ bazelAttr: attrNameToString{"features": `["-no_undefined_symbols"]`},
},
{
description: "allow_undefined_symbols: false",
soongProperty: `allow_undefined_symbols: false,`,
+ bazelAttr: attrNameToString{},
},
{
description: "allow_undefined_symbols: not set",
+ bazelAttr: attrNameToString{},
},
}
@@ -410,25 +434,16 @@
include_build_directory: false,
}
`
-
- baseBazelTarget := `cc_binary(
- name = "foo",%s{target_compatible_with}
-)`
-
for _, btc := range baseTestCases {
prop := btc.soongProperty
if len(prop) > 0 {
prop = "\n" + prop
}
- attr := btc.bazelAttr
- if len(attr) > 0 {
- attr = "\n" + attr
- }
- runCcBinaryTests(t, bp2buildTestCase{
+ runCcBinaryTests(t, ccBinaryBp2buildTestCase{
description: btc.description,
blueprint: fmt.Sprintf(baseBlueprint, prop),
- expectedBazelTargets: []string{
- fmt.Sprintf(baseBazelTarget, attr),
+ targets: []testBazelTarget{
+ {"cc_binary", "foo", btc.bazelAttr},
},
})
}
diff --git a/bp2build/cc_genrule_conversion_test.go b/bp2build/cc_genrule_conversion_test.go
index a7e9cb2..b3624dd 100644
--- a/bp2build/cc_genrule_conversion_test.go
+++ b/bp2build/cc_genrule_conversion_test.go
@@ -39,15 +39,15 @@
func runCcGenruleTestCase(t *testing.T, tc bp2buildTestCase) {
t.Helper()
+ (&tc).moduleTypeUnderTest = "cc_genrule"
+ (&tc).moduleTypeUnderTestFactory = cc.GenRuleFactory
+ (&tc).moduleTypeUnderTestBp2BuildMutator = genrule.CcGenruleBp2Build
runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
}
func TestCliVariableReplacement(t *testing.T) {
runCcGenruleTestCase(t, bp2buildTestCase{
- description: "cc_genrule with command line variable replacements",
- moduleTypeUnderTest: "cc_genrule",
- moduleTypeUnderTestFactory: cc.GenRuleFactory,
- moduleTypeUnderTestBp2BuildMutator: genrule.CcGenruleBp2Build,
+ description: "cc_genrule with command line variable replacements",
blueprint: `cc_genrule {
name: "foo.tool",
out: ["foo_tool.out"],
@@ -65,29 +65,24 @@
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []string{
- `genrule(
- name = "foo",
- cmd = "$(location :foo.tool) --genDir=$(RULEDIR) arg $(SRCS) $(OUTS)",
- outs = ["foo.out"],
- srcs = ["foo.in"],
- tools = [":foo.tool"],
-)`,
- `genrule(
- name = "foo.tool",
- cmd = "cp $(SRCS) $(OUTS)",
- outs = ["foo_tool.out"],
- srcs = ["foo_tool.in"],
-)`,
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"$(location :foo.tool) --genDir=$(RULEDIR) arg $(SRCS) $(OUTS)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ "tools": `[":foo.tool"]`,
+ }),
+ makeBazelTarget("genrule", "foo.tool", attrNameToString{
+ "cmd": `"cp $(SRCS) $(OUTS)"`,
+ "outs": `["foo_tool.out"]`,
+ "srcs": `["foo_tool.in"]`,
+ }),
},
})
}
func TestUsingLocationsLabel(t *testing.T) {
runCcGenruleTestCase(t, bp2buildTestCase{
- description: "cc_genrule using $(locations :label)",
- moduleTypeUnderTest: "cc_genrule",
- moduleTypeUnderTestFactory: cc.GenRuleFactory,
- moduleTypeUnderTestBp2BuildMutator: genrule.CcGenruleBp2Build,
+ description: "cc_genrule using $(locations :label)",
blueprint: `cc_genrule {
name: "foo.tools",
out: ["foo_tool.out", "foo_tool2.out"],
@@ -104,32 +99,28 @@
cmd: "$(locations :foo.tools) -s $(out) $(in)",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`genrule(
- name = "foo",
- cmd = "$(locations :foo.tools) -s $(OUTS) $(SRCS)",
- outs = ["foo.out"],
- srcs = ["foo.in"],
- tools = [":foo.tools"],
-)`,
- `genrule(
- name = "foo.tools",
- cmd = "cp $(SRCS) $(OUTS)",
- outs = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"$(locations :foo.tools) -s $(OUTS) $(SRCS)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ "tools": `[":foo.tools"]`,
+ }),
+ makeBazelTarget("genrule", "foo.tools", attrNameToString{
+ "cmd": `"cp $(SRCS) $(OUTS)"`,
+ "outs": `[
"foo_tool.out",
"foo_tool2.out",
- ],
- srcs = ["foo_tool.in"],
-)`,
+ ]`,
+ "srcs": `["foo_tool.in"]`,
+ }),
},
})
}
func TestUsingLocationsAbsoluteLabel(t *testing.T) {
runCcGenruleTestCase(t, bp2buildTestCase{
- description: "cc_genrule using $(locations //absolute:label)",
- moduleTypeUnderTest: "cc_genrule",
- moduleTypeUnderTestFactory: cc.GenRuleFactory,
- moduleTypeUnderTestBp2BuildMutator: genrule.CcGenruleBp2Build,
+ description: "cc_genrule using $(locations //absolute:label)",
blueprint: `cc_genrule {
name: "foo",
out: ["foo.out"],
@@ -138,24 +129,21 @@
cmd: "$(locations :foo.tool) -s $(out) $(in)",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`genrule(
- name = "foo",
- cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
- outs = ["foo.out"],
- srcs = ["foo.in"],
- tools = ["//other:foo.tool"],
-)`,
- },
filesystem: otherCcGenruleBp,
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ "tools": `["//other:foo.tool"]`,
+ }),
+ },
})
}
func TestSrcsUsingAbsoluteLabel(t *testing.T) {
runCcGenruleTestCase(t, bp2buildTestCase{
- description: "cc_genrule srcs using $(locations //absolute:label)",
- moduleTypeUnderTest: "cc_genrule",
- moduleTypeUnderTestFactory: cc.GenRuleFactory,
- moduleTypeUnderTestBp2BuildMutator: genrule.CcGenruleBp2Build,
+ description: "cc_genrule srcs using $(locations //absolute:label)",
blueprint: `cc_genrule {
name: "foo",
out: ["foo.out"],
@@ -164,24 +152,21 @@
cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`genrule(
- name = "foo",
- cmd = "$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)",
- outs = ["foo.out"],
- srcs = ["//other:other.tool"],
- tools = ["//other:foo.tool"],
-)`,
- },
filesystem: otherCcGenruleBp,
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["//other:other.tool"]`,
+ "tools": `["//other:foo.tool"]`,
+ }),
+ },
})
}
func TestLocationsLabelUsesFirstToolFile(t *testing.T) {
runCcGenruleTestCase(t, bp2buildTestCase{
- description: "cc_genrule using $(location) label should substitute first tool label automatically",
- moduleTypeUnderTest: "cc_genrule",
- moduleTypeUnderTestFactory: cc.GenRuleFactory,
- moduleTypeUnderTestBp2BuildMutator: genrule.CcGenruleBp2Build,
+ description: "cc_genrule using $(location) label should substitute first tool label automatically",
blueprint: `cc_genrule {
name: "foo",
out: ["foo.out"],
@@ -190,27 +175,24 @@
cmd: "$(location) -s $(out) $(in)",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`genrule(
- name = "foo",
- cmd = "$(location //other:foo.tool) -s $(OUTS) $(SRCS)",
- outs = ["foo.out"],
- srcs = ["foo.in"],
- tools = [
+ filesystem: otherCcGenruleBp,
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"$(location //other:foo.tool) -s $(OUTS) $(SRCS)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ "tools": `[
"//other:foo.tool",
"//other:other.tool",
- ],
-)`,
+ ]`,
+ }),
},
- filesystem: otherCcGenruleBp,
})
}
func TestLocationsLabelUsesFirstTool(t *testing.T) {
runCcGenruleTestCase(t, bp2buildTestCase{
- description: "cc_genrule using $(locations) label should substitute first tool label automatically",
- moduleTypeUnderTest: "cc_genrule",
- moduleTypeUnderTestFactory: cc.GenRuleFactory,
- moduleTypeUnderTestBp2BuildMutator: genrule.CcGenruleBp2Build,
+ description: "cc_genrule using $(locations) label should substitute first tool label automatically",
blueprint: `cc_genrule {
name: "foo",
out: ["foo.out"],
@@ -219,27 +201,24 @@
cmd: "$(locations) -s $(out) $(in)",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`genrule(
- name = "foo",
- cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
- outs = ["foo.out"],
- srcs = ["foo.in"],
- tools = [
+ filesystem: otherCcGenruleBp,
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ "tools": `[
"//other:foo.tool",
"//other:other.tool",
- ],
-)`,
+ ]`,
+ }),
},
- filesystem: otherCcGenruleBp,
})
}
func TestWithoutToolsOrToolFiles(t *testing.T) {
runCcGenruleTestCase(t, bp2buildTestCase{
- description: "cc_genrule without tools or tool_files can convert successfully",
- moduleTypeUnderTest: "cc_genrule",
- moduleTypeUnderTestFactory: cc.GenRuleFactory,
- moduleTypeUnderTestBp2BuildMutator: genrule.CcGenruleBp2Build,
+ description: "cc_genrule without tools or tool_files can convert successfully",
blueprint: `cc_genrule {
name: "foo",
out: ["foo.out"],
@@ -247,12 +226,12 @@
cmd: "cp $(in) $(out)",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`genrule(
- name = "foo",
- cmd = "cp $(SRCS) $(OUTS)",
- outs = ["foo.out"],
- srcs = ["foo.in"],
-)`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"cp $(SRCS) $(OUTS)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ }),
},
})
}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index cbdc167..a3d902a 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -81,8 +81,8 @@
"x86_64.cpp": "",
"foo-dir/a.h": "",
},
- blueprint: soongCcLibraryPreamble + `
-cc_library_headers { name: "some-headers" }
+ blueprint: soongCcLibraryPreamble +
+ simpleModuleDoNotConvertBp2build("cc_library_headers", "some-headers") + `
cc_library {
name: "foo-lib",
srcs: ["impl.cpp"],
@@ -117,17 +117,17 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "foo-lib",
- copts = ["-Wall"],
- export_includes = ["foo-dir"],
- implementation_deps = [":some-headers"],
- linkopts = ["-Wl,--exclude-libs=bar.a"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "foo-lib", attrNameToString{
+ "copts": `["-Wall"]`,
+ "export_includes": `["foo-dir"]`,
+ "implementation_deps": `[":some-headers"]`,
+ "linkopts": `["-Wl,--exclude-libs=bar.a"] + select({
"//build/bazel/platforms/arch:x86": ["-Wl,--exclude-libs=baz.a"],
"//build/bazel/platforms/arch:x86_64": ["-Wl,--exclude-libs=qux.a"],
"//conditions:default": [],
- }),
- srcs = ["impl.cpp"] + select({
+ })`,
+ "srcs": `["impl.cpp"] + select({
"//build/bazel/platforms/arch:x86": ["x86.cpp"],
"//build/bazel/platforms/arch:x86_64": ["x86_64.cpp"],
"//conditions:default": [],
@@ -140,8 +140,10 @@
"//build/bazel/platforms/os:linux": ["linux.cpp"],
"//build/bazel/platforms/os:linux_bionic": ["bionic.cpp"],
"//conditions:default": [],
- }),
-)`}})
+ })`,
+ }),
+ },
+ })
}
func TestCcLibraryTrimmedLdAndroid(t *testing.T) {
@@ -188,16 +190,17 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "fake-ld-android",
- copts = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "fake-ld-android", attrNameToString{
+ "srcs": `["ld_android.cpp"]`,
+ "copts": `[
"-Wall",
"-Wextra",
"-Wunused",
"-Werror",
- ],
- implementation_deps = [":libc_headers"],
- linkopts = [
+ ]`,
+ "implementation_deps": `[":libc_headers"]`,
+ "linkopts": `[
"-Wl,--exclude-libs=libgcc.a",
"-Wl,--exclude-libs=libgcc_stripped.a",
"-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
@@ -208,9 +211,9 @@
"//build/bazel/platforms/arch:x86": ["-Wl,--exclude-libs=libgcc_eh.a"],
"//build/bazel/platforms/arch:x86_64": ["-Wl,--exclude-libs=libgcc_eh.a"],
"//conditions:default": [],
- }),
- srcs = ["ld_android.cpp"],
-)`},
+ })`,
+ }),
+ },
})
}
@@ -255,15 +258,16 @@
`,
},
blueprint: soongCcLibraryPreamble,
- expectedBazelTargets: []string{`cc_library(
- name = "fake-libarm-optimized-routines-math",
- copts = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "fake-libarm-optimized-routines-math", attrNameToString{
+ "copts": `select({
"//build/bazel/platforms/arch:arm64": ["-DHAVE_FAST_FMA=1"],
"//conditions:default": [],
- }),
- local_includes = ["."],
- srcs_c = ["math/cosf.c"],
-)`},
+ })`,
+ "local_includes": `["."]`,
+ "srcs_c": `["math/cosf.c"]`,
+ }),
+ },
})
}
@@ -348,28 +352,29 @@
bazel_module: { bp2build_available: false },
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "a",
- copts = ["bothflag"],
- implementation_deps = [":static_dep_for_both"],
- implementation_dynamic_deps = [":shared_dep_for_both"],
- shared = {
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "a", attrNameToString{
+ "copts": `["bothflag"]`,
+ "implementation_deps": `[":static_dep_for_both"]`,
+ "implementation_dynamic_deps": `[":shared_dep_for_both"]`,
+ "shared": `{
"copts": ["sharedflag"],
"implementation_deps": [":static_dep_for_shared"],
"implementation_dynamic_deps": [":shared_dep_for_shared"],
"srcs": ["sharedonly.cpp"],
"whole_archive_deps": [":whole_static_lib_for_shared"],
- },
- srcs = ["both.cpp"],
- static = {
+ }`,
+ "srcs": `["both.cpp"]`,
+ "static": `{
"copts": ["staticflag"],
"implementation_deps": [":static_dep_for_static"],
"implementation_dynamic_deps": [":shared_dep_for_static"],
"srcs": ["staticonly.cpp"],
"whole_archive_deps": [":whole_static_lib_for_static"],
- },
- whole_archive_deps = [":whole_static_lib_for_both"],
-)`},
+ }`,
+ "whole_archive_deps": `[":whole_static_lib_for_both"]`,
+ }),
+ },
})
}
@@ -432,14 +437,14 @@
simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_static") +
simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_both") +
simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_both"),
- expectedBazelTargets: []string{`cc_library(
- name = "a",
- copts = ["bothflag"],
- deps = [":static_dep_for_both"],
- dynamic_deps = [":shared_dep_for_both"],
- implementation_deps = [":implementation_static_dep_for_both"],
- implementation_dynamic_deps = [":implementation_shared_dep_for_both"],
- shared = {
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "a", attrNameToString{
+ "copts": `["bothflag"]`,
+ "deps": `[":static_dep_for_both"]`,
+ "dynamic_deps": `[":shared_dep_for_both"]`,
+ "implementation_deps": `[":implementation_static_dep_for_both"]`,
+ "implementation_dynamic_deps": `[":implementation_shared_dep_for_both"]`,
+ "shared": `{
"copts": ["sharedflag"],
"deps": [":static_dep_for_shared"],
"dynamic_deps": [":shared_dep_for_shared"],
@@ -450,9 +455,9 @@
":not_explicitly_exported_whole_static_dep_for_shared",
":whole_static_dep_for_shared",
],
- },
- srcs = ["both.cpp"],
- static = {
+ }`,
+ "srcs": `["both.cpp"]`,
+ "static": `{
"copts": ["staticflag"],
"deps": [":static_dep_for_static"],
"dynamic_deps": [":shared_dep_for_static"],
@@ -463,12 +468,13 @@
":not_explicitly_exported_whole_static_dep_for_static",
":whole_static_dep_for_static",
],
- },
- whole_archive_deps = [
+ }`,
+ "whole_archive_deps": `[
":not_explicitly_exported_whole_static_dep_for_both",
":whole_static_dep_for_both",
- ],
-)`},
+ ]`,
+ }),
+ },
})
}
@@ -501,16 +507,17 @@
`,
},
blueprint: soongCcLibraryPreamble,
- expectedBazelTargets: []string{`cc_library(
- name = "a",
- shared = {
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "a", attrNameToString{
+ "shared": `{
"whole_archive_deps": [":whole_static_lib_for_shared_alwayslink"],
- },
- static = {
+ }`,
+ "static": `{
"whole_archive_deps": [":whole_static_lib_for_static_alwayslink"],
- },
- whole_archive_deps = [":whole_static_lib_for_both_alwayslink"],
-)`},
+ }`,
+ "whole_archive_deps": `[":whole_static_lib_for_both_alwayslink"]`,
+ }),
+ },
})
}
@@ -591,12 +598,12 @@
`,
},
blueprint: soongCcLibraryPreamble,
- expectedBazelTargets: []string{`cc_library(
- name = "a",
- copts = ["bothflag"],
- implementation_deps = [":static_dep_for_both"],
- local_includes = ["."],
- shared = {
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "a", attrNameToString{
+ "copts": `["bothflag"]`,
+ "implementation_deps": `[":static_dep_for_both"]`,
+ "local_includes": `["."]`,
+ "shared": `{
"copts": ["sharedflag"] + select({
"//build/bazel/platforms/arch:arm": ["-DARM_SHARED"],
"//conditions:default": [],
@@ -629,9 +636,9 @@
"//build/bazel/platforms/arch:arm": [":arm_whole_static_dep_for_shared"],
"//conditions:default": [],
}),
- },
- srcs = ["both.cpp"],
- static = {
+ }`,
+ "srcs": `["both.cpp"]`,
+ "static": `{
"copts": ["staticflag"] + select({
"//build/bazel/platforms/arch:x86": ["-DX86_STATIC"],
"//conditions:default": [],
@@ -644,8 +651,9 @@
"//build/bazel/platforms/arch:x86": ["x86_static.cpp"],
"//conditions:default": [],
}),
- },
-)`},
+ }`,
+ }),
+ },
})
}
@@ -729,10 +737,10 @@
`,
},
blueprint: soongCcLibraryPreamble,
- expectedBazelTargets: []string{`cc_library(
- name = "a",
- local_includes = ["."],
- shared = {
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "a", attrNameToString{
+ "local_includes": `["."]`,
+ "shared": `{
"srcs": [
"shared_source.cpp",
"shared_source.cc",
@@ -747,22 +755,22 @@
"shared_source.c",
":shared_filegroup_c_srcs",
],
- },
- srcs = [
+ }`,
+ "srcs": `[
"both_source.cpp",
"both_source.cc",
":both_filegroup_cpp_srcs",
- ],
- srcs_as = [
+ ]`,
+ "srcs_as": `[
"both_source.s",
"both_source.S",
":both_filegroup_as_srcs",
- ],
- srcs_c = [
+ ]`,
+ "srcs_c": `[
"both_source.c",
":both_filegroup_c_srcs",
- ],
- static = {
+ ]`,
+ "static": `{
"srcs": [
"static_source.cpp",
"static_source.cc",
@@ -777,8 +785,9 @@
"static_source.c",
":static_filegroup_c_srcs",
],
- },
-)`},
+ }`,
+ }),
+ },
})
}
@@ -801,12 +810,13 @@
`,
},
blueprint: soongCcLibraryPreamble,
- expectedBazelTargets: []string{`cc_library(
- name = "a",
- additional_linker_inputs = ["v.map"],
- linkopts = ["-Wl,--version-script,$(location v.map)"],
- srcs = ["a.cpp"],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "a", attrNameToString{
+ "additional_linker_inputs": `["v.map"]`,
+ "linkopts": `["-Wl,--version-script,$(location v.map)"]`,
+ "srcs": `["a.cpp"]`,
+ }),
+ },
})
}
@@ -837,20 +847,21 @@
`,
},
blueprint: soongCcLibraryPreamble,
- expectedBazelTargets: []string{`cc_library(
- name = "a",
- additional_linker_inputs = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "a", attrNameToString{
+ "additional_linker_inputs": `select({
"//build/bazel/platforms/arch:arm": ["arm.map"],
"//build/bazel/platforms/arch:arm64": ["arm64.map"],
"//conditions:default": [],
- }),
- linkopts = select({
+ })`,
+ "linkopts": `select({
"//build/bazel/platforms/arch:arm": ["-Wl,--version-script,$(location arm.map)"],
"//build/bazel/platforms/arch:arm64": ["-Wl,--version-script,$(location arm64.map)"],
"//conditions:default": [],
- }),
- srcs = ["a.cpp"],
-)`},
+ })`,
+ "srcs": `["a.cpp"]`,
+ }),
+ },
})
}
@@ -872,10 +883,11 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "a",
- implementation_dynamic_deps = [":mylib"],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "a", attrNameToString{
+ "implementation_dynamic_deps": `[":mylib"]`,
+ }),
+ },
})
}
@@ -917,34 +929,33 @@
},
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library(
- name = "a",
- features = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "a", attrNameToString{
+ "features": `[
"disable_pack_relocations",
"-no_undefined_symbols",
- ],
- srcs = ["a.cpp"],
-)`, `cc_library(
- name = "b",
- features = select({
+ ]`,
+ "srcs": `["a.cpp"]`,
+ }), makeBazelTarget("cc_library", "b", attrNameToString{
+ "features": `select({
"//build/bazel/platforms/arch:x86_64": [
"disable_pack_relocations",
"-no_undefined_symbols",
],
"//conditions:default": [],
- }),
- srcs = ["b.cpp"],
-)`, `cc_library(
- name = "c",
- features = select({
+ })`,
+ "srcs": `["b.cpp"]`,
+ }), makeBazelTarget("cc_library", "c", attrNameToString{
+ "features": `select({
"//build/bazel/platforms/os:darwin": [
"disable_pack_relocations",
"-no_undefined_symbols",
],
"//conditions:default": [],
- }),
- srcs = ["c.cpp"],
-)`},
+ })`,
+ "srcs": `["c.cpp"]`,
+ }),
+ },
})
}
@@ -961,13 +972,14 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "a",
- copts = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "a", attrNameToString{
+ "copts": `[
"-include",
"header.h",
- ],
-)`},
+ ]`,
+ }),
+ },
})
}
@@ -998,10 +1010,10 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "a",
- copts = ["-Wall"],
- cppflags = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "a", attrNameToString{
+ "copts": `["-Wall"]`,
+ "cppflags": `[
"-fsigned-char",
"-pedantic",
] + select({
@@ -1010,9 +1022,10 @@
}) + select({
"//build/bazel/platforms/os:android": ["-DANDROID=1"],
"//conditions:default": [],
- }),
- srcs = ["a.cpp"],
-)`},
+ })`,
+ "srcs": `["a.cpp"]`,
+ }),
+ },
})
}
@@ -1097,31 +1110,30 @@
}
`,
expectedBazelTargets: []string{
- `cc_library(
- name = "foo_static",
- implementation_deps = select({
+ makeBazelTarget("cc_library", "foo_static", attrNameToString{
+ "implementation_deps": `select({
"//build/bazel/platforms/arch:arm": [],
"//conditions:default": [":arm_static_lib_excludes_bp2build_cc_library_static"],
}) + select({
"//build/bazel/product_variables:malloc_not_svelte": [],
"//conditions:default": [":malloc_not_svelte_static_lib_excludes_bp2build_cc_library_static"],
- }),
- implementation_dynamic_deps = select({
+ })`,
+ "implementation_dynamic_deps": `select({
"//build/bazel/platforms/arch:arm": [],
"//conditions:default": [":arm_shared_lib_excludes"],
}) + select({
"//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_shared_lib"],
"//conditions:default": [],
- }),
- srcs_c = ["common.c"],
- whole_archive_deps = select({
+ })`,
+ "srcs_c": `["common.c"]`,
+ "whole_archive_deps": `select({
"//build/bazel/platforms/arch:arm": [],
"//conditions:default": [":arm_whole_static_lib_excludes_bp2build_cc_library_static"],
}) + select({
"//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_whole_static_lib_bp2build_cc_library_static"],
"//conditions:default": [":malloc_not_svelte_whole_static_lib_excludes_bp2build_cc_library_static"],
- }),
-)`,
+ })`,
+ }),
},
})
}
@@ -1143,11 +1155,13 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "foo-lib",
- link_crt = False,
- srcs = ["impl.cpp"],
-)`}})
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "foo-lib", attrNameToString{
+ "link_crt": `False`,
+ "srcs": `["impl.cpp"]`,
+ }),
+ },
+ })
}
func TestCCLibraryNoCrtFalse(t *testing.T) {
@@ -1167,10 +1181,12 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "foo-lib",
- srcs = ["impl.cpp"],
-)`}})
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "foo-lib", attrNameToString{
+ "srcs": `["impl.cpp"]`,
+ }),
+ },
+ })
}
func TestCCLibraryNoCrtArchVariant(t *testing.T) {
@@ -1219,11 +1235,12 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "foo-lib",
- srcs = ["impl.cpp"],
- use_libcrt = False,
-)`}})
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "foo-lib", attrNameToString{
+ "srcs": `["impl.cpp"]`,
+ "use_libcrt": `False`,
+ }),
+ }})
}
func TestCCLibraryNoLibCrtFalse(t *testing.T) {
@@ -1243,11 +1260,12 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "foo-lib",
- srcs = ["impl.cpp"],
- use_libcrt = True,
-)`}})
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "foo-lib", attrNameToString{
+ "srcs": `["impl.cpp"]`,
+ "use_libcrt": `True`,
+ }),
+ }})
}
func TestCCLibraryNoLibCrtArchVariant(t *testing.T) {
@@ -1273,15 +1291,16 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "foo-lib",
- srcs = ["impl.cpp"],
- use_libcrt = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "foo-lib", attrNameToString{
+ "srcs": `["impl.cpp"]`,
+ "use_libcrt": `select({
"//build/bazel/platforms/arch:arm": False,
"//build/bazel/platforms/arch:x86": False,
"//conditions:default": None,
- }),
-)`}})
+ })`,
+ }),
+ }})
}
func TestCcLibraryStrip(t *testing.T) {
@@ -1331,34 +1350,29 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "all",
- strip = {
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "all", attrNameToString{
+ "strip": `{
"all": True,
- },
-)`, `cc_library(
- name = "keep_symbols",
- strip = {
+ }`,
+ }), makeBazelTarget("cc_library", "keep_symbols", attrNameToString{
+ "strip": `{
"keep_symbols": True,
- },
-)`, `cc_library(
- name = "keep_symbols_and_debug_frame",
- strip = {
+ }`,
+ }), makeBazelTarget("cc_library", "keep_symbols_and_debug_frame", attrNameToString{
+ "strip": `{
"keep_symbols_and_debug_frame": True,
- },
-)`, `cc_library(
- name = "keep_symbols_list",
- strip = {
+ }`,
+ }), makeBazelTarget("cc_library", "keep_symbols_list", attrNameToString{
+ "strip": `{
"keep_symbols_list": ["symbol"],
- },
-)`, `cc_library(
- name = "none",
- strip = {
+ }`,
+ }), makeBazelTarget("cc_library", "none", attrNameToString{
+ "strip": `{
"none": True,
- },
-)`, `cc_library(
- name = "nothing",
-)`},
+ }`,
+ }), makeBazelTarget("cc_library", "nothing", attrNameToString{}),
+ },
})
}
@@ -1393,9 +1407,9 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "multi-arch",
- strip = {
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "multi-arch", attrNameToString{
+ "strip": `{
"keep_symbols": select({
"//build/bazel/platforms/arch:arm64": True,
"//conditions:default": None,
@@ -1411,8 +1425,9 @@
],
"//conditions:default": [],
}),
- },
-)`},
+ }`,
+ }),
+ },
})
}
@@ -1429,10 +1444,11 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "root_empty",
- system_dynamic_deps = [],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "root_empty", attrNameToString{
+ "system_dynamic_deps": `[]`,
+ }),
+ },
})
}
@@ -1451,12 +1467,13 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "static_empty",
- static = {
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "static_empty", attrNameToString{
+ "static": `{
"system_dynamic_deps": [],
- },
-)`},
+ }`,
+ }),
+ },
})
}
@@ -1475,12 +1492,13 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "shared_empty",
- shared = {
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "shared_empty", attrNameToString{
+ "shared": `{
"system_dynamic_deps": [],
- },
-)`},
+ }`,
+ }),
+ },
})
}
@@ -1503,12 +1521,13 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "shared_empty",
- shared = {
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "shared_empty", attrNameToString{
+ "shared": `{
"system_dynamic_deps": [],
- },
-)`},
+ }`,
+ }),
+ },
})
}
@@ -1533,10 +1552,11 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "target_linux_bionic_empty",
- system_dynamic_deps = [],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "target_linux_bionic_empty", attrNameToString{
+ "system_dynamic_deps": `[]`,
+ }),
+ },
})
}
@@ -1557,10 +1577,11 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "target_bionic_empty",
- system_dynamic_deps = [],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "target_bionic_empty", attrNameToString{
+ "system_dynamic_deps": `[]`,
+ }),
+ },
})
}
@@ -1589,13 +1610,14 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "foo",
- shared = {
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "foo", attrNameToString{
+ "shared": `{
"system_dynamic_deps": [":libm"],
- },
- system_dynamic_deps = [":libc"],
-)`},
+ }`,
+ "system_dynamic_deps": `[":libc"]`,
+ }),
+ },
})
}
@@ -1637,9 +1659,9 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library(
- name = "foo-lib",
- srcs = ["base.cpp"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "foo-lib", attrNameToString{
+ "srcs": `["base.cpp"] + select({
"//build/bazel/platforms/os:android": [
"linux.cpp",
"bionic.cpp",
@@ -1660,9 +1682,10 @@
],
"//build/bazel/platforms/os:windows": ["windows.cpp"],
"//conditions:default": [],
- }),
-)`}})
-
+ })`,
+ }),
+ },
+ })
}
func TestCcLibraryCppStdWithGnuExtensions_ConvertsToFeatureAttr(t *testing.T) {
@@ -1714,17 +1737,17 @@
{cpp_std: "gnu++17", gnu_extensions: "true", bazel_cpp_std: "gnu++17"},
}
for _, tc := range testCases {
- cppStdAttr := ""
+ cppStdProp := ""
if tc.cpp_std != "" {
- cppStdAttr = fmt.Sprintf(" cpp_std: \"%s\",", tc.cpp_std)
+ cppStdProp = fmt.Sprintf(" cpp_std: \"%s\",", tc.cpp_std)
}
- gnuExtensionsAttr := ""
+ gnuExtensionsProp := ""
if tc.gnu_extensions != "" {
- gnuExtensionsAttr = fmt.Sprintf(" gnu_extensions: %s,", tc.gnu_extensions)
+ gnuExtensionsProp = fmt.Sprintf(" gnu_extensions: %s,", tc.gnu_extensions)
}
- bazelCppStdAttr := ""
+ attrs := attrNameToString{}
if tc.bazel_cpp_std != "" {
- bazelCppStdAttr = fmt.Sprintf("\n cpp_std = \"%s\",", tc.bazel_cpp_std)
+ attrs["cpp_std"] = fmt.Sprintf(`"%s"`, tc.bazel_cpp_std)
}
runCcLibraryTestCase(t, bp2buildTestCase{
@@ -1740,10 +1763,10 @@
%s // gnu_extensions: *bool
include_build_directory: false,
}
-`, cppStdAttr, gnuExtensionsAttr),
- expectedBazelTargets: []string{fmt.Sprintf(`cc_library(
- name = "a",%s
-)`, bazelCppStdAttr)},
+`, cppStdProp, gnuExtensionsProp),
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library", "a", attrs),
+ },
})
runCcLibraryStaticTestCase(t, bp2buildTestCase{
@@ -1759,10 +1782,10 @@
%s // gnu_extensions: *bool
include_build_directory: false,
}
-`, cppStdAttr, gnuExtensionsAttr),
- expectedBazelTargets: []string{fmt.Sprintf(`cc_library_static(
- name = "a",%s
-)`, bazelCppStdAttr)},
+`, cppStdProp, gnuExtensionsProp),
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "a", attrs),
+ },
})
runCcLibrarySharedTestCase(t, bp2buildTestCase{
@@ -1778,10 +1801,10 @@
%s // gnu_extensions: *bool
include_build_directory: false,
}
-`, cppStdAttr, gnuExtensionsAttr),
- expectedBazelTargets: []string{fmt.Sprintf(`cc_library_shared(
- name = "a",%s
-)`, bazelCppStdAttr)},
+`, cppStdProp, gnuExtensionsProp),
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_shared", "a", attrs),
+ },
})
}
}
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index e43672b..76fdab2 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -128,9 +128,9 @@
// TODO: Also support export_header_lib_headers
}`,
- expectedBazelTargets: []string{`cc_library_headers(
- name = "foo_headers",
- export_includes = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_headers", "foo_headers", attrNameToString{
+ "export_includes": `[
"dir-1",
"dir-2",
] + select({
@@ -138,12 +138,13 @@
"//build/bazel/platforms/arch:x86": ["arch_x86_exported_include_dir"],
"//build/bazel/platforms/arch:x86_64": ["arch_x86_64_exported_include_dir"],
"//conditions:default": [],
- }),
- implementation_deps = [
+ })`,
+ "implementation_deps": `[
":lib-1",
":lib-2",
- ],
-)`},
+ ]`,
+ }),
+ },
})
}
@@ -191,17 +192,18 @@
},
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_headers(
- name = "foo_headers",
- implementation_deps = [":base-lib"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_headers", "foo_headers", attrNameToString{
+ "implementation_deps": `[":base-lib"] + select({
"//build/bazel/platforms/os:android": [":android-lib"],
"//build/bazel/platforms/os:darwin": [":darwin-lib"],
"//build/bazel/platforms/os:linux": [":linux-lib"],
"//build/bazel/platforms/os:linux_bionic": [":linux_bionic-lib"],
"//build/bazel/platforms/os:windows": [":windows-lib"],
"//conditions:default": [],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
@@ -231,17 +233,18 @@
},
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_headers(
- name = "foo_headers",
- deps = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_headers", "foo_headers", attrNameToString{
+ "deps": `select({
"//build/bazel/platforms/os:android": [":exported-lib"],
"//conditions:default": [],
- }),
- implementation_deps = select({
+ })`,
+ "implementation_deps": `select({
"//build/bazel/platforms/os:android": [":android-lib"],
"//conditions:default": [],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
@@ -288,9 +291,9 @@
},
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_headers(
- name = "foo_headers",
- export_system_includes = ["shared_include_dir"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_headers", "foo_headers", attrNameToString{
+ "export_system_includes": `["shared_include_dir"] + select({
"//build/bazel/platforms/arch:arm": ["arm_include_dir"],
"//build/bazel/platforms/arch:x86_64": ["x86_64_include_dir"],
"//conditions:default": [],
@@ -299,8 +302,9 @@
"//build/bazel/platforms/os:darwin": ["darwin_include_dir"],
"//build/bazel/platforms/os:linux": ["linux_include_dir"],
"//conditions:default": [],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
@@ -330,9 +334,10 @@
no_libcrt: true,
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_headers(
- name = "lib-1",
- export_includes = ["lib-1"],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_headers", "lib-1", attrNameToString{
+ "export_includes": `["lib-1"]`,
+ }),
+ },
})
}
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index bb15776..4ec95c3 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -37,15 +37,15 @@
func runCcLibrarySharedTestCase(t *testing.T, tc bp2buildTestCase) {
t.Helper()
+ (&tc).moduleTypeUnderTest = "cc_library_shared"
+ (&tc).moduleTypeUnderTestFactory = cc.LibrarySharedFactory
+ (&tc).moduleTypeUnderTestBp2BuildMutator = cc.CcLibrarySharedBp2Build
runBp2BuildTestCase(t, registerCcLibrarySharedModuleTypes, tc)
}
func TestCcLibrarySharedSimple(t *testing.T) {
runCcLibrarySharedTestCase(t, bp2buildTestCase{
- description: "cc_library_shared simple overall test",
- moduleTypeUnderTest: "cc_library_shared",
- moduleTypeUnderTestFactory: cc.LibrarySharedFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build,
+ description: "cc_library_shared simple overall test",
filesystem: map[string]string{
// NOTE: include_dir headers *should not* appear in Bazel hdrs later (?)
"include_dir_1/include_dir_1_a.h": "",
@@ -140,52 +140,50 @@
// TODO: Also support export_header_lib_headers
}`,
- expectedBazelTargets: []string{`cc_library_shared(
- name = "foo_shared",
- absolute_includes = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{
+ "absolute_includes": `[
"include_dir_1",
"include_dir_2",
- ],
- copts = [
+ ]`,
+ "copts": `[
"-Dflag1",
"-Dflag2",
- ],
- export_includes = [
+ ]`,
+ "export_includes": `[
"export_include_dir_1",
"export_include_dir_2",
- ],
- implementation_deps = [
+ ]`,
+ "implementation_deps": `[
":header_lib_1",
":header_lib_2",
- ],
- implementation_dynamic_deps = [
+ ]`,
+ "implementation_dynamic_deps": `[
":shared_lib_1",
":shared_lib_2",
- ],
- local_includes = [
+ ]`,
+ "local_includes": `[
"local_include_dir_1",
"local_include_dir_2",
".",
- ],
- srcs = [
+ ]`,
+ "srcs": `[
"foo_shared1.cc",
"foo_shared2.cc",
- ],
- whole_archive_deps = [
+ ]`,
+ "whole_archive_deps": `[
":whole_static_lib_1",
":whole_static_lib_2",
- ],
-)`},
+ ]`,
+ }),
+ },
})
}
func TestCcLibrarySharedArchSpecificSharedLib(t *testing.T) {
runCcLibrarySharedTestCase(t, bp2buildTestCase{
- description: "cc_library_shared arch-specific shared_libs with whole_static_libs",
- moduleTypeUnderTest: "cc_library_shared",
- moduleTypeUnderTestFactory: cc.LibrarySharedFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build,
- filesystem: map[string]string{},
+ description: "cc_library_shared arch-specific shared_libs with whole_static_libs",
+ filesystem: map[string]string{},
blueprint: soongCcLibrarySharedPreamble + `
cc_library_static {
name: "static_dep",
@@ -200,27 +198,25 @@
arch: { arm64: { shared_libs: ["shared_dep"], whole_static_libs: ["static_dep"] } },
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_shared(
- name = "foo_shared",
- implementation_dynamic_deps = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{
+ "implementation_dynamic_deps": `select({
"//build/bazel/platforms/arch:arm64": [":shared_dep"],
"//conditions:default": [],
- }),
- whole_archive_deps = select({
+ })`,
+ "whole_archive_deps": `select({
"//build/bazel/platforms/arch:arm64": [":static_dep"],
"//conditions:default": [],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestCcLibrarySharedOsSpecificSharedLib(t *testing.T) {
- runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_shared os-specific shared_libs",
- moduleTypeUnderTest: "cc_library_shared",
- moduleTypeUnderTestFactory: cc.LibrarySharedFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build,
- filesystem: map[string]string{},
+ runCcLibrarySharedTestCase(t, bp2buildTestCase{
+ description: "cc_library_shared os-specific shared_libs",
+ filesystem: map[string]string{},
blueprint: soongCcLibrarySharedPreamble + `
cc_library_shared {
name: "shared_dep",
@@ -231,23 +227,21 @@
target: { android: { shared_libs: ["shared_dep"], } },
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_shared(
- name = "foo_shared",
- implementation_dynamic_deps = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{
+ "implementation_dynamic_deps": `select({
"//build/bazel/platforms/os:android": [":shared_dep"],
"//conditions:default": [],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestCcLibrarySharedBaseArchOsSpecificSharedLib(t *testing.T) {
runCcLibrarySharedTestCase(t, bp2buildTestCase{
- description: "cc_library_shared base, arch, and os-specific shared_libs",
- moduleTypeUnderTest: "cc_library_shared",
- moduleTypeUnderTestFactory: cc.LibrarySharedFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build,
- filesystem: map[string]string{},
+ description: "cc_library_shared base, arch, and os-specific shared_libs",
+ filesystem: map[string]string{},
blueprint: soongCcLibrarySharedPreamble + `
cc_library_shared {
name: "shared_dep",
@@ -268,25 +262,23 @@
arch: { arm64: { shared_libs: ["shared_dep3"] } },
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_shared(
- name = "foo_shared",
- implementation_dynamic_deps = [":shared_dep"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{
+ "implementation_dynamic_deps": `[":shared_dep"] + select({
"//build/bazel/platforms/arch:arm64": [":shared_dep3"],
"//conditions:default": [],
}) + select({
"//build/bazel/platforms/os:android": [":shared_dep2"],
"//conditions:default": [],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestCcLibrarySharedSimpleExcludeSrcs(t *testing.T) {
runCcLibrarySharedTestCase(t, bp2buildTestCase{
- description: "cc_library_shared simple exclude_srcs",
- moduleTypeUnderTest: "cc_library_shared",
- moduleTypeUnderTestFactory: cc.LibrarySharedFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build,
+ description: "cc_library_shared simple exclude_srcs",
filesystem: map[string]string{
"common.c": "",
"foo-a.c": "",
@@ -299,23 +291,21 @@
exclude_srcs: ["foo-excluded.c"],
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_shared(
- name = "foo_shared",
- srcs_c = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{
+ "srcs_c": `[
"common.c",
"foo-a.c",
- ],
-)`},
+ ]`,
+ }),
+ },
})
}
func TestCcLibrarySharedStrip(t *testing.T) {
runCcLibrarySharedTestCase(t, bp2buildTestCase{
- description: "cc_library_shared stripping",
- moduleTypeUnderTest: "cc_library_shared",
- moduleTypeUnderTestFactory: cc.LibrarySharedFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build,
- filesystem: map[string]string{},
+ description: "cc_library_shared stripping",
+ filesystem: map[string]string{},
blueprint: soongCcLibrarySharedPreamble + `
cc_library_shared {
name: "foo_shared",
@@ -328,9 +318,9 @@
},
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_shared(
- name = "foo_shared",
- strip = {
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{
+ "strip": `{
"all": True,
"keep_symbols": False,
"keep_symbols_and_debug_frame": True,
@@ -339,17 +329,15 @@
"sym2",
],
"none": False,
- },
-)`},
+ }`,
+ }),
+ },
})
}
func TestCcLibrarySharedVersionScript(t *testing.T) {
runCcLibrarySharedTestCase(t, bp2buildTestCase{
- description: "cc_library_shared version script",
- moduleTypeUnderTest: "cc_library_shared",
- moduleTypeUnderTestFactory: cc.LibrarySharedFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build,
+ description: "cc_library_shared version script",
filesystem: map[string]string{
"version_script": "",
},
@@ -359,20 +347,18 @@
version_script: "version_script",
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_shared(
- name = "foo_shared",
- additional_linker_inputs = ["version_script"],
- linkopts = ["-Wl,--version-script,$(location version_script)"],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{
+ "additional_linker_inputs": `["version_script"]`,
+ "linkopts": `["-Wl,--version-script,$(location version_script)"]`,
+ }),
+ },
})
}
func TestCcLibrarySharedNoCrtTrue(t *testing.T) {
runCcLibrarySharedTestCase(t, bp2buildTestCase{
- description: "cc_library_shared - nocrt: true emits attribute",
- moduleTypeUnderTest: "cc_library_shared",
- moduleTypeUnderTestFactory: cc.LibrarySharedFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build,
+ description: "cc_library_shared - nocrt: true emits attribute",
filesystem: map[string]string{
"impl.cpp": "",
},
@@ -384,19 +370,18 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library_shared(
- name = "foo_shared",
- link_crt = False,
- srcs = ["impl.cpp"],
-)`}})
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{
+ "link_crt": `False`,
+ "srcs": `["impl.cpp"]`,
+ }),
+ },
+ })
}
func TestCcLibrarySharedNoCrtFalse(t *testing.T) {
runCcLibrarySharedTestCase(t, bp2buildTestCase{
- description: "cc_library_shared - nocrt: false doesn't emit attribute",
- moduleTypeUnderTest: "cc_library_shared",
- moduleTypeUnderTestFactory: cc.LibrarySharedFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build,
+ description: "cc_library_shared - nocrt: false doesn't emit attribute",
filesystem: map[string]string{
"impl.cpp": "",
},
@@ -408,18 +393,17 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library_shared(
- name = "foo_shared",
- srcs = ["impl.cpp"],
-)`}})
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_shared", "foo_shared", attrNameToString{
+ "srcs": `["impl.cpp"]`,
+ }),
+ },
+ })
}
func TestCcLibrarySharedNoCrtArchVariant(t *testing.T) {
runCcLibrarySharedTestCase(t, bp2buildTestCase{
- description: "cc_library_shared - nocrt in select",
- moduleTypeUnderTest: "cc_library_shared",
- moduleTypeUnderTestFactory: cc.LibrarySharedFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build,
+ description: "cc_library_shared - nocrt in select",
filesystem: map[string]string{
"impl.cpp": "",
},
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 9887811..2f760d2 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -79,15 +79,16 @@
func runCcLibraryStaticTestCase(t *testing.T, tc bp2buildTestCase) {
t.Helper()
+
+ (&tc).moduleTypeUnderTest = "cc_library_static"
+ (&tc).moduleTypeUnderTestFactory = cc.LibraryStaticFactory
+ (&tc).moduleTypeUnderTestBp2BuildMutator = cc.CcLibraryStaticBp2Build
runBp2BuildTestCase(t, registerCcLibraryStaticModuleTypes, tc)
}
func TestCcLibraryStaticSimple(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static test",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static test",
filesystem: map[string]string{
// NOTE: include_dir headers *should not* appear in Bazel hdrs later (?)
"include_dir_1/include_dir_1_a.h": "",
@@ -182,49 +183,47 @@
// TODO: Also support export_header_lib_headers
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- absolute_includes = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "absolute_includes": `[
"include_dir_1",
"include_dir_2",
- ],
- copts = [
+ ]`,
+ "copts": `[
"-Dflag1",
"-Dflag2",
- ],
- export_includes = [
+ ]`,
+ "export_includes": `[
"export_include_dir_1",
"export_include_dir_2",
- ],
- implementation_deps = [
+ ]`,
+ "implementation_deps": `[
":header_lib_1",
":header_lib_2",
":static_lib_1",
":static_lib_2",
- ],
- local_includes = [
+ ]`,
+ "local_includes": `[
"local_include_dir_1",
"local_include_dir_2",
".",
- ],
- srcs = [
+ ]`,
+ "srcs": `[
"foo_static1.cc",
"foo_static2.cc",
- ],
- whole_archive_deps = [
+ ]`,
+ "whole_archive_deps": `[
":whole_static_lib_1",
":whole_static_lib_2",
- ],
-)`},
+ ]`,
+ }),
+ },
})
}
func TestCcLibraryStaticSubpackage(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static subpackage test",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static subpackage test",
filesystem: map[string]string{
// subpackage with subdirectory
"subpackage/Android.bp": "",
@@ -247,20 +246,18 @@
"subpackage",
],
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- absolute_includes = ["subpackage"],
- local_includes = ["."],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "absolute_includes": `["subpackage"]`,
+ "local_includes": `["."]`,
+ }),
+ },
})
}
func TestCcLibraryStaticExportIncludeDir(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static export include dir",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static export include dir",
filesystem: map[string]string{
// subpackage with subdirectory
"subpackage/Android.bp": "",
@@ -273,19 +270,17 @@
export_include_dirs: ["subpackage"],
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- export_includes = ["subpackage"],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "export_includes": `["subpackage"]`,
+ }),
+ },
})
}
func TestCcLibraryStaticExportSystemIncludeDir(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static export system include dir",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static export system include dir",
filesystem: map[string]string{
// subpackage with subdirectory
"subpackage/Android.bp": "",
@@ -298,20 +293,18 @@
export_system_include_dirs: ["subpackage"],
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- export_system_includes = ["subpackage"],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "export_system_includes": `["subpackage"]`,
+ }),
+ },
})
}
func TestCcLibraryStaticManyIncludeDirs(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static include_dirs, local_include_dirs, export_include_dirs (b/183742505)",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
- dir: "subpackage",
+ description: "cc_library_static include_dirs, local_include_dirs, export_include_dirs (b/183742505)",
+ dir: "subpackage",
filesystem: map[string]string{
// subpackage with subdirectory
"subpackage/Android.bp": `
@@ -335,28 +328,25 @@
"subpackage3/subsubpackage/header.h": "",
},
blueprint: soongCcLibraryStaticPreamble,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- absolute_includes = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "absolute_includes": `[
"subpackage/subsubpackage",
"subpackage2",
"subpackage3/subsubpackage",
- ],
- export_includes = ["./exported_subsubpackage"],
- local_includes = [
+ ]`,
+ "export_includes": `["./exported_subsubpackage"]`,
+ "local_includes": `[
"subsubpackage2",
".",
- ],
-)`},
+ ]`,
+ })},
})
}
func TestCcLibraryStaticIncludeBuildDirectoryDisabled(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static include_build_directory disabled",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static include_build_directory disabled",
filesystem: map[string]string{
// subpackage with subdirectory
"subpackage/Android.bp": "",
@@ -370,20 +360,18 @@
local_include_dirs: ["subpackage2"],
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- absolute_includes = ["subpackage"],
- local_includes = ["subpackage2"],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "absolute_includes": `["subpackage"]`,
+ "local_includes": `["subpackage2"]`,
+ }),
+ },
})
}
func TestCcLibraryStaticIncludeBuildDirectoryEnabled(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static include_build_directory enabled",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static include_build_directory enabled",
filesystem: map[string]string{
// subpackage with subdirectory
"subpackage/Android.bp": "",
@@ -399,24 +387,22 @@
local_include_dirs: ["subpackage2"],
include_build_directory: true,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- absolute_includes = ["subpackage"],
- local_includes = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "absolute_includes": `["subpackage"]`,
+ "local_includes": `[
"subpackage2",
".",
- ],
-)`},
+ ]`,
+ }),
+ },
})
}
func TestCcLibraryStaticArchSpecificStaticLib(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static arch-specific static_libs",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
- filesystem: map[string]string{},
+ description: "cc_library_static arch-specific static_libs",
+ filesystem: map[string]string{},
blueprint: soongCcLibraryStaticPreamble + `
cc_library_static {
name: "static_dep",
@@ -431,27 +417,25 @@
arch: { arm64: { static_libs: ["static_dep"], whole_static_libs: ["static_dep2"] } },
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- implementation_deps = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "implementation_deps": `select({
"//build/bazel/platforms/arch:arm64": [":static_dep"],
"//conditions:default": [],
- }),
- whole_archive_deps = select({
+ })`,
+ "whole_archive_deps": `select({
"//build/bazel/platforms/arch:arm64": [":static_dep2"],
"//conditions:default": [],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestCcLibraryStaticOsSpecificStaticLib(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static os-specific static_libs",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
- filesystem: map[string]string{},
+ description: "cc_library_static os-specific static_libs",
+ filesystem: map[string]string{},
blueprint: soongCcLibraryStaticPreamble + `
cc_library_static {
name: "static_dep",
@@ -466,27 +450,25 @@
target: { android: { static_libs: ["static_dep"], whole_static_libs: ["static_dep2"] } },
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- implementation_deps = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "implementation_deps": `select({
"//build/bazel/platforms/os:android": [":static_dep"],
"//conditions:default": [],
- }),
- whole_archive_deps = select({
+ })`,
+ "whole_archive_deps": `select({
"//build/bazel/platforms/os:android": [":static_dep2"],
"//conditions:default": [],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestCcLibraryStaticBaseArchOsSpecificStaticLib(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static base, arch and os-specific static_libs",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
- filesystem: map[string]string{},
+ description: "cc_library_static base, arch and os-specific static_libs",
+ filesystem: map[string]string{},
blueprint: soongCcLibraryStaticPreamble + `
cc_library_static {
name: "static_dep",
@@ -512,26 +494,24 @@
arch: { arm64: { static_libs: ["static_dep4"] } },
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- implementation_deps = [":static_dep"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "implementation_deps": `[":static_dep"] + select({
"//build/bazel/platforms/arch:arm64": [":static_dep4"],
"//conditions:default": [],
}) + select({
"//build/bazel/platforms/os:android": [":static_dep3"],
"//conditions:default": [],
- }),
- whole_archive_deps = [":static_dep2"],
-)`},
+ })`,
+ "whole_archive_deps": `[":static_dep2"]`,
+ }),
+ },
})
}
func TestCcLibraryStaticSimpleExcludeSrcs(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static simple exclude_srcs",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static simple exclude_srcs",
filesystem: map[string]string{
"common.c": "",
"foo-a.c": "",
@@ -544,22 +524,20 @@
exclude_srcs: ["foo-excluded.c"],
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- srcs_c = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "srcs_c": `[
"common.c",
"foo-a.c",
- ],
-)`},
+ ]`,
+ }),
+ },
})
}
func TestCcLibraryStaticOneArchSrcs(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static one arch specific srcs",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static one arch specific srcs",
filesystem: map[string]string{
"common.c": "",
"foo-arm.c": "",
@@ -571,22 +549,20 @@
arch: { arm: { srcs: ["foo-arm.c"] } },
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- srcs_c = ["common.c"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "srcs_c": `["common.c"] + select({
"//build/bazel/platforms/arch:arm": ["foo-arm.c"],
"//conditions:default": [],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestCcLibraryStaticOneArchSrcsExcludeSrcs(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static one arch specific srcs and exclude_srcs",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static one arch specific srcs and exclude_srcs",
filesystem: map[string]string{
"common.c": "",
"for-arm.c": "",
@@ -603,22 +579,20 @@
},
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- srcs_c = ["common.c"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "srcs_c": `["common.c"] + select({
"//build/bazel/platforms/arch:arm": ["for-arm.c"],
"//conditions:default": ["not-for-arm.c"],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestCcLibraryStaticTwoArchExcludeSrcs(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static arch specific exclude_srcs for 2 architectures",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static arch specific exclude_srcs for 2 architectures",
filesystem: map[string]string{
"common.c": "",
"for-arm.c": "",
@@ -637,9 +611,9 @@
},
include_build_directory: false,
} `,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- srcs_c = ["common.c"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "srcs_c": `["common.c"] + select({
"//build/bazel/platforms/arch:arm": [
"not-for-x86.c",
"for-arm.c",
@@ -652,16 +626,15 @@
"not-for-arm.c",
"not-for-x86.c",
],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
+
func TestCcLibraryStaticFourArchExcludeSrcs(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static arch specific exclude_srcs for 4 architectures",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static arch specific exclude_srcs for 4 architectures",
filesystem: map[string]string{
"common.c": "",
"for-arm.c": "",
@@ -687,9 +660,9 @@
},
include_build_directory: false,
} `,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- srcs_c = ["common.c"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "srcs_c": `["common.c"] + select({
"//build/bazel/platforms/arch:arm": [
"not-for-arm64.c",
"not-for-x86.c",
@@ -720,17 +693,15 @@
"not-for-x86.c",
"not-for-x86_64.c",
],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestCcLibraryStaticOneArchEmpty(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static one arch empty",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static one arch empty",
filesystem: map[string]string{
"common.cc": "",
"foo-no-arm.cc": "",
@@ -746,22 +717,20 @@
},
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- srcs = ["common.cc"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "srcs": `["common.cc"] + select({
"//build/bazel/platforms/arch:arm": [],
"//conditions:default": ["foo-no-arm.cc"],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestCcLibraryStaticOneArchEmptyOtherSet(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static one arch empty other set",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static one arch empty other set",
filesystem: map[string]string{
"common.cc": "",
"foo-no-arm.cc": "",
@@ -779,27 +748,25 @@
},
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- srcs = ["common.cc"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "srcs": `["common.cc"] + select({
"//build/bazel/platforms/arch:arm": [],
"//build/bazel/platforms/arch:x86": [
"foo-no-arm.cc",
"x86-only.cc",
],
"//conditions:default": ["foo-no-arm.cc"],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestCcLibraryStaticMultipleDepSameName(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static multiple dep same name panic",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
- filesystem: map[string]string{},
+ description: "cc_library_static multiple dep same name panic",
+ filesystem: map[string]string{},
blueprint: soongCcLibraryStaticPreamble + `
cc_library_static {
name: "static_dep",
@@ -810,19 +777,17 @@
static_libs: ["static_dep", "static_dep"],
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- implementation_deps = [":static_dep"],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "implementation_deps": `[":static_dep"]`,
+ }),
+ },
})
}
func TestCcLibraryStaticOneMultilibSrcsExcludeSrcs(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static 1 multilib srcs and exclude_srcs",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static 1 multilib srcs and exclude_srcs",
filesystem: map[string]string{
"common.c": "",
"for-lib32.c": "",
@@ -837,23 +802,21 @@
},
include_build_directory: false,
} `,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- srcs_c = ["common.c"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "srcs_c": `["common.c"] + select({
"//build/bazel/platforms/arch:arm": ["for-lib32.c"],
"//build/bazel/platforms/arch:x86": ["for-lib32.c"],
"//conditions:default": ["not-for-lib32.c"],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestCcLibraryStaticTwoMultilibSrcsExcludeSrcs(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static 2 multilib srcs and exclude_srcs",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static 2 multilib srcs and exclude_srcs",
filesystem: map[string]string{
"common.c": "",
"for-lib32.c": "",
@@ -863,7 +826,7 @@
},
blueprint: soongCcLibraryStaticPreamble + `
cc_library_static {
- name: "foo_static2",
+ name: "foo_static",
srcs: ["common.c", "not-for-*.c"],
multilib: {
lib32: { srcs: ["for-lib32.c"], exclude_srcs: ["not-for-lib32.c"] },
@@ -871,9 +834,9 @@
},
include_build_directory: false,
} `,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static2",
- srcs_c = ["common.c"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "srcs_c": `["common.c"] + select({
"//build/bazel/platforms/arch:arm": [
"not-for-lib64.c",
"for-lib32.c",
@@ -894,17 +857,15 @@
"not-for-lib32.c",
"not-for-lib64.c",
],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestCcLibrarySTaticArchMultilibSrcsExcludeSrcs(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static arch and multilib srcs and exclude_srcs",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static arch and multilib srcs and exclude_srcs",
filesystem: map[string]string{
"common.c": "",
"for-arm.c": "",
@@ -923,7 +884,7 @@
},
blueprint: soongCcLibraryStaticPreamble + `
cc_library_static {
- name: "foo_static3",
+ name: "foo_static",
srcs: ["common.c", "not-for-*.c"],
exclude_srcs: ["not-for-everything.c"],
arch: {
@@ -938,9 +899,9 @@
},
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static3",
- srcs_c = ["common.c"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "srcs_c": `["common.c"] + select({
"//build/bazel/platforms/arch:arm": [
"not-for-arm64.c",
"not-for-lib64.c",
@@ -981,16 +942,14 @@
"not-for-x86.c",
"not-for-x86_64.c",
],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestCcLibraryStaticGeneratedHeadersAllPartitions(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
blueprint: soongCcLibraryStaticPreamble + `
genrule {
name: "generated_hdr",
@@ -1009,31 +968,29 @@
export_generated_headers: ["export_generated_hdr"],
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- hdrs = [":export_generated_hdr"],
- srcs = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "hdrs": `[":export_generated_hdr"]`,
+ "srcs": `[
"cpp_src.cpp",
":generated_hdr",
- ],
- srcs_as = [
+ ]`,
+ "srcs_as": `[
"as_src.S",
":generated_hdr",
- ],
- srcs_c = [
+ ]`,
+ "srcs_c": `[
"c_src.c",
":generated_hdr",
- ],
-)`},
+ ]`,
+ }),
+ },
})
}
func TestCcLibraryStaticArchSrcsExcludeSrcsGeneratedFiles(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static arch srcs/exclude_srcs with generated files",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static arch srcs/exclude_srcs with generated files",
filesystem: map[string]string{
"common.cpp": "",
"for-x86.cpp": "",
@@ -1082,7 +1039,7 @@
}
cc_library_static {
- name: "foo_static3",
+ name: "foo_static",
srcs: ["common.cpp", "not-for-*.cpp"],
exclude_srcs: ["not-for-everything.cpp"],
generated_sources: ["generated_src", "generated_src_other_pkg", "generated_src_not_x86"],
@@ -1105,9 +1062,9 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static3",
- srcs = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "srcs": `[
"common.cpp",
":generated_src",
"//dep:generated_src_other_pkg",
@@ -1128,18 +1085,16 @@
"//dep:generated_hdr_other_pkg_android",
],
"//conditions:default": [],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestCcLibraryStaticGetTargetProperties(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static complex GetTargetProperties",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static complex GetTargetProperties",
blueprint: soongCcLibraryStaticPreamble + `
cc_library_static {
name: "foo_static",
@@ -1168,9 +1123,9 @@
},
include_build_directory: false,
}`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- srcs_c = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "srcs_c": `select({
"//build/bazel/platforms/os:android": ["android_src.c"],
"//conditions:default": [],
}) + select({
@@ -1181,17 +1136,15 @@
"//build/bazel/platforms/os_arch:linux_bionic_arm64": ["linux_bionic_arm64_src.c"],
"//build/bazel/platforms/os_arch:linux_bionic_x86_64": ["linux_bionic_x86_64_src.c"],
"//conditions:default": [],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestCcLibraryStaticProductVariableSelects(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static product variable selects",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static product variable selects",
blueprint: soongCcLibraryStaticPreamble + `
cc_library_static {
name: "foo_static",
@@ -1209,9 +1162,9 @@
},
include_build_directory: false,
} `,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- copts = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "copts": `select({
"//build/bazel/product_variables:binder32bit": ["-Wbinder32bit"],
"//conditions:default": [],
}) + select({
@@ -1220,19 +1173,17 @@
}) + select({
"//build/bazel/product_variables:malloc_zero_contents": ["-Wmalloc_zero_contents"],
"//conditions:default": [],
- }),
- srcs_c = ["common.c"],
-)`},
+ })`,
+ "srcs_c": `["common.c"]`,
+ }),
+ },
})
}
func TestCcLibraryStaticProductVariableArchSpecificSelects(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static arch-specific product variable selects",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
- filesystem: map[string]string{},
+ description: "cc_library_static arch-specific product variable selects",
+ filesystem: map[string]string{},
blueprint: soongCcLibraryStaticPreamble + `
cc_library_static {
name: "foo_static",
@@ -1271,9 +1222,9 @@
},
include_build_directory: false,
} `,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- copts = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "copts": `select({
"//build/bazel/product_variables:malloc_not_svelte": ["-Wmalloc_not_svelte"],
"//conditions:default": [],
}) + select({
@@ -1288,19 +1239,17 @@
}) + select({
"//build/bazel/product_variables:malloc_not_svelte-x86": ["-Wlib32_malloc_not_svelte"],
"//conditions:default": [],
- }),
- srcs_c = ["common.c"],
-)`},
+ })`,
+ "srcs_c": `["common.c"]`,
+ }),
+ },
})
}
func TestCcLibraryStaticProductVariableStringReplacement(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static product variable string replacement",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
- filesystem: map[string]string{},
+ description: "cc_library_static product variable string replacement",
+ filesystem: map[string]string{},
blueprint: soongCcLibraryStaticPreamble + `
cc_library_static {
name: "foo_static",
@@ -1312,23 +1261,21 @@
},
include_build_directory: false,
} `,
- expectedBazelTargets: []string{`cc_library_static(
- name = "foo_static",
- asflags = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
+ "asflags": `select({
"//build/bazel/product_variables:platform_sdk_version": ["-DPLATFORM_SDK_VERSION=$(Platform_sdk_version)"],
"//conditions:default": [],
- }),
- srcs_as = ["common.S"],
-)`},
+ })`,
+ "srcs_as": `["common.S"]`,
+ }),
+ },
})
}
func TestStaticLibrary_SystemSharedLibsRootEmpty(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static system_shared_lib empty root",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static system_shared_lib empty root",
blueprint: soongCcLibraryStaticPreamble + `
cc_library_static {
name: "root_empty",
@@ -1336,19 +1283,17 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "root_empty",
- system_dynamic_deps = [],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "root_empty", attrNameToString{
+ "system_dynamic_deps": `[]`,
+ }),
+ },
})
}
func TestStaticLibrary_SystemSharedLibsStaticEmpty(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static system_shared_lib empty static default",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static system_shared_lib empty static default",
blueprint: soongCcLibraryStaticPreamble + `
cc_defaults {
name: "static_empty_defaults",
@@ -1362,19 +1307,17 @@
defaults: ["static_empty_defaults"],
}
`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "static_empty",
- system_dynamic_deps = [],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "static_empty", attrNameToString{
+ "system_dynamic_deps": `[]`,
+ }),
+ },
})
}
func TestStaticLibrary_SystemSharedLibsBionicEmpty(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static system_shared_lib empty for bionic variant",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static system_shared_lib empty for bionic variant",
blueprint: soongCcLibraryStaticPreamble + `
cc_library_static {
name: "target_bionic_empty",
@@ -1386,10 +1329,11 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "target_bionic_empty",
- system_dynamic_deps = [],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "target_bionic_empty", attrNameToString{
+ "system_dynamic_deps": `[]`,
+ }),
+ },
})
}
@@ -1399,10 +1343,7 @@
// only for linux_bionic, but `android` had `["libc", "libdl", "libm"].
// b/195791252 tracks the fix.
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static system_shared_lib empty for linux_bionic variant",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static system_shared_lib empty for linux_bionic variant",
blueprint: soongCcLibraryStaticPreamble + `
cc_library_static {
name: "target_linux_bionic_empty",
@@ -1414,19 +1355,17 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "target_linux_bionic_empty",
- system_dynamic_deps = [],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "target_linux_bionic_empty", attrNameToString{
+ "system_dynamic_deps": `[]`,
+ }),
+ },
})
}
func TestStaticLibrary_SystemSharedLibsBionic(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static system_shared_libs set for bionic variant",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static system_shared_libs set for bionic variant",
blueprint: soongCcLibraryStaticPreamble + `
cc_library{name: "libc"}
@@ -1440,23 +1379,21 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "target_bionic",
- system_dynamic_deps = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "target_bionic", attrNameToString{
+ "system_dynamic_deps": `select({
"//build/bazel/platforms/os:android": [":libc"],
"//build/bazel/platforms/os:linux_bionic": [":libc"],
"//conditions:default": [],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
func TestStaticLibrary_SystemSharedLibsLinuxRootAndLinuxBionic(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
- description: "cc_library_static system_shared_libs set for root and linux_bionic variant",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "cc_library_static system_shared_libs set for root and linux_bionic variant",
blueprint: soongCcLibraryStaticPreamble + `
cc_library{name: "libc"}
cc_library{name: "libm"}
@@ -1472,12 +1409,13 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_library_static(
- name = "target_linux_bionic",
- system_dynamic_deps = [":libc"] + select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "target_linux_bionic", attrNameToString{
+ "system_dynamic_deps": `[":libc"] + select({
"//build/bazel/platforms/os:linux_bionic": [":libm"],
"//conditions:default": [],
- }),
-)`},
+ })`,
+ }),
+ },
})
}
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index c4b276a..5ab9129 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -28,15 +28,15 @@
func runCcObjectTestCase(t *testing.T, tc bp2buildTestCase) {
t.Helper()
+ (&tc).moduleTypeUnderTest = "cc_object"
+ (&tc).moduleTypeUnderTestFactory = cc.ObjectFactory
+ (&tc).moduleTypeUnderTestBp2BuildMutator = cc.ObjectBp2Build
runBp2BuildTestCase(t, registerCcObjectModuleTypes, tc)
}
func TestCcObjectSimple(t *testing.T) {
runCcObjectTestCase(t, bp2buildTestCase{
- description: "simple cc_object generates cc_object with include header dep",
- moduleTypeUnderTest: "cc_object",
- moduleTypeUnderTestFactory: cc.ObjectFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ description: "simple cc_object generates cc_object with include header dep",
filesystem: map[string]string{
"a/b/foo.h": "",
"a/b/bar.h": "",
@@ -58,30 +58,27 @@
exclude_srcs: ["a/b/exclude.c"],
}
`,
- expectedBazelTargets: []string{`cc_object(
- name = "foo",
- copts = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_object", "foo", attrNameToString{
+ "copts": `[
"-fno-addrsig",
"-Wno-gcc-compat",
"-Wall",
"-Werror",
- ],
- local_includes = [
+ ]`,
+ "local_includes": `[
"include",
".",
- ],
- srcs = ["a/b/c.c"],
- system_dynamic_deps = [],
-)`,
+ ]`,
+ "srcs": `["a/b/c.c"]`,
+ "system_dynamic_deps": `[]`,
+ }),
},
})
}
func TestCcObjectDefaults(t *testing.T) {
runCcObjectTestCase(t, bp2buildTestCase{
- moduleTypeUnderTest: "cc_object",
- moduleTypeUnderTestFactory: cc.ObjectFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
blueprint: `cc_object {
name: "foo",
system_shared_libs: [],
@@ -101,33 +98,26 @@
cc_defaults {
name: "foo_bar_defaults",
cflags: [
- "-Wno-gcc-compat",
- "-Wall",
"-Werror",
],
}
`,
- expectedBazelTargets: []string{`cc_object(
- name = "foo",
- copts = [
- "-Wno-gcc-compat",
- "-Wall",
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_object", "foo", attrNameToString{
+ "copts": `[
"-Werror",
"-fno-addrsig",
- ],
- local_includes = ["."],
- srcs = ["a/b/c.c"],
- system_dynamic_deps = [],
-)`,
+ ]`,
+ "local_includes": `["."]`,
+ "srcs": `["a/b/c.c"]`,
+ "system_dynamic_deps": `[]`,
+ }),
}})
}
func TestCcObjectCcObjetDepsInObjs(t *testing.T) {
runCcObjectTestCase(t, bp2buildTestCase{
- description: "cc_object with cc_object deps in objs props",
- moduleTypeUnderTest: "cc_object",
- moduleTypeUnderTestFactory: cc.ObjectFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ description: "cc_object with cc_object deps in objs props",
filesystem: map[string]string{
"a/b/c.c": "",
"x/y/z.c": "",
@@ -147,28 +137,24 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_object(
- name = "bar",
- copts = ["-fno-addrsig"],
- srcs = ["x/y/z.c"],
- system_dynamic_deps = [],
-)`, `cc_object(
- name = "foo",
- copts = ["-fno-addrsig"],
- deps = [":bar"],
- srcs = ["a/b/c.c"],
- system_dynamic_deps = [],
-)`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_object", "bar", attrNameToString{
+ "copts": `["-fno-addrsig"]`,
+ "srcs": `["x/y/z.c"]`,
+ "system_dynamic_deps": `[]`,
+ }), makeBazelTarget("cc_object", "foo", attrNameToString{
+ "copts": `["-fno-addrsig"]`,
+ "deps": `[":bar"]`,
+ "srcs": `["a/b/c.c"]`,
+ "system_dynamic_deps": `[]`,
+ }),
},
})
}
func TestCcObjectIncludeBuildDirFalse(t *testing.T) {
runCcObjectTestCase(t, bp2buildTestCase{
- description: "cc_object with include_build_dir: false",
- moduleTypeUnderTest: "cc_object",
- moduleTypeUnderTestFactory: cc.ObjectFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ description: "cc_object with include_build_dir: false",
filesystem: map[string]string{
"a/b/c.c": "",
"x/y/z.c": "",
@@ -180,22 +166,19 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{`cc_object(
- name = "foo",
- copts = ["-fno-addrsig"],
- srcs = ["a/b/c.c"],
- system_dynamic_deps = [],
-)`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_object", "foo", attrNameToString{
+ "copts": `["-fno-addrsig"]`,
+ "srcs": `["a/b/c.c"]`,
+ "system_dynamic_deps": `[]`,
+ }),
},
})
}
func TestCcObjectProductVariable(t *testing.T) {
runCcObjectTestCase(t, bp2buildTestCase{
- description: "cc_object with product variable",
- moduleTypeUnderTest: "cc_object",
- moduleTypeUnderTestFactory: cc.ObjectFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ description: "cc_object with product variable",
blueprint: `cc_object {
name: "foo",
system_shared_libs: [],
@@ -208,26 +191,23 @@
srcs: ["src.S"],
}
`,
- expectedBazelTargets: []string{`cc_object(
- name = "foo",
- asflags = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_object", "foo", attrNameToString{
+ "asflags": `select({
"//build/bazel/product_variables:platform_sdk_version": ["-DPLATFORM_SDK_VERSION=$(Platform_sdk_version)"],
"//conditions:default": [],
- }),
- copts = ["-fno-addrsig"],
- srcs_as = ["src.S"],
- system_dynamic_deps = [],
-)`,
+ })`,
+ "copts": `["-fno-addrsig"]`,
+ "srcs_as": `["src.S"]`,
+ "system_dynamic_deps": `[]`,
+ }),
},
})
}
func TestCcObjectCflagsOneArch(t *testing.T) {
runCcObjectTestCase(t, bp2buildTestCase{
- description: "cc_object setting cflags for one arch",
- moduleTypeUnderTest: "cc_object",
- moduleTypeUnderTestFactory: cc.ObjectFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ description: "cc_object setting cflags for one arch",
blueprint: `cc_object {
name: "foo",
system_shared_libs: [],
@@ -244,28 +224,24 @@
}
`,
expectedBazelTargets: []string{
- `cc_object(
- name = "foo",
- copts = ["-fno-addrsig"] + select({
+ makeBazelTarget("cc_object", "foo", attrNameToString{
+ "copts": `["-fno-addrsig"] + select({
"//build/bazel/platforms/arch:x86": ["-fPIC"],
"//conditions:default": [],
- }),
- srcs = ["a.cpp"] + select({
+ })`,
+ "srcs": `["a.cpp"] + select({
"//build/bazel/platforms/arch:arm": ["arch/arm/file.cpp"],
"//conditions:default": [],
- }),
- system_dynamic_deps = [],
-)`,
+ })`,
+ "system_dynamic_deps": `[]`,
+ }),
},
})
}
func TestCcObjectCflagsFourArch(t *testing.T) {
runCcObjectTestCase(t, bp2buildTestCase{
- description: "cc_object setting cflags for 4 architectures",
- moduleTypeUnderTest: "cc_object",
- moduleTypeUnderTestFactory: cc.ObjectFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ description: "cc_object setting cflags for 4 architectures",
blueprint: `cc_object {
name: "foo",
system_shared_libs: [],
@@ -292,34 +268,30 @@
}
`,
expectedBazelTargets: []string{
- `cc_object(
- name = "foo",
- copts = ["-fno-addrsig"] + select({
+ makeBazelTarget("cc_object", "foo", attrNameToString{
+ "copts": `["-fno-addrsig"] + select({
"//build/bazel/platforms/arch:arm": ["-Wall"],
"//build/bazel/platforms/arch:arm64": ["-Wall"],
"//build/bazel/platforms/arch:x86": ["-fPIC"],
"//build/bazel/platforms/arch:x86_64": ["-fPIC"],
"//conditions:default": [],
- }),
- srcs = ["base.cpp"] + select({
+ })`,
+ "srcs": `["base.cpp"] + select({
"//build/bazel/platforms/arch:arm": ["arm.cpp"],
"//build/bazel/platforms/arch:arm64": ["arm64.cpp"],
"//build/bazel/platforms/arch:x86": ["x86.cpp"],
"//build/bazel/platforms/arch:x86_64": ["x86_64.cpp"],
"//conditions:default": [],
- }),
- system_dynamic_deps = [],
-)`,
+ })`,
+ "system_dynamic_deps": `[]`,
+ }),
},
})
}
func TestCcObjectLinkerScript(t *testing.T) {
runCcObjectTestCase(t, bp2buildTestCase{
- description: "cc_object setting linker_script",
- moduleTypeUnderTest: "cc_object",
- moduleTypeUnderTestFactory: cc.ObjectFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ description: "cc_object setting linker_script",
blueprint: `cc_object {
name: "foo",
srcs: ["base.cpp"],
@@ -328,22 +300,18 @@
}
`,
expectedBazelTargets: []string{
- `cc_object(
- name = "foo",
- copts = ["-fno-addrsig"],
- linker_script = "bunny.lds",
- srcs = ["base.cpp"],
-)`,
+ makeBazelTarget("cc_object", "foo", attrNameToString{
+ "copts": `["-fno-addrsig"]`,
+ "linker_script": `"bunny.lds"`,
+ "srcs": `["base.cpp"]`,
+ }),
},
})
}
func TestCcObjectDepsAndLinkerScriptSelects(t *testing.T) {
runCcObjectTestCase(t, bp2buildTestCase{
- description: "cc_object setting deps and linker_script across archs",
- moduleTypeUnderTest: "cc_object",
- moduleTypeUnderTestFactory: cc.ObjectFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ description: "cc_object setting deps and linker_script across archs",
blueprint: `cc_object {
name: "foo",
srcs: ["base.cpp"],
@@ -389,33 +357,29 @@
}
`,
expectedBazelTargets: []string{
- `cc_object(
- name = "foo",
- copts = ["-fno-addrsig"],
- deps = select({
+ makeBazelTarget("cc_object", "foo", attrNameToString{
+ "copts": `["-fno-addrsig"]`,
+ "deps": `select({
"//build/bazel/platforms/arch:arm": [":arm_obj"],
"//build/bazel/platforms/arch:x86": [":x86_obj"],
"//build/bazel/platforms/arch:x86_64": [":x86_64_obj"],
"//conditions:default": [],
- }),
- linker_script = select({
+ })`,
+ "linker_script": `select({
"//build/bazel/platforms/arch:arm": "arm.lds",
"//build/bazel/platforms/arch:x86": "x86.lds",
"//build/bazel/platforms/arch:x86_64": "x86_64.lds",
"//conditions:default": None,
- }),
- srcs = ["base.cpp"],
-)`,
+ })`,
+ "srcs": `["base.cpp"]`,
+ }),
},
})
}
func TestCcObjectSelectOnLinuxAndBionicArchs(t *testing.T) {
runCcObjectTestCase(t, bp2buildTestCase{
- description: "cc_object setting srcs based on linux and bionic archs",
- moduleTypeUnderTest: "cc_object",
- moduleTypeUnderTestFactory: cc.ObjectFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ description: "cc_object setting srcs based on linux and bionic archs",
blueprint: `cc_object {
name: "foo",
srcs: ["base.cpp"],
@@ -434,10 +398,9 @@
}
`,
expectedBazelTargets: []string{
- `cc_object(
- name = "foo",
- copts = ["-fno-addrsig"],
- srcs = ["base.cpp"] + select({
+ makeBazelTarget("cc_object", "foo", attrNameToString{
+ "copts": `["-fno-addrsig"]`,
+ "srcs": `["base.cpp"] + select({
"//build/bazel/platforms/os_arch:android_arm64": [
"linux_arm64.cpp",
"bionic_arm64.cpp",
@@ -450,8 +413,8 @@
"//build/bazel/platforms/os_arch:linux_glibc_x86": ["linux_x86.cpp"],
"//build/bazel/platforms/os_arch:linux_musl_x86": ["linux_x86.cpp"],
"//conditions:default": [],
- }),
-)`,
+ })`,
+ }),
},
})
}
diff --git a/bp2build/cc_prebuilt_library_shared_test.go b/bp2build/cc_prebuilt_library_shared_test.go
index 97545c8..bac3908 100644
--- a/bp2build/cc_prebuilt_library_shared_test.go
+++ b/bp2build/cc_prebuilt_library_shared_test.go
@@ -23,10 +23,9 @@
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []string{
- `prebuilt_library_shared(
- name = "libtest",
- shared_library = "libf.so",
-)`,
+ makeBazelTarget("prebuilt_library_shared", "libtest", attrNameToString{
+ "shared_library": `"libf.so"`,
+ }),
},
})
}
@@ -52,14 +51,13 @@
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []string{
- `prebuilt_library_shared(
- name = "libtest",
- shared_library = select({
+ makeBazelTarget("prebuilt_library_shared", "libtest", attrNameToString{
+ "shared_library": `select({
"//build/bazel/platforms/arch:arm": "libg.so",
"//build/bazel/platforms/arch:arm64": "libf.so",
"//conditions:default": None,
- }),
-)`,
+ })`,
+ }),
},
})
}
diff --git a/bp2build/filegroup_conversion_test.go b/bp2build/filegroup_conversion_test.go
index ad99236..9f4add2 100644
--- a/bp2build/filegroup_conversion_test.go
+++ b/bp2build/filegroup_conversion_test.go
@@ -23,6 +23,9 @@
func runFilegroupTestCase(t *testing.T, tc bp2buildTestCase) {
t.Helper()
+ (&tc).moduleTypeUnderTest = "filegroup"
+ (&tc).moduleTypeUnderTestFactory = android.FileGroupFactory
+ (&tc).moduleTypeUnderTestBp2BuildMutator = android.FilegroupBp2Build
runBp2BuildTestCase(t, registerFilegroupModuleTypes, tc)
}
@@ -30,11 +33,8 @@
func TestFilegroupSameNameAsFile_OneFile(t *testing.T) {
runFilegroupTestCase(t, bp2buildTestCase{
- description: "filegroup - same name as file, with one file",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
- filesystem: map[string]string{},
+ description: "filegroup - same name as file, with one file",
+ filesystem: map[string]string{},
blueprint: `
filegroup {
name: "foo",
@@ -46,11 +46,8 @@
func TestFilegroupSameNameAsFile_MultipleFiles(t *testing.T) {
runFilegroupTestCase(t, bp2buildTestCase{
- description: "filegroup - same name as file, with multiple files",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
- filesystem: map[string]string{},
+ description: "filegroup - same name as file, with multiple files",
+ filesystem: map[string]string{},
blueprint: `
filegroup {
name: "foo",
diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go
index f3bc1ba..5976666 100644
--- a/bp2build/genrule_conversion_test.go
+++ b/bp2build/genrule_conversion_test.go
@@ -17,10 +17,21 @@
import (
"android/soong/android"
"android/soong/genrule"
- "strings"
"testing"
)
+func registerGenruleModuleTypes(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("genrule_defaults", func() android.Module { return genrule.DefaultsFactory() })
+}
+
+func runGenruleTestCase(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
+ (&tc).moduleTypeUnderTest = "genrule"
+ (&tc).moduleTypeUnderTestFactory = genrule.GenRuleFactory
+ (&tc).moduleTypeUnderTestBp2BuildMutator = genrule.GenruleBp2Build
+ runBp2BuildTestCase(t, registerGenruleModuleTypes, tc)
+}
+
func TestGenruleBp2Build(t *testing.T) {
otherGenruleBp := map[string]string{
"other/Android.bp": `genrule {
@@ -39,10 +50,7 @@
testCases := []bp2buildTestCase{
{
- description: "genrule with command line variable replacements",
- moduleTypeUnderTest: "genrule",
- moduleTypeUnderTestFactory: genrule.GenRuleFactory,
- moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ description: "genrule with command line variable replacements",
blueprint: `genrule {
name: "foo.tool",
out: ["foo_tool.out"],
@@ -60,26 +68,21 @@
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []string{
- `genrule(
- name = "foo",
- cmd = "$(location :foo.tool) --genDir=$(GENDIR) arg $(SRCS) $(OUTS)",
- outs = ["foo.out"],
- srcs = ["foo.in"],
- tools = [":foo.tool"],
-)`,
- `genrule(
- name = "foo.tool",
- cmd = "cp $(SRCS) $(OUTS)",
- outs = ["foo_tool.out"],
- srcs = ["foo_tool.in"],
-)`,
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"$(location :foo.tool) --genDir=$(GENDIR) arg $(SRCS) $(OUTS)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ "tools": `[":foo.tool"]`,
+ }),
+ makeBazelTarget("genrule", "foo.tool", attrNameToString{
+ "cmd": `"cp $(SRCS) $(OUTS)"`,
+ "outs": `["foo_tool.out"]`,
+ "srcs": `["foo_tool.in"]`,
+ }),
},
},
{
- description: "genrule using $(locations :label)",
- moduleTypeUnderTest: "genrule",
- moduleTypeUnderTestFactory: genrule.GenRuleFactory,
- moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ description: "genrule using $(locations :label)",
blueprint: `genrule {
name: "foo.tools",
out: ["foo_tool.out", "foo_tool2.out"],
@@ -96,29 +99,25 @@
cmd: "$(locations :foo.tools) -s $(out) $(in)",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`genrule(
- name = "foo",
- cmd = "$(locations :foo.tools) -s $(OUTS) $(SRCS)",
- outs = ["foo.out"],
- srcs = ["foo.in"],
- tools = [":foo.tools"],
-)`,
- `genrule(
- name = "foo.tools",
- cmd = "cp $(SRCS) $(OUTS)",
- outs = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"$(locations :foo.tools) -s $(OUTS) $(SRCS)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ "tools": `[":foo.tools"]`,
+ }),
+ makeBazelTarget("genrule", "foo.tools", attrNameToString{
+ "cmd": `"cp $(SRCS) $(OUTS)"`,
+ "outs": `[
"foo_tool.out",
"foo_tool2.out",
- ],
- srcs = ["foo_tool.in"],
-)`,
+ ]`,
+ "srcs": `["foo_tool.in"]`,
+ }),
},
},
{
- description: "genrule using $(locations //absolute:label)",
- moduleTypeUnderTest: "genrule",
- moduleTypeUnderTestFactory: genrule.GenRuleFactory,
- moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ description: "genrule using $(locations //absolute:label)",
blueprint: `genrule {
name: "foo",
out: ["foo.out"],
@@ -127,21 +126,18 @@
cmd: "$(locations :foo.tool) -s $(out) $(in)",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`genrule(
- name = "foo",
- cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
- outs = ["foo.out"],
- srcs = ["foo.in"],
- tools = ["//other:foo.tool"],
-)`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ "tools": `["//other:foo.tool"]`,
+ }),
},
filesystem: otherGenruleBp,
},
{
- description: "genrule srcs using $(locations //absolute:label)",
- moduleTypeUnderTest: "genrule",
- moduleTypeUnderTestFactory: genrule.GenRuleFactory,
- moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ description: "genrule srcs using $(locations //absolute:label)",
blueprint: `genrule {
name: "foo",
out: ["foo.out"],
@@ -150,21 +146,18 @@
cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`genrule(
- name = "foo",
- cmd = "$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)",
- outs = ["foo.out"],
- srcs = ["//other:other.tool"],
- tools = ["//other:foo.tool"],
-)`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["//other:other.tool"]`,
+ "tools": `["//other:foo.tool"]`,
+ }),
},
filesystem: otherGenruleBp,
},
{
- description: "genrule using $(location) label should substitute first tool label automatically",
- moduleTypeUnderTest: "genrule",
- moduleTypeUnderTestFactory: genrule.GenRuleFactory,
- moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ description: "genrule using $(location) label should substitute first tool label automatically",
blueprint: `genrule {
name: "foo",
out: ["foo.out"],
@@ -173,24 +166,21 @@
cmd: "$(location) -s $(out) $(in)",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`genrule(
- name = "foo",
- cmd = "$(location //other:foo.tool) -s $(OUTS) $(SRCS)",
- outs = ["foo.out"],
- srcs = ["foo.in"],
- tools = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"$(location //other:foo.tool) -s $(OUTS) $(SRCS)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ "tools": `[
"//other:foo.tool",
"//other:other.tool",
- ],
-)`,
+ ]`,
+ }),
},
filesystem: otherGenruleBp,
},
{
- description: "genrule using $(locations) label should substitute first tool label automatically",
- moduleTypeUnderTest: "genrule",
- moduleTypeUnderTestFactory: genrule.GenRuleFactory,
- moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ description: "genrule using $(locations) label should substitute first tool label automatically",
blueprint: `genrule {
name: "foo",
out: ["foo.out"],
@@ -199,24 +189,21 @@
cmd: "$(locations) -s $(out) $(in)",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`genrule(
- name = "foo",
- cmd = "$(locations //other:foo.tool) -s $(OUTS) $(SRCS)",
- outs = ["foo.out"],
- srcs = ["foo.in"],
- tools = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ "tools": `[
"//other:foo.tool",
"//other:other.tool",
- ],
-)`,
+ ]`,
+ }),
},
filesystem: otherGenruleBp,
},
{
- description: "genrule without tools or tool_files can convert successfully",
- moduleTypeUnderTest: "genrule",
- moduleTypeUnderTestFactory: genrule.GenRuleFactory,
- moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ description: "genrule without tools or tool_files can convert successfully",
blueprint: `genrule {
name: "foo",
out: ["foo.out"],
@@ -224,85 +211,28 @@
cmd: "cp $(in) $(out)",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`genrule(
- name = "foo",
- cmd = "cp $(SRCS) $(OUTS)",
- outs = ["foo.out"],
- srcs = ["foo.in"],
-)`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"cp $(SRCS) $(OUTS)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ }),
},
},
}
- dir := "."
for _, testCase := range testCases {
- fs := make(map[string][]byte)
- toParse := []string{
- "Android.bp",
- }
- for f, content := range testCase.filesystem {
- if strings.HasSuffix(f, "Android.bp") {
- toParse = append(toParse, f)
- }
- fs[f] = []byte(content)
- }
- config := android.TestConfig(buildDir, nil, testCase.blueprint, fs)
- ctx := android.NewTestContext(config)
- ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
- ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
- ctx.RegisterForBazelConversion()
-
- _, errs := ctx.ParseFileList(dir, toParse)
- if errored(t, testCase, errs) {
- continue
- }
- _, errs = ctx.ResolveDependencies(config)
- if errored(t, testCase, errs) {
- continue
- }
-
- checkDir := dir
- if testCase.dir != "" {
- checkDir = testCase.dir
- }
-
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
- bazelTargets, err := generateBazelTargetsForDir(codegenCtx, checkDir)
- android.FailIfErrored(t, err)
- if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
- t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
- } else {
- for i, target := range bazelTargets {
- if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
- t.Errorf(
- "%s: Expected generated Bazel target to be '%s', got '%s'",
- testCase.description,
- w,
- g,
- )
- }
- }
- }
+ t.Run(testCase.description, func(t *testing.T) {
+ runGenruleTestCase(t, testCase)
+ })
}
}
func TestBp2BuildInlinesDefaults(t *testing.T) {
- testCases := []struct {
- moduleTypesUnderTest map[string]android.ModuleFactory
- bp2buildMutatorsUnderTest map[string]bp2buildMutator
- bp string
- expectedBazelTarget string
- description string
- }{
+ testCases := []bp2buildTestCase{
{
- moduleTypesUnderTest: map[string]android.ModuleFactory{
- "genrule": genrule.GenRuleFactory,
- "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
- },
- bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
- "genrule": genrule.GenruleBp2Build,
- },
- bp: `genrule_defaults {
+ description: "genrule applies properties from a genrule_defaults dependency if not specified",
+ blueprint: `genrule_defaults {
name: "gen_defaults",
cmd: "do-something $(in) $(out)",
}
@@ -314,23 +244,17 @@
bazel_module: { bp2build_available: true },
}
`,
- expectedBazelTarget: `genrule(
- name = "gen",
- cmd = "do-something $(SRCS) $(OUTS)",
- outs = ["out"],
- srcs = ["in1"],
-)`,
- description: "genrule applies properties from a genrule_defaults dependency if not specified",
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "gen", attrNameToString{
+ "cmd": `"do-something $(SRCS) $(OUTS)"`,
+ "outs": `["out"]`,
+ "srcs": `["in1"]`,
+ }),
+ },
},
{
- moduleTypesUnderTest: map[string]android.ModuleFactory{
- "genrule": genrule.GenRuleFactory,
- "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
- },
- bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
- "genrule": genrule.GenruleBp2Build,
- },
- bp: `genrule_defaults {
+ description: "genrule does merges properties from a genrule_defaults dependency, latest-first",
+ blueprint: `genrule_defaults {
name: "gen_defaults",
out: ["out-from-defaults"],
srcs: ["in-from-defaults"],
@@ -345,29 +269,23 @@
bazel_module: { bp2build_available: true },
}
`,
- expectedBazelTarget: `genrule(
- name = "gen",
- cmd = "do-something $(SRCS) $(OUTS)",
- outs = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "gen", attrNameToString{
+ "cmd": `"do-something $(SRCS) $(OUTS)"`,
+ "outs": `[
"out-from-defaults",
"out",
- ],
- srcs = [
+ ]`,
+ "srcs": `[
"in-from-defaults",
"in1",
- ],
-)`,
- description: "genrule does merges properties from a genrule_defaults dependency, latest-first",
+ ]`,
+ }),
+ },
},
{
- moduleTypesUnderTest: map[string]android.ModuleFactory{
- "genrule": genrule.GenRuleFactory,
- "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
- },
- bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
- "genrule": genrule.GenruleBp2Build,
- },
- bp: `genrule_defaults {
+ description: "genrule applies properties from list of genrule_defaults",
+ blueprint: `genrule_defaults {
name: "gen_defaults1",
cmd: "cp $(in) $(out)",
}
@@ -384,23 +302,17 @@
bazel_module: { bp2build_available: true },
}
`,
- expectedBazelTarget: `genrule(
- name = "gen",
- cmd = "cp $(SRCS) $(OUTS)",
- outs = ["out"],
- srcs = ["in1"],
-)`,
- description: "genrule applies properties from list of genrule_defaults",
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "gen", attrNameToString{
+ "cmd": `"cp $(SRCS) $(OUTS)"`,
+ "outs": `["out"]`,
+ "srcs": `["in1"]`,
+ }),
+ },
},
{
- moduleTypesUnderTest: map[string]android.ModuleFactory{
- "genrule": genrule.GenRuleFactory,
- "genrule_defaults": func() android.Module { return genrule.DefaultsFactory() },
- },
- bp2buildMutatorsUnderTest: map[string]bp2buildMutator{
- "genrule": genrule.GenruleBp2Build,
- },
- bp: `genrule_defaults {
+ description: "genrule applies properties from genrule_defaults transitively",
+ blueprint: `genrule_defaults {
name: "gen_defaults1",
defaults: ["gen_defaults2"],
cmd: "cmd1 $(in) $(out)", // overrides gen_defaults2's cmd property value.
@@ -427,55 +339,26 @@
bazel_module: { bp2build_available: true },
}
`,
- expectedBazelTarget: `genrule(
- name = "gen",
- cmd = "cmd1 $(SRCS) $(OUTS)",
- outs = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("genrule", "gen", attrNameToString{
+ "cmd": `"cmd1 $(SRCS) $(OUTS)"`,
+ "outs": `[
"out-from-3",
"out-from-2",
"out",
- ],
- srcs = [
+ ]`,
+ "srcs": `[
"srcs-from-3",
"in1",
- ],
-)`,
- description: "genrule applies properties from genrule_defaults transitively",
+ ]`,
+ }),
+ },
},
}
- dir := "."
for _, testCase := range testCases {
- config := android.TestConfig(buildDir, nil, testCase.bp, nil)
- ctx := android.NewTestContext(config)
- for m, factory := range testCase.moduleTypesUnderTest {
- ctx.RegisterModuleType(m, factory)
- }
- for mutator, f := range testCase.bp2buildMutatorsUnderTest {
- ctx.RegisterBp2BuildMutator(mutator, f)
- }
- ctx.RegisterForBazelConversion()
-
- _, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.ResolveDependencies(config)
- android.FailIfErrored(t, errs)
-
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
- bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
- android.FailIfErrored(t, err)
- if actualCount := len(bazelTargets); actualCount != 1 {
- t.Fatalf("%s: Expected 1 bazel target, got %d", testCase.description, actualCount)
- }
-
- actualBazelTarget := bazelTargets[0]
- if actualBazelTarget.content != testCase.expectedBazelTarget {
- t.Errorf(
- "%s: Expected generated Bazel target to be '%s', got '%s'",
- testCase.description,
- testCase.expectedBazelTarget,
- actualBazelTarget.content,
- )
- }
+ t.Run(testCase.description, func(t *testing.T) {
+ runGenruleTestCase(t, testCase)
+ })
}
}
diff --git a/bp2build/prebuilt_etc_conversion_test.go b/bp2build/prebuilt_etc_conversion_test.go
index 62e407b..1189309 100644
--- a/bp2build/prebuilt_etc_conversion_test.go
+++ b/bp2build/prebuilt_etc_conversion_test.go
@@ -23,6 +23,9 @@
func runPrebuiltEtcTestCase(t *testing.T, tc bp2buildTestCase) {
t.Helper()
+ (&tc).moduleTypeUnderTest = "prebuilt_etc"
+ (&tc).moduleTypeUnderTestFactory = etc.PrebuiltEtcFactory
+ (&tc).moduleTypeUnderTestBp2BuildMutator = etc.PrebuiltEtcBp2Build
runBp2BuildTestCase(t, registerPrebuiltEtcModuleTypes, tc)
}
@@ -31,11 +34,8 @@
func TestPrebuiltEtcSimple(t *testing.T) {
runPrebuiltEtcTestCase(t, bp2buildTestCase{
- description: "prebuilt_etc - simple example",
- moduleTypeUnderTest: "prebuilt_etc",
- moduleTypeUnderTestFactory: etc.PrebuiltEtcFactory,
- moduleTypeUnderTestBp2BuildMutator: etc.PrebuiltEtcBp2Build,
- filesystem: map[string]string{},
+ description: "prebuilt_etc - simple example",
+ filesystem: map[string]string{},
blueprint: `
prebuilt_etc {
name: "apex_tz_version",
@@ -45,22 +45,19 @@
installable: false,
}
`,
- expectedBazelTargets: []string{`prebuilt_etc(
- name = "apex_tz_version",
- filename = "tz_version",
- installable = False,
- src = "version/tz_version",
- sub_dir = "tz",
-)`}})
+ expectedBazelTargets: []string{
+ makeBazelTarget("prebuilt_etc", "apex_tz_version", attrNameToString{
+ "filename": `"tz_version"`,
+ "installable": `False`,
+ "src": `"version/tz_version"`,
+ "sub_dir": `"tz"`,
+ })}})
}
func TestPrebuiltEtcArchVariant(t *testing.T) {
runPrebuiltEtcTestCase(t, bp2buildTestCase{
- description: "prebuilt_etc - simple example",
- moduleTypeUnderTest: "prebuilt_etc",
- moduleTypeUnderTestFactory: etc.PrebuiltEtcFactory,
- moduleTypeUnderTestBp2BuildMutator: etc.PrebuiltEtcBp2Build,
- filesystem: map[string]string{},
+ description: "prebuilt_etc - arch variant",
+ filesystem: map[string]string{},
blueprint: `
prebuilt_etc {
name: "apex_tz_version",
@@ -78,15 +75,15 @@
}
}
`,
- expectedBazelTargets: []string{`prebuilt_etc(
- name = "apex_tz_version",
- filename = "tz_version",
- installable = False,
- src = select({
+ expectedBazelTargets: []string{
+ makeBazelTarget("prebuilt_etc", "apex_tz_version", attrNameToString{
+ "filename": `"tz_version"`,
+ "installable": `False`,
+ "src": `select({
"//build/bazel/platforms/arch:arm": "arm",
"//build/bazel/platforms/arch:arm64": "arm64",
"//conditions:default": "version/tz_version",
- }),
- sub_dir = "tz",
-)`}})
+ })`,
+ "sub_dir": `"tz"`,
+ })}})
}
diff --git a/bp2build/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go
index 5b4829e..01b6aa2 100644
--- a/bp2build/python_binary_conversion_test.go
+++ b/bp2build/python_binary_conversion_test.go
@@ -7,7 +7,8 @@
"android/soong/python"
)
-func runBp2BuildTestCaseWithLibs(t *testing.T, tc bp2buildTestCase) {
+func runBp2BuildTestCaseWithPythonLibraries(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("python_library", python.PythonLibraryFactory)
ctx.RegisterModuleType("python_library_host", python.PythonLibraryHostFactory)
@@ -15,7 +16,7 @@
}
func TestPythonBinaryHostSimple(t *testing.T) {
- runBp2BuildTestCaseWithLibs(t, bp2buildTestCase{
+ runBp2BuildTestCaseWithPythonLibraries(t, bp2buildTestCase{
description: "simple python_binary_host converts to a native py_binary",
moduleTypeUnderTest: "python_binary_host",
moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
@@ -41,17 +42,17 @@
srcs: ["b/e.py"],
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`py_binary(
- name = "foo",
- data = ["files/data.txt"],
- deps = [":bar"],
- main = "a.py",
- srcs = [
+ expectedBazelTargets: []string{
+ makeBazelTarget("py_binary", "foo", attrNameToString{
+ "data": `["files/data.txt"]`,
+ "deps": `[":bar"]`,
+ "main": `"a.py"`,
+ "srcs": `[
"a.py",
"b/c.py",
"b/d.py",
- ],
-)`,
+ ]`,
+ }),
},
})
}
@@ -77,11 +78,11 @@
bazel_module: { bp2build_available: true },
}
`,
- expectedBazelTargets: []string{`py_binary(
- name = "foo",
- python_version = "PY2",
- srcs = ["a.py"],
-)`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("py_binary", "foo", attrNameToString{
+ "python_version": `"PY2"`,
+ "srcs": `["a.py"]`,
+ }),
},
})
}
@@ -109,10 +110,9 @@
`,
expectedBazelTargets: []string{
// python_version is PY3 by default.
- `py_binary(
- name = "foo",
- srcs = ["a.py"],
-)`,
+ makeBazelTarget("py_binary", "foo", attrNameToString{
+ "srcs": `["a.py"]`,
+ }),
},
})
}
@@ -139,14 +139,13 @@
},
}`,
expectedBazelTargets: []string{
- `py_binary(
- name = "foo-arm",
- srcs = select({
+ makeBazelTarget("py_binary", "foo-arm", attrNameToString{
+ "srcs": `select({
"//build/bazel/platforms/arch:arm": ["arm.py"],
"//build/bazel/platforms/arch:x86": ["x86.py"],
"//conditions:default": [],
- }),
-)`,
+ })`,
+ }),
},
})
}
diff --git a/bp2build/python_library_conversion_test.go b/bp2build/python_library_conversion_test.go
index 7f983ad..e334592 100644
--- a/bp2build/python_library_conversion_test.go
+++ b/bp2build/python_library_conversion_test.go
@@ -11,38 +11,49 @@
// TODO(alexmarquez): Should be lifted into a generic Bp2Build file
type PythonLibBp2Build func(ctx android.TopDownMutatorContext)
-func TestPythonLibrary(t *testing.T) {
- testPythonLib(t, "python_library",
- python.PythonLibraryFactory, python.PythonLibraryBp2Build,
- func(ctx android.RegistrationContext) {})
-}
-
-func TestPythonLibraryHost(t *testing.T) {
- testPythonLib(t, "python_library_host",
- python.PythonLibraryHostFactory, python.PythonLibraryHostBp2Build,
- func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("python_library", python.PythonLibraryFactory)
- })
-}
-
-func testPythonLib(t *testing.T, modType string,
- factory android.ModuleFactory, mutator PythonLibBp2Build,
- registration func(ctx android.RegistrationContext)) {
+func runPythonLibraryTestCase(t *testing.T, tc bp2buildTestCase) {
t.Helper()
- // Simple
- runBp2BuildTestCase(t, registration, bp2buildTestCase{
- description: fmt.Sprintf("simple %s converts to a native py_library", modType),
- moduleTypeUnderTest: modType,
- moduleTypeUnderTestFactory: factory,
- moduleTypeUnderTestBp2BuildMutator: mutator,
- filesystem: map[string]string{
- "a.py": "",
- "b/c.py": "",
- "b/d.py": "",
- "b/e.py": "",
- "files/data.txt": "",
- },
- blueprint: fmt.Sprintf(`%s {
+ testCase := tc
+ testCase.description = fmt.Sprintf(testCase.description, "python_library")
+ testCase.blueprint = fmt.Sprintf(testCase.blueprint, "python_library")
+ testCase.moduleTypeUnderTest = "python_library"
+ testCase.moduleTypeUnderTestFactory = python.PythonLibraryFactory
+ testCase.moduleTypeUnderTestBp2BuildMutator = python.PythonLibraryBp2Build
+ runBp2BuildTestCaseSimple(t, testCase)
+}
+
+func runPythonLibraryHostTestCase(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
+ testCase := tc
+ testCase.description = fmt.Sprintf(testCase.description, "python_library_host")
+ testCase.blueprint = fmt.Sprintf(testCase.blueprint, "python_library_host")
+ testCase.moduleTypeUnderTest = "python_library_host"
+ testCase.moduleTypeUnderTestFactory = python.PythonLibraryHostFactory
+ testCase.moduleTypeUnderTestBp2BuildMutator = python.PythonLibraryHostBp2Build
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("python_library", python.PythonLibraryFactory)
+ },
+ testCase)
+}
+
+func runPythonLibraryTestCases(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
+ runPythonLibraryTestCase(t, tc)
+ runPythonLibraryHostTestCase(t, tc)
+}
+
+func TestSimplePythonLib(t *testing.T) {
+ testCases := []bp2buildTestCase{
+ {
+ description: "simple %s converts to a native py_library",
+ filesystem: map[string]string{
+ "a.py": "",
+ "b/c.py": "",
+ "b/d.py": "",
+ "b/e.py": "",
+ "files/data.txt": "",
+ },
+ blueprint: `%s {
name: "foo",
srcs: ["**/*.py"],
exclude_srcs: ["b/e.py"],
@@ -54,28 +65,23 @@
name: "bar",
srcs: ["b/e.py"],
bazel_module: { bp2build_available: false },
- }`, modType),
- expectedBazelTargets: []string{`py_library(
- name = "foo",
- data = ["files/data.txt"],
- deps = [":bar"],
- srcs = [
+ }`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("py_library", "foo", attrNameToString{
+ "data": `["files/data.txt"]`,
+ "deps": `[":bar"]`,
+ "srcs": `[
"a.py",
"b/c.py",
"b/d.py",
- ],
- srcs_version = "PY3",
-)`,
+ ]`,
+ "srcs_version": `"PY3"`,
+ }),
+ },
},
- })
-
- // PY2
- runBp2BuildTestCaseSimple(t, bp2buildTestCase{
- description: fmt.Sprintf("py2 %s converts to a native py_library", modType),
- moduleTypeUnderTest: modType,
- moduleTypeUnderTestFactory: factory,
- moduleTypeUnderTestBp2BuildMutator: mutator,
- blueprint: fmt.Sprintf(`%s {
+ {
+ description: "py2 %s converts to a native py_library",
+ blueprint: `%s {
name: "foo",
srcs: ["a.py"],
version: {
@@ -88,22 +94,17 @@
},
bazel_module: { bp2build_available: true },
-}`, modType),
- expectedBazelTargets: []string{`py_library(
- name = "foo",
- srcs = ["a.py"],
- srcs_version = "PY2",
-)`,
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("py_library", "foo", attrNameToString{
+ "srcs": `["a.py"]`,
+ "srcs_version": `"PY2"`,
+ }),
+ },
},
- })
-
- // PY3
- runBp2BuildTestCaseSimple(t, bp2buildTestCase{
- description: fmt.Sprintf("py3 %s converts to a native py_library", modType),
- moduleTypeUnderTest: modType,
- moduleTypeUnderTestFactory: factory,
- moduleTypeUnderTestBp2BuildMutator: mutator,
- blueprint: fmt.Sprintf(`%s {
+ {
+ description: "py3 %s converts to a native py_library",
+ blueprint: `%s {
name: "foo",
srcs: ["a.py"],
version: {
@@ -116,22 +117,17 @@
},
bazel_module: { bp2build_available: true },
-}`, modType),
- expectedBazelTargets: []string{`py_library(
- name = "foo",
- srcs = ["a.py"],
- srcs_version = "PY3",
-)`,
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("py_library", "foo", attrNameToString{
+ "srcs": `["a.py"]`,
+ "srcs_version": `"PY3"`,
+ }),
+ },
},
- })
-
- // Both
- runBp2BuildTestCaseSimple(t, bp2buildTestCase{
- description: fmt.Sprintf("py2&3 %s converts to a native py_library", modType),
- moduleTypeUnderTest: modType,
- moduleTypeUnderTestFactory: factory,
- moduleTypeUnderTestBp2BuildMutator: mutator,
- blueprint: fmt.Sprintf(`%s {
+ {
+ description: "py2&3 %s converts to a native py_library",
+ blueprint: `%s {
name: "foo",
srcs: ["a.py"],
version: {
@@ -144,44 +140,31 @@
},
bazel_module: { bp2build_available: true },
-}`, modType),
- expectedBazelTargets: []string{
- // srcs_version is PY2ANDPY3 by default.
- `py_library(
- name = "foo",
- srcs = ["a.py"],
-)`,
+}`,
+ expectedBazelTargets: []string{
+ // srcs_version is PY2ANDPY3 by default.
+ makeBazelTarget("py_library", "foo", attrNameToString{
+ "srcs": `["a.py"]`,
+ }),
+ },
},
- })
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.description, func(t *testing.T) {
+ runPythonLibraryTestCases(t, tc)
+ })
+ }
}
-func TestPythonLibraryArchVariance(t *testing.T) {
- testPythonArchVariance(t, "python_library", "py_library",
- python.PythonLibraryFactory, python.PythonLibraryBp2Build,
- func(ctx android.RegistrationContext) {})
-}
-
-func TestPythonLibraryHostArchVariance(t *testing.T) {
- testPythonArchVariance(t, "python_library_host", "py_library",
- python.PythonLibraryHostFactory, python.PythonLibraryHostBp2Build,
- func(ctx android.RegistrationContext) {})
-}
-
-// TODO: refactor python_binary_conversion_test to use this
-func testPythonArchVariance(t *testing.T, modType, bazelTarget string,
- factory android.ModuleFactory, mutator PythonLibBp2Build,
- registration func(ctx android.RegistrationContext)) {
- t.Helper()
- runBp2BuildTestCase(t, registration, bp2buildTestCase{
- description: fmt.Sprintf("test %s arch variants", modType),
- moduleTypeUnderTest: modType,
- moduleTypeUnderTestFactory: factory,
- moduleTypeUnderTestBp2BuildMutator: mutator,
+func TestPythonArchVariance(t *testing.T) {
+ runPythonLibraryTestCases(t, bp2buildTestCase{
+ description: "test %s arch variants",
filesystem: map[string]string{
"dir/arm.py": "",
"dir/x86.py": "",
},
- blueprint: fmt.Sprintf(`%s {
+ blueprint: `%s {
name: "foo",
arch: {
arm: {
@@ -191,17 +174,16 @@
srcs: ["x86.py"],
},
},
- }`, modType),
+ }`,
expectedBazelTargets: []string{
- fmt.Sprintf(`%s(
- name = "foo",
- srcs = select({
+ makeBazelTarget("py_library", "foo", attrNameToString{
+ "srcs": `select({
"//build/bazel/platforms/arch:arm": ["arm.py"],
"//build/bazel/platforms/arch:x86": ["x86.py"],
"//conditions:default": [],
- }),
- srcs_version = "PY3",
-)`, bazelTarget),
+ })`,
+ "srcs_version": `"PY3"`,
+ }),
},
})
}
diff --git a/bp2build/sh_conversion_test.go b/bp2build/sh_conversion_test.go
index 82e0a14..1ca4a0e 100644
--- a/bp2build/sh_conversion_test.go
+++ b/bp2build/sh_conversion_test.go
@@ -64,9 +64,9 @@
src: "foo.sh",
bazel_module: { bp2build_available: true },
}`,
- expectedBazelTargets: []string{`sh_binary(
- name = "foo",
- srcs = ["foo.sh"],
-)`},
+ expectedBazelTargets: []string{
+ makeBazelTarget("sh_binary", "foo", attrNameToString{
+ "srcs": `["foo.sh"]`,
+ })},
})
}
diff --git a/bp2build/soong_config_module_type_conversion_test.go b/bp2build/soong_config_module_type_conversion_test.go
index 4118479..2e6f54c 100644
--- a/bp2build/soong_config_module_type_conversion_test.go
+++ b/bp2build/soong_config_module_type_conversion_test.go
@@ -68,7 +68,7 @@
expectedBazelTargets: []string{`cc_library_static(
name = "foo",
copts = select({
- "//build/bazel/product_variables:acme__feature1": ["-DFEATURE1"],
+ "//build/bazel/product_variables:acme__feature1__enabled": ["-DFEATURE1"],
"//conditions:default": ["-DDEFAULT1"],
}),
local_includes = ["."],
@@ -118,7 +118,7 @@
expectedBazelTargets: []string{`cc_library_static(
name = "foo",
copts = select({
- "//build/bazel/product_variables:acme__feature1": ["-DFEATURE1"],
+ "//build/bazel/product_variables:acme__feature1__enabled": ["-DFEATURE1"],
"//conditions:default": ["-DDEFAULT1"],
}),
local_includes = ["."],
@@ -246,12 +246,81 @@
"//build/bazel/product_variables:acme__board__soc_b": ["-DSOC_B"],
"//conditions:default": ["-DSOC_DEFAULT"],
}) + select({
- "//build/bazel/product_variables:acme__feature1": ["-DFEATURE1"],
+ "//build/bazel/product_variables:acme__feature1__enabled": ["-DFEATURE1"],
"//conditions:default": ["-DDEFAULT1"],
}) + select({
- "//build/bazel/product_variables:acme__feature2": ["-DFEATURE2"],
+ "//build/bazel/product_variables:acme__feature2__enabled": ["-DFEATURE2"],
"//conditions:default": ["-DDEFAULT2"],
}),
local_includes = ["."],
)`}})
}
+
+func TestSoongConfigModuleType_StringVar_LabelListDeps(t *testing.T) {
+ bp := `
+soong_config_string_variable {
+ name: "board",
+ values: ["soc_a", "soc_b", "soc_c"],
+}
+
+soong_config_module_type {
+ name: "custom_cc_library_static",
+ module_type: "cc_library_static",
+ config_namespace: "acme",
+ variables: ["board"],
+ properties: ["cflags", "static_libs"],
+ bazel_module: { bp2build_available: true },
+}
+
+custom_cc_library_static {
+ name: "foo",
+ bazel_module: { bp2build_available: true },
+ soong_config_variables: {
+ board: {
+ soc_a: {
+ cflags: ["-DSOC_A"],
+ static_libs: ["soc_a_dep"],
+ },
+ soc_b: {
+ cflags: ["-DSOC_B"],
+ static_libs: ["soc_b_dep"],
+ },
+ soc_c: {},
+ conditions_default: {
+ cflags: ["-DSOC_DEFAULT"],
+ static_libs: ["soc_default_static_dep"],
+ },
+ },
+ },
+}`
+
+ otherDeps := `
+cc_library_static { name: "soc_a_dep", bazel_module: { bp2build_available: false } }
+cc_library_static { name: "soc_b_dep", bazel_module: { bp2build_available: false } }
+cc_library_static { name: "soc_default_static_dep", bazel_module: { bp2build_available: false } }
+`
+
+ runSoongConfigModuleTypeTest(t, bp2buildTestCase{
+ description: "soong config variables - generates selects for label list attributes",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ blueprint: bp,
+ filesystem: map[string]string{
+ "foo/bar/Android.bp": otherDeps,
+ },
+ expectedBazelTargets: []string{`cc_library_static(
+ name = "foo",
+ copts = select({
+ "//build/bazel/product_variables:acme__board__soc_a": ["-DSOC_A"],
+ "//build/bazel/product_variables:acme__board__soc_b": ["-DSOC_B"],
+ "//conditions:default": ["-DSOC_DEFAULT"],
+ }),
+ implementation_deps = select({
+ "//build/bazel/product_variables:acme__board__soc_a": ["//foo/bar:soc_a_dep"],
+ "//build/bazel/product_variables:acme__board__soc_b": ["//foo/bar:soc_b_dep"],
+ "//conditions:default": ["//foo/bar:soc_default_static_dep"],
+ }),
+ local_includes = ["."],
+)`}})
+}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 7c2f43a..daa9c22 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -364,3 +364,16 @@
bazel_module: { bp2build_available: false },
}`, typ, name)
}
+
+type attrNameToString map[string]string
+
+func makeBazelTarget(typ, name string, attrs attrNameToString) string {
+ attrStrings := make([]string, 0, len(attrs)+1)
+ attrStrings = append(attrStrings, fmt.Sprintf(` name = "%s",`, name))
+ for _, k := range android.SortedStringKeys(attrs) {
+ attrStrings = append(attrStrings, fmt.Sprintf(" %s = %s,", k, attrs[k]))
+ }
+ return fmt.Sprintf(`%s(
+%s
+)`, typ, strings.Join(attrStrings, "\n"))
+}
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index a608630..e1140b8 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -19,9 +19,13 @@
import (
"bytes"
"errors"
+ "flag"
"fmt"
"io"
+ "os"
"path/filepath"
+ "reflect"
+ "sort"
"strings"
"github.com/google/blueprint/parser"
@@ -137,11 +141,35 @@
Fix: runPatchListMod(removeObsoleteProperty("sanitize.scudo")),
},
{
+ Name: "removeAndroidLicenseKinds",
+ Fix: runPatchListMod(removeIncorrectProperties("android_license_kinds")),
+ },
+ {
+ Name: "removeAndroidLicenseConditions",
+ Fix: runPatchListMod(removeIncorrectProperties("android_license_conditions")),
+ },
+ {
+ Name: "removeAndroidLicenseFiles",
+ Fix: runPatchListMod(removeIncorrectProperties("android_license_files")),
+ },
+ {
Name: "formatFlagProperties",
Fix: runPatchListMod(formatFlagProperties),
},
}
+// for fix that only need to run once
+var fixStepsOnce = []FixStep{
+ {
+ Name: "haveSameLicense",
+ Fix: haveSameLicense,
+ },
+ {
+ Name: "rewriteLicenseProperties",
+ Fix: runPatchListMod(rewriteLicenseProperties),
+ },
+}
+
func NewFixRequest() FixRequest {
return FixRequest{}
}
@@ -196,6 +224,16 @@
return nil, err
}
+ // run fix that is expected to run once first
+ configOnce := NewFixRequest()
+ configOnce.steps = append(configOnce.steps, fixStepsOnce...)
+ if len(configOnce.steps) > 0 {
+ err = f.fixTreeOnce(configOnce)
+ if err != nil {
+ return nil, err
+ }
+ }
+
maxNumIterations := 20
i := 0
for {
@@ -1413,3 +1451,304 @@
}
return nil
}
+
+// rewrite the "android_license_kinds" and "android_license_files" properties to a package module
+// (and a license module when needed).
+func rewriteLicenseProperties(mod *parser.Module, buf []byte, patchList *parser.PatchList) error {
+ // if a package module has been added, no more action is needed.
+ for _, patch := range *patchList {
+ if strings.Contains(patch.Replacement, "package {") {
+ return nil
+ }
+ }
+
+ licenseKindsPropertyName := "android_license_kinds"
+ licenseFilesPropertyName := "android_license_files"
+
+ androidBpFileErr := "// Error: No Android.bp file is found at\n" +
+ "// %s\n" +
+ "// Please add one there with the needed license module first.\n"
+ licenseModuleErr := "// Error: Cannot get the name of the license module in the\n" +
+ "// %s file.\n" +
+ "// If no such license module exists, please add one there first.\n"
+
+ defaultApplicableLicense := "Android-Apache-2.0"
+ var licenseModuleName, licensePatch string
+ var hasFileInParentDir bool
+
+ // when LOCAL_NOTICE_FILE is not empty
+ if hasNonEmptyLiteralListProperty(mod, licenseFilesPropertyName) {
+ hasFileInParentDir = hasValueStartWithTwoDotsLiteralList(mod, licenseFilesPropertyName)
+ // if have LOCAL_NOTICE_FILE outside the current directory, need to find and refer to the license
+ // module in the LOCAL_NOTICE_FILE location directly and no new license module needs to be created
+ if hasFileInParentDir {
+ bpPath, ok := getPathFromProperty(mod, licenseFilesPropertyName)
+ if !ok {
+ bpDir, err := getDirFromProperty(mod, licenseFilesPropertyName)
+ if err != nil {
+ return err
+ }
+ licensePatch += fmt.Sprintf(androidBpFileErr, bpDir)
+ } else {
+ licenseModuleName, _ = getModuleName(bpPath, "license")
+ if len(licenseModuleName) == 0 {
+ licensePatch += fmt.Sprintf(licenseModuleErr, bpPath)
+ }
+ defaultApplicableLicense = licenseModuleName
+ }
+ } else {
+ // if have LOCAL_NOTICE_FILE in the current directory, need to create a new license module
+ relativePath := getModuleRelativePath()
+ if len(relativePath) == 0 {
+ return fmt.Errorf("Cannot obtain the relative path of the Android.mk file")
+ }
+ licenseModuleName = strings.Replace(relativePath, "/", "_", -1) + "_license"
+ defaultApplicableLicense = licenseModuleName
+ }
+ }
+
+ //add the package module
+ if hasNonEmptyLiteralListProperty(mod, licenseKindsPropertyName) {
+ licensePatch += "package {\n" +
+ " // See: http://go/android-license-faq\n" +
+ " default_applicable_licenses: [\n" +
+ " \"" + defaultApplicableLicense + "\",\n" +
+ " ],\n" +
+ "}\n" +
+ "\n"
+ }
+
+ // append the license module when necessary
+ // when LOCAL_NOTICE_FILE is not empty and in the current directory, create a new license module
+ // otherwise, use the above default license directly
+ if hasNonEmptyLiteralListProperty(mod, licenseFilesPropertyName) && !hasFileInParentDir {
+ licenseKinds, err := mergeLiteralListPropertyValue(mod, licenseKindsPropertyName)
+ if err != nil {
+ return err
+ }
+ licenseFiles, err := mergeLiteralListPropertyValue(mod, licenseFilesPropertyName)
+ if err != nil {
+ return err
+ }
+ licensePatch += "license {\n" +
+ " name: \"" + licenseModuleName + "\",\n" +
+ " visibility: [\":__subpackages__\"],\n" +
+ " license_kinds: [\n" +
+ licenseKinds +
+ " ],\n" +
+ " license_text: [\n" +
+ licenseFiles +
+ " ],\n" +
+ "}\n" +
+ "\n"
+ }
+
+ // add to the patchList
+ pos := mod.Pos().Offset
+ err := patchList.Add(pos, pos, licensePatch)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// merge the string vaules in a list property of a module into one string with expected format
+func mergeLiteralListPropertyValue(mod *parser.Module, property string) (s string, err error) {
+ listValue, ok := getLiteralListPropertyValue(mod, property)
+ if !ok {
+ // if do not find
+ return "", fmt.Errorf("Cannot retrieve the %s.%s field", mod.Type, property)
+ }
+ for i := 0; i < len(listValue); i++ {
+ s += " \"" + listValue[i] + "\",\n"
+ }
+ return s, nil
+}
+
+// check whether a string list property has any value starting with `../`
+func hasValueStartWithTwoDotsLiteralList(mod *parser.Module, property string) bool {
+ listValue, ok := getLiteralListPropertyValue(mod, property)
+ if ok {
+ for i := 0; i < len(listValue); i++ {
+ if strings.HasPrefix(listValue[i], "../") {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+// get the relative path from ANDROID_BUILD_TOP to the Android.mk file to be converted
+func getModuleRelativePath() string {
+ // get the absolute path of the top of the tree
+ rootPath := os.Getenv("ANDROID_BUILD_TOP")
+ // get the absolute path of the `Android.mk` file to be converted
+ absPath := getModuleAbsolutePath()
+ // get the relative path of the `Android.mk` file to top of the tree
+ relModulePath, err := filepath.Rel(rootPath, absPath)
+ if err != nil {
+ return ""
+ }
+ return relModulePath
+}
+
+// get the absolute path of the Android.mk file to be converted
+func getModuleAbsolutePath() string {
+ // get the absolute path at where the `androidmk` commend is executed
+ curAbsPath, err := filepath.Abs(".")
+ if err != nil {
+ return ""
+ }
+ // the argument for the `androidmk` command could be
+ // 1. "./a/b/c/Android.mk"; 2. "a/b/c/Android.mk"; 3. "Android.mk"
+ argPath := flag.Arg(0)
+ if strings.HasPrefix(argPath, "./") {
+ argPath = strings.TrimPrefix(argPath, ".")
+ }
+ argPath = strings.TrimSuffix(argPath, "Android.mk")
+ if strings.HasSuffix(argPath, "/") {
+ argPath = strings.TrimSuffix(argPath, "/")
+ }
+ if len(argPath) > 0 && !strings.HasPrefix(argPath, "/") {
+ argPath = "/" + argPath
+ }
+ // get the absolute path of the `Android.mk` file to be converted
+ absPath := curAbsPath + argPath
+ return absPath
+}
+
+// check whether a file exists in a directory
+func hasFile(dir string, fileName string) error {
+ _, err := os.Stat(dir + fileName)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// get the directory where an `Android.bp` file and the property files are expected to locate
+func getDirFromProperty(mod *parser.Module, property string) (string, error) {
+ listValue, ok := getLiteralListPropertyValue(mod, property)
+ if !ok {
+ // if do not find
+ return "", fmt.Errorf("Cannot retrieve the %s.%s property", mod.Type, property)
+ }
+ if len(listValue) == 0 {
+ // if empty
+ return "", fmt.Errorf("Cannot find the value of the %s.%s property", mod.Type, property)
+ }
+ path := getModuleAbsolutePath()
+ for {
+ if !strings.HasPrefix(listValue[0], "../") {
+ break
+ }
+ path = filepath.Dir(path)
+ listValue[0] = strings.TrimPrefix(listValue[0], "../")
+ }
+ return path, nil
+}
+
+// get the path of the `Android.bp` file at the expected location where the property files locate
+func getPathFromProperty(mod *parser.Module, property string) (string, bool) {
+ dir, err := getDirFromProperty(mod, property)
+ if err != nil {
+ return "", false
+ }
+ err = hasFile(dir, "/Android.bp")
+ if err != nil {
+ return "", false
+ }
+ return dir + "/Android.bp", true
+}
+
+// parse an Android.bp file to get the name of the first module with type of moduleType
+func getModuleName(path string, moduleType string) (string, error) {
+ tree, err := parserPath(path)
+ if err != nil {
+ return "", err
+ }
+ for _, def := range tree.Defs {
+ mod, ok := def.(*parser.Module)
+ if !ok || mod.Type != moduleType {
+ continue
+ }
+ prop, ok := mod.GetProperty("name")
+ if !ok {
+ return "", fmt.Errorf("Cannot get the %s."+"name property", mod.Type)
+ }
+ propVal, ok := prop.Value.(*parser.String)
+ if ok {
+ return propVal.Value, nil
+ }
+ }
+ return "", fmt.Errorf("Cannot find the value of the %s."+"name property", moduleType)
+}
+
+// parse an Android.bp file with the specific path
+func parserPath(path string) (tree *parser.File, err error) {
+ fileContent, _ := os.ReadFile(path)
+ tree, err = parse(path, bytes.NewBufferString(string(fileContent)))
+ if err != nil {
+ return tree, err
+ }
+ return tree, nil
+}
+
+// remove the incorrect property that Soong does not support
+func removeIncorrectProperties(propName string) patchListModFunction {
+ return removeObsoleteProperty(propName)
+}
+
+// the modules on the same Android.mk file are expected to have the same license
+func haveSameLicense(f *Fixer) error {
+ androidLicenseProperties := []string{
+ "android_license_kinds",
+ "android_license_conditions",
+ "android_license_files",
+ }
+
+ var prevModuleName string
+ var prevLicenseKindsVals, prevLicenseConditionsVals, prevLicenseFilesVals []string
+ prevLicenseVals := [][]string{
+ prevLicenseKindsVals,
+ prevLicenseConditionsVals,
+ prevLicenseFilesVals,
+ }
+
+ for _, def := range f.tree.Defs {
+ mod, ok := def.(*parser.Module)
+ if !ok {
+ continue
+ }
+ for idx, property := range androidLicenseProperties {
+ curModuleName, ok := getLiteralStringPropertyValue(mod, "name")
+ // some modules in the existing test cases in the androidmk_test.go do not have name property
+ hasNameProperty := hasProperty(mod, "name")
+ if hasNameProperty && (!ok || len(curModuleName) == 0) {
+ return fmt.Errorf("Cannot retrieve the name property of a module of %s type.", mod.Type)
+ }
+ curVals, ok := getLiteralListPropertyValue(mod, property)
+ // some modules in the existing test cases in the androidmk_test.go do not have license-related property
+ hasLicenseProperty := hasProperty(mod, property)
+ if hasLicenseProperty && (!ok || len(curVals) == 0) {
+ // if do not find the property, or no value is found for the property
+ return fmt.Errorf("Cannot retrieve the %s.%s property", mod.Type, property)
+ }
+ if len(prevLicenseVals[idx]) > 0 {
+ if !reflect.DeepEqual(prevLicenseVals[idx], curVals) {
+ return fmt.Errorf("Modules %s and %s are expected to have the same %s property.",
+ prevModuleName, curModuleName, property)
+ }
+ }
+ sort.Strings(curVals)
+ prevLicenseVals[idx] = curVals
+ prevModuleName = curModuleName
+ }
+ }
+ return nil
+}
+
+func hasProperty(mod *parser.Module, propName string) bool {
+ _, ok := mod.GetProperty(propName)
+ return ok
+}
diff --git a/bpfix/bpfix/bpfix_test.go b/bpfix/bpfix/bpfix_test.go
index d8772c1..e6b6af5 100644
--- a/bpfix/bpfix/bpfix_test.go
+++ b/bpfix/bpfix/bpfix_test.go
@@ -125,34 +125,103 @@
implFilterListTest(t, []string{}, []string{}, []string{})
}
-func runPass(t *testing.T, in, out string, innerTest func(*Fixer) error) {
- expected, err := Reformat(out)
+func checkError(t *testing.T, in, expectedErr string, innerTest func(*Fixer) error) {
+ expected := preProcessOutErr(expectedErr)
+ runTestOnce(t, in, expected, innerTest)
+}
+
+func runTestOnce(t *testing.T, in, expected string, innerTest func(*Fixer) error) {
+ fixer, err := preProcessIn(in)
if err != nil {
t.Fatal(err)
}
+ out, err := runFixerOnce(fixer, innerTest)
+ if err != nil {
+ out = err.Error()
+ }
+
+ compareResult := compareOutExpected(in, out, expected)
+ if len(compareResult) > 0 {
+ t.Errorf(compareResult)
+ }
+}
+
+func preProcessOutErr(expectedErr string) string {
+ expected := strings.TrimSpace(expectedErr)
+ return expected
+}
+
+func preProcessOut(out string) (expected string, err error) {
+ expected, err = Reformat(out)
+ if err != nil {
+ return expected, err
+ }
+ return expected, nil
+}
+
+func preProcessIn(in string) (fixer *Fixer, err error) {
in, err = Reformat(in)
if err != nil {
- t.Fatal(err)
+ return fixer, err
}
tree, errs := parser.Parse("<testcase>", bytes.NewBufferString(in), parser.NewScope(nil))
if errs != nil {
- t.Fatal(errs)
+ return fixer, err
}
- fixer := NewFixer(tree)
+ fixer = NewFixer(tree)
+
+ return fixer, nil
+}
+
+func runFixerOnce(fixer *Fixer, innerTest func(*Fixer) error) (string, error) {
+ err := innerTest(fixer)
+ if err != nil {
+ return "", err
+ }
+
+ out, err := parser.Print(fixer.tree)
+ if err != nil {
+ return "", err
+ }
+ return string(out), nil
+}
+
+func compareOutExpected(in, out, expected string) string {
+ if out != expected {
+ return fmt.Sprintf("output didn't match:\ninput:\n%s\n\nexpected:\n%s\ngot:\n%s\n",
+ in, expected, out)
+ }
+ return ""
+}
+
+func runPassOnce(t *testing.T, in, out string, innerTest func(*Fixer) error) {
+ expected, err := preProcessOut(out)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ runTestOnce(t, in, expected, innerTest)
+}
+
+func runPass(t *testing.T, in, out string, innerTest func(*Fixer) error) {
+ expected, err := preProcessOut(out)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ fixer, err := preProcessIn(in)
+ if err != nil {
+ t.Fatal(err)
+ }
got := ""
prev := "foo"
passes := 0
for got != prev && passes < 10 {
- err := innerTest(fixer)
- if err != nil {
- t.Fatal(err)
- }
-
- out, err := parser.Print(fixer.tree)
+ out, err = runFixerOnce(fixer, innerTest)
if err != nil {
t.Fatal(err)
}
@@ -162,9 +231,9 @@
passes++
}
- if got != expected {
- t.Errorf("output didn't match:\ninput:\n%s\n\nexpected:\n%s\ngot:\n%s\n",
- in, expected, got)
+ compareResult := compareOutExpected(in, out, expected)
+ if len(compareResult) > 0 {
+ t.Errorf(compareResult)
}
}
@@ -1608,3 +1677,157 @@
})
}
}
+
+func TestRewriteLicenseProperties(t *testing.T) {
+ tests := []struct {
+ name string
+ in string
+ out string
+ }{
+ {
+ name: "license rewriting with one module",
+ in: `
+ android_test {
+ name: "foo",
+ android_license_kinds: ["license_kind"],
+ android_license_conditions: ["license_notice"],
+ }
+ `,
+ out: `
+ package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "Android-Apache-2.0",
+ ],
+ }
+
+ android_test {
+ name: "foo",
+ android_license_kinds: ["license_kind"],
+ android_license_conditions: ["license_notice"],
+ }
+ `,
+ },
+ {
+ name: "license rewriting with two modules",
+ in: `
+ android_test {
+ name: "foo1",
+ android_license_kinds: ["license_kind1"],
+ android_license_conditions: ["license_notice1"],
+ }
+
+ android_test {
+ name: "foo2",
+ android_license_kinds: ["license_kind2"],
+ android_license_conditions: ["license_notice2"],
+ }
+ `,
+ out: `
+ package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "Android-Apache-2.0",
+ ],
+ }
+
+ android_test {
+ name: "foo1",
+ android_license_kinds: ["license_kind1"],
+ android_license_conditions: ["license_notice1"],
+ }
+
+ android_test {
+ name: "foo2",
+ android_license_kinds: ["license_kind2"],
+ android_license_conditions: ["license_notice2"],
+ }
+ `,
+ },
+ // TODO(b/205615944): When valid "android_license_files" exists, the test requires an Android.mk
+ // file (and an Android.bp file is required as well if the license files locates outside the current
+ // directory). So plan to use a mock file system to mock the Android.mk and Android.bp files.
+ }
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ runPassOnce(t, test.in, test.out, runPatchListMod(rewriteLicenseProperties))
+ })
+ }
+}
+
+func TestHaveSameLicense(t *testing.T) {
+ tests := []struct {
+ name string
+ in string
+ out string
+ }{
+ {
+ name: "two modules with the same license",
+ in: `
+ android_test {
+ name: "foo1",
+ android_license_kinds: ["license_kind"],
+ android_license_conditions: ["license_notice"],
+ }
+
+ android_test {
+ name: "foo2",
+ android_license_kinds: ["license_kind"],
+ android_license_conditions: ["license_notice"],
+ }
+ `,
+ out: `
+ android_test {
+ name: "foo1",
+ android_license_kinds: ["license_kind"],
+ android_license_conditions: ["license_notice"],
+ }
+
+ android_test {
+ name: "foo2",
+ android_license_kinds: ["license_kind"],
+ android_license_conditions: ["license_notice"],
+ }
+ `,
+ },
+ }
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ runPassOnce(t, test.in, test.out, func(fixer *Fixer) error {
+ return haveSameLicense(fixer)
+ })
+ })
+ }
+ testErrs := []struct {
+ name string
+ in string
+ expectedErr string
+ }{
+ {
+ name: "two modules will different licenses",
+ in: `
+ android_test {
+ name: "foo1",
+ android_license_kinds: ["license_kind1"],
+ android_license_conditions: ["license_notice1"],
+ }
+
+ android_test {
+ name: "foo2",
+ android_license_kinds: ["license_kind2"],
+ android_license_conditions: ["license_notice2"],
+ }
+ `,
+ expectedErr: `
+ Modules foo1 and foo2 are expected to have the same android_license_kinds property.
+ `,
+ },
+ }
+ for _, test := range testErrs {
+ t.Run(test.name, func(t *testing.T) {
+ checkError(t, test.in, test.expectedErr, func(fixer *Fixer) error {
+ return haveSameLicense(fixer)
+ })
+ })
+ }
+}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 5c4ef17..45bb1ca 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -80,7 +80,7 @@
// to be installed. And this is breaking some older devices (like marlin)
// where system.img is small.
Required: c.Properties.AndroidMkRuntimeLibs,
- Include: "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
+ Include: "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
@@ -582,8 +582,8 @@
if p.properties.Check_elf_files != nil {
entries.SetBool("LOCAL_CHECK_ELF_FILES", *p.properties.Check_elf_files)
} else {
- // soong_cc_prebuilt.mk does not include check_elf_file.mk by default
- // because cc_library_shared and cc_binary use soong_cc_prebuilt.mk as well.
+ // soong_cc_rust_prebuilt.mk does not include check_elf_file.mk by default
+ // because cc_library_shared and cc_binary use soong_cc_rust_prebuilt.mk as well.
// In order to turn on prebuilt ABI checker, set `LOCAL_CHECK_ELF_FILES` to
// true if `p.properties.Check_elf_files` is not specified.
entries.SetBool("LOCAL_CHECK_ELF_FILES", true)
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 2059f5e..dde8dd4 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -320,14 +320,14 @@
"CppFlags": &ca.cppFlags,
}
for propName, attr := range productVarPropNameToAttribute {
- if props, exists := productVariableProps[propName]; exists {
- for _, prop := range props {
- flags, ok := prop.Property.([]string)
+ if productConfigProps, exists := productVariableProps[propName]; exists {
+ for productConfigProp, prop := range productConfigProps {
+ flags, ok := prop.([]string)
if !ok {
ctx.ModuleErrorf("Could not convert product variable %s property", proptools.PropertyNameForField(propName))
}
- newFlags, _ := bazel.TryVariableSubstitutions(flags, prop.ProductConfigVariable)
- attr.SetSelectValue(prop.ConfigurationAxis(), prop.FullConfig, newFlags)
+ newFlags, _ := bazel.TryVariableSubstitutions(flags, productConfigProp.Name)
+ attr.SetSelectValue(productConfigProp.ConfigurationAxis(), productConfigProp.SelectKey(), newFlags)
}
}
}
@@ -587,31 +587,35 @@
if !exists && !excludesExists {
continue
}
- // collect all the configurations that an include or exclude property exists for.
- // we want to iterate all configurations rather than either the include or exclude because for a
- // particular configuration we may have only and include or only an exclude to handle
- configs := make(map[string]bool, len(props)+len(excludeProps))
- for config := range props {
- configs[config] = true
+ // Collect all the configurations that an include or exclude property exists for.
+ // We want to iterate all configurations rather than either the include or exclude because, for a
+ // particular configuration, we may have either only an include or an exclude to handle.
+ productConfigProps := make(map[android.ProductConfigProperty]bool, len(props)+len(excludeProps))
+ for p := range props {
+ productConfigProps[p] = true
}
- for config := range excludeProps {
- configs[config] = true
+ for p := range excludeProps {
+ productConfigProps[p] = true
}
- for config := range configs {
- prop, includesExists := props[config]
- excludesProp, excludesExists := excludeProps[config]
+ for productConfigProp := range productConfigProps {
+ prop, includesExists := props[productConfigProp]
+ excludesProp, excludesExists := excludeProps[productConfigProp]
var includes, excludes []string
var ok bool
// if there was no includes/excludes property, casting fails and that's expected
- if includes, ok = prop.Property.([]string); includesExists && !ok {
+ if includes, ok = prop.([]string); includesExists && !ok {
ctx.ModuleErrorf("Could not convert product variable %s property", name)
}
- if excludes, ok = excludesProp.Property.([]string); excludesExists && !ok {
+ if excludes, ok = excludesProp.([]string); excludesExists && !ok {
ctx.ModuleErrorf("Could not convert product variable %s property", dep.excludesField)
}
- dep.attribute.SetSelectValue(prop.ConfigurationAxis(), config, dep.depResolutionFunc(ctx, android.FirstUniqueStrings(includes), excludes))
+ dep.attribute.SetSelectValue(
+ productConfigProp.ConfigurationAxis(),
+ productConfigProp.SelectKey(),
+ dep.depResolutionFunc(ctx, android.FirstUniqueStrings(includes), excludes),
+ )
}
}
}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index ad2ccae..9ffe48d 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -730,9 +730,16 @@
gtest: false,
}
+ cc_binary {
+ name: "test_bin",
+ relative_install_path: "foo/bar/baz",
+ compile_multilib: "both",
+ }
+
cc_test {
name: "main_test",
data_libs: ["test_lib"],
+ data_bins: ["test_bin"],
gtest: false,
}
`
@@ -750,10 +757,10 @@
t.Fatalf("Expected cc_test to produce output files, error: %s", err)
}
if len(outputFiles) != 1 {
- t.Errorf("expected exactly one output file. output files: [%s]", outputFiles)
+ t.Fatalf("expected exactly one output file. output files: [%s]", outputFiles)
}
- if len(testBinary.dataPaths()) != 1 {
- t.Errorf("expected exactly one test data file. test data files: [%s]", testBinary.dataPaths())
+ if len(testBinary.dataPaths()) != 2 {
+ t.Fatalf("expected exactly one test data file. test data files: [%s]", testBinary.dataPaths())
}
outputPath := outputFiles[0].String()
@@ -766,6 +773,10 @@
t.Errorf("expected LOCAL_TEST_DATA to end with `:test_lib.so:foo/bar/baz`,"+
" but was '%s'", entries.EntryMap["LOCAL_TEST_DATA"][0])
}
+ if !strings.HasSuffix(entries.EntryMap["LOCAL_TEST_DATA"][1], ":test_bin:foo/bar/baz") {
+ t.Errorf("expected LOCAL_TEST_DATA to end with `:test_bin:foo/bar/baz`,"+
+ " but was '%s'", entries.EntryMap["LOCAL_TEST_DATA"][1])
+ }
}
func TestVndkWhenVndkVersionIsNotSet(t *testing.T) {
diff --git a/cc/test.go b/cc/test.go
index c589165..f37fdae 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -378,31 +378,26 @@
ctx.VisitDirectDepsWithTag(dataLibDepTag, func(dep android.Module) {
depName := ctx.OtherModuleName(dep)
- ccDep, ok := dep.(LinkableInterface)
-
+ linkableDep, ok := dep.(LinkableInterface)
if !ok {
- ctx.ModuleErrorf("data_lib %q is not a linkable cc module", depName)
+ ctx.ModuleErrorf("data_lib %q is not a LinkableInterface module", depName)
}
- ccModule, ok := dep.(*Module)
- if !ok {
- ctx.ModuleErrorf("data_lib %q is not a cc module", depName)
- }
- if ccDep.OutputFile().Valid() {
+ if linkableDep.OutputFile().Valid() {
test.data = append(test.data,
- android.DataPath{SrcPath: ccDep.OutputFile().Path(),
- RelativeInstallPath: ccModule.installer.relativeInstallPath()})
+ android.DataPath{SrcPath: linkableDep.OutputFile().Path(),
+ RelativeInstallPath: linkableDep.RelativeInstallPath()})
}
})
ctx.VisitDirectDepsWithTag(dataBinDepTag, func(dep android.Module) {
depName := ctx.OtherModuleName(dep)
- ccModule, ok := dep.(*Module)
+ linkableDep, ok := dep.(LinkableInterface)
if !ok {
- ctx.ModuleErrorf("data_bin %q is not a cc module", depName)
+ ctx.ModuleErrorf("data_bin %q is not a LinkableInterface module", depName)
}
- if ccModule.OutputFile().Valid() {
+ if linkableDep.OutputFile().Valid() {
test.data = append(test.data,
- android.DataPath{SrcPath: ccModule.OutputFile().Path(),
- RelativeInstallPath: ccModule.installer.relativeInstallPath()})
+ android.DataPath{SrcPath: linkableDep.OutputFile().Path(),
+ RelativeInstallPath: linkableDep.RelativeInstallPath()})
}
})
diff --git a/cc/testing.go b/cc/testing.go
index b0a220c..3bf936d 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -763,3 +763,11 @@
}
return paths
}
+
+func AssertExcludeFromRecoverySnapshotIs(t *testing.T, ctx *android.TestContext, name string, expected bool, variant string) {
+ t.Helper()
+ m := ctx.ModuleForTests(name, variant).Module().(LinkableInterface)
+ if m.ExcludeFromRecoverySnapshot() != expected {
+ t.Errorf("expected %q ExcludeFromRecoverySnapshot to be %t", m.String(), expected)
+ }
+}
diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go
index ca2f569..b5022c8 100644
--- a/cc/vendor_snapshot_test.go
+++ b/cc/vendor_snapshot_test.go
@@ -1020,14 +1020,6 @@
assertString(t, staticCfiModule.outputFile.Path().Base(), "libsnapshot.cfi.a")
}
-func assertExcludeFromRecoverySnapshotIs(t *testing.T, ctx *android.TestContext, name string, expected bool) {
- t.Helper()
- m := ctx.ModuleForTests(name, recoveryVariant).Module().(*Module)
- if m.ExcludeFromRecoverySnapshot() != expected {
- t.Errorf("expected %q ExcludeFromRecoverySnapshot to be %t", m.String(), expected)
- }
-}
-
func TestVendorSnapshotExclude(t *testing.T) {
// This test verifies that the exclude_from_vendor_snapshot property
@@ -1371,13 +1363,13 @@
android.FailIfErrored(t, errs)
// Test an include and exclude framework module.
- assertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude", false)
- assertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude", true)
- assertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude", true)
+ AssertExcludeFromRecoverySnapshotIs(t, ctx, "libinclude", false, recoveryVariant)
+ AssertExcludeFromRecoverySnapshotIs(t, ctx, "libexclude", true, recoveryVariant)
+ AssertExcludeFromRecoverySnapshotIs(t, ctx, "libavailable_exclude", true, recoveryVariant)
// A recovery module is excluded, but by its path, not the
// exclude_from_recovery_snapshot property.
- assertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery", false)
+ AssertExcludeFromRecoverySnapshotIs(t, ctx, "librecovery", false, recoveryVariant)
// Verify the content of the recovery snapshot.
diff --git a/cmd/extract_apks/main.go b/cmd/extract_apks/main.go
index 6e51a28..1cf64de 100644
--- a/cmd/extract_apks/main.go
+++ b/cmd/extract_apks/main.go
@@ -356,7 +356,7 @@
// Writes out selected entries, renaming them as needed
func (apkSet *ApkSet) writeApks(selected SelectionResult, config TargetConfig,
- writer Zip2ZipWriter, partition string) ([]string, error) {
+ outFile io.Writer, zipWriter Zip2ZipWriter, partition string) ([]string, error) {
// Renaming rules:
// splits/MODULE-master.apk to STEM.apk
// else
@@ -406,8 +406,14 @@
origin, inName, outName)
}
entryOrigin[outName] = inName
- if err := writer.CopyFrom(apkFile, outName); err != nil {
- return nil, err
+ if outName == config.stem+".apk" {
+ if err := writeZipEntryToFile(outFile, apkFile); err != nil {
+ return nil, err
+ }
+ } else {
+ if err := zipWriter.CopyFrom(apkFile, outName); err != nil {
+ return nil, err
+ }
}
if partition != "" {
apkcerts = append(apkcerts, fmt.Sprintf(
@@ -426,14 +432,13 @@
if !ok {
return fmt.Errorf("Couldn't find apk path %s", selected.entries[0])
}
- inputReader, _ := apk.Open()
- _, err := io.Copy(outFile, inputReader)
- return err
+ return writeZipEntryToFile(outFile, apk)
}
// Arguments parsing
var (
- outputFile = flag.String("o", "", "output file containing extracted entries")
+ outputFile = flag.String("o", "", "output file for primary entry")
+ zipFile = flag.String("zip", "", "output file containing additional extracted entries")
targetConfig = TargetConfig{
screenDpi: map[android_bundle_proto.ScreenDensity_DensityAlias]bool{},
abis: map[android_bundle_proto.Abi_AbiAlias]int{},
@@ -494,7 +499,8 @@
func processArgs() {
flag.Usage = func() {
- fmt.Fprintln(os.Stderr, `usage: extract_apks -o <output-file> -sdk-version value -abis value `+
+ fmt.Fprintln(os.Stderr, `usage: extract_apks -o <output-file> [-zip <output-zip-file>] `+
+ `-sdk-version value -abis value `+
`-screen-densities value {-stem value | -extract-single} [-allow-prereleased] `+
`[-apkcerts <apkcerts output file> -partition <partition>] <APK set>`)
flag.PrintDefaults()
@@ -510,7 +516,8 @@
flag.StringVar(&targetConfig.stem, "stem", "", "output entries base name in the output zip file")
flag.Parse()
if (*outputFile == "") || len(flag.Args()) != 1 || *version == 0 ||
- (targetConfig.stem == "" && !*extractSingle) || (*apkcertsOutput != "" && *partition == "") {
+ ((targetConfig.stem == "" || *zipFile == "") && !*extractSingle) ||
+ (*apkcertsOutput != "" && *partition == "") {
flag.Usage()
}
targetConfig.sdkVersion = int32(*version)
@@ -542,13 +549,20 @@
if *extractSingle {
err = apkSet.extractAndCopySingle(sel, outFile)
} else {
- writer := zip.NewWriter(outFile)
+ zipOutputFile, err := os.Create(*zipFile)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer zipOutputFile.Close()
+
+ zipWriter := zip.NewWriter(zipOutputFile)
defer func() {
- if err := writer.Close(); err != nil {
+ if err := zipWriter.Close(); err != nil {
log.Fatal(err)
}
}()
- apkcerts, err := apkSet.writeApks(sel, targetConfig, writer, *partition)
+
+ apkcerts, err := apkSet.writeApks(sel, targetConfig, outFile, zipWriter, *partition)
if err == nil && *apkcertsOutput != "" {
apkcertsFile, err := os.Create(*apkcertsOutput)
if err != nil {
@@ -567,3 +581,13 @@
log.Fatal(err)
}
}
+
+func writeZipEntryToFile(outFile io.Writer, zipEntry *zip.File) error {
+ reader, err := zipEntry.Open()
+ if err != nil {
+ return err
+ }
+ defer reader.Close()
+ _, err = io.Copy(outFile, reader)
+ return err
+}
diff --git a/cmd/extract_apks/main_test.go b/cmd/extract_apks/main_test.go
index 9fcf324..f5e4046 100644
--- a/cmd/extract_apks/main_test.go
+++ b/cmd/extract_apks/main_test.go
@@ -15,6 +15,7 @@
package main
import (
+ "bytes"
"fmt"
"reflect"
"testing"
@@ -437,8 +438,8 @@
stem string
partition string
// what we write from what
- expectedZipEntries map[string]string
- expectedApkcerts []string
+ zipEntries map[string]string
+ expectedApkcerts []string
}
func TestWriteApks(t *testing.T) {
@@ -448,7 +449,7 @@
moduleName: "mybase",
stem: "Foo",
partition: "system",
- expectedZipEntries: map[string]string{
+ zipEntries: map[string]string{
"Foo.apk": "splits/mybase-master.apk",
"Foo-xhdpi.apk": "splits/mybase-xhdpi.apk",
},
@@ -462,7 +463,7 @@
moduleName: "base",
stem: "Bar",
partition: "product",
- expectedZipEntries: map[string]string{
+ zipEntries: map[string]string{
"Bar.apk": "universal.apk",
},
expectedApkcerts: []string{
@@ -471,23 +472,46 @@
},
}
for _, testCase := range testCases {
- apkSet := ApkSet{entries: make(map[string]*zip.File)}
- sel := SelectionResult{moduleName: testCase.moduleName}
- for _, in := range testCase.expectedZipEntries {
- apkSet.entries[in] = &zip.File{FileHeader: zip.FileHeader{Name: in}}
- sel.entries = append(sel.entries, in)
- }
- writer := testZip2ZipWriter{make(map[string]string)}
- config := TargetConfig{stem: testCase.stem}
- apkcerts, err := apkSet.writeApks(sel, config, writer, testCase.partition)
- if err != nil {
- t.Error(err)
- }
- if !reflect.DeepEqual(testCase.expectedZipEntries, writer.entries) {
- t.Errorf("expected zip entries %v, got %v", testCase.expectedZipEntries, writer.entries)
- }
- if !reflect.DeepEqual(testCase.expectedApkcerts, apkcerts) {
- t.Errorf("expected apkcerts %v, got %v", testCase.expectedApkcerts, apkcerts)
- }
+ t.Run(testCase.name, func(t *testing.T) {
+ testZipBuf := &bytes.Buffer{}
+ testZip := zip.NewWriter(testZipBuf)
+ for _, in := range testCase.zipEntries {
+ f, _ := testZip.Create(in)
+ f.Write([]byte(in))
+ }
+ testZip.Close()
+
+ zipReader, _ := zip.NewReader(bytes.NewReader(testZipBuf.Bytes()), int64(testZipBuf.Len()))
+
+ apkSet := ApkSet{entries: make(map[string]*zip.File)}
+ sel := SelectionResult{moduleName: testCase.moduleName}
+ for _, f := range zipReader.File {
+ apkSet.entries[f.Name] = f
+ sel.entries = append(sel.entries, f.Name)
+ }
+
+ zipWriter := testZip2ZipWriter{make(map[string]string)}
+ outWriter := &bytes.Buffer{}
+ config := TargetConfig{stem: testCase.stem}
+ apkcerts, err := apkSet.writeApks(sel, config, outWriter, zipWriter, testCase.partition)
+ if err != nil {
+ t.Error(err)
+ }
+ expectedZipEntries := make(map[string]string)
+ for k, v := range testCase.zipEntries {
+ if k != testCase.stem+".apk" {
+ expectedZipEntries[k] = v
+ }
+ }
+ if !reflect.DeepEqual(expectedZipEntries, zipWriter.entries) {
+ t.Errorf("expected zip entries %v, got %v", testCase.zipEntries, zipWriter.entries)
+ }
+ if !reflect.DeepEqual(testCase.expectedApkcerts, apkcerts) {
+ t.Errorf("expected apkcerts %v, got %v", testCase.expectedApkcerts, apkcerts)
+ }
+ if g, w := outWriter.String(), testCase.zipEntries[testCase.stem+".apk"]; !reflect.DeepEqual(g, w) {
+ t.Errorf("expected output file contents %q, got %q", testCase.stem+".apk", outWriter.String())
+ }
+ })
}
}
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index c7f3f6a..4fa7486 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -164,7 +164,7 @@
if useSubDir {
localTempDir = filepath.Join(localTempDir, strconv.Itoa(i))
}
- depFile, err := runCommand(command, localTempDir)
+ depFile, err := runCommand(command, localTempDir, i)
if err != nil {
// Running the command failed, keep the temporary output directory around in
// case a user wants to inspect it for debugging purposes. Soong will delete
@@ -194,6 +194,28 @@
return nil
}
+// createCommandScript will create and return an exec.Cmd that runs rawCommand.
+//
+// rawCommand is executed via a script in the sandbox.
+// tempDir is the temporary where the script is created.
+// toDirInSandBox is the path containing the script in the sbox environment.
+// toDirInSandBox is the path containing the script in the sbox environment.
+// seed is a unique integer used to distinguish different scripts that might be at location.
+//
+// returns an exec.Cmd that can be ran from within sbox context if no error, or nil if error.
+// caller must ensure script is cleaned up if function succeeds.
+//
+func createCommandScript(rawCommand string, tempDir, toDirInSandbox string, seed int) (*exec.Cmd, error) {
+ scriptName := fmt.Sprintf("sbox_command.%d.bash", seed)
+ scriptPathAndName := joinPath(tempDir, scriptName)
+ err := os.WriteFile(scriptPathAndName, []byte(rawCommand), 0644)
+ if err != nil {
+ return nil, fmt.Errorf("failed to write command %s... to %s",
+ rawCommand[0:40], scriptPathAndName)
+ }
+ return exec.Command("bash", joinPath(toDirInSandbox, filepath.Base(scriptName))), nil
+}
+
// readManifest reads an sbox manifest from a textproto file.
func readManifest(file string) (*sbox_proto.Manifest, error) {
manifestData, err := ioutil.ReadFile(file)
@@ -213,7 +235,7 @@
// runCommand runs a single command from a manifest. If the command references the
// __SBOX_DEPFILE__ placeholder it returns the name of the depfile that was used.
-func runCommand(command *sbox_proto.Command, tempDir string) (depFile string, err error) {
+func runCommand(command *sbox_proto.Command, tempDir string, commandIndex int) (depFile string, err error) {
rawCommand := command.GetCommand()
if rawCommand == "" {
return "", fmt.Errorf("command is required")
@@ -255,7 +277,11 @@
return "", err
}
- cmd := exec.Command("bash", "-c", rawCommand)
+ cmd, err := createCommandScript(rawCommand, tempDir, pathToTempDirInSbox, commandIndex)
+ if err != nil {
+ return "", err
+ }
+
buf := &bytes.Buffer{}
cmd.Stdin = os.Stdin
cmd.Stdout = buf
diff --git a/java/androidmk.go b/java/androidmk.go
index 4c115d5..272a4fd 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -696,12 +696,12 @@
return []android.AndroidMkEntries{
android.AndroidMkEntries{
Class: "APPS",
- OutputFile: android.OptionalPathForPath(apkSet.packedOutput),
+ OutputFile: android.OptionalPathForPath(apkSet.primaryOutput),
Include: "$(BUILD_SYSTEM)/soong_android_app_set.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", apkSet.Privileged())
- entries.SetString("LOCAL_APK_SET_INSTALL_FILE", apkSet.InstallFile())
+ entries.SetPath("LOCAL_APK_SET_INSTALL_FILE", apkSet.PackedAdditionalOutputs())
entries.SetPath("LOCAL_APKCERTS_FILE", apkSet.apkcertsFile)
entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", apkSet.properties.Overrides...)
},
diff --git a/java/app_set.go b/java/app_set.go
index 6b25638..694b167 100644
--- a/java/app_set.go
+++ b/java/app_set.go
@@ -55,10 +55,10 @@
android.DefaultableModuleBase
prebuilt android.Prebuilt
- properties AndroidAppSetProperties
- packedOutput android.WritablePath
- installFile string
- apkcertsFile android.ModuleOutPath
+ properties AndroidAppSetProperties
+ packedOutput android.WritablePath
+ primaryOutput android.WritablePath
+ apkcertsFile android.ModuleOutPath
}
func (as *AndroidAppSet) Name() string {
@@ -78,11 +78,11 @@
}
func (as *AndroidAppSet) OutputFile() android.Path {
- return as.packedOutput
+ return as.primaryOutput
}
-func (as *AndroidAppSet) InstallFile() string {
- return as.installFile
+func (as *AndroidAppSet) PackedAdditionalOutputs() android.Path {
+ return as.packedOutput
}
func (as *AndroidAppSet) APKCertsFile() android.Path {
@@ -114,11 +114,11 @@
func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
as.packedOutput = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
+ as.primaryOutput = android.PathForModuleOut(ctx, as.BaseModuleName()+".apk")
as.apkcertsFile = android.PathForModuleOut(ctx, "apkcerts.txt")
// We are assuming here that the install file in the APK
// set has `.apk` suffix. If it doesn't the build will fail.
// APK sets containing APEX files are handled elsewhere.
- as.installFile = as.BaseModuleName() + ".apk"
screenDensities := "all"
if dpis := ctx.Config().ProductAAPTPrebuiltDPI(); len(dpis) > 0 {
screenDensities = strings.ToUpper(strings.Join(dpis, ","))
@@ -127,11 +127,11 @@
// TODO(asmundak): do we support device features
ctx.Build(pctx,
android.BuildParams{
- Rule: extractMatchingApks,
- Description: "Extract APKs from APK set",
- Output: as.packedOutput,
- ImplicitOutput: as.apkcertsFile,
- Inputs: android.Paths{as.prebuilt.SingleSourcePath(ctx)},
+ Rule: extractMatchingApks,
+ Description: "Extract APKs from APK set",
+ Output: as.primaryOutput,
+ ImplicitOutputs: android.WritablePaths{as.packedOutput, as.apkcertsFile},
+ Inputs: android.Paths{as.prebuilt.SingleSourcePath(ctx)},
Args: map[string]string{
"abis": strings.Join(SupportedAbis(ctx), ","),
"allow-prereleased": strconv.FormatBool(proptools.Bool(as.properties.Prerelease)),
@@ -140,10 +140,21 @@
"stem": as.BaseModuleName(),
"apkcerts": as.apkcertsFile.String(),
"partition": as.PartitionTag(ctx.DeviceConfig()),
+ "zip": as.packedOutput.String(),
},
})
+
+ var installDir android.InstallPath
+ if as.Privileged() {
+ installDir = android.PathForModuleInstall(ctx, "priv-app", as.BaseModuleName())
+ } else {
+ installDir = android.PathForModuleInstall(ctx, "app", as.BaseModuleName())
+ }
+ ctx.InstallFileWithExtraFilesZip(installDir, as.BaseModuleName()+".apk", as.primaryOutput, as.packedOutput)
}
+func (as *AndroidAppSet) InstallBypassMake() bool { return true }
+
// android_app_set extracts a set of APKs based on the target device
// configuration and installs this set as "split APKs".
// The extracted set always contains an APK whose name is
diff --git a/java/app_set_test.go b/java/app_set_test.go
index adaf71b..03eb667 100644
--- a/java/app_set_test.go
+++ b/java/app_set_test.go
@@ -17,19 +17,20 @@
import (
"fmt"
"reflect"
+ "strings"
"testing"
"android/soong/android"
)
func TestAndroidAppSet(t *testing.T) {
- ctx, _ := testJava(t, `
+ result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, `
android_app_set {
name: "foo",
set: "prebuilts/apks/app.apks",
prerelease: true,
}`)
- module := ctx.ModuleForTests("foo", "android_common")
+ module := result.ModuleForTests("foo", "android_common")
const packedSplitApks = "foo.zip"
params := module.Output(packedSplitApks)
if params.Rule == nil {
@@ -41,9 +42,22 @@
if s := params.Args["partition"]; s != "system" {
t.Errorf("wrong partition value: '%s', expected 'system'", s)
}
- mkEntries := android.AndroidMkEntriesForTest(t, ctx, module.Module())[0]
+
+ android.AssertPathRelativeToTopEquals(t, "incorrect output path",
+ "out/soong/.intermediates/foo/android_common/foo.apk", params.Output)
+
+ android.AssertPathsRelativeToTopEquals(t, "incorrect implicit output paths",
+ []string{
+ "out/soong/.intermediates/foo/android_common/foo.zip",
+ "out/soong/.intermediates/foo/android_common/apkcerts.txt",
+ },
+ params.ImplicitOutputs.Paths())
+
+ mkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, module.Module())[0]
actualInstallFile := mkEntries.EntryMap["LOCAL_APK_SET_INSTALL_FILE"]
- expectedInstallFile := []string{"foo.apk"}
+ expectedInstallFile := []string{
+ strings.Replace(params.ImplicitOutputs[0].String(), android.OutSoongDir, result.Config.SoongOutDir(), 1),
+ }
if !reflect.DeepEqual(actualInstallFile, expectedInstallFile) {
t.Errorf("Unexpected LOCAL_APK_SET_INSTALL_FILE value: '%s', expected: '%s',",
actualInstallFile, expectedInstallFile)
diff --git a/java/app_test.go b/java/app_test.go
index 07439fc..0aae928 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -144,14 +144,14 @@
}
`)
- testJavaError(t, "platform_apis must be true when sdk_version is empty.", `
+ testJavaError(t, "This module has conflicting settings. sdk_version is empty, which means that this module is build against platform APIs. However platform_apis is not set to true", `
android_app {
name: "bar",
srcs: ["b.java"],
}
`)
- testJavaError(t, "platform_apis must be false when sdk_version is not empty.", `
+ testJavaError(t, "This module has conflicting settings. sdk_version is not empty, which means this module cannot use platform APIs. However platform_apis is set to true.", `
android_app {
name: "bar",
srcs: ["b.java"],
diff --git a/java/base.go b/java/base.go
index 6930bcd..d9b1260 100644
--- a/java/base.go
+++ b/java/base.go
@@ -184,16 +184,21 @@
// Properties that are specific to device modules. Host module factories should not add these when
// constructing a new module.
type DeviceProperties struct {
- // if not blank, set to the version of the sdk to compile against.
+ // If not blank, set to the version of the sdk to compile against.
// Defaults to compiling against the current platform.
+ // Values are of one of the following forms:
+ // 1) numerical API level or "current"
+ // 2) An SDK kind with an API level: "<sdk kind>_<API level>". See
+ // build/soong/android/sdk_version.go for the complete and up to date list of
+ // SDK kinds. If the SDK kind value is empty, it will be set to public.
Sdk_version *string
// if not blank, set the minimum version of the sdk that the compiled artifacts will run against.
- // Defaults to sdk_version if not set.
+ // Defaults to sdk_version if not set. See sdk_version for possible values.
Min_sdk_version *string
// if not blank, set the targetSdkVersion in the AndroidManifest.xml.
- // Defaults to sdk_version if not set.
+ // Defaults to sdk_version if not set. See sdk_version for possible values.
Target_sdk_version *string
// Whether to compile against the platform APIs instead of an SDK.
@@ -505,9 +510,9 @@
usePlatformAPI := proptools.Bool(j.deviceProperties.Platform_apis)
sdkVersionSpecified := sc.SdkVersion(ctx).Specified()
if usePlatformAPI && sdkVersionSpecified {
- ctx.PropertyErrorf("platform_apis", "platform_apis must be false when sdk_version is not empty.")
+ ctx.PropertyErrorf("platform_apis", "This module has conflicting settings. sdk_version is not empty, which means this module cannot use platform APIs. However platform_apis is set to true.")
} else if !usePlatformAPI && !sdkVersionSpecified {
- ctx.PropertyErrorf("platform_apis", "platform_apis must be true when sdk_version is empty.")
+ ctx.PropertyErrorf("platform_apis", "This module has conflicting settings. sdk_version is empty, which means that this module is build against platform APIs. However platform_apis is not set to true")
}
}
@@ -1061,7 +1066,7 @@
j.compiledSrcJars = srcJars
enableSharding := false
- var headerJarFileWithoutJarjar android.Path
+ var headerJarFileWithoutDepsOrJarjar android.Path
if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !deps.disableTurbine {
if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {
enableSharding = true
@@ -1071,7 +1076,7 @@
// allow for the use of annotation processors that do function correctly
// with sharding enabled. See: b/77284273.
}
- headerJarFileWithoutJarjar, j.headerJarFile =
+ headerJarFileWithoutDepsOrJarjar, j.headerJarFile =
j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinJars)
if ctx.Failed() {
return
@@ -1100,7 +1105,9 @@
}
if enableSharding {
- flags.classpath = append(flags.classpath, headerJarFileWithoutJarjar)
+ if headerJarFileWithoutDepsOrJarjar != nil {
+ flags.classpath = append(classpath{headerJarFileWithoutDepsOrJarjar}, flags.classpath...)
+ }
shardSize := int(*(j.properties.Javac_shard_size))
var shardSrcs []android.Paths
if len(uniqueSrcFiles) > 0 {
@@ -1503,7 +1510,7 @@
func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths,
deps deps, flags javaBuilderFlags, jarName string,
- extraJars android.Paths) (headerJar, jarjarHeaderJar android.Path) {
+ extraJars android.Paths) (headerJar, jarjarAndDepsHeaderJar android.Path) {
var jars android.Paths
if len(srcFiles) > 0 || len(srcJars) > 0 {
@@ -1514,6 +1521,7 @@
return nil, nil
}
jars = append(jars, turbineJar)
+ headerJar = turbineJar
}
jars = append(jars, extraJars...)
@@ -1527,20 +1535,19 @@
combinedJar := android.PathForModuleOut(ctx, "turbine-combined", jarName)
TransformJarsToJar(ctx, combinedJar, "for turbine", jars, android.OptionalPath{},
false, nil, []string{"META-INF/TRANSITIVE"})
- headerJar = combinedJar
- jarjarHeaderJar = combinedJar
+ jarjarAndDepsHeaderJar = combinedJar
if j.expandJarjarRules != nil {
// Transform classes.jar into classes-jarjar.jar
jarjarFile := android.PathForModuleOut(ctx, "turbine-jarjar", jarName)
- TransformJarJar(ctx, jarjarFile, headerJar, j.expandJarjarRules)
- jarjarHeaderJar = jarjarFile
+ TransformJarJar(ctx, jarjarFile, jarjarAndDepsHeaderJar, j.expandJarjarRules)
+ jarjarAndDepsHeaderJar = jarjarFile
if ctx.Failed() {
return nil, nil
}
}
- return headerJar, jarjarHeaderJar
+ return headerJar, jarjarAndDepsHeaderJar
}
func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
diff --git a/java/builder.go b/java/builder.go
index ae124a3..e64a61f 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -120,14 +120,14 @@
"extractMatchingApks",
blueprint.RuleParams{
Command: `rm -rf "$out" && ` +
- `${config.ExtractApksCmd} -o "${out}" -allow-prereleased=${allow-prereleased} ` +
+ `${config.ExtractApksCmd} -o "${out}" -zip "${zip}" -allow-prereleased=${allow-prereleased} ` +
`-sdk-version=${sdk-version} -abis=${abis} ` +
`--screen-densities=${screen-densities} --stem=${stem} ` +
`-apkcerts=${apkcerts} -partition=${partition} ` +
`${in}`,
CommandDeps: []string{"${config.ExtractApksCmd}"},
},
- "abis", "allow-prereleased", "screen-densities", "sdk-version", "stem", "apkcerts", "partition")
+ "abis", "allow-prereleased", "screen-densities", "sdk-version", "stem", "apkcerts", "partition", "zip")
turbine, turbineRE = pctx.RemoteStaticRules("turbine",
blueprint.RuleParams{
diff --git a/java/java_test.go b/java/java_test.go
index c039f72..6e4e673 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -988,11 +988,11 @@
}
`)
- barHeaderJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar")
+ barHeaderJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine", "bar.jar")
for i := 0; i < 3; i++ {
barJavac := ctx.ModuleForTests("bar", "android_common").Description("javac" + strconv.Itoa(i))
- if !strings.Contains(barJavac.Args["classpath"], barHeaderJar) {
- t.Errorf("bar javac classpath %v does not contain %q", barJavac.Args["classpath"], barHeaderJar)
+ if !strings.HasPrefix(barJavac.Args["classpath"], "-classpath "+barHeaderJar+":") {
+ t.Errorf("bar javac classpath %v does start with %q", barJavac.Args["classpath"], barHeaderJar)
}
}
}
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index d75635c..e263cc4 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -125,6 +125,12 @@
// TODO(b/203233647): Add better mechanism to make it optional.
_, unknown = android.RemoveFromList("car-frameworks-service-module", unknown)
+ // This module is optional, so it is not present in all products.
+ // (See PRODUCT_ISOLATED_COMPILATION_ENABLED.)
+ // So ignore it even if it is not in PRODUCT_APEX_SYSTEM_SERVER_JARS.
+ // TODO(b/203233647): Add better mechanism to make it optional.
+ _, unknown = android.RemoveFromList("service-compos", unknown)
+
// TODO(satayev): for apex_test we want to include all contents unconditionally to classpaths
// config. However, any test specific jars would not be present in ApexSystemServerJars. Instead,
// we should check if we are creating a config for apex_test via ApexInfo and amend the values.
diff --git a/licenses/Android.bp b/licenses/Android.bp
index a983b5b..5b764dc 100644
--- a/licenses/Android.bp
+++ b/licenses/Android.bp
@@ -492,36 +492,36 @@
license_kind {
name: "SPDX-license-identifier-CC-BY-ND",
- conditions: ["restricted"],
+ conditions: ["by_exception_only"],
}
license_kind {
name: "SPDX-license-identifier-CC-BY-ND-1.0",
- conditions: ["restricted"],
+ conditions: ["by_exception_only"],
url: "https://spdx.org/licenses/CC-BY-ND-1.0.html",
}
license_kind {
name: "SPDX-license-identifier-CC-BY-ND-2.0",
- conditions: ["restricted"],
+ conditions: ["by_exception_only"],
url: "https://spdx.org/licenses/CC-BY-ND-2.0.html",
}
license_kind {
name: "SPDX-license-identifier-CC-BY-ND-2.5",
- conditions: ["restricted"],
+ conditions: ["by_exception_only"],
url: "https://spdx.org/licenses/CC-BY-ND-2.5.html",
}
license_kind {
name: "SPDX-license-identifier-CC-BY-ND-3.0",
- conditions: ["restricted"],
+ conditions: ["by_exception_only"],
url: "https://spdx.org/licenses/CC-BY-ND-3.0.html",
}
license_kind {
name: "SPDX-license-identifier-CC-BY-ND-4.0",
- conditions: ["restricted"],
+ conditions: ["by_exception_only"],
url: "https://spdx.org/licenses/CC-BY-ND-4.0.html",
}
@@ -562,7 +562,10 @@
license_kind {
name: "SPDX-license-identifier-CC-BY-SA-ND",
- conditions: ["restricted"],
+ conditions: [
+ "restricted",
+ "by_exception_only",
+ ],
}
license_kind {
diff --git a/mk2rbc/cmd/mk2rbc.go b/mk2rbc/cmd/mk2rbc.go
index 7bb0246..bb5a680 100644
--- a/mk2rbc/cmd/mk2rbc.go
+++ b/mk2rbc/cmd/mk2rbc.go
@@ -46,8 +46,6 @@
dryRun = flag.Bool("dry_run", false, "dry run")
recurse = flag.Bool("convert_dependents", false, "convert all dependent files")
mode = flag.String("mode", "", `"backup" to back up existing files, "write" to overwrite them`)
- noWarn = flag.Bool("no_warnings", false, "don't warn about partially failed conversions")
- verbose = flag.Bool("v", false, "print summary")
errstat = flag.Bool("error_stat", false, "print error statistics")
traceVar = flag.String("trace", "", "comma-separated list of variables to trace")
// TODO(asmundak): this option is for debugging
@@ -75,7 +73,6 @@
flagAlias("root", "d")
flagAlias("dry_run", "n")
flagAlias("convert_dependents", "r")
- flagAlias("no_warnings", "w")
flagAlias("error_stat", "e")
}
@@ -207,9 +204,9 @@
}
}
- printStats()
if *errstat {
errorLogger.printStatistics()
+ printStats()
}
if !ok {
os.Exit(1)
@@ -329,17 +326,16 @@
}()
mk2starRequest := mk2rbc.Request{
- MkFile: mkFile,
- Reader: nil,
- RootDir: *rootDir,
- OutputDir: *outputTop,
- OutputSuffix: *suffix,
- TracedVariables: tracedVariables,
- TraceCalls: *traceCalls,
- WarnPartialSuccess: !*noWarn,
- SourceFS: os.DirFS(*rootDir),
- MakefileFinder: makefileFinder,
- ErrorLogger: errorLogger,
+ MkFile: mkFile,
+ Reader: nil,
+ RootDir: *rootDir,
+ OutputDir: *outputTop,
+ OutputSuffix: *suffix,
+ TracedVariables: tracedVariables,
+ TraceCalls: *traceCalls,
+ SourceFS: os.DirFS(*rootDir),
+ MakefileFinder: makefileFinder,
+ ErrorLogger: errorLogger,
}
ss, err := mk2rbc.Convert(mk2starRequest)
if err != nil {
@@ -417,9 +413,6 @@
func printStats() {
var sortedFiles []string
- if *noWarn && !*verbose {
- return
- }
for p := range converted {
sortedFiles = append(sortedFiles, p)
}
@@ -435,27 +428,22 @@
nOk++
}
}
- if !*noWarn {
- if nPartial > 0 {
- fmt.Fprintf(os.Stderr, "Conversion was partially successful for:\n")
- for _, f := range sortedFiles {
- if ss := converted[f]; ss != nil && ss.HasErrors() {
- fmt.Fprintln(os.Stderr, " ", f)
- }
- }
- }
-
- if nFailed > 0 {
- fmt.Fprintf(os.Stderr, "Conversion failed for files:\n")
- for _, f := range sortedFiles {
- if converted[f] == nil {
- fmt.Fprintln(os.Stderr, " ", f)
- }
+ if nPartial > 0 {
+ fmt.Fprintf(os.Stderr, "Conversion was partially successful for:\n")
+ for _, f := range sortedFiles {
+ if ss := converted[f]; ss != nil && ss.HasErrors() {
+ fmt.Fprintln(os.Stderr, " ", f)
}
}
}
- if *verbose && (nPartial > 0 || nFailed > 0) {
- fmt.Fprintln(os.Stderr, "Succeeded: ", nOk, " Partial: ", nPartial, " Failed: ", nFailed)
+
+ if nFailed > 0 {
+ fmt.Fprintf(os.Stderr, "Conversion failed for files:\n")
+ for _, f := range sortedFiles {
+ if converted[f] == nil {
+ fmt.Fprintln(os.Stderr, " ", f)
+ }
+ }
}
}
@@ -468,8 +456,8 @@
data map[string]datum
}
-func (ebt errorSink) NewError(sourceFile string, sourceLine int, node parser.Node, message string, args ...interface{}) {
- fmt.Fprintf(os.Stderr, "%s:%d ", sourceFile, sourceLine)
+func (ebt errorSink) NewError(el mk2rbc.ErrorLocation, node parser.Node, message string, args ...interface{}) {
+ fmt.Fprint(os.Stderr, el, ": ")
fmt.Fprintf(os.Stderr, message, args...)
fmt.Fprintln(os.Stderr)
if !*errstat {
diff --git a/mk2rbc/expr.go b/mk2rbc/expr.go
index 0bb8b95..ec0b279 100644
--- a/mk2rbc/expr.go
+++ b/mk2rbc/expr.go
@@ -18,8 +18,6 @@
"fmt"
"strconv"
"strings"
-
- mkparser "android/soong/androidmk/parser"
)
// Represents an expression in the Starlark code. An expression has
@@ -106,7 +104,7 @@
format += "%s" + strings.ReplaceAll(chunk, "%", "%%")
}
gctx.writef("%q %% ", format)
- emitarg := func(arg starlarkExpr) {
+ emitArg := func(arg starlarkExpr) {
if arg.typ() == starlarkTypeList {
gctx.write(`" ".join(`)
arg.emit(gctx)
@@ -116,12 +114,12 @@
}
}
if len(xi.args) == 1 {
- emitarg(xi.args[0])
+ emitArg(xi.args[0])
} else {
sep := "("
for _, arg := range xi.args {
gctx.write(sep)
- emitarg(arg)
+ emitArg(arg)
sep = ", "
}
gctx.write(")")
@@ -197,6 +195,51 @@
}
}
+type toStringExpr struct {
+ expr starlarkExpr
+}
+
+func (s *toStringExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same bool) {
+ if x, same := s.expr.eval(valueMap); same {
+ res = s
+ } else {
+ res = &toStringExpr{expr: x}
+ }
+ return
+}
+
+func (s *toStringExpr) emit(ctx *generationContext) {
+ switch s.expr.typ() {
+ case starlarkTypeString, starlarkTypeUnknown:
+ // Assume unknown types are strings already.
+ s.expr.emit(ctx)
+ case starlarkTypeList:
+ ctx.write(`" ".join(`)
+ s.expr.emit(ctx)
+ ctx.write(")")
+ case starlarkTypeInt:
+ ctx.write(`("%d" % (`)
+ s.expr.emit(ctx)
+ ctx.write("))")
+ case starlarkTypeBool:
+ ctx.write(`("true" if (`)
+ s.expr.emit(ctx)
+ ctx.write(`) else "")`)
+ case starlarkTypeVoid:
+ ctx.write(`""`)
+ default:
+ panic("Unknown starlark type!")
+ }
+}
+
+func (s *toStringExpr) typ() starlarkType {
+ return starlarkTypeString
+}
+
+func (s *toStringExpr) emitListVarCopy(gctx *generationContext) {
+ s.emit(gctx)
+}
+
type notExpr struct {
expr starlarkExpr
}
@@ -240,21 +283,40 @@
}
func (eq *eqExpr) emit(gctx *generationContext) {
- emitSimple := func(expr starlarkExpr) {
- if eq.isEq {
- gctx.write("not ")
- }
- expr.emit(gctx)
+ var stringOperand string
+ var otherOperand starlarkExpr
+ if s, ok := maybeString(eq.left); ok {
+ stringOperand = s
+ otherOperand = eq.right
+ } else if s, ok := maybeString(eq.right); ok {
+ stringOperand = s
+ otherOperand = eq.left
}
- // Are we checking that a variable is empty?
- if isEmptyString(eq.left) {
- emitSimple(eq.right)
- return
- } else if isEmptyString(eq.right) {
- emitSimple(eq.left)
- return
+ // If we've identified one of the operands as being a string literal, check
+ // for some special cases we can do to simplify the resulting expression.
+ if otherOperand != nil {
+ if stringOperand == "" {
+ if eq.isEq {
+ gctx.write("not ")
+ }
+ otherOperand.emit(gctx)
+ return
+ }
+ if stringOperand == "true" && otherOperand.typ() == starlarkTypeBool {
+ if !eq.isEq {
+ gctx.write("not ")
+ }
+ otherOperand.emit(gctx)
+ return
+ }
}
+
+ if eq.left.typ() != eq.right.typ() {
+ eq.left = &toStringExpr{expr: eq.left}
+ eq.right = &toStringExpr{expr: eq.right}
+ }
+
// General case
eq.left.emit(gctx)
if eq.isEq {
@@ -363,7 +425,7 @@
return &v
}
-// concatExpr generates epxr1 + expr2 + ... + exprN in Starlark.
+// concatExpr generates expr1 + expr2 + ... + exprN in Starlark.
type concatExpr struct {
items []starlarkExpr
}
@@ -556,8 +618,8 @@
}
type badExpr struct {
- node mkparser.Node
- message string
+ errorLocation ErrorLocation
+ message string
}
func (b *badExpr) eval(_ map[string]starlarkExpr) (res starlarkExpr, same bool) {
@@ -566,15 +628,15 @@
return
}
-func (b *badExpr) emit(_ *generationContext) {
- panic("implement me")
+func (b *badExpr) emit(gctx *generationContext) {
+ gctx.emitConversionError(b.errorLocation, b.message)
}
func (_ *badExpr) typ() starlarkType {
return starlarkTypeUnknown
}
-func (b *badExpr) emitListVarCopy(gctx *generationContext) {
+func (_ *badExpr) emitListVarCopy(_ *generationContext) {
panic("implement me")
}
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 7ce1834..c55300e 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -102,6 +102,7 @@
"addsuffix": {baseName + ".addsuffix", starlarkTypeList, hiddenArgNone},
"copy-files": {baseName + ".copy_files", starlarkTypeList, hiddenArgNone},
"dir": {baseName + ".dir", starlarkTypeList, hiddenArgNone},
+ "dist-for-goals": {baseName + ".mkdist_for_goals", starlarkTypeVoid, hiddenArgGlobal},
"enforce-product-packages-exist": {baseName + ".enforce_product_packages_exist", starlarkTypeVoid, hiddenArgNone},
"error": {baseName + ".mkerror", starlarkTypeVoid, hiddenArgNone},
"findstring": {"!findstring", starlarkTypeInt, hiddenArgNone},
@@ -156,23 +157,31 @@
// Conversion request parameters
type Request struct {
- MkFile string // file to convert
- Reader io.Reader // if set, read input from this stream instead
- RootDir string // root directory path used to resolve included files
- OutputSuffix string // generated Starlark files suffix
- OutputDir string // if set, root of the output hierarchy
- ErrorLogger ErrorLogger
- TracedVariables []string // trace assignment to these variables
- TraceCalls bool
- WarnPartialSuccess bool
- SourceFS fs.FS
- MakefileFinder MakefileFinder
+ MkFile string // file to convert
+ Reader io.Reader // if set, read input from this stream instead
+ RootDir string // root directory path used to resolve included files
+ OutputSuffix string // generated Starlark files suffix
+ OutputDir string // if set, root of the output hierarchy
+ ErrorLogger ErrorLogger
+ TracedVariables []string // trace assignment to these variables
+ TraceCalls bool
+ SourceFS fs.FS
+ MakefileFinder MakefileFinder
}
// ErrorLogger prints errors and gathers error statistics.
// Its NewError function is called on every error encountered during the conversion.
type ErrorLogger interface {
- NewError(sourceFile string, sourceLine int, node mkparser.Node, text string, args ...interface{})
+ NewError(el ErrorLocation, node mkparser.Node, text string, args ...interface{})
+}
+
+type ErrorLocation struct {
+ MkFile string
+ MkLine int
+}
+
+func (el ErrorLocation) String() string {
+ return fmt.Sprintf("%s:%d", el.MkFile, el.MkLine)
}
// Derives module name for a given file. It is base name
@@ -248,10 +257,6 @@
node.emit(gctx)
}
- if ss.hasErrors && ss.warnPartialSuccess {
- gctx.newLine()
- gctx.writef("%s(%q, %q)", cfnWarning, filepath.Base(ss.mkFile), "partially successful conversion")
- }
if gctx.starScript.traceCalls {
gctx.newLine()
gctx.writef(`print("<%s")`, gctx.starScript.mkFile)
@@ -306,6 +311,10 @@
gctx.writef("%*s", 2*gctx.indentLevel, "")
}
+func (gctx *generationContext) emitConversionError(el ErrorLocation, message string) {
+ gctx.writef(`rblf.mk2rbc_error("%s", %q)`, el, message)
+}
+
type knownVariable struct {
name string
class varClass
@@ -370,18 +379,17 @@
// Information about the generated Starlark script.
type StarlarkScript struct {
- mkFile string
- moduleName string
- mkPos scanner.Position
- nodes []starlarkNode
- inherited []*moduleInfo
- hasErrors bool
- topDir string
- traceCalls bool // print enter/exit each init function
- warnPartialSuccess bool
- sourceFS fs.FS
- makefileFinder MakefileFinder
- nodeLocator func(pos mkparser.Pos) int
+ mkFile string
+ moduleName string
+ mkPos scanner.Position
+ nodes []starlarkNode
+ inherited []*moduleInfo
+ hasErrors bool
+ topDir string
+ traceCalls bool // print enter/exit each init function
+ sourceFS fs.FS
+ makefileFinder MakefileFinder
+ nodeLocator func(pos mkparser.Pos) int
}
func (ss *StarlarkScript) newNode(node starlarkNode) {
@@ -560,7 +568,7 @@
return
}
_, isTraced := ctx.tracedVariables[name]
- asgn := &assignmentNode{lhs: lhs, mkValue: a.Value, isTraced: isTraced}
+ asgn := &assignmentNode{lhs: lhs, mkValue: a.Value, isTraced: isTraced, location: ctx.errorLocation(a)}
if lhs.valueType() == starlarkTypeUnknown {
// Try to divine variable type from the RHS
asgn.value = ctx.parseMakeString(a, a.Value)
@@ -1023,10 +1031,10 @@
func (ctx *parseContext) newBadExpr(node mkparser.Node, text string, args ...interface{}) starlarkExpr {
message := fmt.Sprintf(text, args...)
if ctx.errorLogger != nil {
- ctx.errorLogger.NewError(ctx.script.mkFile, ctx.script.nodeLocator(node.Pos()), node, text, args...)
+ ctx.errorLogger.NewError(ctx.errorLocation(node), node, text, args...)
}
ctx.script.hasErrors = true
- return &badExpr{node, message}
+ return &badExpr{errorLocation: ctx.errorLocation(node), message: message}
}
func (ctx *parseContext) parseCompare(cond *mkparser.Directive) starlarkExpr {
@@ -1044,48 +1052,54 @@
args[1].TrimLeftSpaces()
isEq := !strings.HasSuffix(cond.Name, "neq")
- switch xLeft := ctx.parseMakeString(cond, args[0]).(type) {
- case *stringLiteralExpr, *variableRefExpr:
- switch xRight := ctx.parseMakeString(cond, args[1]).(type) {
- case *stringLiteralExpr, *variableRefExpr:
- return &eqExpr{left: xLeft, right: xRight, isEq: isEq}
- case *badExpr:
- return xRight
- default:
- expr, ok := ctx.parseCheckFunctionCallResult(cond, xLeft, args[1])
- if ok {
- return expr
- }
- return ctx.newBadExpr(cond, "right operand is too complex: %s", args[1].Dump())
- }
- case *badExpr:
- return xLeft
- default:
- switch xRight := ctx.parseMakeString(cond, args[1]).(type) {
- case *stringLiteralExpr, *variableRefExpr:
- expr, ok := ctx.parseCheckFunctionCallResult(cond, xRight, args[0])
- if ok {
- return expr
- }
- return ctx.newBadExpr(cond, "left operand is too complex: %s", args[0].Dump())
- case *badExpr:
- return xRight
- default:
- return ctx.newBadExpr(cond, "operands are too complex: (%s,%s)", args[0].Dump(), args[1].Dump())
- }
+ xLeft := ctx.parseMakeString(cond, args[0])
+ xRight := ctx.parseMakeString(cond, args[1])
+ if bad, ok := xLeft.(*badExpr); ok {
+ return bad
}
+ if bad, ok := xRight.(*badExpr); ok {
+ return bad
+ }
+
+ if expr, ok := ctx.parseCompareSpecialCases(cond, xLeft, xRight); ok {
+ return expr
+ }
+
+ return &eqExpr{left: xLeft, right: xRight, isEq: isEq}
}
-func (ctx *parseContext) parseCheckFunctionCallResult(directive *mkparser.Directive, xValue starlarkExpr,
- varArg *mkparser.MakeString) (starlarkExpr, bool) {
- mkSingleVar, ok := varArg.SingleVariable()
- if !ok {
+// Given an if statement's directive and the left/right starlarkExprs,
+// check if the starlarkExprs are one of a few hardcoded special cases
+// that can be converted to a simpler equalify expression than simply comparing
+// the two.
+func (ctx *parseContext) parseCompareSpecialCases(directive *mkparser.Directive, left starlarkExpr,
+ right starlarkExpr) (starlarkExpr, bool) {
+ isEq := !strings.HasSuffix(directive.Name, "neq")
+
+ // All the special cases require a call on one side and a
+ // string literal/variable on the other. Turn the left/right variables into
+ // call/value variables, and return false if that's not possible.
+ var value starlarkExpr = nil
+ call, ok := left.(*callExpr)
+ if ok {
+ switch right.(type) {
+ case *stringLiteralExpr, *variableRefExpr:
+ value = right
+ }
+ } else {
+ call, _ = right.(*callExpr)
+ switch left.(type) {
+ case *stringLiteralExpr, *variableRefExpr:
+ value = left
+ }
+ }
+
+ if call == nil || value == nil {
return nil, false
}
- expr := ctx.parseReference(directive, mkSingleVar)
- negate := strings.HasSuffix(directive.Name, "neq")
+
checkIsSomethingFunction := func(xCall *callExpr) starlarkExpr {
- s, ok := maybeString(xValue)
+ s, ok := maybeString(value)
if !ok || s != "true" {
return ctx.newBadExpr(directive,
fmt.Sprintf("the result of %s can be compared only to 'true'", xCall.name))
@@ -1095,97 +1109,90 @@
}
return nil
}
- switch x := expr.(type) {
- case *callExpr:
- switch x.name {
- case "filter":
- return ctx.parseCompareFilterFuncResult(directive, x, xValue, !negate), true
- case "filter-out":
- return ctx.parseCompareFilterFuncResult(directive, x, xValue, negate), true
- case "wildcard":
- return ctx.parseCompareWildcardFuncResult(directive, x, xValue, negate), true
- case "findstring":
- return ctx.parseCheckFindstringFuncResult(directive, x, xValue, negate), true
- case "strip":
- return ctx.parseCompareStripFuncResult(directive, x, xValue, negate), true
- case "is-board-platform":
- if xBad := checkIsSomethingFunction(x); xBad != nil {
- return xBad, true
- }
- return &eqExpr{
- left: &variableRefExpr{ctx.addVariable("TARGET_BOARD_PLATFORM"), false},
- right: x.args[0],
- isEq: !negate,
- }, true
- case "is-board-platform-in-list":
- if xBad := checkIsSomethingFunction(x); xBad != nil {
- return xBad, true
- }
- return &inExpr{
- expr: &variableRefExpr{ctx.addVariable("TARGET_BOARD_PLATFORM"), false},
- list: maybeConvertToStringList(x.args[0]),
- isNot: negate,
- }, true
- case "is-product-in-list":
- if xBad := checkIsSomethingFunction(x); xBad != nil {
- return xBad, true
- }
- return &inExpr{
- expr: &variableRefExpr{ctx.addVariable("TARGET_PRODUCT"), true},
- list: maybeConvertToStringList(x.args[0]),
- isNot: negate,
- }, true
- case "is-vendor-board-platform":
- if xBad := checkIsSomethingFunction(x); xBad != nil {
- return xBad, true
- }
- s, ok := maybeString(x.args[0])
- if !ok {
- return ctx.newBadExpr(directive, "cannot handle non-constant argument to is-vendor-board-platform"), true
- }
- return &inExpr{
- expr: &variableRefExpr{ctx.addVariable("TARGET_BOARD_PLATFORM"), false},
- list: &variableRefExpr{ctx.addVariable(s + "_BOARD_PLATFORMS"), true},
- isNot: negate,
- }, true
- case "is-board-platform2", "is-board-platform-in-list2":
- if s, ok := maybeString(xValue); !ok || s != "" {
- return ctx.newBadExpr(directive,
- fmt.Sprintf("the result of %s can be compared only to empty", x.name)), true
- }
- if len(x.args) != 1 {
- return ctx.newBadExpr(directive, "%s requires an argument", x.name), true
- }
- cc := &callExpr{
- name: x.name,
- args: []starlarkExpr{x.args[0]},
- returnType: starlarkTypeBool,
- }
- if !negate {
- return ¬Expr{cc}, true
- }
- return cc, true
- case "is-vendor-board-qcom":
- if s, ok := maybeString(xValue); !ok || s != "" {
- return ctx.newBadExpr(directive,
- fmt.Sprintf("the result of %s can be compared only to empty", x.name)), true
- }
- // if the expression is ifneq (,$(call is-vendor-board-platform,...)), negate==true,
- // so we should set inExpr.isNot to false
- return &inExpr{
- expr: &variableRefExpr{ctx.addVariable("TARGET_BOARD_PLATFORM"), false},
- list: &variableRefExpr{ctx.addVariable("QCOM_BOARD_PLATFORMS"), true},
- isNot: !negate,
- }, true
- default:
- return ctx.newBadExpr(directive, "Unknown function in ifeq: %s", x.name), true
+ switch call.name {
+ case "filter":
+ return ctx.parseCompareFilterFuncResult(directive, call, value, isEq), true
+ case "filter-out":
+ return ctx.parseCompareFilterFuncResult(directive, call, value, !isEq), true
+ case "wildcard":
+ return ctx.parseCompareWildcardFuncResult(directive, call, value, !isEq), true
+ case "findstring":
+ return ctx.parseCheckFindstringFuncResult(directive, call, value, !isEq), true
+ case "strip":
+ return ctx.parseCompareStripFuncResult(directive, call, value, !isEq), true
+ case "is-board-platform":
+ if xBad := checkIsSomethingFunction(call); xBad != nil {
+ return xBad, true
}
- case *badExpr:
- return x, true
- default:
- return nil, false
+ return &eqExpr{
+ left: &variableRefExpr{ctx.addVariable("TARGET_BOARD_PLATFORM"), false},
+ right: call.args[0],
+ isEq: isEq,
+ }, true
+ case "is-board-platform-in-list":
+ if xBad := checkIsSomethingFunction(call); xBad != nil {
+ return xBad, true
+ }
+ return &inExpr{
+ expr: &variableRefExpr{ctx.addVariable("TARGET_BOARD_PLATFORM"), false},
+ list: maybeConvertToStringList(call.args[0]),
+ isNot: !isEq,
+ }, true
+ case "is-product-in-list":
+ if xBad := checkIsSomethingFunction(call); xBad != nil {
+ return xBad, true
+ }
+ return &inExpr{
+ expr: &variableRefExpr{ctx.addVariable("TARGET_PRODUCT"), true},
+ list: maybeConvertToStringList(call.args[0]),
+ isNot: !isEq,
+ }, true
+ case "is-vendor-board-platform":
+ if xBad := checkIsSomethingFunction(call); xBad != nil {
+ return xBad, true
+ }
+ s, ok := maybeString(call.args[0])
+ if !ok {
+ return ctx.newBadExpr(directive, "cannot handle non-constant argument to is-vendor-board-platform"), true
+ }
+ return &inExpr{
+ expr: &variableRefExpr{ctx.addVariable("TARGET_BOARD_PLATFORM"), false},
+ list: &variableRefExpr{ctx.addVariable(s + "_BOARD_PLATFORMS"), true},
+ isNot: !isEq,
+ }, true
+
+ case "is-board-platform2", "is-board-platform-in-list2":
+ if s, ok := maybeString(value); !ok || s != "" {
+ return ctx.newBadExpr(directive,
+ fmt.Sprintf("the result of %s can be compared only to empty", call.name)), true
+ }
+ if len(call.args) != 1 {
+ return ctx.newBadExpr(directive, "%s requires an argument", call.name), true
+ }
+ cc := &callExpr{
+ name: call.name,
+ args: []starlarkExpr{call.args[0]},
+ returnType: starlarkTypeBool,
+ }
+ if isEq {
+ return ¬Expr{cc}, true
+ }
+ return cc, true
+ case "is-vendor-board-qcom":
+ if s, ok := maybeString(value); !ok || s != "" {
+ return ctx.newBadExpr(directive,
+ fmt.Sprintf("the result of %s can be compared only to empty", call.name)), true
+ }
+ // if the expression is ifneq (,$(call is-vendor-board-platform,...)), negate==true,
+ // so we should set inExpr.isNot to false
+ return &inExpr{
+ expr: &variableRefExpr{ctx.addVariable("TARGET_BOARD_PLATFORM"), false},
+ list: &variableRefExpr{ctx.addVariable("QCOM_BOARD_PLATFORMS"), true},
+ isNot: isEq,
+ }, true
}
+ return nil, false
}
func (ctx *parseContext) parseCompareFilterFuncResult(cond *mkparser.Directive,
@@ -1545,18 +1552,14 @@
// records that the given node failed to be converted and includes an explanatory message
func (ctx *parseContext) errorf(failedNode mkparser.Node, message string, args ...interface{}) {
if ctx.errorLogger != nil {
- ctx.errorLogger.NewError(ctx.script.mkFile, ctx.script.nodeLocator(failedNode.Pos()), failedNode, message, args...)
+ ctx.errorLogger.NewError(ctx.errorLocation(failedNode), failedNode, message, args...)
}
- message = fmt.Sprintf(message, args...)
- ctx.insertComment(fmt.Sprintf("# MK2RBC TRANSLATION ERROR: %s", message))
- ctx.carryAsComment(failedNode)
-
+ ctx.receiver.newNode(&exprNode{ctx.newBadExpr(failedNode, message, args...)})
ctx.script.hasErrors = true
}
func (ctx *parseContext) wrapBadExpr(xBad *badExpr) {
- ctx.insertComment(fmt.Sprintf("# MK2RBC TRANSLATION ERROR: %s", xBad.message))
- ctx.carryAsComment(xBad.node)
+ ctx.receiver.newNode(&exprNode{xBad})
}
func (ctx *parseContext) loadedModulePath(path string) string {
@@ -1622,6 +1625,10 @@
return ok
}
+func (ctx *parseContext) errorLocation(node mkparser.Node) ErrorLocation {
+ return ErrorLocation{ctx.script.mkFile, ctx.script.nodeLocator(node.Pos())}
+}
+
func (ss *StarlarkScript) String() string {
return NewGenerateContext(ss).emit()
}
@@ -1660,14 +1667,13 @@
return nil, fmt.Errorf("bad makefile %s", req.MkFile)
}
starScript := &StarlarkScript{
- moduleName: moduleNameForFile(req.MkFile),
- mkFile: req.MkFile,
- topDir: req.RootDir,
- traceCalls: req.TraceCalls,
- warnPartialSuccess: req.WarnPartialSuccess,
- sourceFS: req.SourceFS,
- makefileFinder: req.MakefileFinder,
- nodeLocator: func(pos mkparser.Pos) int { return parser.Unpack(pos).Line },
+ moduleName: moduleNameForFile(req.MkFile),
+ mkFile: req.MkFile,
+ topDir: req.RootDir,
+ traceCalls: req.TraceCalls,
+ sourceFS: req.SourceFS,
+ makefileFinder: req.MakefileFinder,
+ nodeLocator: func(pos mkparser.Pos) int { return parser.Unpack(pos).Line },
}
ctx := newParseContext(starScript, nodes)
ctx.outputSuffix = req.OutputSuffix
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 1e79552..dfdf274 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -105,15 +105,12 @@
PRODUCT_NAME := $(call foo1, bar)
PRODUCT_NAME := $(call foo0)
`,
- expected: `# MK2RBC TRANSLATION ERROR: cannot handle invoking foo1
-# PRODUCT_NAME := $(call foo1, bar)
-# MK2RBC TRANSLATION ERROR: cannot handle invoking foo0
-# PRODUCT_NAME := $(call foo0)
-load("//build/make/core:product_config.rbc", "rblf")
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
def init(g, handle):
cfg = rblf.cfg(handle)
- rblf.warning("product.mk", "partially successful conversion")
+ rblf.mk2rbc_error("product.mk:2", "cannot handle invoking foo1")
+ rblf.mk2rbc_error("product.mk:3", "cannot handle invoking foo0")
`,
},
{
@@ -207,15 +204,11 @@
$(info foo)
endef
`,
- expected: `# MK2RBC TRANSLATION ERROR: define is not supported: some-macro
-# define some-macro
-# $(info foo)
-# endef
-load("//build/make/core:product_config.rbc", "rblf")
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
def init(g, handle):
cfg = rblf.cfg(handle)
- rblf.warning("product.mk", "partially successful conversion")
+ rblf.mk2rbc_error("product.mk:2", "define is not supported: some-macro")
`,
},
{
@@ -282,9 +275,7 @@
# Comment
pass
else:
- # MK2RBC TRANSLATION ERROR: cannot set predefined variable TARGET_COPY_OUT_RECOVERY to "foo", its value should be "recovery"
- pass
- rblf.warning("product.mk", "partially successful conversion")
+ rblf.mk2rbc_error("product.mk:5", "cannot set predefined variable TARGET_COPY_OUT_RECOVERY to \"foo\", its value should be \"recovery\"")
`,
},
{
@@ -353,6 +344,36 @@
`,
},
{
+ desc: "ifeq with soong_config_get",
+ mkname: "product.mk",
+ in: `
+ifeq (true,$(call soong_config_get,art_module,source_build))
+endif
+`,
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ if "true" == rblf.soong_config_get(g, "art_module", "source_build"):
+ pass
+`,
+ },
+ {
+ desc: "ifeq with $(NATIVE_COVERAGE)",
+ mkname: "product.mk",
+ in: `
+ifeq ($(NATIVE_COVERAGE),true)
+endif
+`,
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ if g.get("NATIVE_COVERAGE", False):
+ pass
+`,
+ },
+ {
desc: "Check filter result",
mkname: "product.mk",
in: `
@@ -515,6 +536,21 @@
`,
},
{
+ desc: "if with interpolation",
+ mkname: "product.mk",
+ in: `
+ifeq ($(VARIABLE1)text$(VARIABLE2),true)
+endif
+`,
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ if "%stext%s" % (g.get("VARIABLE1", ""), g.get("VARIABLE2", "")) == "true":
+ pass
+`,
+ },
+ {
desc: "ifneq $(X),true",
mkname: "product.mk",
in: `
@@ -659,6 +695,7 @@
$(call enforce-product-packages-exist, foo)
$(call require-artifacts-in-path, foo, bar)
$(call require-artifacts-in-path-relaxed, foo, bar)
+$(call dist-for-goals, goal, from:to)
`,
expected: `load("//build/make/core:product_config.rbc", "rblf")
@@ -668,6 +705,7 @@
rblf.enforce_product_packages_exist("foo")
rblf.require_artifacts_in_path("foo", "bar")
rblf.require_artifacts_in_path_relaxed("foo", "bar")
+ rblf.mkdist_for_goals(g, "goal", "from:to")
`,
},
{
@@ -827,9 +865,7 @@
rblf.soong_config_namespace(g, "cvd")
rblf.soong_config_set(g, "cvd", "launch_configs", "cvd_config_auto.json")
rblf.soong_config_append(g, "cvd", "grub_config", "grub.cfg")
- # MK2RBC TRANSLATION ERROR: SOONG_CONFIG_ variables cannot be referenced, use soong_config_get instead: SOONG_CONFIG_cvd_grub_config
- # x := $(SOONG_CONFIG_cvd_grub_config)
- rblf.warning("product.mk", "partially successful conversion")
+ rblf.mk2rbc_error("product.mk:7", "SOONG_CONFIG_ variables cannot be referenced, use soong_config_get instead: SOONG_CONFIG_cvd_grub_config")
`,
}, {
desc: "soong namespace accesses",
@@ -1016,15 +1052,11 @@
in: `
foo: foo.c
gcc -o $@ $*`,
- expected: `# MK2RBC TRANSLATION ERROR: unsupported line rule: foo: foo.c
-#gcc -o $@ $*
-# rule: foo: foo.c
-# gcc -o $@ $*
-load("//build/make/core:product_config.rbc", "rblf")
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
def init(g, handle):
cfg = rblf.cfg(handle)
- rblf.warning("product.mk", "partially successful conversion")
+ rblf.mk2rbc_error("product.mk:2", "unsupported line rule: foo: foo.c\n#gcc -o $@ $*")
`,
},
{
@@ -1032,14 +1064,27 @@
mkname: "product.mk",
in: `
override FOO:=`,
- expected: `# MK2RBC TRANSLATION ERROR: cannot handle override directive
-# override FOO :=
-load("//build/make/core:product_config.rbc", "rblf")
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
def init(g, handle):
cfg = rblf.cfg(handle)
+ rblf.mk2rbc_error("product.mk:2", "cannot handle override directive")
g["override FOO"] = ""
- rblf.warning("product.mk", "partially successful conversion")
+`,
+ },
+ {
+ desc: "Bad expression",
+ mkname: "build/product.mk",
+ in: `
+ifeq (,$(call foobar))
+endif
+`,
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ if rblf.mk2rbc_error("build/product.mk:2", "cannot handle invoking foobar"):
+ pass
`,
},
}
@@ -1049,6 +1094,7 @@
class varClass
starlarkType
}{
+ {"NATIVE_COVERAGE", VarClassSoong, starlarkTypeBool},
{"PRODUCT_NAME", VarClassConfig, starlarkTypeString},
{"PRODUCT_MODEL", VarClassConfig, starlarkTypeString},
{"PRODUCT_PACKAGES", VarClassConfig, starlarkTypeList},
@@ -1110,13 +1156,12 @@
t.Run(test.desc,
func(t *testing.T) {
ss, err := Convert(Request{
- MkFile: test.mkname,
- Reader: bytes.NewBufferString(test.in),
- RootDir: ".",
- OutputSuffix: ".star",
- WarnPartialSuccess: true,
- SourceFS: fs,
- MakefileFinder: &testMakefileFinder{fs: fs},
+ MkFile: test.mkname,
+ Reader: bytes.NewBufferString(test.in),
+ RootDir: ".",
+ OutputSuffix: ".star",
+ SourceFS: fs,
+ MakefileFinder: &testMakefileFinder{fs: fs},
})
if err != nil {
t.Error(err)
diff --git a/mk2rbc/node.go b/mk2rbc/node.go
index 3fe1a17..d38299d 100644
--- a/mk2rbc/node.go
+++ b/mk2rbc/node.go
@@ -183,6 +183,7 @@
value starlarkExpr
mkValue *mkparser.MakeString
flavor assignmentFlavor
+ location ErrorLocation
isTraced bool
previous *assignmentNode
}
@@ -223,18 +224,6 @@
}
gctx.newLine()
- if bad, ok := in.expr.(*badExpr); ok {
- gctx.write("# MK2STAR ERROR converting:")
- gctx.newLine()
- gctx.writef("# %s", bad.node.Dump())
- gctx.newLine()
- gctx.writef("# %s", bad.message)
- gctx.newLine()
- // The init function emits a warning if the conversion was not
- // fullly successful, so here we (arbitrarily) take the false path.
- gctx.writef("%sFalse:", ifElif)
- return
- }
gctx.write(ifElif)
in.expr.emit(gctx)
gctx.write(":")
diff --git a/mk2rbc/variable.go b/mk2rbc/variable.go
index ded07fe..6b67a7c 100644
--- a/mk2rbc/variable.go
+++ b/mk2rbc/variable.go
@@ -228,10 +228,9 @@
if actualValue == expectedValue {
return
}
- gctx.writef("# MK2RBC TRANSLATION ERROR: cannot set predefined variable %s to %q, its value should be %q",
- pv.name(), actualValue, expectedValue)
- gctx.newLine()
- gctx.write("pass")
+ gctx.emitConversionError(asgn.location,
+ fmt.Sprintf("cannot set predefined variable %s to %q, its value should be %q",
+ pv.name(), actualValue, expectedValue))
gctx.starScript.hasErrors = true
return
}
diff --git a/rust/Android.bp b/rust/Android.bp
index cda2dbc..5e14da8 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -38,6 +38,7 @@
"strip.go",
"test.go",
"testing.go",
+ "toolchain_library.go",
],
testSrcs: [
"benchmark_test.go",
diff --git a/rust/androidmk.go b/rust/androidmk.go
index c9f6486..1f18b4a 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -51,7 +51,7 @@
ret := android.AndroidMkEntries{
OutputFile: android.OptionalPathForPath(mod.UnstrippedOutputFile()),
- Include: "$(BUILD_SYSTEM)/soong_rust_prebuilt.mk",
+ Include: "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.AddStrings("LOCAL_RLIB_LIBRARIES", mod.Properties.AndroidMkRlibs...)
diff --git a/rust/rust.go b/rust/rust.go
index 3cc7868..b575c7a 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -393,6 +393,10 @@
WholeStaticLibs []string
HeaderLibs []string
+ // Used for data dependencies adjacent to tests
+ DataLibs []string
+ DataBins []string
+
CrtBegin, CrtEnd string
}
@@ -577,7 +581,7 @@
func (mod *Module) CcLibrary() bool {
if mod.compiler != nil {
- if _, ok := mod.compiler.(*libraryDecorator); ok {
+ if _, ok := mod.compiler.(libraryInterface); ok {
return true
}
}
@@ -982,6 +986,8 @@
procMacroDepTag = dependencyTag{name: "procMacro", procMacro: true}
testPerSrcDepTag = dependencyTag{name: "rust_unit_tests"}
sourceDepTag = dependencyTag{name: "source"}
+ dataLibDepTag = dependencyTag{name: "data lib"}
+ dataBinDepTag = dependencyTag{name: "data bin"}
)
func IsDylibDepTag(depTag blueprint.DependencyTag) bool {
@@ -1428,6 +1434,12 @@
}
}
+ actx.AddVariationDependencies([]blueprint.Variation{
+ {Mutator: "link", Variation: "shared"},
+ }, dataLibDepTag, deps.DataLibs...)
+
+ actx.AddVariationDependencies(nil, dataBinDepTag, deps.DataBins...)
+
// proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy.
actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), procMacroDepTag, deps.ProcMacros...)
}
@@ -1542,7 +1554,7 @@
// Overrides ApexModule.IsInstallabeToApex()
func (mod *Module) IsInstallableToApex() bool {
if mod.compiler != nil {
- if lib, ok := mod.compiler.(*libraryDecorator); ok && (lib.shared() || lib.dylib()) {
+ if lib, ok := mod.compiler.(libraryInterface); ok && (lib.shared() || lib.dylib()) {
return true
}
if _, ok := mod.compiler.(*binaryDecorator); ok {
diff --git a/rust/rust_test.go b/rust/rust_test.go
index b99b1e6..97bd541 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -79,8 +79,10 @@
}
const (
- sharedVendorVariant = "android_vendor.29_arm64_armv8-a_shared"
- rlibVendorVariant = "android_vendor.29_arm64_armv8-a_rlib_rlib-std"
+ 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"
)
func testRustVndkFs(t *testing.T, bp string, fs android.MockFS) *android.TestContext {
@@ -101,7 +103,22 @@
),
).RunTestWithBp(t, bp)
return result.TestContext
+}
+func testRustRecoveryFsVersions(t *testing.T, bp string, fs android.MockFS, device_version, vndk_version, recovery_version string) *android.TestContext {
+ skipTestIfOsNotSupported(t)
+ result := android.GroupFixturePreparers(
+ prepareForRustTest,
+ fs.AddToFixture(),
+ android.FixtureModifyProductVariables(
+ func(variables android.FixtureProductVariables) {
+ variables.DeviceVndkVersion = StringPtr(device_version)
+ variables.RecoverySnapshotVersion = StringPtr(recovery_version)
+ variables.Platform_vndk_version = StringPtr(vndk_version)
+ },
+ ),
+ ).RunTestWithBp(t, bp)
+ return result.TestContext
}
// testRustCov returns a TestContext in which a basic environment has been
diff --git a/rust/sanitize.go b/rust/sanitize.go
index fdb342d..be9dc42 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -144,7 +144,7 @@
// Global Sanitizers
if found, globalSanitizers = android.RemoveFromList("hwaddress", globalSanitizers); found && s.Hwaddress == nil {
- // TODO(b/180495975): HWASan for static Rust binaries isn't supported yet.
+ // TODO(b/204776996): HWASan for static Rust binaries isn't supported yet.
if !ctx.RustModule().StaticExecutable() {
s.Hwaddress = proptools.BoolPtr(true)
}
@@ -161,7 +161,10 @@
}
if found, globalSanitizers = android.RemoveFromList("fuzzer", globalSanitizers); found && s.Fuzzer == nil {
- s.Fuzzer = proptools.BoolPtr(true)
+ // TODO(b/204776996): HWASan for static Rust binaries isn't supported yet, and fuzzer enables HWAsan
+ if !ctx.RustModule().StaticExecutable() {
+ s.Fuzzer = proptools.BoolPtr(true)
+ }
}
// Global Diag Sanitizers
@@ -237,12 +240,10 @@
} else {
flags.RustFlags = append(flags.RustFlags, asanFlags...)
}
- }
- if Bool(sanitize.Properties.Sanitize.Address) {
- flags.RustFlags = append(flags.RustFlags, asanFlags...)
- }
- if Bool(sanitize.Properties.Sanitize.Hwaddress) {
+ } else if Bool(sanitize.Properties.Sanitize.Hwaddress) {
flags.RustFlags = append(flags.RustFlags, hwasanFlags...)
+ } else if Bool(sanitize.Properties.Sanitize.Address) {
+ flags.RustFlags = append(flags.RustFlags, asanFlags...)
}
return flags, deps
}
@@ -289,7 +290,7 @@
deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan")}
} else if mod.IsSanitizerEnabled(cc.Hwasan) ||
(mod.IsSanitizerEnabled(cc.Fuzzer) && mctx.Arch().ArchType == android.Arm64) {
- // TODO(b/180495975): HWASan for static Rust binaries isn't supported yet.
+ // TODO(b/204776996): HWASan for static Rust binaries isn't supported yet.
if binary, ok := mod.compiler.(binaryInterface); ok {
if binary.staticallyLinked() {
mctx.ModuleErrorf("HWASan is not supported for static Rust executables yet.")
diff --git a/rust/test.go b/rust/test.go
index bb877a9..3eea0ad 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -18,6 +18,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/cc"
"android/soong/tradefed"
)
@@ -49,6 +50,12 @@
// the test
Data []string `android:"path,arch_variant"`
+ // list of shared library modules that should be installed alongside the test
+ Data_libs []string `android:"arch_variant"`
+
+ // list of binary modules that should be installed alongside the test
+ Data_bins []string `android:"arch_variant"`
+
// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
// explicitly.
@@ -137,6 +144,32 @@
dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data)
+ ctx.VisitDirectDepsWithTag(dataLibDepTag, func(dep android.Module) {
+ depName := ctx.OtherModuleName(dep)
+ linkableDep, ok := dep.(cc.LinkableInterface)
+ if !ok {
+ ctx.ModuleErrorf("data_lib %q is not a linkable module", depName)
+ }
+ if linkableDep.OutputFile().Valid() {
+ test.data = append(test.data,
+ android.DataPath{SrcPath: linkableDep.OutputFile().Path(),
+ RelativeInstallPath: linkableDep.RelativeInstallPath()})
+ }
+ })
+
+ ctx.VisitDirectDepsWithTag(dataBinDepTag, func(dep android.Module) {
+ depName := ctx.OtherModuleName(dep)
+ linkableDep, ok := dep.(cc.LinkableInterface)
+ if !ok {
+ ctx.ModuleErrorf("data_bin %q is not a linkable module", depName)
+ }
+ if linkableDep.OutputFile().Valid() {
+ test.data = append(test.data,
+ android.DataPath{SrcPath: linkableDep.OutputFile().Path(),
+ RelativeInstallPath: linkableDep.RelativeInstallPath()})
+ }
+ })
+
for _, dataSrcPath := range dataSrcPaths {
test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath})
}
@@ -194,6 +227,9 @@
deps.Rustlibs = append(deps.Rustlibs, "libtest")
+ deps.DataLibs = append(deps.DataLibs, test.Properties.Data_libs...)
+ deps.DataBins = append(deps.DataBins, test.Properties.Data_bins...)
+
return deps
}
diff --git a/rust/test_test.go b/rust/test_test.go
index 892761a..1124176 100644
--- a/rust/test_test.go
+++ b/rust/test_test.go
@@ -74,3 +74,129 @@
t.Errorf("Device rust_test module 'my_test' does not link libstd as an rlib")
}
}
+
+func TestDataLibs(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "test_lib",
+ srcs: ["test_lib.cpp"],
+ }
+
+ rust_binary {
+ name: "rusty",
+ srcs: ["foo.rs"],
+ compile_multilib: "both",
+ }
+
+ rust_ffi {
+ name: "librust_test_lib",
+ crate_name: "rust_test_lib",
+ srcs: ["test_lib.rs"],
+ relative_install_path: "foo/bar/baz",
+ compile_multilib: "64",
+ }
+
+ rust_test {
+ name: "main_test",
+ srcs: ["foo.rs"],
+ data_libs: ["test_lib"],
+ data_bins: ["rusty"],
+ }
+ `
+
+ ctx := testRust(t, bp)
+
+ module := ctx.ModuleForTests("main_test", "android_arm64_armv8-a").Module()
+ testBinary := module.(*Module).compiler.(*testDecorator)
+ outputFiles, err := module.(android.OutputFileProducer).OutputFiles("")
+ if err != nil {
+ t.Fatalf("Expected rust_test to produce output files, error: %s", err)
+ }
+ if len(outputFiles) != 1 {
+ t.Fatalf("expected exactly one output file. output files: [%s]", outputFiles)
+ }
+ if len(testBinary.dataPaths()) != 2 {
+ t.Fatalf("expected exactly two test data files. test data files: [%s]", testBinary.dataPaths())
+ }
+
+ outputPath := outputFiles[0].String()
+ dataLibraryPath := testBinary.dataPaths()[0].SrcPath.String()
+ dataBinaryPath := testBinary.dataPaths()[1].SrcPath.String()
+
+ if !strings.HasSuffix(outputPath, "/main_test") {
+ t.Errorf("expected test output file to be 'main_test', but was '%s'", outputPath)
+ }
+ if !strings.HasSuffix(dataLibraryPath, "/test_lib.so") {
+ t.Errorf("expected test data file to be 'test_lib.so', but was '%s'", dataLibraryPath)
+ }
+ if !strings.HasSuffix(dataBinaryPath, "/rusty") {
+ t.Errorf("expected test data file to be 'test_lib.so', but was '%s'", dataBinaryPath)
+ }
+}
+
+func TestDataLibsRelativeInstallPath(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "test_lib",
+ srcs: ["test_lib.cpp"],
+ relative_install_path: "foo/bar/baz",
+ compile_multilib: "64",
+ }
+
+ rust_ffi {
+ name: "librust_test_lib",
+ crate_name: "rust_test_lib",
+ srcs: ["test_lib.rs"],
+ relative_install_path: "foo/bar/baz",
+ compile_multilib: "64",
+ }
+
+ rust_binary {
+ name: "rusty",
+ srcs: ["foo.rs"],
+ relative_install_path: "foo/bar/baz",
+ compile_multilib: "64",
+ }
+
+ rust_test {
+ name: "main_test",
+ srcs: ["foo.rs"],
+ data_libs: ["test_lib", "librust_test_lib"],
+ data_bins: ["rusty"],
+ compile_multilib: "64",
+ }
+ `
+
+ ctx := testRust(t, bp)
+ module := ctx.ModuleForTests("main_test", "android_arm64_armv8-a").Module()
+ testBinary := module.(*Module).compiler.(*testDecorator)
+ outputFiles, err := module.(android.OutputFileProducer).OutputFiles("")
+ if err != nil {
+ t.Fatalf("Expected rust_test to produce output files, error: %s", err)
+ }
+ if len(outputFiles) != 1 {
+ t.Fatalf("expected exactly one output file. output files: [%s]", outputFiles)
+ }
+ if len(testBinary.dataPaths()) != 3 {
+ t.Fatalf("expected exactly two test data files. test data files: [%s]", testBinary.dataPaths())
+ }
+
+ outputPath := outputFiles[0].String()
+
+ if !strings.HasSuffix(outputPath, "/main_test") {
+ t.Errorf("expected test output file to be 'main_test', but was '%s'", outputPath)
+ }
+ entries := android.AndroidMkEntriesForTest(t, ctx, module)[0]
+ if !strings.HasSuffix(entries.EntryMap["LOCAL_TEST_DATA"][0], ":test_lib.so:foo/bar/baz") {
+ t.Errorf("expected LOCAL_TEST_DATA to end with `:test_lib.so:foo/bar/baz`,"+
+ " but was '%s'", entries.EntryMap["LOCAL_TEST_DATA"][0])
+ }
+ if !strings.HasSuffix(entries.EntryMap["LOCAL_TEST_DATA"][1], ":librust_test_lib.so:foo/bar/baz") {
+ t.Errorf("expected LOCAL_TEST_DATA to end with `:librust_test_lib.so:foo/bar/baz`,"+
+ " but was '%s'", entries.EntryMap["LOCAL_TEST_DATA"][1])
+ }
+ if !strings.HasSuffix(entries.EntryMap["LOCAL_TEST_DATA"][2], ":rusty:foo/bar/baz") {
+ t.Errorf("expected LOCAL_TEST_DATA to end with `:rusty:foo/bar/baz`,"+
+ " but was '%s'", entries.EntryMap["LOCAL_TEST_DATA"][2])
+ }
+}
diff --git a/rust/testing.go b/rust/testing.go
index 9f8ed54..1b34dfe 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -75,6 +75,7 @@
apex_available: ["//apex_available:platform", "//apex_available:anyapex"],
min_sdk_version: "29",
vendor_available: true,
+ recovery_available: true,
llndk: {
symbol_file: "liblog.map.txt",
},
@@ -106,6 +107,7 @@
host_supported: true,
vendor_available: true,
vendor_ramdisk_available: true,
+ recovery_available: true,
native_coverage: false,
sysroot: true,
apex_available: ["//apex_available:platform", "//apex_available:anyapex"],
@@ -118,6 +120,7 @@
host_supported: true,
vendor_available: true,
vendor_ramdisk_available: true,
+ recovery_available: true,
native_coverage: false,
apex_available: ["//apex_available:platform", "//apex_available:anyapex"],
min_sdk_version: "29",
diff --git a/rust/toolchain_library.go b/rust/toolchain_library.go
new file mode 100644
index 0000000..326d529
--- /dev/null
+++ b/rust/toolchain_library.go
@@ -0,0 +1,103 @@
+//
+// Copyright (C) 2021 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.
+//
+
+package rust
+
+import (
+ "path"
+
+ "android/soong/android"
+ "android/soong/rust/config"
+)
+
+// This module is used to compile the rust toolchain libraries
+// When RUST_PREBUILTS_VERSION is set, the library will generated
+// from the given Rust version.
+func init() {
+ android.RegisterModuleType("rust_toolchain_library",
+ rustToolchainLibraryFactory)
+ android.RegisterModuleType("rust_toolchain_library_rlib",
+ rustToolchainLibraryRlibFactory)
+ android.RegisterModuleType("rust_toolchain_library_dylib",
+ rustToolchainLibraryDylibFactory)
+}
+
+type toolchainLibraryProperties struct {
+ // path to the toolchain source, relative to the top of the toolchain source
+ Toolchain_src *string `android:"arch_variant"`
+}
+
+type toolchainLibraryDecorator struct {
+ *libraryDecorator
+ Properties toolchainLibraryProperties
+}
+
+// rust_toolchain_library produces all rust variants.
+func rustToolchainLibraryFactory() android.Module {
+ module, library := NewRustLibrary(android.HostAndDeviceSupported)
+ library.BuildOnlyRust()
+
+ return initToolchainLibrary(module, library)
+}
+
+// rust_toolchain_library_dylib produces a dylib.
+func rustToolchainLibraryDylibFactory() android.Module {
+ module, library := NewRustLibrary(android.HostAndDeviceSupported)
+ library.BuildOnlyDylib()
+
+ return initToolchainLibrary(module, library)
+}
+
+// rust_toolchain_library_rlib produces an rlib.
+func rustToolchainLibraryRlibFactory() android.Module {
+ module, library := NewRustLibrary(android.HostAndDeviceSupported)
+ library.BuildOnlyRlib()
+
+ return initToolchainLibrary(module, library)
+}
+
+func initToolchainLibrary(module *Module, library *libraryDecorator) android.Module {
+ toolchainLibrary := &toolchainLibraryDecorator{
+ libraryDecorator: library,
+ }
+ module.compiler = toolchainLibrary
+ module.AddProperties(&toolchainLibrary.Properties)
+ android.AddLoadHook(module, rustSetToolchainSource)
+
+ return module.Init()
+}
+
+func rustSetToolchainSource(ctx android.LoadHookContext) {
+ if toolchainLib, ok := ctx.Module().(*Module).compiler.(*toolchainLibraryDecorator); ok {
+ prefix := "linux-x86/" + GetRustPrebuiltVersion(ctx)
+ newSrcs := []string{path.Join(prefix, android.String(toolchainLib.Properties.Toolchain_src))}
+
+ type props struct {
+ Srcs []string
+ }
+ p := &props{}
+ p.Srcs = newSrcs
+ ctx.AppendProperties(p)
+
+ } else {
+ ctx.ModuleErrorf("Called rustSetToolchainSource on a non-Rust Module.")
+ }
+}
+
+// GetRustPrebuiltVersion returns the RUST_PREBUILTS_VERSION env var, or the default version if it is not defined.
+func GetRustPrebuiltVersion(ctx android.LoadHookContext) string {
+ return ctx.AConfig().GetenvWithDefault("RUST_PREBUILTS_VERSION", config.RustDefaultVersion)
+}
diff --git a/rust/vendor_snapshot_test.go b/rust/vendor_snapshot_test.go
index bfa6f36..03bd867 100644
--- a/rust/vendor_snapshot_test.go
+++ b/rust/vendor_snapshot_test.go
@@ -1028,3 +1028,354 @@
t.Errorf("wanted memtag_binary AndroidMkStaticLibs %q, got %q", w, g)
}
}
+
+func TestRecoverySnapshotCapture(t *testing.T) {
+ bp := `
+ rust_ffi {
+ name: "librecovery",
+ recovery: true,
+ srcs: ["foo.rs"],
+ crate_name: "recovery",
+ }
+
+ rust_ffi {
+ name: "librecovery_available",
+ recovery_available: true,
+ srcs: ["foo.rs"],
+ crate_name: "recovery_available",
+ }
+
+ rust_library_rlib {
+ name: "librecovery_rlib",
+ recovery: true,
+ srcs: ["foo.rs"],
+ crate_name: "recovery_rlib",
+ }
+
+ rust_library_rlib {
+ name: "librecovery_available_rlib",
+ recovery_available: true,
+ srcs: ["foo.rs"],
+ crate_name: "recovery_available_rlib",
+ }
+
+ rust_binary {
+ name: "recovery_bin",
+ recovery: true,
+ srcs: ["foo.rs"],
+ }
+
+ rust_binary {
+ name: "recovery_available_bin",
+ recovery_available: true,
+ srcs: ["foo.rs"],
+ }
+
+`
+ // Check Recovery snapshot output.
+
+ ctx := testRustRecoveryFsVersions(t, bp, rustMockedFiles, "", "29", "current")
+ snapshotDir := "recovery-snapshot"
+ snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
+
+ var jsonFiles []string
+
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
+
+ // For shared libraries, all recovery:true and recovery_available modules are captured.
+ sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(sharedDir, "librecovery.so.json"),
+ filepath.Join(sharedDir, "librecovery_available.so.json"))
+
+ // For static libraries, all recovery:true and recovery_available modules are captured.
+ staticVariant := fmt.Sprintf("android_recovery_%s_%s_static", archType, archVariant)
+ staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.a", staticDir, staticVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.a", staticDir, staticVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(staticDir, "librecovery.a.json"),
+ 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)
+ 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)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(rlibDir, "librecovery_rlib.rlib.json"),
+ filepath.Join(rlibDir, "librecovery_available_rlib.rlib.json"))
+
+ // For binary executables, all recovery:true and recovery_available modules are captured.
+ if archType == "arm64" {
+ binaryVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant)
+ binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "recovery_bin", "recovery_bin", binaryDir, binaryVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "recovery_available_bin", "recovery_available_bin", binaryDir, binaryVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(binaryDir, "recovery_bin.json"),
+ filepath.Join(binaryDir, "recovery_available_bin.json"))
+ }
+ }
+
+ for _, jsonFile := range jsonFiles {
+ // verify all json files exist
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("%q expected but not found", jsonFile)
+ }
+ }
+}
+
+func TestRecoverySnapshotExclude(t *testing.T) {
+ // This test verifies that the exclude_from_recovery_snapshot property
+ // makes its way from the Android.bp source file into the module data
+ // structure. It also verifies that modules are correctly included or
+ // excluded in the recovery snapshot based on their path (framework or
+ // vendor) and the exclude_from_recovery_snapshot property.
+
+ frameworkBp := `
+ rust_ffi_shared {
+ name: "libinclude",
+ srcs: ["src/include.rs"],
+ recovery_available: true,
+ crate_name: "include",
+ }
+ rust_ffi_shared {
+ name: "libexclude",
+ srcs: ["src/exclude.rs"],
+ recovery: true,
+ exclude_from_recovery_snapshot: true,
+ crate_name: "exclude",
+ }
+ rust_ffi_shared {
+ name: "libavailable_exclude",
+ srcs: ["src/exclude.rs"],
+ recovery_available: true,
+ exclude_from_recovery_snapshot: true,
+ crate_name: "available_exclude",
+ }
+ rust_library_rlib {
+ name: "libinclude_rlib",
+ srcs: ["src/include.rs"],
+ recovery_available: true,
+ crate_name: "include_rlib",
+ }
+ rust_library_rlib {
+ name: "libexclude_rlib",
+ srcs: ["src/exclude.rs"],
+ recovery: true,
+ exclude_from_recovery_snapshot: true,
+ crate_name: "exclude_rlib",
+ }
+ rust_library_rlib {
+ name: "libavailable_exclude_rlib",
+ srcs: ["src/exclude.rs"],
+ recovery_available: true,
+ exclude_from_recovery_snapshot: true,
+ crate_name: "available_exclude_rlib",
+ }
+ `
+
+ vendorProprietaryBp := `
+ rust_ffi_shared {
+ name: "librecovery",
+ srcs: ["recovery.rs"],
+ recovery: true,
+ crate_name: "recovery",
+ }
+ rust_library_rlib {
+ name: "librecovery_rlib",
+ srcs: ["recovery.rs"],
+ recovery: true,
+ crate_name: "recovery_rlib",
+ }
+ `
+
+ mockFS := map[string][]byte{
+ "framework/Android.bp": []byte(frameworkBp),
+ "framework/include.rs": nil,
+ "framework/exclude.rs": nil,
+ "device/Android.bp": []byte(vendorProprietaryBp),
+ "device/recovery.rs": nil,
+ }
+
+ ctx := testRustRecoveryFsVersions(t, "", mockFS, "", "29", "current")
+
+ // Test an include and exclude framework module.
+ 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)
+
+ // 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)
+
+ // Verify the content of the recovery snapshot.
+
+ snapshotDir := "recovery-snapshot"
+ snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
+
+ var includeJsonFiles []string
+ var excludeJsonFiles []string
+
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ 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)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+ rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
+
+ // 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"))
+
+ // Excluded modules
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
+ 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"))
+ }
+
+ // Verify that each json file for an included module has a rule.
+ for _, jsonFile := range includeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("include json file %q not found", jsonFile)
+ }
+ }
+
+ // Verify that each json file for an excluded module has no rule.
+ for _, jsonFile := range excludeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
+ t.Errorf("exclude json file %q found", jsonFile)
+ }
+ }
+}
+
+func TestRecoverySnapshotDirected(t *testing.T) {
+ bp := `
+ rust_ffi_shared {
+ name: "librecovery",
+ recovery: true,
+ crate_name: "recovery",
+ srcs: ["foo.rs"],
+ }
+
+ rust_ffi_shared {
+ name: "librecovery_available",
+ recovery_available: true,
+ crate_name: "recovery_available",
+ srcs: ["foo.rs"],
+ }
+
+ rust_library_rlib {
+ name: "librecovery_rlib",
+ recovery: true,
+ crate_name: "recovery",
+ srcs: ["foo.rs"],
+ }
+
+ rust_library_rlib {
+ name: "librecovery_available_rlib",
+ recovery_available: true,
+ crate_name: "recovery_available",
+ srcs: ["foo.rs"],
+ }
+
+ /* TODO: Uncomment when Rust supports the "prefer" property for prebuilts
+ rust_library_rlib {
+ name: "libfoo_rlib",
+ recovery: true,
+ crate_name: "foo",
+ }
+
+ rust_prebuilt_rlib {
+ name: "libfoo_rlib",
+ recovery: true,
+ prefer: true,
+ srcs: ["libfoo.rlib"],
+ crate_name: "foo",
+ }
+ */
+`
+ 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.DirectedRecoverySnapshot = true
+
+ // Check recovery snapshot output.
+ snapshotDir := "recovery-snapshot"
+ snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
+
+ var includeJsonFiles []string
+
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ 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)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+ rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
+
+ // 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"))
+
+ // TODO: When Rust supports the "prefer" property for prebuilts, perform this check.
+ /*
+ // Check that snapshot captures "prefer: true" prebuilt
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo_rlib", "libfoo_rlib.rlib", rlibDir, rlibVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo_rlib.rlib.json"))
+ */
+
+ // Excluded modules. Modules not included in the directed recovery snapshot
+ // 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"))
+ }
+
+ // Verify that each json file for an included module has a rule.
+ for _, jsonFile := range includeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("include json file %q not found, %#v", jsonFile, includeJsonFiles)
+ }
+ }
+}
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index f183c05..1e3f6ce 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -17,7 +17,6 @@
MODULES_SDK_AND_EXPORTS=(
art-module-sdk
art-module-test-exports
- compos-module-sdk
conscrypt-module-host-exports
conscrypt-module-sdk
conscrypt-module-test-exports
diff --git a/scripts/update_out b/scripts/update_out
new file mode 100755
index 0000000..d3950cf
--- /dev/null
+++ b/scripts/update_out
@@ -0,0 +1,21 @@
+#! /bin/bash
+# Run given command application and update the contents of a given file.
+# Will not change the file if its contents has not changed.
+[[ $# -gt 1 ]] || { echo "Usage: ${0##*/} FILE COMMAND" >&2; exit 1; }
+set -u
+declare -r outfile="$1"
+shift
+if [[ ! -f $outfile ]]; then
+ $@ >$outfile
+ exit
+fi
+
+declare -r newout=${outfile}.new
+$@ >$newout
+rc=$?
+if cmp -s $newout $outfile; then
+ rm $newout
+else
+ mv -f $newout $outfile
+fi
+exit $rc
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index d5033ef..c32cde0 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -284,7 +284,7 @@
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "EXECUTABLES",
OutputFile: android.OptionalPathForPath(s.outputFilePath),
- Include: "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
+ Include: "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
s.customAndroidMkEntries(entries)
@@ -433,7 +433,7 @@
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "NATIVE_TESTS",
OutputFile: android.OptionalPathForPath(s.outputFilePath),
- Include: "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
+ Include: "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
s.customAndroidMkEntries(entries)
diff --git a/ui/metrics/Android.bp b/ui/metrics/Android.bp
index 1590ab0..96f6389 100644
--- a/ui/metrics/Android.bp
+++ b/ui/metrics/Android.bp
@@ -23,6 +23,7 @@
"golang-protobuf-proto",
"soong-ui-metrics_upload_proto",
"soong-ui-metrics_proto",
+ "soong-ui-bp2build_metrics_proto",
"soong-ui-tracer",
],
srcs: [
@@ -57,3 +58,15 @@
"upload_proto/upload.pb.go",
],
}
+
+bootstrap_go_package {
+ name: "soong-ui-bp2build_metrics_proto",
+ pkgPath: "android/soong/ui/metrics/bp2build_metrics_proto",
+ deps: [
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ ],
+ srcs: [
+ "bp2build_metrics_proto/bp2build_metrics.pb.go",
+ ],
+}
diff --git a/ui/metrics/bp2build_metrics_proto/bp2build_metrics.pb.go b/ui/metrics/bp2build_metrics_proto/bp2build_metrics.pb.go
new file mode 100644
index 0000000..11177e4
--- /dev/null
+++ b/ui/metrics/bp2build_metrics_proto/bp2build_metrics.pb.go
@@ -0,0 +1,222 @@
+// Copyright 2021 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.27.1
+// protoc v3.9.1
+// source: bp2build_metrics.proto
+
+package bp2build_metrics_proto
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type Bp2BuildMetrics struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Total number of Soong modules converted to generated targets
+ GeneratedModuleCount uint64 `protobuf:"varint,1,opt,name=generatedModuleCount,proto3" json:"generatedModuleCount,omitempty"`
+ // Total number of Soong modules converted to handcrafted targets
+ HandCraftedModuleCount uint64 `protobuf:"varint,2,opt,name=handCraftedModuleCount,proto3" json:"handCraftedModuleCount,omitempty"`
+ // Total number of unconverted Soong modules
+ UnconvertedModuleCount uint64 `protobuf:"varint,3,opt,name=unconvertedModuleCount,proto3" json:"unconvertedModuleCount,omitempty"`
+ // Counts of generated Bazel targets per Bazel rule class
+ RuleClassCount map[string]uint64 `protobuf:"bytes,4,rep,name=ruleClassCount,proto3" json:"ruleClassCount,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
+ // List of converted modules
+ ConvertedModules []string `protobuf:"bytes,5,rep,name=convertedModules,proto3" json:"convertedModules,omitempty"`
+}
+
+func (x *Bp2BuildMetrics) Reset() {
+ *x = Bp2BuildMetrics{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_bp2build_metrics_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Bp2BuildMetrics) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Bp2BuildMetrics) ProtoMessage() {}
+
+func (x *Bp2BuildMetrics) ProtoReflect() protoreflect.Message {
+ mi := &file_bp2build_metrics_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Bp2BuildMetrics.ProtoReflect.Descriptor instead.
+func (*Bp2BuildMetrics) Descriptor() ([]byte, []int) {
+ return file_bp2build_metrics_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Bp2BuildMetrics) GetGeneratedModuleCount() uint64 {
+ if x != nil {
+ return x.GeneratedModuleCount
+ }
+ return 0
+}
+
+func (x *Bp2BuildMetrics) GetHandCraftedModuleCount() uint64 {
+ if x != nil {
+ return x.HandCraftedModuleCount
+ }
+ return 0
+}
+
+func (x *Bp2BuildMetrics) GetUnconvertedModuleCount() uint64 {
+ if x != nil {
+ return x.UnconvertedModuleCount
+ }
+ return 0
+}
+
+func (x *Bp2BuildMetrics) GetRuleClassCount() map[string]uint64 {
+ if x != nil {
+ return x.RuleClassCount
+ }
+ return nil
+}
+
+func (x *Bp2BuildMetrics) GetConvertedModules() []string {
+ if x != nil {
+ return x.ConvertedModules
+ }
+ return nil
+}
+
+var File_bp2build_metrics_proto protoreflect.FileDescriptor
+
+var file_bp2build_metrics_proto_rawDesc = []byte{
+ 0x0a, 0x16, 0x62, 0x70, 0x32, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f,
+ 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x62, 0x70, 0x32, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x8f, 0x03, 0x0a, 0x0f, 0x42, 0x70, 0x32, 0x42, 0x75,
+ 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x32, 0x0a, 0x14, 0x67, 0x65,
+ 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x75,
+ 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61,
+ 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x36,
+ 0x0a, 0x16, 0x68, 0x61, 0x6e, 0x64, 0x43, 0x72, 0x61, 0x66, 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x64,
+ 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16,
+ 0x68, 0x61, 0x6e, 0x64, 0x43, 0x72, 0x61, 0x66, 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c,
+ 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x36, 0x0a, 0x16, 0x75, 0x6e, 0x63, 0x6f, 0x6e, 0x76,
+ 0x65, 0x72, 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x75, 0x6e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72,
+ 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x69,
+ 0x0a, 0x0e, 0x72, 0x75, 0x6c, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+ 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62,
+ 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x62, 0x70, 0x32, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x42, 0x70, 0x32, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x43,
+ 0x6f, 0x75, 0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x72, 0x75, 0x6c, 0x65, 0x43,
+ 0x6c, 0x61, 0x73, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x6f, 0x6e,
+ 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x05, 0x20,
+ 0x03, 0x28, 0x09, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x4d, 0x6f,
+ 0x64, 0x75, 0x6c, 0x65, 0x73, 0x1a, 0x41, 0x0a, 0x13, 0x52, 0x75, 0x6c, 0x65, 0x43, 0x6c, 0x61,
+ 0x73, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
+ 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14,
+ 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76,
+ 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x31, 0x5a, 0x2f, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x2f, 0x62, 0x70, 0x32, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_bp2build_metrics_proto_rawDescOnce sync.Once
+ file_bp2build_metrics_proto_rawDescData = file_bp2build_metrics_proto_rawDesc
+)
+
+func file_bp2build_metrics_proto_rawDescGZIP() []byte {
+ file_bp2build_metrics_proto_rawDescOnce.Do(func() {
+ file_bp2build_metrics_proto_rawDescData = protoimpl.X.CompressGZIP(file_bp2build_metrics_proto_rawDescData)
+ })
+ return file_bp2build_metrics_proto_rawDescData
+}
+
+var file_bp2build_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_bp2build_metrics_proto_goTypes = []interface{}{
+ (*Bp2BuildMetrics)(nil), // 0: soong_build_bp2build_metrics.Bp2BuildMetrics
+ nil, // 1: soong_build_bp2build_metrics.Bp2BuildMetrics.RuleClassCountEntry
+}
+var file_bp2build_metrics_proto_depIdxs = []int32{
+ 1, // 0: soong_build_bp2build_metrics.Bp2BuildMetrics.ruleClassCount:type_name -> soong_build_bp2build_metrics.Bp2BuildMetrics.RuleClassCountEntry
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_bp2build_metrics_proto_init() }
+func file_bp2build_metrics_proto_init() {
+ if File_bp2build_metrics_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_bp2build_metrics_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Bp2BuildMetrics); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_bp2build_metrics_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_bp2build_metrics_proto_goTypes,
+ DependencyIndexes: file_bp2build_metrics_proto_depIdxs,
+ MessageInfos: file_bp2build_metrics_proto_msgTypes,
+ }.Build()
+ File_bp2build_metrics_proto = out.File
+ file_bp2build_metrics_proto_rawDesc = nil
+ file_bp2build_metrics_proto_goTypes = nil
+ file_bp2build_metrics_proto_depIdxs = nil
+}
diff --git a/ui/metrics/bp2build_metrics_proto/bp2build_metrics.proto b/ui/metrics/bp2build_metrics_proto/bp2build_metrics.proto
new file mode 100644
index 0000000..5e88966
--- /dev/null
+++ b/ui/metrics/bp2build_metrics_proto/bp2build_metrics.proto
@@ -0,0 +1,35 @@
+// Copyright 2021 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.
+
+syntax = "proto3";
+
+package soong_build_bp2build_metrics;
+option go_package = "android/soong/ui/metrics/bp2build_metrics_proto";
+
+message Bp2BuildMetrics {
+ // Total number of Soong modules converted to generated targets
+ uint64 generatedModuleCount = 1;
+
+ // Total number of Soong modules converted to handcrafted targets
+ uint64 handCraftedModuleCount = 2;
+
+ // Total number of unconverted Soong modules
+ uint64 unconvertedModuleCount = 3;
+
+ // Counts of generated Bazel targets per Bazel rule class
+ map<string, uint64> ruleClassCount = 4;
+
+ // List of converted modules
+ repeated string convertedModules = 5;
+}
diff --git a/ui/metrics/bp2build_metrics_proto/regen.sh b/ui/metrics/bp2build_metrics_proto/regen.sh
new file mode 100755
index 0000000..bfe4294
--- /dev/null
+++ b/ui/metrics/bp2build_metrics_proto/regen.sh
@@ -0,0 +1,29 @@
+#!/bin/bash -e
+
+# Copyright 2021 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.
+
+# Generates the golang source file of bp2build_metrics.proto protobuf file.
+
+function die() { echo "ERROR: $1" >&2; exit 1; }
+
+readonly error_msg="Maybe you need to run 'lunch aosp_arm-eng && m aprotoc blueprint_tools'?"
+
+if ! hash aprotoc &>/dev/null; then
+ die "could not find aprotoc. ${error_msg}"
+fi
+
+if ! aprotoc --go_out=paths=source_relative:. bp2build_metrics.proto; then
+ die "build failed. ${error_msg}"
+fi