Merge "Keep build/bazel/ci/dist/BUILD for bp2build."
diff --git a/README.md b/README.md
index 18c6604..caffd3d 100644
--- a/README.md
+++ b/README.md
@@ -550,6 +550,26 @@
and produces build rules. The build rules are collected by blueprint and
written to a [ninja](http://ninja-build.org) build file.
+## Environment Variables Config File
+
+Soong can optionally load environment variables from a pre-specified
+configuration file during startup. These environment variables can be used
+to control the behavior of the build. For example, these variables can determine
+whether remote-execution should be used for the build or not.
+
+The `ANDROID_BUILD_ENVIRONMENT_CONFIG_DIR` environment variable specifies the
+directory in which the config file should be searched for. The
+`ANDROID_BUILD_ENVIRONMENT_CONFIG` variable determines the name of the config
+file to be searched for within the config directory. For example, the following
+build comand will load `ENV_VAR_1` and `ENV_VAR_2` environment variables from
+the `example_config.json` file inside the `build/soong` directory.
+
+```
+ANDROID_BUILD_ENVIRONMENT_CONFIG_DIR=build/soong \
+ ANDROID_BUILD_ENVIRONMENT_CONFIG=example_config \
+ build/soong/soong_ui.bash
+```
+
## Other documentation
* [Best Practices](docs/best_practices.md)
diff --git a/android/Android.bp b/android/Android.bp
index da36959..d3540b2 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -16,7 +16,9 @@
"soong-remoteexec",
"soong-response",
"soong-shared",
+ "soong-starlark-format",
"soong-ui-metrics_proto",
+
"golang-protobuf-proto",
"golang-protobuf-encoding-prototext",
diff --git a/android/arch.go b/android/arch.go
index 96a4cbf..a719cf3 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -917,7 +917,8 @@
for _, archType := range osArchTypeMap[os] {
targets = append(targets, GetCompoundTargetField(os, archType))
- // Also add the special "linux_<arch>" and "bionic_<arch>" property structs.
+ // Also add the special "linux_<arch>", "bionic_<arch>" , "glibc_<arch>", and
+ // "musl_<arch>" property structs.
if os.Linux() {
target := "Linux_" + archType.Name
if !InList(target, targets) {
@@ -930,6 +931,18 @@
targets = append(targets, target)
}
}
+ if os == Linux {
+ target := "Glibc_" + archType.Name
+ if !InList(target, targets) {
+ targets = append(targets, target)
+ }
+ }
+ if os == LinuxMusl {
+ target := "Musl_" + archType.Name
+ if !InList(target, targets) {
+ targets = append(targets, target)
+ }
+ }
}
}
@@ -1379,11 +1392,25 @@
result = append(result, osArchProperties)
}
+ if os == Linux {
+ field := "Glibc_" + archType.Name
+ userFriendlyField := "target.glibc_" + "_" + archType.Name
+ if osArchProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok {
+ result = append(result, osArchProperties)
+ }
+ }
+
if os == LinuxMusl {
+ field := "Musl_" + archType.Name
+ userFriendlyField := "target.musl_" + "_" + archType.Name
+ if osArchProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok {
+ result = append(result, osArchProperties)
+ }
+
// Special case: to ease the transition from glibc to musl, apply linux_glibc
// properties (which has historically mean host linux) to musl variants.
- field := "Linux_glibc_" + archType.Name
- userFriendlyField := "target.linux_glibc_" + archType.Name
+ field = "Linux_glibc_" + archType.Name
+ userFriendlyField = "target.linux_glibc_" + archType.Name
if osArchProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok {
result = append(result, osArchProperties)
}
diff --git a/android/bazel.go b/android/bazel.go
index 4dcc9ae..4a96918 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -289,6 +289,8 @@
"development/samples/WiFiDirectDemo": Bp2BuildDefaultTrue,
"development/sdk": Bp2BuildDefaultTrueRecursively,
"external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
+ "external/auto/common": Bp2BuildDefaultTrueRecursively,
+ "external/auto/service": Bp2BuildDefaultTrueRecursively,
"external/boringssl": Bp2BuildDefaultTrueRecursively,
"external/bouncycastle": Bp2BuildDefaultTrue,
"external/brotli": Bp2BuildDefaultTrue,
@@ -301,6 +303,7 @@
"external/icu": Bp2BuildDefaultTrueRecursively,
"external/icu/android_icu4j": Bp2BuildDefaultFalse, // java rules incomplete
"external/icu/icu4j": Bp2BuildDefaultFalse, // java rules incomplete
+ "external/javapoet": Bp2BuildDefaultTrueRecursively,
"external/jemalloc_new": Bp2BuildDefaultTrueRecursively,
"external/jsoncpp": Bp2BuildDefaultTrueRecursively,
"external/libcap": Bp2BuildDefaultTrueRecursively,
@@ -513,6 +516,8 @@
"art-script", // depends on unconverted modules: dalvikvm, dex2oat
"dex2oat-script", // depends on unconverted modules: dex2oat
+
+ "error_prone_checkerframework_dataflow_nullaway", // TODO(b/219908977): "Error in fail: deps not allowed without srcs; move to runtime_deps?"
}
// Per-module denylist of cc_library modules to only generate the static
diff --git a/android/config.go b/android/config.go
index 10e074c..877800a 100644
--- a/android/config.go
+++ b/android/config.go
@@ -38,6 +38,7 @@
"android/soong/android/soongconfig"
"android/soong/bazel"
"android/soong/remoteexec"
+ "android/soong/starlark_fmt"
)
// Bool re-exports proptools.Bool for the android package.
@@ -286,14 +287,12 @@
}
}
- //TODO(b/216168792) should use common function to print Starlark code
- nonArchVariantProductVariablesJson, err := json.MarshalIndent(&nonArchVariantProductVariables, "", " ")
+ nonArchVariantProductVariablesJson := starlark_fmt.PrintStringList(nonArchVariantProductVariables, 0)
if err != nil {
return fmt.Errorf("cannot marshal product variable data: %s", err.Error())
}
- //TODO(b/216168792) should use common function to print Starlark code
- archVariantProductVariablesJson, err := json.MarshalIndent(&archVariantProductVariables, "", " ")
+ archVariantProductVariablesJson := starlark_fmt.PrintStringList(archVariantProductVariables, 0)
if err != nil {
return fmt.Errorf("cannot marshal arch variant product variable data: %s", err.Error())
}
@@ -1983,3 +1982,8 @@
func (c *config) RBEWrapper() string {
return c.GetenvWithDefault("RBE_WRAPPER", remoteexec.DefaultWrapperPath)
}
+
+// UseHostMusl returns true if the host target has been configured to build against musl libc.
+func (c *config) UseHostMusl() bool {
+ return Bool(c.productVariables.HostMusl)
+}
diff --git a/android/license.go b/android/license.go
index 587cb36..ebee055 100644
--- a/android/license.go
+++ b/android/license.go
@@ -63,7 +63,7 @@
func (m *licenseModule) GenerateAndroidBuildActions(ctx ModuleContext) {
// license modules have no licenses, but license_kinds must refer to license_kind modules
mergeStringProps(&m.base().commonProperties.Effective_licenses, ctx.ModuleName())
- mergePathProps(&m.base().commonProperties.Effective_license_text, PathsForModuleSrc(ctx, m.properties.License_text)...)
+ namePathProps(&m.base().commonProperties.Effective_license_text, m.properties.Package_name, PathsForModuleSrc(ctx, m.properties.License_text)...)
for _, module := range ctx.GetDirectDepsWithTag(licenseKindTag) {
if lk, ok := module.(*licenseKindModule); ok {
mergeStringProps(&m.base().commonProperties.Effective_license_conditions, lk.properties.Conditions...)
diff --git a/android/license_sdk_member.go b/android/license_sdk_member.go
index 2ce921b..b17defe 100644
--- a/android/license_sdk_member.go
+++ b/android/license_sdk_member.go
@@ -90,7 +90,10 @@
// Populate the properties from the variant.
l := variant.(*licenseModule)
p.License_kinds = l.properties.License_kinds
- p.License_text = l.base().commonProperties.Effective_license_text
+ p.License_text = make(Paths, 0, len(l.base().commonProperties.Effective_license_text))
+ for _, np := range l.base().commonProperties.Effective_license_text {
+ p.License_text = append(p.License_text, np.Path)
+ }
}
func (p *licenseSdkMemberProperties) AddToPropertySet(ctx SdkMemberContext, propertySet BpPropertySet) {
diff --git a/android/licenses.go b/android/licenses.go
index b82d8d7..b51a06b 100644
--- a/android/licenses.go
+++ b/android/licenses.go
@@ -213,7 +213,7 @@
m.base().commonProperties.Effective_package_name = l.properties.Package_name
}
mergeStringProps(&m.base().commonProperties.Effective_licenses, module.base().commonProperties.Effective_licenses...)
- mergePathProps(&m.base().commonProperties.Effective_license_text, module.base().commonProperties.Effective_license_text...)
+ mergeNamedPathProps(&m.base().commonProperties.Effective_license_text, module.base().commonProperties.Effective_license_text...)
mergeStringProps(&m.base().commonProperties.Effective_license_kinds, module.base().commonProperties.Effective_license_kinds...)
mergeStringProps(&m.base().commonProperties.Effective_license_conditions, module.base().commonProperties.Effective_license_conditions...)
} else {
@@ -239,10 +239,24 @@
*prop = SortedUniqueStrings(*prop)
}
-// Update a property Path array with a distinct union of its values and a list of new values.
-func mergePathProps(prop *Paths, values ...Path) {
+// Update a property NamedPath array with a distinct union of its values and a list of new values.
+func namePathProps(prop *NamedPaths, name *string, values ...Path) {
+ if name == nil {
+ for _, value := range values {
+ *prop = append(*prop, NamedPath{value, ""})
+ }
+ } else {
+ for _, value := range values {
+ *prop = append(*prop, NamedPath{value, *name})
+ }
+ }
+ *prop = SortedUniqueNamedPaths(*prop)
+}
+
+// Update a property NamedPath array with a distinct union of its values and a list of new values.
+func mergeNamedPathProps(prop *NamedPaths, values ...NamedPath) {
*prop = append(*prop, values...)
- *prop = SortedUniquePaths(*prop)
+ *prop = SortedUniqueNamedPaths(*prop)
}
// Get the licenses property falling back to the package default.
diff --git a/android/licenses_test.go b/android/licenses_test.go
index 70160fa..8a81e12 100644
--- a/android/licenses_test.go
+++ b/android/licenses_test.go
@@ -90,9 +90,9 @@
"libother": []string{"shownotice"},
},
effectiveNotices: map[string][]string{
- "libexample1": []string{"top/LICENSE", "top/NOTICE"},
- "libnested": []string{"top/LICENSE", "top/NOTICE"},
- "libother": []string{"top/LICENSE", "top/NOTICE"},
+ "libexample1": []string{"top/LICENSE:topDog", "top/NOTICE:topDog"},
+ "libnested": []string{"top/LICENSE:topDog", "top/NOTICE:topDog"},
+ "libother": []string{"top/LICENSE:topDog", "top/NOTICE:topDog"},
},
},
diff --git a/android/module.go b/android/module.go
index d0807c3..03d3f80 100644
--- a/android/module.go
+++ b/android/module.go
@@ -16,11 +16,13 @@
import (
"fmt"
+ "net/url"
"os"
"path"
"path/filepath"
"reflect"
"regexp"
+ "sort"
"strings"
"text/scanner"
@@ -616,6 +618,53 @@
Tag *string `android:"arch_variant"`
}
+// NamedPath associates a path with a name. e.g. a license text path with a package name
+type NamedPath struct {
+ Path Path
+ Name string
+}
+
+// String returns an escaped string representing the `NamedPath`.
+func (p NamedPath) String() string {
+ if len(p.Name) > 0 {
+ return p.Path.String() + ":" + url.QueryEscape(p.Name)
+ }
+ return p.Path.String()
+}
+
+// NamedPaths describes a list of paths each associated with a name.
+type NamedPaths []NamedPath
+
+// Strings returns a list of escaped strings representing each `NamedPath` in the list.
+func (l NamedPaths) Strings() []string {
+ result := make([]string, 0, len(l))
+ for _, p := range l {
+ result = append(result, p.String())
+ }
+ return result
+}
+
+// SortedUniqueNamedPaths modifies `l` in place to return the sorted unique subset.
+func SortedUniqueNamedPaths(l NamedPaths) NamedPaths {
+ if len(l) == 0 {
+ return l
+ }
+ sort.Slice(l, func(i, j int) bool {
+ return l[i].String() < l[j].String()
+ })
+ k := 0
+ for i := 1; i < len(l); i++ {
+ if l[i].String() == l[k].String() {
+ continue
+ }
+ k++
+ if k < i {
+ l[k] = l[i]
+ }
+ }
+ return l[:k+1]
+}
+
type nameProperties struct {
// The name of the module. Must be unique across all modules.
Name *string
@@ -684,7 +733,7 @@
// Override of module name when reporting licenses
Effective_package_name *string `blueprint:"mutated"`
// Notice files
- Effective_license_text Paths `blueprint:"mutated"`
+ Effective_license_text NamedPaths `blueprint:"mutated"`
// License names
Effective_license_kinds []string `blueprint:"mutated"`
// License conditions
@@ -1801,7 +1850,11 @@
}
func (m *ModuleBase) EffectiveLicenseFiles() Paths {
- return m.commonProperties.Effective_license_text
+ result := make(Paths, 0, len(m.commonProperties.Effective_license_text))
+ for _, p := range m.commonProperties.Effective_license_text {
+ result = append(result, p.Path)
+ }
+ return result
}
// computeInstallDeps finds the installed paths of all dependencies that have a dependency
diff --git a/android/module_test.go b/android/module_test.go
index c35e66e..a1bab6d 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -816,3 +816,120 @@
})
}
}
+
+func TestSortedUniqueNamedPaths(t *testing.T) {
+ type np struct {
+ path, name string
+ }
+ makePaths := func(l []np) NamedPaths {
+ result := make(NamedPaths, 0, len(l))
+ for _, p := range l {
+ result = append(result, NamedPath{PathForTesting(p.path), p.name})
+ }
+ return result
+ }
+
+ tests := []struct {
+ name string
+ in []np
+ expectedOut []np
+ }{
+ {
+ name: "empty",
+ in: []np{},
+ expectedOut: []np{},
+ },
+ {
+ name: "all_same",
+ in: []np{
+ {"a.txt", "A"},
+ {"a.txt", "A"},
+ {"a.txt", "A"},
+ {"a.txt", "A"},
+ {"a.txt", "A"},
+ },
+ expectedOut: []np{
+ {"a.txt", "A"},
+ },
+ },
+ {
+ name: "same_path_different_names",
+ in: []np{
+ {"a.txt", "C"},
+ {"a.txt", "A"},
+ {"a.txt", "D"},
+ {"a.txt", "B"},
+ {"a.txt", "E"},
+ },
+ expectedOut: []np{
+ {"a.txt", "A"},
+ {"a.txt", "B"},
+ {"a.txt", "C"},
+ {"a.txt", "D"},
+ {"a.txt", "E"},
+ },
+ },
+ {
+ name: "different_paths_same_name",
+ in: []np{
+ {"b/b.txt", "A"},
+ {"a/a.txt", "A"},
+ {"a/txt", "A"},
+ {"b", "A"},
+ {"a/b/d", "A"},
+ },
+ expectedOut: []np{
+ {"a/a.txt", "A"},
+ {"a/b/d", "A"},
+ {"a/txt", "A"},
+ {"b/b.txt", "A"},
+ {"b", "A"},
+ },
+ },
+ {
+ name: "all_different",
+ in: []np{
+ {"b/b.txt", "A"},
+ {"a/a.txt", "B"},
+ {"a/txt", "D"},
+ {"b", "C"},
+ {"a/b/d", "E"},
+ },
+ expectedOut: []np{
+ {"a/a.txt", "B"},
+ {"a/b/d", "E"},
+ {"a/txt", "D"},
+ {"b/b.txt", "A"},
+ {"b", "C"},
+ },
+ },
+ {
+ name: "some_different",
+ in: []np{
+ {"b/b.txt", "A"},
+ {"a/a.txt", "B"},
+ {"a/txt", "D"},
+ {"a/b/d", "E"},
+ {"b", "C"},
+ {"a/a.txt", "B"},
+ {"a/b/d", "E"},
+ },
+ expectedOut: []np{
+ {"a/a.txt", "B"},
+ {"a/b/d", "E"},
+ {"a/txt", "D"},
+ {"b/b.txt", "A"},
+ {"b", "C"},
+ },
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ actual := SortedUniqueNamedPaths(makePaths(tt.in))
+ expected := makePaths(tt.expectedOut)
+ t.Logf("actual: %v", actual)
+ t.Logf("expected: %v", expected)
+ AssertDeepEquals(t, "SortedUniqueNamedPaths ", expected, actual)
+ })
+ }
+}
diff --git a/android/proto.go b/android/proto.go
index 64d4d05..f466261 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -187,7 +187,7 @@
if axis == bazel.NoConfigAxis {
info.Type = props.Proto.Type
- if proptools.BoolDefault(props.Proto.Canonical_path_from_root, canonicalPathFromRootDefault) {
+ if !proptools.BoolDefault(props.Proto.Canonical_path_from_root, canonicalPathFromRootDefault) {
// an empty string indicates to strips the package path
path := ""
attrs.Strip_import_prefix = &path
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 1c6b1c0..098c1fc 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -470,7 +470,7 @@
func (r *RuleBuilder) depFileMergerCmd(depFiles WritablePaths) *RuleBuilderCommand {
return r.Command().
- BuiltTool("dep_fixer").
+ builtToolWithoutDeps("dep_fixer").
Inputs(depFiles.Paths())
}
@@ -638,7 +638,7 @@
}
sboxCmd.Text("rm -rf").Output(r.outDir)
sboxCmd.Text("&&")
- sboxCmd.BuiltTool("sbox").
+ sboxCmd.builtToolWithoutDeps("sbox").
Flag("--sandbox-path").Text(shared.TempDirForOutDir(PathForOutput(r.ctx).String())).
Flag("--manifest").Input(r.sboxManifestPath)
@@ -1040,6 +1040,19 @@
// It is equivalent to:
// cmd.Tool(ctx.Config().HostToolPath(ctx, tool))
func (c *RuleBuilderCommand) BuiltTool(tool string) *RuleBuilderCommand {
+ if c.rule.ctx.Config().UseHostMusl() {
+ // If the host is using musl, assume that the tool was built against musl libc and include
+ // libc_musl.so in the sandbox.
+ // TODO(ccross): if we supported adding new dependencies during GenerateAndroidBuildActions
+ // this could be a dependency + TransitivePackagingSpecs.
+ c.ImplicitTool(c.rule.ctx.Config().HostJNIToolPath(c.rule.ctx, "libc_musl"))
+ }
+ return c.builtToolWithoutDeps(tool)
+}
+
+// builtToolWithoutDeps is similar to BuiltTool, but doesn't add any dependencies. It is used
+// internally by RuleBuilder for helper tools that are known to be compiled statically.
+func (c *RuleBuilderCommand) builtToolWithoutDeps(tool string) *RuleBuilderCommand {
return c.Tool(c.rule.ctx.Config().HostToolPath(c.rule.ctx, tool))
}
diff --git a/android/soong_config_modules_test.go b/android/soong_config_modules_test.go
index acb9d18..ceb8e45 100644
--- a/android/soong_config_modules_test.go
+++ b/android/soong_config_modules_test.go
@@ -386,6 +386,46 @@
})).RunTest(t)
}
+func TestDuplicateStringValueInSoongConfigStringVariable(t *testing.T) {
+ bp := `
+ soong_config_string_variable {
+ name: "board",
+ values: ["soc_a", "soc_b", "soc_c", "soc_a"],
+ }
+
+ soong_config_module_type {
+ name: "acme_test",
+ module_type: "test",
+ config_namespace: "acme",
+ variables: ["board"],
+ properties: ["cflags", "srcs", "defaults"],
+ }
+ `
+
+ fixtureForVendorVars := func(vars map[string]map[string]string) FixturePreparer {
+ return FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+ variables.VendorVars = vars
+ })
+ }
+
+ GroupFixturePreparers(
+ fixtureForVendorVars(map[string]map[string]string{"acme": {"feature1": "1"}}),
+ PrepareForTestWithDefaults,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("soong_config_module_type_import", SoongConfigModuleTypeImportFactory)
+ ctx.RegisterModuleType("soong_config_module_type", SoongConfigModuleTypeFactory)
+ ctx.RegisterModuleType("soong_config_string_variable", SoongConfigStringVariableDummyFactory)
+ ctx.RegisterModuleType("soong_config_bool_variable", SoongConfigBoolVariableDummyFactory)
+ ctx.RegisterModuleType("test_defaults", soongConfigTestDefaultsModuleFactory)
+ ctx.RegisterModuleType("test", soongConfigTestModuleFactory)
+ }),
+ FixtureWithRootAndroidBp(bp),
+ ).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern([]string{
+ // TODO(b/171232169): improve the error message for non-existent properties
+ `Android.bp: soong_config_string_variable: values property error: duplicate value: "soc_a"`,
+ })).RunTest(t)
+}
+
func testConfigWithVendorVars(buildDir, bp string, fs map[string][]byte, vendorVars map[string]map[string]string) Config {
config := TestConfig(buildDir, nil, bp, fs)
diff --git a/android/soongconfig/Android.bp b/android/soongconfig/Android.bp
index 9bf3344..8fe1ff1 100644
--- a/android/soongconfig/Android.bp
+++ b/android/soongconfig/Android.bp
@@ -10,6 +10,7 @@
"blueprint-parser",
"blueprint-proptools",
"soong-bazel",
+ "soong-starlark-format",
],
srcs: [
"config.go",
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index 09a5057..212b752 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -25,6 +25,8 @@
"github.com/google/blueprint"
"github.com/google/blueprint/parser"
"github.com/google/blueprint/proptools"
+
+ "android/soong/starlark_fmt"
)
const conditionsDefault = "conditions_default"
@@ -177,10 +179,14 @@
return []error{fmt.Errorf("values property must be set")}
}
+ vals := make(map[string]bool, len(stringProps.Values))
for _, name := range stringProps.Values {
if err := checkVariableName(name); err != nil {
return []error{fmt.Errorf("soong_config_string_variable: values property error %s", err)}
+ } else if _, ok := vals[name]; ok {
+ return []error{fmt.Errorf("soong_config_string_variable: values property error: duplicate value: %q", name)}
}
+ vals[name] = true
}
v.variables[base.variable] = &stringVariable{
@@ -235,7 +241,12 @@
// string vars, bool vars and value vars created by every
// soong_config_module_type in this build.
type Bp2BuildSoongConfigDefinitions struct {
- StringVars map[string]map[string]bool
+ // varCache contains a cache of string variables namespace + property
+ // The same variable may be used in multiple module types (for example, if need support
+ // for cc_default and java_default), only need to process once
+ varCache map[string]bool
+
+ StringVars map[string][]string
BoolVars map[string]bool
ValueVars map[string]bool
}
@@ -253,7 +264,7 @@
defer bp2buildSoongConfigVarsLock.Unlock()
if defs.StringVars == nil {
- defs.StringVars = make(map[string]map[string]bool)
+ defs.StringVars = make(map[string][]string)
}
if defs.BoolVars == nil {
defs.BoolVars = make(map[string]bool)
@@ -261,15 +272,24 @@
if defs.ValueVars == nil {
defs.ValueVars = make(map[string]bool)
}
+ if defs.varCache == nil {
+ defs.varCache = make(map[string]bool)
+ }
for _, moduleType := range mtDef.ModuleTypes {
for _, v := range moduleType.Variables {
key := strings.Join([]string{moduleType.ConfigNamespace, v.variableProperty()}, "__")
+
+ // The same variable may be used in multiple module types (for example, if need support
+ // for cc_default and java_default), only need to process once
+ if _, keyInCache := defs.varCache[key]; keyInCache {
+ continue
+ } else {
+ defs.varCache[key] = true
+ }
+
if strVar, ok := v.(*stringVariable); ok {
- if _, ok := defs.StringVars[key]; !ok {
- defs.StringVars[key] = make(map[string]bool, 0)
- }
for _, value := range strVar.values {
- defs.StringVars[key][value] = true
+ defs.StringVars[key] = append(defs.StringVars[key], value)
}
} else if _, ok := v.(*boolVariable); ok {
defs.BoolVars[key] = true
@@ -302,29 +322,16 @@
// String emits the Soong config variable definitions as Starlark dictionaries.
func (defs Bp2BuildSoongConfigDefinitions) String() string {
ret := ""
- ret += "soong_config_bool_variables = {\n"
- for _, boolVar := range sortedStringKeys(defs.BoolVars) {
- ret += fmt.Sprintf(" \"%s\": True,\n", boolVar)
- }
- ret += "}\n"
- ret += "\n"
+ ret += "soong_config_bool_variables = "
+ ret += starlark_fmt.PrintBoolDict(defs.BoolVars, 0)
+ ret += "\n\n"
- ret += "soong_config_value_variables = {\n"
- for _, valueVar := range sortedStringKeys(defs.ValueVars) {
- ret += fmt.Sprintf(" \"%s\": True,\n", valueVar)
- }
- ret += "}\n"
- ret += "\n"
+ ret += "soong_config_value_variables = "
+ ret += starlark_fmt.PrintBoolDict(defs.ValueVars, 0)
+ ret += "\n\n"
- ret += "soong_config_string_variables = {\n"
- for _, stringVar := range sortedStringKeys(defs.StringVars) {
- ret += fmt.Sprintf(" \"%s\": [\n", stringVar)
- for _, choice := range sortedStringKeys(defs.StringVars[stringVar]) {
- ret += fmt.Sprintf(" \"%s\",\n", choice)
- }
- ret += fmt.Sprintf(" ],\n")
- }
- ret += "}"
+ ret += "soong_config_string_variables = "
+ ret += starlark_fmt.PrintStringListDict(defs.StringVars, 0)
return ret
}
diff --git a/android/soongconfig/modules_test.go b/android/soongconfig/modules_test.go
index b14f8b4..a7800e8 100644
--- a/android/soongconfig/modules_test.go
+++ b/android/soongconfig/modules_test.go
@@ -367,19 +367,19 @@
func Test_Bp2BuildSoongConfigDefinitions(t *testing.T) {
testCases := []struct {
+ desc string
defs Bp2BuildSoongConfigDefinitions
expected string
}{
{
+ desc: "all empty",
defs: Bp2BuildSoongConfigDefinitions{},
- expected: `soong_config_bool_variables = {
-}
+ expected: `soong_config_bool_variables = {}
-soong_config_value_variables = {
-}
+soong_config_value_variables = {}
-soong_config_string_variables = {
-}`}, {
+soong_config_string_variables = {}`}, {
+ desc: "only bool",
defs: Bp2BuildSoongConfigDefinitions{
BoolVars: map[string]bool{
"bool_var": true,
@@ -389,39 +389,35 @@
"bool_var": True,
}
-soong_config_value_variables = {
-}
+soong_config_value_variables = {}
-soong_config_string_variables = {
-}`}, {
+soong_config_string_variables = {}`}, {
+ desc: "only value vars",
defs: Bp2BuildSoongConfigDefinitions{
ValueVars: map[string]bool{
"value_var": true,
},
},
- expected: `soong_config_bool_variables = {
-}
+ expected: `soong_config_bool_variables = {}
soong_config_value_variables = {
"value_var": True,
}
-soong_config_string_variables = {
-}`}, {
+soong_config_string_variables = {}`}, {
+ desc: "only string vars",
defs: Bp2BuildSoongConfigDefinitions{
- StringVars: map[string]map[string]bool{
- "string_var": map[string]bool{
- "choice1": true,
- "choice2": true,
- "choice3": true,
+ StringVars: map[string][]string{
+ "string_var": []string{
+ "choice1",
+ "choice2",
+ "choice3",
},
},
},
- expected: `soong_config_bool_variables = {
-}
+ expected: `soong_config_bool_variables = {}
-soong_config_value_variables = {
-}
+soong_config_value_variables = {}
soong_config_string_variables = {
"string_var": [
@@ -430,6 +426,7 @@
"choice3",
],
}`}, {
+ desc: "all vars",
defs: Bp2BuildSoongConfigDefinitions{
BoolVars: map[string]bool{
"bool_var_one": true,
@@ -438,15 +435,15 @@
"value_var_one": true,
"value_var_two": true,
},
- StringVars: map[string]map[string]bool{
- "string_var_one": map[string]bool{
- "choice1": true,
- "choice2": true,
- "choice3": true,
+ StringVars: map[string][]string{
+ "string_var_one": []string{
+ "choice1",
+ "choice2",
+ "choice3",
},
- "string_var_two": map[string]bool{
- "foo": true,
- "bar": true,
+ "string_var_two": []string{
+ "foo",
+ "bar",
},
},
},
@@ -466,15 +463,17 @@
"choice3",
],
"string_var_two": [
- "bar",
"foo",
+ "bar",
],
}`},
}
for _, test := range testCases {
- actual := test.defs.String()
- if actual != test.expected {
- t.Errorf("Expected:\n%s\nbut got:\n%s", test.expected, actual)
- }
+ t.Run(test.desc, func(t *testing.T) {
+ actual := test.defs.String()
+ if actual != test.expected {
+ t.Errorf("Expected:\n%s\nbut got:\n%s", test.expected, actual)
+ }
+ })
}
}
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index 6fac79d..295b0e5 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -68,6 +68,8 @@
"LOCAL_MODULE_PATH": prebuiltModulePath,
"LOCAL_REPLACE_PREBUILT_APK_INSTALLED": prebuiltPreprocessed,
+ "LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG": invert("auto_gen_config"),
+
// composite functions
"LOCAL_MODULE_TAGS": includeVariableIf(bpVariable{"tags", bpparser.ListType}, not(valueDumpEquals("optional"))),
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index 81b5c30..e8b6f78 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -1645,6 +1645,36 @@
}
`,
},
+ {
+ desc: "LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG is true",
+ in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := foo
+LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG := true
+include $(BUILD_PACKAGE)
+ `,
+ expected: `
+android_app {
+ name: "foo",
+ auto_gen_config: false,
+}
+`,
+ },
+ {
+ desc: "LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG is false",
+ in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := foo
+LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG := false
+include $(BUILD_PACKAGE)
+ `,
+ expected: `
+android_app {
+ name: "foo",
+ auto_gen_config: true,
+}
+`,
+ },
}
func TestEndToEnd(t *testing.T) {
diff --git a/apex/builder.go b/apex/builder.go
index 1a1f22b..fc4bf8a 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -398,18 +398,8 @@
}
func markManifestTestOnly(ctx android.ModuleContext, androidManifestFile android.Path) android.Path {
- return java.ManifestFixer(java.ManifestFixerParams{
- Ctx: ctx,
- Manifest: androidManifestFile,
- SdkContext: nil,
- ClassLoaderContexts: nil,
- IsLibrary: false,
- UseEmbeddedNativeLibs: false,
- UsesNonSdkApis: false,
- UseEmbeddedDex: false,
- HasNoCode: false,
- TestOnly: true,
- LoggingParent: "",
+ return java.ManifestFixer(ctx, androidManifestFile, java.ManifestFixerParams{
+ TestOnly: true,
})
}
@@ -618,6 +608,8 @@
implicitInputs = append(implicitInputs, androidManifestFile)
optFlags = append(optFlags, "--android_manifest "+androidManifestFile.String())
+ } else if a.testApex {
+ optFlags = append(optFlags, "--test_only")
}
// Determine target/min sdk version from the context
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index 4dc0e4c..5d00b0b 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -114,7 +114,7 @@
rootStaticArchives = []
linker_inputs = cc_info.linking_context.linker_inputs.to_list()
-static_info_tag = "//build/bazel/rules:cc_library_static.bzl%CcStaticLibraryInfo"
+static_info_tag = "//build/bazel/rules/cc:cc_library_static.bzl%CcStaticLibraryInfo"
if static_info_tag in providers(target):
static_info = providers(target)[static_info_tag]
ccObjectFiles = [f.path for f in static_info.objects]
@@ -149,7 +149,7 @@
rootSharedLibraries.append(path)
toc_file = ""
-toc_file_tag = "//build/bazel/rules:generate_toc.bzl%CcTocInfo"
+toc_file_tag = "//build/bazel/rules/cc:generate_toc.bzl%CcTocInfo"
if toc_file_tag in providers(target):
toc_file = providers(target)[toc_file_tag].toc.path
else:
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 4bcfa61..b904c35 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -28,6 +28,7 @@
"soong-genrule",
"soong-python",
"soong-sh",
+ "soong-starlark-format",
"soong-ui-metrics",
],
testSrcs: [
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index b3bec65..1d3b105 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -27,6 +27,7 @@
"android/soong/android"
"android/soong/bazel"
+ "android/soong/starlark_fmt"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -559,48 +560,27 @@
return "", nil
}
- var ret string
switch propertyValue.Kind() {
case reflect.String:
- ret = fmt.Sprintf("\"%v\"", escapeString(propertyValue.String()))
+ return fmt.Sprintf("\"%v\"", escapeString(propertyValue.String())), nil
case reflect.Bool:
- ret = strings.Title(fmt.Sprintf("%v", propertyValue.Interface()))
+ return starlark_fmt.PrintBool(propertyValue.Bool()), nil
case reflect.Int, reflect.Uint, reflect.Int64:
- ret = fmt.Sprintf("%v", propertyValue.Interface())
+ return fmt.Sprintf("%v", propertyValue.Interface()), nil
case reflect.Ptr:
return prettyPrint(propertyValue.Elem(), indent, emitZeroValues)
case reflect.Slice:
- if propertyValue.Len() == 0 {
- return "[]", nil
- }
-
- if propertyValue.Len() == 1 {
- // Single-line list for list with only 1 element
- ret += "["
- indexedValue, err := prettyPrint(propertyValue.Index(0), indent, emitZeroValues)
+ elements := make([]string, 0, propertyValue.Len())
+ for i := 0; i < propertyValue.Len(); i++ {
+ val, err := prettyPrint(propertyValue.Index(i), indent, emitZeroValues)
if err != nil {
return "", err
}
- ret += indexedValue
- ret += "]"
- } else {
- // otherwise, use a multiline list.
- ret += "[\n"
- for i := 0; i < propertyValue.Len(); i++ {
- indexedValue, err := prettyPrint(propertyValue.Index(i), indent+1, emitZeroValues)
- if err != nil {
- return "", err
- }
-
- if indexedValue != "" {
- ret += makeIndent(indent + 1)
- ret += indexedValue
- ret += ",\n"
- }
+ if val != "" {
+ elements = append(elements, val)
}
- ret += makeIndent(indent)
- ret += "]"
}
+ return starlark_fmt.PrintList(elements, indent, "%s"), nil
case reflect.Struct:
// Special cases where the bp2build sends additional information to the codegenerator
@@ -611,18 +591,12 @@
return fmt.Sprintf("%q", label.Label), nil
}
- ret = "{\n"
// Sort and print the struct props by the key.
structProps := extractStructProperties(propertyValue, indent)
if len(structProps) == 0 {
return "", nil
}
- for _, k := range android.SortedStringKeys(structProps) {
- ret += makeIndent(indent + 1)
- ret += fmt.Sprintf("%q: %s,\n", k, structProps[k])
- }
- ret += makeIndent(indent)
- ret += "}"
+ return starlark_fmt.PrintDict(structProps, indent), nil
case reflect.Interface:
// TODO(b/164227191): implement pretty print for interfaces.
// Interfaces are used for for arch, multilib and target properties.
@@ -631,7 +605,6 @@
return "", fmt.Errorf(
"unexpected kind for property struct field: %s", propertyValue.Kind())
}
- return ret, nil
}
// Converts a reflected property struct value into a map of property names and property values,
@@ -736,13 +709,6 @@
return strings.ReplaceAll(s, "\"", "\\\"")
}
-func makeIndent(indent int) string {
- if indent < 0 {
- panic(fmt.Errorf("indent column cannot be less than 0, but got %d", indent))
- }
- return strings.Repeat(" ", indent)
-}
-
func targetNameWithVariant(c bpToBuildContext, logicModule blueprint.Module) string {
name := ""
if c.ModuleSubDir(logicModule) != "" {
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index f9adc78..8d94079 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -459,7 +459,6 @@
name: "foo",
srcs: ["foo.proto"],
proto: {
- canonical_path_from_root: false,
},
include_build_directory: false,
}`,
@@ -483,7 +482,6 @@
srcs: ["foo.proto"],
static_executable: true,
proto: {
- canonical_path_from_root: false,
},
include_build_directory: false,
}`,
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 4c4953d..8fde655 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -1998,8 +1998,7 @@
}`,
expectedBazelTargets: []string{
makeBazelTarget("proto_library", "foo_proto", attrNameToString{
- "srcs": `["foo.proto"]`,
- "strip_import_prefix": `""`,
+ "srcs": `["foo.proto"]`,
}), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
"deps": `[":foo_proto"]`,
}), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
@@ -2024,7 +2023,8 @@
}`,
expectedBazelTargets: []string{
makeBazelTarget("proto_library", "foo_proto", attrNameToString{
- "srcs": `["foo.proto"]`,
+ "srcs": `["foo.proto"]`,
+ "strip_import_prefix": `""`,
}), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
"deps": `[":foo_proto"]`,
}), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
@@ -2049,8 +2049,7 @@
}`,
expectedBazelTargets: []string{
makeBazelTarget("proto_library", "foo_proto", attrNameToString{
- "srcs": `["foo.proto"]`,
- "strip_import_prefix": `""`,
+ "srcs": `["foo.proto"]`,
}), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
"deps": `[":foo_proto"]`,
}), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
@@ -2071,7 +2070,6 @@
name: "foo",
srcs: ["foo.proto"],
proto: {
- canonical_path_from_root: false,
type: "full",
},
include_build_directory: false,
@@ -2099,7 +2097,6 @@
name: "foo",
srcs: ["foo.proto"],
proto: {
- canonical_path_from_root: false,
type: "lite",
},
include_build_directory: false,
@@ -2127,7 +2124,6 @@
name: "foo",
srcs: ["foo.proto"],
proto: {
- canonical_path_from_root: false,
export_proto_headers: true,
},
include_build_directory: false,
@@ -2161,7 +2157,6 @@
name: "a",
srcs: [":a_fg_proto"],
proto: {
- canonical_path_from_root: false,
export_proto_headers: true,
},
include_build_directory: false,
@@ -2171,7 +2166,6 @@
name: "b",
srcs: [":b_protos"],
proto: {
- canonical_path_from_root: false,
export_proto_headers: true,
},
include_build_directory: false,
@@ -2181,7 +2175,6 @@
name: "c",
srcs: [":c-proto-srcs"],
proto: {
- canonical_path_from_root: false,
export_proto_headers: true,
},
include_build_directory: false,
@@ -2191,7 +2184,6 @@
name: "d",
srcs: [":proto-srcs-d"],
proto: {
- canonical_path_from_root: false,
export_proto_headers: true,
},
include_build_directory: false,
@@ -2437,3 +2429,18 @@
},
)
}
+
+func TestCcLibraryEscapeLdflags(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ blueprint: soongCcProtoPreamble + `cc_library {
+ name: "foo",
+ ldflags: ["-Wl,--rpath,${ORIGIN}"],
+ include_build_directory: false,
+}`,
+ expectedBazelTargets: makeCcLibraryTargets("foo", attrNameToString{
+ "linkopts": `["-Wl,--rpath,$${ORIGIN}"]`,
+ }),
+ })
+}
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index e8ba573..78192fe 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -431,7 +431,6 @@
name: "foo",
srcs: ["foo.proto"],
proto: {
- canonical_path_from_root: false,
export_proto_headers: true,
},
include_build_directory: false,
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index f1684c4..205bf4d 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -1436,7 +1436,6 @@
name: "foo",
srcs: ["foo.proto"],
proto: {
- canonical_path_from_root: false,
export_proto_headers: true,
},
include_build_directory: false,
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
index dfbb265..d37a523 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -6,6 +6,7 @@
"android/soong/android"
"android/soong/bazel"
+ "android/soong/starlark_fmt"
)
// Configurability support for bp2build.
@@ -250,10 +251,10 @@
} else if defaultValue != nil {
// Print an explicit empty list (the default value) even if the value is
// empty, to avoid errors about not finding a configuration that matches.
- ret += fmt.Sprintf("%s\"%s\": %s,\n", makeIndent(indent+1), bazel.ConditionsDefaultSelectKey, *defaultValue)
+ ret += fmt.Sprintf("%s\"%s\": %s,\n", starlark_fmt.Indention(indent+1), bazel.ConditionsDefaultSelectKey, *defaultValue)
}
- ret += makeIndent(indent)
+ ret += starlark_fmt.Indention(indent)
ret += "})"
return ret, nil
@@ -262,7 +263,7 @@
// prettyPrintSelectEntry converts a reflect.Value into an entry in a select map
// with a provided key.
func prettyPrintSelectEntry(value reflect.Value, key string, indent int, emitZeroValues bool) (string, error) {
- s := makeIndent(indent + 1)
+ s := starlark_fmt.Indention(indent + 1)
v, err := prettyPrint(value, indent+1, emitZeroValues)
if err != nil {
return "", err
diff --git a/bpf/bpf.go b/bpf/bpf.go
index a4999e5..14b2d84 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -20,7 +20,6 @@
"strings"
"android/soong/android"
- _ "android/soong/cc/config"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -74,7 +73,10 @@
Include_dirs []string
Sub_dir string
// If set to true, generate BTF debug info for maps & programs
- Btf *bool
+ Btf *bool
+ Vendor *bool
+
+ VendorInternal bool `blueprint:"mutated"`
}
type bpf struct {
@@ -85,6 +87,41 @@
objs android.Paths
}
+var _ android.ImageInterface = (*bpf)(nil)
+
+func (bpf *bpf) ImageMutatorBegin(ctx android.BaseModuleContext) {}
+
+func (bpf *bpf) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+ return !proptools.Bool(bpf.properties.Vendor)
+}
+
+func (bpf *bpf) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return false
+}
+
+func (bpf *bpf) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return false
+}
+
+func (bpf *bpf) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+ return false
+}
+
+func (bpf *bpf) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
+ return false
+}
+
+func (bpf *bpf) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+ if proptools.Bool(bpf.properties.Vendor) {
+ return []string{"vendor"}
+ }
+ return nil
+}
+
+func (bpf *bpf) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
+ bpf.properties.VendorInternal = variation == "vendor"
+}
+
func (bpf *bpf) GenerateAndroidBuildActions(ctx android.ModuleContext) {
cflags := []string{
"-nostdlibinc",
@@ -132,8 +169,8 @@
if proptools.Bool(bpf.properties.Btf) {
objStripped := android.ObjPathWithExt(ctx, "", src, "o")
ctx.Build(pctx, android.BuildParams{
- Rule: stripRule,
- Input: obj,
+ Rule: stripRule,
+ Input: obj,
Output: objStripped,
Args: map[string]string{
"stripCmd": "${config.ClangBin}/llvm-strip",
@@ -154,7 +191,12 @@
fmt.Fprintln(w)
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
fmt.Fprintln(w)
- localModulePath := "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf"
+ var localModulePath string
+ if bpf.properties.VendorInternal {
+ localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/bpf"
+ } else {
+ localModulePath = "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf"
+ }
if len(bpf.properties.Sub_dir) > 0 {
localModulePath += "/" + bpf.properties.Sub_dir
}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index b56d689..7154905 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -108,6 +108,9 @@
if len(c.Properties.AndroidMkHeaderLibs) > 0 {
entries.AddStrings("LOCAL_HEADER_LIBRARIES", c.Properties.AndroidMkHeaderLibs...)
}
+ if len(c.Properties.AndroidMkRuntimeLibs) > 0 {
+ entries.AddStrings("LOCAL_RUNTIME_LIBRARIES", c.Properties.AndroidMkRuntimeLibs...)
+ }
entries.SetString("LOCAL_SOONG_LINK_TYPE", c.makeLinkType)
if c.UseVndk() {
entries.SetBool("LOCAL_USE_VNDK", true)
diff --git a/cc/binary.go b/cc/binary.go
index 05923b1..54fd339 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -607,7 +607,7 @@
ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{
Rule_class: "cc_binary",
- Bzl_load_location: "//build/bazel/rules:cc_binary.bzl",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_binary.bzl",
},
android.CommonAttributes{Name: m.Name()},
attrs)
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 30c3c50..42fc0e4 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -644,7 +644,7 @@
var linkerFlags []string
if len(props.Ldflags) > 0 {
- linkerFlags = append(linkerFlags, props.Ldflags...)
+ linkerFlags = append(linkerFlags, proptools.NinjaEscapeList(props.Ldflags)...)
// binaries remove static flag if -shared is in the linker flags
if isBinary && android.InList("-shared", linkerFlags) {
axisFeatures = append(axisFeatures, "-static_flag")
diff --git a/cc/builder.go b/cc/builder.go
index a5e5406..8e6f7cd 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -203,25 +203,34 @@
"clangBin", "format")
// Rule for invoking clang-tidy (a clang-based linter).
+ clangTidyDep, clangTidyDepRE = pctx.RemoteStaticRules("clangTidyDep",
+ blueprint.RuleParams{
+ Depfile: "$out",
+ Deps: blueprint.DepsGCC,
+ Command: "${config.CcWrapper}$ccCmd $cFlags -E -o /dev/null $in " +
+ "-MQ $tidyFile -MD -MF $out",
+ CommandDeps: []string{"$ccCmd"},
+ },
+ &remoteexec.REParams{
+ Labels: map[string]string{"type": "lint", "tool": "clang-tidy", "lang": "cpp"},
+ ExecStrategy: "${config.REClangTidyExecStrategy}",
+ Inputs: []string{"$in"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REClangTidyPool}"},
+ }, []string{"ccCmd", "cFlags", "tidyFile"}, []string{})
+
clangTidy, clangTidyRE = pctx.RemoteStaticRules("clangTidy",
blueprint.RuleParams{
Depfile: "${out}.d",
Deps: blueprint.DepsGCC,
- // Pick bash because some machines with old /bin/sh cannot handle arrays.
- // All $cFlags and $tidyFlags should have single quotes escaped.
- // Assume no single quotes in other parameters like $in, $out, $ccCmd.
- Command: "/bin/bash -c 'SRCF=$in; TIDYF=$out; CLANGFLAGS=($cFlags); " +
- "rm -f $$TIDYF $${TIDYF}.d && " +
- "${config.CcWrapper}$ccCmd \"$${CLANGFLAGS[@]}\" -E -o /dev/null $$SRCF " +
- "-MQ $$TIDYF -MD -MF $${TIDYF}.d && " +
- "$tidyVars $reTemplate${config.ClangBin}/clang-tidy $tidyFlags $$SRCF " +
- "-- \"$${CLANGFLAGS[@]}\" && touch $$TIDYF'",
- CommandDeps: []string{"${config.ClangBin}/clang-tidy", "$ccCmd"},
+ Command: "cp ${out}.dep ${out}.d && " +
+ "$tidyVars$reTemplate${config.ClangBin}/clang-tidy $tidyFlags $in -- $cFlags && " +
+ "touch $out",
+ CommandDeps: []string{"${config.ClangBin}/clang-tidy"},
},
&remoteexec.REParams{
Labels: map[string]string{"type": "lint", "tool": "clang-tidy", "lang": "cpp"},
ExecStrategy: "${config.REClangTidyExecStrategy}",
- Inputs: []string{"$in"},
+ Inputs: []string{"$in", "${out}.dep"},
EnvironmentVariables: []string{"TIDY_TIMEOUT"},
// Although clang-tidy has an option to "fix" source files, that feature is hardly useable
// under parallel compilation and RBE. So we assume no OutputFiles here.
@@ -230,7 +239,7 @@
// (1) New timestamps trigger clang and clang-tidy compilations again.
// (2) Changing source files caused concurrent clang or clang-tidy jobs to crash.
Platform: map[string]string{remoteexec.PoolKey: "${config.REClangTidyPool}"},
- }, []string{"ccCmd", "cFlags", "tidyFlags", "tidyVars"}, []string{})
+ }, []string{"cFlags", "tidyFlags", "tidyVars"}, []string{})
_ = pctx.SourcePathVariable("yasmCmd", "prebuilts/misc/${config.HostPrebuiltTag}/yasm/yasm")
@@ -449,28 +458,22 @@
}
}
-func escapeSingleQuotes(s string) string {
- // Replace single quotes to work when embedded in a single quoted string for bash.
- // Relying on string concatenation of bash to get A'B from quoted 'A'\''B'.
- return strings.Replace(s, `'`, `'\''`, -1)
-}
-
// Generate rules for compiling multiple .c, .cpp, or .S files to individual .o files
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
- noTidySrcsMap := make(map[android.Path]bool)
+ noTidySrcsMap := make(map[string]bool)
var tidyVars string
if flags.tidy {
tidyFiles = make(android.Paths, 0, len(srcFiles))
for _, path := range noTidySrcs {
- noTidySrcsMap[path] = true
+ noTidySrcsMap[path.String()] = true
}
tidyTimeout := ctx.Config().Getenv("TIDY_TIMEOUT")
if len(tidyTimeout) > 0 {
- tidyVars += "TIDY_TIMEOUT=" + tidyTimeout
+ tidyVars += "TIDY_TIMEOUT=" + tidyTimeout + " "
}
}
var coverageFiles android.Paths
@@ -672,26 +675,46 @@
}
// Even with tidy, some src file could be skipped by noTidySrcsMap.
- if tidy && !noTidySrcsMap[srcFile] {
+ if tidy && !noTidySrcsMap[srcFile.String()] {
tidyFile := android.ObjPathWithExt(ctx, subdir, srcFile, "tidy")
+ tidyDepFile := android.ObjPathWithExt(ctx, subdir, srcFile, "tidy.dep")
tidyFiles = append(tidyFiles, tidyFile)
+ ruleDep := clangTidyDep
rule := clangTidy
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_CLANG_TIDY") {
+ ruleDep = clangTidyDepRE
rule = clangTidyRE
}
+ sharedCFlags := shareFlags("cFlags", moduleFlags)
+ srcRelPath := srcFile.Rel()
+
+ // Add the .tidy.d rule
ctx.Build(pctx, android.BuildParams{
- Rule: rule,
- Description: "clang-tidy " + srcFile.Rel(),
- Output: tidyFile,
+ Rule: ruleDep,
+ Description: "clang-tidy-dep " + srcRelPath,
+ Output: tidyDepFile,
Input: srcFile,
Implicits: cFlagsDeps,
OrderOnly: pathDeps,
Args: map[string]string{
- "ccCmd": ccCmd,
- "cFlags": shareFlags("cFlags", escapeSingleQuotes(moduleToolingFlags)),
- "tidyFlags": shareFlags("tidyFlags", escapeSingleQuotes(config.TidyFlagsForSrcFile(srcFile, flags.tidyFlags))),
+ "ccCmd": ccCmd,
+ "cFlags": sharedCFlags,
+ "tidyFile": tidyFile.String(),
+ },
+ })
+ // Add the .tidy rule with order only dependency on the .tidy.d file
+ ctx.Build(pctx, android.BuildParams{
+ Rule: rule,
+ Description: "clang-tidy " + srcRelPath,
+ Output: tidyFile,
+ Input: srcFile,
+ Implicits: cFlagsDeps,
+ OrderOnly: append(android.Paths{}, tidyDepFile),
+ Args: map[string]string{
+ "cFlags": sharedCFlags,
+ "tidyFlags": shareFlags("tidyFlags", config.TidyFlagsForSrcFile(srcFile, flags.tidyFlags)),
"tidyVars": tidyVars, // short and not shared
},
})
diff --git a/cc/cc.go b/cc/cc.go
index 2a84f55..019b1f2 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -505,6 +505,7 @@
selectedStl() string
baseModuleName() string
getVndkExtendsModuleName() string
+ isAfdoCompile() bool
isPgoCompile() bool
isNDKStubLibrary() bool
useClangLld(actx ModuleContext) bool
@@ -1259,6 +1260,13 @@
return false
}
+func (c *Module) isAfdoCompile() bool {
+ if afdo := c.afdo; afdo != nil {
+ return afdo.Properties.AfdoTarget != nil
+ }
+ return false
+}
+
func (c *Module) isPgoCompile() bool {
if pgo := c.pgo; pgo != nil {
return pgo.Properties.PgoCompile
@@ -1536,6 +1544,10 @@
return ctx.mod.IsVndk()
}
+func (ctx *moduleContextImpl) isAfdoCompile() bool {
+ return ctx.mod.isAfdoCompile()
+}
+
func (ctx *moduleContextImpl) isPgoCompile() bool {
return ctx.mod.isPgoCompile()
}
diff --git a/cc/config/Android.bp b/cc/config/Android.bp
index 7b7ee28..e1b0605 100644
--- a/cc/config/Android.bp
+++ b/cc/config/Android.bp
@@ -8,6 +8,7 @@
deps: [
"soong-android",
"soong-remoteexec",
+ "soong-starlark-format",
],
srcs: [
"bp2build.go",
diff --git a/cc/config/bp2build.go b/cc/config/bp2build.go
index 982b436..eca5161 100644
--- a/cc/config/bp2build.go
+++ b/cc/config/bp2build.go
@@ -22,14 +22,11 @@
"strings"
"android/soong/android"
+ "android/soong/starlark_fmt"
"github.com/google/blueprint"
)
-const (
- bazelIndent = 4
-)
-
type bazelVarExporter interface {
asBazel(android.Config, exportedStringVariables, exportedStringListVariables, exportedConfigDependingVariables) []bazelConstant
}
@@ -73,21 +70,6 @@
m[k] = v
}
-func bazelIndention(level int) string {
- return strings.Repeat(" ", level*bazelIndent)
-}
-
-func printBazelList(items []string, indentLevel int) string {
- list := make([]string, 0, len(items)+2)
- list = append(list, "[")
- innerIndent := bazelIndention(indentLevel + 1)
- for _, item := range items {
- list = append(list, fmt.Sprintf(`%s"%s",`, innerIndent, item))
- }
- list = append(list, bazelIndention(indentLevel)+"]")
- return strings.Join(list, "\n")
-}
-
func (m exportedStringVariables) asBazel(config android.Config,
stringVars exportedStringVariables, stringListVars exportedStringListVariables, cfgDepVars exportedConfigDependingVariables) []bazelConstant {
ret := make([]bazelConstant, 0, len(m))
@@ -139,7 +121,7 @@
// out through a constants struct later.
ret = append(ret, bazelConstant{
variableName: k,
- internalDefinition: printBazelList(expandedVars, 0),
+ internalDefinition: starlark_fmt.PrintStringList(expandedVars, 0),
})
}
return ret
@@ -173,17 +155,6 @@
m[k] = v
}
-func printBazelStringListDict(dict map[string][]string) string {
- bazelDict := make([]string, 0, len(dict)+2)
- bazelDict = append(bazelDict, "{")
- for k, v := range dict {
- bazelDict = append(bazelDict,
- fmt.Sprintf(`%s"%s": %s,`, bazelIndention(1), k, printBazelList(v, 1)))
- }
- bazelDict = append(bazelDict, "}")
- return strings.Join(bazelDict, "\n")
-}
-
// Since dictionaries are not supported in Ninja, we do not expand variables for dictionaries
func (m exportedStringListDictVariables) asBazel(_ android.Config, _ exportedStringVariables,
_ exportedStringListVariables, _ exportedConfigDependingVariables) []bazelConstant {
@@ -191,7 +162,7 @@
for k, dict := range m {
ret = append(ret, bazelConstant{
variableName: k,
- internalDefinition: printBazelStringListDict(dict),
+ internalDefinition: starlark_fmt.PrintStringListDict(dict, 0),
})
}
return ret
@@ -223,7 +194,7 @@
definitions = append(definitions,
fmt.Sprintf("_%s = %s", b.variableName, b.internalDefinition))
constants = append(constants,
- fmt.Sprintf("%[1]s%[2]s = _%[2]s,", bazelIndention(1), b.variableName))
+ fmt.Sprintf("%[1]s%[2]s = _%[2]s,", starlark_fmt.Indention(1), b.variableName))
}
// Build the exported constants struct.
diff --git a/cc/config/bp2build_test.go b/cc/config/bp2build_test.go
index 3118df1..4cbf0c6 100644
--- a/cc/config/bp2build_test.go
+++ b/cc/config/bp2build_test.go
@@ -211,15 +211,11 @@
expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
_a = {
- "b1": [
- "b2",
- ],
+ "b1": ["b2"],
}
_c = {
- "d1": [
- "d2",
- ],
+ "d1": ["d2"],
}
constants = struct(
@@ -246,27 +242,19 @@
expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
_a = {
- "a1": [
- "a2",
- ],
+ "a1": ["a2"],
}
_b = "b-val"
-_c = [
- "c-val",
-]
+_c = ["c-val"]
_d = "d-val"
-_e = [
- "e-val",
-]
+_e = ["e-val"]
_f = {
- "f1": [
- "f2",
- ],
+ "f1": ["f2"],
}
constants = struct(
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index 00f07ff..d789cde 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -15,6 +15,7 @@
package config
import (
+ "fmt"
"strings"
"android/soong/android"
@@ -190,6 +191,11 @@
}
func x86_64ToolchainFactory(arch android.Arch) Toolchain {
+ // Error now rather than having a confusing Ninja error
+ if _, ok := x86_64ArchVariantCflags[arch.ArchVariant]; !ok {
+ panic(fmt.Sprintf("Unknown x86_64 architecture version: %q", arch.ArchVariant))
+ }
+
toolchainCflags := []string{
"${config.X86_64ToolchainCflags}",
"${config.X86_64" + arch.ArchVariant + "VariantCflags}",
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index 29f0593..e32e1bd 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -15,6 +15,7 @@
package config
import (
+ "fmt"
"strings"
"android/soong/android"
@@ -186,6 +187,11 @@
}
func x86ToolchainFactory(arch android.Arch) Toolchain {
+ // Error now rather than having a confusing Ninja error
+ if _, ok := x86ArchVariantCflags[arch.ArchVariant]; !ok {
+ panic(fmt.Sprintf("Unknown x86 architecture version: %q", arch.ArchVariant))
+ }
+
toolchainCflags := []string{
"${config.X86ToolchainCflags}",
"${config.X86" + arch.ArchVariant + "VariantCflags}",
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 43333fa..60f03c2 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -194,10 +194,6 @@
return ""
}
-func (t *toolchainLinuxX86) ClangTriple() string {
- return "i686-linux-gnu"
-}
-
func (t *toolchainLinuxX86) Cflags() string {
return "${config.LinuxCflags} ${config.LinuxX86Cflags}"
}
@@ -206,10 +202,6 @@
return ""
}
-func (t *toolchainLinuxX8664) ClangTriple() string {
- return "x86_64-linux-gnu"
-}
-
func (t *toolchainLinuxX8664) Cflags() string {
return "${config.LinuxCflags} ${config.LinuxX8664Cflags}"
}
@@ -283,6 +275,10 @@
toolchainGlibc
}
+func (t *toolchainLinuxGlibcX86) ClangTriple() string {
+ return "i686-linux-gnu"
+}
+
func (t *toolchainLinuxGlibcX86) Cflags() string {
return t.toolchainLinuxX86.Cflags() + " " + t.toolchainGlibc.Cflags()
}
@@ -295,6 +291,10 @@
return t.toolchainLinuxX86.Lldflags() + " " + t.toolchainGlibc.Lldflags()
}
+func (t *toolchainLinuxGlibcX8664) ClangTriple() string {
+ return "x86_64-linux-gnu"
+}
+
func (t *toolchainLinuxGlibcX8664) Cflags() string {
return t.toolchainLinuxX8664.Cflags() + " " + t.toolchainGlibc.Cflags()
}
@@ -356,6 +356,10 @@
toolchainMusl
}
+func (t *toolchainLinuxMuslX86) ClangTriple() string {
+ return "i686-linux-musl"
+}
+
func (t *toolchainLinuxMuslX86) Cflags() string {
return t.toolchainLinuxX86.Cflags() + " " + t.toolchainMusl.Cflags()
}
@@ -368,6 +372,10 @@
return t.toolchainLinuxX86.Lldflags() + " " + t.toolchainMusl.Lldflags()
}
+func (t *toolchainLinuxMuslX8664) ClangTriple() string {
+ return "x86_64-linux-musl"
+}
+
func (t *toolchainLinuxMuslX8664) Cflags() string {
return t.toolchainLinuxX8664.Cflags() + " " + t.toolchainMusl.Cflags()
}
diff --git a/cc/library.go b/cc/library.go
index 5d40820..708aa10 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -32,7 +32,7 @@
"github.com/google/blueprint/pathtools"
)
-// LibraryProperties is a collection of properties shared by cc library rules.
+// LibraryProperties is a collection of properties shared by cc library rules/cc.
type LibraryProperties struct {
// local file name to pass to the linker as -unexported_symbols_list
Unexported_symbols_list *string `android:"path,arch_variant"`
@@ -403,11 +403,11 @@
staticProps := bazel.BazelTargetModuleProperties{
Rule_class: "cc_library_static",
- Bzl_load_location: "//build/bazel/rules:cc_library_static.bzl",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_library_static.bzl",
}
sharedProps := bazel.BazelTargetModuleProperties{
Rule_class: "cc_library_shared",
- Bzl_load_location: "//build/bazel/rules:cc_library_shared.bzl",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_library_shared.bzl",
}
ctx.CreateBazelTargetModuleWithRestrictions(staticProps,
@@ -2552,7 +2552,7 @@
}
props := bazel.BazelTargetModuleProperties{
Rule_class: modType,
- Bzl_load_location: fmt.Sprintf("//build/bazel/rules:%s.bzl", modType),
+ Bzl_load_location: fmt.Sprintf("//build/bazel/rules/cc:%s.bzl", modType),
}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
diff --git a/cc/library_headers.go b/cc/library_headers.go
index 064e2b8..5d38fba 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -136,7 +136,7 @@
props := bazel.BazelTargetModuleProperties{
Rule_class: "cc_library_headers",
- Bzl_load_location: "//build/bazel/rules:cc_library_headers.bzl",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_library_headers.bzl",
}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
diff --git a/cc/lto.go b/cc/lto.go
index 6d55579..2c274bd 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -123,7 +123,7 @@
// If the module does not have a profile, be conservative and limit cross TU inline
// limit to 5 LLVM IR instructions, to balance binary size increase and performance.
- if !ctx.isPgoCompile() {
+ if !ctx.isPgoCompile() && !ctx.isAfdoCompile() {
flags.Local.LdFlags = append(flags.Local.LdFlags,
"-Wl,-plugin-opt,-import-instr-limit=5")
}
diff --git a/cc/object.go b/cc/object.go
index 24f6ed4..fdd0b11 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -195,7 +195,7 @@
props := bazel.BazelTargetModuleProperties{
Rule_class: "cc_object",
- Bzl_load_location: "//build/bazel/rules:cc_object.bzl",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_object.bzl",
}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index c928ed9..339a16d 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -339,7 +339,7 @@
props := bazel.BazelTargetModuleProperties{
Rule_class: "prebuilt_library_static",
- Bzl_load_location: "//build/bazel/rules:prebuilt_library_static.bzl",
+ Bzl_load_location: "//build/bazel/rules/cc:prebuilt_library_static.bzl",
}
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
@@ -359,7 +359,7 @@
props := bazel.BazelTargetModuleProperties{
Rule_class: "prebuilt_library_shared",
- Bzl_load_location: "//build/bazel/rules:prebuilt_library_shared.bzl",
+ Bzl_load_location: "//build/bazel/rules/cc:prebuilt_library_shared.bzl",
}
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
diff --git a/cc/proto.go b/cc/proto.go
index f3410bc..3cf1453 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -210,7 +210,7 @@
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: rule_class,
- Bzl_load_location: "//build/bazel/rules:cc_proto.bzl",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_proto.bzl",
},
android.CommonAttributes{Name: name},
&protoAttrs)
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index 0577c86..7cb8ab7 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -407,10 +407,10 @@
s.Finish()
- if failures == 1 {
+ if failures.count == 1 {
log.Fatal("1 failure")
- } else if failures > 1 {
- log.Fatalf("%d failures", failures)
+ } else if failures.count > 1 {
+ log.Fatalf("%d failures %q", failures.count, failures.fails)
} else {
fmt.Fprintln(output, "Success")
}
@@ -522,19 +522,23 @@
})
}
-type failureCount int
+type failureCount struct {
+ count int
+ fails []string
+}
func (f *failureCount) StartAction(action *status.Action, counts status.Counts) {}
func (f *failureCount) FinishAction(result status.ActionResult, counts status.Counts) {
if result.Error != nil {
- *f += 1
+ f.count += 1
+ f.fails = append(f.fails, result.Action.Description)
}
}
func (f *failureCount) Message(level status.MsgLevel, message string) {
if level >= status.ErrorLvl {
- *f += 1
+ f.count += 1
}
}
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index d80051c..a0cfbea 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -205,14 +205,7 @@
buildCtx.Verbosef("Parallelism (local/remote/highmem): %v/%v/%v",
config.Parallel(), config.RemoteParallel(), config.HighmemParallel())
- {
- var limits syscall.Rlimit
- err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limits)
- if err != nil {
- buildCtx.Verbosef("Failed to get file limit:", err)
- }
- buildCtx.Verbosef("Current file limits: %d soft, %d hard", limits.Cur, limits.Max)
- }
+ setMaxFiles(buildCtx)
{
// The order of the function calls is important. The last defer function call
@@ -614,3 +607,24 @@
}
}
}
+
+func setMaxFiles(ctx build.Context) {
+ var limits syscall.Rlimit
+
+ err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limits)
+ if err != nil {
+ ctx.Println("Failed to get file limit:", err)
+ return
+ }
+
+ ctx.Verbosef("Current file limits: %d soft, %d hard", limits.Cur, limits.Max)
+ if limits.Cur == limits.Max {
+ return
+ }
+
+ limits.Cur = limits.Max
+ err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &limits)
+ if err != nil {
+ ctx.Println("Failed to increase file limit:", err)
+ }
+}
diff --git a/example_config.json b/example_config.json
new file mode 100644
index 0000000..7489840
--- /dev/null
+++ b/example_config.json
@@ -0,0 +1,6 @@
+{
+ "env": {
+ "ENV_VAR_1": "Value1",
+ "ENV_VAR_2": "Value2"
+ }
+}
diff --git a/java/aar.go b/java/aar.go
index 51aad8d..8e10253 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -280,9 +280,7 @@
manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
- manifestPath := ManifestFixer(ManifestFixerParams{
- Ctx: ctx,
- Manifest: manifestSrcPath,
+ manifestPath := ManifestFixer(ctx, manifestSrcPath, ManifestFixerParams{
SdkContext: sdkContext,
ClassLoaderContexts: classLoaderContexts,
IsLibrary: a.isLibrary,
@@ -290,7 +288,6 @@
UsesNonSdkApis: a.usesNonSdkApis,
UseEmbeddedDex: a.useEmbeddedDex,
HasNoCode: a.hasNoCode,
- TestOnly: false,
LoggingParent: a.LoggingParent,
})
diff --git a/java/android_manifest.go b/java/android_manifest.go
index a5d5b97..7772b70 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -56,8 +56,6 @@
}
type ManifestFixerParams struct {
- Ctx android.ModuleContext
- Manifest android.Path
SdkContext android.SdkContext
ClassLoaderContexts dexpreopt.ClassLoaderContextMap
IsLibrary bool
@@ -70,20 +68,21 @@
}
// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
-func ManifestFixer(params ManifestFixerParams) android.Path {
+func ManifestFixer(ctx android.ModuleContext, manifest android.Path,
+ params ManifestFixerParams) android.Path {
var args []string
if params.IsLibrary {
args = append(args, "--library")
} else if params.SdkContext != nil {
- minSdkVersion, err := params.SdkContext.MinSdkVersion(params.Ctx).EffectiveVersion(params.Ctx)
+ minSdkVersion, err := params.SdkContext.MinSdkVersion(ctx).EffectiveVersion(ctx)
if err != nil {
- params.Ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
+ ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
}
if minSdkVersion.FinalOrFutureInt() >= 23 {
args = append(args, fmt.Sprintf("--extract-native-libs=%v", !params.UseEmbeddedNativeLibs))
} else if params.UseEmbeddedNativeLibs {
- params.Ctx.ModuleErrorf("module attempted to store uncompressed native libraries, but minSdkVersion=%d doesn't support it",
+ ctx.ModuleErrorf("module attempted to store uncompressed native libraries, but minSdkVersion=%d doesn't support it",
minSdkVersion)
}
}
@@ -124,38 +123,38 @@
var argsMapper = make(map[string]string)
if params.SdkContext != nil {
- targetSdkVersion := targetSdkVersionForManifestFixer(params.Ctx, params.SdkContext)
+ targetSdkVersion := targetSdkVersionForManifestFixer(ctx, params.SdkContext)
args = append(args, "--targetSdkVersion ", targetSdkVersion)
- if UseApiFingerprint(params.Ctx) && params.Ctx.ModuleName() != "framework-res" {
- targetSdkVersion = params.Ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(params.Ctx).String())
- deps = append(deps, ApiFingerprintPath(params.Ctx))
+ if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
+ targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
+ deps = append(deps, ApiFingerprintPath(ctx))
}
- minSdkVersion, err := params.SdkContext.MinSdkVersion(params.Ctx).EffectiveVersionString(params.Ctx)
+ minSdkVersion, err := params.SdkContext.MinSdkVersion(ctx).EffectiveVersionString(ctx)
if err != nil {
- params.Ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
+ ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
}
- if UseApiFingerprint(params.Ctx) && params.Ctx.ModuleName() != "framework-res" {
- minSdkVersion = params.Ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(params.Ctx).String())
- deps = append(deps, ApiFingerprintPath(params.Ctx))
+ if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
+ minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
+ deps = append(deps, ApiFingerprintPath(ctx))
}
if err != nil {
- params.Ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
+ ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
}
args = append(args, "--minSdkVersion ", minSdkVersion)
args = append(args, "--raise-min-sdk-version")
}
- fixedManifest := android.PathForModuleOut(params.Ctx, "manifest_fixer", "AndroidManifest.xml")
+ fixedManifest := android.PathForModuleOut(ctx, "manifest_fixer", "AndroidManifest.xml")
argsMapper["args"] = strings.Join(args, " ")
- params.Ctx.Build(pctx, android.BuildParams{
+ ctx.Build(pctx, android.BuildParams{
Rule: manifestFixerRule,
Description: "fix manifest",
- Input: params.Manifest,
+ Input: manifest,
Implicits: deps,
Output: fixedManifest,
Args: argsMapper,
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index a36bd6a..5fe409e 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -931,13 +931,13 @@
All_flags_path android.OptionalPath `supported_build_releases:"S"`
// The path to the generated signature-patterns.csv file.
- Signature_patterns_path android.OptionalPath `supported_build_releases:"T+"`
+ Signature_patterns_path android.OptionalPath `supported_build_releases:"Tiramisu+"`
// The path to the generated filtered-stub-flags.csv file.
- Filtered_stub_flags_path android.OptionalPath `supported_build_releases:"T+"`
+ Filtered_stub_flags_path android.OptionalPath `supported_build_releases:"Tiramisu+"`
// The path to the generated filtered-flags.csv file.
- Filtered_flags_path android.OptionalPath `supported_build_releases:"T+"`
+ Filtered_flags_path android.OptionalPath `supported_build_releases:"Tiramisu+"`
}
func (b *bootclasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
diff --git a/java/proto.go b/java/proto.go
index ab913d8..8d23803 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -73,13 +73,15 @@
}
func protoDeps(ctx android.BottomUpMutatorContext, p *android.ProtoProperties) {
+ const unspecifiedProtobufPluginType = ""
if String(p.Proto.Plugin) == "" {
switch String(p.Proto.Type) {
+ case "stream": // does not require additional dependencies
case "micro":
ctx.AddVariationDependencies(nil, staticLibTag, "libprotobuf-java-micro")
case "nano":
ctx.AddVariationDependencies(nil, staticLibTag, "libprotobuf-java-nano")
- case "lite", "":
+ case "lite", unspecifiedProtobufPluginType:
ctx.AddVariationDependencies(nil, staticLibTag, "libprotobuf-java-lite")
case "full":
if ctx.Host() || ctx.BazelConversionMode() {
diff --git a/java/proto_test.go b/java/proto_test.go
new file mode 100644
index 0000000..d1cb714
--- /dev/null
+++ b/java/proto_test.go
@@ -0,0 +1,53 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+ "strings"
+ "testing"
+
+ "android/soong/android"
+)
+
+const protoModules = `
+java_library_static {
+ name: "libprotobuf-java-lite",
+}
+`
+
+func TestProtoStream(t *testing.T) {
+ bp := `
+ java_library {
+ name: "java-stream-protos",
+ proto: {
+ type: "stream",
+ },
+ srcs: [
+ "a.proto",
+ "b.proto",
+ ],
+ }
+ `
+
+ ctx := android.GroupFixturePreparers(
+ PrepareForIntegrationTestWithJava,
+ ).RunTestWithBp(t, protoModules+bp)
+
+ proto0 := ctx.ModuleForTests("java-stream-protos", "android_common").Output("proto/proto0.srcjar")
+
+ if cmd := proto0.RuleParams.Command; !strings.Contains(cmd, "--javastream_out=") {
+ t.Errorf("expected '--javastream_out' in %q", cmd)
+ }
+}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 6a2a7a8..e794a48 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -21,7 +21,6 @@
"reflect"
"regexp"
"sort"
- "strconv"
"strings"
"sync"
@@ -2551,8 +2550,14 @@
ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"), err.Error())
return ""
}
- intStr := strconv.Itoa(apiLevel.FinalOrPreviewInt())
- return formattedOptionalAttribute(attrName, &intStr)
+ if apiLevel.IsCurrent() {
+ // passing "current" would always mean a future release, never the current (or the current in
+ // progress) which means some conditions would never be triggered.
+ ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"),
+ `"current" is not an allowed value for this attribute`)
+ return ""
+ }
+ return formattedOptionalAttribute(attrName, value)
}
// formats an attribute for the xml permissions file if the value is not null
@@ -2808,7 +2813,7 @@
StubsSrcJar android.Path
CurrentApiFile android.Path
RemovedApiFile android.Path
- AnnotationsZip android.Path `supported_build_releases:"T+"`
+ AnnotationsZip android.Path `supported_build_releases:"Tiramisu+"`
SdkVersion string
}
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index e0e5b56..3500c84 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -182,7 +182,7 @@
"30": {"foo", "fooUpdatable", "fooUpdatableErr"},
}),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.Platform_version_active_codenames = []string{"Tiramisu", "U", "V", "W"}
+ variables.Platform_version_active_codenames = []string{"Tiramisu", "U", "V", "W", "X"}
}),
).RunTestWithBp(t,
`
@@ -193,7 +193,7 @@
on_bootclasspath_since: "U",
on_bootclasspath_before: "V",
min_device_sdk: "W",
- max_device_sdk: "current",
+ max_device_sdk: "X",
min_sdk_version: "S",
}
java_sdk_library {
@@ -202,12 +202,13 @@
api_packages: ["foo"],
}
`)
+
// test that updatability attributes are passed on correctly
fooUpdatable := result.ModuleForTests("fooUpdatable.xml", "android_common").Rule("java_sdk_xml")
- android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `on-bootclasspath-since=\"9001\"`)
- android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `on-bootclasspath-before=\"9002\"`)
- android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `min-device-sdk=\"9003\"`)
- android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `max-device-sdk=\"10000\"`)
+ android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `on-bootclasspath-since=\"U\"`)
+ android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `on-bootclasspath-before=\"V\"`)
+ android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `min-device-sdk=\"W\"`)
+ android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `max-device-sdk=\"X\"`)
// double check that updatability attributes are not written if they don't exist in the bp file
// the permissions file for the foo library defined above
@@ -230,7 +231,7 @@
`on_bootclasspath_since: "aaa" could not be parsed as an integer and is not a recognized codename`,
`on_bootclasspath_before: "bbc" could not be parsed as an integer and is not a recognized codename`,
`min_device_sdk: "ccc" could not be parsed as an integer and is not a recognized codename`,
- `max_device_sdk: "ddd" could not be parsed as an integer and is not a recognized codename`,
+ `max_device_sdk: "current" is not an allowed value for this attribute`,
})).RunTestWithBp(t,
`
java_sdk_library {
@@ -240,7 +241,7 @@
on_bootclasspath_since: "aaa",
on_bootclasspath_before: "bbc",
min_device_sdk: "ccc",
- max_device_sdk: "ddd",
+ max_device_sdk: "current",
}
`)
}
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index b8fe162..cb50a50 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -1092,7 +1092,7 @@
// Given an if statement's directive and the left/right starlarkExprs,
// check if the starlarkExprs are one of a few hardcoded special cases
-// that can be converted to a simpler equalify expression than simply comparing
+// that can be converted to a simpler equality expression than simply comparing
// the two.
func (ctx *parseContext) parseCompareSpecialCases(directive *mkparser.Directive, left starlarkExpr,
right starlarkExpr) (starlarkExpr, bool) {
@@ -1121,8 +1121,8 @@
}
switch call.name {
- case baseName + ".filter", baseName + ".filter-out":
- return ctx.parseCompareFilterFuncResult(directive, call, value, isEq), true
+ case baseName + ".filter":
+ return ctx.parseCompareFilterFuncResult(directive, call, value, isEq)
case baseName + ".expand_wildcard":
return ctx.parseCompareWildcardFuncResult(directive, call, value, !isEq), true
case baseName + ".findstring":
@@ -1134,68 +1134,39 @@
}
func (ctx *parseContext) parseCompareFilterFuncResult(cond *mkparser.Directive,
- filterFuncCall *callExpr, xValue starlarkExpr, negate bool) starlarkExpr {
+ filterFuncCall *callExpr, xValue starlarkExpr, negate bool) (starlarkExpr, bool) {
// We handle:
// * ifeq/ifneq (,$(filter v1 v2 ..., EXPR) becomes if EXPR not in/in ["v1", "v2", ...]
// * ifeq/ifneq (,$(filter EXPR, v1 v2 ...) becomes if EXPR not in/in ["v1", "v2", ...]
- // * ifeq/ifneq ($(VAR),$(filter $(VAR), v1 v2 ...) becomes if VAR in/not in ["v1", "v2"]
- // TODO(Asmundak): check the last case works for filter-out, too.
+ if x, ok := xValue.(*stringLiteralExpr); !ok || x.literal != "" {
+ return nil, false
+ }
xPattern := filterFuncCall.args[0]
xText := filterFuncCall.args[1]
var xInList *stringLiteralExpr
var expr starlarkExpr
var ok bool
- switch x := xValue.(type) {
- case *stringLiteralExpr:
- if x.literal != "" {
- return ctx.newBadExpr(cond, "filter comparison to non-empty value: %s", xValue)
- }
- // Either pattern or text should be const, and the
- // non-const one should be varRefExpr
- if xInList, ok = xPattern.(*stringLiteralExpr); ok && !strings.ContainsRune(xInList.literal, '%') && xText.typ() == starlarkTypeList {
- expr = xText
- } else if xInList, ok = xText.(*stringLiteralExpr); ok {
- expr = xPattern
- } else {
- expr = &callExpr{
- object: nil,
- name: filterFuncCall.name,
- args: filterFuncCall.args,
- returnType: starlarkTypeBool,
- }
- if negate {
- expr = ¬Expr{expr: expr}
- }
- return expr
- }
- case *variableRefExpr:
- if v, ok := xPattern.(*variableRefExpr); ok {
- if xInList, ok = xText.(*stringLiteralExpr); ok && v.ref.name() == x.ref.name() {
- // ifeq/ifneq ($(VAR),$(filter $(VAR), v1 v2 ...), flip negate,
- // it's the opposite to what is done when comparing to empty.
- expr = xPattern
- negate = !negate
- }
- }
+ if xInList, ok = xPattern.(*stringLiteralExpr); ok && !strings.ContainsRune(xInList.literal, '%') && xText.typ() == starlarkTypeList {
+ expr = xText
+ } else if xInList, ok = xText.(*stringLiteralExpr); ok {
+ expr = xPattern
+ } else {
+ return nil, false
}
- if expr != nil && xInList != nil {
- slExpr := newStringListExpr(strings.Fields(xInList.literal))
- // Generate simpler code for the common cases:
- if expr.typ() == starlarkTypeList {
- if len(slExpr.items) == 1 {
- // Checking that a string belongs to list
- return &inExpr{isNot: negate, list: expr, expr: slExpr.items[0]}
- } else {
- // TODO(asmundak):
- panic("TBD")
- }
- } else if len(slExpr.items) == 1 {
- return &eqExpr{left: expr, right: slExpr.items[0], isEq: !negate}
+ slExpr := newStringListExpr(strings.Fields(xInList.literal))
+ // Generate simpler code for the common cases:
+ if expr.typ() == starlarkTypeList {
+ if len(slExpr.items) == 1 {
+ // Checking that a string belongs to list
+ return &inExpr{isNot: negate, list: expr, expr: slExpr.items[0]}, true
} else {
- return &inExpr{isNot: negate, list: newStringListExpr(strings.Fields(xInList.literal)), expr: expr}
+ return nil, false
}
+ } else if len(slExpr.items) == 1 {
+ return &eqExpr{left: expr, right: slExpr.items[0], isEq: !negate}, true
+ } else {
+ return &inExpr{isNot: negate, list: newStringListExpr(strings.Fields(xInList.literal)), expr: expr}, true
}
- return ctx.newBadExpr(cond, "filter arguments are too complex: %s", cond.Dump())
}
func (ctx *parseContext) parseCompareWildcardFuncResult(directive *mkparser.Directive,
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 2083121..447f658 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -389,6 +389,10 @@
endif
ifeq ($(TARGET_BUILD_VARIANT), $(filter $(TARGET_BUILD_VARIANT), userdebug eng))
endif
+ifneq (, $(filter $(TARGET_BUILD_VARIANT), userdebug eng))
+endif
+ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
+endif
ifneq (,$(filter true, $(v1)$(v2)))
endif
ifeq (,$(filter barbet coral%,$(TARGET_PRODUCT)))
@@ -407,8 +411,12 @@
pass
if "plaf" in g.get("PLATFORM_LIST", []):
pass
+ if g["TARGET_BUILD_VARIANT"] == " ".join(rblf.filter(g["TARGET_BUILD_VARIANT"], "userdebug eng")):
+ pass
if g["TARGET_BUILD_VARIANT"] in ["userdebug", "eng"]:
pass
+ if rblf.filter("userdebug eng", g["TARGET_BUILD_VARIANT"]):
+ pass
if rblf.filter("true", "%s%s" % (_v1, _v2)):
pass
if not rblf.filter("barbet coral%", g["TARGET_PRODUCT"]):
@@ -1119,7 +1127,7 @@
rblf.inherit(handle, "foo/font", _font_init)
# There's some space and even this comment between the include_top and the inherit-product
rblf.inherit(handle, "foo/font", _font_init)
- rblf.mkwarning("product.mk:11", "Including a path with a non-constant prefix, please convert this to a simple literal to generate cleaner starlark.")
+ rblf.mkwarning("product.mk:11", "Please avoid starting an include path with a variable. See https://source.android.com/setup/build/bazel/product_config/issues/includes for details.")
_entry = {
"foo/font.mk": ("foo/font", _font_init),
"bar/font.mk": ("bar/font", _font1_init),
diff --git a/mk2rbc/node.go b/mk2rbc/node.go
index 2fa6a85..5d98d7b 100644
--- a/mk2rbc/node.go
+++ b/mk2rbc/node.go
@@ -101,7 +101,7 @@
func (i inheritedDynamicModule) emitSelect(gctx *generationContext) {
if i.needsWarning {
gctx.newLine()
- gctx.writef("%s.mkwarning(%q, %q)", baseName, i.location, "Including a path with a non-constant prefix, please convert this to a simple literal to generate cleaner starlark. See https://source.android.com/setup/build/bazel/product_config/issues/includes for details.")
+ gctx.writef("%s.mkwarning(%q, %q)", baseName, i.location, "Please avoid starting an include path with a variable. See https://source.android.com/setup/build/bazel/product_config/issues/includes for details.")
}
gctx.newLine()
gctx.writef("_entry = {")
diff --git a/rust/rust.go b/rust/rust.go
index 018d1dd..f40f1a8 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -1192,6 +1192,10 @@
depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
directStaticLibDeps = append(directStaticLibDeps, ccDep)
+
+ // Record baseLibName for snapshots.
+ mod.Properties.SnapshotStaticLibs = append(mod.Properties.SnapshotStaticLibs, cc.BaseLibName(depName))
+
mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, makeLibName)
case cc.IsSharedDepTag(depTag):
// For the shared lib dependencies, we may link to the stub variant
@@ -1214,7 +1218,6 @@
// Record baseLibName for snapshots.
mod.Properties.SnapshotSharedLibs = append(mod.Properties.SnapshotSharedLibs, cc.BaseLibName(depName))
- mod.Properties.SnapshotStaticLibs = append(mod.Properties.SnapshotStaticLibs, cc.BaseLibName(depName))
mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, makeLibName)
exportDep = true
diff --git a/scripts/rustfmt.toml b/scripts/rustfmt.toml
index 617d425..cefaa42 100644
--- a/scripts/rustfmt.toml
+++ b/scripts/rustfmt.toml
@@ -1,5 +1,5 @@
# Android Format Style
-edition = "2018"
+edition = "2021"
use_small_heuristics = "Max"
newline_style = "Unix"
diff --git a/sdk/build_release.go b/sdk/build_release.go
index 2bcdc6f..4c2277e 100644
--- a/sdk/build_release.go
+++ b/sdk/build_release.go
@@ -85,7 +85,7 @@
// Add the build releases from oldest to newest.
buildReleaseS = initBuildRelease("S")
- buildReleaseT = initBuildRelease("T")
+ buildReleaseT = initBuildRelease("Tiramisu")
)
// initBuildRelease creates a new build release with the specified name.
diff --git a/sdk/build_release_test.go b/sdk/build_release_test.go
index 6608be4..6f1ef9e 100644
--- a/sdk/build_release_test.go
+++ b/sdk/build_release_test.go
@@ -60,7 +60,7 @@
t.Run("closed range", func(t *testing.T) {
set, err := parseBuildReleaseSet("S-F1")
android.AssertDeepEquals(t, "errors", nil, err)
- android.AssertStringEquals(t, "set", "[S,T,F1]", set.String())
+ android.AssertStringEquals(t, "set", "[S,Tiramisu,F1]", set.String())
})
invalidAReleaseMessage := `unknown release "A", expected one of ` + allBuildReleaseSet.String()
t.Run("invalid release", func(t *testing.T) {
@@ -79,7 +79,7 @@
android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), invalidAReleaseMessage)
})
t.Run("invalid release in closed range end", func(t *testing.T) {
- set, err := parseBuildReleaseSet("T-A")
+ set, err := parseBuildReleaseSet("Tiramisu-A")
android.AssertDeepEquals(t, "set", (*buildReleaseSet)(nil), set)
android.AssertStringDoesContain(t, "errors", fmt.Sprint(err), invalidAReleaseMessage)
})
@@ -128,13 +128,13 @@
type mapped struct {
Default string
- T_only string `supported_build_releases:"T"`
+ T_only string `supported_build_releases:"Tiramisu"`
}
type testBuildReleasePruner struct {
Default string
- S_and_T_only string `supported_build_releases:"S-T"`
- T_later string `supported_build_releases:"T+"`
+ S_and_T_only string `supported_build_releases:"S-Tiramisu"`
+ T_later string `supported_build_releases:"Tiramisu+"`
Nested nested
Mapped map[string]*mapped
}
diff --git a/starlark_fmt/Android.bp b/starlark_fmt/Android.bp
new file mode 100644
index 0000000..8d80ccd
--- /dev/null
+++ b/starlark_fmt/Android.bp
@@ -0,0 +1,28 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-starlark-format",
+ pkgPath: "android/soong/starlark_fmt",
+ srcs: [
+ "format.go",
+ ],
+ testSrcs: [
+ "format_test.go",
+ ],
+}
diff --git a/starlark_fmt/format.go b/starlark_fmt/format.go
new file mode 100644
index 0000000..23eee59
--- /dev/null
+++ b/starlark_fmt/format.go
@@ -0,0 +1,96 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package starlark_fmt
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+)
+
+const (
+ indent = 4
+)
+
+// Indention returns an indent string of the specified level.
+func Indention(level int) string {
+ if level < 0 {
+ panic(fmt.Errorf("indent level cannot be less than 0, but got %d", level))
+ }
+ return strings.Repeat(" ", level*indent)
+}
+
+// PrintBool returns a Starlark compatible bool string.
+func PrintBool(item bool) string {
+ return strings.Title(fmt.Sprintf("%t", item))
+}
+
+// PrintsStringList returns a Starlark-compatible string of a list of Strings/Labels.
+func PrintStringList(items []string, indentLevel int) string {
+ return PrintList(items, indentLevel, `"%s"`)
+}
+
+// PrintList returns a Starlark-compatible string of list formmated as requested.
+func PrintList(items []string, indentLevel int, formatString string) string {
+ if len(items) == 0 {
+ return "[]"
+ } else if len(items) == 1 {
+ return fmt.Sprintf("["+formatString+"]", items[0])
+ }
+ list := make([]string, 0, len(items)+2)
+ list = append(list, "[")
+ innerIndent := Indention(indentLevel + 1)
+ for _, item := range items {
+ list = append(list, fmt.Sprintf(`%s`+formatString+`,`, innerIndent, item))
+ }
+ list = append(list, Indention(indentLevel)+"]")
+ return strings.Join(list, "\n")
+}
+
+// PrintStringListDict returns a Starlark-compatible string formatted as dictionary with
+// string keys and list of string values.
+func PrintStringListDict(dict map[string][]string, indentLevel int) string {
+ formattedValueDict := make(map[string]string, len(dict))
+ for k, v := range dict {
+ formattedValueDict[k] = PrintStringList(v, indentLevel+1)
+ }
+ return PrintDict(formattedValueDict, indentLevel)
+}
+
+// PrintBoolDict returns a starlark-compatible string containing a dictionary with string keys and
+// values printed with no additional formatting.
+func PrintBoolDict(dict map[string]bool, indentLevel int) string {
+ formattedValueDict := make(map[string]string, len(dict))
+ for k, v := range dict {
+ formattedValueDict[k] = PrintBool(v)
+ }
+ return PrintDict(formattedValueDict, indentLevel)
+}
+
+// PrintDict returns a starlark-compatible string containing a dictionary with string keys and
+// values printed with no additional formatting.
+func PrintDict(dict map[string]string, indentLevel int) string {
+ if len(dict) == 0 {
+ return "{}"
+ }
+ items := make([]string, 0, len(dict))
+ for k, v := range dict {
+ items = append(items, fmt.Sprintf(`%s"%s": %s,`, Indention(indentLevel+1), k, v))
+ }
+ sort.Strings(items)
+ return fmt.Sprintf(`{
+%s
+%s}`, strings.Join(items, "\n"), Indention(indentLevel))
+}
diff --git a/starlark_fmt/format_test.go b/starlark_fmt/format_test.go
new file mode 100644
index 0000000..90f78ef
--- /dev/null
+++ b/starlark_fmt/format_test.go
@@ -0,0 +1,169 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package starlark_fmt
+
+import (
+ "testing"
+)
+
+func TestPrintEmptyStringList(t *testing.T) {
+ in := []string{}
+ indentLevel := 0
+ out := PrintStringList(in, indentLevel)
+ expectedOut := "[]"
+ if out != expectedOut {
+ t.Errorf("Expected %q, got %q", expectedOut, out)
+ }
+}
+
+func TestPrintSingleElementStringList(t *testing.T) {
+ in := []string{"a"}
+ indentLevel := 0
+ out := PrintStringList(in, indentLevel)
+ expectedOut := `["a"]`
+ if out != expectedOut {
+ t.Errorf("Expected %q, got %q", expectedOut, out)
+ }
+}
+
+func TestPrintMultiElementStringList(t *testing.T) {
+ in := []string{"a", "b"}
+ indentLevel := 0
+ out := PrintStringList(in, indentLevel)
+ expectedOut := `[
+ "a",
+ "b",
+]`
+ if out != expectedOut {
+ t.Errorf("Expected %q, got %q", expectedOut, out)
+ }
+}
+
+func TestPrintEmptyList(t *testing.T) {
+ in := []string{}
+ indentLevel := 0
+ out := PrintList(in, indentLevel, "%s")
+ expectedOut := "[]"
+ if out != expectedOut {
+ t.Errorf("Expected %q, got %q", expectedOut, out)
+ }
+}
+
+func TestPrintSingleElementList(t *testing.T) {
+ in := []string{"1"}
+ indentLevel := 0
+ out := PrintList(in, indentLevel, "%s")
+ expectedOut := `[1]`
+ if out != expectedOut {
+ t.Errorf("Expected %q, got %q", expectedOut, out)
+ }
+}
+
+func TestPrintMultiElementList(t *testing.T) {
+ in := []string{"1", "2"}
+ indentLevel := 0
+ out := PrintList(in, indentLevel, "%s")
+ expectedOut := `[
+ 1,
+ 2,
+]`
+ if out != expectedOut {
+ t.Errorf("Expected %q, got %q", expectedOut, out)
+ }
+}
+
+func TestListWithNonZeroIndent(t *testing.T) {
+ in := []string{"1", "2"}
+ indentLevel := 1
+ out := PrintList(in, indentLevel, "%s")
+ expectedOut := `[
+ 1,
+ 2,
+ ]`
+ if out != expectedOut {
+ t.Errorf("Expected %q, got %q", expectedOut, out)
+ }
+}
+
+func TestStringListDictEmpty(t *testing.T) {
+ in := map[string][]string{}
+ indentLevel := 0
+ out := PrintStringListDict(in, indentLevel)
+ expectedOut := `{}`
+ if out != expectedOut {
+ t.Errorf("Expected %q, got %q", expectedOut, out)
+ }
+}
+
+func TestStringListDict(t *testing.T) {
+ in := map[string][]string{
+ "key1": []string{},
+ "key2": []string{"a"},
+ "key3": []string{"1", "2"},
+ }
+ indentLevel := 0
+ out := PrintStringListDict(in, indentLevel)
+ expectedOut := `{
+ "key1": [],
+ "key2": ["a"],
+ "key3": [
+ "1",
+ "2",
+ ],
+}`
+ if out != expectedOut {
+ t.Errorf("Expected %q, got %q", expectedOut, out)
+ }
+}
+
+func TestPrintDict(t *testing.T) {
+ in := map[string]string{
+ "key1": `""`,
+ "key2": `"a"`,
+ "key3": `[
+ 1,
+ 2,
+ ]`,
+ }
+ indentLevel := 0
+ out := PrintDict(in, indentLevel)
+ expectedOut := `{
+ "key1": "",
+ "key2": "a",
+ "key3": [
+ 1,
+ 2,
+ ],
+}`
+ if out != expectedOut {
+ t.Errorf("Expected %q, got %q", expectedOut, out)
+ }
+}
+
+func TestPrintDictWithIndent(t *testing.T) {
+ in := map[string]string{
+ "key1": `""`,
+ "key2": `"a"`,
+ }
+ indentLevel := 1
+ out := PrintDict(in, indentLevel)
+ expectedOut := `{
+ "key1": "",
+ "key2": "a",
+ }`
+ if out != expectedOut {
+ t.Errorf("Expected %q, got %q", expectedOut, out)
+ }
+}