Merge "Add builtins and minimal runtime as dependencies instead of flags"
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/bazel.go b/android/bazel.go
index 7e5736f..4a96918 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -198,6 +198,7 @@
// build/bazel is not recursive. Instead list each subdirectory under
// build/bazel explicitly.
"build/bazel":/* recursive = */ false,
+ "build/bazel/ci/dist":/* recursive = */ false,
"build/bazel/examples/android_app":/* recursive = */ true,
"build/bazel/examples/java":/* recursive = */ true,
"build/bazel/bazel_skylib":/* recursive = */ true,
@@ -515,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/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/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/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 3bf0221..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,
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/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/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/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/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/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/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/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 7362cfb..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
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 a56815f..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"]):
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