Merge "bp2build/queryview: codegen control sequences literally."
diff --git a/android/apex.go b/android/apex.go
index a5ff442..257bdad 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -453,6 +453,23 @@
}
}
+// AvailableToSameApexes returns true if the two modules are apex_available to
+// exactly the same set of APEXes (and platform), i.e. if their apex_available
+// properties have the same elements.
+func AvailableToSameApexes(mod1, mod2 ApexModule) bool {
+ mod1ApexAvail := SortedUniqueStrings(mod1.apexModuleBase().ApexProperties.Apex_available)
+ mod2ApexAvail := SortedUniqueStrings(mod2.apexModuleBase().ApexProperties.Apex_available)
+ if len(mod1ApexAvail) != len(mod2ApexAvail) {
+ return false
+ }
+ for i, v := range mod1ApexAvail {
+ if v != mod2ApexAvail[i] {
+ return false
+ }
+ }
+ return true
+}
+
type byApexName []ApexInfo
func (a byApexName) Len() int { return len(a) }
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 0595d68..45dfbaa 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -344,73 +344,39 @@
# This file is generated by soong_build. Do not edit.
#####################################################
-def _x86_64_transition_impl(settings, attr):
+def _config_node_transition_impl(settings, attr):
return {
- "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_x86_64",
+ "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_%s" % attr.arch,
}
-def _x86_transition_impl(settings, attr):
- return {
- "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_x86",
- }
-
-def _arm64_transition_impl(settings, attr):
- return {
- "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_arm64",
- }
-
-def _arm_transition_impl(settings, attr):
- return {
- "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_arm",
- }
-
-x86_64_transition = transition(
- implementation = _x86_64_transition_impl,
+_config_node_transition = transition(
+ implementation = _config_node_transition_impl,
inputs = [],
outputs = [
"//command_line_option:platforms",
],
)
-x86_transition = transition(
- implementation = _x86_transition_impl,
- inputs = [],
- outputs = [
- "//command_line_option:platforms",
- ],
+def _passthrough_rule_impl(ctx):
+ return [DefaultInfo(files = depset(ctx.files.deps))]
+
+config_node = rule(
+ implementation = _passthrough_rule_impl,
+ attrs = {
+ "arch" : attr.string(mandatory = True),
+ "deps" : attr.label_list(cfg = _config_node_transition),
+ "_allowlist_function_transition": attr.label(default = "@bazel_tools//tools/allowlists/function_transition_allowlist"),
+ },
)
-arm64_transition = transition(
- implementation = _arm64_transition_impl,
- inputs = [],
- outputs = [
- "//command_line_option:platforms",
- ],
-)
-
-arm_transition = transition(
- implementation = _arm_transition_impl,
- inputs = [],
- outputs = [
- "//command_line_option:platforms",
- ],
-)
-
-def _mixed_build_root_impl(ctx):
- all_files = ctx.files.deps_x86_64 + ctx.files.deps_x86 + ctx.files.deps_arm64 + ctx.files.deps_arm
- return [DefaultInfo(files = depset(all_files))]
# Rule representing the root of the build, to depend on all Bazel targets that
# are required for the build. Building this target will build the entire Bazel
# build tree.
mixed_build_root = rule(
- implementation = _mixed_build_root_impl,
+ implementation = _passthrough_rule_impl,
attrs = {
- "deps_x86_64" : attr.label_list(cfg = x86_64_transition),
- "deps_x86" : attr.label_list(cfg = x86_transition),
- "deps_arm64" : attr.label_list(cfg = arm64_transition),
- "deps_arm" : attr.label_list(cfg = arm_transition),
- "_allowlist_function_transition": attr.label(default = "@bazel_tools//tools/allowlists/function_transition_allowlist"),
+ "deps" : attr.label_list(),
},
)
@@ -446,44 +412,42 @@
// architecture mapping.
formatString := `
# This file is generated by soong_build. Do not edit.
-load(":main.bzl", "mixed_build_root", "phony_root")
+load(":main.bzl", "config_node", "mixed_build_root", "phony_root")
+
+%s
mixed_build_root(name = "buildroot",
- deps_x86_64 = [%s],
- deps_x86 = [%s],
- deps_arm64 = [%s],
- deps_arm = [%s],
+ deps = [%s],
)
phony_root(name = "phonyroot",
deps = [":buildroot"],
)
`
- var deps_x86_64 []string = nil
- var deps_x86 []string = nil
- var deps_arm64 []string = nil
- var deps_arm []string = nil
+ configNodeFormatString := `
+config_node(name = "%s",
+ arch = "%s",
+ deps = [%s],
+)
+`
+
+ configNodesSection := ""
+
+ labelsByArch := map[string][]string{}
for val, _ := range context.requests {
labelString := fmt.Sprintf("\"%s\"", canonicalizeLabel(val.label))
- switch getArchString(val) {
- case "x86_64":
- deps_x86_64 = append(deps_x86_64, labelString)
- case "x86":
- deps_x86 = append(deps_x86, labelString)
- case "arm64":
- deps_arm64 = append(deps_arm64, labelString)
- case "arm":
- deps_arm = append(deps_arm, labelString)
- default:
- panic(fmt.Sprintf("unhandled architecture %s for %v", getArchString(val), val))
- }
+ archString := getArchString(val)
+ labelsByArch[archString] = append(labelsByArch[archString], labelString)
}
- return []byte(fmt.Sprintf(formatString,
- strings.Join(deps_x86_64, ",\n "),
- strings.Join(deps_x86, ",\n "),
- strings.Join(deps_arm64, ",\n "),
- strings.Join(deps_arm, ",\n ")))
+ configNodeLabels := []string{}
+ for archString, labels := range labelsByArch {
+ configNodeLabels = append(configNodeLabels, fmt.Sprintf("\":%s\"", archString))
+ labelsString := strings.Join(labels, ",\n ")
+ configNodesSection += fmt.Sprintf(configNodeFormatString, archString, archString, labelsString)
+ }
+
+ return []byte(fmt.Sprintf(formatString, configNodesSection, strings.Join(configNodeLabels, ",\n ")))
}
func indent(original string) string {
diff --git a/android/filegroup.go b/android/filegroup.go
index abbb4d4..2f13ab8 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -30,7 +30,7 @@
// https://docs.bazel.build/versions/master/be/general.html#filegroup
type bazelFilegroupAttributes struct {
- Srcs bazel.LabelList
+ Srcs bazel.LabelListAttribute
}
type bazelFilegroup struct {
@@ -57,8 +57,10 @@
return
}
+ srcs := bazel.MakeLabelListAttribute(
+ BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs))
attrs := &bazelFilegroupAttributes{
- Srcs: BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs),
+ Srcs: srcs,
}
props := bazel.BazelTargetModuleProperties{Rule_class: "filegroup"}
diff --git a/android/paths.go b/android/paths.go
index 1278961..db9e06a 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -286,6 +286,16 @@
return p.path
}
+// RelativeToPath returns an OptionalPath with the path that was embedded having been replaced by
+// the result of calling Path.RelativeToPath on it.
+func (p OptionalPath) RelativeToPath() OptionalPath {
+ if !p.valid {
+ return p
+ }
+ p.path = p.path.RelativeToTop()
+ return p
+}
+
// String returns the string version of the Path, or "" if it isn't valid.
func (p OptionalPath) String() string {
if p.valid {
@@ -477,6 +487,9 @@
// already be resolved by either deps mutator or path deps mutator.
func getOtherModuleLabel(ctx BazelConversionPathContext, dep, tag string) bazel.Label {
m, _ := ctx.GetDirectDep(dep)
+ if m == nil {
+ panic(fmt.Errorf("cannot get direct dep %s of %s", dep, ctx.Module().Name()))
+ }
otherLabel := bazelModuleLabel(ctx, m, tag)
label := bazelModuleLabel(ctx, ctx.Module(), "")
if samePackage(label, otherLabel) {
@@ -1642,16 +1655,10 @@
// Will panic if called from outside a test environment.
func ensureTestOnly() {
- // Normal soong test environment
- if InList("-test.short", os.Args) {
+ if PrefixInList(os.Args, "-test.") {
return
}
- // IntelliJ test environment
- if InList("-test.v", os.Args) {
- return
- }
-
- panic(fmt.Errorf("Not in test\n%s", strings.Join(os.Args, "\n")))
+ panic(fmt.Errorf("Not in test. Command line:\n %s", strings.Join(os.Args, "\n ")))
}
func (p InstallPath) RelativeToTop() Path {
diff --git a/android/queryview.go b/android/queryview.go
index 12d14df..224652e 100644
--- a/android/queryview.go
+++ b/android/queryview.go
@@ -68,7 +68,7 @@
Command: fmt.Sprintf(
`rm -rf "${outDir}/"* && `+
`mkdir -p "${outDir}" && `+
- `echo WORKSPACE: cat "%s" > "${outDir}/.queryview-depfile.d" && `+
+ `echo WORKSPACE: $$(cat "%s") > "${outDir}/.queryview-depfile.d" && `+
`BUILDER="%s" && `+
`echo BUILDER=$$BUILDER && `+
`cd "$$(dirname "$$BUILDER")" && `+
diff --git a/android/testing.go b/android/testing.go
index 27573d5..f4f5c98 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -558,7 +558,7 @@
return p
}
if p.config.config == nil {
- panic("cannot call RelativeToTop() on a TestingBuildParams previously returned by RelativeToTop()")
+ return p
}
// Take a copy of the build params and replace any args that contains test specific temporary
// paths with paths relative to the top.
@@ -670,7 +670,7 @@
config: b.config,
BuildParams: bparams,
RuleParams: b.provider.RuleParamsForTests()[bparams.Rule],
- }
+ }.RelativeToTop()
}
func (b baseTestingComponent) maybeBuildParamsFromRule(rule string) (TestingBuildParams, []string) {
@@ -816,6 +816,22 @@
return normalizeStringMapRelativeToTop(m.config, m.module.VariablesForTests())
}
+// OutputFiles calls OutputFileProducer.OutputFiles on the encapsulated module, exits the test
+// immediately if there is an error and otherwise returns the result of calling Paths.RelativeToTop
+// on the returned Paths.
+func (m TestingModule) OutputFiles(t *testing.T, tag string) Paths {
+ producer, ok := m.module.(OutputFileProducer)
+ if !ok {
+ t.Fatalf("%q must implement OutputFileProducer\n", m.module.Name())
+ }
+ paths, err := producer.OutputFiles(tag)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ return paths.RelativeToTop()
+}
+
// TestingSingleton is wrapper around an android.Singleton that provides methods to find information about individual
// ctx.Build parameters for verification in tests.
type TestingSingleton struct {
@@ -1040,3 +1056,20 @@
}
return result
}
+
+// StringRelativeToTop will normalize a string containing paths, e.g. ninja command, by replacing
+// any references to the test specific temporary build directory that changes with each run to a
+// fixed path relative to a notional top directory.
+//
+// This is similar to StringPathRelativeToTop except that assumes the string is a single path
+// containing at most one instance of the temporary build directory at the start of the path while
+// this assumes that there can be any number at any position.
+func StringRelativeToTop(config Config, command string) string {
+ return normalizeStringRelativeToTop(config, command)
+}
+
+// StringsRelativeToTop will return a new slice such that each item in the new slice is the result
+// of calling StringRelativeToTop on the corresponding item in the input slice.
+func StringsRelativeToTop(config Config, command []string) []string {
+ return normalizeStringArrayRelativeToTop(config, command)
+}
diff --git a/android/util.go b/android/util.go
index 506f8f7..a0394f6 100644
--- a/android/util.go
+++ b/android/util.go
@@ -193,6 +193,17 @@
return
}
+// FilterListPred returns the elements of the given list for which the predicate
+// returns true. Order is kept.
+func FilterListPred(list []string, pred func(s string) bool) (filtered []string) {
+ for _, l := range list {
+ if pred(l) {
+ filtered = append(filtered, l)
+ }
+ }
+ return
+}
+
// RemoveListFromList removes the strings belonging to the filter list from the
// given list and returns the result
func RemoveListFromList(list []string, filter_out []string) (result []string) {
diff --git a/android/util_test.go b/android/util_test.go
index fa26c77..09bec01 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -18,6 +18,7 @@
"fmt"
"reflect"
"strconv"
+ "strings"
"testing"
)
@@ -299,6 +300,14 @@
}
}
+func TestFilterListPred(t *testing.T) {
+ pred := func(s string) bool { return strings.HasPrefix(s, "a/") }
+ AssertArrayString(t, "filter", FilterListPred([]string{"a/c", "b/a", "a/b"}, pred), []string{"a/c", "a/b"})
+ AssertArrayString(t, "filter", FilterListPred([]string{"b/c", "a/a", "b/b"}, pred), []string{"a/a"})
+ AssertArrayString(t, "filter", FilterListPred([]string{"c/c", "b/a", "c/b"}, pred), []string{})
+ AssertArrayString(t, "filter", FilterListPred([]string{"a/c", "a/a", "a/b"}, pred), []string{"a/c", "a/a", "a/b"})
+}
+
func TestRemoveListFromList(t *testing.T) {
input := []string{"a", "b", "c", "d", "a", "c", "d"}
filter := []string{"a", "c"}
diff --git a/apex/apex.go b/apex/apex.go
index dca5595..9d06e1c 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -93,8 +93,14 @@
Multilib apexMultilibProperties
// List of boot images that are embedded inside this APEX bundle.
+ //
+ // deprecated: Use Bootclasspath_fragments
+ // TODO(b/177892522): Remove after has been replaced by Bootclasspath_fragments
Boot_images []string
+ // List of bootclasspath fragments that are embedded inside this APEX bundle.
+ Bootclasspath_fragments []string
+
// List of java libraries that are embedded inside this APEX bundle.
Java_libs []string
@@ -567,7 +573,7 @@
certificateTag = dependencyTag{name: "certificate"}
executableTag = dependencyTag{name: "executable", payload: true}
fsTag = dependencyTag{name: "filesystem", payload: true}
- bootImageTag = dependencyTag{name: "bootImage", payload: true}
+ bootImageTag = dependencyTag{name: "bootImage", payload: true, sourceOnly: true}
compatConfigTag = dependencyTag{name: "compatConfig", payload: true, sourceOnly: true}
javaLibTag = dependencyTag{name: "javaLib", payload: true}
jniLibTag = dependencyTag{name: "jniLib", payload: true}
@@ -748,6 +754,7 @@
// Common-arch dependencies come next
commonVariation := ctx.Config().AndroidCommonTarget.Variations()
ctx.AddFarVariationDependencies(commonVariation, bootImageTag, a.properties.Boot_images...)
+ ctx.AddFarVariationDependencies(commonVariation, bootImageTag, a.properties.Bootclasspath_fragments...)
ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.properties.Bpfs...)
ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
@@ -1695,6 +1702,9 @@
filesInfo = append(filesInfo, af)
}
}
+
+ // Track transitive dependencies.
+ return true
}
case javaLibTag:
switch child.(type) {
@@ -1903,6 +1913,21 @@
filesInfo = append(filesInfo, af)
return true // track transitive dependencies
}
+ } else if java.IsbootImageContentDepTag(depTag) {
+ // Add the contents of the boot image to the apex.
+ switch child.(type) {
+ case *java.Library, *java.SdkLibrary:
+ af := apexFileForJavaModule(ctx, child.(javaModule))
+ if !af.ok() {
+ ctx.PropertyErrorf("boot_images", "boot image content %q is not configured to be compiled into dex", depName)
+ return false
+ }
+ filesInfo = append(filesInfo, af)
+ return true // track transitive dependencies
+ default:
+ ctx.PropertyErrorf("boot_images", "boot image content %q of type %q is not supported", depName, ctx.OtherModuleType(child))
+ }
+
} else if _, ok := depTag.(android.CopyDirectlyInAnyApexTag); ok {
// nothing
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index e0cefa1..11b23c6 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -16,7 +16,6 @@
import (
"fmt"
- "io/ioutil"
"os"
"path"
"path/filepath"
@@ -38,8 +37,6 @@
"android/soong/sh"
)
-var buildDir string
-
// names returns name list from white space separated string
func names(s string) (ns []string) {
for _, n := range strings.Split(s, " ") {
@@ -118,7 +115,7 @@
)
var apexFixtureFactory = android.NewFixtureFactory(
- &buildDir,
+ nil,
// General preparers in alphabetical order as test infrastructure will enforce correct
// registration order.
android.PrepareForTestWithAndroidBuildComponents,
@@ -140,13 +137,13 @@
],
}
`),
+ prepareForTestWithMyapex,
android.FixtureMergeMockFs(android.MockFS{
- "a.java": nil,
- "PrebuiltAppFoo.apk": nil,
- "PrebuiltAppFooPriv.apk": nil,
- "apex_manifest.json": nil,
- "AndroidManifest.xml": nil,
- "system/sepolicy/apex/myapex-file_contexts": nil,
+ "a.java": nil,
+ "PrebuiltAppFoo.apk": nil,
+ "PrebuiltAppFooPriv.apk": nil,
+ "apex_manifest.json": nil,
+ "AndroidManifest.xml": nil,
"system/sepolicy/apex/myapex.updatable-file_contexts": nil,
"system/sepolicy/apex/myapex2-file_contexts": nil,
"system/sepolicy/apex/otherapex-file_contexts": nil,
@@ -204,17 +201,9 @@
}),
)
-func setUp() {
- var err error
- buildDir, err = ioutil.TempDir("", "soong_apex_test")
- if err != nil {
- panic(err)
- }
-}
-
-func tearDown() {
- _ = os.RemoveAll(buildDir)
-}
+var prepareForTestWithMyapex = android.FixtureMergeMockFs(android.MockFS{
+ "system/sepolicy/apex/myapex-file_contexts": nil,
+})
// ensure that 'result' equals 'expected'
func ensureEquals(t *testing.T, result string, expected string) {
@@ -496,7 +485,7 @@
}
`)
- apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
+ apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule").RelativeToTop()
// Make sure that Android.mk is created
ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
@@ -511,7 +500,7 @@
optFlags := apexRule.Args["opt_flags"]
ensureContains(t, optFlags, "--pubkey vendor/foo/devkeys/testkey.avbpubkey")
// Ensure that the NOTICE output is being packaged as an asset.
- ensureContains(t, optFlags, "--assets_dir "+buildDir+"/.intermediates/myapex/android_common_myapex_image/NOTICE")
+ ensureContains(t, optFlags, "--assets_dir out/soong/.intermediates/myapex/android_common_myapex_image/NOTICE")
copyCmds := apexRule.Args["copy_commands"]
@@ -2464,8 +2453,8 @@
prefix := "TARGET_"
var builder strings.Builder
data.Custom(&builder, name, prefix, "", data)
- androidMk := builder.String()
- installPath := path.Join(buildDir, "../target/product/test_device/vendor/apex")
+ androidMk := android.StringRelativeToTop(ctx.Config(), builder.String())
+ installPath := "out/target/product/test_device/vendor/apex"
ensureContains(t, androidMk, "LOCAL_MODULE_PATH := "+installPath)
apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
@@ -2509,13 +2498,13 @@
vendorVariant := "android_vendor.VER_arm64_armv8-a"
- ldRule := ctx.ModuleForTests("mybin", vendorVariant+"_apex10000").Rule("ld")
+ ldRule := ctx.ModuleForTests("mybin", vendorVariant+"_apex10000").Rule("ld").RelativeToTop()
libs := names(ldRule.Args["libFlags"])
// VNDK libs(libvndk/libc++) as they are
- ensureListContains(t, libs, buildDir+"/.intermediates/libvndk/"+vendorVariant+"_shared/libvndk.so")
- ensureListContains(t, libs, buildDir+"/.intermediates/"+cc.DefaultCcCommonTestModulesDir+"libc++/"+vendorVariant+"_shared/libc++.so")
+ ensureListContains(t, libs, "out/soong/.intermediates/libvndk/"+vendorVariant+"_shared/libvndk.so")
+ ensureListContains(t, libs, "out/soong/.intermediates/"+cc.DefaultCcCommonTestModulesDir+"libc++/"+vendorVariant+"_shared/libc++.so")
// non-stable Vendor libs as APEX variants
- ensureListContains(t, libs, buildDir+"/.intermediates/libvendor/"+vendorVariant+"_shared_apex10000/libvendor.so")
+ ensureListContains(t, libs, "out/soong/.intermediates/libvendor/"+vendorVariant+"_shared_apex10000/libvendor.so")
// VNDK libs are not included when use_vndk_as_stable: true
ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
@@ -4088,15 +4077,15 @@
`)
apex := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
- expected := buildDir + "/target/product/test_device/" + tc.parition + "/apex"
- actual := apex.installDir.String()
+ expected := "out/soong/target/product/test_device/" + tc.parition + "/apex"
+ actual := apex.installDir.RelativeToTop().String()
if actual != expected {
t.Errorf("wrong install path. expected %q. actual %q", expected, actual)
}
flattened := ctx.ModuleForTests("myapex", "android_common_myapex_flattened").Module().(*apexBundle)
- expected = buildDir + "/target/product/test_device/" + tc.flattenedPartition + "/apex"
- actual = flattened.installDir.String()
+ expected = "out/soong/target/product/test_device/" + tc.flattenedPartition + "/apex"
+ actual = flattened.installDir.RelativeToTop().String()
if actual != expected {
t.Errorf("wrong install path. expected %q. actual %q", expected, actual)
}
@@ -5077,7 +5066,7 @@
}
// JNI libraries including transitive deps are
for _, jni := range []string{"libjni", "libfoo"} {
- jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_sdk_shared_apex10000").Module().(*cc.Module).OutputFile()
+ jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_sdk_shared_apex10000").Module().(*cc.Module).OutputFile().RelativeToPath()
// ... embedded inside APK (jnilibs.zip)
ensureListContains(t, appZipRule.Implicits.Strings(), jniOutput.String())
// ... and not directly inside the APEX
@@ -5715,7 +5704,7 @@
// The bar library should depend on the implementation jar.
barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac")
- if expected, actual := `^-classpath /[^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected %q, found %#q", expected, actual)
}
}
@@ -5766,7 +5755,7 @@
// The bar library should depend on the stubs jar.
barLibrary := ctx.ModuleForTests("bar", "android_common").Rule("javac")
- if expected, actual := `^-classpath /[^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected %q, found %#q", expected, actual)
}
}
@@ -5856,7 +5845,7 @@
// The bar library should depend on the implementation jar.
barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac")
- if expected, actual := `^-classpath /[^:]*/turbine-combined/foo\.impl\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.impl\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected %q, found %#q", expected, actual)
}
}
@@ -6327,7 +6316,7 @@
)
m := ctx.ModuleForTests("myapex", "android_common")
- extractedApex := m.Output(buildDir + "/.intermediates/myapex/android_common/foo_v2.apex")
+ extractedApex := m.Output("out/soong/.intermediates/myapex/android_common/foo_v2.apex")
actual := extractedApex.Inputs
if len(actual) != 1 {
@@ -6454,7 +6443,7 @@
for k, v := range filesForSdkLibrary {
fs[k] = v
}
- config := android.TestArchConfig(buildDir, nil, bp, fs)
+ config := android.TestArchConfig(t.TempDir(), nil, bp, fs)
ctx := android.NewTestArchContext(config)
ctx.RegisterModuleType("apex", BundleFactory)
@@ -6675,7 +6664,7 @@
"system/sepolicy/apex/myapex-file_contexts": nil,
}
- config := android.TestArchConfig(buildDir, nil, bp, fs)
+ config := android.TestArchConfig(t.TempDir(), nil, bp, fs)
android.SetTestNeverallowRules(config, rules)
updatableBootJars := make([]string, 0, len(apexBootJars))
for _, apexBootJar := range apexBootJars {
@@ -6859,21 +6848,77 @@
}
`)
- // the test 'mytest' is a test for the apex, therefore is linked to the
+ ensureLinkedLibIs := func(mod, variant, linkedLib, expectedVariant string) {
+ ldFlags := strings.Split(ctx.ModuleForTests(mod, variant).Rule("ld").RelativeToTop().Args["libFlags"], " ")
+ mylibLdFlags := android.FilterListPred(ldFlags, func(s string) bool { return strings.HasPrefix(s, linkedLib) })
+ android.AssertArrayString(t, "unexpected "+linkedLib+" link library for "+mod, []string{linkedLib + expectedVariant}, mylibLdFlags)
+ }
+
+ // These modules are tests for the apex, therefore are linked to the
// actual implementation of mylib instead of its stub.
- ldFlags := ctx.ModuleForTests("mytest", "android_arm64_armv8-a").Rule("ld").Args["libFlags"]
- ensureContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared/mylib.so")
- ensureNotContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared_1/mylib.so")
+ ensureLinkedLibIs("mytest", "android_arm64_armv8-a", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so")
+ ensureLinkedLibIs("mytestlib", "android_arm64_armv8-a_shared", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so")
+ ensureLinkedLibIs("mybench", "android_arm64_armv8-a", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so")
+}
- // The same should be true for cc_library
- ldFlags = ctx.ModuleForTests("mytestlib", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
- ensureContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared/mylib.so")
- ensureNotContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared_1/mylib.so")
+func TestIndirectTestFor(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib", "myprivlib"],
+ updatable: false,
+ }
- // ... and for cc_benchmark
- ldFlags = ctx.ModuleForTests("mybench", "android_arm64_armv8-a").Rule("ld").Args["libFlags"]
- ensureContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared/mylib.so")
- ensureNotContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared_1/mylib.so")
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ stubs: {
+ versions: ["1"],
+ },
+ apex_available: ["myapex"],
+ }
+
+ cc_library {
+ name: "myprivlib",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ shared_libs: ["mylib"],
+ apex_available: ["myapex"],
+ }
+
+ cc_library {
+ name: "mytestlib",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ shared_libs: ["myprivlib"],
+ stl: "none",
+ test_for: ["myapex"],
+ }
+ `)
+
+ ensureLinkedLibIs := func(mod, variant, linkedLib, expectedVariant string) {
+ ldFlags := strings.Split(ctx.ModuleForTests(mod, variant).Rule("ld").RelativeToTop().Args["libFlags"], " ")
+ mylibLdFlags := android.FilterListPred(ldFlags, func(s string) bool { return strings.HasPrefix(s, linkedLib) })
+ android.AssertArrayString(t, "unexpected "+linkedLib+" link library for "+mod, []string{linkedLib + expectedVariant}, mylibLdFlags)
+ }
+
+ // The platform variant of mytestlib links to the platform variant of the
+ // internal myprivlib.
+ ensureLinkedLibIs("mytestlib", "android_arm64_armv8-a_shared", "out/soong/.intermediates/myprivlib/", "android_arm64_armv8-a_shared/myprivlib.so")
+
+ // The platform variant of myprivlib links to the platform variant of mylib
+ // and bypasses its stubs.
+ ensureLinkedLibIs("myprivlib", "android_arm64_armv8-a_shared", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so")
}
// TODO(jungjw): Move this to proptools
@@ -6904,7 +6949,7 @@
m := ctx.ModuleForTests("myapex", "android_common")
// Check extract_apks tool parameters.
- extractedApex := m.Output(buildDir + "/.intermediates/myapex/android_common/foo_v2.apex")
+ extractedApex := m.Output("out/soong/.intermediates/myapex/android_common/foo_v2.apex")
actual := extractedApex.Args["abis"]
expected := "ARMEABI_V7A,ARM64_V8A"
if actual != expected {
@@ -7395,12 +7440,5 @@
}
func TestMain(m *testing.M) {
- run := func() int {
- setUp()
- defer tearDown()
-
- return m.Run()
- }
-
- os.Exit(run())
+ os.Exit(m.Run())
}
diff --git a/apex/boot_image_test.go b/apex/boot_image_test.go
index 7e37e42..574166a 100644
--- a/apex/boot_image_test.go
+++ b/apex/boot_image_test.go
@@ -26,23 +26,32 @@
// Contains tests for boot_image logic from java/boot_image.go as the ART boot image requires
// modules from the ART apex.
+var prepareForTestWithBootImage = android.GroupFixturePreparers(
+ java.PrepareForTestWithDexpreopt,
+ PrepareForTestWithApexBuildComponents,
+)
+
+// Some additional files needed for the art apex.
+var prepareForTestWithArtApex = android.FixtureMergeMockFs(android.MockFS{
+ "com.android.art.avbpubkey": nil,
+ "com.android.art.pem": nil,
+ "system/sepolicy/apex/com.android.art-file_contexts": nil,
+})
+
func TestBootImages(t *testing.T) {
- result := apexFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
+ prepareForTestWithBootImage,
// Configure some libraries in the art and framework boot images.
dexpreopt.FixtureSetArtBootJars("com.android.art:baz", "com.android.art:quuz"),
dexpreopt.FixtureSetBootJars("platform:foo", "platform:bar"),
- filesForSdkLibrary.AddToFixture(),
- // Some additional files needed for the art apex.
- android.FixtureMergeMockFs(android.MockFS{
- "com.android.art.avbpubkey": nil,
- "com.android.art.pem": nil,
- "system/sepolicy/apex/com.android.art-file_contexts": nil,
- }),
+ prepareForTestWithArtApex,
+
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.FixtureWithLastReleaseApis("foo"),
).RunTestWithBp(t, `
java_sdk_library {
name: "foo",
srcs: ["b.java"],
- unsafe_ignore_missing_latest_api: true,
}
java_library {
@@ -86,6 +95,9 @@
boot_image {
name: "art-boot-image",
image_name: "art",
+ apex_available: [
+ "com.android.art",
+ ],
}
boot_image {
@@ -151,10 +163,163 @@
android.AssertTrimmedStringEquals(t, "invalid paths for "+moduleName, expectedBootImageFiles, strings.Join(allPaths, "\n"))
}
-func TestBootImageInApex(t *testing.T) {
- result := apexFixtureFactory.Extend(
- // Configure some libraries in the framework boot image.
- dexpreopt.FixtureSetBootJars("platform:foo", "platform:bar"),
+func TestBootImageInArtApex(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithBootImage,
+ prepareForTestWithArtApex,
+
+ // Configure some libraries in the art boot image.
+ dexpreopt.FixtureSetArtBootJars("com.android.art:foo", "com.android.art:bar"),
+ ).RunTestWithBp(t, `
+ apex {
+ name: "com.android.art",
+ key: "com.android.art.key",
+ boot_images: [
+ "mybootimage",
+ ],
+ // bar (like foo) should be transitively included in this apex because it is part of the
+ // mybootimage boot_image. However, it is kept here to ensure that the apex dedups the files
+ // correctly.
+ java_libs: [
+ "bar",
+ ],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "com.android.art.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "foo",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ boot_image {
+ name: "mybootimage",
+ image_name: "art",
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ // Make sure that a preferred prebuilt doesn't affect the apex.
+ prebuilt_boot_image {
+ name: "mybootimage",
+ image_name: "art",
+ prefer: true,
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+ `)
+
+ ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+ "javalib/arm/boot.art",
+ "javalib/arm/boot.oat",
+ "javalib/arm/boot.vdex",
+ "javalib/arm/boot-bar.art",
+ "javalib/arm/boot-bar.oat",
+ "javalib/arm/boot-bar.vdex",
+ "javalib/arm64/boot.art",
+ "javalib/arm64/boot.oat",
+ "javalib/arm64/boot.vdex",
+ "javalib/arm64/boot-bar.art",
+ "javalib/arm64/boot-bar.oat",
+ "javalib/arm64/boot-bar.vdex",
+ "javalib/bar.jar",
+ "javalib/foo.jar",
+ })
+
+ java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+ `bar`,
+ `com.android.art.key`,
+ `mybootimage`,
+ })
+}
+
+func TestBootImageInPrebuiltArtApex(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithBootImage,
+ prepareForTestWithArtApex,
+
+ android.FixtureMergeMockFs(android.MockFS{
+ "com.android.art-arm64.apex": nil,
+ "com.android.art-arm.apex": nil,
+ }),
+
+ // Configure some libraries in the art boot image.
+ dexpreopt.FixtureSetArtBootJars("com.android.art:foo", "com.android.art:bar"),
+ ).RunTestWithBp(t, `
+ prebuilt_apex {
+ name: "com.android.art",
+ arch: {
+ arm64: {
+ src: "com.android.art-arm64.apex",
+ },
+ arm: {
+ src: "com.android.art-arm.apex",
+ },
+ },
+ exported_java_libs: ["foo", "bar"],
+ }
+
+ java_import {
+ name: "foo",
+ jars: ["foo.jar"],
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ java_import {
+ name: "bar",
+ jars: ["bar.jar"],
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ prebuilt_boot_image {
+ name: "mybootimage",
+ image_name: "art",
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+ `)
+
+ java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common", []string{
+ `prebuilt_bar`,
+ `prebuilt_foo`,
+ })
+
+ java.CheckModuleDependencies(t, result.TestContext, "mybootimage", "android_common", []string{
+ `dex2oatd`,
+ `prebuilt_bar`,
+ `prebuilt_foo`,
+ })
+}
+
+func TestBootImageContentsNoName(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithBootImage,
+ prepareForTestWithMyapex,
).RunTestWithBp(t, `
apex {
name: "myapex",
@@ -175,17 +340,26 @@
name: "foo",
srcs: ["b.java"],
installable: true,
+ apex_available: [
+ "myapex",
+ ],
}
java_library {
name: "bar",
srcs: ["b.java"],
installable: true,
+ apex_available: [
+ "myapex",
+ ],
}
boot_image {
name: "mybootimage",
- image_name: "boot",
+ contents: [
+ "foo",
+ "bar",
+ ],
apex_available: [
"myapex",
],
@@ -193,18 +367,15 @@
`)
ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
- "javalib/arm/boot-bar.art",
- "javalib/arm/boot-bar.oat",
- "javalib/arm/boot-bar.vdex",
- "javalib/arm/boot-foo.art",
- "javalib/arm/boot-foo.oat",
- "javalib/arm/boot-foo.vdex",
- "javalib/arm64/boot-bar.art",
- "javalib/arm64/boot-bar.oat",
- "javalib/arm64/boot-bar.vdex",
- "javalib/arm64/boot-foo.art",
- "javalib/arm64/boot-foo.oat",
- "javalib/arm64/boot-foo.vdex",
+ // This does not include art, oat or vdex files as they are only included for the art boot
+ // image.
+ "javalib/bar.jar",
+ "javalib/foo.jar",
+ })
+
+ java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
+ `myapex.key`,
+ `mybootimage`,
})
}
diff --git a/bazel/properties.go b/bazel/properties.go
index abdc107..25e110a 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -76,6 +76,92 @@
return uniqueLabelList
}
+const (
+ ARCH_X86 = "x86"
+ ARCH_X86_64 = "x86_64"
+ ARCH_ARM = "arm"
+ ARCH_ARM64 = "arm64"
+)
+
+var (
+ // This is the list of architectures with a Bazel config_setting and
+ // constraint value equivalent. is actually android.ArchTypeList, but the
+ // android package depends on the bazel package, so a cyclic dependency
+ // prevents using that here.
+ selectableArchs = []string{ARCH_X86, ARCH_X86_64, ARCH_ARM, ARCH_ARM64}
+)
+
+// Arch-specific label_list typed Bazel attribute values. This should correspond
+// to the types of architectures supported for compilation in arch.go.
+type labelListArchValues struct {
+ X86 LabelList
+ X86_64 LabelList
+ Arm LabelList
+ Arm64 LabelList
+ // TODO(b/181299724): this is currently missing the "common" arch, which
+ // doesn't have an equivalent platform() definition yet.
+}
+
+// LabelListAttribute is used to represent a list of Bazel labels as an
+// attribute.
+type LabelListAttribute struct {
+ // The non-arch specific attribute label list Value. Required.
+ Value LabelList
+
+ // The arch-specific attribute label list values. Optional. If used, these
+ // are generated in a select statement and appended to the non-arch specific
+ // label list Value.
+ ArchValues labelListArchValues
+}
+
+// MakeLabelListAttribute initializes a LabelListAttribute with the non-arch specific value.
+func MakeLabelListAttribute(value LabelList) LabelListAttribute {
+ return LabelListAttribute{Value: UniqueBazelLabelList(value)}
+}
+
+// HasArchSpecificValues returns true if the attribute contains
+// architecture-specific label_list values.
+func (attrs *LabelListAttribute) HasArchSpecificValues() bool {
+ for _, arch := range selectableArchs {
+ if len(attrs.GetValueForArch(arch).Includes) > 0 || len(attrs.GetValueForArch(arch).Excludes) > 0 {
+ return true
+ }
+ }
+ return false
+}
+
+// GetValueForArch returns the label_list attribute value for an architecture.
+func (attrs *LabelListAttribute) GetValueForArch(arch string) LabelList {
+ switch arch {
+ case ARCH_X86:
+ return attrs.ArchValues.X86
+ case ARCH_X86_64:
+ return attrs.ArchValues.X86_64
+ case ARCH_ARM:
+ return attrs.ArchValues.Arm
+ case ARCH_ARM64:
+ return attrs.ArchValues.Arm64
+ default:
+ panic(fmt.Errorf("Unknown arch: %s", arch))
+ }
+}
+
+// SetValueForArch sets the label_list attribute value for an architecture.
+func (attrs *LabelListAttribute) SetValueForArch(arch string, value LabelList) {
+ switch arch {
+ case "x86":
+ attrs.ArchValues.X86 = value
+ case "x86_64":
+ attrs.ArchValues.X86_64 = value
+ case "arm":
+ attrs.ArchValues.Arm = value
+ case "arm64":
+ attrs.ArchValues.Arm64 = value
+ default:
+ panic(fmt.Errorf("Unknown arch: %s", arch))
+ }
+}
+
// StringListAttribute corresponds to the string_list Bazel attribute type with
// support for additional metadata, like configurations.
type StringListAttribute struct {
@@ -89,11 +175,10 @@
// Arch-specific string_list typed Bazel attribute values. This should correspond
// to the types of architectures supported for compilation in arch.go.
type stringListArchValues struct {
- X86 []string
- X86_64 []string
- Arm []string
- Arm64 []string
- Default []string
+ X86 []string
+ X86_64 []string
+ Arm []string
+ Arm64 []string
// TODO(b/181299724): this is currently missing the "common" arch, which
// doesn't have an equivalent platform() definition yet.
}
@@ -101,7 +186,7 @@
// HasArchSpecificValues returns true if the attribute contains
// architecture-specific string_list values.
func (attrs *StringListAttribute) HasArchSpecificValues() bool {
- for _, arch := range []string{"x86", "x86_64", "arm", "arm64", "default"} {
+ for _, arch := range selectableArchs {
if len(attrs.GetValueForArch(arch)) > 0 {
return true
}
@@ -112,16 +197,14 @@
// GetValueForArch returns the string_list attribute value for an architecture.
func (attrs *StringListAttribute) GetValueForArch(arch string) []string {
switch arch {
- case "x86":
+ case ARCH_X86:
return attrs.ArchValues.X86
- case "x86_64":
+ case ARCH_X86_64:
return attrs.ArchValues.X86_64
- case "arm":
+ case ARCH_ARM:
return attrs.ArchValues.Arm
- case "arm64":
+ case ARCH_ARM64:
return attrs.ArchValues.Arm64
- case "default":
- return attrs.ArchValues.Default
default:
panic(fmt.Errorf("Unknown arch: %s", arch))
}
@@ -130,16 +213,14 @@
// SetValueForArch sets the string_list attribute value for an architecture.
func (attrs *StringListAttribute) SetValueForArch(arch string, value []string) {
switch arch {
- case "x86":
+ case ARCH_X86:
attrs.ArchValues.X86 = value
- case "x86_64":
+ case ARCH_X86_64:
attrs.ArchValues.X86_64 = value
- case "arm":
+ case ARCH_ARM:
attrs.ArchValues.Arm = value
- case "arm64":
+ case ARCH_ARM64:
attrs.ArchValues.Arm64 = value
- case "default":
- attrs.ArchValues.Default = value
default:
panic(fmt.Errorf("Unknown arch: %s", arch))
}
diff --git a/bloaty/bloaty.go b/bloaty/bloaty.go
index 21bf4ac..653c489 100644
--- a/bloaty/bloaty.go
+++ b/bloaty/bloaty.go
@@ -22,7 +22,7 @@
"github.com/google/blueprint"
)
-const bloatyDescriptorExt = "bloaty.csv"
+const bloatyDescriptorExt = ".bloaty.csv"
const protoFilename = "binary_sizes.pb"
var (
@@ -75,7 +75,7 @@
return
}
filePath := ctx.ModuleProvider(m, fileSizeMeasurerKey).(android.ModuleOutPath)
- sizeFile := filePath.ReplaceExtension(ctx, bloatyDescriptorExt)
+ sizeFile := filePath.InSameDir(ctx, filePath.Base()+bloatyDescriptorExt)
ctx.Build(pctx, android.BuildParams{
Rule: bloaty,
Description: "bloaty " + filePath.Rel(),
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 3564da0..e93b3dc 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -370,9 +370,20 @@
// values for unset properties, like system_shared_libs = ["libc", "libm", "libdl"] at
// https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=281-287;drc=f70926eef0b9b57faf04c17a1062ce50d209e480
//
- // In Bazel-parlance, we would use "attr.<type>(default = <default value>)" to set the default
- // value of unset attributes.
- return "", nil
+ // In Bazel-parlance, we would use "attr.<type>(default = <default
+ // value>)" to set the default value of unset attributes. In the cases
+ // where the bp2build converter didn't set the default value within the
+ // mutator when creating the BazelTargetModule, this would be a zero
+ // value. For those cases, we return a non-surprising default value so
+ // generated BUILD files are syntactically correct.
+ switch propertyValue.Kind() {
+ case reflect.Slice:
+ return "[]", nil
+ case reflect.Map:
+ return "{}", nil
+ default:
+ return "", nil
+ }
}
var ret string
@@ -404,9 +415,34 @@
case reflect.Struct:
// Special cases where the bp2build sends additional information to the codegenerator
// by wrapping the attributes in a custom struct type.
- if labels, ok := propertyValue.Interface().(bazel.LabelList); ok {
+ if labels, ok := propertyValue.Interface().(bazel.LabelListAttribute); ok {
// TODO(b/165114590): convert glob syntax
- return prettyPrint(reflect.ValueOf(labels.Includes), indent)
+ ret, err := prettyPrint(reflect.ValueOf(labels.Value.Includes), indent)
+ if err != nil {
+ return ret, err
+ }
+
+ if !labels.HasArchSpecificValues() {
+ // Select statement not needed.
+ return ret, nil
+ }
+
+ ret += " + " + "select({\n"
+ for _, arch := range android.ArchTypeList() {
+ value := labels.GetValueForArch(arch.Name)
+ if len(value.Includes) > 0 {
+ ret += makeIndent(indent + 1)
+ list, _ := prettyPrint(reflect.ValueOf(value.Includes), indent+1)
+ ret += fmt.Sprintf("\"%s\": %s,\n", platformArchMap[arch], list)
+ }
+ }
+
+ ret += makeIndent(indent + 1)
+ ret += fmt.Sprintf("\"%s\": [],\n", "//conditions:default")
+
+ ret += makeIndent(indent)
+ ret += "})"
+ return ret, err
} else if label, ok := propertyValue.Interface().(bazel.Label); ok {
return fmt.Sprintf("%q", label.Label), nil
} else if stringList, ok := propertyValue.Interface().(bazel.StringListAttribute); ok {
@@ -432,8 +468,7 @@
}
ret += makeIndent(indent + 1)
- list, _ := prettyPrint(reflect.ValueOf(stringList.GetValueForArch("default")), indent+1)
- ret += fmt.Sprintf("\"%s\": %s,\n", "//conditions:default", list)
+ ret += fmt.Sprintf("\"%s\": [],\n", "//conditions:default")
ret += makeIndent(indent)
ret += "})"
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 3fa1e2a..49897b3 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -518,8 +518,6 @@
expectedBazelTargets: []string{
`filegroup(
name = "fg_foo",
- srcs = [
- ],
)`,
},
},
@@ -1117,8 +1115,8 @@
"out",
],
srcs = [
- "srcs-from-3",
"in1",
+ "srcs-from-3",
],
)`,
description: "genrule applies properties from genrule_defaults transitively",
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index 1c058ba..b007033 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -74,8 +74,8 @@
],
srcs = [
"a/b/bar.h",
- "a/b/foo.h",
"a/b/c.c",
+ "a/b/foo.h",
],
)`,
},
@@ -278,9 +278,13 @@
moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
blueprint: `cc_object {
name: "foo",
+ srcs: ["a.cpp"],
arch: {
x86: {
- cflags: ["-fPIC"],
+ cflags: ["-fPIC"], // string list
+ },
+ arm: {
+ srcs: ["arch/arm/file.S"], // label list
},
},
bazel_module: { bp2build_available: true },
@@ -295,12 +299,19 @@
"@bazel_tools//platforms:x86_32": [
"-fPIC",
],
- "//conditions:default": [
- ],
+ "//conditions:default": [],
}),
local_include_dirs = [
".",
],
+ srcs = [
+ "a.cpp",
+ ] + select({
+ "@bazel_tools//platforms:arm": [
+ "arch/arm/file.S",
+ ],
+ "//conditions:default": [],
+ }),
)`,
},
},
@@ -311,17 +322,22 @@
moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
blueprint: `cc_object {
name: "foo",
+ srcs: ["base.cpp"],
arch: {
x86: {
+ srcs: ["x86.cpp"],
cflags: ["-fPIC"],
},
x86_64: {
+ srcs: ["x86_64.cpp"],
cflags: ["-fPIC"],
},
arm: {
+ srcs: ["arm.cpp"],
cflags: ["-Wall"],
},
arm64: {
+ srcs: ["arm64.cpp"],
cflags: ["-Wall"],
},
},
@@ -346,12 +362,28 @@
"@bazel_tools//platforms:x86_64": [
"-fPIC",
],
- "//conditions:default": [
- ],
+ "//conditions:default": [],
}),
local_include_dirs = [
".",
],
+ srcs = [
+ "base.cpp",
+ ] + select({
+ "@bazel_tools//platforms:arm": [
+ "arm.cpp",
+ ],
+ "@bazel_tools//platforms:aarch64": [
+ "arm64.cpp",
+ ],
+ "@bazel_tools//platforms:x86_32": [
+ "x86.cpp",
+ ],
+ "@bazel_tools//platforms:x86_64": [
+ "x86_64.cpp",
+ ],
+ "//conditions:default": [],
+ }),
)`,
},
},
diff --git a/bp2build/constants.go b/bp2build/constants.go
index 23bca83..70f320e 100644
--- a/bp2build/constants.go
+++ b/bp2build/constants.go
@@ -18,7 +18,7 @@
// When both a BUILD and BUILD.bazel file are exist in the same package, the BUILD.bazel file will
// be preferred for use within a Bazel build.
- // The file name used for automatically generated files. Files with this name are ignored by git.
+ // The file name used for automatically generated files.
GeneratedBuildFileName = "BUILD"
// The file name used for hand-crafted build targets.
HandcraftedBuildFileName = "BUILD.bazel"
diff --git a/cc/cc.go b/cc/cc.go
index f843b41..f074597 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -363,7 +363,7 @@
// List of APEXes that this module has private access to for testing purpose. The module
// can depend on libraries that are not exported by the APEXes and use private symbols
// from the exported libraries.
- Test_for []string
+ Test_for []string `android:"arch_variant"`
}
type VendorProperties struct {
@@ -2631,14 +2631,31 @@
// However, for host, ramdisk, vendor_ramdisk, recovery or bootstrap modules,
// always link to non-stub variant
useStubs = dep.(android.ApexModule).NotInPlatform() && !c.bootstrap()
- // Another exception: if this module is bundled with an APEX, then
- // it is linked with the non-stub variant of a module in the APEX
- // as if this is part of the APEX.
- testFor := ctx.Provider(android.ApexTestForInfoProvider).(android.ApexTestForInfo)
- for _, apexContents := range testFor.ApexContents {
- if apexContents.DirectlyInApex(depName) {
+ if useStubs {
+ // Another exception: if this module is a test for an APEX, then
+ // it is linked with the non-stub variant of a module in the APEX
+ // as if this is part of the APEX.
+ testFor := ctx.Provider(android.ApexTestForInfoProvider).(android.ApexTestForInfo)
+ for _, apexContents := range testFor.ApexContents {
+ if apexContents.DirectlyInApex(depName) {
+ useStubs = false
+ break
+ }
+ }
+ }
+ if useStubs {
+ // Yet another exception: If this module and the dependency are
+ // available to the same APEXes then skip stubs between their
+ // platform variants. This complements the test_for case above,
+ // which avoids the stubs on a direct APEX library dependency, by
+ // avoiding stubs for indirect test dependencies as well.
+ //
+ // TODO(b/183882457): This doesn't work if the two libraries have
+ // only partially overlapping apex_available. For that test_for
+ // modules would need to be split into APEX variants and resolved
+ // separately for each APEX they have access to.
+ if android.AvailableToSameApexes(c, dep.(android.ApexModule)) {
useStubs = false
- break
}
}
} else {
diff --git a/cc/cc_test.go b/cc/cc_test.go
index f1efbff..205c71f 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -301,13 +301,9 @@
func checkSnapshotIncludeExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string, include bool, fake bool) {
t.Helper()
- mod, ok := ctx.ModuleForTests(moduleName, variant).Module().(android.OutputFileProducer)
- if !ok {
- t.Errorf("%q must have output\n", moduleName)
- return
- }
- outputFiles, err := mod.OutputFiles("")
- if err != nil || len(outputFiles) != 1 {
+ mod := ctx.ModuleForTests(moduleName, variant)
+ outputFiles := mod.OutputFiles(t, "")
+ if len(outputFiles) != 1 {
t.Errorf("%q must have single output\n", moduleName)
return
}
@@ -333,14 +329,17 @@
}
func checkSnapshot(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
+ t.Helper()
checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, false)
}
func checkSnapshotExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
+ t.Helper()
checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, false, false)
}
func checkSnapshotRule(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
+ t.Helper()
checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, true)
}
@@ -2552,7 +2551,7 @@
func getOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
for _, moduleName := range moduleNames {
module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)
- output := module.outputFile.Path()
+ output := module.outputFile.Path().RelativeToTop()
paths = append(paths, output)
}
return paths
@@ -2583,7 +2582,8 @@
variant := "android_arm64_armv8-a_static"
moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
- actual := ctx.ModuleProvider(moduleA, StaticLibraryInfoProvider).(StaticLibraryInfo).TransitiveStaticLibrariesForOrdering.ToList()
+ actual := ctx.ModuleProvider(moduleA, StaticLibraryInfoProvider).(StaticLibraryInfo).
+ TransitiveStaticLibrariesForOrdering.ToList().RelativeToTop()
expected := getOutputPaths(ctx, variant, []string{"a", "c", "b", "d"})
if !reflect.DeepEqual(actual, expected) {
@@ -2617,7 +2617,8 @@
variant := "android_arm64_armv8-a_static"
moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
- actual := ctx.ModuleProvider(moduleA, StaticLibraryInfoProvider).(StaticLibraryInfo).TransitiveStaticLibrariesForOrdering.ToList()
+ actual := ctx.ModuleProvider(moduleA, StaticLibraryInfoProvider).(StaticLibraryInfo).
+ TransitiveStaticLibrariesForOrdering.ToList().RelativeToTop()
expected := getOutputPaths(ctx, variant, []string{"a", "c", "b"})
if !reflect.DeepEqual(actual, expected) {
diff --git a/cc/gen_test.go b/cc/gen_test.go
index 41ef95c..40a5716 100644
--- a/cc/gen_test.go
+++ b/cc/gen_test.go
@@ -36,8 +36,10 @@
aidl := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("aidl")
libfoo := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Module().(*Module)
- if !inList("-I"+filepath.Dir(aidl.Output.String()), libfoo.flags.Local.CommonFlags) {
- t.Errorf("missing aidl includes in global flags")
+ expected := "-I" + filepath.Dir(aidl.Output.String())
+ actual := android.StringsRelativeToTop(ctx.Config(), libfoo.flags.Local.CommonFlags)
+ if !inList(expected, actual) {
+ t.Errorf("missing aidl includes in global flags, expected %q, actual %q", expected, actual)
}
})
@@ -61,7 +63,7 @@
aidlManifest := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Output("aidl.sbox.textproto")
libfoo := ctx.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Module().(*Module)
- if !inList("-I"+filepath.Dir(aidl.Output.String()), libfoo.flags.Local.CommonFlags) {
+ if !inList("-I"+filepath.Dir(aidl.Output.String()), android.StringsRelativeToTop(ctx.Config(), libfoo.flags.Local.CommonFlags)) {
t.Errorf("missing aidl includes in global flags")
}
diff --git a/cc/library.go b/cc/library.go
index 9bec974..28e4f61 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -2029,7 +2029,7 @@
return outputFile
}
-func Bp2BuildParseHeaderLibs(ctx android.TopDownMutatorContext, module *Module) bazel.LabelList {
+func Bp2BuildParseHeaderLibs(ctx android.TopDownMutatorContext, module *Module) bazel.LabelListAttribute {
var headerLibs []string
for _, linkerProps := range module.linker.linkerProps() {
if baseLinkerProps, ok := linkerProps.(*BaseLinkerProperties); ok {
@@ -2038,12 +2038,11 @@
break
}
}
-
- headerLibsLabels := android.BazelLabelForModuleDeps(ctx, headerLibs)
+ headerLibsLabels := bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, headerLibs))
return headerLibsLabels
}
-func Bp2BuildParseExportedIncludes(ctx android.TopDownMutatorContext, module *Module) (bazel.LabelList, bazel.LabelList) {
+func Bp2BuildParseExportedIncludes(ctx android.TopDownMutatorContext, module *Module) (bazel.LabelListAttribute, bazel.LabelListAttribute) {
libraryDecorator := module.linker.(*libraryDecorator)
includeDirs := libraryDecorator.flagExporter.Properties.Export_system_include_dirs
@@ -2059,17 +2058,16 @@
}
headersLabels := android.BazelLabelForModuleSrc(ctx, includeDirGlobs)
-
- return includeDirsLabels, headersLabels
+ return bazel.MakeLabelListAttribute(includeDirsLabels), bazel.MakeLabelListAttribute(headersLabels)
}
type bazelCcLibraryStaticAttributes struct {
Copts []string
- Srcs bazel.LabelList
- Deps bazel.LabelList
+ Srcs bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
Linkstatic bool
- Includes bazel.LabelList
- Hdrs bazel.LabelList
+ Includes bazel.LabelListAttribute
+ Hdrs bazel.LabelListAttribute
}
type bazelCcLibraryStatic struct {
@@ -2110,7 +2108,7 @@
break
}
}
- srcsLabels := android.BazelLabelForModuleSrc(ctx, srcs)
+ srcsLabels := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, srcs))
var staticLibs []string
var wholeStaticLibs []string
@@ -2135,18 +2133,18 @@
includesLabels := android.BazelLabelForModuleSrc(ctx, allIncludes)
exportedIncludesLabels, exportedIncludesHeadersLabels := Bp2BuildParseExportedIncludes(ctx, module)
- includesLabels.Append(exportedIncludesLabels)
+ includesLabels.Append(exportedIncludesLabels.Value)
headerLibsLabels := Bp2BuildParseHeaderLibs(ctx, module)
- depsLabels.Append(headerLibsLabels)
+ depsLabels.Append(headerLibsLabels.Value)
attrs := &bazelCcLibraryStaticAttributes{
Copts: copts,
- Srcs: bazel.UniqueBazelLabelList(srcsLabels),
- Deps: bazel.UniqueBazelLabelList(depsLabels),
+ Srcs: srcsLabels,
+ Deps: bazel.MakeLabelListAttribute(depsLabels),
Linkstatic: true,
- Includes: bazel.UniqueBazelLabelList(includesLabels),
- Hdrs: bazel.UniqueBazelLabelList(exportedIncludesHeadersLabels),
+ Includes: bazel.MakeLabelListAttribute(includesLabels),
+ Hdrs: exportedIncludesHeadersLabels,
}
props := bazel.BazelTargetModuleProperties{
diff --git a/cc/library_headers.go b/cc/library_headers.go
index 719d538..8286848 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -62,9 +62,9 @@
}
type bazelCcLibraryHeadersAttributes struct {
- Hdrs bazel.LabelList
- Includes bazel.LabelList
- Deps bazel.LabelList
+ Hdrs bazel.LabelListAttribute
+ Includes bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
}
type bazelCcLibraryHeaders struct {
diff --git a/cc/object.go b/cc/object.go
index 664be8d..abc3e83 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -103,8 +103,8 @@
// For bp2build conversion.
type bazelObjectAttributes struct {
- Srcs bazel.LabelList
- Deps bazel.LabelList
+ Srcs bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
Copts bazel.StringListAttribute
Local_include_dirs []string
}
@@ -147,14 +147,16 @@
// Set arch-specific configurable attributes
var copts bazel.StringListAttribute
- var srcs []string
- var excludeSrcs []string
+ var srcs bazel.LabelListAttribute
var localIncludeDirs []string
for _, props := range m.compiler.compilerProps() {
if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
copts.Value = baseCompilerProps.Cflags
- srcs = baseCompilerProps.Srcs
- excludeSrcs = baseCompilerProps.Exclude_srcs
+ srcs = bazel.MakeLabelListAttribute(
+ android.BazelLabelForModuleSrcExcludes(
+ ctx,
+ baseCompilerProps.Srcs,
+ baseCompilerProps.Exclude_srcs))
localIncludeDirs = baseCompilerProps.Local_include_dirs
break
}
@@ -164,22 +166,23 @@
localIncludeDirs = append(localIncludeDirs, ".")
}
- var deps bazel.LabelList
+ var deps bazel.LabelListAttribute
for _, props := range m.linker.linkerProps() {
if objectLinkerProps, ok := props.(*ObjectLinkerProperties); ok {
- deps = android.BazelLabelForModuleDeps(ctx, objectLinkerProps.Objs)
+ deps = bazel.MakeLabelListAttribute(
+ android.BazelLabelForModuleDeps(ctx, objectLinkerProps.Objs))
}
}
for arch, p := range m.GetArchProperties(&BaseCompilerProperties{}) {
if cProps, ok := p.(*BaseCompilerProperties); ok {
+ srcs.SetValueForArch(arch.Name, android.BazelLabelForModuleSrcExcludes(ctx, cProps.Srcs, cProps.Exclude_srcs))
copts.SetValueForArch(arch.Name, cProps.Cflags)
}
}
- copts.SetValueForArch("default", []string{})
attrs := &bazelObjectAttributes{
- Srcs: android.BazelLabelForModuleSrcExcludes(ctx, srcs, excludeSrcs),
+ Srcs: srcs,
Deps: deps,
Copts: copts,
Local_include_dirs: localIncludeDirs,
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 20274b2..f72371a 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -15,7 +15,6 @@
package cc
import (
- "path/filepath"
"testing"
"android/soong/android"
@@ -302,8 +301,7 @@
})
fooRule := ctx.ModuleForTests("foo", "linux_glibc_x86_64").Rule("Symlink")
- assertString(t, fooRule.Output.String(),
- filepath.Join(buildDir, ".intermediates/foo/linux_glibc_x86_64/foo"))
+ assertString(t, fooRule.Output.String(), "out/soong/.intermediates/foo/linux_glibc_x86_64/foo")
assertString(t, fooRule.Args["fromPath"], "$$PWD/linux_glibc_x86_64/bin/foo")
var libfooDep android.Path
@@ -313,8 +311,7 @@
break
}
}
- assertString(t, libfooDep.String(),
- filepath.Join(buildDir, ".intermediates/libfoo/linux_glibc_x86_64_shared/libfoo.so"))
+ assertString(t, libfooDep.String(), "out/soong/.intermediates/libfoo/linux_glibc_x86_64_shared/libfoo.so")
}
func TestPrebuiltLibrarySanitized(t *testing.T) {
diff --git a/cc/proto_test.go b/cc/proto_test.go
index f8bbd26..3d636fb 100644
--- a/cc/proto_test.go
+++ b/cc/proto_test.go
@@ -61,7 +61,7 @@
t.Errorf("expected %q in %q", w, cmd)
}
- foobarPath := foobar.Module().(android.HostToolProvider).HostToolPath().String()
+ foobarPath := foobar.Module().(android.HostToolProvider).HostToolPath().RelativeToPath().String()
if w := "--plugin=protoc-gen-foobar=" + foobarPath; !strings.Contains(cmd, w) {
t.Errorf("expected %q in %q", w, cmd)
diff --git a/cc/sanitize.go b/cc/sanitize.go
index cd09e6e..e1ac9f0 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -1129,6 +1129,9 @@
Bool(c.sanitize.Properties.Sanitize.Undefined) ||
Bool(c.sanitize.Properties.Sanitize.All_undefined) {
runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)
+ if c.staticBinary() {
+ runtimeLibrary += ".static"
+ }
}
if runtimeLibrary != "" && (toolchain.Bionic() || c.sanitize.Properties.UbsanRuntimeDep) {
diff --git a/cc/sdk_test.go b/cc/sdk_test.go
index 5a3c181..61925e3 100644
--- a/cc/sdk_test.go
+++ b/cc/sdk_test.go
@@ -66,6 +66,7 @@
} else {
toFile = m.outputFile.Path()
}
+ toFile = toFile.RelativeToTop()
rule := from.Description("link")
for _, dep := range rule.Implicits {
diff --git a/cc/stl.go b/cc/stl.go
index 75fab17..594231d 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -188,12 +188,7 @@
if needsLibAndroidSupport(ctx) {
deps.StaticLibs = append(deps.StaticLibs, "ndk_libandroid_support")
}
- // TODO: Switch the NDK over to the LLVM unwinder for non-arm32 architectures.
- if ctx.Arch().ArchType == android.Arm {
- deps.StaticLibs = append(deps.StaticLibs, "ndk_libunwind")
- } else {
- deps.StaticLibs = append(deps.StaticLibs, "libgcc_stripped")
- }
+ deps.StaticLibs = append(deps.StaticLibs, "ndk_libunwind")
default:
panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl))
}
diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go
index d341b8c..d9116b0 100644
--- a/cmd/pom2bp/pom2bp.go
+++ b/cmd/pom2bp/pom2bp.go
@@ -144,6 +144,7 @@
var hostAndDeviceModuleNames = HostAndDeviceModuleNames{}
var sdkVersion string
+var defaultMinSdkVersion string
var useVersion string
var staticDeps bool
var jetifier bool
@@ -286,6 +287,10 @@
return sdkVersion
}
+func (p Pom) DefaultMinSdkVersion() string {
+ return defaultMinSdkVersion
+}
+
func (p Pom) Jetifier() bool {
return jetifier
}
@@ -457,7 +462,7 @@
min_sdk_version: "{{.MinSdkVersion}}",
manifest: "manifests/{{.BpName}}/AndroidManifest.xml",
{{- else if not .IsHostOnly}}
- min_sdk_version: "24",
+ min_sdk_version: "{{.DefaultMinSdkVersion}}",
{{- end}}
{{- end}}
static_libs: [
@@ -598,6 +603,8 @@
This may be specified multiple times to declare these dependencies.
-sdk-version <version>
Sets sdk_version: "<version>" for all modules.
+ -default-min-sdk-version
+ The default min_sdk_version to use for a module if one cannot be mined from AndroidManifest.xml
-use-version <version>
If the maven directory contains multiple versions of artifacts and their pom files,
-use-version can be used to only write Android.bp files for a specific version of those artifacts.
@@ -622,6 +629,7 @@
flag.Var(&hostModuleNames, "host", "Specifies that the corresponding module (specified in the form 'module.group:module.artifact') is a host module")
flag.Var(&hostAndDeviceModuleNames, "host-and-device", "Specifies that the corresponding module (specified in the form 'module.group:module.artifact') is both a host and device module.")
flag.StringVar(&sdkVersion, "sdk-version", "", "What to write to sdk_version")
+ flag.StringVar(&defaultMinSdkVersion, "default-min-sdk-version", "24", "Default min_sdk_version to use, if one is not available from AndroidManifest.xml. Default: 24")
flag.StringVar(&useVersion, "use-version", "", "Only read artifacts of a specific version")
flag.BoolVar(&staticDeps, "static-deps", false, "Statically include direct dependencies")
flag.BoolVar(&jetifier, "jetifier", false, "Sets jetifier: true on all modules")
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 4999bc7..81a63b0 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -259,35 +259,53 @@
Implicits(clcHost).
Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(clcTarget, ":") + "]")
- } else if module.EnforceUsesLibraries {
- // Generate command that saves target SDK version in a shell variable.
- manifestOrApk := module.ManifestPath
- if manifestOrApk == nil {
- // No manifest to extract targetSdkVersion from, hope that dexjar is an APK.
+ } else {
+ // There are three categories of Java modules handled here:
+ //
+ // - Modules that have passed verify_uses_libraries check. They are AOT-compiled and
+ // expected to be loaded on device without CLC mismatch errors.
+ //
+ // - Modules that have failed the check in relaxed mode, so it didn't cause a build error.
+ // They are dexpreopted with "verify" filter and not AOT-compiled.
+ // TODO(b/132357300): ensure that CLC mismatch errors are ignored with "verify" filter.
+ //
+ // - Modules that didn't run the check. They are AOT-compiled, but it's unknown if they
+ // will have CLC mismatch errors on device (the check is disabled by default).
+ //
+ // TODO(b/132357300): enable the check by default and eliminate the last category, so that
+ // no time/space is wasted on AOT-compiling modules that will fail CLC check on device.
+
+ var manifestOrApk android.Path
+ if module.ManifestPath != nil {
+ // Ok, there is an XML manifest.
+ manifestOrApk = module.ManifestPath
+ } else if filepath.Ext(base) == ".apk" {
+ // Ok, there is is an APK with the manifest inside.
manifestOrApk = module.DexPath
}
- rule.Command().Text(`target_sdk_version="$(`).
- Tool(globalSoong.ManifestCheck).
- Flag("--extract-target-sdk-version").
- Input(manifestOrApk).
- FlagWithInput("--aapt ", ctx.Config().HostToolPath(ctx, "aapt")).
- Text(`)"`)
+
+ // Generate command that saves target SDK version in a shell variable.
+ if manifestOrApk == nil {
+ // There is neither an XML manifest nor APK => nowhere to extract targetSdkVersion from.
+ // Set the latest ("any") version: then construct_context will not add any compatibility
+ // libraries (if this is incorrect, there will be a CLC mismatch and dexopt on device).
+ rule.Command().Textf(`target_sdk_version=%d`, AnySdkVersion)
+ } else {
+ rule.Command().Text(`target_sdk_version="$(`).
+ Tool(globalSoong.ManifestCheck).
+ Flag("--extract-target-sdk-version").
+ Input(manifestOrApk).
+ FlagWithInput("--aapt ", globalSoong.Aapt).
+ Text(`)"`)
+ }
// Generate command that saves host and target class loader context in shell variables.
clc, paths := ComputeClassLoaderContext(module.ClassLoaderContexts)
rule.Command().
- Text("if ! test -s ").Input(module.EnforceUsesLibrariesStatusFile).
- Text(` ; then eval "$(`).Tool(globalSoong.ConstructContext).
+ Text(`eval "$(`).Tool(globalSoong.ConstructContext).
Text(` --target-sdk-version ${target_sdk_version}`).
Text(clc).Implicits(paths).
- Text(`)" ; fi`)
-
- } else {
- // Other libraries or APKs for which the exact <uses-library> list is unknown.
- // We assume the class loader context is empty.
- rule.Command().
- Text(`class_loader_context_arg=--class-loader-context=PCL[]`).
- Text(`stored_class_loader_context_arg=""`)
+ Text(`)"`)
}
// Devices that do not have a product partition use a symlink from /product to /system/product.
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 9019a83..5d438ea 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -798,9 +798,9 @@
}
type bazelGenruleAttributes struct {
- Srcs bazel.LabelList
+ Srcs bazel.LabelListAttribute
Outs []string
- Tools bazel.LabelList
+ Tools bazel.LabelListAttribute
Cmd string
}
@@ -828,15 +828,16 @@
}
// Bazel only has the "tools" attribute.
- tools := android.BazelLabelForModuleDeps(ctx, m.properties.Tools)
- tool_files := android.BazelLabelForModuleSrc(ctx, m.properties.Tool_files)
- tools.Append(tool_files)
+ tools_prop := android.BazelLabelForModuleDeps(ctx, m.properties.Tools)
+ tool_files_prop := android.BazelLabelForModuleSrc(ctx, m.properties.Tool_files)
+ tools_prop.Append(tool_files_prop)
- srcs := android.BazelLabelForModuleSrc(ctx, m.properties.Srcs)
+ tools := bazel.MakeLabelListAttribute(tools_prop)
+ srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Srcs))
var allReplacements bazel.LabelList
- allReplacements.Append(tools)
- allReplacements.Append(srcs)
+ allReplacements.Append(tools.Value)
+ allReplacements.Append(srcs.Value)
// Replace in and out variables with $< and $@
var cmd string
@@ -844,9 +845,9 @@
cmd = strings.Replace(*m.properties.Cmd, "$(in)", "$(SRCS)", -1)
cmd = strings.Replace(cmd, "$(out)", "$(OUTS)", -1)
cmd = strings.Replace(cmd, "$(genDir)", "$(GENDIR)", -1)
- if len(tools.Includes) > 0 {
- cmd = strings.Replace(cmd, "$(location)", fmt.Sprintf("$(location %s)", tools.Includes[0].Label), -1)
- cmd = strings.Replace(cmd, "$(locations)", fmt.Sprintf("$(locations %s)", tools.Includes[0].Label), -1)
+ if len(tools.Value.Includes) > 0 {
+ cmd = strings.Replace(cmd, "$(location)", fmt.Sprintf("$(location %s)", tools.Value.Includes[0].Label), -1)
+ cmd = strings.Replace(cmd, "$(locations)", fmt.Sprintf("$(locations %s)", tools.Value.Includes[0].Label), -1)
}
for _, l := range allReplacements.Includes {
bpLoc := fmt.Sprintf("$(location %s)", l.Bp_text)
diff --git a/java/app.go b/java/app.go
index 1b6e0e3..b849b98 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1294,7 +1294,8 @@
// check is not necessary, and although it is good to have, it is difficult to maintain on
// non-linux build platforms where dexpreopt is generally disabled (the check may fail due to
// various unrelated reasons, such as a failure to get manifest from an APK).
- if dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
+ global := dexpreopt.GetGlobalConfig(ctx)
+ if global.DisablePreopt || global.OnlyPreoptBootImageAndSystemServer {
return inputFile
}
diff --git a/java/boot_image.go b/java/boot_image.go
index a14940d..0c47976 100644
--- a/java/boot_image.go
+++ b/java/boot_image.go
@@ -20,6 +20,7 @@
"android/soong/android"
"android/soong/dexpreopt"
+ "github.com/google/blueprint/proptools"
"github.com/google/blueprint"
)
@@ -27,24 +28,62 @@
func init() {
RegisterBootImageBuildComponents(android.InitRegistrationContext)
+ // TODO(b/177892522): Remove after has been replaced by bootclasspath_fragments
android.RegisterSdkMemberType(&bootImageMemberType{
SdkMemberTypeBase: android.SdkMemberTypeBase{
PropertyName: "boot_images",
SupportsSdk: true,
},
})
+
+ android.RegisterSdkMemberType(&bootImageMemberType{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
+ PropertyName: "bootclasspath_fragments",
+ SupportsSdk: true,
+ },
+ })
}
func RegisterBootImageBuildComponents(ctx android.RegistrationContext) {
+ // TODO(b/177892522): Remove after has been replaced by bootclasspath_fragment
ctx.RegisterModuleType("boot_image", bootImageFactory)
ctx.RegisterModuleType("prebuilt_boot_image", prebuiltBootImageFactory)
+
+ ctx.RegisterModuleType("bootclasspath_fragment", bootImageFactory)
+ ctx.RegisterModuleType("prebuilt_bootclasspath_fragment", prebuiltBootImageFactory)
+}
+
+type bootImageContentDependencyTag struct {
+ blueprint.BaseDependencyTag
+}
+
+// Avoid having to make boot image content visible to the boot image.
+//
+// This is a temporary workaround to make it easier to migrate to boot image modules with proper
+// dependencies.
+// TODO(b/177892522): Remove this and add needed visibility.
+func (b bootImageContentDependencyTag) ExcludeFromVisibilityEnforcement() {
+}
+
+// The tag used for the dependency between the boot image module and its contents.
+var bootImageContentDepTag = bootImageContentDependencyTag{}
+
+var _ android.ExcludeFromVisibilityEnforcementTag = bootImageContentDepTag
+
+func IsbootImageContentDepTag(tag blueprint.DependencyTag) bool {
+ return tag == bootImageContentDepTag
}
type bootImageProperties struct {
// The name of the image this represents.
//
- // Must be one of "art" or "boot".
- Image_name string
+ // If specified then it must be one of "art" or "boot".
+ Image_name *string
+
+ // The contents of this boot image, could be either java_library, java_sdk_library, or boot_image.
+ //
+ // The order of this list matters as it is the order that is used in the bootclasspath.
+ Contents []string
}
type BootImageModule struct {
@@ -60,9 +99,59 @@
android.InitApexModule(m)
android.InitSdkAwareModule(m)
android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
+
+ // Perform some consistency checking to ensure that the configuration is correct.
+ android.AddLoadHook(m, func(ctx android.LoadHookContext) {
+ bootImageConsistencyCheck(ctx, m)
+ })
return m
}
+func bootImageConsistencyCheck(ctx android.EarlyModuleContext, m *BootImageModule) {
+ contents := m.properties.Contents
+ if m.properties.Image_name == nil && len(contents) == 0 {
+ ctx.ModuleErrorf(`neither of the "image_name" and "contents" properties have been supplied, please supply exactly one`)
+ }
+ if m.properties.Image_name != nil && len(contents) != 0 {
+ ctx.ModuleErrorf(`both of the "image_name" and "contents" properties have been supplied, please supply exactly one`)
+ }
+ imageName := proptools.String(m.properties.Image_name)
+ if imageName == "art" {
+ // Get the configuration for the art apex jars. Do not use getImageConfig(ctx) here as this is
+ // too early in the Soong processing for that to work.
+ global := dexpreopt.GetGlobalConfig(ctx)
+ modules := global.ArtApexJars
+
+ // Make sure that the apex specified in the configuration is consistent and is one for which
+ // this boot image is available.
+ jars := []string{}
+ commonApex := ""
+ for i := 0; i < modules.Len(); i++ {
+ apex := modules.Apex(i)
+ jar := modules.Jar(i)
+ if apex == "platform" {
+ ctx.ModuleErrorf("ArtApexJars is invalid as it requests a platform variant of %q", jar)
+ continue
+ }
+ if !m.AvailableFor(apex) {
+ ctx.ModuleErrorf("incompatible with ArtApexJars which expects this to be in apex %q but this is only in apexes %q",
+ apex, m.ApexAvailable())
+ continue
+ }
+ if commonApex == "" {
+ commonApex = apex
+ } else if commonApex != apex {
+ ctx.ModuleErrorf("ArtApexJars configuration is inconsistent, expected all jars to be in the same apex but it specifies apex %q and %q",
+ commonApex, apex)
+ }
+ jars = append(jars, jar)
+ }
+
+ // Store the jars in the Contents property so that they can be used to add dependencies.
+ m.properties.Contents = jars
+ }
+}
+
var BootImageInfoProvider = blueprint.NewProvider(BootImageInfo{})
type BootImageInfo struct {
@@ -96,6 +185,10 @@
func (b *BootImageModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
tag := ctx.OtherModuleDependencyTag(dep)
+ if tag == bootImageContentDepTag {
+ // Boot image contents are automatically added to apex.
+ return true
+ }
if android.IsMetaDependencyTag(tag) {
// Cross-cutting metadata dependencies are metadata.
return false
@@ -108,6 +201,8 @@
}
func (b *BootImageModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ ctx.AddDependency(ctx.Module(), bootImageContentDepTag, b.properties.Contents...)
+
if SkipDexpreoptBootJars(ctx) {
return
}
@@ -127,14 +222,8 @@
// GenerateSingletonBuildActions method as it cannot create it for itself.
dexpreopt.GetGlobalSoongConfig(ctx)
- // Get a map of the image configs that are supported.
- imageConfigs := genBootImageConfigs(ctx)
-
- // Retrieve the config for this image.
- imageName := b.properties.Image_name
- imageConfig := imageConfigs[imageName]
+ imageConfig := b.getImageConfig(ctx)
if imageConfig == nil {
- ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedStringKeys(imageConfigs), ", "))
return
}
@@ -145,6 +234,25 @@
ctx.SetProvider(BootImageInfoProvider, info)
}
+func (b *BootImageModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
+ // Get a map of the image configs that are supported.
+ imageConfigs := genBootImageConfigs(ctx)
+
+ // Retrieve the config for this image.
+ imageNamePtr := b.properties.Image_name
+ if imageNamePtr == nil {
+ return nil
+ }
+
+ imageName := *imageNamePtr
+ imageConfig := imageConfigs[imageName]
+ if imageConfig == nil {
+ ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedStringKeys(imageConfigs), ", "))
+ return nil
+ }
+ return imageConfig
+}
+
type bootImageMemberType struct {
android.SdkMemberTypeBase
}
@@ -159,7 +267,11 @@
}
func (b *bootImageMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
- return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_boot_image")
+ if b.PropertyName == "boot_images" {
+ return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_boot_image")
+ } else {
+ return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_bootclasspath_fragment")
+ }
}
func (b *bootImageMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
@@ -169,7 +281,7 @@
type bootImageSdkMemberProperties struct {
android.SdkMemberPropertiesBase
- Image_name string
+ Image_name *string
}
func (b *bootImageSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
@@ -179,8 +291,8 @@
}
func (b *bootImageSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
- if b.Image_name != "" {
- propertySet.AddProperty("image_name", b.Image_name)
+ if b.Image_name != nil {
+ propertySet.AddProperty("image_name", *b.Image_name)
}
}
@@ -213,5 +325,10 @@
android.InitApexModule(m)
android.InitSdkAwareModule(m)
android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibCommon)
+
+ // Perform some consistency checking to ensure that the configuration is correct.
+ android.AddLoadHook(m, func(ctx android.LoadHookContext) {
+ bootImageConsistencyCheck(ctx, &m.BootImageModule)
+ })
return m
}
diff --git a/java/boot_image_test.go b/java/boot_image_test.go
index 65e590d..e1866de 100644
--- a/java/boot_image_test.go
+++ b/java/boot_image_test.go
@@ -16,25 +16,112 @@
import (
"testing"
+
+ "android/soong/android"
+ "android/soong/dexpreopt"
)
// Contains some simple tests for boot_image logic, additional tests can be found in
// apex/boot_image_test.go as the ART boot image requires modules from the ART apex.
+var prepareForTestWithBootImage = android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ dexpreopt.PrepareForTestByEnablingDexpreopt,
+)
+
func TestUnknownBootImage(t *testing.T) {
- testJavaError(t, "image_name: Unknown image name \\\"unknown\\\", expected one of art, boot", `
- boot_image {
- name: "unknown-boot-image",
- image_name: "unknown",
- }
-`)
+ prepareForTestWithBootImage.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `\Qimage_name: Unknown image name "unknown", expected one of art, boot\E`)).
+ RunTestWithBp(t, `
+ boot_image {
+ name: "unknown-boot-image",
+ image_name: "unknown",
+ }
+ `)
+}
+
+func TestUnknownBootclasspathFragmentImageName(t *testing.T) {
+ prepareForTestWithBootImage.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `\Qimage_name: Unknown image name "unknown", expected one of art, boot\E`)).
+ RunTestWithBp(t, `
+ bootclasspath_fragment {
+ name: "unknown-boot-image",
+ image_name: "unknown",
+ }
+ `)
}
func TestUnknownPrebuiltBootImage(t *testing.T) {
- testJavaError(t, "image_name: Unknown image name \\\"unknown\\\", expected one of art, boot", `
- prebuilt_boot_image {
- name: "unknown-boot-image",
- image_name: "unknown",
- }
-`)
+ prepareForTestWithBootImage.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `\Qimage_name: Unknown image name "unknown", expected one of art, boot\E`)).
+ RunTestWithBp(t, `
+ prebuilt_boot_image {
+ name: "unknown-boot-image",
+ image_name: "unknown",
+ }
+ `)
+}
+
+func TestBootImageInconsistentArtConfiguration_Platform(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForTestWithBootImage,
+ dexpreopt.FixtureSetArtBootJars("platform:foo", "apex:bar"),
+ ).
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `\QArtApexJars is invalid as it requests a platform variant of "foo"\E`)).
+ RunTestWithBp(t, `
+ boot_image {
+ name: "boot-image",
+ image_name: "art",
+ apex_available: [
+ "apex",
+ ],
+ }
+ `)
+}
+
+func TestBootImageInconsistentArtConfiguration_ApexMixture(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForTestWithBootImage,
+ dexpreopt.FixtureSetArtBootJars("apex1:foo", "apex2:bar"),
+ ).
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `\QArtApexJars configuration is inconsistent, expected all jars to be in the same apex but it specifies apex "apex1" and "apex2"\E`)).
+ RunTestWithBp(t, `
+ boot_image {
+ name: "boot-image",
+ image_name: "art",
+ apex_available: [
+ "apex1",
+ "apex2",
+ ],
+ }
+ `)
+}
+
+func TestBootImageWithoutImageNameOrContents(t *testing.T) {
+ prepareForTestWithBootImage.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `\Qneither of the "image_name" and "contents" properties\E`)).
+ RunTestWithBp(t, `
+ boot_image {
+ name: "boot-image",
+ }
+ `)
+}
+
+func TestBootImageWithImageNameAndContents(t *testing.T) {
+ prepareForTestWithBootImage.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `\Qboth of the "image_name" and "contents" properties\E`)).
+ RunTestWithBp(t, `
+ boot_image {
+ name: "boot-image",
+ image_name: "boot",
+ contents: ["other"],
+ }
+ `)
}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index a8e2b0e..f7595b1 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -226,11 +226,8 @@
srcJars android.Paths
srcFiles android.Paths
sourcepaths android.Paths
- argFiles android.Paths
implicits android.Paths
- args []string
-
docZip android.WritablePath
stubsSrcJar android.WritablePath
}
@@ -480,15 +477,20 @@
j.sourcepaths = android.PathsForModuleSrc(ctx, []string{"."})
}
- j.argFiles = android.PathsForModuleSrc(ctx, j.properties.Arg_files)
+ return deps
+}
+
+func (j *Javadoc) expandArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
+ var argFiles android.Paths
argFilesMap := map[string]string{}
argFileLabels := []string{}
for _, label := range j.properties.Arg_files {
var paths = android.PathsForModuleSrc(ctx, []string{label})
if _, exists := argFilesMap[label]; !exists {
- argFilesMap[label] = strings.Join(paths.Strings(), " ")
+ argFilesMap[label] = strings.Join(cmd.PathsForInputs(paths), " ")
argFileLabels = append(argFileLabels, label)
+ argFiles = append(argFiles, paths...)
} else {
ctx.ModuleErrorf("multiple arg_files for %q, %q and %q",
label, argFilesMap[label], paths)
@@ -508,7 +510,7 @@
}
for _, flag := range flags {
- args, err := android.Expand(flag, func(name string) (string, error) {
+ expanded, err := android.Expand(flag, func(name string) (string, error) {
if strings.HasPrefix(name, "location ") {
label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
if paths, ok := argFilesMap[label]; ok {
@@ -526,10 +528,10 @@
if err != nil {
ctx.PropertyErrorf(argsPropertyName, "%s", err.Error())
}
- j.args = append(j.args, args)
+ cmd.Flag(expanded)
}
- return deps
+ cmd.Implicits(argFiles)
}
func (j *Javadoc) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -563,6 +565,8 @@
Flag("-XDignore.symbol.file").
Flag("-Xdoclint:none")
+ j.expandArgs(ctx, cmd)
+
rule.Command().
BuiltTool("soong_zip").
Flag("-write_if_changed").
@@ -821,7 +825,7 @@
deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths)
}
- cmd.Flag(strings.Join(d.Javadoc.args, " ")).Implicits(d.Javadoc.argFiles)
+ d.expandArgs(ctx, cmd)
if d.properties.Compat_config != nil {
compatConfig := android.PathForModuleSrc(ctx, String(d.properties.Compat_config))
diff --git a/java/droidstubs.go b/java/droidstubs.go
index e453e62..be4d8f8 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -284,7 +284,7 @@
cmd.Flag("--include-annotations")
validatingNullability :=
- android.InList("--validate-nullability-from-merged-stubs", d.Javadoc.args) ||
+ strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
String(d.properties.Validate_nullability_from_list) != ""
migratingNullability := String(d.properties.Previous_api) != ""
@@ -360,7 +360,16 @@
ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
if t, ok := m.(*ExportedDroiddocDir); ok {
for _, dep := range t.deps {
- if strings.HasSuffix(dep.String(), filename) {
+ if dep.Base() == filename {
+ cmd.Implicit(dep)
+ }
+ if filename != "android.jar" && dep.Base() == "android.jar" {
+ // Metalava implicitly searches these patterns:
+ // prebuilts/tools/common/api-versions/android-%/android.jar
+ // prebuilts/sdk/%/public/android.jar
+ // Add android.jar files from the api_levels_annotations_dirs directories to try
+ // to satisfy these patterns. If Metalava can't find a match for an API level
+ // between 1 and 28 in at least one pattern it will fail.
cmd.Implicit(dep)
}
}
@@ -509,14 +518,8 @@
d.inclusionAnnotationsFlags(ctx, cmd)
d.apiLevelsAnnotationsFlags(ctx, cmd)
- if android.InList("--generate-documentation", d.Javadoc.args) {
- // Currently Metalava have the ability to invoke Javadoc in a separate process.
- // Pass "-nodocs" to suppress the Javadoc invocation when Metalava receives
- // "--generate-documentation" arg. This is not needed when Metalava removes this feature.
- d.Javadoc.args = append(d.Javadoc.args, "-nodocs")
- }
+ d.expandArgs(ctx, cmd)
- cmd.Flag(strings.Join(d.Javadoc.args, " ")).Implicits(d.Javadoc.argFiles)
for _, o := range d.Javadoc.properties.Out {
cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
}
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index c6db979..6ad9323 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -81,10 +81,19 @@
func TestDroidstubsSandbox(t *testing.T) {
ctx, _ := testJavaWithFS(t, `
+ genrule {
+ name: "foo",
+ out: ["foo.txt"],
+ cmd: "touch $(out)",
+ }
+
droidstubs {
name: "bar-stubs",
srcs: ["bar-doc/a.java"],
sandbox: true,
+
+ args: "--reference $(location :foo)",
+ arg_files: [":foo"],
}
`,
map[string][]byte{
@@ -96,6 +105,11 @@
if g, w := metalava.Inputs.Strings(), []string{"bar-doc/a.java"}; !reflect.DeepEqual(w, g) {
t.Errorf("Expected inputs %q, got %q", w, g)
}
+
+ manifest := android.RuleBuilderSboxProtoForTests(t, m.Output("metalava.sbox.textproto"))
+ if g, w := manifest.Commands[0].GetCommand(), "reference __SBOX_SANDBOX_DIR__/out/.intermediates/foo/gen/foo.txt"; !strings.Contains(g, w) {
+ t.Errorf("Expected command to contain %q, got %q", w, g)
+ }
}
func TestDroidstubsWithSystemModules(t *testing.T) {
diff --git a/java/java_test.go b/java/java_test.go
index 2ade0fe..1d1a796 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1670,7 +1670,7 @@
// The bar library should depend on the stubs jar.
barLibrary := result.ModuleForTests("bar", "android_common").Rule("javac")
- if expected, actual := `^-classpath .*:/[^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ if expected, actual := `^-classpath .*:out/soong/[^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected %q, found %#q", expected, actual)
}
}
@@ -1973,7 +1973,7 @@
`)
// The baz library should depend on the system stubs jar.
bazLibrary := result.ModuleForTests("baz", "android_common").Rule("javac")
- if expected, actual := `^-classpath .*:/[^:]*/turbine-combined/foo\.stubs.system\.jar$`, bazLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ if expected, actual := `^-classpath .*:out/soong/[^:]*/turbine-combined/foo\.stubs.system\.jar$`, bazLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
t.Errorf("expected %q, found %#q", expected, actual)
}
}
diff --git a/java/system_modules_test.go b/java/system_modules_test.go
index 7d8935a..120bbf7 100644
--- a/java/system_modules_test.go
+++ b/java/system_modules_test.go
@@ -20,12 +20,12 @@
"android/soong/android"
)
-func getModuleHeaderJarsAsNormalizedPaths(result *android.TestResult, moduleNames ...string) []string {
+func getModuleHeaderJarsAsRelativeToTopPaths(result *android.TestResult, moduleNames ...string) []string {
paths := []string{}
for _, moduleName := range moduleNames {
module := result.Module(moduleName, "android_common")
info := result.ModuleProvider(module, JavaInfoProvider).(JavaInfo)
- paths = append(paths, result.NormalizePathsForTesting(info.HeaderJars)...)
+ paths = append(paths, info.HeaderJars.RelativeToTop().Strings()...)
}
return paths
}
@@ -57,8 +57,8 @@
sourceInputs := sourceSystemModules.Rule("jarsTosystemModules").Inputs
// The expected paths are the header jars from the source input modules.
- expectedSourcePaths := getModuleHeaderJarsAsNormalizedPaths(result, "system-module1", "system-module2")
- android.AssertArrayString(t, "source system modules inputs", expectedSourcePaths, result.NormalizePathsForTesting(sourceInputs))
+ expectedSourcePaths := getModuleHeaderJarsAsRelativeToTopPaths(result, "system-module1", "system-module2")
+ android.AssertArrayString(t, "source system modules inputs", expectedSourcePaths, sourceInputs.RelativeToTop().Strings())
}
var addPrebuiltSystemModules = android.FixtureAddTextFile("prebuilts/Android.bp", `
@@ -84,8 +84,8 @@
prebuiltInputs := prebuiltSystemModules.Rule("jarsTosystemModules").Inputs
// The expected paths are the header jars from the renamed prebuilt input modules.
- expectedPrebuiltPaths := getModuleHeaderJarsAsNormalizedPaths(result, "system-module1", "system-module2")
- android.AssertArrayString(t, "renamed prebuilt system modules inputs", expectedPrebuiltPaths, result.NormalizePathsForTesting(prebuiltInputs))
+ expectedPrebuiltPaths := getModuleHeaderJarsAsRelativeToTopPaths(result, "system-module1", "system-module2")
+ android.AssertArrayString(t, "renamed prebuilt system modules inputs", expectedPrebuiltPaths, prebuiltInputs.RelativeToTop().Strings())
}
func TestJavaSystemModulesMixSourceAndPrebuilt(t *testing.T) {
@@ -99,14 +99,14 @@
sourceInputs := sourceSystemModules.Rule("jarsTosystemModules").Inputs
// The expected paths are the header jars from the source input modules.
- expectedSourcePaths := getModuleHeaderJarsAsNormalizedPaths(result, "system-module1", "system-module2")
- android.AssertArrayString(t, "source system modules inputs", expectedSourcePaths, result.NormalizePathsForTesting(sourceInputs))
+ expectedSourcePaths := getModuleHeaderJarsAsRelativeToTopPaths(result, "system-module1", "system-module2")
+ android.AssertArrayString(t, "source system modules inputs", expectedSourcePaths, sourceInputs.RelativeToTop().Strings())
// check the existence of the renamed prebuilt module
prebuiltSystemModules := result.ModuleForTests("prebuilt_system-modules", "android_common")
prebuiltInputs := prebuiltSystemModules.Rule("jarsTosystemModules").Inputs
// The expected paths are the header jars from the renamed prebuilt input modules.
- expectedPrebuiltPaths := getModuleHeaderJarsAsNormalizedPaths(result, "prebuilt_system-module1", "prebuilt_system-module2")
- android.AssertArrayString(t, "prebuilt system modules inputs", expectedPrebuiltPaths, result.NormalizePathsForTesting(prebuiltInputs))
+ expectedPrebuiltPaths := getModuleHeaderJarsAsRelativeToTopPaths(result, "prebuilt_system-module1", "prebuilt_system-module2")
+ android.AssertArrayString(t, "prebuilt system modules inputs", expectedPrebuiltPaths, prebuiltInputs.RelativeToTop().Strings())
}
diff --git a/kernel/prebuilt_kernel_modules.go b/kernel/prebuilt_kernel_modules.go
index 14ac021..5bcca04 100644
--- a/kernel/prebuilt_kernel_modules.go
+++ b/kernel/prebuilt_kernel_modules.go
@@ -27,8 +27,12 @@
)
func init() {
- android.RegisterModuleType("prebuilt_kernel_modules", prebuiltKernelModulesFactory)
pctx.Import("android/soong/cc/config")
+ registerKernelBuildComponents(android.InitRegistrationContext)
+}
+
+func registerKernelBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("prebuilt_kernel_modules", prebuiltKernelModulesFactory)
}
type prebuiltKernelModules struct {
diff --git a/kernel/prebuilt_kernel_modules_test.go b/kernel/prebuilt_kernel_modules_test.go
index 433548b..90b9886 100644
--- a/kernel/prebuilt_kernel_modules_test.go
+++ b/kernel/prebuilt_kernel_modules_test.go
@@ -15,73 +15,29 @@
package kernel
import (
- "io/ioutil"
"os"
- "reflect"
- "strings"
"testing"
"android/soong/android"
"android/soong/cc"
)
-func testKernelModules(t *testing.T, bp string, fs map[string][]byte) (*android.TestContext, android.Config) {
- bp = bp + `
- cc_binary_host {
- name: "depmod",
- srcs: ["depmod.cpp"],
- stl: "none",
- static_executable: true,
- system_shared_libs: [],
- }
- `
- bp = bp + cc.GatherRequiredDepsForTest(android.Android)
-
- fs["depmod.cpp"] = nil
- cc.GatherRequiredFilesForTest(fs)
-
- config := android.TestArchConfig(buildDir, nil, bp, fs)
-
- ctx := android.NewTestArchContext(config)
- ctx.RegisterModuleType("prebuilt_kernel_modules", prebuiltKernelModulesFactory)
- ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
- cc.RegisterRequiredBuildComponentsForTest(ctx)
-
- ctx.Register()
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
-
- return ctx, config
-}
-
-func ensureListContains(t *testing.T, result []string, expected string) {
- t.Helper()
- if !android.InList(expected, result) {
- t.Errorf("%q is not found in %v", expected, result)
- }
-}
-
-func ensureContains(t *testing.T, result string, expected string) {
- t.Helper()
- if !strings.Contains(result, expected) {
- t.Errorf("%q is not found in %q", expected, result)
- }
-}
-
func TestKernelModulesFilelist(t *testing.T) {
- ctx, _ := testKernelModules(t, `
+ ctx := android.GroupFixturePreparers(
+ cc.PrepareForTestWithCcDefaultModules,
+ android.FixtureRegisterWithContext(registerKernelBuildComponents),
+ android.MockFS{
+ "depmod.cpp": nil,
+ "mod1.ko": nil,
+ "mod2.ko": nil,
+ }.AddToFixture(),
+ ).RunTestWithBp(t, `
prebuilt_kernel_modules {
name: "foo",
srcs: ["*.ko"],
kernel_version: "5.10",
}
- `,
- map[string][]byte{
- "mod1.ko": nil,
- "mod2.ko": nil,
- })
+ `)
expected := []string{
"lib/modules/5.10/mod1.ko",
@@ -98,32 +54,9 @@
}
actual = android.SortedUniqueStrings(actual)
expected = android.SortedUniqueStrings(expected)
- if !reflect.DeepEqual(actual, expected) {
- t.Errorf("\ngot: %v\nexpected: %v\n", actual, expected)
- }
-}
-
-var buildDir string
-
-func setUp() {
- var err error
- buildDir, err = ioutil.TempDir("", "soong_kernel_test")
- if err != nil {
- panic(err)
- }
-}
-
-func tearDown() {
- os.RemoveAll(buildDir)
+ android.AssertDeepEquals(t, "foo packaging specs", expected, actual)
}
func TestMain(m *testing.M) {
- run := func() int {
- setUp()
- defer tearDown()
-
- return m.Run()
- }
-
- os.Exit(run())
+ os.Exit(m.Run())
}
diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go
index ff548e5..da80a47 100644
--- a/linkerconfig/linkerconfig.go
+++ b/linkerconfig/linkerconfig.go
@@ -27,7 +27,11 @@
func init() {
pctx.HostBinToolVariable("conv_linker_config", "conv_linker_config")
- android.RegisterModuleType("linker_config", linkerConfigFactory)
+ registerLinkerConfigBuildComponent(android.InitRegistrationContext)
+}
+
+func registerLinkerConfigBuildComponent(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("linker_config", linkerConfigFactory)
}
type linkerConfigProperties struct {
diff --git a/linkerconfig/linkerconfig_test.go b/linkerconfig/linkerconfig_test.go
index 8eed4b5..939e4bb 100644
--- a/linkerconfig/linkerconfig_test.go
+++ b/linkerconfig/linkerconfig_test.go
@@ -15,65 +15,29 @@
package linkerconfig
import (
- "android/soong/android"
- "io/ioutil"
"os"
"reflect"
"testing"
+
+ "android/soong/android"
)
-var buildDir string
-
-func setUp() {
- var err error
- buildDir, err = ioutil.TempDir("", "soong_etc_test")
- if err != nil {
- panic(err)
- }
-}
-
-func tearDown() {
- os.RemoveAll(buildDir)
-}
-
func TestMain(m *testing.M) {
- run := func() int {
- setUp()
- defer tearDown()
-
- return m.Run()
- }
-
- os.Exit(run())
+ os.Exit(m.Run())
}
-func testContext(t *testing.T, bp string) *android.TestContext {
- t.Helper()
-
- fs := map[string][]byte{
- "linker.config.json": nil,
- }
-
- config := android.TestArchConfig(buildDir, nil, bp, fs)
-
- ctx := android.NewTestArchContext(config)
- ctx.RegisterModuleType("linker_config", linkerConfigFactory)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(".", []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
-
- return ctx
-}
+var prepareForLinkerConfigTest = android.GroupFixturePreparers(
+ android.PrepareForTestWithAndroidBuildComponents,
+ android.FixtureRegisterWithContext(registerLinkerConfigBuildComponent),
+ android.FixtureAddFile("linker.config.json", nil),
+)
func TestBaseLinkerConfig(t *testing.T) {
- ctx := testContext(t, `
- linker_config {
- name: "linker-config-base",
- src: "linker.config.json",
- }
+ result := prepareForLinkerConfigTest.RunTestWithBp(t, `
+ linker_config {
+ name: "linker-config-base",
+ src: "linker.config.json",
+ }
`)
expected := map[string][]string{
@@ -82,13 +46,13 @@
"LOCAL_INSTALLED_MODULE_STEM": {"linker.config.pb"},
}
- p := ctx.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
+ p := result.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
if p.outputFilePath.Base() != "linker.config.pb" {
t.Errorf("expected linker.config.pb, got %q", p.outputFilePath.Base())
}
- entries := android.AndroidMkEntriesForTest(t, ctx, p)[0]
+ entries := android.AndroidMkEntriesForTest(t, result.TestContext, p)[0]
for k, expectedValue := range expected {
if value, ok := entries.EntryMap[k]; ok {
if !reflect.DeepEqual(value, expectedValue) {
@@ -105,18 +69,18 @@
}
func TestUninstallableLinkerConfig(t *testing.T) {
- ctx := testContext(t, `
- linker_config {
- name: "linker-config-base",
- src: "linker.config.json",
- installable: false,
- }
+ result := prepareForLinkerConfigTest.RunTestWithBp(t, `
+ linker_config {
+ name: "linker-config-base",
+ src: "linker.config.json",
+ installable: false,
+ }
`)
expected := []string{"true"}
- p := ctx.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
- entries := android.AndroidMkEntriesForTest(t, ctx, p)[0]
+ p := result.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
+ entries := android.AndroidMkEntriesForTest(t, result.TestContext, p)[0]
if value, ok := entries.EntryMap["LOCAL_UNINSTALLABLE_MODULE"]; ok {
if !reflect.DeepEqual(value, expected) {
t.Errorf("LOCAL_UNINSTALLABLE_MODULE is expected to be true but %s", value)
diff --git a/python/binary.go b/python/binary.go
index 5b0f080..e955492 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -36,8 +36,8 @@
type bazelPythonBinaryAttributes struct {
Main string
- Srcs bazel.LabelList
- Data bazel.LabelList
+ Srcs bazel.LabelListAttribute
+ Data bazel.LabelListAttribute
Python_version string
}
@@ -97,10 +97,13 @@
// do nothing, since python_version defaults to PY3.
}
+ srcs := android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
+ data := android.BazelLabelForModuleSrc(ctx, m.properties.Data)
+
attrs := &bazelPythonBinaryAttributes{
Main: main,
- Srcs: android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs),
- Data: android.BazelLabelForModuleSrc(ctx, m.properties.Data),
+ Srcs: bazel.MakeLabelListAttribute(srcs),
+ Data: bazel.MakeLabelListAttribute(data),
Python_version: python_version,
}
diff --git a/rust/project_json.go b/rust/project_json.go
index 8d3d250..c28bc7b 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -49,7 +49,7 @@
RootModule string `json:"root_module"`
Edition string `json:"edition,omitempty"`
Deps []rustProjectDep `json:"deps"`
- Cfgs []string `json:"cfgs"`
+ Cfg []string `json:"cfg"`
Env map[string]string `json:"env"`
}
@@ -230,7 +230,7 @@
RootModule: rootModule,
Edition: comp.edition(),
Deps: make([]rustProjectDep, 0),
- Cfgs: make([]string, 0),
+ Cfg: make([]string, 0),
Env: make(map[string]string),
}
@@ -238,6 +238,10 @@
crate.Env["OUT_DIR"] = comp.CargoOutDir().String()
}
+ for _, feature := range comp.Properties.Features {
+ crate.Cfg = append(crate.Cfg, "feature=\""+feature+"\"")
+ }
+
deps := make(map[string]int)
singleton.mergeDependencies(ctx, rModule, &crate, deps)
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index 8f64f56..7af4635 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -18,6 +18,7 @@
"encoding/json"
"io/ioutil"
"path/filepath"
+ "sort"
"strings"
"testing"
@@ -115,6 +116,41 @@
validateJsonCrates(t, jsonContent)
}
+func TestProjectJsonFeature(t *testing.T) {
+ bp := `
+ rust_library {
+ name: "liba",
+ srcs: ["a/src/lib.rs"],
+ crate_name: "a",
+ features: ["f1", "f2"]
+ }
+ `
+ jsonContent := testProjectJson(t, bp)
+ crates := validateJsonCrates(t, jsonContent)
+ for _, c := range crates {
+ crate := validateCrate(t, c)
+ cfgs, ok := crate["cfg"].([]interface{})
+ if !ok {
+ t.Fatalf("Unexpected type for cfgs: %v", crate)
+ }
+ expectedCfgs := []string{"feature=\"f1\"", "feature=\"f2\""}
+ foundCfgs := []string{}
+ for _, cfg := range cfgs {
+ cfg, ok := cfg.(string)
+ if !ok {
+ t.Fatalf("Unexpected type for cfg: %v", cfg)
+ }
+ foundCfgs = append(foundCfgs, cfg)
+ }
+ sort.Strings(foundCfgs)
+ for i, foundCfg := range foundCfgs {
+ if foundCfg != expectedCfgs[i] {
+ t.Errorf("Incorrect features: got %v; want %v", foundCfg, expectedCfgs[i])
+ }
+ }
+ }
+}
+
func TestProjectJsonBinary(t *testing.T) {
bp := `
rust_binary {
diff --git a/scripts/OWNERS b/scripts/OWNERS
index 8198083..2b9c2de 100644
--- a/scripts/OWNERS
+++ b/scripts/OWNERS
@@ -3,3 +3,4 @@
per-file build-aml-prebuilts.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com
per-file construct_context.py = ngeoffray@google.com,calin@google.com,mathieuc@google.com,skvadrik@google.com
per-file conv_linker_config.py = kiyoungkim@google.com, jiyong@google.com, jooyung@google.com
+per-file gen_ndk*.sh = sophiez@google.com, allenhair@google.com
diff --git a/scripts/construct_context.py b/scripts/construct_context.py
index 6f9edc4..f0658ba 100755
--- a/scripts/construct_context.py
+++ b/scripts/construct_context.py
@@ -66,9 +66,9 @@
if not args.sdk:
raise SystemExit('target sdk version is not set')
if not args.host_contexts:
- raise SystemExit('host context is not set')
+ args.host_contexts = []
if not args.target_contexts:
- raise SystemExit('target context is not set')
+ args.target_contexts = []
print(construct_contexts(args))
diff --git a/scripts/gen_ndk_usedby_apex.sh b/scripts/gen_ndk_usedby_apex.sh
index f143161..0d3ed5a 100755
--- a/scripts/gen_ndk_usedby_apex.sh
+++ b/scripts/gen_ndk_usedby_apex.sh
@@ -33,7 +33,7 @@
do
if [[ $line = *FUNC*GLOBAL*UND*@* ]] ;
then
- echo "$line" | sed -r 's/.*UND (.*)@.*/\1/g' >> "$2"
+ echo "$line" | sed -r 's/.*UND (.*@.*)/\1/g' >> "$2"
fi
done < "$1"
echo "" >> "$2"
diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py
index 1343f35..907f239 100755
--- a/scripts/manifest_check.py
+++ b/scripts/manifest_check.py
@@ -289,7 +289,12 @@
f.write("%s\n" % errmsg)
if args.extract_target_sdk_version:
- print(extract_target_sdk_version(manifest, is_apk))
+ try:
+ print(extract_target_sdk_version(manifest, is_apk))
+ except:
+ # Failed; don't crash, return "any" SDK version. This will result in
+ # dexpreopt not adding any compatibility libraries.
+ print(10000)
if args.output:
# XML output is supposed to be written only when this script is invoked
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 1ae557a..6623381 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -485,7 +485,7 @@
}
type bazelShBinaryAttributes struct {
- Srcs bazel.LabelList
+ Srcs bazel.LabelListAttribute
// Bazel also supports the attributes below, but (so far) these are not required for Bionic
// deps
// data
@@ -525,7 +525,8 @@
return
}
- srcs := android.BazelLabelForModuleSrc(ctx, []string{*m.properties.Src})
+ srcs := bazel.MakeLabelListAttribute(
+ android.BazelLabelForModuleSrc(ctx, []string{*m.properties.Src}))
attrs := &bazelShBinaryAttributes{
Srcs: srcs,