Merge "Revert "Revert "Add static_libs support to android_app bp2build converter."""
diff --git a/OWNERS b/OWNERS
index f0ccd82..937a243 100644
--- a/OWNERS
+++ b/OWNERS
@@ -7,12 +7,15 @@
asmundak@google.com
ccross@android.com
cparsons@google.com
+delmerico@google.com
dwillemsen@google.com
eakammer@google.com
jobredeaux@google.com
joeo@google.com
lamontjones@google.com
spandandas@google.com
+tradical@google.com
+usta@google.com
weiwli@google.com
yudiliu@google.com
yuntaoxu@google.com
diff --git a/README.md b/README.md
index b820fd1..127c52c 100644
--- a/README.md
+++ b/README.md
@@ -452,10 +452,9 @@
The values of the variables can be set from a product's `BoardConfig.mk` file:
```
-$(call add_soong_config_namespace, acme)
-$(call add_soong_config_var_value, acme, board, soc_a)
-$(call add_soong_config_var_value, acme, feature, true)
-$(call add_soong_config_var_value, acme, width, 200)
+$(call soong_config_set,acme,board,soc_a)
+$(call soong_config_set,acme,feature,true)
+$(call soong_config_set,acme,width,200)
```
The `acme_cc_defaults` module type can be used anywhere after the definition in
diff --git a/android/api_levels.go b/android/api_levels.go
index 1fbbc15..926d297 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -344,7 +344,7 @@
var apiLevelsMapKey = NewOnceKey("ApiLevelsMap")
-func getApiLevelsMap(config Config) map[string]int {
+func GetApiLevelsMap(config Config) map[string]int {
return config.Once(apiLevelsMapKey, func() interface{} {
apiLevelsMap := map[string]int{
"G": 9,
@@ -374,7 +374,7 @@
}
func (a *apiLevelsSingleton) GenerateBuildActions(ctx SingletonContext) {
- apiLevelsMap := getApiLevelsMap(ctx.Config())
+ apiLevelsMap := GetApiLevelsMap(ctx.Config())
apiLevelsJson := GetApiLevelsJson(ctx)
createApiLevelsJson(ctx, apiLevelsJson, apiLevelsMap)
}
diff --git a/android/arch.go b/android/arch.go
index fb33f30..96a4cbf 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -993,8 +993,6 @@
base := m.base()
- // Store the original list of top level property structs
- base.generalProperties = m.GetProperties()
if len(base.archProperties) != 0 {
panic(fmt.Errorf("module %s already has archProperties", m.Name()))
}
@@ -1015,7 +1013,7 @@
return t
}
- for _, properties := range base.generalProperties {
+ for _, properties := range m.GetProperties() {
t := getStructType(properties)
// Get or create the arch-specific property struct types for this property struct type.
archPropTypes := archPropTypeMap.Once(NewCustomOnceKey(t), func() interface{} {
@@ -1036,7 +1034,6 @@
m.AddProperties(archProperties...)
}
- base.generalProperties = m.GetProperties()
}
func maybeBlueprintEmbed(src reflect.Value) reflect.Value {
@@ -1110,7 +1107,7 @@
os := m.commonProperties.CompileOS
for i := range m.archProperties {
- genProps := m.generalProperties[i]
+ genProps := m.GetProperties()[i]
if m.archProperties[i] == nil {
continue
}
@@ -1438,7 +1435,7 @@
os := m.Os()
for i := range m.archProperties {
- genProps := m.generalProperties[i]
+ genProps := m.GetProperties()[i]
if m.archProperties[i] == nil {
continue
}
@@ -2016,8 +2013,8 @@
var archProperties []interface{}
// First find the property set in the module that corresponds to the requested
- // one. m.archProperties[i] corresponds to m.generalProperties[i].
- for i, generalProp := range m.generalProperties {
+ // one. m.archProperties[i] corresponds to m.GetProperties()[i].
+ for i, generalProp := range m.GetProperties() {
srcType := reflect.ValueOf(generalProp).Type()
if srcType == dstType {
archProperties = m.archProperties[i]
diff --git a/android/bazel.go b/android/bazel.go
index 382e2a7..528c7b1 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -226,6 +226,7 @@
"packages/apps/WallpaperPicker":/* recursive = */ false,
"prebuilts/gcc":/* recursive = */ true,
+ "prebuilts/build-tools":/* recursive = */ false,
"prebuilts/sdk":/* recursive = */ false,
"prebuilts/sdk/current/extras/app-toolkit":/* recursive = */ false,
"prebuilts/sdk/current/support":/* recursive = */ false,
@@ -236,6 +237,8 @@
// Configure modules in these directories to enable bp2build_available: true or false by default.
bp2buildDefaultConfig = Bp2BuildConfig{
"art/libdexfile": Bp2BuildDefaultTrueRecursively,
+ "art/runtime": Bp2BuildDefaultTrueRecursively,
+ "art/tools": Bp2BuildDefaultTrue,
"bionic": Bp2BuildDefaultTrueRecursively,
"bootable/recovery/tools/recovery_l10n": Bp2BuildDefaultTrue,
"build/bazel/examples/soong_config_variables": Bp2BuildDefaultTrueRecursively,
@@ -245,6 +248,7 @@
"build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir
"build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue,
"build/soong/cc/symbolfile": Bp2BuildDefaultTrue,
+ "build/soong/linkerconfig": Bp2BuildDefaultTrueRecursively,
"build/soong/scripts": Bp2BuildDefaultTrueRecursively,
"cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively,
"development/apps/DevelopmentSettings": Bp2BuildDefaultTrue,
@@ -324,6 +328,7 @@
"packages/apps/DevCamera": Bp2BuildDefaultTrue,
"packages/apps/HTMLViewer": Bp2BuildDefaultTrue,
"packages/apps/Protips": Bp2BuildDefaultTrue,
+ "packages/modules/StatsD/lib/libstatssocket": Bp2BuildDefaultTrueRecursively,
"packages/modules/adb": Bp2BuildDefaultTrue,
"packages/modules/adb/apex": Bp2BuildDefaultTrue,
"packages/modules/adb/crypto": Bp2BuildDefaultTrueRecursively,
@@ -337,6 +342,8 @@
"packages/services/Car/tests/SampleRearViewCamera": Bp2BuildDefaultTrue,
"prebuilts/clang/host/linux-x86": Bp2BuildDefaultTrueRecursively,
"system/apex": Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures
+ "system/apex/proto": Bp2BuildDefaultTrueRecursively,
+ "system/apex/libs": Bp2BuildDefaultTrueRecursively,
"system/core/debuggerd": Bp2BuildDefaultTrueRecursively,
"system/core/diagnose_usb": Bp2BuildDefaultTrueRecursively,
"system/core/libasyncio": Bp2BuildDefaultTrue,
@@ -365,6 +372,16 @@
// Per-module denylist to always opt modules out of both bp2build and mixed builds.
bp2buildModuleDoNotConvertList = []string{
+ "libnativehelper_compat_libc", // Broken compile: implicit declaration of function 'strerror_r' is invalid in C99
+
+ "libart", // depends on unconverted modules: art_operator_srcs, libodrstatslog, libelffile, art_cmdlineparser_headers, cpp-define-generator-definitions, libcpu_features, libdexfile, libartpalette, libbacktrace, libnativebridge, libnativeloader, libsigchain, libunwindstack, libartbase, libprofile, cpp-define-generator-asm-support, apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, libstatssocket, heapprofd_client_api
+ "libart-runtime-gtest", // depends on unconverted modules: libgtest_isolated, libart-compiler, libdexfile, libprofile, libartbase, libbacktrace, libartbase-art-gtest
+ "libart_headers", // depends on unconverted modules: art_libartbase_headers
+ "libartd", // depends on unconverted modules: apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, libstatssocket, heapprofd_client_api, art_operator_srcs, libodrstatslog, libelffiled, art_cmdlineparser_headers, cpp-define-generator-definitions, libcpu_features, libdexfiled, libartpalette, libbacktrace, libnativebridge, libnativeloader, libsigchain, libunwindstack, libartbased, libprofiled, cpp-define-generator-asm-support
+ "libartd-runtime-gtest", // depends on unconverted modules: libgtest_isolated, libartd-compiler, libdexfiled, libprofiled, libartbased, libbacktrace, libartbased-art-gtest
+ "libstatslog_art", // depends on unconverted modules: statslog_art.cpp, statslog_art.h
+ "statslog_art.h", "statslog_art.cpp", // depends on unconverted modules: stats-log-api-gen
+
"libandroid_runtime_lazy", // depends on unconverted modules: libbinder_headers
"libcmd", // depends on unconverted modules: libbinder
@@ -404,22 +421,23 @@
"libdebuggerd", // depends on unconverted modules libdexfile_support, libunwindstack, gwp_asan_crash_handler, libtombstone_proto, libprotobuf-cpp-lite
"libdexfile_static", // depends on libartpalette, libartbase, libdexfile, which are of unsupported type: art_cc_library.
- "host_bionic_linker_asm", // depends on extract_linker, a go binary.
- "host_bionic_linker_script", // depends on extract_linker, a go binary.
- "static_crasher", // depends on unconverted modules: libdebuggerd_handler
+ "static_crasher", // depends on unconverted modules: libdebuggerd_handler
"pbtombstone", "crash_dump", // depends on libdebuggerd, libunwindstack
"libbase_ndk", // http://b/186826477, fails to link libctscamera2_jni for device (required for CtsCameraTestCases)
- "libprotobuf-python", // contains .proto sources
"libprotobuf-internal-protos", // b/210751803, we don't handle path property for filegroups
"libprotobuf-internal-python-srcs", // b/210751803, we don't handle path property for filegroups
"libprotobuf-java-full", // b/210751803, we don't handle path property for filegroups
"libprotobuf-java-util-full", // b/210751803, we don't handle path property for filegroups
"conscrypt", // b/210751803, we don't handle path property for filegroups
- "conv_linker_config", // depends on linker_config_proto, a python lib with proto sources
+ // python protos
+ "libprotobuf-python", // contains .proto sources
+ "conv_linker_config", // depends on linker_config_proto, a python lib with proto sources
+ "apex_build_info_proto", "apex_manifest_proto", // a python lib with proto sources
+ "linker_config_proto", // contains .proto sources
"brotli-fuzzer-corpus", // b/202015218: outputs are in location incompatible with bazel genrule handling.
@@ -436,6 +454,8 @@
"abb", // depends on unconverted modules: libcmd, libbinder
"adb", // depends on unconverted modules: AdbWinApi, libadb_host, libandroidfw, libapp_processes_protos_full, libfastdeploy_host, libopenscreen-discovery, libopenscreen-platform-impl, libusb, bin2c_fastdeployagent, AdbWinUsbApi
+ "libadb_host", // depends on unconverted modules: libopenscreen-discovery, libopenscreen-platform-impl, libusb, AdbWinApi
+ "libfastdeploy_host", // depends on unconverted modules: libandroidfw, libusb, AdbWinApi
"linker", // depends on unconverted modules: libdebuggerd_handler_fallback
"linker_reloc_bench_main", // depends on unconverted modules: liblinker_reloc_bench_*
"versioner", // depends on unconverted modules: libclang_cxx_host, libLLVM_host, of unsupported type llvm_host_prebuilt_library_shared
@@ -447,6 +467,15 @@
"libdexfile", // depends on unconverted modules: dexfile_operator_srcs, libartbase, libartpalette,
"libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette
+
+ // go deps:
+ "apex-protos", // depends on soong_zip, a go binary
+ "robolectric_tzdata", // depends on soong_zip, a go binary
+ "host_bionic_linker_asm", // depends on extract_linker, a go binary.
+ "host_bionic_linker_script", // depends on extract_linker, a go binary.
+
+ // java deps
+ "bin2c_fastdeployagent", // depends on deployagent, a java binary
}
// Per-module denylist of cc_library modules to only generate the static
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 62e6156..f353a9d 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -92,6 +92,7 @@
GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
ModuleFromName(name string) (blueprint.Module, bool)
AddUnconvertedBp2buildDep(string)
+ AddMissingBp2buildDep(dep string)
}
// BazelLabelForModuleDeps expects a list of reference to other modules, ("<module>"
@@ -129,8 +130,10 @@
}
if m, t := SrcIsModuleWithTag(module); m != "" {
l := getOtherModuleLabel(ctx, m, t, moduleToLabelFn)
- l.OriginalModuleName = bpText
- labels.Includes = append(labels.Includes, l)
+ if l != nil {
+ l.OriginalModuleName = bpText
+ labels.Includes = append(labels.Includes, *l)
+ }
} else {
ctx.ModuleErrorf("%q, is not a module reference", module)
}
@@ -157,11 +160,17 @@
}
func BazelLabelForModuleSrcSingle(ctx BazelConversionPathContext, path string) bazel.Label {
- return BazelLabelForModuleSrcExcludes(ctx, []string{path}, []string(nil)).Includes[0]
+ if srcs := BazelLabelForModuleSrcExcludes(ctx, []string{path}, []string(nil)).Includes; len(srcs) > 0 {
+ return srcs[0]
+ }
+ return bazel.Label{}
}
func BazelLabelForModuleDepSingle(ctx BazelConversionPathContext, path string) bazel.Label {
- return BazelLabelForModuleDepsExcludes(ctx, []string{path}, []string(nil)).Includes[0]
+ if srcs := BazelLabelForModuleDepsExcludes(ctx, []string{path}, []string(nil)).Includes; len(srcs) > 0 {
+ return srcs[0]
+ }
+ return bazel.Label{}
}
// BazelLabelForModuleSrc expects a list of path (relative to local module directory) and module
@@ -328,9 +337,9 @@
for _, p := range paths {
if m, tag := SrcIsModuleWithTag(p); m != "" {
l := getOtherModuleLabel(ctx, m, tag, BazelModuleLabel)
- if !InList(l.Label, expandedExcludes) {
+ if l != nil && !InList(l.Label, expandedExcludes) {
l.OriginalModuleName = fmt.Sprintf(":%s", m)
- labels.Includes = append(labels.Includes, l)
+ labels.Includes = append(labels.Includes, *l)
}
} else {
var expandedPaths []bazel.Label
@@ -354,10 +363,16 @@
// module. The label will be relative to the current directory if appropriate. The dependency must
// already be resolved by either deps mutator or path deps mutator.
func getOtherModuleLabel(ctx BazelConversionPathContext, dep, tag string,
- labelFromModule func(BazelConversionPathContext, blueprint.Module) string) bazel.Label {
+ labelFromModule func(BazelConversionPathContext, blueprint.Module) string) *bazel.Label {
m, _ := ctx.ModuleFromName(dep)
+ // The module was not found in an Android.bp file, this is often due to:
+ // * a limited manifest
+ // * a required module not being converted from Android.mk
if m == nil {
- panic(fmt.Errorf("No module named %q found, but was a direct dep of %q", dep, ctx.Module().Name()))
+ ctx.AddMissingBp2buildDep(dep)
+ return &bazel.Label{
+ Label: ":" + dep + "__BP2BUILD__MISSING__DEP",
+ }
}
if !convertedToBazel(ctx, m) {
ctx.AddUnconvertedBp2buildDep(dep)
@@ -371,7 +386,7 @@
otherLabel = bazelShortLabel(otherLabel)
}
- return bazel.Label{
+ return &bazel.Label{
Label: otherLabel,
}
}
diff --git a/android/config.go b/android/config.go
index 0187a8a..afc138b 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1469,6 +1469,10 @@
return String(c.config.productVariables.TotSepolicyVersion)
}
+func (c *deviceConfig) PlatformSepolicyCompatVersions() []string {
+ return c.config.productVariables.PlatformSepolicyCompatVersions
+}
+
func (c *deviceConfig) BoardSepolicyVers() string {
if ver := String(c.config.productVariables.BoardSepolicyVers); ver != "" {
return ver
diff --git a/android/defaults.go b/android/defaults.go
index 15fd675..8b121f6 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -96,8 +96,6 @@
module.setProperties(module.GetProperties(), module.base().variableProperties)
module.AddProperties(module.defaults())
-
- module.base().generalProperties = module.GetProperties()
}
// A restricted subset of context methods, similar to LoadHookContext.
diff --git a/android/hooks.go b/android/hooks.go
index 1b61cd7..bded764 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -68,7 +68,7 @@
func (l *loadHookContext) appendPrependHelper(props []interface{},
extendFn func([]interface{}, interface{}, proptools.ExtendPropertyFilterFunc) error) {
for _, p := range props {
- err := extendFn(l.Module().base().generalProperties, p, nil)
+ err := extendFn(l.Module().base().GetProperties(), p, nil)
if err != nil {
if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
l.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
diff --git a/android/license.go b/android/license.go
index d7e1d87..587cb36 100644
--- a/android/license.go
+++ b/android/license.go
@@ -80,8 +80,6 @@
base := module.base()
module.AddProperties(&base.nameProperties, &module.properties)
- base.generalProperties = module.GetProperties()
-
// The visibility property needs to be checked and parsed by the visibility module.
setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
diff --git a/android/license_kind.go b/android/license_kind.go
index f007ef1..838dedd 100644
--- a/android/license_kind.go
+++ b/android/license_kind.go
@@ -53,8 +53,6 @@
base := module.base()
module.AddProperties(&base.nameProperties, &module.properties)
- base.generalProperties = module.GetProperties()
-
// The visibility property needs to be checked and parsed by the visibility module.
setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
diff --git a/android/licenses_test.go b/android/licenses_test.go
index 6ddbd3e..70160fa 100644
--- a/android/licenses_test.go
+++ b/android/licenses_test.go
@@ -779,8 +779,6 @@
base := m.base()
m.AddProperties(&base.nameProperties, &m.properties)
- base.generalProperties = m.GetProperties()
-
// The default_visibility property needs to be checked and parsed by the visibility module during
// its checking and parsing phases so make it the primary visibility property.
setPrimaryVisibilityProperty(m, "visibility", &m.properties.Visibility)
diff --git a/android/module.go b/android/module.go
index d2c4d40..3c8c777 100644
--- a/android/module.go
+++ b/android/module.go
@@ -19,6 +19,7 @@
"os"
"path"
"path/filepath"
+ "reflect"
"regexp"
"strings"
"text/scanner"
@@ -320,6 +321,9 @@
// AddUnconvertedBp2buildDep stores module name of a direct dependency that was not converted via bp2build
AddUnconvertedBp2buildDep(dep string)
+ // AddMissingBp2buildDep stores the module name of a direct dependency that was not found.
+ AddMissingBp2buildDep(dep string)
+
Target() Target
TargetPrimary() bool
@@ -516,6 +520,7 @@
// Bp2buildTargets returns the target(s) generated for Bazel via bp2build for this module
Bp2buildTargets() []bp2buildInfo
GetUnconvertedBp2buildDeps() []string
+ GetMissingBp2buildDeps() []string
BuildParamsForTests() []BuildParams
RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
@@ -857,6 +862,9 @@
// UnconvertedBp2buildDep stores the module names of direct dependency that were not converted to
// Bazel
UnconvertedBp2buildDeps []string `blueprint:"mutated"`
+
+ // MissingBp2buildDep stores the module names of direct dependency that were not found
+ MissingBp2buildDeps []string `blueprint:"mutated"`
}
// CommonAttributes represents the common Bazel attributes from which properties
@@ -1032,8 +1040,6 @@
initProductVariableModule(m)
- base.generalProperties = m.GetProperties()
-
// The default_visibility property needs to be checked and parsed by the visibility module during
// its checking and parsing phases so make it the primary visibility property.
setPrimaryVisibilityProperty(m, "visibility", &base.commonProperties.Visibility)
@@ -1141,20 +1147,71 @@
}
}
- data.Append(required)
+ productConfigEnabledLabels := []bazel.Label{}
+ if !proptools.BoolDefault(enabledProperty.Value, true) {
+ // If the module is not enabled by default, then we can check if a
+ // product variable enables it
+ productConfigEnabledLabels = productVariableConfigEnableLabels(ctx)
- var err error
- constraints := constraintAttributes{}
- constraints.Target_compatible_with, err = enabledProperty.ToLabelListAttribute(
+ if len(productConfigEnabledLabels) > 0 {
+ // In this case, an existing product variable configuration overrides any
+ // module-level `enable: false` definition
+ newValue := true
+ enabledProperty.Value = &newValue
+ }
+ }
+
+ productConfigEnabledAttribute := bazel.MakeLabelListAttribute(bazel.LabelList{
+ productConfigEnabledLabels, nil,
+ })
+
+ platformEnabledAttribute, err := enabledProperty.ToLabelListAttribute(
bazel.LabelList{[]bazel.Label{bazel.Label{Label: "@platforms//:incompatible"}}, nil},
bazel.LabelList{[]bazel.Label{}, nil})
-
if err != nil {
- ctx.ModuleErrorf("Error processing enabled attribute: %s", err)
+ ctx.ModuleErrorf("Error processing platform enabled attribute: %s", err)
}
+
+ data.Append(required)
+
+ constraints := constraintAttributes{}
+ moduleEnableConstraints := bazel.LabelListAttribute{}
+ moduleEnableConstraints.Append(platformEnabledAttribute)
+ moduleEnableConstraints.Append(productConfigEnabledAttribute)
+ constraints.Target_compatible_with = moduleEnableConstraints
+
return constraints
}
+// Check product variables for `enabled: true` flag override.
+// Returns a list of the constraint_value targets who enable this override.
+func productVariableConfigEnableLabels(ctx *topDownMutatorContext) []bazel.Label {
+ productVariableProps := ProductVariableProperties(ctx)
+ productConfigEnablingTargets := []bazel.Label{}
+ const propName = "Enabled"
+ if productConfigProps, exists := productVariableProps[propName]; exists {
+ for productConfigProp, prop := range productConfigProps {
+ flag, ok := prop.(*bool)
+ if !ok {
+ ctx.ModuleErrorf("Could not convert product variable %s property", proptools.PropertyNameForField(propName))
+ }
+
+ if *flag {
+ axis := productConfigProp.ConfigurationAxis()
+ targetLabel := axis.SelectKey(productConfigProp.SelectKey())
+ productConfigEnablingTargets = append(productConfigEnablingTargets, bazel.Label{
+ Label: targetLabel,
+ })
+ } else {
+ // TODO(b/210546943): handle negative case where `enabled: false`
+ ctx.ModuleErrorf("`enabled: false` is not currently supported for configuration variables. See b/210546943", proptools.PropertyNameForField(propName))
+ }
+ }
+ }
+
+ return productConfigEnablingTargets
+}
+
// A ModuleBase object contains the properties that are common to all Android
// modules. It should be included as an anonymous field in every module
// struct definition. InitAndroidModule should then be called from the module's
@@ -1207,13 +1264,12 @@
distProperties distProperties
variableProperties interface{}
hostAndDeviceProperties hostAndDeviceProperties
- generalProperties []interface{}
- // Arch specific versions of structs in generalProperties. The outer index
- // has the same order as generalProperties as initialized in
- // InitAndroidArchModule, and the inner index chooses the props specific to
- // the architecture. The interface{} value is an archPropRoot that is
- // filled with arch specific values by the arch mutator.
+ // Arch specific versions of structs in GetProperties() prior to
+ // initialization in InitAndroidArchModule, lets call it `generalProperties`.
+ // The outer index has the same order as generalProperties and the inner index
+ // chooses the props specific to the architecture. The interface{} value is an
+ // archPropRoot that is filled with arch specific values by the arch mutator.
archProperties [][]interface{}
// Properties specific to the Blueprint to BUILD migration.
@@ -1322,14 +1378,82 @@
*unconvertedDeps = append(*unconvertedDeps, dep)
}
+// AddMissingBp2buildDep stores module name of a dependency that was not found in a Android.bp file.
+func (b *baseModuleContext) AddMissingBp2buildDep(dep string) {
+ missingDeps := &b.Module().base().commonProperties.MissingBp2buildDeps
+ *missingDeps = append(*missingDeps, dep)
+}
+
// GetUnconvertedBp2buildDeps returns the list of module names of this module's direct dependencies that
// were not converted to Bazel.
func (m *ModuleBase) GetUnconvertedBp2buildDeps() []string {
return FirstUniqueStrings(m.commonProperties.UnconvertedBp2buildDeps)
}
+// GetMissingBp2buildDeps eturns the list of module names that were not found in Android.bp files.
+func (m *ModuleBase) GetMissingBp2buildDeps() []string {
+ return FirstUniqueStrings(m.commonProperties.MissingBp2buildDeps)
+}
+
func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
- (*d)["Android"] = map[string]interface{}{}
+ (*d)["Android"] = map[string]interface{}{
+ // Properties set in Blueprint or in blueprint of a defaults modules
+ "SetProperties": m.propertiesWithValues(),
+ }
+}
+
+type propInfo struct {
+ Name string
+ Type string
+}
+
+func (m *ModuleBase) propertiesWithValues() []propInfo {
+ var info []propInfo
+ props := m.GetProperties()
+
+ var propsWithValues func(name string, v reflect.Value)
+ propsWithValues = func(name string, v reflect.Value) {
+ kind := v.Kind()
+ switch kind {
+ case reflect.Ptr, reflect.Interface:
+ if v.IsNil() {
+ return
+ }
+ propsWithValues(name, v.Elem())
+ case reflect.Struct:
+ if v.IsZero() {
+ return
+ }
+ for i := 0; i < v.NumField(); i++ {
+ namePrefix := name
+ sTyp := v.Type().Field(i)
+ if proptools.ShouldSkipProperty(sTyp) {
+ continue
+ }
+ if name != "" && !strings.HasSuffix(namePrefix, ".") {
+ namePrefix += "."
+ }
+ if !proptools.IsEmbedded(sTyp) {
+ namePrefix += sTyp.Name
+ }
+ sVal := v.Field(i)
+ propsWithValues(namePrefix, sVal)
+ }
+ case reflect.Array, reflect.Slice:
+ if v.IsNil() {
+ return
+ }
+ elKind := v.Type().Elem().Kind()
+ info = append(info, propInfo{name, elKind.String() + " " + kind.String()})
+ default:
+ info = append(info, propInfo{name, kind.String()})
+ }
+ }
+
+ for _, p := range props {
+ propsWithValues("", reflect.ValueOf(p).Elem())
+ }
+ return info
}
func (m *ModuleBase) ComponentDepsMutator(BottomUpMutatorContext) {}
@@ -1808,6 +1932,10 @@
return append(Paths{}, m.vintfFragmentsPaths...)
}
+func (m *ModuleBase) CompileMultilib() *string {
+ return m.base().commonProperties.Compile_multilib
+}
+
// SetLicenseInstallMap stores the set of dependency module:location mappings for files in an
// apex container for use when generation the license metadata file.
func (m *ModuleBase) SetLicenseInstallMap(installMap []string) {
diff --git a/android/module_test.go b/android/module_test.go
index d9e2c87..c35e66e 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -615,3 +615,204 @@
return rules
}
+
+type PropsTestModuleEmbedded struct {
+ Embedded_prop *string
+}
+
+type propsTestModule struct {
+ ModuleBase
+ DefaultableModuleBase
+ props struct {
+ A string `android:"arch_variant"`
+ B *bool
+ C []string
+ }
+ otherProps struct {
+ PropsTestModuleEmbedded
+
+ D *int64
+ Nested struct {
+ E *string
+ }
+ F *string `blueprint:"mutated"`
+ }
+}
+
+func propsTestModuleFactory() Module {
+ module := &propsTestModule{}
+ module.AddProperties(&module.props, &module.otherProps)
+ InitAndroidArchModule(module, HostAndDeviceSupported, MultilibBoth)
+ InitDefaultableModule(module)
+ return module
+}
+
+type propsTestModuleDefaults struct {
+ ModuleBase
+ DefaultsModuleBase
+}
+
+func propsTestModuleDefaultsFactory() Module {
+ defaults := &propsTestModuleDefaults{}
+ module := propsTestModule{}
+ defaults.AddProperties(&module.props, &module.otherProps)
+ InitDefaultsModule(defaults)
+ return defaults
+}
+
+func (p *propsTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ str := "abc"
+ p.otherProps.F = &str
+}
+
+func TestUsedProperties(t *testing.T) {
+ testCases := []struct {
+ desc string
+ bp string
+ expectedProps []propInfo
+ }{
+ {
+ desc: "only name",
+ bp: `test {
+ name: "foo",
+ }
+ `,
+ expectedProps: []propInfo{
+ propInfo{"Name", "string"},
+ },
+ },
+ {
+ desc: "some props",
+ bp: `test {
+ name: "foo",
+ a: "abc",
+ b: true,
+ d: 123,
+ }
+ `,
+ expectedProps: []propInfo{
+ propInfo{"A", "string"},
+ propInfo{"B", "bool"},
+ propInfo{"D", "int64"},
+ propInfo{"Name", "string"},
+ },
+ },
+ {
+ desc: "unused non-pointer prop",
+ bp: `test {
+ name: "foo",
+ b: true,
+ d: 123,
+ }
+ `,
+ expectedProps: []propInfo{
+ // for non-pointer cannot distinguish between unused and intentionally set to empty
+ propInfo{"A", "string"},
+ propInfo{"B", "bool"},
+ propInfo{"D", "int64"},
+ propInfo{"Name", "string"},
+ },
+ },
+ {
+ desc: "nested props",
+ bp: `test {
+ name: "foo",
+ nested: {
+ e: "abc",
+ }
+ }
+ `,
+ expectedProps: []propInfo{
+ propInfo{"Nested.E", "string"},
+ propInfo{"Name", "string"},
+ },
+ },
+ {
+ desc: "arch props",
+ bp: `test {
+ name: "foo",
+ arch: {
+ x86_64: {
+ a: "abc",
+ },
+ }
+ }
+ `,
+ expectedProps: []propInfo{
+ propInfo{"Name", "string"},
+ propInfo{"Arch.X86_64.A", "string"},
+ },
+ },
+ {
+ desc: "embedded props",
+ bp: `test {
+ name: "foo",
+ embedded_prop: "a",
+ }
+ `,
+ expectedProps: []propInfo{
+ propInfo{"Embedded_prop", "string"},
+ propInfo{"Name", "string"},
+ },
+ },
+ {
+ desc: "defaults",
+ bp: `
+test_defaults {
+ name: "foo_defaults",
+ a: "a",
+ b: true,
+ embedded_prop:"a",
+ arch: {
+ x86_64: {
+ a: "a",
+ },
+ },
+}
+test {
+ name: "foo",
+ defaults: ["foo_defaults"],
+ c: ["a"],
+ nested: {
+ e: "d",
+ },
+ target: {
+ linux: {
+ a: "a",
+ },
+ },
+}
+ `,
+ expectedProps: []propInfo{
+ propInfo{"A", "string"},
+ propInfo{"B", "bool"},
+ propInfo{"C", "string slice"},
+ propInfo{"Embedded_prop", "string"},
+ propInfo{"Nested.E", "string"},
+ propInfo{"Name", "string"},
+ propInfo{"Arch.X86_64.A", "string"},
+ propInfo{"Target.Linux.A", "string"},
+ propInfo{"Defaults", "string slice"},
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.desc, func(t *testing.T) {
+ result := GroupFixturePreparers(
+ PrepareForTestWithAllowMissingDependencies,
+ PrepareForTestWithDefaults,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("test", propsTestModuleFactory)
+ ctx.RegisterModuleType("test_defaults", propsTestModuleDefaultsFactory)
+ }),
+ FixtureWithRootAndroidBp(tc.bp),
+ ).RunTest(t)
+
+ foo := result.ModuleForTests("foo", "").Module().base()
+
+ AssertDeepEquals(t, "foo ", tc.expectedProps, foo.propertiesWithValues())
+
+ })
+ }
+}
diff --git a/android/neverallow.go b/android/neverallow.go
index 2859750..6f9ae58 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -214,11 +214,8 @@
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 and seapp contexts may be imported as a makefile goal."),
+ Because("Only boot images may be imported as a makefile goal."),
}
}
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 58a90b3..59016d4 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -324,7 +324,7 @@
`),
},
expectedErrors: []string{
- "Only boot images and seapp contexts may be imported as a makefile goal.",
+ "Only boot images may be imported as a makefile goal.",
},
},
{
diff --git a/android/path_properties.go b/android/path_properties.go
index 3976880..fdc4d91 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -33,7 +33,7 @@
// The pathDepsMutator automatically adds dependencies on any module that is listed with the
// ":module" module reference syntax in a property that is tagged with `android:"path"`.
func pathDepsMutator(ctx BottomUpMutatorContext) {
- props := ctx.Module().base().generalProperties
+ props := ctx.Module().base().GetProperties()
addPathDepsForProps(ctx, props)
}
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 22aa946..5843487 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -183,7 +183,6 @@
func initPrebuiltModuleCommon(module PrebuiltInterface) *Prebuilt {
p := module.Prebuilt()
module.AddProperties(&p.properties)
- module.base().generalProperties = module.GetProperties()
return p
}
@@ -310,6 +309,54 @@
return nil
}
+// PrebuiltGetPreferred returns the module that is preferred for the given
+// module. That is either the module itself or the prebuilt counterpart that has
+// taken its place. The given module must be a direct dependency of the current
+// context module, and it must be the source module if both source and prebuilt
+// exist.
+//
+// This function is for use on dependencies after PrebuiltPostDepsMutator has
+// run - any dependency that is registered before that will already reference
+// the right module. This function is only safe to call after all mutators that
+// may call CreateVariations, e.g. in GenerateAndroidBuildActions.
+func PrebuiltGetPreferred(ctx BaseModuleContext, module Module) Module {
+ if !module.IsReplacedByPrebuilt() {
+ return module
+ }
+ if IsModulePrebuilt(module) {
+ // If we're given a prebuilt then assume there's no source module around.
+ return module
+ }
+
+ sourceModDepFound := false
+ var prebuiltMod Module
+
+ ctx.WalkDeps(func(child, parent Module) bool {
+ if prebuiltMod != nil {
+ return false
+ }
+ if parent == ctx.Module() {
+ // First level: Only recurse if the module is found as a direct dependency.
+ sourceModDepFound = child == module
+ return sourceModDepFound
+ }
+ // Second level: Follow PrebuiltDepTag to the prebuilt.
+ if t := ctx.OtherModuleDependencyTag(child); t == PrebuiltDepTag {
+ prebuiltMod = child
+ }
+ return false
+ })
+
+ if prebuiltMod == nil {
+ if !sourceModDepFound {
+ panic(fmt.Errorf("Failed to find source module as a direct dependency: %s", module))
+ } else {
+ panic(fmt.Errorf("Failed to find prebuilt for source module: %s", module))
+ }
+ }
+ return prebuiltMod
+}
+
func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) {
ctx.BottomUp("prebuilt_rename", PrebuiltRenameMutator).Parallel()
}
diff --git a/android/variable.go b/android/variable.go
index a6156b1..40dd2d8 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -124,6 +124,7 @@
Shared_libs []string
Cmdline []string
+
Srcs []string
Exclude_srcs []string
}
@@ -363,6 +364,8 @@
PlatformSepolicyVersion *string `json:",omitempty"`
TotSepolicyVersion *string `json:",omitempty"`
+ PlatformSepolicyCompatVersions []string `json:",omitempty"`
+
VendorVars map[string]map[string]string `json:",omitempty"`
Ndk_abis *bool `json:",omitempty"`
@@ -598,10 +601,16 @@
value := p.FullConfig
if value == p.Name {
- value = "enabled"
+ value = ""
}
- // e.g. acme__feature1__enabled, android__board__soc_a
- return strings.ToLower(strings.Join([]string{p.Namespace, p.Name, value}, "__"))
+
+ // e.g. acme__feature1, android__board__soc_a
+ selectKey := strings.ToLower(strings.Join([]string{p.Namespace, p.Name}, "__"))
+ if value != "" {
+ selectKey = strings.ToLower(strings.Join([]string{selectKey, value}, "__"))
+ }
+
+ return selectKey
}
// ProductConfigProperties is a map of maps to group property values according
@@ -1028,7 +1037,7 @@
printfIntoProperties(ctx, prefix, productVariablePropertyValue, variableValue)
- err := proptools.AppendMatchingProperties(m.generalProperties,
+ err := proptools.AppendMatchingProperties(m.GetProperties(),
productVariablePropertyValue.Addr().Interface(), nil)
if err != nil {
if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
diff --git a/apex/apex.go b/apex/apex.go
index 635ff30..3051553 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1612,8 +1612,8 @@
return af
}
-func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path, bpfProgram bpf.BpfModule) apexFile {
- dirInApex := filepath.Join("etc", "bpf")
+func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path, apex_sub_dir string, bpfProgram bpf.BpfModule) apexFile {
+ dirInApex := filepath.Join("etc", "bpf", apex_sub_dir)
return newApexFile(ctx, builtFile, builtFile.Base(), dirInApex, etc, bpfProgram)
}
@@ -1765,13 +1765,17 @@
}
case bcpfTag:
{
- if _, ok := child.(*java.BootclasspathFragmentModule); !ok {
+ bcpfModule, ok := child.(*java.BootclasspathFragmentModule)
+ if !ok {
ctx.PropertyErrorf("bootclasspath_fragments", "%q is not a bootclasspath_fragment module", depName)
return false
}
filesToAdd := apexBootclasspathFragmentFiles(ctx, child)
filesInfo = append(filesInfo, filesToAdd...)
+ for _, makeModuleName := range bcpfModule.BootImageDeviceInstallMakeModules() {
+ a.requiredDeps = append(a.requiredDeps, makeModuleName)
+ }
return true
}
case sscpfTag:
@@ -1827,8 +1831,9 @@
case bpfTag:
if bpfProgram, ok := child.(bpf.BpfModule); ok {
filesToCopy, _ := bpfProgram.OutputFiles("")
+ apex_sub_dir := bpfProgram.SubDir()
for _, bpfFile := range filesToCopy {
- filesInfo = append(filesInfo, apexFileForBpfProgram(ctx, bpfFile, bpfProgram))
+ filesInfo = append(filesInfo, apexFileForBpfProgram(ctx, bpfFile, apex_sub_dir, bpfProgram))
}
} else {
ctx.PropertyErrorf("bpfs", "%q is not a bpf module", depName)
@@ -2175,13 +2180,15 @@
var filesToAdd []apexFile
// Add the boot image files, e.g. .art, .oat and .vdex files.
- for arch, files := range bootclasspathFragmentInfo.AndroidBootImageFilesByArchType() {
- dirInApex := filepath.Join("javalib", arch.String())
- for _, f := range files {
- androidMkModuleName := "javalib_" + arch.String() + "_" + filepath.Base(f.String())
- // TODO(b/177892522) - consider passing in the bootclasspath fragment module here instead of nil
- af := newApexFile(ctx, f, androidMkModuleName, dirInApex, etc, nil)
- filesToAdd = append(filesToAdd, af)
+ if bootclasspathFragmentInfo.ShouldInstallBootImageInApex() {
+ for arch, files := range bootclasspathFragmentInfo.AndroidBootImageFilesByArchType() {
+ dirInApex := filepath.Join("javalib", arch.String())
+ for _, f := range files {
+ androidMkModuleName := "javalib_" + arch.String() + "_" + filepath.Base(f.String())
+ // TODO(b/177892522) - consider passing in the bootclasspath fragment module here instead of nil
+ af := newApexFile(ctx, f, androidMkModuleName, dirInApex, etc, nil)
+ filesToAdd = append(filesToAdd, af)
+ }
}
}
@@ -3204,8 +3211,15 @@
WithMatcher("permitted_packages", android.NotInList(module_packages)).
WithMatcher("min_sdk_version", android.LessThanSdkVersion("Tiramisu")).
Because("jars that are part of the " + module_name +
- " module may only allow these packages: " + strings.Join(module_packages, ",") +
- " with min_sdk < T. Please jarjar or move code around.")
+ " module may only use these package prefixes: " + strings.Join(module_packages, ",") +
+ " with min_sdk < T. Please consider the following alternatives:\n" +
+ " 1. If the offending code is from a statically linked library, consider " +
+ "removing that dependency and using an alternative already in the " +
+ "bootclasspath, or perhaps a shared library." +
+ " 2. Move the offending code into an allowed package.\n" +
+ " 3. Jarjar the offending code. Please be mindful of the potential system " +
+ "health implications of bundling that code, particularly if the offending jar " +
+ "is part of the bootclasspath.")
rules = append(rules, permittedPackagesRule)
}
return rules
@@ -3263,17 +3277,23 @@
// For Bazel / bp2build
type bazelApexBundleAttributes struct {
- Manifest bazel.LabelAttribute
- Android_manifest bazel.LabelAttribute
- File_contexts bazel.LabelAttribute
- Key bazel.LabelAttribute
- Certificate bazel.LabelAttribute
- Min_sdk_version *string
- Updatable bazel.BoolAttribute
- Installable bazel.BoolAttribute
- Native_shared_libs bazel.LabelListAttribute
- Binaries bazel.LabelListAttribute
- Prebuilts bazel.LabelListAttribute
+ Manifest bazel.LabelAttribute
+ Android_manifest bazel.LabelAttribute
+ File_contexts bazel.LabelAttribute
+ Key bazel.LabelAttribute
+ Certificate bazel.LabelAttribute
+ Min_sdk_version *string
+ Updatable bazel.BoolAttribute
+ Installable bazel.BoolAttribute
+ Binaries bazel.LabelListAttribute
+ Prebuilts bazel.LabelListAttribute
+ Native_shared_libs_32 bazel.LabelListAttribute
+ Native_shared_libs_64 bazel.LabelListAttribute
+}
+
+type convertedNativeSharedLibs struct {
+ Native_shared_libs_32 bazel.LabelListAttribute
+ Native_shared_libs_64 bazel.LabelListAttribute
}
// ConvertWithBp2build performs bp2build conversion of an apex
@@ -3313,9 +3333,21 @@
certificateLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *a.overridableProperties.Certificate))
}
- nativeSharedLibs := a.properties.ApexNativeDependencies.Native_shared_libs
- nativeSharedLibsLabelList := android.BazelLabelForModuleDeps(ctx, nativeSharedLibs)
- nativeSharedLibsLabelListAttribute := bazel.MakeLabelListAttribute(nativeSharedLibsLabelList)
+ nativeSharedLibs := &convertedNativeSharedLibs{
+ Native_shared_libs_32: bazel.LabelListAttribute{},
+ Native_shared_libs_64: bazel.LabelListAttribute{},
+ }
+ compileMultilib := "both"
+ if a.CompileMultilib() != nil {
+ compileMultilib = *a.CompileMultilib()
+ }
+
+ // properties.Native_shared_libs is treated as "both"
+ convertBothLibs(ctx, compileMultilib, a.properties.Native_shared_libs, nativeSharedLibs)
+ convertBothLibs(ctx, compileMultilib, a.properties.Multilib.Both.Native_shared_libs, nativeSharedLibs)
+ convert32Libs(ctx, compileMultilib, a.properties.Multilib.Lib32.Native_shared_libs, nativeSharedLibs)
+ convert64Libs(ctx, compileMultilib, a.properties.Multilib.Lib64.Native_shared_libs, nativeSharedLibs)
+ convertFirstLibs(ctx, compileMultilib, a.properties.Multilib.First.Native_shared_libs, nativeSharedLibs)
prebuilts := a.overridableProperties.Prebuilts
prebuiltsLabelList := android.BazelLabelForModuleDeps(ctx, prebuilts)
@@ -3335,17 +3367,18 @@
}
attrs := &bazelApexBundleAttributes{
- Manifest: manifestLabelAttribute,
- Android_manifest: androidManifestLabelAttribute,
- File_contexts: fileContextsLabelAttribute,
- Min_sdk_version: minSdkVersion,
- Key: keyLabelAttribute,
- Certificate: certificateLabelAttribute,
- Updatable: updatableAttribute,
- Installable: installableAttribute,
- Native_shared_libs: nativeSharedLibsLabelListAttribute,
- Binaries: binariesLabelListAttribute,
- Prebuilts: prebuiltsLabelListAttribute,
+ Manifest: manifestLabelAttribute,
+ Android_manifest: androidManifestLabelAttribute,
+ File_contexts: fileContextsLabelAttribute,
+ Min_sdk_version: minSdkVersion,
+ Key: keyLabelAttribute,
+ Certificate: certificateLabelAttribute,
+ Updatable: updatableAttribute,
+ Installable: installableAttribute,
+ Native_shared_libs_32: nativeSharedLibs.Native_shared_libs_32,
+ Native_shared_libs_64: nativeSharedLibs.Native_shared_libs_64,
+ Binaries: binariesLabelListAttribute,
+ Prebuilts: prebuiltsLabelListAttribute,
}
props := bazel.BazelTargetModuleProperties{
@@ -3355,3 +3388,107 @@
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: a.Name()}, attrs)
}
+
+// The following conversions are based on this table where the rows are the compile_multilib
+// values and the columns are the properties.Multilib.*.Native_shared_libs. Each cell
+// represents how the libs should be compiled for a 64-bit/32-bit device: 32 means it
+// should be compiled as 32-bit, 64 means it should be compiled as 64-bit, none means it
+// should not be compiled.
+// multib/compile_multilib, 32, 64, both, first
+// 32, 32/32, none/none, 32/32, none/32
+// 64, none/none, 64/none, 64/none, 64/none
+// both, 32/32, 64/none, 32&64/32, 64/32
+// first, 32/32, 64/none, 64/32, 64/32
+
+func convert32Libs(ctx android.TopDownMutatorContext, compileMultilb string,
+ libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
+ libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
+ switch compileMultilb {
+ case "both", "32":
+ makeNoConfig32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
+ case "first":
+ make32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
+ case "64":
+ // Incompatible, ignore
+ default:
+ invalidCompileMultilib(ctx, compileMultilb)
+ }
+}
+
+func convert64Libs(ctx android.TopDownMutatorContext, compileMultilb string,
+ libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
+ libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
+ switch compileMultilb {
+ case "both", "64", "first":
+ make64SharedLibsAttributes(libsLabelList, nativeSharedLibs)
+ case "32":
+ // Incompatible, ignore
+ default:
+ invalidCompileMultilib(ctx, compileMultilb)
+ }
+}
+
+func convertBothLibs(ctx android.TopDownMutatorContext, compileMultilb string,
+ libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
+ libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
+ switch compileMultilb {
+ case "both":
+ makeNoConfig32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
+ make64SharedLibsAttributes(libsLabelList, nativeSharedLibs)
+ case "first":
+ makeFirstSharedLibsAttributes(libsLabelList, nativeSharedLibs)
+ case "32":
+ makeNoConfig32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
+ case "64":
+ make64SharedLibsAttributes(libsLabelList, nativeSharedLibs)
+ default:
+ invalidCompileMultilib(ctx, compileMultilb)
+ }
+}
+
+func convertFirstLibs(ctx android.TopDownMutatorContext, compileMultilb string,
+ libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
+ libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
+ switch compileMultilb {
+ case "both", "first":
+ makeFirstSharedLibsAttributes(libsLabelList, nativeSharedLibs)
+ case "32":
+ make32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
+ case "64":
+ make64SharedLibsAttributes(libsLabelList, nativeSharedLibs)
+ default:
+ invalidCompileMultilib(ctx, compileMultilb)
+ }
+}
+
+func makeFirstSharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) {
+ make32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
+ make64SharedLibsAttributes(libsLabelList, nativeSharedLibs)
+}
+
+func makeNoConfig32SharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) {
+ list := bazel.LabelListAttribute{}
+ list.SetSelectValue(bazel.NoConfigAxis, "", libsLabelList)
+ nativeSharedLibs.Native_shared_libs_32.Append(list)
+}
+
+func make32SharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) {
+ makeSharedLibsAttributes("x86", libsLabelList, &nativeSharedLibs.Native_shared_libs_32)
+ makeSharedLibsAttributes("arm", libsLabelList, &nativeSharedLibs.Native_shared_libs_32)
+}
+
+func make64SharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) {
+ makeSharedLibsAttributes("x86_64", libsLabelList, &nativeSharedLibs.Native_shared_libs_64)
+ makeSharedLibsAttributes("arm64", libsLabelList, &nativeSharedLibs.Native_shared_libs_64)
+}
+
+func makeSharedLibsAttributes(config string, libsLabelList bazel.LabelList,
+ labelListAttr *bazel.LabelListAttribute) {
+ list := bazel.LabelListAttribute{}
+ list.SetSelectValue(bazel.ArchConfigurationAxis, config, libsLabelList)
+ labelListAttr.Append(list)
+}
+
+func invalidCompileMultilib(ctx android.TopDownMutatorContext, value string) {
+ ctx.PropertyErrorf("compile_multilib", "Invalid value: %s", value)
+}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 727a1f2..c546fa1 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -623,7 +623,7 @@
java_libs: ["myjar"],
apps: ["AppFoo"],
rros: ["rro"],
- bpfs: ["bpf"],
+ bpfs: ["bpf", "netd_test"],
updatable: false,
}
@@ -676,6 +676,12 @@
srcs: ["bpf.c", "bpf2.c"],
}
+ bpf {
+ name: "netd_test",
+ srcs: ["netd_test.c"],
+ sub_dir: "netd",
+ }
+
`)
ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
"etc/myetc",
@@ -685,6 +691,7 @@
"overlay/blue/rro.apk",
"etc/bpf/bpf.o",
"etc/bpf/bpf2.o",
+ "etc/bpf/netd/netd_test.o",
})
}
@@ -7457,7 +7464,7 @@
},
{
name: "Bootclasspath apex jar not satisfying allowed module packages on Q.",
- expectedError: `(?s)module "bcp_lib2" .* which is restricted because jars that are part of the myapex module may only allow these packages: foo.bar with min_sdk < T. Please jarjar or move code around.`,
+ expectedError: `(?s)module "bcp_lib2" .* which is restricted because jars that are part of the myapex module may only use these package prefixes: foo.bar with min_sdk < T. Please consider the following alternatives:\n 1. If the offending code is from a statically linked library, consider removing that dependency and using an alternative already in the bootclasspath, or perhaps a shared library. 2. Move the offending code into an allowed package.\n 3. Jarjar the offending code. Please be mindful of the potential system health implications of bundling that code, particularly if the offending jar is part of the bootclasspath.`,
bp: `
java_library {
name: "bcp_lib1",
@@ -7494,7 +7501,7 @@
},
{
name: "Bootclasspath apex jar not satisfying allowed module packages on R.",
- expectedError: `(?s)module "bcp_lib2" .* which is restricted because jars that are part of the myapex module may only allow these packages: foo.bar with min_sdk < T. Please jarjar or move code around.`,
+ expectedError: `(?s)module "bcp_lib2" .* which is restricted because jars that are part of the myapex module may only use these package prefixes: foo.bar with min_sdk < T. Please consider the following alternatives:\n 1. If the offending code is from a statically linked library, consider removing that dependency and using an alternative already in the bootclasspath, or perhaps a shared library. 2. Move the offending code into an allowed package.\n 3. Jarjar the offending code. Please be mindful of the potential system health implications of bundling that code, particularly if the offending jar is part of the bootclasspath.`,
bp: `
java_library {
name: "bcp_lib1",
@@ -8739,6 +8746,22 @@
})
}
+// Verifies that the APEX depends on all the Make modules in the list.
+func ensureContainsRequiredDeps(t *testing.T, ctx *android.TestContext, moduleName, variant string, deps []string) {
+ a := ctx.ModuleForTests(moduleName, variant).Module().(*apexBundle)
+ for _, dep := range deps {
+ android.AssertStringListContains(t, "", a.requiredDeps, dep)
+ }
+}
+
+// Verifies that the APEX does not depend on any of the Make modules in the list.
+func ensureDoesNotContainRequiredDeps(t *testing.T, ctx *android.TestContext, moduleName, variant string, deps []string) {
+ a := ctx.ModuleForTests(moduleName, variant).Module().(*apexBundle)
+ for _, dep := range deps {
+ android.AssertStringListDoesNotContain(t, "", a.requiredDeps, dep)
+ }
+}
+
func TestMain(m *testing.M) {
os.Exit(m.Run())
}
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index ce828e1..8f44fc5 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -410,6 +410,7 @@
// bootclasspath_fragment's contents property.
java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
addSource("foo", "bar"),
+ java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
).RunTest(t)
ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
@@ -437,12 +438,62 @@
`mybootclasspathfragment`,
})
+ // The boot images are installed in the APEX by Soong, so there shouldn't be any dexpreopt-related Make modules.
+ ensureDoesNotContainRequiredDeps(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+ "mybootclasspathfragment-dexpreopt-arm64-boot.art",
+ "mybootclasspathfragment-dexpreopt-arm64-boot.oat",
+ "mybootclasspathfragment-dexpreopt-arm64-boot.vdex",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.art",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.oat",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.vdex",
+ "mybootclasspathfragment-dexpreopt-arm-boot.art",
+ "mybootclasspathfragment-dexpreopt-arm-boot.oat",
+ "mybootclasspathfragment-dexpreopt-arm-boot.vdex",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.art",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.oat",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.vdex",
+ })
+
// Make sure that the source bootclasspath_fragment copies its dex files to the predefined
// locations for the art image.
module := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
})
+ t.Run("boot image files from source no boot image in apex", func(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ commonPreparer,
+
+ // Configure some libraries in the art bootclasspath_fragment that match the source
+ // bootclasspath_fragment's contents property.
+ java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
+ addSource("foo", "bar"),
+ java.FixtureSetBootImageInstallDirOnDevice("art", "system/framework"),
+ ).RunTest(t)
+
+ ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+ "etc/boot-image.prof",
+ "etc/classpaths/bootclasspath.pb",
+ "javalib/bar.jar",
+ "javalib/foo.jar",
+ })
+
+ ensureContainsRequiredDeps(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+ "mybootclasspathfragment-dexpreopt-arm64-boot.art",
+ "mybootclasspathfragment-dexpreopt-arm64-boot.oat",
+ "mybootclasspathfragment-dexpreopt-arm64-boot.vdex",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.art",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.oat",
+ "mybootclasspathfragment-dexpreopt-arm64-boot-bar.vdex",
+ "mybootclasspathfragment-dexpreopt-arm-boot.art",
+ "mybootclasspathfragment-dexpreopt-arm-boot.oat",
+ "mybootclasspathfragment-dexpreopt-arm-boot.vdex",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.art",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.oat",
+ "mybootclasspathfragment-dexpreopt-arm-boot-bar.vdex",
+ })
+ })
+
t.Run("boot image disable generate profile", func(t *testing.T) {
result := android.GroupFixturePreparers(
commonPreparer,
@@ -472,6 +523,8 @@
// Make sure that a preferred prebuilt with consistent contents doesn't affect the apex.
addPrebuilt(true, "foo", "bar"),
+
+ java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
).RunTest(t)
ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index 41f9886..4dc0e4c 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -14,6 +14,7 @@
type CcInfo struct {
OutputFiles []string
CcObjectFiles []string
+ CcSharedLibraryFiles []string
CcStaticLibraryFiles []string
Includes []string
SystemIncludes []string
@@ -128,28 +129,43 @@
if linker_input.owner == target.label:
rootStaticArchives.append(library.static_library.path)
-rootDynamicLibraries = []
+sharedLibraries = []
+rootSharedLibraries = []
shared_info_tag = "@rules_cc//examples:experimental_cc_shared_library.bzl%CcSharedLibraryInfo"
if shared_info_tag in providers(target):
shared_info = providers(target)[shared_info_tag]
for lib in shared_info.linker_input.libraries:
- rootDynamicLibraries += [lib.dynamic_library.path]
+ path = lib.dynamic_library.path
+ rootSharedLibraries += [path]
+ sharedLibraries.append(path)
+else:
+ for linker_input in linker_inputs:
+ for library in linker_input.libraries:
+ if library.dynamic_library:
+ path = library.dynamic_library.path
+ sharedLibraries.append(path)
+ if linker_input.owner == target.label:
+ rootSharedLibraries.append(path)
toc_file = ""
toc_file_tag = "//build/bazel/rules:generate_toc.bzl%CcTocInfo"
if toc_file_tag in providers(target):
toc_file = providers(target)[toc_file_tag].toc.path
+else:
+ # NOTE: It's OK if there's no ToC, as Soong just uses it for optimization
+ pass
returns = [
outputFiles,
- staticLibraries,
ccObjectFiles,
+ sharedLibraries,
+ staticLibraries,
includes,
system_includes,
headers,
rootStaticArchives,
- rootDynamicLibraries,
+ rootSharedLibraries,
[toc_file]
]
@@ -160,28 +176,35 @@
// The given rawString must correspond to the string output which was created by evaluating the
// Starlark given in StarlarkFunctionBody.
func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) {
- var outputFiles []string
- var ccObjects []string
-
+ const expectedLen = 10
splitString := strings.Split(rawString, "|")
- if expectedLen := 9; len(splitString) != expectedLen {
+ if len(splitString) != expectedLen {
return CcInfo{}, fmt.Errorf("Expected %d items, got %q", expectedLen, splitString)
}
outputFilesString := splitString[0]
- ccStaticLibrariesString := splitString[1]
- ccObjectsString := splitString[2]
- outputFiles = splitOrEmpty(outputFilesString, ", ")
+ ccObjectsString := splitString[1]
+ ccSharedLibrariesString := splitString[2]
+ ccStaticLibrariesString := splitString[3]
+ includesString := splitString[4]
+ systemIncludesString := splitString[5]
+ headersString := splitString[6]
+ rootStaticArchivesString := splitString[7]
+ rootDynamicLibrariesString := splitString[8]
+ tocFile := splitString[9] // NOTE: Will be the empty string if there wasn't
+
+ outputFiles := splitOrEmpty(outputFilesString, ", ")
+ ccObjects := splitOrEmpty(ccObjectsString, ", ")
+ ccSharedLibraries := splitOrEmpty(ccSharedLibrariesString, ", ")
ccStaticLibraries := splitOrEmpty(ccStaticLibrariesString, ", ")
- ccObjects = splitOrEmpty(ccObjectsString, ", ")
- includes := splitOrEmpty(splitString[3], ", ")
- systemIncludes := splitOrEmpty(splitString[4], ", ")
- headers := splitOrEmpty(splitString[5], ", ")
- rootStaticArchives := splitOrEmpty(splitString[6], ", ")
- rootDynamicLibraries := splitOrEmpty(splitString[7], ", ")
- tocFile := splitString[8] // NOTE: Will be the empty string if there wasn't
+ includes := splitOrEmpty(includesString, ", ")
+ systemIncludes := splitOrEmpty(systemIncludesString, ", ")
+ headers := splitOrEmpty(headersString, ", ")
+ rootStaticArchives := splitOrEmpty(rootStaticArchivesString, ", ")
+ rootDynamicLibraries := splitOrEmpty(rootDynamicLibrariesString, ", ")
return CcInfo{
OutputFiles: outputFiles,
CcObjectFiles: ccObjects,
+ CcSharedLibraryFiles: ccSharedLibraries,
CcStaticLibraryFiles: ccStaticLibraries,
Includes: includes,
SystemIncludes: systemIncludes,
diff --git a/bazel/cquery/request_type_test.go b/bazel/cquery/request_type_test.go
index d3bcb45..606e285 100644
--- a/bazel/cquery/request_type_test.go
+++ b/bazel/cquery/request_type_test.go
@@ -63,6 +63,8 @@
}
func TestGetCcInfoParseResults(t *testing.T) {
+ const expectedSplits = 10
+ noResult := strings.Repeat("|", expectedSplits-1)
testCases := []struct {
description string
input string
@@ -71,10 +73,11 @@
}{
{
description: "no result",
- input: "||||||||",
+ input: noResult,
expectedOutput: CcInfo{
OutputFiles: []string{},
CcObjectFiles: []string{},
+ CcSharedLibraryFiles: []string{},
CcStaticLibraryFiles: []string{},
Includes: []string{},
SystemIncludes: []string{},
@@ -86,10 +89,11 @@
},
{
description: "only output",
- input: "test||||||||",
+ input: "test" + noResult,
expectedOutput: CcInfo{
OutputFiles: []string{"test"},
CcObjectFiles: []string{},
+ CcSharedLibraryFiles: []string{},
CcStaticLibraryFiles: []string{},
Includes: []string{},
SystemIncludes: []string{},
@@ -100,11 +104,37 @@
},
},
{
+ description: "only ToC",
+ input: noResult + "test",
+ expectedOutput: CcInfo{
+ OutputFiles: []string{},
+ CcObjectFiles: []string{},
+ CcSharedLibraryFiles: []string{},
+ CcStaticLibraryFiles: []string{},
+ Includes: []string{},
+ SystemIncludes: []string{},
+ Headers: []string{},
+ RootStaticArchives: []string{},
+ RootDynamicLibraries: []string{},
+ TocFile: "test",
+ },
+ },
+ {
description: "all items set",
- input: "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir|dir/subdir/hdr.h|rootstaticarchive1|rootdynamiclibrary1|lib.so.toc",
+ input: "out1, out2" +
+ "|object1, object2" +
+ "|shared_lib1, shared_lib2" +
+ "|static_lib1, static_lib2" +
+ "|., dir/subdir" +
+ "|system/dir, system/other/dir" +
+ "|dir/subdir/hdr.h" +
+ "|rootstaticarchive1" +
+ "|rootdynamiclibrary1" +
+ "|lib.so.toc",
expectedOutput: CcInfo{
OutputFiles: []string{"out1", "out2"},
CcObjectFiles: []string{"object1", "object2"},
+ CcSharedLibraryFiles: []string{"shared_lib1", "shared_lib2"},
CcStaticLibraryFiles: []string{"static_lib1", "static_lib2"},
Includes: []string{".", "dir/subdir"},
SystemIncludes: []string{"system/dir", "system/other/dir"},
@@ -118,22 +148,22 @@
description: "too few result splits",
input: "|",
expectedOutput: CcInfo{},
- expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 9, []string{"", ""}),
+ expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", expectedSplits, []string{"", ""}),
},
{
description: "too many result splits",
- input: strings.Repeat("|", 50),
+ input: strings.Repeat("|", expectedSplits+1), // 2 too many
expectedOutput: CcInfo{},
- expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 9, make([]string, 51)),
+ expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", expectedSplits, make([]string, expectedSplits+2)),
},
}
for _, tc := range testCases {
actualOutput, err := GetCcInfo.ParseResult(tc.input)
if (err == nil && tc.expectedErrorMessage != "") ||
(err != nil && err.Error() != tc.expectedErrorMessage) {
- t.Errorf("%q: expected Error %s, got %s", tc.description, tc.expectedErrorMessage, err)
+ t.Errorf("%q:\nexpected Error %s\n, got %s", tc.description, tc.expectedErrorMessage, err)
} else if err == nil && !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
- t.Errorf("%q: expected %#v != actual %#v", tc.description, tc.expectedOutput, actualOutput)
+ t.Errorf("%q:\n expected %#v\n!= actual %#v", tc.description, tc.expectedOutput, actualOutput)
}
}
}
diff --git a/bazel/properties.go b/bazel/properties.go
index 870d293..1300a53 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -492,7 +492,7 @@
// Verify post-condition; this should never fail, provided no additional
// axes are introduced.
if len(ba.ConfigurableValues) > 1 {
- panic(fmt.Errorf("error in collapsing attribute: %s", ba))
+ panic(fmt.Errorf("error in collapsing attribute: %#v", ba))
}
}
return nil
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index ae0fb11..4bcfa61 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -38,7 +38,6 @@
"build_conversion_test.go",
"bzl_conversion_test.go",
"cc_binary_conversion_test.go",
- "cc_genrule_conversion_test.go",
"cc_library_conversion_test.go",
"cc_library_headers_conversion_test.go",
"cc_library_shared_conversion_test.go",
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
index a3825e6..4b141c9 100644
--- a/bp2build/apex_conversion_test.go
+++ b/bp2build/apex_conversion_test.go
@@ -131,10 +131,21 @@
"key": `":com.android.apogee.key"`,
"manifest": `"apogee_manifest.json"`,
"min_sdk_version": `"29"`,
- "native_shared_libs": `[
+ "native_shared_libs_32": `[
":native_shared_lib_1",
":native_shared_lib_2",
]`,
+ "native_shared_libs_64": `select({
+ "//build/bazel/platforms/arch:arm64": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_2",
+ ],
+ "//build/bazel/platforms/arch:x86_64": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_2",
+ ],
+ "//conditions:default": [],
+ })`,
"prebuilts": `[
":pretend_prebuilt_1",
":pretend_prebuilt_2",
@@ -144,6 +155,126 @@
}})
}
+func TestApexBundleCompileMultilibBoth(t *testing.T) {
+ runApexTestCase(t, bp2buildTestCase{
+ description: "apex - example with compile_multilib=both",
+ moduleTypeUnderTest: "apex",
+ moduleTypeUnderTestFactory: apex.BundleFactory,
+ filesystem: map[string]string{},
+ blueprint: createMultilibBlueprint("both"),
+ expectedBazelTargets: []string{
+ makeBazelTarget("apex", "com.android.apogee", attrNameToString{
+ "native_shared_libs_32": `[
+ ":native_shared_lib_1",
+ ":native_shared_lib_3",
+ ] + select({
+ "//build/bazel/platforms/arch:arm": [":native_shared_lib_2"],
+ "//build/bazel/platforms/arch:x86": [":native_shared_lib_2"],
+ "//conditions:default": [],
+ })`,
+ "native_shared_libs_64": `select({
+ "//build/bazel/platforms/arch:arm64": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_4",
+ ":native_shared_lib_2",
+ ],
+ "//build/bazel/platforms/arch:x86_64": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_4",
+ ":native_shared_lib_2",
+ ],
+ "//conditions:default": [],
+ })`,
+ }),
+ }})
+}
+
+func TestApexBundleCompileMultilibFirst(t *testing.T) {
+ runApexTestCase(t, bp2buildTestCase{
+ description: "apex - example with compile_multilib=first",
+ moduleTypeUnderTest: "apex",
+ moduleTypeUnderTestFactory: apex.BundleFactory,
+ filesystem: map[string]string{},
+ blueprint: createMultilibBlueprint("first"),
+ expectedBazelTargets: []string{
+ makeBazelTarget("apex", "com.android.apogee", attrNameToString{
+ "native_shared_libs_32": `select({
+ "//build/bazel/platforms/arch:arm": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_3",
+ ":native_shared_lib_2",
+ ],
+ "//build/bazel/platforms/arch:x86": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_3",
+ ":native_shared_lib_2",
+ ],
+ "//conditions:default": [],
+ })`,
+ "native_shared_libs_64": `select({
+ "//build/bazel/platforms/arch:arm64": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_4",
+ ":native_shared_lib_2",
+ ],
+ "//build/bazel/platforms/arch:x86_64": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_4",
+ ":native_shared_lib_2",
+ ],
+ "//conditions:default": [],
+ })`,
+ }),
+ }})
+}
+
+func TestApexBundleCompileMultilib32(t *testing.T) {
+ runApexTestCase(t, bp2buildTestCase{
+ description: "apex - example with compile_multilib=32",
+ moduleTypeUnderTest: "apex",
+ moduleTypeUnderTestFactory: apex.BundleFactory,
+ filesystem: map[string]string{},
+ blueprint: createMultilibBlueprint("32"),
+ expectedBazelTargets: []string{
+ makeBazelTarget("apex", "com.android.apogee", attrNameToString{
+ "native_shared_libs_32": `[
+ ":native_shared_lib_1",
+ ":native_shared_lib_3",
+ ] + select({
+ "//build/bazel/platforms/arch:arm": [":native_shared_lib_2"],
+ "//build/bazel/platforms/arch:x86": [":native_shared_lib_2"],
+ "//conditions:default": [],
+ })`,
+ }),
+ }})
+}
+
+func TestApexBundleCompileMultilib64(t *testing.T) {
+ runApexTestCase(t, bp2buildTestCase{
+ description: "apex - example with compile_multilib=64",
+ moduleTypeUnderTest: "apex",
+ moduleTypeUnderTestFactory: apex.BundleFactory,
+ filesystem: map[string]string{},
+ blueprint: createMultilibBlueprint("64"),
+ expectedBazelTargets: []string{
+ makeBazelTarget("apex", "com.android.apogee", attrNameToString{
+ "native_shared_libs_64": `select({
+ "//build/bazel/platforms/arch:arm64": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_4",
+ ":native_shared_lib_2",
+ ],
+ "//build/bazel/platforms/arch:x86_64": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_4",
+ ":native_shared_lib_2",
+ ],
+ "//conditions:default": [],
+ })`,
+ }),
+ }})
+}
+
func TestApexBundleDefaultPropertyValues(t *testing.T) {
runApexTestCase(t, bp2buildTestCase{
description: "apex - default property values",
@@ -180,3 +311,53 @@
}),
}})
}
+
+func createMultilibBlueprint(compile_multilib string) string {
+ return `
+cc_library {
+ name: "native_shared_lib_1",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "native_shared_lib_2",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "native_shared_lib_3",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "native_shared_lib_4",
+ bazel_module: { bp2build_available: false },
+}
+
+apex {
+ name: "com.android.apogee",
+ compile_multilib: "` + compile_multilib + `",
+ multilib: {
+ both: {
+ native_shared_libs: [
+ "native_shared_lib_1",
+ ],
+ },
+ first: {
+ native_shared_libs: [
+ "native_shared_lib_2",
+ ],
+ },
+ lib32: {
+ native_shared_libs: [
+ "native_shared_lib_3",
+ ],
+ },
+ lib64: {
+ native_shared_libs: [
+ "native_shared_lib_4",
+ ],
+ },
+ },
+}`
+}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 54b59af..b3bec65 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -259,7 +259,9 @@
// Simple metrics tracking for bp2build
metrics := CodegenMetrics{
- ruleClassCount: make(map[string]uint64),
+ ruleClassCount: make(map[string]uint64),
+ convertedModuleTypeCount: make(map[string]uint64),
+ totalModuleTypeCount: make(map[string]uint64),
}
dirs := make(map[string]bool)
@@ -269,6 +271,7 @@
bpCtx := ctx.Context()
bpCtx.VisitAllModules(func(m blueprint.Module) {
dir := bpCtx.ModuleDir(m)
+ moduleType := bpCtx.ModuleType(m)
dirs[dir] = true
var targets []BazelTarget
@@ -292,7 +295,7 @@
// targets in the same BUILD file (or package).
// Log the module.
- metrics.AddConvertedModule(m.Name(), Handcrafted)
+ metrics.AddConvertedModule(m, moduleType, Handcrafted)
pathToBuildFile := getBazelPackagePath(b)
if _, exists := buildFileToAppend[pathToBuildFile]; exists {
@@ -312,7 +315,7 @@
// Handle modules converted to generated targets.
// Log the module.
- metrics.AddConvertedModule(m.Name(), Generated)
+ metrics.AddConvertedModule(aModule, moduleType, Generated)
// Handle modules with unconverted deps. By default, emit a warning.
if unconvertedDeps := aModule.GetUnconvertedBp2buildDeps(); len(unconvertedDeps) > 0 {
@@ -324,6 +327,15 @@
return
}
}
+ if unconvertedDeps := aModule.GetMissingBp2buildDeps(); len(unconvertedDeps) > 0 {
+ msg := fmt.Sprintf("%q depends on missing modules: %s", m.Name(), strings.Join(unconvertedDeps, ", "))
+ if ctx.unconvertedDepMode == warnUnconvertedDeps {
+ metrics.moduleWithMissingDepsMsgs = append(metrics.moduleWithMissingDepsMsgs, msg)
+ } else if ctx.unconvertedDepMode == errorModulesUnconvertedDeps {
+ errs = append(errs, fmt.Errorf(msg))
+ return
+ }
+ }
targets = generateBazelTargets(bpCtx, aModule)
for _, t := range targets {
// A module can potentially generate more than 1 Bazel
@@ -331,7 +343,7 @@
metrics.IncrementRuleClassCount(t.ruleClass)
}
} else {
- metrics.IncrementUnconvertedCount()
+ metrics.AddUnconvertedModule(moduleType)
return
}
case QueryView:
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 1440b6f..b21a477 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -301,6 +301,19 @@
},
},
{
+ description: "non-existent dep",
+ blueprint: `custom {
+ name: "has_dep",
+ arch_paths: [":dep"],
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("custom", "has_dep", attrNameToString{
+ "arch_paths": `[":dep__BP2BUILD__MISSING__DEP"]`,
+ }),
+ },
+ },
+ {
description: "arch-variant srcs",
blueprint: `custom {
name: "arch_paths",
diff --git a/bp2build/cc_genrule_conversion_test.go b/bp2build/cc_genrule_conversion_test.go
deleted file mode 100644
index 440b462..0000000
--- a/bp2build/cc_genrule_conversion_test.go
+++ /dev/null
@@ -1,235 +0,0 @@
-// 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.
-
-package bp2build
-
-import (
- "testing"
-
- "android/soong/android"
- "android/soong/cc"
-)
-
-var otherCcGenruleBp = map[string]string{
- "other/Android.bp": `cc_genrule {
- name: "foo.tool",
- out: ["foo_tool.out"],
- srcs: ["foo_tool.in"],
- cmd: "cp $(in) $(out)",
-}
-cc_genrule {
- name: "other.tool",
- out: ["other_tool.out"],
- srcs: ["other_tool.in"],
- cmd: "cp $(in) $(out)",
-}`,
-}
-
-func runCcGenruleTestCase(t *testing.T, tc bp2buildTestCase) {
- t.Helper()
- (&tc).moduleTypeUnderTest = "cc_genrule"
- (&tc).moduleTypeUnderTestFactory = cc.GenRuleFactory
- runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
-}
-
-func TestCliVariableReplacement(t *testing.T) {
- runCcGenruleTestCase(t, bp2buildTestCase{
- description: "cc_genrule with command line variable replacements",
- blueprint: `cc_genrule {
- name: "foo.tool",
- out: ["foo_tool.out"],
- srcs: ["foo_tool.in"],
- cmd: "cp $(in) $(out)",
- bazel_module: { bp2build_available: true },
-}
-
-cc_genrule {
- name: "foo",
- out: ["foo.out"],
- srcs: ["foo.in"],
- tools: [":foo.tool"],
- cmd: "$(location :foo.tool) --genDir=$(genDir) arg $(in) $(out)",
- bazel_module: { bp2build_available: true },
-}`,
- expectedBazelTargets: []string{
- 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)",
- blueprint: `cc_genrule {
- name: "foo.tools",
- out: ["foo_tool.out", "foo_tool2.out"],
- srcs: ["foo_tool.in"],
- cmd: "cp $(in) $(out)",
- bazel_module: { bp2build_available: true },
-}
-
-cc_genrule {
- name: "foo",
- out: ["foo.out"],
- srcs: ["foo.in"],
- tools: [":foo.tools"],
- cmd: "$(locations :foo.tools) -s $(out) $(in)",
- bazel_module: { bp2build_available: true },
-}`,
- 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"]`,
- }),
- },
- })
-}
-
-func TestUsingLocationsAbsoluteLabel(t *testing.T) {
- runCcGenruleTestCase(t, bp2buildTestCase{
- description: "cc_genrule using $(locations //absolute:label)",
- blueprint: `cc_genrule {
- name: "foo",
- out: ["foo.out"],
- srcs: ["foo.in"],
- tool_files: [":foo.tool"],
- cmd: "$(locations :foo.tool) -s $(out) $(in)",
- bazel_module: { bp2build_available: true },
-}`,
- 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)",
- blueprint: `cc_genrule {
- name: "foo",
- out: ["foo.out"],
- srcs: [":other.tool"],
- tool_files: [":foo.tool"],
- cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)",
- bazel_module: { bp2build_available: true },
-}`,
- 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",
- blueprint: `cc_genrule {
- name: "foo",
- out: ["foo.out"],
- srcs: ["foo.in"],
- tool_files: [":foo.tool", ":other.tool"],
- cmd: "$(location) -s $(out) $(in)",
- bazel_module: { bp2build_available: true },
-}`,
- 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",
- ]`,
- }),
- },
- })
-}
-
-func TestLocationsLabelUsesFirstTool(t *testing.T) {
- runCcGenruleTestCase(t, bp2buildTestCase{
- description: "cc_genrule using $(locations) label should substitute first tool label automatically",
- blueprint: `cc_genrule {
- name: "foo",
- out: ["foo.out"],
- srcs: ["foo.in"],
- tools: [":foo.tool", ":other.tool"],
- cmd: "$(locations) -s $(out) $(in)",
- bazel_module: { bp2build_available: true },
-}`,
- 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",
- ]`,
- }),
- },
- })
-}
-
-func TestWithoutToolsOrToolFiles(t *testing.T) {
- runCcGenruleTestCase(t, bp2buildTestCase{
- description: "cc_genrule without tools or tool_files can convert successfully",
- blueprint: `cc_genrule {
- name: "foo",
- out: ["foo.out"],
- srcs: ["foo.in"],
- cmd: "cp $(in) $(out)",
- bazel_module: { bp2build_available: true },
-}`,
- 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 59a2389..de4f437 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -1297,6 +1297,8 @@
"additional_linker_inputs": true,
"linkopts": true,
"strip": true,
+ "stubs_symbol_file": true,
+ "stubs_versions": true,
}
sharedAttrs := attrNameToString{}
staticAttrs := attrNameToString{}
@@ -2390,3 +2392,32 @@
}),
}})
}
+
+func TestCcLibraryStubs(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ description: "cc_library stubs",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ dir: "foo/bar",
+ filesystem: map[string]string{
+ "foo/bar/Android.bp": `
+cc_library {
+ name: "a",
+ stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
+ bazel_module: { bp2build_available: true },
+ include_build_directory: false,
+}
+`,
+ },
+ blueprint: soongCcLibraryPreamble,
+ expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{
+ "stubs_symbol_file": `"a.map.txt"`,
+ "stubs_versions": `[
+ "28",
+ "29",
+ "current",
+ ]`,
+ }),
+ },
+ )
+}
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 97a600a..0f67653 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -464,3 +464,33 @@
},
})
}
+
+func TestCcLibrarySharedStubs(t *testing.T) {
+ runCcLibrarySharedTestCase(t, bp2buildTestCase{
+ description: "cc_library_shared stubs",
+ moduleTypeUnderTest: "cc_library_shared",
+ moduleTypeUnderTestFactory: cc.LibrarySharedFactory,
+ dir: "foo/bar",
+ filesystem: map[string]string{
+ "foo/bar/Android.bp": `
+cc_library_shared {
+ name: "a",
+ stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
+ bazel_module: { bp2build_available: true },
+ include_build_directory: false,
+}
+`,
+ },
+ blueprint: soongCcLibraryPreamble,
+ expectedBazelTargets: []string{makeBazelTarget("cc_library_shared", "a", attrNameToString{
+ "stubs_symbol_file": `"a.map.txt"`,
+ "stubs_versions": `[
+ "28",
+ "29",
+ "current",
+ ]`,
+ }),
+ },
+ },
+ )
+}
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 81a4b26..96c12d3 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -1,6 +1,7 @@
package bp2build
import (
+ "encoding/json"
"fmt"
"reflect"
"strings"
@@ -27,6 +28,13 @@
files = append(files, newFile("product_config", "soong_config_variables.bzl", cfg.Bp2buildSoongConfigDefinitions.String()))
+ apiLevelsContent, err := json.Marshal(android.GetApiLevelsMap(cfg))
+ if err != nil {
+ panic(err)
+ }
+ files = append(files, newFile("api_levels", GeneratedBuildFileName, `exports_files(["api_levels.json"])`))
+ files = append(files, newFile("api_levels", "api_levels.json", string(apiLevelsContent)))
+
return files
}
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index 3e6d9e6..629ca9b 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -102,6 +102,14 @@
dir: "product_config",
basename: "soong_config_variables.bzl",
},
+ {
+ dir: "api_levels",
+ basename: GeneratedBuildFileName,
+ },
+ {
+ dir: "api_levels",
+ basename: "api_levels.json",
+ },
}
if len(files) != len(expectedFilePaths) {
diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go
index fd631a5..0666da7 100644
--- a/bp2build/genrule_conversion_test.go
+++ b/bp2build/genrule_conversion_test.go
@@ -16,7 +16,10 @@
import (
"android/soong/android"
+ "android/soong/cc"
"android/soong/genrule"
+ "android/soong/java"
+ "fmt"
"testing"
)
@@ -31,58 +34,114 @@
runBp2BuildTestCase(t, registerGenruleModuleTypes, tc)
}
-func TestGenruleBp2Build(t *testing.T) {
- otherGenruleBp := map[string]string{
- "other/Android.bp": `genrule {
+func otherGenruleBp(genruleTarget string) map[string]string {
+ return map[string]string{
+ "other/Android.bp": fmt.Sprintf(`%s {
name: "foo.tool",
out: ["foo_tool.out"],
srcs: ["foo_tool.in"],
cmd: "cp $(in) $(out)",
}
-genrule {
+%s {
name: "other.tool",
out: ["other_tool.out"],
srcs: ["other_tool.in"],
cmd: "cp $(in) $(out)",
-}`,
+}`, genruleTarget, genruleTarget),
+ }
+}
+
+func TestGenruleCliVariableReplacement(t *testing.T) {
+ testCases := []struct {
+ moduleType string
+ factory android.ModuleFactory
+ genDir string
+ }{
+ {
+ moduleType: "genrule",
+ factory: genrule.GenRuleFactory,
+ genDir: "$(GENDIR)",
+ },
+ {
+ moduleType: "cc_genrule",
+ factory: cc.GenRuleFactory,
+ genDir: "$(RULEDIR)",
+ },
+ {
+ moduleType: "java_genrule",
+ factory: java.GenRuleFactory,
+ genDir: "$(RULEDIR)",
+ },
+ {
+ moduleType: "java_genrule_host",
+ factory: java.GenRuleFactoryHost,
+ genDir: "$(RULEDIR)",
+ },
}
- testCases := []bp2buildTestCase{
- {
- description: "genrule with command line variable replacements",
- blueprint: `genrule {
+ bp := `%s {
name: "foo.tool",
out: ["foo_tool.out"],
srcs: ["foo_tool.in"],
cmd: "cp $(in) $(out)",
- bazel_module: { bp2build_available: true },
+ bazel_module: { bp2build_available: false },
}
-genrule {
+%s {
name: "foo",
out: ["foo.out"],
srcs: ["foo.in"],
tools: [":foo.tool"],
cmd: "$(location :foo.tool) --genDir=$(genDir) arg $(in) $(out)",
bazel_module: { bp2build_available: true },
-}`,
- expectedBazelTargets: []string{
- 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"]`,
- }),
- },
+}`
+
+ for _, tc := range testCases {
+ expectedBazelTargets := []string{
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": fmt.Sprintf(`"$(location :foo.tool) --genDir=%s arg $(SRCS) $(OUTS)"`, tc.genDir),
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ "tools": `[":foo.tool"]`,
+ }),
+ }
+
+ t.Run(tc.moduleType, func(t *testing.T) {
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+ bp2buildTestCase{
+ moduleTypeUnderTest: tc.moduleType,
+ moduleTypeUnderTestFactory: tc.factory,
+ blueprint: fmt.Sprintf(bp, tc.moduleType, tc.moduleType),
+ expectedBazelTargets: expectedBazelTargets,
+ })
+ })
+ }
+}
+
+func TestGenruleLocationsLabel(t *testing.T) {
+ testCases := []struct {
+ moduleType string
+ factory android.ModuleFactory
+ }{
+ {
+ moduleType: "genrule",
+ factory: genrule.GenRuleFactory,
},
{
- description: "genrule using $(locations :label)",
- blueprint: `genrule {
+ moduleType: "cc_genrule",
+ factory: cc.GenRuleFactory,
+ },
+ {
+ moduleType: "java_genrule",
+ factory: java.GenRuleFactory,
+ },
+ {
+ moduleType: "java_genrule_host",
+ factory: java.GenRuleFactoryHost,
+ },
+ }
+
+ bp := `%s {
name: "foo.tools",
out: ["foo_tool.out", "foo_tool2.out"],
srcs: ["foo_tool.in"],
@@ -90,144 +149,322 @@
bazel_module: { bp2build_available: true },
}
-genrule {
+%s {
name: "foo",
out: ["foo.out"],
srcs: ["foo.in"],
tools: [":foo.tools"],
cmd: "$(locations :foo.tools) -s $(out) $(in)",
bazel_module: { bp2build_available: true },
-}`,
- 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": `[
+}`
+
+ 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"]`,
+ }),
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.moduleType, func(t *testing.T) {
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+ bp2buildTestCase{
+ moduleTypeUnderTest: tc.moduleType,
+ moduleTypeUnderTestFactory: tc.factory,
+ blueprint: fmt.Sprintf(bp, tc.moduleType, tc.moduleType),
+ expectedBazelTargets: expectedBazelTargets,
+ })
+ })
+ }
+}
+
+func TestGenruleLocationsAbsoluteLabel(t *testing.T) {
+ testCases := []struct {
+ moduleType string
+ factory android.ModuleFactory
+ }{
+ {
+ moduleType: "genrule",
+ factory: genrule.GenRuleFactory,
},
{
- description: "genrule using $(locations //absolute:label)",
- blueprint: `genrule {
+ moduleType: "cc_genrule",
+ factory: cc.GenRuleFactory,
+ },
+ {
+ moduleType: "java_genrule",
+ factory: java.GenRuleFactory,
+ },
+ {
+ moduleType: "java_genrule_host",
+ factory: java.GenRuleFactoryHost,
+ },
+ }
+
+ bp := `%s {
name: "foo",
out: ["foo.out"],
srcs: ["foo.in"],
tool_files: [":foo.tool"],
cmd: "$(locations :foo.tool) -s $(out) $(in)",
bazel_module: { bp2build_available: true },
-}`,
- 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,
+}`
+
+ expectedBazelTargets := []string{
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ "tools": `["//other:foo.tool"]`,
+ }),
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.moduleType, func(t *testing.T) {
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+ bp2buildTestCase{
+ moduleTypeUnderTest: tc.moduleType,
+ moduleTypeUnderTestFactory: tc.factory,
+ blueprint: fmt.Sprintf(bp, tc.moduleType),
+ expectedBazelTargets: expectedBazelTargets,
+ filesystem: otherGenruleBp(tc.moduleType),
+ })
+ })
+ }
+}
+
+func TestGenruleSrcsLocationsAbsoluteLabel(t *testing.T) {
+ testCases := []struct {
+ moduleType string
+ factory android.ModuleFactory
+ }{
+ {
+ moduleType: "genrule",
+ factory: genrule.GenRuleFactory,
},
{
- description: "genrule srcs using $(locations //absolute:label)",
- blueprint: `genrule {
+ moduleType: "cc_genrule",
+ factory: cc.GenRuleFactory,
+ },
+ {
+ moduleType: "java_genrule",
+ factory: java.GenRuleFactory,
+ },
+ {
+ moduleType: "java_genrule_host",
+ factory: java.GenRuleFactoryHost,
+ },
+ }
+
+ bp := `%s {
name: "foo",
out: ["foo.out"],
srcs: [":other.tool"],
tool_files: [":foo.tool"],
cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)",
bazel_module: { bp2build_available: true },
-}`,
- 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,
+}`
+
+ 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"]`,
+ }),
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.moduleType, func(t *testing.T) {
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+ bp2buildTestCase{
+ moduleTypeUnderTest: tc.moduleType,
+ moduleTypeUnderTestFactory: tc.factory,
+ blueprint: fmt.Sprintf(bp, tc.moduleType),
+ expectedBazelTargets: expectedBazelTargets,
+ filesystem: otherGenruleBp(tc.moduleType),
+ })
+ })
+ }
+}
+
+func TestGenruleLocationLabelShouldSubstituteFirstToolLabel(t *testing.T) {
+ testCases := []struct {
+ moduleType string
+ factory android.ModuleFactory
+ }{
+ {
+ moduleType: "genrule",
+ factory: genrule.GenRuleFactory,
},
{
- description: "genrule using $(location) label should substitute first tool label automatically",
- blueprint: `genrule {
+ moduleType: "cc_genrule",
+ factory: cc.GenRuleFactory,
+ },
+ {
+ moduleType: "java_genrule",
+ factory: java.GenRuleFactory,
+ },
+ {
+ moduleType: "java_genrule_host",
+ factory: java.GenRuleFactoryHost,
+ },
+ }
+
+ bp := `%s {
name: "foo",
out: ["foo.out"],
srcs: ["foo.in"],
tool_files: [":foo.tool", ":other.tool"],
cmd: "$(location) -s $(out) $(in)",
bazel_module: { bp2build_available: true },
-}`,
- expectedBazelTargets: []string{
- makeBazelTarget("genrule", "foo", attrNameToString{
- "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,
+ })}
+
+ for _, tc := range testCases {
+ t.Run(tc.moduleType, func(t *testing.T) {
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+ bp2buildTestCase{
+ moduleTypeUnderTest: tc.moduleType,
+ moduleTypeUnderTestFactory: tc.factory,
+ blueprint: fmt.Sprintf(bp, tc.moduleType),
+ expectedBazelTargets: expectedBazelTargets,
+ filesystem: otherGenruleBp(tc.moduleType),
+ })
+ })
+ }
+}
+
+func TestGenruleLocationsLabelShouldSubstituteFirstToolLabel(t *testing.T) {
+ testCases := []struct {
+ moduleType string
+ factory android.ModuleFactory
+ }{
+ {
+ moduleType: "genrule",
+ factory: genrule.GenRuleFactory,
},
{
- description: "genrule using $(locations) label should substitute first tool label automatically",
- blueprint: `genrule {
+ moduleType: "cc_genrule",
+ factory: cc.GenRuleFactory,
+ },
+ {
+ moduleType: "java_genrule",
+ factory: java.GenRuleFactory,
+ },
+ {
+ moduleType: "java_genrule_host",
+ factory: java.GenRuleFactoryHost,
+ },
+ }
+
+ bp := `%s {
name: "foo",
out: ["foo.out"],
srcs: ["foo.in"],
- tools: [":foo.tool", ":other.tool"],
+ tool_files: [":foo.tool", ":other.tool"],
cmd: "$(locations) -s $(out) $(in)",
bazel_module: { bp2build_available: true },
-}`,
- expectedBazelTargets: []string{
- makeBazelTarget("genrule", "foo", attrNameToString{
- "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,
+ })}
+
+ for _, tc := range testCases {
+ t.Run(tc.moduleType, func(t *testing.T) {
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+ bp2buildTestCase{
+ moduleTypeUnderTest: tc.moduleType,
+ moduleTypeUnderTestFactory: tc.factory,
+ blueprint: fmt.Sprintf(bp, tc.moduleType),
+ expectedBazelTargets: expectedBazelTargets,
+ filesystem: otherGenruleBp(tc.moduleType),
+ })
+ })
+ }
+}
+
+func TestGenruleWithoutToolsOrToolFiles(t *testing.T) {
+ testCases := []struct {
+ moduleType string
+ factory android.ModuleFactory
+ }{
+ {
+ moduleType: "genrule",
+ factory: genrule.GenRuleFactory,
},
{
- description: "genrule without tools or tool_files can convert successfully",
- blueprint: `genrule {
+ moduleType: "cc_genrule",
+ factory: cc.GenRuleFactory,
+ },
+ {
+ moduleType: "java_genrule",
+ factory: java.GenRuleFactory,
+ },
+ {
+ moduleType: "java_genrule_host",
+ factory: java.GenRuleFactoryHost,
+ },
+ }
+
+ bp := `%s {
name: "foo",
out: ["foo.out"],
srcs: ["foo.in"],
cmd: "cp $(in) $(out)",
bazel_module: { bp2build_available: true },
-}`,
- expectedBazelTargets: []string{
- makeBazelTarget("genrule", "foo", attrNameToString{
- "cmd": `"cp $(SRCS) $(OUTS)"`,
- "outs": `["foo.out"]`,
- "srcs": `["foo.in"]`,
- }),
- },
- },
- }
+}`
- for _, testCase := range testCases {
- t.Run(testCase.description, func(t *testing.T) {
- runGenruleTestCase(t, testCase)
+ expectedBazelTargets := []string{
+ makeBazelTarget("genrule", "foo", attrNameToString{
+ "cmd": `"cp $(SRCS) $(OUTS)"`,
+ "outs": `["foo.out"]`,
+ "srcs": `["foo.in"]`,
+ })}
+
+ for _, tc := range testCases {
+ t.Run(tc.moduleType, func(t *testing.T) {
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+ bp2buildTestCase{
+ moduleTypeUnderTest: tc.moduleType,
+ moduleTypeUnderTestFactory: tc.factory,
+ blueprint: fmt.Sprintf(bp, tc.moduleType),
+ expectedBazelTargets: expectedBazelTargets,
+ })
})
}
}
-func TestBp2BuildInlinesDefaults(t *testing.T) {
+func TestGenruleBp2BuildInlinesDefaults(t *testing.T) {
testCases := []bp2buildTestCase{
{
description: "genrule applies properties from a genrule_defaults dependency if not specified",
diff --git a/bp2build/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go
index 96b8958..c683b25 100644
--- a/bp2build/java_binary_host_conversion_test.go
+++ b/bp2build/java_binary_host_conversion_test.go
@@ -41,7 +41,7 @@
func TestJavaBinaryHost(t *testing.T) {
runJavaBinaryHostTestCase(t, bp2buildTestCase{
- description: "java_binary_host with srcs, exclude_srcs, jni_libs and manifest.",
+ description: "java_binary_host with srcs, exclude_srcs, jni_libs, javacflags, and manifest.",
filesystem: fs,
blueprint: `java_binary_host {
name: "java-binary-host-1",
@@ -49,6 +49,7 @@
exclude_srcs: ["b.java"],
manifest: "test.mf",
jni_libs: ["jni-lib-1"],
+ javacflags: ["-Xdoclint:all/protected"],
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []string{
@@ -57,6 +58,7 @@
"main_class": `"com.android.test.MainClass"`,
"deps": `["//other:jni-lib-1"]`,
"jvm_flags": `["-Djava.library.path=$${RUNPATH}other"]`,
+ "javacopts": `["-Xdoclint:all/protected"]`,
}),
},
})
diff --git a/bp2build/metrics.go b/bp2build/metrics.go
index 68ac544..8a0b1c9 100644
--- a/bp2build/metrics.go
+++ b/bp2build/metrics.go
@@ -9,6 +9,7 @@
"android/soong/android"
"android/soong/shared"
"android/soong/ui/metrics/bp2build_metrics_proto"
+ "github.com/google/blueprint"
)
// Simple metrics struct to collect information about a Blueprint to BUILD
@@ -30,18 +31,30 @@
// NOTE: NOT in the .proto
moduleWithUnconvertedDepsMsgs []string
+ // List of modules with missing deps
+ // NOTE: NOT in the .proto
+ moduleWithMissingDepsMsgs []string
+
// List of converted modules
convertedModules []string
+
+ // Counts of converted modules by module type.
+ convertedModuleTypeCount map[string]uint64
+
+ // Counts of total modules by module type.
+ totalModuleTypeCount map[string]uint64
}
// Serialize returns the protoized version of CodegenMetrics: bp2build_metrics_proto.Bp2BuildMetrics
func (metrics *CodegenMetrics) Serialize() bp2build_metrics_proto.Bp2BuildMetrics {
return bp2build_metrics_proto.Bp2BuildMetrics{
- GeneratedModuleCount: metrics.generatedModuleCount,
- HandCraftedModuleCount: metrics.handCraftedModuleCount,
- UnconvertedModuleCount: metrics.unconvertedModuleCount,
- RuleClassCount: metrics.ruleClassCount,
- ConvertedModules: metrics.convertedModules,
+ GeneratedModuleCount: metrics.generatedModuleCount,
+ HandCraftedModuleCount: metrics.handCraftedModuleCount,
+ UnconvertedModuleCount: metrics.unconvertedModuleCount,
+ RuleClassCount: metrics.ruleClassCount,
+ ConvertedModules: metrics.convertedModules,
+ ConvertedModuleTypeCount: metrics.convertedModuleTypeCount,
+ TotalModuleTypeCount: metrics.totalModuleTypeCount,
}
}
@@ -54,13 +67,21 @@
generatedTargetCount += count
}
fmt.Printf(
- "[bp2build] Converted %d Android.bp modules to %d total generated BUILD targets. Included %d handcrafted BUILD targets. There are %d total Android.bp modules.\n%d converted modules have unconverted deps: \n\t%s",
+ `[bp2build] Converted %d Android.bp modules to %d total generated BUILD targets. Included %d handcrafted BUILD targets. There are %d total Android.bp modules.
+%d converted modules have unconverted deps:
+ %s
+%d converted modules have missing deps:
+ %s
+`,
metrics.generatedModuleCount,
generatedTargetCount,
metrics.handCraftedModuleCount,
metrics.TotalModuleCount(),
len(metrics.moduleWithUnconvertedDepsMsgs),
- strings.Join(metrics.moduleWithUnconvertedDepsMsgs, "\n\t"))
+ strings.Join(metrics.moduleWithUnconvertedDepsMsgs, "\n\t"),
+ len(metrics.moduleWithMissingDepsMsgs),
+ strings.Join(metrics.moduleWithMissingDepsMsgs, "\n\t"),
+ )
}
const bp2buildMetricsFilename = "bp2build_metrics.pb"
@@ -101,8 +122,9 @@
metrics.ruleClassCount[ruleClass] += 1
}
-func (metrics *CodegenMetrics) IncrementUnconvertedCount() {
+func (metrics *CodegenMetrics) AddUnconvertedModule(moduleType string) {
metrics.unconvertedModuleCount += 1
+ metrics.totalModuleTypeCount[moduleType] += 1
}
func (metrics *CodegenMetrics) TotalModuleCount() uint64 {
@@ -124,10 +146,12 @@
Handcrafted
)
-func (metrics *CodegenMetrics) AddConvertedModule(moduleName string, conversionType ConversionType) {
+func (metrics *CodegenMetrics) AddConvertedModule(m blueprint.Module, moduleType string, conversionType ConversionType) {
// Undo prebuilt_ module name prefix modifications
- moduleName = android.RemoveOptionalPrebuiltPrefix(moduleName)
+ moduleName := android.RemoveOptionalPrebuiltPrefix(m.Name())
metrics.convertedModules = append(metrics.convertedModules, moduleName)
+ metrics.convertedModuleTypeCount[moduleType] += 1
+ metrics.totalModuleTypeCount[moduleType] += 1
if conversionType == Handcrafted {
metrics.handCraftedModuleCount += 1
diff --git a/bp2build/soong_config_module_type_conversion_test.go b/bp2build/soong_config_module_type_conversion_test.go
index f1489aa..b1e1fb2 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__enabled": ["-DFEATURE1"],
+ "//build/bazel/product_variables:acme__feature1": ["-DFEATURE1"],
"//conditions:default": ["-DDEFAULT1"],
}),
local_includes = ["."],
@@ -116,7 +116,7 @@
expectedBazelTargets: []string{`cc_library_static(
name = "foo",
copts = select({
- "//build/bazel/product_variables:acme__feature1__enabled": ["-DFEATURE1"],
+ "//build/bazel/product_variables:acme__feature1": ["-DFEATURE1"],
"//conditions:default": ["-DDEFAULT1"],
}),
local_includes = ["."],
@@ -240,10 +240,10 @@
"//build/bazel/product_variables:acme__board__soc_b": ["-DSOC_B"],
"//conditions:default": ["-DSOC_DEFAULT"],
}) + select({
- "//build/bazel/product_variables:acme__feature1__enabled": ["-DFEATURE1"],
+ "//build/bazel/product_variables:acme__feature1": ["-DFEATURE1"],
"//conditions:default": ["-DDEFAULT1"],
}) + select({
- "//build/bazel/product_variables:acme__feature2__enabled": ["-DFEATURE2"],
+ "//build/bazel/product_variables:acme__feature2": ["-DFEATURE2"],
"//conditions:default": ["-DDEFAULT2"],
}),
local_includes = ["."],
@@ -367,7 +367,7 @@
expectedBazelTargets: []string{`cc_library_static(
name = "lib",
copts = select({
- "//build/bazel/product_variables:vendor_foo__feature__enabled": [
+ "//build/bazel/product_variables:vendor_foo__feature": [
"-cflag_feature_2",
"-cflag_feature_1",
],
@@ -446,11 +446,11 @@
expectedBazelTargets: []string{`cc_library_static(
name = "lib",
asflags = select({
- "//build/bazel/product_variables:acme__feature__enabled": ["-asflag_bar"],
+ "//build/bazel/product_variables:acme__feature": ["-asflag_bar"],
"//conditions:default": ["-asflag_default_bar"],
}),
copts = select({
- "//build/bazel/product_variables:acme__feature__enabled": [
+ "//build/bazel/product_variables:acme__feature": [
"-cflag_foo",
"-cflag_bar",
],
@@ -465,11 +465,11 @@
`cc_library_static(
name = "lib2",
asflags = select({
- "//build/bazel/product_variables:acme__feature__enabled": ["-asflag_bar"],
+ "//build/bazel/product_variables:acme__feature": ["-asflag_bar"],
"//conditions:default": ["-asflag_default_bar"],
}),
copts = select({
- "//build/bazel/product_variables:acme__feature__enabled": [
+ "//build/bazel/product_variables:acme__feature": [
"-cflag_bar",
"-cflag_foo",
],
@@ -561,13 +561,13 @@
expectedBazelTargets: []string{`cc_library_static(
name = "lib",
copts = select({
- "//build/bazel/product_variables:vendor_bar__feature__enabled": ["-DVENDOR_BAR_FEATURE"],
+ "//build/bazel/product_variables:vendor_bar__feature": ["-DVENDOR_BAR_FEATURE"],
"//conditions:default": ["-DVENDOR_BAR_DEFAULT"],
}) + select({
- "//build/bazel/product_variables:vendor_foo__feature__enabled": ["-DVENDOR_FOO_FEATURE"],
+ "//build/bazel/product_variables:vendor_foo__feature": ["-DVENDOR_FOO_FEATURE"],
"//conditions:default": ["-DVENDOR_FOO_DEFAULT"],
}) + select({
- "//build/bazel/product_variables:vendor_qux__feature__enabled": ["-DVENDOR_QUX_FEATURE"],
+ "//build/bazel/product_variables:vendor_qux__feature": ["-DVENDOR_QUX_FEATURE"],
"//conditions:default": ["-DVENDOR_QUX_DEFAULT"],
}),
local_includes = ["."],
@@ -834,3 +834,152 @@
srcs = ["main.cc"],
)`}})
}
+
+func TestSoongConfigModuleType_ProductVariableConfigWithPlatformConfig(t *testing.T) {
+ bp := `
+soong_config_bool_variable {
+ name: "special_build",
+}
+
+soong_config_module_type {
+ name: "alphabet_cc_defaults",
+ module_type: "cc_defaults",
+ config_namespace: "alphabet_module",
+ bool_variables: ["special_build"],
+ properties: ["enabled"],
+}
+
+alphabet_cc_defaults {
+ name: "alphabet_sample_cc_defaults",
+ soong_config_variables: {
+ special_build: {
+ enabled: true,
+ },
+ },
+}
+
+cc_binary {
+ name: "alphabet_binary",
+ srcs: ["main.cc"],
+ defaults: ["alphabet_sample_cc_defaults"],
+ enabled: false,
+ arch: {
+ x86_64: {
+ enabled: false,
+ },
+ },
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+}`
+
+ runSoongConfigModuleTypeTest(t, bp2buildTestCase{
+ description: "soong config variables - generates selects for library_linking_strategy",
+ moduleTypeUnderTest: "cc_binary",
+ moduleTypeUnderTestFactory: cc.BinaryFactory,
+ blueprint: bp,
+ filesystem: map[string]string{},
+ expectedBazelTargets: []string{`cc_binary(
+ name = "alphabet_binary",
+ local_includes = ["."],
+ srcs = ["main.cc"],
+ target_compatible_with = ["//build/bazel/product_variables:alphabet_module__special_build"] + select({
+ "//build/bazel/platforms/os_arch:android_x86_64": ["@platforms//:incompatible"],
+ "//build/bazel/platforms/os_arch:darwin_arm64": ["@platforms//:incompatible"],
+ "//build/bazel/platforms/os_arch:darwin_x86_64": ["@platforms//:incompatible"],
+ "//build/bazel/platforms/os_arch:linux_bionic_x86_64": ["@platforms//:incompatible"],
+ "//build/bazel/platforms/os_arch:linux_glibc_x86_64": ["@platforms//:incompatible"],
+ "//build/bazel/platforms/os_arch:linux_musl_x86_64": ["@platforms//:incompatible"],
+ "//build/bazel/platforms/os_arch:windows_x86_64": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ }),
+)`}})
+}
+
+func TestSoongConfigModuleType_ProductVariableConfigOverridesEnable(t *testing.T) {
+ bp := `
+soong_config_bool_variable {
+ name: "special_build",
+}
+
+soong_config_module_type {
+ name: "alphabet_cc_defaults",
+ module_type: "cc_defaults",
+ config_namespace: "alphabet_module",
+ bool_variables: ["special_build"],
+ properties: ["enabled"],
+}
+
+alphabet_cc_defaults {
+ name: "alphabet_sample_cc_defaults",
+ soong_config_variables: {
+ special_build: {
+ enabled: true,
+ },
+ },
+}
+
+cc_binary {
+ name: "alphabet_binary",
+ srcs: ["main.cc"],
+ defaults: ["alphabet_sample_cc_defaults"],
+ enabled: false,
+}`
+
+ runSoongConfigModuleTypeTest(t, bp2buildTestCase{
+ description: "soong config variables - generates selects for library_linking_strategy",
+ moduleTypeUnderTest: "cc_binary",
+ moduleTypeUnderTestFactory: cc.BinaryFactory,
+ blueprint: bp,
+ filesystem: map[string]string{},
+ expectedBazelTargets: []string{`cc_binary(
+ name = "alphabet_binary",
+ local_includes = ["."],
+ srcs = ["main.cc"],
+ target_compatible_with = ["//build/bazel/product_variables:alphabet_module__special_build"],
+)`}})
+}
+
+func TestSoongConfigModuleType_ProductVariableIgnoredIfEnabledByDefault(t *testing.T) {
+ bp := `
+soong_config_bool_variable {
+ name: "special_build",
+}
+
+soong_config_module_type {
+ name: "alphabet_cc_defaults",
+ module_type: "cc_defaults",
+ config_namespace: "alphabet_module",
+ bool_variables: ["special_build"],
+ properties: ["enabled"],
+}
+
+alphabet_cc_defaults {
+ name: "alphabet_sample_cc_defaults",
+ soong_config_variables: {
+ special_build: {
+ enabled: true,
+ },
+ },
+}
+
+cc_binary {
+ name: "alphabet_binary",
+ srcs: ["main.cc"],
+ defaults: ["alphabet_sample_cc_defaults"],
+}`
+
+ runSoongConfigModuleTypeTest(t, bp2buildTestCase{
+ description: "soong config variables - generates selects for library_linking_strategy",
+ moduleTypeUnderTest: "cc_binary",
+ moduleTypeUnderTestFactory: cc.BinaryFactory,
+ blueprint: bp,
+ filesystem: map[string]string{},
+ expectedBazelTargets: []string{`cc_binary(
+ name = "alphabet_binary",
+ local_includes = ["."],
+ srcs = ["main.cc"],
+)`}})
+}
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 9f0c86c..187b4db 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -54,12 +54,16 @@
android.Module
OutputFiles(tag string) (android.Paths, error)
+
+ // Returns the sub install directory if the bpf module is included by apex.
+ SubDir() string
}
type BpfProperties struct {
Srcs []string `android:"path"`
Cflags []string
Include_dirs []string
+ Sub_dir string
}
type bpf struct {
@@ -121,6 +125,10 @@
fmt.Fprintln(w)
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
fmt.Fprintln(w)
+ localModulePath := "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf"
+ if len(bpf.properties.Sub_dir) > 0 {
+ localModulePath += "/" + bpf.properties.Sub_dir
+ }
for _, obj := range bpf.objs {
objName := name + "_" + obj.Base()
names = append(names, objName)
@@ -130,7 +138,7 @@
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", obj.String())
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", obj.Base())
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
- fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf")
+ fmt.Fprintln(w, localModulePath)
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
fmt.Fprintln(w)
}
@@ -154,6 +162,10 @@
}
}
+func (bpf *bpf) SubDir() string {
+ return bpf.properties.Sub_dir
+}
+
var _ android.OutputFileProducer = (*bpf)(nil)
func BpfFactory() android.Module {
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 800b58f..f6fe6f7 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -241,7 +241,7 @@
entries.Class = "SHARED_LIBRARIES"
entries.ExtraEntries = append(entries.ExtraEntries, func(_ android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetString("LOCAL_SOONG_TOC", library.toc().String())
- if !library.buildStubs() {
+ if !library.buildStubs() && library.unstrippedOutputFile != nil {
entries.SetString("LOCAL_SOONG_UNSTRIPPED_BINARY", library.unstrippedOutputFile.String())
}
if len(library.Properties.Overrides) > 0 {
diff --git a/cc/binary.go b/cc/binary.go
index b59e762..ee3de3f 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -427,7 +427,7 @@
linkerDeps = append(linkerDeps, ndkSharedLibDeps(ctx)...)
}
- validations = append(validations, objs.tidyFiles...)
+ validations = append(validations, objs.tidyDepFiles...)
linkerDeps = append(linkerDeps, flags.LdFlagsDeps...)
// Register link action.
diff --git a/cc/bp2build.go b/cc/bp2build.go
index cc2e60e..c5eab06 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -280,6 +280,9 @@
includes BazelIncludes
protoSrcs bazel.LabelListAttribute
+
+ stubsSymbolFile *string
+ stubsVersions bazel.StringListAttribute
}
type filterOutFn func(string) bool
@@ -464,10 +467,11 @@
return relative, absolute
}
-// bp2BuildParseCompilerProps returns copts, srcs and hdrs and other attributes.
+// bp2BuildParseBaseProps returns all compiler, linker, library attributes of a cc module..
func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) baseAttributes {
archVariantCompilerProps := module.GetArchVariantProperties(ctx, &BaseCompilerProperties{})
archVariantLinkerProps := module.GetArchVariantProperties(ctx, &BaseLinkerProperties{})
+ archVariantLibraryProperties := module.GetArchVariantProperties(ctx, &LibraryProperties{})
var implementationHdrs bazel.LabelListAttribute
@@ -484,6 +488,7 @@
}
allAxesAndConfigs(archVariantCompilerProps)
allAxesAndConfigs(archVariantLinkerProps)
+ allAxesAndConfigs(archVariantLibraryProperties)
compilerAttrs := compilerAttributes{}
linkerAttrs := linkerAttributes{}
@@ -519,6 +524,13 @@
currIncludes := compilerAttrs.localIncludes.SelectValue(axis, config)
currIncludes = android.FirstUniqueStrings(append(currIncludes, includes...))
compilerAttrs.localIncludes.SetSelectValue(axis, config, currIncludes)
+
+ if libraryProps, ok := archVariantLibraryProperties[axis][config].(*LibraryProperties); ok {
+ if axis == bazel.NoConfigAxis {
+ compilerAttrs.stubsSymbolFile = libraryProps.Stubs.Symbol_file
+ compilerAttrs.stubsVersions.SetSelectValue(axis, config, libraryProps.Stubs.Versions)
+ }
+ }
}
}
diff --git a/cc/builder.go b/cc/builder.go
index fa7f7a3..512f838 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -387,10 +387,11 @@
toolchain config.Toolchain
// True if these extra features are enabled.
- tidy bool
- gcovCoverage bool
- sAbiDump bool
- emitXrefs bool
+ tidy bool
+ needTidyFiles bool
+ gcovCoverage bool
+ sAbiDump bool
+ emitXrefs bool
assemblerWithCpp bool // True if .s files should be processed with the c preprocessor.
@@ -420,6 +421,7 @@
type Objects struct {
objFiles android.Paths
tidyFiles android.Paths
+ tidyDepFiles android.Paths // link dependent .tidy files
coverageFiles android.Paths
sAbiDumpFiles android.Paths
kytheFiles android.Paths
@@ -429,6 +431,7 @@
return Objects{
objFiles: append(android.Paths{}, a.objFiles...),
tidyFiles: append(android.Paths{}, a.tidyFiles...),
+ tidyDepFiles: append(android.Paths{}, a.tidyDepFiles...),
coverageFiles: append(android.Paths{}, a.coverageFiles...),
sAbiDumpFiles: append(android.Paths{}, a.sAbiDumpFiles...),
kytheFiles: append(android.Paths{}, a.kytheFiles...),
@@ -439,6 +442,7 @@
return Objects{
objFiles: append(a.objFiles, b.objFiles...),
tidyFiles: append(a.tidyFiles, b.tidyFiles...),
+ tidyDepFiles: append(a.tidyDepFiles, b.tidyDepFiles...),
coverageFiles: append(a.coverageFiles, b.coverageFiles...),
sAbiDumpFiles: append(a.sAbiDumpFiles, b.sAbiDumpFiles...),
kytheFiles: append(a.kytheFiles, b.kytheFiles...),
@@ -452,9 +456,8 @@
}
// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
-func transformSourceToObj(ctx android.ModuleContext, subdir string, srcFiles, noTidySrcs android.Paths,
+func transformSourceToObj(ctx ModuleContext, subdir string, srcFiles, noTidySrcs android.Paths,
flags builderFlags, pathDeps android.Paths, cFlagsDeps android.Paths) Objects {
-
// Source files are one-to-one with tidy, coverage, or kythe files, if enabled.
objFiles := make(android.Paths, len(srcFiles))
var tidyFiles android.Paths
@@ -540,8 +543,7 @@
// Multiple source files have build rules usually share the same cFlags or tidyFlags.
// Define only one version in this module and share it in multiple build rules.
// To simplify the code, the shared variables are all named as $flags<nnn>.
- numSharedFlags := 0
- flagsMap := make(map[string]string)
+ shared := ctx.getSharedFlags()
// Share flags only when there are multiple files or tidy rules.
var hasMultipleRules = len(srcFiles) > 1 || flags.tidy
@@ -553,11 +555,11 @@
return flags
}
mapKey := kind + flags
- n, ok := flagsMap[mapKey]
+ n, ok := shared.flagsMap[mapKey]
if !ok {
- numSharedFlags += 1
- n = strconv.Itoa(numSharedFlags)
- flagsMap[mapKey] = n
+ shared.numSharedFlags += 1
+ n = strconv.Itoa(shared.numSharedFlags)
+ shared.flagsMap[mapKey] = n
ctx.Variable(pctx, kind+n, flags)
}
return "$" + kind + n
@@ -720,9 +722,14 @@
}
+ var tidyDepFiles android.Paths
+ if flags.needTidyFiles {
+ tidyDepFiles = tidyFiles
+ }
return Objects{
objFiles: objFiles,
tidyFiles: tidyFiles,
+ tidyDepFiles: tidyDepFiles,
coverageFiles: coverageFiles,
sAbiDumpFiles: sAbiDumpFiles,
kytheFiles: kytheFiles,
diff --git a/cc/cc.go b/cc/cc.go
index a4b7c9c..9c35348 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -210,11 +210,12 @@
// These must be after any module include flags, which will be in CommonFlags.
SystemIncludeFlags []string
- Toolchain config.Toolchain
- Tidy bool // True if clang-tidy is enabled.
- GcovCoverage bool // True if coverage files should be generated.
- SAbiDump bool // True if header abi dumps should be generated.
- EmitXrefs bool // If true, generate Ninja rules to generate emitXrefs input files for Kythe
+ Toolchain config.Toolchain
+ Tidy bool // True if ninja .tidy rules should be generated.
+ NeedTidyFiles bool // True if module link should depend on .tidy files
+ GcovCoverage bool // True if coverage files should be generated.
+ SAbiDump bool // True if header abi dumps should be generated.
+ EmitXrefs bool // If true, generate Ninja rules to generate emitXrefs input files for Kythe
// The instruction set required for clang ("arm" or "thumb").
RequiredInstructionSet string
@@ -516,6 +517,12 @@
directlyInAnyApex() bool
isPreventInstall() bool
isCfiAssemblySupportEnabled() bool
+ getSharedFlags() *SharedFlags
+}
+
+type SharedFlags struct {
+ numSharedFlags int
+ flagsMap map[string]string
}
type ModuleContext interface {
@@ -827,6 +834,9 @@
// Flags used to compile this module
flags Flags
+ // Shared flags among build rules of this module
+ sharedFlags SharedFlags
+
// only non-nil when this is a shared library that reuses the objects of a static library
staticAnalogue *StaticLibraryInfo
@@ -1605,6 +1615,15 @@
return ctx.mod.Properties.PreventInstall
}
+func (ctx *moduleContextImpl) getSharedFlags() *SharedFlags {
+ shared := &ctx.mod.sharedFlags
+ if shared.flagsMap == nil {
+ shared.numSharedFlags = 0
+ shared.flagsMap = make(map[string]string)
+ }
+ return shared
+}
+
func (ctx *moduleContextImpl) isCfiAssemblySupportEnabled() bool {
return ctx.mod.isCfiAssemblySupportEnabled()
}
@@ -3490,9 +3509,7 @@
libraryBp2Build(ctx, c)
}
} else if !static && !shared {
- if !prebuilt {
- libraryHeadersBp2Build(ctx, c)
- }
+ libraryHeadersBp2Build(ctx, c)
} else if static {
if prebuilt {
prebuiltLibraryStaticBp2Build(ctx, c)
diff --git a/cc/compiler.go b/cc/compiler.go
index 8adc3ab..9dbf2d1 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -675,7 +675,7 @@
}
// Compile a list of source files into objects a specified subdirectory
-func compileObjs(ctx android.ModuleContext, flags builderFlags, subdir string,
+func compileObjs(ctx ModuleContext, flags builderFlags, subdir string,
srcFiles, noTidySrcs, pathDeps android.Paths, cFlagsDeps android.Paths) Objects {
return transformSourceToObj(ctx, subdir, srcFiles, noTidySrcs, flags, pathDeps, cFlagsDeps)
diff --git a/cc/config/bp2build.go b/cc/config/bp2build.go
index 4797acc..982b436 100644
--- a/cc/config/bp2build.go
+++ b/cc/config/bp2build.go
@@ -22,6 +22,7 @@
"strings"
"android/soong/android"
+
"github.com/google/blueprint"
)
@@ -162,6 +163,10 @@
exportedStringListVars.Set(name, value)
}
+func ExportStringList(name string, value []string) {
+ exportedStringListVars.Set(name, value)
+}
+
type exportedStringListDictVariables map[string]map[string][]string
func (m exportedStringListDictVariables) Set(k string, v map[string][]string) {
diff --git a/cc/library.go b/cc/library.go
index 5720944..cefbf6c 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -381,6 +381,9 @@
None: linkerAttrs.stripNone,
},
Features: linkerAttrs.features,
+
+ Stubs_symbol_file: compilerAttrs.stubsSymbolFile,
+ Stubs_versions: compilerAttrs.stubsVersions,
}
staticProps := bazel.BazelTargetModuleProperties{
@@ -443,6 +446,8 @@
module, library := NewLibrary(android.HostSupported)
library.BuildOnlyStatic()
module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
+ module.bazelable = true
+ module.bazelHandler = &ccLibraryBazelHandler{module: module}
return module.Init()
}
@@ -1338,7 +1343,7 @@
}
}
- transformObjToStaticLib(ctx, library.objects.objFiles, deps.WholeStaticLibsFromPrebuilts, builderFlags, outputFile, nil, objs.tidyFiles)
+ transformObjToStaticLib(ctx, library.objects.objFiles, deps.WholeStaticLibsFromPrebuilts, builderFlags, outputFile, nil, objs.tidyDepFiles)
library.coverageOutputFile = transformCoverageFilesToZip(ctx, library.objects, ctx.ModuleName())
@@ -1485,7 +1490,7 @@
linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...)
transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
- linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile, implicitOutputs, objs.tidyFiles)
+ linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile, implicitOutputs, objs.tidyDepFiles)
objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...)
objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...)
@@ -2516,6 +2521,9 @@
},
Features: linkerAttrs.features,
+
+ Stubs_symbol_file: compilerAttrs.stubsSymbolFile,
+ Stubs_versions: compilerAttrs.stubsVersions,
}
}
@@ -2589,4 +2597,7 @@
Asflags bazel.StringListAttribute
Features bazel.StringListAttribute
+
+ Stubs_symbol_file *string
+ Stubs_versions bazel.StringListAttribute
}
diff --git a/cc/library_headers.go b/cc/library_headers.go
index 70e4715..064e2b8 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -104,6 +104,8 @@
func prebuiltLibraryHeaderFactory() android.Module {
module, library := NewPrebuiltLibrary(android.HostAndDeviceSupported, "")
library.HeaderOnly()
+ module.bazelable = true
+ module.bazelHandler = &ccLibraryBazelHandler{module: module}
return module.Init()
}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 7879a7d..7efe134 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -25,6 +25,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/cc/config"
)
func init() {
@@ -208,20 +209,26 @@
*ndkKnownLibs = append(*ndkKnownLibs, name)
}
+var stubLibraryCompilerFlags = []string{
+ // We're knowingly doing some otherwise unsightly things with builtin
+ // functions here. We're just generating stub libraries, so ignore it.
+ "-Wno-incompatible-library-redeclaration",
+ "-Wno-incomplete-setjmp-declaration",
+ "-Wno-builtin-requires-header",
+ "-Wno-invalid-noreturn",
+ "-Wall",
+ "-Werror",
+ // These libraries aren't actually used. Don't worry about unwinding
+ // (avoids the need to link an unwinder into a fake library).
+ "-fno-unwind-tables",
+}
+
+func init() {
+ config.ExportStringList("StubLibraryCompilerFlags", stubLibraryCompilerFlags)
+}
+
func addStubLibraryCompilerFlags(flags Flags) Flags {
- flags.Global.CFlags = append(flags.Global.CFlags,
- // We're knowingly doing some otherwise unsightly things with builtin
- // functions here. We're just generating stub libraries, so ignore it.
- "-Wno-incompatible-library-redeclaration",
- "-Wno-incomplete-setjmp-declaration",
- "-Wno-builtin-requires-header",
- "-Wno-invalid-noreturn",
- "-Wall",
- "-Werror",
- // These libraries aren't actually used. Don't worry about unwinding
- // (avoids the need to link an unwinder into a fake library).
- "-fno-unwind-tables",
- )
+ flags.Global.CFlags = append(flags.Global.CFlags, stubLibraryCompilerFlags...)
// All symbols in the stubs library should be visible.
if inList("-fvisibility=hidden", flags.Local.CFlags) {
flags.Local.CFlags = append(flags.Local.CFlags, "-fvisibility=default")
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index feae812..c928ed9 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -298,6 +298,7 @@
module, library := NewPrebuiltLibrary(hod, "srcs")
library.BuildOnlyShared()
module.bazelable = true
+ module.bazelHandler = &prebuiltSharedLibraryBazelHandler{module: module, library: library}
// Prebuilt shared libraries can be included in APEXes
android.InitApexModule(module)
@@ -426,6 +427,69 @@
return true
}
+type prebuiltSharedLibraryBazelHandler struct {
+ android.BazelHandler
+
+ module *Module
+ library *libraryDecorator
+}
+
+func (h *prebuiltSharedLibraryBazelHandler) GenerateBazelBuildActions(ctx android.ModuleContext, label string) bool {
+ bazelCtx := ctx.Config().BazelContext
+ ccInfo, ok, err := bazelCtx.GetCcInfo(label, android.GetConfigKey(ctx))
+ if err != nil {
+ ctx.ModuleErrorf("Error getting Bazel CcInfo for %s: %s", label, err)
+ }
+ if !ok {
+ return false
+ }
+ sharedLibs := ccInfo.CcSharedLibraryFiles
+ if len(sharedLibs) != 1 {
+ ctx.ModuleErrorf("expected 1 shared library from bazel target %s, got %q", label, sharedLibs)
+ return false
+ }
+
+ // TODO(b/184543518): cc_prebuilt_library_shared may have properties for re-exporting flags
+
+ // TODO(eakammer):Add stub-related flags if this library is a stub library.
+ // h.library.exportVersioningMacroIfNeeded(ctx)
+
+ // Dependencies on this library will expect collectedSnapshotHeaders to be set, otherwise
+ // validation will fail. For now, set this to an empty list.
+ // TODO(cparsons): More closely mirror the collectHeadersForSnapshot implementation.
+ h.library.collectedSnapshotHeaders = android.Paths{}
+
+ if len(sharedLibs) == 0 {
+ h.module.outputFile = android.OptionalPath{}
+ return true
+ }
+
+ out := android.PathForBazelOut(ctx, sharedLibs[0])
+ h.module.outputFile = android.OptionalPathForPath(out)
+
+ // FIXME(b/214600441): We don't yet strip prebuilt shared libraries
+ h.library.unstrippedOutputFile = out
+
+ var toc android.Path
+ if len(ccInfo.TocFile) > 0 {
+ toc = android.PathForBazelOut(ctx, ccInfo.TocFile)
+ } else {
+ toc = out // Just reuse `out` so ninja still gets an input but won't matter
+ }
+
+ info := SharedLibraryInfo{
+ SharedLibrary: out,
+ TableOfContents: android.OptionalPathForPath(toc),
+ Target: ctx.Target(),
+ }
+ ctx.SetProvider(SharedLibraryInfoProvider, info)
+
+ h.library.setFlagExporterInfoFromCcInfo(ctx, ccInfo)
+ h.module.maybeUnhideFromMake()
+
+ return true
+}
+
func (p *prebuiltObjectLinker) prebuilt() *android.Prebuilt {
return &p.Prebuilt
}
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index c8f8103..94f75fe 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -19,7 +19,7 @@
"testing"
"android/soong/android"
-
+ "android/soong/bazel/cquery"
"github.com/google/blueprint"
)
@@ -378,3 +378,74 @@
static2 = ctx.ModuleForTests("libtest_static", "android_arm64_armv8-a_static_hwasan").Module().(*Module)
assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a")
}
+
+func TestPrebuiltLibrarySharedWithBazelWithoutToc(t *testing.T) {
+ const bp = `
+cc_prebuilt_library_shared {
+ name: "foo",
+ srcs: ["foo.so"],
+ bazel_module: { label: "//foo/bar:bar" },
+}`
+ outBaseDir := "outputbase"
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: outBaseDir,
+ LabelToCcInfo: map[string]cquery.CcInfo{
+ "//foo/bar:bar": cquery.CcInfo{
+ CcSharedLibraryFiles: []string{"foo.so"},
+ },
+ },
+ }
+ ctx := testCcWithConfig(t, config)
+ sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
+ pathPrefix := outBaseDir + "/execroot/__main__/"
+
+ info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
+ android.AssertPathRelativeToTopEquals(t, "prebuilt shared library",
+ pathPrefix+"foo.so", info.SharedLibrary)
+ android.AssertPathRelativeToTopEquals(t, "prebuilt's 'nullary' ToC",
+ pathPrefix+"foo.so", info.TableOfContents.Path())
+
+ outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
+ if err != nil {
+ t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
+ }
+ expectedOutputFiles := []string{pathPrefix + "foo.so"}
+ android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
+}
+
+func TestPrebuiltLibrarySharedWithBazelWithToc(t *testing.T) {
+ const bp = `
+cc_prebuilt_library_shared {
+ name: "foo",
+ srcs: ["foo.so"],
+ bazel_module: { label: "//foo/bar:bar" },
+}`
+ outBaseDir := "outputbase"
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: outBaseDir,
+ LabelToCcInfo: map[string]cquery.CcInfo{
+ "//foo/bar:bar": cquery.CcInfo{
+ CcSharedLibraryFiles: []string{"foo.so"},
+ TocFile: "toc",
+ },
+ },
+ }
+ ctx := testCcWithConfig(t, config)
+ sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
+ pathPrefix := outBaseDir + "/execroot/__main__/"
+
+ info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
+ android.AssertPathRelativeToTopEquals(t, "prebuilt shared library's ToC",
+ pathPrefix+"toc", info.TableOfContents.Path())
+ android.AssertPathRelativeToTopEquals(t, "prebuilt shared library",
+ pathPrefix+"foo.so", info.SharedLibrary)
+
+ outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
+ if err != nil {
+ t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
+ }
+ expectedOutputFiles := []string{pathPrefix + "foo.so"}
+ android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
+}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 6c68822..a054c91 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -42,6 +42,7 @@
"-fno-omit-frame-pointer",
"-Wno-frame-larger-than=",
"-fsanitize-hwaddress-abi=platform",
+ "-mllvm", "-hwasan-use-after-scope=1",
}
// ThinLTO performs codegen during link time, thus these flags need to
diff --git a/cc/tidy.go b/cc/tidy.go
index 78a791f..97418fe 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -71,13 +71,17 @@
return flags
}
- // If not explicitly set, check the global tidy flag
- if tidy.Properties.Tidy == nil && !ctx.Config().ClangTidy() {
- return flags
- }
-
+ // If not explicitly disabled, set flags.Tidy to generate .tidy rules.
+ // Note that libraries and binaries will depend on .tidy files ONLY if
+ // the global WITH_TIDY or module 'tidy' property is true.
flags.Tidy = true
+ // If explicitly enabled, by global default or local tidy property,
+ // set flags.NeedTidyFiles to make this module depend on .tidy files.
+ if ctx.Config().ClangTidy() || Bool(tidy.Properties.Tidy) {
+ flags.NeedTidyFiles = true
+ }
+
// Add global WITH_TIDY_FLAGS and local tidy_flags.
withTidyFlags := ctx.Config().Getenv("WITH_TIDY_FLAGS")
if len(withTidyFlags) > 0 {
diff --git a/cc/util.go b/cc/util.go
index 88b0aba..b256b9a 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -85,6 +85,7 @@
toolchain: in.Toolchain,
gcovCoverage: in.GcovCoverage,
tidy: in.Tidy,
+ needTidyFiles: in.NeedTidyFiles,
sAbiDump: in.SAbiDump,
emitXrefs: in.EmitXrefs,
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 9ee373e..d8cb47a 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -117,12 +117,23 @@
return indexList(s, list) != -1
}
-func loadEnvConfig() error {
+func loadEnvConfig(config build.Config) error {
bc := os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG")
if bc == "" {
return nil
}
- cfgFile := filepath.Join(os.Getenv("TOP"), configDir, fmt.Sprintf("%s.%s", bc, jsonSuffix))
+ configDirs := []string{
+ os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG_DIR"),
+ config.OutDir(),
+ configDir,
+ }
+ var cfgFile string
+ for _, dir := range configDirs {
+ cfgFile = filepath.Join(os.Getenv("TOP"), dir, fmt.Sprintf("%s.%s", bc, jsonSuffix))
+ if _, err := os.Stat(cfgFile); err == nil {
+ break
+ }
+ }
envVarsJSON, err := ioutil.ReadFile(cfgFile)
if err != nil {
@@ -138,9 +149,7 @@
if os.Getenv(k) != "" {
continue
}
- if err := os.Setenv(k, v); err != nil {
- return err
- }
+ config.Environment().Set(k, v)
}
return nil
}
@@ -207,13 +216,13 @@
Status: stat,
}}
- if err := loadEnvConfig(); err != nil {
+ config := c.config(buildCtx, args...)
+
+ if err := loadEnvConfig(config); err != nil {
fmt.Fprintf(os.Stderr, "failed to parse env config files: %v", err)
os.Exit(1)
}
- config := c.config(buildCtx, args...)
-
build.SetupOutDir(buildCtx, config)
if config.UseBazel() && config.Dist() {
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index 8861d1b..89f8187 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -31,6 +31,7 @@
const (
Cc Lang = ""
Rust Lang = "rust"
+ Java Lang = "java"
)
var BoolDefault = proptools.BoolDefault
@@ -220,6 +221,9 @@
if lang == Rust {
zipFileName = "fuzz-rust-" + hostOrTarget + "-" + arch + ".zip"
}
+ if lang == Java {
+ zipFileName = "fuzz-java-" + hostOrTarget + "-" + arch + ".zip"
+ }
outputFile := android.PathForOutput(ctx, zipFileName)
s.Packages = append(s.Packages, outputFile)
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 6a91e01..1679a57 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -106,6 +106,16 @@
android.LicenseAnnotationToolchainDependencyTag
label string
}
+
+func (t hostToolDependencyTag) AllowDisabledModuleDependency(target android.Module) bool {
+ // Allow depending on a disabled module if it's replaced by a prebuilt
+ // counterpart. We get the prebuilt through android.PrebuiltGetPreferred in
+ // GenerateAndroidBuildActions.
+ return target.IsReplacedByPrebuilt()
+}
+
+var _ android.AllowDisabledModuleDependency = (*hostToolDependencyTag)(nil)
+
type generatorProperties struct {
// The command to run on one or more input files. Cmd supports substitution of a few variables.
//
@@ -298,6 +308,12 @@
switch tag := ctx.OtherModuleDependencyTag(module).(type) {
case hostToolDependencyTag:
tool := ctx.OtherModuleName(module)
+ if m, ok := module.(android.Module); ok {
+ // Necessary to retrieve any prebuilt replacement for the tool, since
+ // toolDepsMutator runs too late for the prebuilt mutators to have
+ // replaced the dependency.
+ module = android.PrebuiltGetPreferred(ctx, m)
+ }
switch t := module.(type) {
case android.HostToolProvider:
@@ -846,7 +862,7 @@
cmd = strings.Replace(*m.properties.Cmd, "$(in)", "$(SRCS)", -1)
cmd = strings.Replace(cmd, "$(out)", "$(OUTS)", -1)
genDir := "$(GENDIR)"
- if ctx.ModuleType() == "cc_genrule" {
+ if t := ctx.ModuleType(); t == "cc_genrule" || t == "java_genrule" || t == "java_genrule_host" {
genDir = "$(RULEDIR)"
}
cmd = strings.Replace(cmd, "$(genDir)", genDir, -1)
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 714d2f8..04c97fd 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -34,7 +34,9 @@
android.PrepareForTestWithFilegroup,
PrepareForTestWithGenRuleBuildComponents,
android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ android.RegisterPrebuiltMutators(ctx)
ctx.RegisterModuleType("tool", toolFactory)
+ ctx.RegisterModuleType("prebuilt_tool", prebuiltToolFactory)
ctx.RegisterModuleType("output", outputProducerFactory)
ctx.RegisterModuleType("use_source", useSourceFactory)
}),
@@ -720,6 +722,69 @@
result.ModuleForTests("gen_all", "").Module().(*useSource).srcs)
}
+func TestPrebuiltTool(t *testing.T) {
+ testcases := []struct {
+ name string
+ bp string
+ expectedToolName string
+ }{
+ {
+ name: "source only",
+ bp: `
+ tool { name: "tool" }
+ `,
+ expectedToolName: "bin/tool",
+ },
+ {
+ name: "prebuilt only",
+ bp: `
+ prebuilt_tool { name: "tool" }
+ `,
+ expectedToolName: "prebuilt_bin/tool",
+ },
+ {
+ name: "source preferred",
+ bp: `
+ tool { name: "tool" }
+ prebuilt_tool { name: "tool" }
+ `,
+ expectedToolName: "bin/tool",
+ },
+ {
+ name: "prebuilt preferred",
+ bp: `
+ tool { name: "tool" }
+ prebuilt_tool { name: "tool", prefer: true }
+ `,
+ expectedToolName: "prebuilt_bin/prebuilt_tool",
+ },
+ {
+ name: "source disabled",
+ bp: `
+ tool { name: "tool", enabled: false }
+ prebuilt_tool { name: "tool" }
+ `,
+ expectedToolName: "prebuilt_bin/prebuilt_tool",
+ },
+ }
+
+ for _, test := range testcases {
+ t.Run(test.name, func(t *testing.T) {
+ result := prepareForGenRuleTest.RunTestWithBp(t, test.bp+`
+ genrule {
+ name: "gen",
+ tools: ["tool"],
+ out: ["foo"],
+ cmd: "$(location tool)",
+ }
+ `)
+ gen := result.Module("gen", "").(*Module)
+ expectedCmd := "__SBOX_SANDBOX_DIR__/tools/out/" + test.expectedToolName
+ android.AssertStringEquals(t, "command", expectedCmd, gen.rawCommands[0])
+ })
+ }
+}
+
func TestGenruleWithBazel(t *testing.T) {
bp := `
genrule {
@@ -764,7 +829,33 @@
return android.OptionalPathForPath(t.outputFile)
}
+type prebuiltTestTool struct {
+ android.ModuleBase
+ prebuilt android.Prebuilt
+ testTool
+}
+
+func (p *prebuiltTestTool) Name() string {
+ return p.prebuilt.Name(p.ModuleBase.Name())
+}
+
+func (p *prebuiltTestTool) Prebuilt() *android.Prebuilt {
+ return &p.prebuilt
+}
+
+func (t *prebuiltTestTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "prebuilt_bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
+}
+
+func prebuiltToolFactory() android.Module {
+ module := &prebuiltTestTool{}
+ android.InitPrebuiltModuleWithoutSrcs(module)
+ android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
+ return module
+}
+
var _ android.HostToolProvider = (*testTool)(nil)
+var _ android.HostToolProvider = (*prebuiltTestTool)(nil)
type testOutputProducer struct {
android.ModuleBase
diff --git a/java/androidmk.go b/java/androidmk.go
index 19fe7e2..b930441 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -433,8 +433,10 @@
if len(a.appProperties.Overrides) > 0 {
overridden = append(overridden, a.appProperties.Overrides...)
}
- if a.Name() != a.installApkName {
- overridden = append(overridden, a.Name())
+ // When APK name is overridden via PRODUCT_PACKAGE_NAME_OVERRIDES
+ // ensure that the original name is overridden.
+ if a.Stem() != a.installApkName {
+ overridden = append(overridden, a.Stem())
}
return overridden
}
diff --git a/java/app.go b/java/app.go
index ffe3e07..7ae73f7 100755
--- a/java/app.go
+++ b/java/app.go
@@ -621,7 +621,7 @@
a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex)
// Check if the install APK name needs to be overridden.
- a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Name())
+ a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Stem())
if ctx.ModuleName() == "framework-res" {
// framework-res.apk is installed as system/framework/framework-res.apk
@@ -1006,6 +1006,7 @@
command := rule.Command().BuiltTool("test_config_fixer").Input(testConfig).Output(fixedConfig)
fixNeeded := false
+ // Auto-generated test config uses `ModuleName` as the APK name. So fix it if it is not the case.
if ctx.ModuleName() != a.installApkName {
fixNeeded = true
command.FlagWithArg("--test-file-name ", a.installApkName+".apk")
@@ -1162,7 +1163,10 @@
// some of its properties.
func OverrideAndroidAppModuleFactory() android.Module {
m := &OverrideAndroidApp{}
- m.AddProperties(&overridableAppProperties{})
+ m.AddProperties(
+ &OverridableDeviceProperties{},
+ &overridableAppProperties{},
+ )
android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon)
android.InitOverrideModule(m)
diff --git a/java/app_test.go b/java/app_test.go
index 4da7c3d..2322ef4 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1707,7 +1707,7 @@
},
},
{
- name: "overridden",
+ name: "overridden via PRODUCT_PACKAGE_NAME_OVERRIDES",
bp: `
android_app {
name: "foo",
@@ -1722,6 +1722,22 @@
"out/soong/target/product/test_device/system/app/bar/bar.apk",
},
},
+ {
+ name: "overridden via stem",
+ bp: `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ stem: "bar",
+ }
+ `,
+ packageNameOverride: "",
+ expected: []string{
+ "out/soong/.intermediates/foo/android_common/bar.apk",
+ "out/soong/target/product/test_device/system/app/bar/bar.apk",
+ },
+ },
}
for _, test := range testCases {
@@ -1965,6 +1981,80 @@
}
}
+func TestOverrideAndroidAppStem(t *testing.T) {
+ ctx, _ := testJava(t, `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ }
+ override_android_app {
+ name: "bar",
+ base: "foo",
+ }
+ override_android_app {
+ name: "baz",
+ base: "foo",
+ stem: "baz_stem",
+ }
+ android_app {
+ name: "foo2",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ stem: "foo2_stem",
+ }
+ override_android_app {
+ name: "bar2",
+ base: "foo2",
+ }
+ override_android_app {
+ name: "baz2",
+ base: "foo2",
+ stem: "baz2_stem",
+ }
+ `)
+ for _, expected := range []struct {
+ moduleName string
+ variantName string
+ apkPath string
+ }{
+ {
+ moduleName: "foo",
+ variantName: "android_common",
+ apkPath: "out/soong/target/product/test_device/system/app/foo/foo.apk",
+ },
+ {
+ moduleName: "foo",
+ variantName: "android_common_bar",
+ apkPath: "out/soong/target/product/test_device/system/app/bar/bar.apk",
+ },
+ {
+ moduleName: "foo",
+ variantName: "android_common_baz",
+ apkPath: "out/soong/target/product/test_device/system/app/baz_stem/baz_stem.apk",
+ },
+ {
+ moduleName: "foo2",
+ variantName: "android_common",
+ apkPath: "out/soong/target/product/test_device/system/app/foo2_stem/foo2_stem.apk",
+ },
+ {
+ moduleName: "foo2",
+ variantName: "android_common_bar2",
+ // Note that this may cause the duplicate output error.
+ apkPath: "out/soong/target/product/test_device/system/app/foo2_stem/foo2_stem.apk",
+ },
+ {
+ moduleName: "foo2",
+ variantName: "android_common_baz2",
+ apkPath: "out/soong/target/product/test_device/system/app/baz2_stem/baz2_stem.apk",
+ },
+ } {
+ variant := ctx.ModuleForTests(expected.moduleName, expected.variantName)
+ variant.Output(expected.apkPath)
+ }
+}
+
func TestOverrideAndroidAppDependency(t *testing.T) {
ctx, _ := testJava(t, `
android_app {
@@ -2168,10 +2258,33 @@
t.Errorf("test_config_fixer was not expected to run, but did: %q", params.RuleParams.Command)
}
}
-
}
}
+func TestInstrumentationTargetPrebuilt(t *testing.T) {
+ bp := `
+ android_app_import {
+ name: "foo",
+ apk: "foo.apk",
+ presigned: true,
+ }
+
+ android_test {
+ name: "bar",
+ srcs: ["a.java"],
+ instrumentation_for: "foo",
+ sdk_version: "current",
+ }
+ `
+
+ android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ ).ExtendWithErrorHandler(
+ android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ "instrumentation_for: dependency \"foo\" of type \"android_app_import\" does not provide JavaInfo so is unsuitable for use with this property")).
+ RunTestWithBp(t, bp)
+}
+
func TestStl(t *testing.T) {
ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
cc_library {
diff --git a/java/base.go b/java/base.go
index 7cd71a2..63328c8 100644
--- a/java/base.go
+++ b/java/base.go
@@ -253,9 +253,6 @@
// otherwise provides defaults libraries to add to the bootclasspath.
System_modules *string
- // set the name of the output
- Stem *string
-
IsSDKLibrary bool `blueprint:"mutated"`
// If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file.
@@ -267,6 +264,15 @@
SyspropPublicStub string `blueprint:"mutated"`
}
+// Device properties that can be overridden by overriding module (e.g. override_android_app)
+type OverridableDeviceProperties struct {
+ // set the name of the output. If not set, `name` is used.
+ // To override a module with this property set, overriding module might need to set this as well.
+ // Otherwise, both the overridden and the overriding modules will have the same output name, which
+ // can cause the duplicate output error.
+ Stem *string
+}
+
// Functionality common to Module and Import
//
// It is embedded in Module so its functionality can be used by methods in Module
@@ -389,6 +395,8 @@
protoProperties android.ProtoProperties
deviceProperties DeviceProperties
+ overridableDeviceProperties OverridableDeviceProperties
+
// jar file containing header classes including static library dependencies, suitable for
// inserting into the bootclasspath/classpath of another compile
headerJarFile android.Path
@@ -544,6 +552,7 @@
j.addHostProperties()
j.AddProperties(
&j.deviceProperties,
+ &j.overridableDeviceProperties,
&j.dexer.dexProperties,
&j.dexpreoptProperties,
&j.linter.properties,
@@ -1671,7 +1680,7 @@
}
func (j *Module) Stem() string {
- return proptools.StringDefault(j.deviceProperties.Stem, j.Name())
+ return proptools.StringDefault(j.overridableDeviceProperties.Stem, j.Name())
}
func (j *Module) JacocoReportClassesFile() android.Path {
@@ -1936,6 +1945,9 @@
sm := module.(SystemModulesProvider)
outputDir, outputDeps := sm.OutputDirAndDeps()
deps.systemModules = &systemModules{outputDir, outputDeps}
+
+ case instrumentationForTag:
+ ctx.PropertyErrorf("instrumentation_for", "dependency %q of type %q does not provide JavaInfo so is unsuitable for use with this property", ctx.OtherModuleName(module), ctx.OtherModuleType(module))
}
}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index bfe895c..fee51d7 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -219,6 +219,11 @@
// Collect the module directory for IDE info in java/jdeps.go.
modulePaths []string
+
+ // Installs for on-device boot image files. This list has entries only if the installs should be
+ // handled by Make (e.g., the boot image should be installed on the system partition, rather than
+ // in the APEX).
+ bootImageDeviceInstalls []dexpreopterInstall
}
// commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt
@@ -387,6 +392,9 @@
// Map from arch type to the boot image files.
bootImageFilesByArch bootImageFilesByArch
+ // True if the boot image should be installed in the APEX.
+ shouldInstallBootImageInApex bool
+
// Map from the base module name (without prebuilt_ prefix) of a fragment's contents module to the
// hidden API encoded dex jar path.
contentModuleDexJarPaths bootDexJarByModule
@@ -410,6 +418,11 @@
return i.bootImageFilesByArch
}
+// Return true if the boot image should be installed in the APEX.
+func (i *BootclasspathFragmentApexContentInfo) ShouldInstallBootImageInApex() bool {
+ return i.shouldInstallBootImageInApex
+}
+
// DexBootJarPathForContentModule returns the path to the dex boot jar for specified module.
//
// The dex boot jar is one which has had hidden API encoding performed on it.
@@ -550,6 +563,24 @@
// Copy the dex jars of this fragment's content modules to their predefined locations.
copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule)
}
+
+ for _, variant := range imageConfig.apexVariants() {
+ arch := variant.target.Arch.ArchType.String()
+ for _, install := range variant.deviceInstalls {
+ // Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT.
+ installDir := strings.TrimPrefix(filepath.Dir(install.To), "/")
+ installBase := filepath.Base(install.To)
+ installPath := android.PathForModuleInPartitionInstall(ctx, "", installDir)
+
+ b.bootImageDeviceInstalls = append(b.bootImageDeviceInstalls, dexpreopterInstall{
+ name: arch + "-" + installBase,
+ moduleName: b.Name(),
+ outputPathOnHost: install.From,
+ installDirOnDevice: installPath,
+ installFileOnDevice: installBase,
+ })
+ }
+ }
}
// A prebuilt fragment cannot contribute to an apex.
@@ -599,6 +630,8 @@
info.profilePathOnHost = imageConfig.profilePathOnHost
info.profileInstallPathInApex = imageConfig.profileInstallPathInApex
}
+
+ info.shouldInstallBootImageInApex = imageConfig.shouldInstallInApex()
}
info.bootImageFilesByArch = bootImageFilesByArch
@@ -813,6 +846,23 @@
return androidBootImageFilesByArch
}
+func (b *BootclasspathFragmentModule) AndroidMkEntries() []android.AndroidMkEntries {
+ var entriesList []android.AndroidMkEntries
+ for _, install := range b.bootImageDeviceInstalls {
+ entriesList = append(entriesList, install.ToMakeEntries())
+ }
+ return entriesList
+}
+
+// Returns the names of all Make modules that handle the installation of the boot image.
+func (b *BootclasspathFragmentModule) BootImageDeviceInstallMakeModules() []string {
+ var makeModules []string
+ for _, install := range b.bootImageDeviceInstalls {
+ makeModules = append(makeModules, install.FullModuleName())
+ }
+ return makeModules
+}
+
// Collect information for opening IDE project files in java/jdeps.go.
func (b *BootclasspathFragmentModule) IDEInfo(dpInfo *android.IdeInfo) {
dpInfo.Deps = append(dpInfo.Deps, b.properties.Contents...)
diff --git a/java/dex.go b/java/dex.go
index 8045b5c..474694a 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -72,6 +72,9 @@
// This defaults to reasonable value based on module and should not be set.
// It exists only to support ART tests.
Uncompress_dex *bool
+
+ // Exclude kotlinc generate files: *.kotlin_module, *.kotlin_builtins. Defaults to false.
+ Exclude_kotlinc_generated_files *bool
}
type dexer struct {
@@ -94,7 +97,7 @@
`${config.Zip2ZipCmd} -i $in -o $tmpJar -x '**/*.dex' && ` +
`$d8Template${config.D8Cmd} ${config.DexFlags} --output $outDir $d8Flags $tmpJar && ` +
`$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
- `${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
+ `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
"${config.D8Cmd}",
"${config.Zip2ZipCmd}",
@@ -116,7 +119,7 @@
ExecStrategy: "${config.RED8ExecStrategy}",
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
},
- }, []string{"outDir", "d8Flags", "zipFlags", "tmpJar"}, nil)
+ }, []string{"outDir", "d8Flags", "zipFlags", "tmpJar", "mergeZipsFlags"}, nil)
var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
blueprint.RuleParams{
@@ -134,7 +137,7 @@
`${config.SoongZipCmd} -o ${outUsageZip} -C ${outUsageDir} -f ${outUsage} && ` +
`rm -rf ${outUsageDir} && ` +
`$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
- `${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
+ `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
"${config.R8Cmd}",
"${config.Zip2ZipCmd}",
@@ -165,7 +168,7 @@
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
},
}, []string{"outDir", "outDict", "outUsage", "outUsageZip", "outUsageDir",
- "r8Flags", "zipFlags", "tmpJar"}, []string{"implicits"})
+ "r8Flags", "zipFlags", "tmpJar", "mergeZipsFlags"}, []string{"implicits"})
func (d *dexer) dexCommonFlags(ctx android.ModuleContext,
minSdkVersion android.SdkSpec) (flags []string, deps android.Paths) {
@@ -254,6 +257,15 @@
if BoolDefault(opt.Proguard_compatibility, true) {
r8Flags = append(r8Flags, "--force-proguard-compatibility")
+ } else {
+ // TODO(b/213833843): Allow configuration of the prefix via a build variable.
+ var sourceFilePrefix = "go/retraceme "
+ var sourceFileTemplate = "\"" + sourceFilePrefix + "%MAP_ID\""
+ // TODO(b/200967150): Also tag the source file in compat builds.
+ if Bool(opt.Optimize) || Bool(opt.Obfuscate) {
+ r8Flags = append(r8Flags, "--map-id-template", "%MAP_HASH")
+ r8Flags = append(r8Flags, "--source-file-template", sourceFileTemplate)
+ }
}
// TODO(ccross): Don't shrink app instrumentation tests by default.
@@ -298,6 +310,12 @@
commonFlags, commonDeps := d.dexCommonFlags(ctx, minSdkVersion)
+ // Exclude kotlinc generated files when "exclude_kotlinc_generated_files" is set to true.
+ mergeZipsFlags := ""
+ if proptools.BoolDefault(d.dexProperties.Exclude_kotlinc_generated_files, false) {
+ mergeZipsFlags = "-stripFile META-INF/*.kotlin_module -stripFile **/*.kotlin_builtins"
+ }
+
useR8 := d.effectiveOptimizeEnabled()
if useR8 {
proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
@@ -311,14 +329,15 @@
r8Deps = append(r8Deps, commonDeps...)
rule := r8
args := map[string]string{
- "r8Flags": strings.Join(append(commonFlags, r8Flags...), " "),
- "zipFlags": zipFlags,
- "outDict": proguardDictionary.String(),
- "outUsageDir": proguardUsageDir.String(),
- "outUsage": proguardUsage.String(),
- "outUsageZip": proguardUsageZip.String(),
- "outDir": outDir.String(),
- "tmpJar": tmpJar.String(),
+ "r8Flags": strings.Join(append(commonFlags, r8Flags...), " "),
+ "zipFlags": zipFlags,
+ "outDict": proguardDictionary.String(),
+ "outUsageDir": proguardUsageDir.String(),
+ "outUsage": proguardUsage.String(),
+ "outUsageZip": proguardUsageZip.String(),
+ "outDir": outDir.String(),
+ "tmpJar": tmpJar.String(),
+ "mergeZipsFlags": mergeZipsFlags,
}
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_R8") {
rule = r8RE
@@ -347,10 +366,11 @@
Input: classesJar,
Implicits: d8Deps,
Args: map[string]string{
- "d8Flags": strings.Join(append(commonFlags, d8Flags...), " "),
- "zipFlags": zipFlags,
- "outDir": outDir.String(),
- "tmpJar": tmpJar.String(),
+ "d8Flags": strings.Join(append(commonFlags, d8Flags...), " "),
+ "zipFlags": zipFlags,
+ "outDir": outDir.String(),
+ "tmpJar": tmpJar.String(),
+ "mergeZipsFlags": mergeZipsFlags,
},
})
}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index e9bc518..7c5f055 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -57,6 +57,25 @@
return "-dexpreopt-" + install.name
}
+// Returns Make entries for installing the file.
+//
+// This function uses a value receiver rather than a pointer receiver to ensure that the object is
+// safe to use in `android.AndroidMkExtraEntriesFunc`.
+func (install dexpreopterInstall) ToMakeEntries() android.AndroidMkEntries {
+ return android.AndroidMkEntries{
+ Class: "ETC",
+ SubName: install.SubModuleName(),
+ OutputFile: android.OptionalPathForPath(install.outputPathOnHost),
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetString("LOCAL_MODULE_PATH", install.installDirOnDevice.String())
+ entries.SetString("LOCAL_INSTALLED_MODULE_STEM", install.installFileOnDevice)
+ entries.SetString("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", "false")
+ },
+ },
+ }
+}
+
type dexpreopter struct {
dexpreoptProperties DexpreoptProperties
@@ -383,19 +402,7 @@
func (d *dexpreopter) AndroidMkEntriesForApex() []android.AndroidMkEntries {
var entries []android.AndroidMkEntries
for _, install := range d.builtInstalledForApex {
- install := install
- entries = append(entries, android.AndroidMkEntries{
- Class: "ETC",
- SubName: install.SubModuleName(),
- OutputFile: android.OptionalPathForPath(install.outputPathOnHost),
- ExtraEntries: []android.AndroidMkExtraEntriesFunc{
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.SetString("LOCAL_MODULE_PATH", install.installDirOnDevice.String())
- entries.SetString("LOCAL_INSTALLED_MODULE_STEM", install.installFileOnDevice)
- entries.SetString("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", "false")
- },
- },
- })
+ entries = append(entries, install.ToMakeEntries())
}
return entries
}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index c599c4d..cad9c33 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -313,10 +313,13 @@
// This is only set for a variant of an image that extends another image.
primaryImagesDeps android.Paths
- // Rules which should be used in make to install the outputs.
+ // Rules which should be used in make to install the outputs on host.
installs android.RuleBuilderInstalls
vdexInstalls android.RuleBuilderInstalls
unstrippedInstalls android.RuleBuilderInstalls
+
+ // Rules which should be used in make to install the outputs on device.
+ deviceInstalls android.RuleBuilderInstalls
}
// Get target-specific boot image variant for the given boot image config and target.
@@ -388,6 +391,11 @@
return variants
}
+// Returns true if the boot image should be installed in the APEX.
+func (image *bootImageConfig) shouldInstallInApex() bool {
+ return strings.HasPrefix(image.installDirOnDevice, "apex/")
+}
+
// Return boot image locations (as a list of symbolic paths).
//
// The image "location" is a symbolic path that, with multiarchitecture support, doesn't really
@@ -710,6 +718,7 @@
var vdexInstalls android.RuleBuilderInstalls
var unstrippedInstalls android.RuleBuilderInstalls
+ var deviceInstalls android.RuleBuilderInstalls
for _, artOrOat := range image.moduleFiles(ctx, outputDir, ".art", ".oat") {
cmd.ImplicitOutput(artOrOat)
@@ -735,12 +744,21 @@
android.RuleBuilderInstall{unstrippedOat, filepath.Join(installDir, unstrippedOat.Base())})
}
+ if image.installDirOnHost != image.installDirOnDevice && !image.shouldInstallInApex() && !ctx.Config().UnbundledBuild() {
+ installDirOnDevice := filepath.Join("/", image.installDirOnDevice, arch.String())
+ for _, file := range image.moduleFiles(ctx, outputDir, ".art", ".oat", ".vdex") {
+ deviceInstalls = append(deviceInstalls,
+ android.RuleBuilderInstall{file, filepath.Join(installDirOnDevice, file.Base())})
+ }
+ }
+
rule.Build(image.name+"JarsDexpreopt_"+image.target.String(), "dexpreopt "+image.name+" jars "+arch.String())
// save output and installed files for makevars
image.installs = rule.Installs()
image.vdexInstalls = vdexInstalls
image.unstrippedInstalls = unstrippedInstalls
+ image.deviceInstalls = deviceInstalls
}
const failureMessage = `ERROR: Dex2oat failed to compile a boot image.
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 26c1105..df8d8c8 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -41,17 +41,14 @@
var (
bootImageConfigKey = android.NewOnceKey("bootImageConfig")
+ bootImageConfigRawKey = android.NewOnceKey("bootImageConfigRaw")
artBootImageName = "art"
frameworkBootImageName = "boot"
)
-// Construct the global boot image configs.
-func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig {
- return ctx.Config().Once(bootImageConfigKey, func() interface{} {
-
+func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig {
+ return ctx.Config().Once(bootImageConfigRawKey, func() interface{} {
global := dexpreopt.GetGlobalConfig(ctx)
- targets := dexpreoptTargets(ctx)
- deviceDir := android.PathForOutput(ctx, ctx.Config().DeviceName())
artModules := global.ArtApexJars
frameworkModules := global.BootJars.RemoveList(artModules)
@@ -79,10 +76,22 @@
modules: frameworkModules,
}
- configs := map[string]*bootImageConfig{
+ return map[string]*bootImageConfig{
artBootImageName: &artCfg,
frameworkBootImageName: &frameworkCfg,
}
+ }).(map[string]*bootImageConfig)
+}
+
+// Construct the global boot image configs.
+func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig {
+ return ctx.Config().Once(bootImageConfigKey, func() interface{} {
+ targets := dexpreoptTargets(ctx)
+ deviceDir := android.PathForOutput(ctx, ctx.Config().DeviceName())
+
+ configs := genBootImageConfigRaw(ctx)
+ artCfg := configs[artBootImageName]
+ frameworkCfg := configs[frameworkBootImageName]
// common to all configs
for _, c := range configs {
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 7ad316f..5a84e05 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -19,6 +19,7 @@
"path/filepath"
"strings"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -806,7 +807,8 @@
properties PrebuiltStubsSourcesProperties
- stubsSrcJar android.Path
+ stubsSrcJar android.Path
+ jsonDataActions []blueprint.JSONDataAction
}
func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
@@ -822,6 +824,13 @@
return d.stubsSrcJar
}
+// AddJSONData is a temporary solution for droidstubs module to put action
+// related data into the module json graph.
+func (p *PrebuiltStubsSources) AddJSONData(d *map[string]interface{}) {
+ p.ModuleBase.AddJSONData(d)
+ (*d)["Actions"] = blueprint.FormatJSONDataActions(p.jsonDataActions)
+}
+
func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if len(p.properties.Srcs) != 1 {
ctx.PropertyErrorf("srcs", "must only specify one directory path or srcjar, contains %d paths", len(p.properties.Srcs))
@@ -829,9 +838,12 @@
}
src := p.properties.Srcs[0]
+ var jsonDataAction blueprint.JSONDataAction
if filepath.Ext(src) == ".srcjar" {
// This is a srcjar. We can use it directly.
p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
+ jsonDataAction.Inputs = []string{src}
+ jsonDataAction.Outputs = []string{src}
} else {
outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
@@ -855,7 +867,10 @@
rule.Restat()
rule.Build("zip src", "Create srcjar from prebuilt source")
p.stubsSrcJar = outPath
+ jsonDataAction.Inputs = srcPaths.Strings()
+ jsonDataAction.Outputs = []string{outPath.String()}
}
+ p.jsonDataActions = []blueprint.JSONDataAction{jsonDataAction}
}
func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 10d99f3..82ebba7 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -21,6 +21,8 @@
"strings"
"testing"
+ "github.com/google/blueprint"
+
"android/soong/android"
)
@@ -232,6 +234,27 @@
checkSystemModulesUseByDroidstubs(t, ctx, "stubs-prebuilt-system-modules", "prebuilt-jar.jar")
}
+func TestAddJSONData(t *testing.T) {
+ prebuiltStubsSources := PrebuiltStubsSources{}
+ prebuiltStubsSources.jsonDataActions = []blueprint.JSONDataAction{
+ blueprint.JSONDataAction{
+ Inputs: []string{},
+ Outputs: []string{},
+ },
+ }
+ jsonData := map[string]interface{}{}
+ prebuiltStubsSources.AddJSONData(&jsonData)
+ expectedOut := []map[string]interface{}{
+ map[string]interface{}{
+ "Inputs": []string{},
+ "Outputs": []string{},
+ },
+ }
+ if !reflect.DeepEqual(jsonData["Actions"], expectedOut) {
+ t.Errorf("The JSON action data %#v isn't as expected %#v.", jsonData["Actions"], expectedOut)
+ }
+}
+
func checkSystemModulesUseByDroidstubs(t *testing.T, ctx *android.TestContext, moduleName string, systemJar string) {
metalavaRule := ctx.ModuleForTests(moduleName, "android_common").Rule("metalava")
var systemJars []string
diff --git a/java/fuzz.go b/java/fuzz.go
index f72bfff..257f343 100644
--- a/java/fuzz.go
+++ b/java/fuzz.go
@@ -16,6 +16,8 @@
import (
"github.com/google/blueprint/proptools"
+ "sort"
+ "strings"
"android/soong/android"
"android/soong/fuzz"
@@ -27,6 +29,7 @@
func RegisterJavaFuzzBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("java_fuzz_host", FuzzFactory)
+ ctx.RegisterSingletonType("java_fuzz_packaging", javaFuzzPackagingFactory)
}
type JavaFuzzLibrary struct {
@@ -65,8 +68,92 @@
module.Module.properties.Installable = proptools.BoolPtr(false)
module.AddProperties(&module.fuzzPackagedModule.FuzzProperties)
+ // java_fuzz packaging rules collide when both linux_glibc and linux_bionic are enabled, disable the linux_bionic variants.
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ disableLinuxBionic := struct {
+ Target struct {
+ Linux_bionic struct {
+ Enabled *bool
+ }
+ }
+ }{}
+ disableLinuxBionic.Target.Linux_bionic.Enabled = proptools.BoolPtr(false)
+ ctx.AppendProperties(&disableLinuxBionic)
+ })
+
module.initModuleAndImport(module)
android.InitSdkAwareModule(module)
InitJavaModule(module, android.HostSupported)
return module
}
+
+// Responsible for generating rules that package fuzz targets into
+// their architecture & target/host specific zip file.
+type javaFuzzPackager struct {
+ fuzz.FuzzPackager
+}
+
+func javaFuzzPackagingFactory() android.Singleton {
+ return &javaFuzzPackager{}
+}
+
+func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
+ // Map between each architecture + host/device combination.
+ archDirs := make(map[fuzz.ArchOs][]fuzz.FileToZip)
+
+ // List of individual fuzz targets.
+ s.FuzzTargets = make(map[string]bool)
+
+ ctx.VisitAllModules(func(module android.Module) {
+ // Discard non-fuzz targets.
+ javaModule, ok := module.(*JavaFuzzLibrary)
+ if !ok {
+ return
+ }
+
+ fuzzModuleValidator := fuzz.FuzzModule{
+ javaModule.ModuleBase,
+ javaModule.DefaultableModuleBase,
+ javaModule.ApexModuleBase,
+ }
+
+ if ok := fuzz.IsValid(fuzzModuleValidator); !ok || *javaModule.Module.properties.Installable {
+ return
+ }
+
+ hostOrTargetString := "target"
+ if javaModule.Host() {
+ hostOrTargetString = "host"
+ }
+ archString := javaModule.Arch().ArchType.String()
+
+ archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
+ archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
+
+ var files []fuzz.FileToZip
+ builder := android.NewRuleBuilder(pctx, ctx)
+
+ // Package the artifacts (data, corpus, config and dictionary into a zipfile.
+ files = s.PackageArtifacts(ctx, module, javaModule.fuzzPackagedModule, archDir, builder)
+
+ // Add .jar
+ files = append(files, fuzz.FileToZip{javaModule.outputFile, ""})
+
+ archDirs[archOs], ok = s.BuildZipFile(ctx, module, javaModule.fuzzPackagedModule, files, builder, archDir, archString, "host", archOs, archDirs)
+ if !ok {
+ return
+ }
+
+ })
+ s.CreateFuzzPackage(ctx, archDirs, fuzz.Java, pctx)
+}
+
+func (s *javaFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
+ packages := s.Packages.Strings()
+ sort.Strings(packages)
+
+ ctx.Strict("SOONG_JAVA_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
+
+ // Preallocate the slice of fuzz targets to minimize memory allocations.
+ s.PreallocateSlice(ctx, "ALL_JAVA_FUZZ_TARGETS")
+}
diff --git a/java/genrule.go b/java/genrule.go
index 16743b3..5047c41 100644
--- a/java/genrule.go
+++ b/java/genrule.go
@@ -24,8 +24,8 @@
}
func RegisterGenRuleBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("java_genrule", genRuleFactory)
- ctx.RegisterModuleType("java_genrule_host", genRuleFactoryHost)
+ ctx.RegisterModuleType("java_genrule", GenRuleFactory)
+ ctx.RegisterModuleType("java_genrule_host", GenRuleFactoryHost)
}
// java_genrule is a genrule that can depend on other java_* objects.
@@ -33,7 +33,7 @@
// By default a java_genrule has a single variant that will run against the device variant of its dependencies and
// produce an output that can be used as an input to a device java rule.
//
-// Specifying `host_supported: true` will produce two variants, one that uses device dependencie sand one that uses
+// Specifying `host_supported: true` will produce two variants, one that uses device dependencies and one that uses
// host dependencies. Each variant will run the command.
//
// Use a java_genrule instead of a genrule when it needs to depend on or be depended on by other java modules, unless
@@ -44,7 +44,7 @@
// Use a java_genrule to package generated java resources:
//
// java_genrule {
-// name: "generated_resources",
+// name: "generated_resources",
// tools: [
// "generator",
// "soong_zip",
@@ -60,11 +60,12 @@
// srcs: ["src/**/*.java"],
// static_libs: ["generated_resources"],
// }
-func genRuleFactory() android.Module {
+func GenRuleFactory() android.Module {
module := genrule.NewGenRule()
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
+ android.InitBazelModule(module)
return module
}
@@ -73,11 +74,12 @@
//
// A java_genrule_host has a single variant that will run against the host variant of its dependencies and
// produce an output that can be used as an input to a host java rule.
-func genRuleFactoryHost() android.Module {
+func GenRuleFactoryHost() android.Module {
module := genrule.NewGenRule()
android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
+ android.InitBazelModule(module)
return module
}
diff --git a/java/genrule_test.go b/java/genrule_test.go
new file mode 100644
index 0000000..1c294b2
--- /dev/null
+++ b/java/genrule_test.go
@@ -0,0 +1,118 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+ "reflect"
+ "strings"
+ "testing"
+
+ "android/soong/android"
+)
+
+func testGenruleContext(config android.Config) *android.TestContext {
+ ctx := android.NewTestArchContext(config)
+ ctx.RegisterModuleType("java_genrule", GenRuleFactory)
+ ctx.Register()
+
+ return ctx
+}
+
+func TestGenruleCmd(t *testing.T) {
+ fs := map[string][]byte{
+ "tool": nil,
+ "foo": nil,
+ }
+ bp := `
+ java_genrule {
+ name: "gen",
+ tool_files: ["tool"],
+ cmd: "$(location tool) $(in) $(out)",
+ srcs: ["foo"],
+ out: ["out"],
+ }
+ `
+ config := android.TestArchConfig(t.TempDir(), nil, bp, fs)
+
+ ctx := testGenruleContext(config)
+
+ _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+ if errs == nil {
+ _, errs = ctx.PrepareBuildActions(config)
+ }
+ if errs != nil {
+ t.Fatal(errs)
+ }
+
+ gen := ctx.ModuleForTests("gen", "android_common").Output("out")
+ expected := []string{"foo"}
+ if !reflect.DeepEqual(expected, gen.Implicits.Strings()[:len(expected)]) {
+ t.Errorf(`want arm inputs %v, got %v`, expected, gen.Implicits.Strings())
+ }
+}
+
+func TestJarGenrules(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ }
+
+ java_genrule {
+ name: "jargen",
+ tool_files: ["b.java"],
+ cmd: "$(location b.java) $(in) $(out)",
+ out: ["jargen.jar"],
+ srcs: [":foo"],
+ }
+
+ java_library {
+ name: "bar",
+ static_libs: ["jargen"],
+ srcs: ["c.java"],
+ }
+
+ java_library {
+ name: "baz",
+ libs: ["jargen"],
+ srcs: ["c.java"],
+ }
+ `)
+
+ foo := ctx.ModuleForTests("foo", "android_common").Output("javac/foo.jar")
+ jargen := ctx.ModuleForTests("jargen", "android_common").Output("jargen.jar")
+ bar := ctx.ModuleForTests("bar", "android_common").Output("javac/bar.jar")
+ baz := ctx.ModuleForTests("baz", "android_common").Output("javac/baz.jar")
+ barCombined := ctx.ModuleForTests("bar", "android_common").Output("combined/bar.jar")
+
+ if g, w := jargen.Implicits.Strings(), foo.Output.String(); !android.InList(w, g) {
+ t.Errorf("expected jargen inputs [%q], got %q", w, g)
+ }
+
+ if !strings.Contains(bar.Args["classpath"], jargen.Output.String()) {
+ t.Errorf("bar classpath %v does not contain %q", bar.Args["classpath"], jargen.Output.String())
+ }
+
+ if !strings.Contains(baz.Args["classpath"], jargen.Output.String()) {
+ t.Errorf("baz classpath %v does not contain %q", baz.Args["classpath"], jargen.Output.String())
+ }
+
+ if len(barCombined.Inputs) != 2 ||
+ barCombined.Inputs[0].String() != bar.Output.String() ||
+ barCombined.Inputs[1].String() != jargen.Output.String() {
+ t.Errorf("bar combined jar inputs %v is not [%q, %q]",
+ barCombined.Inputs.Strings(), bar.Output.String(), jargen.Output.String())
+ }
+}
diff --git a/java/java.go b/java/java.go
index 9b4a005..bb7c32b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -24,6 +24,7 @@
"strings"
"android/soong/bazel"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -1866,6 +1867,7 @@
module.AddProperties(
&CommonProperties{},
&DeviceProperties{},
+ &OverridableDeviceProperties{},
&DexProperties{},
&DexpreoptProperties{},
&android.ProtoProperties{},
@@ -2000,6 +2002,7 @@
Deps bazel.LabelListAttribute
Main_class string
Jvm_flags bazel.StringListAttribute
+ Javacopts bazel.StringListAttribute
}
// JavaBinaryHostBp2Build is for java_binary_host bp2build.
@@ -2021,6 +2024,10 @@
Main_class: mainClass,
}
+ if m.properties.Javacflags != nil {
+ attrs.Javacopts = bazel.MakeStringListAttribute(m.properties.Javacflags)
+ }
+
// Attribute deps
deps := []string{}
if m.properties.Static_libs != nil {
diff --git a/java/java_test.go b/java/java_test.go
index 6e4e673..3a51981 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -997,60 +997,6 @@
}
}
-func TestJarGenrules(t *testing.T) {
- ctx, _ := testJava(t, `
- java_library {
- name: "foo",
- srcs: ["a.java"],
- }
-
- java_genrule {
- name: "jargen",
- tool_files: ["b.java"],
- cmd: "$(location b.java) $(in) $(out)",
- out: ["jargen.jar"],
- srcs: [":foo"],
- }
-
- java_library {
- name: "bar",
- static_libs: ["jargen"],
- srcs: ["c.java"],
- }
-
- java_library {
- name: "baz",
- libs: ["jargen"],
- srcs: ["c.java"],
- }
- `)
-
- foo := ctx.ModuleForTests("foo", "android_common").Output("javac/foo.jar")
- jargen := ctx.ModuleForTests("jargen", "android_common").Output("jargen.jar")
- bar := ctx.ModuleForTests("bar", "android_common").Output("javac/bar.jar")
- baz := ctx.ModuleForTests("baz", "android_common").Output("javac/baz.jar")
- barCombined := ctx.ModuleForTests("bar", "android_common").Output("combined/bar.jar")
-
- if g, w := jargen.Implicits.Strings(), foo.Output.String(); !android.InList(w, g) {
- t.Errorf("expected jargen inputs [%q], got %q", w, g)
- }
-
- if !strings.Contains(bar.Args["classpath"], jargen.Output.String()) {
- t.Errorf("bar classpath %v does not contain %q", bar.Args["classpath"], jargen.Output.String())
- }
-
- if !strings.Contains(baz.Args["classpath"], jargen.Output.String()) {
- t.Errorf("baz classpath %v does not contain %q", baz.Args["classpath"], jargen.Output.String())
- }
-
- if len(barCombined.Inputs) != 2 ||
- barCombined.Inputs[0].String() != bar.Output.String() ||
- barCombined.Inputs[1].String() != jargen.Output.String() {
- t.Errorf("bar combined jar inputs %v is not [%q, %q]",
- barCombined.Inputs.Strings(), bar.Output.String(), jargen.Output.String())
- }
-}
-
func TestExcludeFileGroupInSrcs(t *testing.T) {
ctx, _ := testJava(t, `
java_library {
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index e60ca00..e0e5b56 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -48,6 +48,7 @@
name: "bar",
srcs: ["a.java", "b.java"],
api_packages: ["bar"],
+ exclude_kotlinc_generated_files: true,
}
java_library {
name: "baz",
@@ -161,6 +162,14 @@
android.AssertDeepEquals(t, "qux exports (required)", []string{"fred", "quuz", "foo", "bar"}, requiredSdkLibs)
android.AssertDeepEquals(t, "qux exports (optional)", []string{}, optionalSdkLibs)
}
+
+ fooDexJar := result.ModuleForTests("foo", "android_common").Rule("d8")
+ // tests if kotlinc generated files are NOT excluded from output of foo.
+ android.AssertStringDoesNotContain(t, "foo dex", fooDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
+
+ barDexJar := result.ModuleForTests("bar", "android_common").Rule("d8")
+ // tests if kotlinc generated files are excluded from output of bar.
+ android.AssertStringDoesContain(t, "bar dex", barDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
}
func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) {
diff --git a/java/testing.go b/java/testing.go
index 7441e44..6c49bc8 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -506,3 +506,19 @@
}
}
}
+
+// Applies the given modifier on the boot image config with the given name.
+func FixtureModifyBootImageConfig(name string, configModifier func(*bootImageConfig)) android.FixturePreparer {
+ return android.FixtureModifyConfig(func(androidConfig android.Config) {
+ pathCtx := android.PathContextForTesting(androidConfig)
+ config := genBootImageConfigRaw(pathCtx)
+ configModifier(config[name])
+ })
+}
+
+// Sets the value of `installDirOnDevice` of the boot image config with the given name.
+func FixtureSetBootImageInstallDirOnDevice(name string, installDir string) android.FixturePreparer {
+ return FixtureModifyBootImageConfig(name, func(config *bootImageConfig) {
+ config.installDirOnDevice = installDir
+ })
+}
diff --git a/licenses/LICENSE b/licenses/LICENSE
index dae0406..d645695 100644
--- a/licenses/LICENSE
+++ b/licenses/LICENSE
@@ -1,16 +1,4 @@
- Copyright (c) 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.
-
- 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.
-
-
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
diff --git a/mk2rbc/expr.go b/mk2rbc/expr.go
index e78f492..3f355ac 100644
--- a/mk2rbc/expr.go
+++ b/mk2rbc/expr.go
@@ -728,6 +728,36 @@
}
}
+type binaryOpExpr struct {
+ left, right starlarkExpr
+ op string
+ returnType starlarkType
+}
+
+func (b *binaryOpExpr) emit(gctx *generationContext) {
+ b.left.emit(gctx)
+ gctx.write(" " + b.op + " ")
+ b.right.emit(gctx)
+}
+
+func (b *binaryOpExpr) typ() starlarkType {
+ return b.returnType
+}
+
+func (b *binaryOpExpr) emitListVarCopy(gctx *generationContext) {
+ b.emit(gctx)
+}
+
+func (b *binaryOpExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
+ b.left = b.left.transform(transformer)
+ b.right = b.right.transform(transformer)
+ if replacement := transformer(b); replacement != nil {
+ return replacement
+ } else {
+ return b
+ }
+}
+
type badExpr struct {
errorLocation ErrorLocation
message string
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 04038e4..e317cad 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -91,15 +91,20 @@
"foreach": &foreachCallPaser{},
"if": &ifCallParser{},
"info": &makeControlFuncParser{name: baseName + ".mkinfo"},
- "is-board-platform": &isBoardPlatformCallParser{},
+ "is-board-platform": &simpleCallParser{name: baseName + ".board_platform_is", returnType: starlarkTypeBool, addGlobals: true},
"is-board-platform2": &simpleCallParser{name: baseName + ".board_platform_is", returnType: starlarkTypeBool, addGlobals: true},
- "is-board-platform-in-list": &isBoardPlatformInListCallParser{},
+ "is-board-platform-in-list": &simpleCallParser{name: baseName + ".board_platform_in", returnType: starlarkTypeBool, addGlobals: true},
"is-board-platform-in-list2": &simpleCallParser{name: baseName + ".board_platform_in", returnType: starlarkTypeBool, addGlobals: true},
"is-product-in-list": &isProductInListCallParser{},
"is-vendor-board-platform": &isVendorBoardPlatformCallParser{},
"is-vendor-board-qcom": &isVendorBoardQcomCallParser{},
"lastword": &firstOrLastwordCallParser{isLastWord: true},
"notdir": &simpleCallParser{name: baseName + ".notdir", returnType: starlarkTypeString, addGlobals: false},
+ "math_max": &mathMaxOrMinCallParser{function: "max"},
+ "math_min": &mathMaxOrMinCallParser{function: "min"},
+ "math_gt_or_eq": &mathComparisonCallParser{op: ">="},
+ "math_gt": &mathComparisonCallParser{op: ">"},
+ "math_lt": &mathComparisonCallParser{op: "<"},
"my-dir": &myDirCallParser{},
"patsubst": &substCallParser{fname: "patsubst"},
"product-copy-files-by-pattern": &simpleCallParser{name: baseName + ".product_copy_files_by_pattern", returnType: starlarkTypeList, addGlobals: false},
@@ -249,19 +254,19 @@
gctx.writef("load(%q, %q)", baseUri, baseName)
// Emit exactly one load statement for each URI.
loadedSubConfigs := make(map[string]string)
- for _, sc := range gctx.starScript.inherited {
- uri := sc.path
+ for _, mi := range gctx.starScript.inherited {
+ uri := mi.path
if m, ok := loadedSubConfigs[uri]; ok {
// No need to emit load statement, but fix module name.
- sc.moduleLocalName = m
+ mi.moduleLocalName = m
continue
}
- if sc.optional {
+ if mi.optional || mi.missing {
uri += "|init"
}
gctx.newLine()
- gctx.writef("load(%q, %s = \"init\")", uri, sc.entryName())
- loadedSubConfigs[uri] = sc.moduleLocalName
+ gctx.writef("load(%q, %s = \"init\")", uri, mi.entryName())
+ loadedSubConfigs[uri] = mi.moduleLocalName
}
gctx.write("\n")
}
@@ -293,6 +298,20 @@
gctx.writef(`rblf.mk2rbc_error("%s", %q)`, el, message)
}
+func (gctx *generationContext) emitLoadCheck(im inheritedModule) {
+ if !im.needsLoadCheck() {
+ return
+ }
+ gctx.newLine()
+ gctx.writef("if not %s:", im.entryName())
+ gctx.indentLevel++
+ gctx.newLine()
+ gctx.write(`rblf.mkerror("`, gctx.starScript.mkFile, `", "Cannot find %s" % (`)
+ im.pathExpr().emit(gctx)
+ gctx.write("))")
+ gctx.indentLevel--
+}
+
type knownVariable struct {
name string
class varClass
@@ -446,7 +465,7 @@
variables: make(map[string]variable),
dependentModules: make(map[string]*moduleInfo),
soongNamespaces: make(map[string]map[string]bool),
- includeTops: []string{"vendor/google-devices"},
+ includeTops: []string{},
}
ctx.pushVarAssignments()
for _, item := range predefined {
@@ -746,11 +765,13 @@
moduleLocalName += fmt.Sprintf("%d", n)
}
ctx.moduleNameCount[moduleName] = n + 1
+ _, err := fs.Stat(ctx.script.sourceFS, path)
mi := &moduleInfo{
path: modulePath,
originalPath: path,
moduleLocalName: moduleLocalName,
optional: optional,
+ missing: err != nil,
}
ctx.dependentModules[modulePath] = mi
ctx.script.inherited = append(ctx.script.inherited, mi)
@@ -809,6 +830,10 @@
}
}
if pathPattern[0] == "" {
+ if len(ctx.includeTops) == 0 {
+ ctx.errorf(v, "inherit-product/include statements must not be prefixed with a variable, or must include a #RBC# include_top comment beforehand giving a root directory to search.")
+ return
+ }
// If pattern starts from the top. restrict it to the directories where
// we know inherit-product uses dynamically calculated path.
for _, p := range ctx.includeTops {
@@ -1064,6 +1089,23 @@
case *eqExpr:
typedExpr.isEq = !typedExpr.isEq
return typedExpr
+ case *binaryOpExpr:
+ switch typedExpr.op {
+ case ">":
+ typedExpr.op = "<="
+ return typedExpr
+ case "<":
+ typedExpr.op = ">="
+ return typedExpr
+ case ">=":
+ typedExpr.op = "<"
+ return typedExpr
+ case "<=":
+ typedExpr.op = ">"
+ return typedExpr
+ default:
+ return ¬Expr{expr: expr}
+ }
default:
return ¬Expr{expr: expr}
}
@@ -1086,6 +1128,13 @@
return otherOperand
}
}
+ if intOperand, err := strconv.Atoi(strings.TrimSpace(stringOperand)); err == nil && otherOperand.typ() == starlarkTypeInt {
+ return &eqExpr{
+ left: otherOperand,
+ right: &intLiteralExpr{literal: intOperand},
+ isEq: isEq,
+ }
+ }
}
return &eqExpr{left: xLeft, right: xRight, isEq: isEq}
@@ -1406,32 +1455,6 @@
return &variableRefExpr{ctx.addVariable("LOCAL_PATH"), true}
}
-type isBoardPlatformCallParser struct{}
-
-func (p *isBoardPlatformCallParser) parse(ctx *parseContext, node mkparser.Node, args *mkparser.MakeString) starlarkExpr {
- if args.Empty() {
- return ctx.newBadExpr(node, "is-board-platform requires an argument")
- }
- return &eqExpr{
- left: &variableRefExpr{ctx.addVariable("TARGET_BOARD_PLATFORM"), false},
- right: ctx.parseMakeString(node, args),
- isEq: true,
- }
-}
-
-type isBoardPlatformInListCallParser struct{}
-
-func (p *isBoardPlatformInListCallParser) parse(ctx *parseContext, node mkparser.Node, args *mkparser.MakeString) starlarkExpr {
- if args.Empty() {
- return ctx.newBadExpr(node, "is-board-platform-in-list requires an argument")
- }
- return &inExpr{
- expr: &variableRefExpr{ctx.addVariable("TARGET_BOARD_PLATFORM"), false},
- list: maybeConvertToStringList(ctx.parseMakeString(node, args)),
- isNot: false,
- }
-}
-
type isProductInListCallParser struct{}
func (p *isProductInListCallParser) parse(ctx *parseContext, node mkparser.Node, args *mkparser.MakeString) starlarkExpr {
@@ -1621,6 +1644,68 @@
return &indexExpr{&callExpr{object: arg, name: "split", returnType: starlarkTypeList}, index}
}
+func parseIntegerArguments(ctx *parseContext, node mkparser.Node, args *mkparser.MakeString, expectedArgs int) ([]starlarkExpr, error) {
+ parsedArgs := make([]starlarkExpr, 0)
+ for _, arg := range args.Split(",") {
+ expr := ctx.parseMakeString(node, arg)
+ if expr.typ() == starlarkTypeList {
+ return nil, fmt.Errorf("argument to math argument has type list, which cannot be converted to int")
+ }
+ if s, ok := maybeString(expr); ok {
+ intVal, err := strconv.Atoi(strings.TrimSpace(s))
+ if err != nil {
+ return nil, err
+ }
+ expr = &intLiteralExpr{literal: intVal}
+ } else if expr.typ() != starlarkTypeInt {
+ expr = &callExpr{
+ name: "int",
+ args: []starlarkExpr{expr},
+ returnType: starlarkTypeInt,
+ }
+ }
+ parsedArgs = append(parsedArgs, expr)
+ }
+ if len(parsedArgs) != expectedArgs {
+ return nil, fmt.Errorf("function should have %d arguments", expectedArgs)
+ }
+ return parsedArgs, nil
+}
+
+type mathComparisonCallParser struct {
+ op string
+}
+
+func (p *mathComparisonCallParser) parse(ctx *parseContext, node mkparser.Node, args *mkparser.MakeString) starlarkExpr {
+ parsedArgs, err := parseIntegerArguments(ctx, node, args, 2)
+ if err != nil {
+ return ctx.newBadExpr(node, err.Error())
+ }
+ return &binaryOpExpr{
+ left: parsedArgs[0],
+ right: parsedArgs[1],
+ op: p.op,
+ returnType: starlarkTypeBool,
+ }
+}
+
+type mathMaxOrMinCallParser struct {
+ function string
+}
+
+func (p *mathMaxOrMinCallParser) parse(ctx *parseContext, node mkparser.Node, args *mkparser.MakeString) starlarkExpr {
+ parsedArgs, err := parseIntegerArguments(ctx, node, args, 2)
+ if err != nil {
+ return ctx.newBadExpr(node, err.Error())
+ }
+ return &callExpr{
+ object: nil,
+ name: p.function,
+ args: parsedArgs,
+ returnType: starlarkTypeInt,
+ }
+}
+
func (ctx *parseContext) parseMakeString(node mkparser.Node, mk *mkparser.MakeString) starlarkExpr {
if mk.Const() {
return &stringLiteralExpr{mk.Dump()}
@@ -1671,6 +1756,13 @@
default:
ctx.errorf(x, "unsupported line %s", strings.ReplaceAll(x.Dump(), "\n", "\n#"))
}
+
+ // Clear the includeTops after each non-comment statement
+ // so that include annotations placed on certain statements don't apply
+ // globally for the rest of the makefile was well.
+ if _, wasComment := node.(*mkparser.Comment); !wasComment && len(ctx.includeTops) > 0 {
+ ctx.includeTops = []string{}
+ }
}
// Processes annotation. An annotation is a comment that starts with #RBC# and provides
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 1ba273b..d62882d 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -121,7 +121,7 @@
ifdef PRODUCT_NAME
$(call inherit-product, part1.mk)
else # Comment
-$(call inherit-product, $(LOCAL_PATH)/part1.mk)
+$(call inherit-product, $(LOCAL_PATH)/part.mk)
endif
`,
expected: `load("//build/make/core:product_config.rbc", "rblf")
@@ -132,10 +132,12 @@
cfg = rblf.cfg(handle)
rblf.inherit(handle, "part", _part_init)
if g.get("PRODUCT_NAME") != None:
+ if not _part1_init:
+ rblf.mkerror("product.mk", "Cannot find %s" % (":part1.star"))
rblf.inherit(handle, "part1", _part1_init)
else:
# Comment
- rblf.inherit(handle, "part1", _part1_init)
+ rblf.inherit(handle, "part", _part_init)
`,
},
{
@@ -173,6 +175,8 @@
cfg = rblf.cfg(handle)
_part_init(g, handle)
if g.get("PRODUCT_NAME") != None:
+ if not _part1_init:
+ rblf.mkerror("product.mk", "Cannot find %s" % (":part1.star"))
_part1_init(g, handle)
else:
if _part1_init != None:
@@ -598,9 +602,9 @@
def init(g, handle):
cfg = rblf.cfg(handle)
- if g.get("TARGET_BOARD_PLATFORM", "") in ["msm8998"]:
+ if rblf.board_platform_in(g, "msm8998"):
pass
- elif g.get("TARGET_BOARD_PLATFORM", "") != "copper":
+ elif not rblf.board_platform_is(g, "copper"):
pass
elif g.get("TARGET_BOARD_PLATFORM", "") not in g["QCOM_BOARD_PLATFORMS"]:
pass
@@ -1112,6 +1116,46 @@
`,
},
{
+ desc: "Dynamic inherit path that lacks necessary hint",
+ mkname: "product.mk",
+ in: `
+#RBC# include_top foo
+$(call inherit-product,$(MY_VAR)/font.mk)
+
+#RBC# include_top foo
+
+# There's some space and even this comment between the include_top and the inherit-product
+
+$(call inherit-product,$(MY_VAR)/font.mk)
+
+$(call inherit-product,$(MY_VAR)/font.mk)
+`,
+ expected: `#RBC# include_top foo
+load("//build/make/core:product_config.rbc", "rblf")
+load("//foo:font.star|init", _font_init = "init")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ _entry = {
+ "foo/font.mk": ("_font", _font_init),
+ }.get("%s/font.mk" % g.get("MY_VAR", ""))
+ (_varmod, _varmod_init) = _entry if _entry else (None, None)
+ if not _varmod_init:
+ rblf.mkerror("product.mk", "Cannot find %s" % ("%s/font.mk" % g.get("MY_VAR", "")))
+ rblf.inherit(handle, _varmod, _varmod_init)
+ #RBC# include_top foo
+ # There's some space and even this comment between the include_top and the inherit-product
+ _entry = {
+ "foo/font.mk": ("_font", _font_init),
+ }.get("%s/font.mk" % g.get("MY_VAR", ""))
+ (_varmod, _varmod_init) = _entry if _entry else (None, None)
+ if not _varmod_init:
+ rblf.mkerror("product.mk", "Cannot find %s" % ("%s/font.mk" % g.get("MY_VAR", "")))
+ rblf.inherit(handle, _varmod, _varmod_init)
+ rblf.mk2rbc_error("product.mk:11", "inherit-product/include statements must not be prefixed with a variable, or must include a #RBC# include_top comment beforehand giving a root directory to search.")
+`,
+ },
+ {
desc: "Ignore make rules",
mkname: "product.mk",
in: `
@@ -1241,6 +1285,63 @@
g["NATIVE_BRIDGE_PRODUCT_PACKAGES"] += " " + " ".join(rblf.addsuffix(".native_bridge", g.get("NATIVE_BRIDGE_ORIG_GUEST_LIBS", "")))
`,
},
+ {
+ desc: "Math functions",
+ mkname: "product.mk",
+ in: `
+# Test the math functions defined in build/make/common/math.mk
+ifeq ($(call math_max,2,5),5)
+endif
+ifeq ($(call math_min,2,5),2)
+endif
+ifeq ($(call math_gt_or_eq,2,5),true)
+endif
+ifeq ($(call math_gt,2,5),true)
+endif
+ifeq ($(call math_lt,2,5),true)
+endif
+ifeq ($(call math_gt_or_eq,2,5),)
+endif
+ifeq ($(call math_gt,2,5),)
+endif
+ifeq ($(call math_lt,2,5),)
+endif
+ifeq ($(call math_gt_or_eq,$(MY_VAR), 5),true)
+endif
+ifeq ($(call math_gt_or_eq,$(MY_VAR),$(MY_OTHER_VAR)),true)
+endif
+ifeq ($(call math_gt_or_eq,100$(MY_VAR),10),true)
+endif
+`,
+ expected: `# Test the math functions defined in build/make/common/math.mk
+load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ if max(2, 5) == 5:
+ pass
+ if min(2, 5) == 2:
+ pass
+ if 2 >= 5:
+ pass
+ if 2 > 5:
+ pass
+ if 2 < 5:
+ pass
+ if 2 < 5:
+ pass
+ if 2 <= 5:
+ pass
+ if 2 >= 5:
+ pass
+ if int(g.get("MY_VAR", "")) >= 5:
+ pass
+ if int(g.get("MY_VAR", "")) >= int(g.get("MY_OTHER_VAR", "")):
+ pass
+ if int("100%s" % g.get("MY_VAR", "")) >= 10:
+ pass
+`,
+ },
}
var known_variables = []struct {
diff --git a/mk2rbc/node.go b/mk2rbc/node.go
index ebc57b2..333a8da 100644
--- a/mk2rbc/node.go
+++ b/mk2rbc/node.go
@@ -47,6 +47,7 @@
originalPath string // Makefile file path
moduleLocalName string
optional bool
+ missing bool // a module may not exist if a module that depends on it is loaded dynamically
}
func (im moduleInfo) entryName() string {
@@ -57,7 +58,8 @@
name() string
entryName() string
emitSelect(gctx *generationContext)
- shouldExist() bool
+ pathExpr() starlarkExpr
+ needsLoadCheck() bool
}
type inheritedStaticModule struct {
@@ -72,8 +74,12 @@
func (im inheritedStaticModule) emitSelect(_ *generationContext) {
}
-func (im inheritedStaticModule) shouldExist() bool {
- return im.loadAlways
+func (im inheritedStaticModule) pathExpr() starlarkExpr {
+ return &stringLiteralExpr{im.path}
+}
+
+func (im inheritedStaticModule) needsLoadCheck() bool {
+ return im.missing
}
type inheritedDynamicModule struct {
@@ -105,20 +111,14 @@
gctx.write(")")
gctx.newLine()
gctx.writef("(%s, %s) = _entry if _entry else (None, None)", i.name(), i.entryName())
- if i.loadAlways {
- gctx.newLine()
- gctx.writef("if not %s:", i.entryName())
- gctx.indentLevel++
- gctx.newLine()
- gctx.write(`rblf.mkerror("`, gctx.starScript.mkFile, `", "Cannot find %s" % (`)
- i.path.emit(gctx)
- gctx.write("))")
- gctx.indentLevel--
- }
}
-func (i inheritedDynamicModule) shouldExist() bool {
- return i.loadAlways
+func (i inheritedDynamicModule) pathExpr() starlarkExpr {
+ return &i.path
+}
+
+func (i inheritedDynamicModule) needsLoadCheck() bool {
+ return true
}
type inheritNode struct {
@@ -128,20 +128,22 @@
func (inn *inheritNode) emit(gctx *generationContext) {
// Unconditional case:
+ // maybe check that loaded
// rblf.inherit(handle, <module>, module_init)
// Conditional case:
// if <module>_init != None:
// same as above
inn.module.emitSelect(gctx)
-
name := inn.module.name()
entry := inn.module.entryName()
- gctx.newLine()
if inn.loadAlways {
+ gctx.emitLoadCheck(inn.module)
+ gctx.newLine()
gctx.writef("%s(handle, %s, %s)", cfnInherit, name, entry)
return
}
+ gctx.newLine()
gctx.writef("if %s:", entry)
gctx.indentLevel++
gctx.newLine()
@@ -157,12 +159,14 @@
func (inn *includeNode) emit(gctx *generationContext) {
inn.module.emitSelect(gctx)
entry := inn.module.entryName()
- gctx.newLine()
if inn.loadAlways {
+ gctx.emitLoadCheck(inn.module)
+ gctx.newLine()
gctx.writef("%s(g, handle)", entry)
return
}
+ gctx.newLine()
gctx.writef("if %s != None:", entry)
gctx.indentLevel++
gctx.newLine()
diff --git a/rust/OWNERS b/rust/OWNERS
index b5b795c..d07ef7e 100644
--- a/rust/OWNERS
+++ b/rust/OWNERS
@@ -2,4 +2,4 @@
per-file * = chh@google.com, ivanlozano@google.com, jeffv@google.com, mmaurer@google.com, srhines@google.com
# Limited owners/reviewers of the allowed list.
-per-file allowed_list.go = chh@google.com, ivanlozano@google.com, jeffv@google.com, jgalenson@google.com, mmaurer@google.com, srhines@google.com
+per-file allowed_list.go = chh@google.com, ivanlozano@google.com, jeffv@google.com, mmaurer@google.com, srhines@google.com
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index 0d0b712..f318507 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -36,6 +36,7 @@
"system/tools/aidl",
"tools/security/fuzzing/example_rust_fuzzer",
"tools/security/fuzzing/orphans",
+ "tools/vendor",
"vendor/",
}
diff --git a/rust/config/global.go b/rust/config/global.go
index bfb2d1f..bae1dc8 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
var pctx = android.NewPackageContext("android/soong/rust/config")
var (
- RustDefaultVersion = "1.57.0"
+ RustDefaultVersion = "1.58.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2021"
Stdlibs = []string{
diff --git a/rust/config/lints.go b/rust/config/lints.go
index ef6b315..fe195c4 100644
--- a/rust/config/lints.go
+++ b/rust/config/lints.go
@@ -51,6 +51,7 @@
// It should be assumed that any warning lint will be promoted to a
// deny.
defaultClippyLints = []string{
+ "-A clippy::non-send-fields-in-send-ty",
"-A clippy::type-complexity",
"-A clippy::unnecessary-wraps",
"-A clippy::unusual-byte-groupings",
diff --git a/rust/rust.go b/rust/rust.go
index 778000d..cba92c3 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -366,10 +366,6 @@
return ""
}
-func (mod *Module) MinSdkVersion() string {
- return ""
-}
-
func (mod *Module) AlwaysSdk() bool {
return false
}
@@ -1497,15 +1493,13 @@
var _ android.ApexModule = (*Module)(nil)
-func (mod *Module) minSdkVersion() string {
+func (mod *Module) MinSdkVersion() string {
return String(mod.Properties.Min_sdk_version)
}
-var _ android.ApexModule = (*Module)(nil)
-
// Implements android.ApexModule
func (mod *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
- minSdkVersion := mod.minSdkVersion()
+ minSdkVersion := mod.MinSdkVersion()
if minSdkVersion == "apex_inherit" {
return nil
}
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index b1d1bb2..2ab784d 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -268,6 +268,9 @@
func (s *ShBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
s.generateAndroidBuildActions(ctx)
installDir := android.PathForModuleInstall(ctx, "bin", proptools.String(s.properties.Sub_dir))
+ if !s.Installable() {
+ s.SkipInstall()
+ }
s.installedFile = ctx.InstallExecutable(installDir, s.outputFilePath.Base(), s.outputFilePath)
for _, symlink := range s.Symlinks() {
ctx.InstallSymlink(installDir, symlink, s.installedFile)
@@ -283,6 +286,7 @@
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
s.customAndroidMkEntries(entries)
entries.SetString("LOCAL_MODULE_RELATIVE_PATH", proptools.String(s.properties.Sub_dir))
+ entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !s.Installable())
},
},
}}
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index d74f262..8f9a699 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -19,6 +19,7 @@
"math/rand"
"os"
"path/filepath"
+ "runtime"
"syscall"
"time"
@@ -87,6 +88,13 @@
}
vars["RBE_server_address"] = fmt.Sprintf("unix://%v", name)
}
+
+ rf := 1.0
+ if config.Parallel() < runtime.NumCPU() {
+ rf = float64(config.Parallel()) / float64(runtime.NumCPU())
+ }
+ vars["RBE_local_resource_fraction"] = fmt.Sprintf("%.2f", rf)
+
k, v := config.rbeAuth()
vars[k] = v
return vars
diff --git a/ui/metrics/bp2build_metrics_proto/bp2build_metrics.pb.go b/ui/metrics/bp2build_metrics_proto/bp2build_metrics.pb.go
index 11177e4..95f02ca 100644
--- a/ui/metrics/bp2build_metrics_proto/bp2build_metrics.pb.go
+++ b/ui/metrics/bp2build_metrics_proto/bp2build_metrics.pb.go
@@ -49,6 +49,10 @@
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"`
+ // Counts of converted modules by module type.
+ ConvertedModuleTypeCount map[string]uint64 `protobuf:"bytes,6,rep,name=convertedModuleTypeCount,proto3" json:"convertedModuleTypeCount,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
+ // Counts of total modules by module type.
+ TotalModuleTypeCount map[string]uint64 `protobuf:"bytes,7,rep,name=totalModuleTypeCount,proto3" json:"totalModuleTypeCount,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
}
func (x *Bp2BuildMetrics) Reset() {
@@ -118,13 +122,27 @@
return nil
}
+func (x *Bp2BuildMetrics) GetConvertedModuleTypeCount() map[string]uint64 {
+ if x != nil {
+ return x.ConvertedModuleTypeCount
+ }
+ return nil
+}
+
+func (x *Bp2BuildMetrics) GetTotalModuleTypeCount() map[string]uint64 {
+ if x != nil {
+ return x.TotalModuleTypeCount
+ }
+ 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,
+ 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0xac, 0x06, 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,
@@ -145,15 +163,40 @@
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,
+ 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x87, 0x01, 0x0a, 0x18, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72,
+ 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x75,
+ 0x6e, 0x74, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4b, 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, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x65,
+ 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74,
+ 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x18, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64,
+ 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
+ 0x7b, 0x0a, 0x14, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x47, 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, 0x54, 0x6f, 0x74,
+ 0x61, 0x6c, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x75, 0x6e,
+ 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x4d, 0x6f, 0x64,
+ 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 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, 0x1a,
+ 0x4b, 0x0a, 0x1d, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75,
+ 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 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, 0x1a, 0x47, 0x0a, 0x19,
+ 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 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 (
@@ -168,18 +211,22 @@
return file_bp2build_metrics_proto_rawDescData
}
-var file_bp2build_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_bp2build_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_bp2build_metrics_proto_goTypes = []interface{}{
(*Bp2BuildMetrics)(nil), // 0: soong_build_bp2build_metrics.Bp2BuildMetrics
nil, // 1: soong_build_bp2build_metrics.Bp2BuildMetrics.RuleClassCountEntry
+ nil, // 2: soong_build_bp2build_metrics.Bp2BuildMetrics.ConvertedModuleTypeCountEntry
+ nil, // 3: soong_build_bp2build_metrics.Bp2BuildMetrics.TotalModuleTypeCountEntry
}
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
+ 2, // 1: soong_build_bp2build_metrics.Bp2BuildMetrics.convertedModuleTypeCount:type_name -> soong_build_bp2build_metrics.Bp2BuildMetrics.ConvertedModuleTypeCountEntry
+ 3, // 2: soong_build_bp2build_metrics.Bp2BuildMetrics.totalModuleTypeCount:type_name -> soong_build_bp2build_metrics.Bp2BuildMetrics.TotalModuleTypeCountEntry
+ 3, // [3:3] is the sub-list for method output_type
+ 3, // [3:3] is the sub-list for method input_type
+ 3, // [3:3] is the sub-list for extension type_name
+ 3, // [3:3] is the sub-list for extension extendee
+ 0, // [0:3] is the sub-list for field type_name
}
func init() { file_bp2build_metrics_proto_init() }
@@ -207,7 +254,7 @@
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_bp2build_metrics_proto_rawDesc,
NumEnums: 0,
- NumMessages: 2,
+ NumMessages: 4,
NumExtensions: 0,
NumServices: 0,
},
diff --git a/ui/metrics/bp2build_metrics_proto/bp2build_metrics.proto b/ui/metrics/bp2build_metrics_proto/bp2build_metrics.proto
index 5e88966..6d98a3d 100644
--- a/ui/metrics/bp2build_metrics_proto/bp2build_metrics.proto
+++ b/ui/metrics/bp2build_metrics_proto/bp2build_metrics.proto
@@ -32,4 +32,10 @@
// List of converted modules
repeated string convertedModules = 5;
+
+ // Counts of converted modules by module type.
+ map<string, uint64> convertedModuleTypeCount = 6;
+
+ // Counts of total modules by module type.
+ map<string, uint64> totalModuleTypeCount = 7;
}