Merge "Add annotations.zip support to java_sdk_library"
diff --git a/android/bazel.go b/android/bazel.go
index 8341e57..bfd0f90 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -150,17 +150,23 @@
"build/bazel/platforms":/* recursive = */ true,
"build/bazel/product_variables":/* recursive = */ true,
"build/bazel_common_rules":/* recursive = */ true,
+ "build/make/tools":/* recursive = */ true,
"build/pesto":/* recursive = */ true,
// external/bazelbuild-rules_android/... is needed by mixed builds, otherwise mixed builds analysis fails
// e.g. ERROR: Analysis of target '@soong_injection//mixed_builds:buildroot' failed
"external/bazelbuild-rules_android":/* recursive = */ true,
"external/bazel-skylib":/* recursive = */ true,
+ "external/guava":/* recursive = */ true,
+ "external/error_prone":/* recursive = */ true,
+ "external/jsr305":/* recursive = */ true,
+ "frameworks/ex/common":/* recursive = */ true,
"prebuilts/sdk":/* recursive = */ false,
"prebuilts/sdk/tools":/* recursive = */ false,
"prebuilts/r8":/* recursive = */ false,
"packages/apps/Music":/* recursive = */ true,
+ "packages/apps/QuickSearchBox":/* recursive = */ true,
}
// Configure modules in these directories to enable bp2build_available: true or false by default.
@@ -259,7 +265,6 @@
// Per-module denylist of cc_library modules to only generate the static
// variant if their shared variant isn't ready or buildable by Bazel.
bp2buildCcLibraryStaticOnlyList = []string{
- "libstdc++", // http://b/186822597, cc_library, ld.lld: error: undefined symbol: __errno
"libjemalloc5", // http://b/188503688, cc_library, `target: { android: { enabled: false } }` for android targets.
}
@@ -294,8 +299,8 @@
}
}
-func GenerateCcLibraryStaticOnly(ctx BazelConversionPathContext) bool {
- return bp2buildCcLibraryStaticOnly[ctx.Module().Name()]
+func GenerateCcLibraryStaticOnly(moduleName string) bool {
+ return bp2buildCcLibraryStaticOnly[moduleName]
}
func ShouldKeepExistingBuildFileForDir(dir string) bool {
@@ -325,7 +330,7 @@
return false
}
- if GenerateCcLibraryStaticOnly(ctx) {
+ if GenerateCcLibraryStaticOnly(ctx.Module().Name()) {
// Don't use partially-converted cc_library targets in mixed builds,
// since mixed builds would generally rely on both static and shared
// variants of a cc_library.
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index ccbc156..b5746f7 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -15,11 +15,12 @@
package android
import (
- "android/soong/bazel"
"fmt"
"path/filepath"
"strings"
+ "android/soong/bazel"
+
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
)
@@ -84,24 +85,8 @@
// BazelLabelForModuleDeps expects a list of reference to other modules, ("<module>"
// or ":<module>") and returns a Bazel-compatible label which corresponds to dependencies on the
// module within the given ctx.
-func BazelLabelForModuleDeps(ctx BazelConversionPathContext, modules []string) bazel.LabelList {
- return bazelLabelForModuleDeps(ctx, modules, false)
-}
-
-// BazelLabelForModuleWholeDeps expects a list of references to other modules, ("<module>"
-// or ":<module>") and returns a Bazel-compatible label which corresponds to dependencies on the
-// module within the given ctx, where prebuilt dependencies will be appended with _alwayslink so
-// they can be handled as whole static libraries.
-func BazelLabelForModuleWholeDeps(ctx BazelConversionPathContext, modules []string) bazel.LabelList {
- return bazelLabelForModuleDeps(ctx, modules, true)
-}
-
-// BazelLabelForModuleDepsExcludes expects two lists: modules (containing modules to include in the
-// list), and excludes (modules to exclude from the list). Both of these should contain references
-// to other modules, ("<module>" or ":<module>"). It returns a Bazel-compatible label list which
-// corresponds to dependencies on the module within the given ctx, and the excluded dependencies.
-func BazelLabelForModuleDepsExcludes(ctx BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
- return bazelLabelForModuleDepsExcludes(ctx, modules, excludes, false)
+func BazelLabelForModuleDeps(ctx TopDownMutatorContext, modules []string) bazel.LabelList {
+ return BazelLabelForModuleDepsWithFn(ctx, modules, BazelModuleLabel)
}
// BazelLabelForModuleWholeDepsExcludes expects two lists: modules (containing modules to include in
@@ -110,11 +95,15 @@
// list which corresponds to dependencies on the module within the given ctx, and the excluded
// dependencies. Prebuilt dependencies will be appended with _alwayslink so they can be handled as
// whole static libraries.
-func BazelLabelForModuleWholeDepsExcludes(ctx BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
- return bazelLabelForModuleDepsExcludes(ctx, modules, excludes, true)
+func BazelLabelForModuleDepsExcludes(ctx TopDownMutatorContext, modules, excludes []string) bazel.LabelList {
+ return BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, BazelModuleLabel)
}
-func bazelLabelForModuleDeps(ctx BazelConversionPathContext, modules []string, isWholeLibs bool) bazel.LabelList {
+// BazelLabelForModuleDepsWithFn expects a list of reference to other modules, ("<module>"
+// or ":<module>") and applies moduleToLabelFn to determine and return a Bazel-compatible label
+// which corresponds to dependencies on the module within the given ctx.
+func BazelLabelForModuleDepsWithFn(ctx TopDownMutatorContext, modules []string,
+ moduleToLabelFn func(TopDownMutatorContext, blueprint.Module) string) bazel.LabelList {
var labels bazel.LabelList
// In some cases, a nil string list is different than an explicitly empty list.
if len(modules) == 0 && modules != nil {
@@ -127,7 +116,7 @@
module = ":" + module
}
if m, t := SrcIsModuleWithTag(module); m != "" {
- l := getOtherModuleLabel(ctx, m, t, isWholeLibs)
+ l := getOtherModuleLabel(ctx, m, t, moduleToLabelFn)
l.OriginalModuleName = bpText
labels.Includes = append(labels.Includes, l)
} else {
@@ -137,23 +126,29 @@
return labels
}
-func bazelLabelForModuleDepsExcludes(ctx BazelConversionPathContext, modules, excludes []string, isWholeLibs bool) bazel.LabelList {
- moduleLabels := bazelLabelForModuleDeps(ctx, RemoveListFromList(modules, excludes), isWholeLibs)
+// BazelLabelForModuleDepsExcludesWithFn expects two lists: modules (containing modules to include in the
+// list), and excludes (modules to exclude from the list). Both of these should contain references
+// to other modules, ("<module>" or ":<module>"). It applies moduleToLabelFn to determine and return a
+// Bazel-compatible label list which corresponds to dependencies on the module within the given ctx, and
+// the excluded dependencies.
+func BazelLabelForModuleDepsExcludesWithFn(ctx TopDownMutatorContext, modules, excludes []string,
+ moduleToLabelFn func(TopDownMutatorContext, blueprint.Module) string) bazel.LabelList {
+ moduleLabels := BazelLabelForModuleDepsWithFn(ctx, RemoveListFromList(modules, excludes), moduleToLabelFn)
if len(excludes) == 0 {
return moduleLabels
}
- excludeLabels := bazelLabelForModuleDeps(ctx, excludes, isWholeLibs)
+ excludeLabels := BazelLabelForModuleDepsWithFn(ctx, excludes, moduleToLabelFn)
return bazel.LabelList{
Includes: moduleLabels.Includes,
Excludes: excludeLabels.Includes,
}
}
-func BazelLabelForModuleSrcSingle(ctx BazelConversionPathContext, path string) bazel.Label {
+func BazelLabelForModuleSrcSingle(ctx TopDownMutatorContext, path string) bazel.Label {
return BazelLabelForModuleSrcExcludes(ctx, []string{path}, []string(nil)).Includes[0]
}
-func BazelLabelForModuleDepSingle(ctx BazelConversionPathContext, path string) bazel.Label {
+func BazelLabelForModuleDepSingle(ctx TopDownMutatorContext, path string) bazel.Label {
return BazelLabelForModuleDepsExcludes(ctx, []string{path}, []string(nil)).Includes[0]
}
@@ -163,7 +158,7 @@
// relative if within the same package).
// Properties must have been annotated with struct tag `android:"path"` so that dependencies modules
// will have already been handled by the path_deps mutator.
-func BazelLabelForModuleSrc(ctx BazelConversionPathContext, paths []string) bazel.LabelList {
+func BazelLabelForModuleSrc(ctx TopDownMutatorContext, paths []string) bazel.LabelList {
return BazelLabelForModuleSrcExcludes(ctx, paths, []string(nil))
}
@@ -173,7 +168,7 @@
// (absolute if in a different package or relative if within the same package).
// Properties must have been annotated with struct tag `android:"path"` so that dependencies modules
// will have already been handled by the path_deps mutator.
-func BazelLabelForModuleSrcExcludes(ctx BazelConversionPathContext, paths, excludes []string) bazel.LabelList {
+func BazelLabelForModuleSrcExcludes(ctx TopDownMutatorContext, paths, excludes []string) bazel.LabelList {
excludeLabels := expandSrcsForBazel(ctx, excludes, []string(nil))
excluded := make([]string, 0, len(excludeLabels.Includes))
for _, e := range excludeLabels.Includes {
@@ -293,7 +288,7 @@
// Properties passed as the paths or excludes argument must have been annotated with struct tag
// `android:"path"` so that dependencies on other modules will have already been handled by the
// path_deps mutator.
-func expandSrcsForBazel(ctx BazelConversionPathContext, paths, expandedExcludes []string) bazel.LabelList {
+func expandSrcsForBazel(ctx TopDownMutatorContext, paths, expandedExcludes []string) bazel.LabelList {
if paths == nil {
return bazel.LabelList{}
}
@@ -310,7 +305,7 @@
for _, p := range paths {
if m, tag := SrcIsModuleWithTag(p); m != "" {
- l := getOtherModuleLabel(ctx, m, tag, false)
+ l := getOtherModuleLabel(ctx, m, tag, BazelModuleLabel)
if !InList(l.Label, expandedExcludes) {
l.OriginalModuleName = fmt.Sprintf(":%s", m)
labels.Includes = append(labels.Includes, l)
@@ -341,7 +336,8 @@
// getOtherModuleLabel returns a bazel.Label for the given dependency/tag combination for the
// 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, isWholeLibs bool) bazel.Label {
+func getOtherModuleLabel(ctx TopDownMutatorContext, dep, tag string,
+ labelFromModule func(TopDownMutatorContext, blueprint.Module) string) bazel.Label {
m, _ := ctx.ModuleFromName(dep)
if m == nil {
panic(fmt.Errorf("No module named %q found, but was a direct dep of %q", dep, ctx.Module().Name()))
@@ -349,13 +345,11 @@
if !convertedToBazel(ctx, m) {
ctx.AddUnconvertedBp2buildDep(dep)
}
- otherLabel := bazelModuleLabel(ctx, m, tag)
- label := bazelModuleLabel(ctx, ctx.Module(), "")
- if isWholeLibs {
- if m, ok := m.(Module); ok && IsModulePrebuilt(m) {
- otherLabel += "_alwayslink"
- }
- }
+ label := BazelModuleLabel(ctx, ctx.Module())
+ otherLabel := labelFromModule(ctx, m)
+
+ // TODO(b/165114590): Convert tag (":name{.tag}") to corresponding Bazel implicit output targets.
+
if samePackage(label, otherLabel) {
otherLabel = bazelShortLabel(otherLabel)
}
@@ -365,7 +359,7 @@
}
}
-func bazelModuleLabel(ctx BazelConversionPathContext, module blueprint.Module, tag string) string {
+func BazelModuleLabel(ctx TopDownMutatorContext, module blueprint.Module) string {
// TODO(b/165114590): Convert tag (":name{.tag}") to corresponding Bazel implicit output targets.
if !convertedToBazel(ctx, module) {
return bp2buildModuleLabel(ctx, module)
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 07f492e..b1a6e2c 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -261,7 +261,7 @@
// Simple metrics tracking for bp2build
metrics := CodegenMetrics{
- RuleClassCount: make(map[string]int),
+ ruleClassCount: make(map[string]int),
}
dirs := make(map[string]bool)
@@ -277,14 +277,28 @@
switch ctx.Mode() {
case Bp2Build:
+ // There are two main ways of converting a Soong module to Bazel:
+ // 1) Manually handcrafting a Bazel target and associating the module with its label
+ // 2) Automatically generating with bp2build converters
+ //
+ // bp2build converters are used for the majority of modules.
if b, ok := m.(android.Bazelable); ok && b.HasHandcraftedLabel() {
- metrics.handCraftedTargetCount += 1
- metrics.TotalModuleCount += 1
- metrics.AddConvertedModule(m.Name())
+ // Handle modules converted to handcrafted targets.
+ //
+ // Since these modules are associated with some handcrafted
+ // target in a BUILD file, we simply append the entire contents
+ // of that BUILD file to the generated BUILD file.
+ //
+ // The append operation is only done once, even if there are
+ // multiple modules from the same directory associated to
+ // targets in the same BUILD file (or package).
+
+ // Log the module.
+ metrics.AddConvertedModule(m.Name(), Handcrafted)
+
pathToBuildFile := getBazelPackagePath(b)
- // We are using the entire contents of handcrafted build file, so if multiple targets within
- // a package have handcrafted targets, we only want to include the contents one time.
if _, exists := buildFileToAppend[pathToBuildFile]; exists {
+ // Append the BUILD file content once per package, at most.
return
}
t, err := getHandcraftedBuildContent(ctx, b, pathToBuildFile)
@@ -297,23 +311,29 @@
// something more targeted based on the rule type and target
buildFileToAppend[pathToBuildFile] = true
} else if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() {
+ // Handle modules converted to generated targets.
+
+ // Log the module.
+ metrics.AddConvertedModule(m.Name(), Generated)
+
+ // Handle modules with unconverted deps. By default, emit a warning.
if unconvertedDeps := aModule.GetUnconvertedBp2buildDeps(); len(unconvertedDeps) > 0 {
msg := fmt.Sprintf("%q depends on unconverted modules: %s", m.Name(), strings.Join(unconvertedDeps, ", "))
if ctx.unconvertedDepMode == warnUnconvertedDeps {
metrics.moduleWithUnconvertedDepsMsgs = append(metrics.moduleWithUnconvertedDepsMsgs, msg)
} else if ctx.unconvertedDepMode == errorModulesUnconvertedDeps {
- metrics.TotalModuleCount += 1
errs = append(errs, fmt.Errorf(msg))
return
}
}
targets = generateBazelTargets(bpCtx, aModule)
- metrics.AddConvertedModule(m.Name())
for _, t := range targets {
- metrics.RuleClassCount[t.ruleClass] += 1
+ // A module can potentially generate more than 1 Bazel
+ // target, each of a different rule class.
+ metrics.IncrementRuleClassCount(t.ruleClass)
}
} else {
- metrics.TotalModuleCount += 1
+ metrics.IncrementUnconvertedCount()
return
}
case QueryView:
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 371593b..b3a1053 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -1022,18 +1022,18 @@
}),
implementation_deps = select({
"//build/bazel/platforms/arch:arm": [],
- "//conditions:default": [":arm_static_lib_excludes"],
+ "//conditions:default": [":arm_static_lib_excludes_bp2build_cc_library_static"],
}) + select({
"//build/bazel/product_variables:malloc_not_svelte": [],
- "//conditions:default": [":malloc_not_svelte_static_lib_excludes"],
+ "//conditions:default": [":malloc_not_svelte_static_lib_excludes_bp2build_cc_library_static"],
}),
srcs_c = ["common.c"],
whole_archive_deps = select({
"//build/bazel/platforms/arch:arm": [],
- "//conditions:default": [":arm_whole_static_lib_excludes"],
+ "//conditions:default": [":arm_whole_static_lib_excludes_bp2build_cc_library_static"],
}) + select({
- "//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_whole_static_lib"],
- "//conditions:default": [":malloc_not_svelte_whole_static_lib_excludes"],
+ "//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_whole_static_lib_bp2build_cc_library_static"],
+ "//conditions:default": [":malloc_not_svelte_whole_static_lib_excludes_bp2build_cc_library_static"],
}),
)`,
},
diff --git a/bp2build/metrics.go b/bp2build/metrics.go
index 9e7b3b6..1cc4143 100644
--- a/bp2build/metrics.go
+++ b/bp2build/metrics.go
@@ -9,14 +9,17 @@
// Simple metrics struct to collect information about a Blueprint to BUILD
// conversion process.
type CodegenMetrics struct {
- // Total number of Soong/Blueprint modules
- TotalModuleCount int
+ // Total number of Soong modules converted to generated targets
+ generatedModuleCount int
+
+ // Total number of Soong modules converted to handcrafted targets
+ handCraftedModuleCount int
+
+ // Total number of unconverted Soong modules
+ unconvertedModuleCount int
// Counts of generated Bazel targets per Bazel rule class
- RuleClassCount map[string]int
-
- // Total number of handcrafted targets
- handCraftedTargetCount int
+ ruleClassCount map[string]int
moduleWithUnconvertedDepsMsgs []string
@@ -26,22 +29,49 @@
// Print the codegen metrics to stdout.
func (metrics *CodegenMetrics) Print() {
generatedTargetCount := 0
- for _, ruleClass := range android.SortedStringKeys(metrics.RuleClassCount) {
- count := metrics.RuleClassCount[ruleClass]
+ for _, ruleClass := range android.SortedStringKeys(metrics.ruleClassCount) {
+ count := metrics.ruleClassCount[ruleClass]
fmt.Printf("[bp2build] %s: %d targets\n", ruleClass, count)
generatedTargetCount += count
}
fmt.Printf(
"[bp2build] Generated %d total BUILD targets and included %d handcrafted BUILD targets from %d Android.bp modules.\n With %d modules with unconverted deps \n\t%s",
generatedTargetCount,
- metrics.handCraftedTargetCount,
- metrics.TotalModuleCount,
+ metrics.handCraftedModuleCount,
+ metrics.TotalModuleCount(),
len(metrics.moduleWithUnconvertedDepsMsgs),
strings.Join(metrics.moduleWithUnconvertedDepsMsgs, "\n\t"))
}
-func (metrics *CodegenMetrics) AddConvertedModule(moduleName string) {
+func (metrics *CodegenMetrics) IncrementRuleClassCount(ruleClass string) {
+ metrics.ruleClassCount[ruleClass] += 1
+}
+
+func (metrics *CodegenMetrics) IncrementUnconvertedCount() {
+ metrics.unconvertedModuleCount += 1
+}
+
+func (metrics *CodegenMetrics) TotalModuleCount() int {
+ return metrics.handCraftedModuleCount +
+ metrics.generatedModuleCount +
+ metrics.unconvertedModuleCount
+}
+
+type ConversionType int
+
+const (
+ Generated ConversionType = iota
+ Handcrafted
+)
+
+func (metrics *CodegenMetrics) AddConvertedModule(moduleName string, conversionType ConversionType) {
// Undo prebuilt_ module name prefix modifications
moduleName = android.RemoveOptionalPrebuiltPrefix(moduleName)
metrics.convertedModules = append(metrics.convertedModules, moduleName)
+
+ if conversionType == Handcrafted {
+ metrics.handCraftedModuleCount += 1
+ } else if conversionType == Generated {
+ metrics.generatedModuleCount += 1
+ }
}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 67ea70e..e48f757 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -20,6 +20,7 @@
"android/soong/android"
"android/soong/bazel"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -136,10 +137,10 @@
setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) {
attrs.Copts.SetSelectValue(axis, config, props.Cflags)
attrs.Srcs.SetSelectValue(axis, config, android.BazelLabelForModuleSrc(ctx, props.Srcs))
- attrs.Static_deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, props.Static_libs))
- attrs.Dynamic_deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, props.Shared_libs))
- attrs.Whole_archive_deps.SetSelectValue(axis, config, android.BazelLabelForModuleWholeDeps(ctx, props.Whole_static_libs))
- attrs.System_dynamic_deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, props.System_shared_libs))
+ attrs.Static_deps.SetSelectValue(axis, config, bazelLabelForStaticDeps(ctx, props.Static_libs))
+ attrs.Dynamic_deps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, props.Shared_libs))
+ attrs.Whole_archive_deps.SetSelectValue(axis, config, bazelLabelForWholeDeps(ctx, props.Whole_static_libs))
+ attrs.System_dynamic_deps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, props.System_shared_libs))
}
// system_dynamic_deps distinguishes between nil/empty list behavior:
// nil -> use default values
@@ -388,9 +389,9 @@
// Excludes to parallel Soong:
// https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=247-249;drc=088b53577dde6e40085ffd737a1ae96ad82fc4b0
staticLibs := android.FirstUniqueStrings(baseLinkerProps.Static_libs)
- staticDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDepsExcludes(ctx, staticLibs, baseLinkerProps.Exclude_static_libs))
+ staticDeps.SetSelectValue(axis, config, bazelLabelForStaticDepsExcludes(ctx, staticLibs, baseLinkerProps.Exclude_static_libs))
wholeArchiveLibs := android.FirstUniqueStrings(baseLinkerProps.Whole_static_libs)
- wholeArchiveDeps.SetSelectValue(axis, config, android.BazelLabelForModuleWholeDepsExcludes(ctx, wholeArchiveLibs, baseLinkerProps.Exclude_static_libs))
+ wholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, wholeArchiveLibs, baseLinkerProps.Exclude_static_libs))
systemSharedLibs := baseLinkerProps.System_shared_libs
// systemSharedLibs distinguishes between nil/empty list behavior:
@@ -399,15 +400,15 @@
if len(systemSharedLibs) > 0 {
systemSharedLibs = android.FirstUniqueStrings(systemSharedLibs)
}
- systemSharedDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, systemSharedLibs))
+ systemSharedDeps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, systemSharedLibs))
sharedLibs := android.FirstUniqueStrings(baseLinkerProps.Shared_libs)
- dynamicDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDepsExcludes(ctx, sharedLibs, baseLinkerProps.Exclude_shared_libs))
+ dynamicDeps.SetSelectValue(axis, config, bazelLabelForSharedDepsExcludes(ctx, sharedLibs, baseLinkerProps.Exclude_shared_libs))
headerLibs := android.FirstUniqueStrings(baseLinkerProps.Header_libs)
- headerDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, headerLibs))
+ headerDeps.SetSelectValue(axis, config, bazelLabelForHeaderDeps(ctx, headerLibs))
exportedLibs := android.FirstUniqueStrings(baseLinkerProps.Export_header_lib_headers)
- exportedDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, exportedLibs))
+ exportedDeps.SetSelectValue(axis, config, bazelLabelForHeaderDeps(ctx, exportedLibs))
linkopts.SetSelectValue(axis, config, getBp2BuildLinkerFlags(baseLinkerProps))
if baseLinkerProps.Version_script != nil {
@@ -424,14 +425,14 @@
// reference to the bazel attribute that should be set for the given product variable config
attribute *bazel.LabelListAttribute
- depResolutionFunc func(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList
+ depResolutionFunc func(ctx android.TopDownMutatorContext, modules, excludes []string) bazel.LabelList
}
productVarToDepFields := map[string]productVarDep{
// product variables do not support exclude_shared_libs
- "Shared_libs": productVarDep{attribute: &dynamicDeps, depResolutionFunc: android.BazelLabelForModuleDepsExcludes},
- "Static_libs": productVarDep{"Exclude_static_libs", &staticDeps, android.BazelLabelForModuleDepsExcludes},
- "Whole_static_libs": productVarDep{"Exclude_static_libs", &wholeArchiveDeps, android.BazelLabelForModuleWholeDepsExcludes},
+ "Shared_libs": productVarDep{attribute: &dynamicDeps, depResolutionFunc: bazelLabelForSharedDepsExcludes},
+ "Static_libs": productVarDep{"Exclude_static_libs", &staticDeps, bazelLabelForStaticDepsExcludes},
+ "Whole_static_libs": productVarDep{"Exclude_static_libs", &wholeArchiveDeps, bazelLabelForWholeDepsExcludes},
}
productVariableProps := android.ProductVariableProperties(ctx)
@@ -559,3 +560,59 @@
return exported
}
+
+func bazelLabelForStaticModule(ctx android.TopDownMutatorContext, m blueprint.Module) string {
+ label := android.BazelModuleLabel(ctx, m)
+ if aModule, ok := m.(android.Module); ok {
+ if ctx.OtherModuleType(aModule) == "cc_library" && !android.GenerateCcLibraryStaticOnly(m.Name()) {
+ label += "_bp2build_cc_library_static"
+ }
+ }
+ return label
+}
+
+func bazelLabelForSharedModule(ctx android.TopDownMutatorContext, m blueprint.Module) string {
+ // cc_library, at it's root name, propagates the shared library, which depends on the static
+ // library.
+ return android.BazelModuleLabel(ctx, m)
+}
+
+func bazelLabelForStaticWholeModuleDeps(ctx android.TopDownMutatorContext, m blueprint.Module) string {
+ label := bazelLabelForStaticModule(ctx, m)
+ if aModule, ok := m.(android.Module); ok {
+ if android.IsModulePrebuilt(aModule) {
+ label += "_alwayslink"
+ }
+ }
+ return label
+}
+
+func bazelLabelForWholeDeps(ctx android.TopDownMutatorContext, modules []string) bazel.LabelList {
+ return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticWholeModuleDeps)
+}
+
+func bazelLabelForWholeDepsExcludes(ctx android.TopDownMutatorContext, modules, excludes []string) bazel.LabelList {
+ return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForStaticWholeModuleDeps)
+}
+
+func bazelLabelForStaticDepsExcludes(ctx android.TopDownMutatorContext, modules, excludes []string) bazel.LabelList {
+ return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForStaticModule)
+}
+
+func bazelLabelForStaticDeps(ctx android.TopDownMutatorContext, modules []string) bazel.LabelList {
+ return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticModule)
+}
+
+func bazelLabelForSharedDeps(ctx android.TopDownMutatorContext, modules []string) bazel.LabelList {
+ return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForSharedModule)
+}
+
+func bazelLabelForHeaderDeps(ctx android.TopDownMutatorContext, modules []string) bazel.LabelList {
+ // This is not elegant, but bp2build's shared library targets only propagate
+ // their header information as part of the normal C++ provider.
+ return bazelLabelForSharedDeps(ctx, modules)
+}
+
+func bazelLabelForSharedDepsExcludes(ctx android.TopDownMutatorContext, modules, excludes []string) bazel.LabelList {
+ return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForSharedModule)
+}
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index 8c678a1..d4fcf7c 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -55,6 +55,8 @@
"android.hardware.power.stats-unstable-ndk_platform",
"android.hardware.radio-V1-ndk",
"android.hardware.radio-V1-ndk_platform",
+ "android.hardware.radio.config-V1-ndk",
+ "android.hardware.radio.config-V1-ndk_platform",
"android.hardware.rebootescrow-ndk_platform",
"android.hardware.security.keymint-V1-ndk",
"android.hardware.security.keymint-V1-ndk_platform",
diff --git a/cc/library.go b/cc/library.go
index f5a82c2..8a572f9 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -277,7 +277,7 @@
// For some cc_library modules, their static variants are ready to be
// converted, but not their shared variants. For these modules, delegate to
// the cc_library_static bp2build converter temporarily instead.
- if android.GenerateCcLibraryStaticOnly(ctx) {
+ if android.GenerateCcLibraryStaticOnly(ctx.Module().Name()) {
ccSharedOrStaticBp2BuildMutatorInternal(ctx, m, "cc_library_static")
return
}
diff --git a/cc/test.go b/cc/test.go
index 3934784..047a69e 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -357,7 +357,8 @@
}
func (test *testBinary) install(ctx ModuleContext, file android.Path) {
- testInstallBase := "/data/local/tests/unrestricted"
+ // TODO: (b/167308193) Switch to /data/local/tests/unrestricted as the default install base.
+ testInstallBase := "/data/local/tmp"
if ctx.inVendor() || ctx.useVndk() {
testInstallBase = "/data/local/tests/vendor"
}
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index fa63b46..3c9cac1 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -218,10 +218,16 @@
}
}
+func forceAnsiOutput() bool {
+ value := os.Getenv("SOONG_UI_ANSI_OUTPUT")
+ return value == "1" || value == "y" || value == "yes" || value == "on" || value == "true"
+}
+
func main() {
stdio := terminal.StdioImpl{}
- output := terminal.NewStatusOutput(stdio.Stdout(), "", false, false)
+ output := terminal.NewStatusOutput(stdio.Stdout(), "", false, false,
+ forceAnsiOutput())
log := logger.New(output)
defer log.Cleanup()
diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go
index fe567a9..be81487 100644
--- a/cmd/pom2bp/pom2bp.go
+++ b/cmd/pom2bp/pom2bp.go
@@ -24,6 +24,7 @@
"io/ioutil"
"os"
"os/exec"
+ "path"
"path/filepath"
"regexp"
"sort"
@@ -164,7 +165,8 @@
type Dependency struct {
XMLName xml.Name `xml:"dependency"`
- BpTarget string `xml:"-"`
+ BpTarget string `xml:"-"`
+ BazelTarget string `xml:"-"`
GroupId string `xml:"groupId"`
ArtifactId string `xml:"artifactId"`
@@ -230,6 +232,14 @@
}
}
+func (p Pom) BazelTargetType() string {
+ if p.IsAar() {
+ return "android_library"
+ } else {
+ return "java_library"
+ }
+}
+
func (p Pom) ImportModuleType() string {
if p.IsAar() {
return "android_library_import"
@@ -240,6 +250,14 @@
}
}
+func (p Pom) BazelImportTargetType() string {
+ if p.IsAar() {
+ return "aar_import"
+ } else {
+ return "java_import"
+ }
+}
+
func (p Pom) ImportProperty() string {
if p.IsAar() {
return "aars"
@@ -248,6 +266,14 @@
}
}
+func (p Pom) BazelImportProperty() string {
+ if p.IsAar() {
+ return "aar"
+ } else {
+ return "jars"
+ }
+}
+
func (p Pom) BpName() string {
if p.BpTarget == "" {
p.BpTarget = rewriteNames.MavenToBp(p.GroupId, p.ArtifactId)
@@ -263,6 +289,14 @@
return p.BpDeps("aar", []string{"compile", "runtime"})
}
+func (p Pom) BazelJarDeps() []string {
+ return p.BazelDeps("jar", []string{"compile", "runtime"})
+}
+
+func (p Pom) BazelAarDeps() []string {
+ return p.BazelDeps("aar", []string{"compile", "runtime"})
+}
+
func (p Pom) BpExtraStaticLibs() []string {
return extraStaticLibs[p.BpName()]
}
@@ -289,6 +323,91 @@
return ret
}
+// BazelDeps obtains dependencies filtered by type and scope. The results of this
+// method are formatted as Bazel BUILD targets.
+func (p Pom) BazelDeps(typeExt string, scopes []string) []string {
+ var ret []string
+ for _, d := range p.Dependencies {
+ if d.Type != typeExt || !InList(d.Scope, scopes) {
+ continue
+ }
+ ret = append(ret, d.BazelTarget)
+ }
+ return ret
+}
+
+func PathModVars() (string, string, string) {
+ cmd := "/bin/bash"
+ androidTop := os.Getenv("ANDROID_BUILD_TOP")
+ envSetupSh := path.Join(androidTop, "build/envsetup.sh")
+ return cmd, androidTop, envSetupSh
+}
+
+func InitRefreshMod(poms []*Pom) error {
+ cmd, _, envSetupSh := PathModVars()
+ // refreshmod is expensive, so if pathmod is already working we can skip it.
+ _, err := exec.Command(cmd, "-c", ". "+envSetupSh+" && pathmod "+poms[0].BpName()).Output()
+ if exitErr, _ := err.(*exec.ExitError); exitErr != nil || err != nil {
+ _, err := exec.Command(cmd, "-c", ". "+envSetupSh+" && refreshmod").Output()
+ if exitErr, _ := err.(*exec.ExitError); exitErr != nil {
+ return fmt.Errorf("failed to run %s\n%s\ntry running lunch.", cmd, string(exitErr.Stderr))
+ } else if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func BazelifyExtraDeps(extraDeps ExtraDeps, modules map[string]*Pom) error {
+ for _, deps := range extraDeps {
+ for _, dep := range deps {
+ bazelName, err := BpNameToBazelTarget(dep, modules)
+ if err != nil {
+ return err
+ }
+ dep = bazelName
+ }
+
+ }
+ return nil
+}
+
+func (p *Pom) GetBazelDepNames(modules map[string]*Pom) error {
+ for _, d := range p.Dependencies {
+ bazelName, err := BpNameToBazelTarget(d.BpName(), modules)
+ if err != nil {
+ return err
+ }
+ d.BazelTarget = bazelName
+ }
+ return nil
+}
+
+func BpNameToBazelTarget(bpName string, modules map[string]*Pom) (string, error) {
+ cmd, androidTop, envSetupSh := PathModVars()
+
+ if _, ok := modules[bpName]; ok {
+ // We've seen the POM for this dependency, it will be local to the output BUILD file
+ return ":" + bpName, nil
+ } else {
+ // we don't have the POM for this artifact, find and use the fully qualified target name.
+ output, err := exec.Command(cmd, "-c", ". "+envSetupSh+" && pathmod "+bpName).Output()
+ if exitErr, _ := err.(*exec.ExitError); exitErr != nil {
+ return "", fmt.Errorf("failed to run %s %s\n%s", cmd, bpName, string(exitErr.Stderr))
+ } else if err != nil {
+ return "", err
+ }
+ relPath := ""
+ for _, line := range strings.Fields(string(output)) {
+ if strings.Contains(line, androidTop) {
+ relPath = strings.TrimPrefix(line, androidTop)
+ relPath = strings.TrimLeft(relPath, "/")
+ }
+ }
+ return "//" + relPath + ":" + bpName, nil
+ }
+}
+
func (p Pom) SdkVersion() string {
return sdkVersion
}
@@ -512,6 +631,75 @@
}
`))
+var bazelTemplate = template.Must(template.New("bp").Parse(`
+{{.BazelImportTargetType}} (
+ name = "{{.BpName}}",
+ {{.BazelImportProperty}}: {{- if not .IsAar}}[{{- end}}"{{.ArtifactFile}}"{{- if not .IsAar}}]{{- end}},
+ visibility = ["//visibility:public"],
+ {{- if .IsAar}}
+ deps = [
+ {{- range .BazelJarDeps}}
+ "{{.}}",
+ {{- end}}
+ {{- range .BazelAarDeps}}
+ "{{.}}",
+ {{- end}}
+ {{- range .BpExtraStaticLibs}}
+ "{{.}}",
+ {{- end}}
+ {{- range .BpExtraLibs}}
+ "{{.}}",
+ {{- end}}
+ {{- range .BpOptionalUsesLibs}}
+ "{{.}}",
+ {{- end}}
+ ],
+ {{- end}}
+)
+`))
+
+var bazelDepsTemplate = template.Must(template.New("bp").Parse(`
+{{.BazelImportTargetType}} (
+ name = "{{.BpName}}",
+ {{.BazelImportProperty}} = {{- if not .IsAar}}[{{- end}}"{{.ArtifactFile}}"{{- if not .IsAar}}]{{- end}},
+ visibility = ["//visibility:public"],
+ deps = [
+ {{- range .BazelJarDeps}}
+ "{{.}}",
+ {{- end}}
+ {{- range .BazelAarDeps}}
+ "{{.}}",
+ {{- end}}
+ {{- range .BpExtraStaticLibs}}
+ "{{.}}",
+ {{- end}}
+ {{- range .BpExtraLibs}}
+ "{{.}}",
+ {{- end}}
+ {{- range .BpOptionalUsesLibs}}
+ "{{.}}",
+ {{- end}}
+ ],
+ exports = [
+ {{- range .BazelJarDeps}}
+ "{{.}}",
+ {{- end}}
+ {{- range .BazelAarDeps}}
+ "{{.}}",
+ {{- end}}
+ {{- range .BpExtraStaticLibs}}
+ "{{.}}",
+ {{- end}}
+ {{- range .BpExtraLibs}}
+ "{{.}}",
+ {{- end}}
+ {{- range .BpOptionalUsesLibs}}
+ "{{.}}",
+ {{- end}}
+ ],
+)
+`))
+
func parse(filename string) (*Pom, error) {
data, err := ioutil.ReadFile(filename)
if err != nil {
@@ -559,12 +747,14 @@
// Extract the old args from the file
line := scanner.Text()
- if strings.HasPrefix(line, "// pom2bp ") {
+ if strings.HasPrefix(line, "// pom2bp ") { // .bp file
line = strings.TrimPrefix(line, "// pom2bp ")
- } else if strings.HasPrefix(line, "// pom2mk ") {
+ } else if strings.HasPrefix(line, "// pom2mk ") { // .bp file converted from .mk file
line = strings.TrimPrefix(line, "// pom2mk ")
- } else if strings.HasPrefix(line, "# pom2mk ") {
+ } else if strings.HasPrefix(line, "# pom2mk ") { // .mk file
line = strings.TrimPrefix(line, "# pom2mk ")
+ } else if strings.HasPrefix(line, "# pom2bp ") { // Bazel BUILD file
+ line = strings.TrimPrefix(line, "# pom2bp ")
} else {
return fmt.Errorf("unexpected second line: %q", line)
}
@@ -650,6 +840,7 @@
}
var regen string
+ var pom2build bool
flag.Var(&excludes, "exclude", "Exclude module")
flag.Var(&extraStaticLibs, "extra-static-libs", "Extra static dependencies needed when depending on a module")
@@ -664,6 +855,7 @@
flag.BoolVar(&staticDeps, "static-deps", false, "Statically include direct dependencies")
flag.BoolVar(&jetifier, "jetifier", false, "Sets jetifier: true on all modules")
flag.StringVar(®en, "regen", "", "Rewrite specified file")
+ flag.BoolVar(&pom2build, "pom2build", false, "If true, will generate a Bazel BUILD file *instead* of a .bp file")
flag.Parse()
if regen != "" {
@@ -758,6 +950,16 @@
os.Exit(1)
}
+ if pom2build {
+ if err := InitRefreshMod(poms); err != nil {
+ fmt.Fprintf(os.Stderr, "Error in refreshmod: %s", err)
+ os.Exit(1)
+ }
+ BazelifyExtraDeps(extraStaticLibs, modules)
+ BazelifyExtraDeps(extraLibs, modules)
+ BazelifyExtraDeps(optionalUsesLibs, modules)
+ }
+
for _, pom := range poms {
if pom.IsAar() {
err := pom.ExtractMinSdkVersion()
@@ -767,19 +969,32 @@
}
}
pom.FixDeps(modules)
+ if pom2build {
+ pom.GetBazelDepNames(modules)
+ }
}
buf := &bytes.Buffer{}
+ commentString := "//"
+ if pom2build {
+ commentString = "#"
+ }
+ fmt.Fprintln(buf, commentString, "Automatically generated with:")
+ fmt.Fprintln(buf, commentString, "pom2bp", strings.Join(proptools.ShellEscapeList(os.Args[1:]), " "))
- fmt.Fprintln(buf, "// Automatically generated with:")
- fmt.Fprintln(buf, "// pom2bp", strings.Join(proptools.ShellEscapeList(os.Args[1:]), " "))
+ depsTemplate := bpDepsTemplate
+ template := bpTemplate
+ if pom2build {
+ depsTemplate = bazelDepsTemplate
+ template = bazelTemplate
+ }
for _, pom := range poms {
var err error
if staticDeps {
- err = bpDepsTemplate.Execute(buf, pom)
+ err = depsTemplate.Execute(buf, pom)
} else {
- err = bpTemplate.Execute(buf, pom)
+ err = template.Execute(buf, pom)
}
if err != nil {
fmt.Fprintln(os.Stderr, "Error writing", pom.PomFile, pom.BpName(), err)
@@ -787,11 +1002,15 @@
}
}
- out, err := bpfix.Reformat(buf.String())
- if err != nil {
- fmt.Fprintln(os.Stderr, "Error formatting output", err)
- os.Exit(1)
+ if pom2build {
+ os.Stdout.WriteString(buf.String())
+ } else {
+ out, err := bpfix.Reformat(buf.String())
+ if err != nil {
+ fmt.Fprintln(os.Stderr, "Error formatting output", err)
+ os.Exit(1)
+ }
+ os.Stdout.WriteString(out)
}
- os.Stdout.WriteString(out)
}
diff --git a/cmd/soong_build/Android.bp b/cmd/soong_build/Android.bp
index 703a875..e85163e 100644
--- a/cmd/soong_build/Android.bp
+++ b/cmd/soong_build/Android.bp
@@ -22,6 +22,7 @@
"blueprint",
"blueprint-bootstrap",
"golang-protobuf-proto",
+ "golang-protobuf-android",
"soong",
"soong-android",
"soong-bp2build",
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 09a2234..c5e8896 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -23,14 +23,14 @@
"strings"
"time"
+ "android/soong/android"
"android/soong/bp2build"
"android/soong/shared"
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/deptools"
"github.com/google/blueprint/pathtools"
-
- "android/soong/android"
+ androidProtobuf "google.golang.org/protobuf/android"
)
var (
@@ -85,6 +85,12 @@
// Flags that probably shouldn't be flags of soong_build but we haven't found
// the time to remove them yet
flag.BoolVar(&runGoTests, "t", false, "build and run go tests during bootstrap")
+
+ // Disable deterministic randomization in the protobuf package, so incremental
+ // builds with unrelated Soong changes don't trigger large rebuilds (since we
+ // write out text protos in command lines, and command line changes trigger
+ // rebuilds).
+ androidProtobuf.DisableRand()
}
func newNameResolver(config android.Config) *android.NameResolver {
diff --git a/cmd/soong_build/writedocs.go b/cmd/soong_build/writedocs.go
index 8d8f37f..d2fbed4 100644
--- a/cmd/soong_build/writedocs.go
+++ b/cmd/soong_build/writedocs.go
@@ -372,6 +372,7 @@
{{if .Properties -}}
<div class="accordion" id="{{getModule}}.{{.Name}}">
<span class="fixed">⊕</span><b>{{.Name}}</b>
+ <i>{{.Type}}</i>
{{- range .OtherNames -}}, {{.}}{{- end -}}
</div>
<div class="collapsible">
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index d709787..9ee373e 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -164,7 +164,8 @@
// Create a terminal output that mimics Ninja's.
output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.simpleOutput,
- build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"))
+ build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"),
+ build.OsEnvironment().IsEnvTrue("SOONG_UI_ANSI_OUTPUT"))
// Attach a new logger instance to the terminal output.
log := logger.New(output)
diff --git a/cuj/cuj.go b/cuj/cuj.go
index 413f423..869e0f7 100644
--- a/cuj/cuj.go
+++ b/cuj/cuj.go
@@ -48,7 +48,7 @@
// Run runs a single build command. It emulates the "m" command line by calling into Soong UI directly.
func (t *Test) Run(logsDir string) {
- output := terminal.NewStatusOutput(os.Stdout, "", false, false)
+ output := terminal.NewStatusOutput(os.Stdout, "", false, false, false)
log := logger.New(output)
defer log.Cleanup()
@@ -138,6 +138,8 @@
cujDir := filepath.Join(outDir, "cuj_tests")
+ wd, _ := os.Getwd()
+ os.Setenv("TOP", wd)
// Use a subdirectory for the out directory for the tests to keep them isolated.
os.Setenv("OUT_DIR", filepath.Join(cujDir, "out"))
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 51cd501..1c6fbac 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -1194,13 +1194,6 @@
// deferReportingMissingBootDexJar returns true if a missing boot dex jar should not be reported by
// Soong but should instead only be reported in ninja if the file is actually built.
func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.Module) bool {
- // TODO(b/179354495): Remove this workaround when it is unnecessary.
- // Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So,
- // create a fake one that will cause a build error only if it is used.
- if ctx.Config().AlwaysUsePrebuiltSdks() {
- return true
- }
-
// Any missing dependency should be allowed.
if ctx.Config().AllowMissingDependencies() {
return true
diff --git a/java/java.go b/java/java.go
index 2ca4ac8..4a44866 100644
--- a/java/java.go
+++ b/java/java.go
@@ -533,6 +533,10 @@
j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
j.Stem()+".jar", j.outputFile, extraInstallDeps...)
}
+
+ if ctx.Windows() {
+ j.HideFromMake()
+ }
}
func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -1030,14 +1034,14 @@
type binaryProperties struct {
// installable script to execute the resulting jar
- Wrapper *string `android:"path"`
+ Wrapper *string `android:"path,arch_variant"`
// Name of the class containing main to be inserted into the manifest as Main-Class.
Main_class *string
// Names of modules containing JNI libraries that should be installed alongside the host
// variant of the binary.
- Jni_libs []string
+ Jni_libs []string `android:"arch_variant"`
}
type Binary struct {
@@ -1075,14 +1079,27 @@
if j.binaryProperties.Wrapper != nil {
j.wrapperFile = android.PathForModuleSrc(ctx, *j.binaryProperties.Wrapper)
} else {
+ if ctx.Windows() {
+ ctx.PropertyErrorf("wrapper", "wrapper is required for Windows")
+ }
+
j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh")
}
+ ext := ""
+ if ctx.Windows() {
+ ext = ".bat"
+ }
+
// The host installation rules make the installed wrapper depend on all the dependencies
// of the wrapper variant, which will include the common variant's jar file and any JNI
// libraries. This is verified by TestBinary.
j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"),
- ctx.ModuleName(), j.wrapperFile)
+ ctx.ModuleName()+ext, j.wrapperFile)
+ }
+
+ if ctx.Windows() {
+ j.HideFromMake()
}
}
@@ -1283,6 +1300,10 @@
j.hideApexVariantFromMake = true
}
+ if ctx.Windows() {
+ j.HideFromMake()
+ }
+
jars := android.PathsForModuleSrc(ctx, j.properties.Jars)
jarName := j.Stem() + ".jar"
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 207a600..d469522 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -376,6 +376,9 @@
}
type sdkLibraryProperties struct {
+ // List of source files that are needed to compile the API, but are not part of runtime library.
+ Api_srcs []string `android:"arch_variant"`
+
// Visibility for impl library module. If not specified then defaults to the
// visibility property.
Impl_library_visibility []string
@@ -1447,6 +1450,7 @@
props.Name = proptools.StringPtr(name)
props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_source_visibility)
props.Srcs = append(props.Srcs, module.properties.Srcs...)
+ props.Srcs = append(props.Srcs, module.sdkLibraryProperties.Api_srcs...)
props.Sdk_version = module.deviceProperties.Sdk_version
props.System_modules = module.deviceProperties.System_modules
props.Installable = proptools.BoolPtr(false)
diff --git a/python/python.go b/python/python.go
index a35a1ac..f900172 100644
--- a/python/python.go
+++ b/python/python.go
@@ -45,7 +45,7 @@
type VersionProperties struct {
// whether the module is required to be built with this version.
// Defaults to true for Python 3, and false otherwise.
- Enabled *bool `android:"arch_variant"`
+ Enabled *bool
// list of source files specific to this Python version.
// Using the syntax ":module", srcs may reference the outputs of other modules that produce source files,
@@ -60,7 +60,7 @@
Libs []string `android:"arch_variant"`
// whether the binary is required to be built with embedded launcher for this version, defaults to false.
- Embedded_launcher *bool `android:"arch_variant"` // TODO(b/174041232): Remove this property
+ Embedded_launcher *bool // TODO(b/174041232): Remove this property
}
// properties that apply to all python modules
@@ -70,10 +70,10 @@
// eg. Pkg_path = "a/b/c"; Other packages can reference this module by using
// (from a.b.c import ...) statement.
// if left unspecified, all the source/data files path is unchanged within zip file.
- Pkg_path *string `android:"arch_variant"`
+ Pkg_path *string
// true, if the Python module is used internally, eg, Python std libs.
- Is_internal *bool `android:"arch_variant"`
+ Is_internal *bool
// list of source (.py) files compatible both with Python2 and Python3 used to compile the
// Python module.
diff --git a/ui/terminal/simple_status.go b/ui/terminal/simple_status.go
index 4e8c568..936b275 100644
--- a/ui/terminal/simple_status.go
+++ b/ui/terminal/simple_status.go
@@ -24,15 +24,17 @@
type simpleStatusOutput struct {
writer io.Writer
formatter formatter
+ keepANSI bool
}
// NewSimpleStatusOutput returns a StatusOutput that represents the
// current build status similarly to Ninja's built-in terminal
// output.
-func NewSimpleStatusOutput(w io.Writer, formatter formatter) status.StatusOutput {
+func NewSimpleStatusOutput(w io.Writer, formatter formatter, keepANSI bool) status.StatusOutput {
return &simpleStatusOutput{
writer: w,
formatter: formatter,
+ keepANSI: keepANSI,
}
}
@@ -54,7 +56,9 @@
progress := s.formatter.progress(counts) + str
output := s.formatter.result(result)
- output = string(stripAnsiEscapes([]byte(output)))
+ if !s.keepANSI {
+ output = string(stripAnsiEscapes([]byte(output)))
+ }
if output != "" {
fmt.Fprint(s.writer, progress, "\n", output)
diff --git a/ui/terminal/smart_status.go b/ui/terminal/smart_status.go
index 6bdf140..06a4064 100644
--- a/ui/terminal/smart_status.go
+++ b/ui/terminal/smart_status.go
@@ -77,7 +77,12 @@
s.requestedTableHeight = h
}
- s.updateTermSize()
+ if w, h, ok := termSize(s.writer); ok {
+ s.termWidth, s.termHeight = w, h
+ s.computeTableHeight()
+ } else {
+ s.tableMode = false
+ }
if s.tableMode {
// Add empty lines at the bottom of the screen to scroll back the existing history
@@ -296,40 +301,44 @@
close(s.sigwinch)
}
+// computeTableHeight recomputes s.tableHeight based on s.termHeight and s.requestedTableHeight.
+func (s *smartStatusOutput) computeTableHeight() {
+ tableHeight := s.requestedTableHeight
+ if tableHeight == 0 {
+ tableHeight = s.termHeight / 4
+ if tableHeight < 1 {
+ tableHeight = 1
+ } else if tableHeight > 10 {
+ tableHeight = 10
+ }
+ }
+ if tableHeight > s.termHeight-1 {
+ tableHeight = s.termHeight - 1
+ }
+ s.tableHeight = tableHeight
+}
+
+// updateTermSize recomputes the table height after a SIGWINCH and pans any existing text if
+// necessary.
func (s *smartStatusOutput) updateTermSize() {
if w, h, ok := termSize(s.writer); ok {
- firstUpdate := s.termHeight == 0 && s.termWidth == 0
oldScrollingHeight := s.termHeight - s.tableHeight
s.termWidth, s.termHeight = w, h
if s.tableMode {
- tableHeight := s.requestedTableHeight
- if tableHeight == 0 {
- tableHeight = s.termHeight / 4
- if tableHeight < 1 {
- tableHeight = 1
- } else if tableHeight > 10 {
- tableHeight = 10
- }
- }
- if tableHeight > s.termHeight-1 {
- tableHeight = s.termHeight - 1
- }
- s.tableHeight = tableHeight
+ s.computeTableHeight()
scrollingHeight := s.termHeight - s.tableHeight
- if !firstUpdate {
- // If the scrolling region has changed, attempt to pan the existing text so that it is
- // not overwritten by the table.
- if scrollingHeight < oldScrollingHeight {
- pan := oldScrollingHeight - scrollingHeight
- if pan > s.tableHeight {
- pan = s.tableHeight
- }
- fmt.Fprint(s.writer, ansi.panDown(pan))
+ // If the scrolling region has changed, attempt to pan the existing text so that it is
+ // not overwritten by the table.
+ if scrollingHeight < oldScrollingHeight {
+ pan := oldScrollingHeight - scrollingHeight
+ if pan > s.tableHeight {
+ pan = s.tableHeight
}
+ fmt.Fprint(s.writer, ansi.panDown(pan))
}
}
}
diff --git a/ui/terminal/status.go b/ui/terminal/status.go
index d8e7392..2ad174f 100644
--- a/ui/terminal/status.go
+++ b/ui/terminal/status.go
@@ -26,12 +26,12 @@
//
// statusFormat takes nearly all the same options as NINJA_STATUS.
// %c is currently unsupported.
-func NewStatusOutput(w io.Writer, statusFormat string, forceSimpleOutput, quietBuild bool) status.StatusOutput {
+func NewStatusOutput(w io.Writer, statusFormat string, forceSimpleOutput, quietBuild, forceKeepANSI bool) status.StatusOutput {
formatter := newFormatter(statusFormat, quietBuild)
if !forceSimpleOutput && isSmartTerminal(w) {
return NewSmartStatusOutput(w, formatter)
} else {
- return NewSimpleStatusOutput(w, formatter)
+ return NewSimpleStatusOutput(w, formatter, forceKeepANSI)
}
}
diff --git a/ui/terminal/status_test.go b/ui/terminal/status_test.go
index aa69dff..810e31d 100644
--- a/ui/terminal/status_test.go
+++ b/ui/terminal/status_test.go
@@ -94,7 +94,7 @@
t.Run("smart", func(t *testing.T) {
smart := &fakeSmartTerminal{termWidth: 40}
- stat := NewStatusOutput(smart, "", false, false)
+ stat := NewStatusOutput(smart, "", false, false, false)
tt.calls(stat)
stat.Flush()
@@ -105,7 +105,7 @@
t.Run("simple", func(t *testing.T) {
simple := &bytes.Buffer{}
- stat := NewStatusOutput(simple, "", false, false)
+ stat := NewStatusOutput(simple, "", false, false, false)
tt.calls(stat)
stat.Flush()
@@ -116,7 +116,7 @@
t.Run("force simple", func(t *testing.T) {
smart := &fakeSmartTerminal{termWidth: 40}
- stat := NewStatusOutput(smart, "", true, false)
+ stat := NewStatusOutput(smart, "", true, false, false)
tt.calls(stat)
stat.Flush()
@@ -269,7 +269,7 @@
os.Setenv(tableHeightEnVar, "")
smart := &fakeSmartTerminal{termWidth: 40}
- stat := NewStatusOutput(smart, "", false, false)
+ stat := NewStatusOutput(smart, "", false, false, false)
smartStat := stat.(*smartStatusOutput)
smartStat.sigwinchHandled = make(chan bool)