Merge "Remove support for unsandboxed metalava"
diff --git a/android/Android.bp b/android/Android.bp
index 773aa6a..a32e8f2 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -67,6 +67,7 @@
"rule_builder.go",
"sandbox.go",
"sdk.go",
+ "sdk_version.go",
"singleton.go",
"singleton_module.go",
"soong_config_modules.go",
diff --git a/android/apex.go b/android/apex.go
index a5ff442..7f9f0f5 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) }
@@ -786,60 +803,73 @@
}
return list
}(map[string]int{
- "adbd": 30,
- "android.net.ipsec.ike": 30,
- "apache-commons-compress": 29,
- "bouncycastle_ike_digests": 30,
- "brotli-java": 29,
- "captiveportal-lib": 28,
- "flatbuffer_headers": 30,
- "framework-permission": 30,
- "gemmlowp_headers": 30,
- "ike-internals": 30,
- "kotlinx-coroutines-android": 28,
- "kotlinx-coroutines-core": 28,
- "libadb_crypto": 30,
- "libadb_pairing_auth": 30,
- "libadb_pairing_connection": 30,
- "libadb_pairing_server": 30,
- "libadb_protos": 30,
- "libadb_tls_connection": 30,
- "libadbconnection_client": 30,
- "libadbconnection_server": 30,
- "libadbd_core": 30,
- "libadbd_services": 30,
- "libadbd": 30,
- "libapp_processes_protos_lite": 30,
- "libasyncio": 30,
- "libbrotli": 30,
- "libbuildversion": 30,
- "libcrypto_static": 30,
- "libcrypto_utils": 30,
- "libdiagnose_usb": 30,
- "libeigen": 30,
- "liblz4": 30,
- "libmdnssd": 30,
- "libneuralnetworks_common": 30,
- "libneuralnetworks_headers": 30,
- "libneuralnetworks": 30,
- "libprocpartition": 30,
- "libprotobuf-java-lite": 30,
- "libprotoutil": 30,
- "libqemu_pipe": 30,
- "libsync": 30,
- "libtextclassifier_hash_headers": 30,
- "libtextclassifier_hash_static": 30,
- "libtflite_kernel_utils": 30,
- "libwatchdog": 29,
- "libzstd": 30,
- "metrics-constants-protos": 28,
- "net-utils-framework-common": 29,
- "permissioncontroller-statsd": 28,
- "philox_random_headers": 30,
- "philox_random": 30,
- "service-permission": 30,
- "tensorflow_headers": 30,
- "xz-java": 29,
+ "adbd": 30,
+ "android.net.ipsec.ike": 30,
+ "androidx.annotation_annotation-nodeps": 29,
+ "androidx.arch.core_core-common-nodeps": 29,
+ "androidx.collection_collection-nodeps": 29,
+ "androidx.collection_collection-ktx-nodeps": 30,
+ "androidx.concurrent_concurrent-futures-nodeps": 30,
+ "androidx.lifecycle_lifecycle-common-java8-nodeps": 30,
+ "androidx.lifecycle_lifecycle-common-nodeps": 29,
+ "androidx.room_room-common-nodeps": 30,
+ "androidx-constraintlayout_constraintlayout-solver-nodeps": 29,
+ "apache-commons-compress": 29,
+ "bouncycastle_ike_digests": 30,
+ "brotli-java": 29,
+ "captiveportal-lib": 28,
+ "error_prone_annotations": 30,
+ "flatbuffer_headers": 30,
+ "framework-permission": 30,
+ "gemmlowp_headers": 30,
+ "guava-listenablefuture-prebuilt-jar": 30,
+ "ike-internals": 30,
+ "kotlinx-coroutines-android": 28,
+ "kotlinx-coroutines-android-nodeps": 30,
+ "kotlinx-coroutines-core": 28,
+ "kotlinx-coroutines-core-nodeps": 30,
+ "libadb_crypto": 30,
+ "libadb_pairing_auth": 30,
+ "libadb_pairing_connection": 30,
+ "libadb_pairing_server": 30,
+ "libadb_protos": 30,
+ "libadb_tls_connection": 30,
+ "libadbconnection_client": 30,
+ "libadbconnection_server": 30,
+ "libadbd_core": 30,
+ "libadbd_services": 30,
+ "libadbd": 30,
+ "libapp_processes_protos_lite": 30,
+ "libasyncio": 30,
+ "libbrotli": 30,
+ "libbuildversion": 30,
+ "libcrypto_static": 30,
+ "libcrypto_utils": 30,
+ "libdiagnose_usb": 30,
+ "libeigen": 30,
+ "liblz4": 30,
+ "libmdnssd": 30,
+ "libneuralnetworks_common": 30,
+ "libneuralnetworks_headers": 30,
+ "libneuralnetworks": 30,
+ "libprocpartition": 30,
+ "libprotobuf-java-lite": 30,
+ "libprotoutil": 30,
+ "libqemu_pipe": 30,
+ "libsync": 30,
+ "libtextclassifier_hash_headers": 30,
+ "libtextclassifier_hash_static": 30,
+ "libtflite_kernel_utils": 30,
+ "libwatchdog": 29,
+ "libzstd": 30,
+ "metrics-constants-protos": 28,
+ "net-utils-framework-common": 29,
+ "permissioncontroller-statsd": 28,
+ "philox_random_headers": 30,
+ "philox_random": 30,
+ "service-permission": 30,
+ "tensorflow_headers": 30,
+ "xz-java": 29,
})
// Function called while walking an APEX's payload dependencies.
diff --git a/android/api_levels.go b/android/api_levels.go
index 2f6a9d2..9bc7e83 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -31,9 +31,9 @@
// ApiLevelFromUser or ApiLevelOrPanic.
//
// The different *types* of API levels are handled separately. Currently only
-// Java has these, and they're managed with the sdkKind enum of the sdkSpec. A
-// future cleanup should be to migrate sdkSpec to using ApiLevel instead of its
-// sdkVersion int, and to move sdkSpec into this package.
+// Java has these, and they're managed with the SdkKind enum of the SdkSpec. A
+// future cleanup should be to migrate SdkSpec to using ApiLevel instead of its
+// SdkVersion int, and to move SdkSpec into this package.
type ApiLevel struct {
// The string representation of the API level.
value string
diff --git a/android/arch.go b/android/arch.go
index 20b4ab0..3eff5d5 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1709,3 +1709,90 @@
}
return archToProp
}
+
+// GetTargetProperties returns a map of OS target (e.g. android, windows) to the
+// values of the properties of the 'dst' struct that are specific to that OS
+// target.
+//
+// For example, passing a struct { Foo bool, Bar string } will return an
+// interface{} that can be type asserted back into the same struct, containing
+// the os-specific property value specified by the module if defined.
+//
+// While this looks similar to GetArchProperties, the internal representation of
+// the properties have a slightly different layout to warrant a standalone
+// lookup function.
+func (m *ModuleBase) GetTargetProperties(dst interface{}) map[OsType]interface{} {
+ // Return value of the arch types to the prop values for that arch.
+ osToProp := map[OsType]interface{}{}
+
+ // Nothing to do for non-OS/arch-specific modules.
+ if !m.ArchSpecific() {
+ return osToProp
+ }
+
+ // archProperties has the type of [][]interface{}. Looks complicated, so
+ // let's explain this step by step.
+ //
+ // Loop over the outer index, which determines the property struct that
+ // contains a matching set of properties in dst that we're interested in.
+ // For example, BaseCompilerProperties or BaseLinkerProperties.
+ for i := range m.archProperties {
+ if m.archProperties[i] == nil {
+ continue
+ }
+
+ // Iterate over the supported OS types
+ for _, os := range OsTypeList {
+ // e.g android, linux_bionic
+ field := os.Field
+
+ // If it's not nil, loop over the inner index, which determines the arch variant
+ // of the prop type. In an Android.bp file, this is like looping over:
+ //
+ // target: { android: { key: value, ... }, linux_bionic: { key: value, ... } }
+ for _, archProperties := range m.archProperties[i] {
+ archPropValues := reflect.ValueOf(archProperties).Elem()
+
+ // This is the archPropRoot struct. Traverse into the Targetnested struct.
+ src := archPropValues.FieldByName("Target").Elem()
+
+ // Step into non-nil pointers to structs in the src value.
+ if src.Kind() == reflect.Ptr {
+ if src.IsNil() {
+ continue
+ }
+ src = src.Elem()
+ }
+
+ // Find the requested field (e.g. android, linux_bionic) in the src struct.
+ src = src.FieldByName(field)
+
+ // Validation steps. We want valid non-nil pointers to structs.
+ if !src.IsValid() || src.IsNil() {
+ continue
+ }
+
+ if src.Kind() != reflect.Ptr || src.Elem().Kind() != reflect.Struct {
+ continue
+ }
+
+ // Clone the destination prop, since we want a unique prop struct per arch.
+ dstClone := reflect.New(reflect.ValueOf(dst).Elem().Type()).Interface()
+
+ // Copy the located property struct into the cloned destination property struct.
+ err := proptools.ExtendMatchingProperties([]interface{}{dstClone}, src.Interface(), nil, proptools.OrderReplace)
+ if err != nil {
+ // This is fine, it just means the src struct doesn't match.
+ continue
+ }
+
+ // Found the prop for the os, you have.
+ osToProp[os] = dstClone
+
+ // Go to the next prop.
+ break
+ }
+ }
+ }
+ return osToProp
+}
diff --git a/android/bazel.go b/android/bazel.go
index 9a14e70..a08da0e 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -108,6 +108,11 @@
type BazelConversionConfigEntry int
const (
+ // A sentinel value to be used as a key in Bp2BuildConfig for modules with
+ // no package path. This is also the module dir for top level Android.bp
+ // modules.
+ BP2BUILD_TOPLEVEL = "."
+
// iota + 1 ensures that the int value is not 0 when used in the Bp2buildAllowlist map,
// which can also mean that the key doesn't exist in a lookup.
@@ -129,49 +134,60 @@
}
// Per-module denylist to always opt modules out.
- bp2buildModuleDoNotConvert = map[string]bool{
- "libBionicBenchmarksUtils": true,
- "libbionic_spawn_benchmark": true,
- "libc_jemalloc_wrapper": true,
- "libc_bootstrap": true,
- "libc_init_static": true,
- "libc_init_dynamic": true,
- "libc_tzcode": true,
- "lib_dns": true,
- "libc_freebsd": true,
- "libc_freebsd_large_stack": true,
- "libc_netbsd": true,
- "libc_openbsd_ndk": true,
- "libc_openbsd_large_stack": true,
- "libc_openbsd": true,
- "libc_gdtoa": true,
- "libc_fortify": true,
- "libc_bionic": true,
- "libc_bionic_ndk": true,
- "libc_bionic_systrace": true,
- "libc_pthread": true,
- "libc_syscalls": true,
- "libc_aeabi": true,
- "libc_ndk": true,
- "libc_nopthread": true,
- "libc_common": true,
- "libc_static_dispatch": true,
- "libc_dynamic_dispatch": true,
- "libc_common_static": true,
- "libc_common_shared": true,
- "libc_unwind_static": true,
- "libc_nomalloc": true,
- "libasync_safe": true,
- "libc_malloc_debug_backtrace": true,
- "libsystemproperties": true,
- "libdl_static": true,
- "liblinker_main": true,
- "liblinker_malloc": true,
- "liblinker_debuggerd_stub": true,
- "libbionic_tests_headers_posix": true,
+ bp2buildModuleDoNotConvertList = []string{
+ "libBionicBenchmarksUtils", // ruperts@, cc_library_static
+ "libbionic_spawn_benchmark", // ruperts@, cc_library_static, depends on //system/libbase
+ "libc_jemalloc_wrapper", // ruperts@, cc_library_static, depends on //external/jemalloc_new
+ "libc_bootstrap", // ruperts@, cc_library_static
+ "libc_init_static", // ruperts@, cc_library_static
+ "libc_init_dynamic", // ruperts@, cc_library_static
+ "libc_tzcode", // ruperts@, cc_library_static
+ "libc_freebsd", // ruperts@, cc_library_static
+ "libc_freebsd_large_stack", // ruperts@, cc_library_static
+ "libc_netbsd", // ruperts@, cc_library_static
+ "libc_openbsd_ndk", // ruperts@, cc_library_static
+ "libc_openbsd_large_stack", // ruperts@, cc_library_static
+ "libc_openbsd", // ruperts@, cc_library_static
+ "libc_gdtoa", // ruperts@, cc_library_static
+ "libc_fortify", // ruperts@, cc_library_static
+ "libc_bionic", // ruperts@, cc_library_static
+ "libc_bionic_ndk", // ruperts@, cc_library_static, depends on //bionic/libc/system_properties
+ "libc_bionic_systrace", // ruperts@, cc_library_static
+ "libc_pthread", // ruperts@, cc_library_static
+ "libc_syscalls", // ruperts@, cc_library_static
+ "libc_aeabi", // ruperts@, cc_library_static
+ "libc_ndk", // ruperts@, cc_library_static, depends on //bionic/libm:libm
+ "libc_nopthread", // ruperts@, cc_library_static, depends on //external/arm-optimized-routines
+ "libc_common", // ruperts@, cc_library_static, depends on //bionic/libc:libc_nopthread
+ "libc_static_dispatch", // ruperts@, cc_library_static
+ "libc_dynamic_dispatch", // ruperts@, cc_library_static
+ "libc_common_static", // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
+ "libc_common_shared", // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
+ "libc_unwind_static", // ruperts@, cc_library_static
+ "libc_nomalloc", // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
+ "libasync_safe", // ruperts@, cc_library_static
+ "libc_malloc_debug_backtrace", // ruperts@, cc_library_static, depends on //system/libbase
+ "libsystemproperties", // ruperts@, cc_library_static, depends on //system/core/property_service/libpropertyinfoparser
+ "libdl_static", // ruperts@, cc_library_static
+ "liblinker_main", // ruperts@, cc_library_static, depends on //system/libbase
+ "liblinker_malloc", // ruperts@, cc_library_static, depends on //system/logging/liblog:liblog
+ "liblinker_debuggerd_stub", // ruperts@, cc_library_static, depends on //system/libbase
+ "libbionic_tests_headers_posix", // ruperts@, cc_library_static
+ "libc_dns", // ruperts@, cc_library_static
+ "note_memtag_heap_async", // cparsons@, cc_library_static
+ "note_memtag_heap_sync", // cparsons@, cc_library_static
}
+
+ // Used for quicker lookups
+ bp2buildModuleDoNotConvert = map[string]bool{}
)
+func init() {
+ for _, moduleName := range bp2buildModuleDoNotConvertList {
+ bp2buildModuleDoNotConvert[moduleName] = true
+ }
+}
+
// ConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build.
func (b *BazelModuleBase) ConvertWithBp2build(ctx BazelConversionPathContext) bool {
if bp2buildModuleDoNotConvert[ctx.Module().Name()] {
@@ -212,10 +228,15 @@
func bp2buildDefaultTrueRecursively(packagePath string, config Bp2BuildConfig) bool {
ret := false
+ // Return exact matches in the config.
+ if config[packagePath] == Bp2BuildDefaultTrueRecursively {
+ return true
+ }
if config[packagePath] == Bp2BuildDefaultFalse {
return false
}
+ // If not, check for the config recursively.
packagePrefix := ""
// e.g. for x/y/z, iterate over x, x/y, then x/y/z, taking the final value from the allowlist.
for _, part := range strings.Split(packagePath, "/") {
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 0595d68..04b70d6 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -27,6 +27,7 @@
"sync"
"android/soong/bazel/cquery"
+
"github.com/google/blueprint/bootstrap"
"android/soong/bazel"
@@ -37,7 +38,6 @@
const (
getAllFiles CqueryRequestType = iota
- getCcObjectFiles
getAllFilesAndCcObjectFiles
)
@@ -56,10 +56,6 @@
// Returns result files built by building the given bazel target label.
GetOutputFiles(label string, archType ArchType) ([]string, bool)
- // Returns object files produced by compiling the given cc-related target.
- // Retrieves these files from Bazel's CcInfo provider.
- GetCcObjectFiles(label string, archType ArchType) ([]string, bool)
-
// TODO(cparsons): Other cquery-related methods should be added here.
// Returns the results of GetOutputFiles and GetCcObjectFiles in a single query (in that order).
GetOutputFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool)
@@ -116,11 +112,6 @@
return result, ok
}
-func (m MockBazelContext) GetCcObjectFiles(label string, archType ArchType) ([]string, bool) {
- result, ok := m.AllFiles[label]
- return result, ok
-}
-
func (m MockBazelContext) GetOutputFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) {
result, ok := m.AllFiles[label]
return result, result, ok
@@ -154,16 +145,6 @@
return ret, ok
}
-func (bazelCtx *bazelContext) GetCcObjectFiles(label string, archType ArchType) ([]string, bool) {
- rawString, ok := bazelCtx.cquery(label, cquery.GetCcObjectFiles, archType)
- var returnResult []string
- if ok {
- bazelOutput := strings.TrimSpace(rawString)
- returnResult = cquery.GetCcObjectFiles.ParseResult(bazelOutput).([]string)
- }
- return returnResult, ok
-}
-
func (bazelCtx *bazelContext) GetOutputFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) {
var outputFiles []string
var ccObjects []string
@@ -183,10 +164,6 @@
panic("unimplemented")
}
-func (n noopBazelContext) GetCcObjectFiles(label string, archType ArchType) ([]string, bool) {
- panic("unimplemented")
-}
-
func (n noopBazelContext) GetOutputFilesAndCcObjectFiles(label string, archType ArchType) ([]string, []string, bool) {
panic("unimplemented")
}
@@ -293,13 +270,23 @@
cmdFlags = append(cmdFlags, labels...)
cmdFlags = append(cmdFlags, "--package_path=%workspace%/"+context.intermediatesDir())
cmdFlags = append(cmdFlags, "--profile="+shared.BazelMetricsFilename(context, runName))
- // Set default platforms to canonicalized values for mixed builds requests. If these are set
- // in the bazelrc, they will have values that are non-canonicalized, and thus be invalid.
- // The actual platform values here may be overridden by configuration transitions from the buildroot.
+
+ // Set default platforms to canonicalized values for mixed builds requests.
+ // If these are set in the bazelrc, they will have values that are
+ // non-canonicalized to @sourceroot labels, and thus be invalid when
+ // referenced from the buildroot.
+ //
+ // The actual platform values here may be overridden by configuration
+ // transitions from the buildroot.
cmdFlags = append(cmdFlags,
- fmt.Sprintf("--platforms=%s", canonicalizeLabel("//build/bazel/platforms:generic_x86_64")))
+ fmt.Sprintf("--platforms=%s", canonicalizeLabel("//build/bazel/platforms:android_x86_64")))
cmdFlags = append(cmdFlags,
fmt.Sprintf("--extra_toolchains=%s", canonicalizeLabel("//prebuilts/clang/host/linux-x86:all")))
+ // This should be parameterized on the host OS, but let's restrict to linux
+ // to keep things simple for now.
+ cmdFlags = append(cmdFlags,
+ fmt.Sprintf("--host_platform=%s", canonicalizeLabel("//build/bazel/platforms:linux_x86_64")))
+
// Explicitly disable downloading rules (such as canonical C++ and Java rules) from the network.
cmdFlags = append(cmdFlags, "--experimental_repository_disable_download")
cmdFlags = append(cmdFlags, extraFlags...)
@@ -332,8 +319,13 @@
name = "sourceroot",
path = "%s",
)
+
+local_repository(
+ name = "rules_cc",
+ path = "%s/build/bazel/rules_cc",
+)
`
- return []byte(fmt.Sprintf(formatString, context.workspaceDir))
+ return []byte(fmt.Sprintf(formatString, context.workspaceDir, context.workspaceDir))
}
func (context *bazelContext) mainBzlFileContents() []byte {
@@ -344,73 +336,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:android_%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 +404,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 {
@@ -558,10 +514,10 @@
platform_name = build_options(target)["//command_line_option:platforms"][0].name
if platform_name == "host":
return "HOST"
- elif not platform_name.startswith("generic_"):
- fail("expected platform name of the form 'generic_<arch>', but was " + str(platforms))
+ elif not platform_name.startswith("android_"):
+ fail("expected platform name of the form 'android_<arch>', but was " + str(platforms))
return "UNKNOWN"
- return platform_name[len("generic_"):]
+ return platform_name[len("android_"):]
def format(target):
id_string = str(target.label) + "|" + get_arch(target)
@@ -746,6 +702,10 @@
cmd.Implicit(PathForBazelOut(ctx, inputPath))
}
+ if depfile := buildStatement.Depfile; depfile != nil {
+ cmd.ImplicitDepFile(PathForBazelOut(ctx, *depfile))
+ }
+
// This is required to silence warnings pertaining to unexpected timestamps. Particularly,
// some Bazel builtins (such as files in the bazel_tools directory) have far-future
// timestamps. Without restat, Ninja would emit warnings that the input files of a
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/fixture.go b/android/fixture.go
index 8d62958..5fc668a 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -26,16 +26,9 @@
// Fixture
// =======
// These determine the environment within which a test can be run. Fixtures are mutable and are
-// created by FixtureFactory instances and mutated by FixturePreparer instances. They are created by
-// first creating a base Fixture (which is essentially empty) and then applying FixturePreparer
-// instances to it to modify the environment.
-//
-// FixtureFactory (deprecated)
-// ===========================
-// These are responsible for creating fixtures. Factories are immutable and are intended to be
-// initialized once and reused to create multiple fixtures. Each factory has a list of fixture
-// preparers that prepare a fixture for running a test. Factories can also be used to create other
-// factories by extending them with additional fixture preparers.
+// created and mutated by FixturePreparer instances. They are created by first creating a base
+// Fixture (which is essentially empty) and then applying FixturePreparer instances to it to modify
+// the environment.
//
// FixturePreparer
// ===============
@@ -169,77 +162,6 @@
// PrepareForApex,
// )
//
-// // FixtureFactory instances have been deprecated, this remains for informational purposes to
-// // help explain some of the existing code but will be removed along with FixtureFactory.
-//
-// var javaFixtureFactory = android.NewFixtureFactory(
-// PrepareForIntegrationTestWithJava,
-// FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
-// ctx.RegisterModuleType("test_module", testModule)
-// }),
-// javaMockFS.AddToFixture(),
-// ...
-// }
-//
-// func TestJavaStuff(t *testing.T) {
-// result := javaFixtureFactory.RunTest(t,
-// android.FixtureWithRootAndroidBp(`java_library {....}`),
-// android.MockFS{...}.AddToFixture(),
-// )
-// ... test result ...
-// }
-//
-// package cc
-// var PrepareForTestWithCC = GroupFixturePreparers(
-// android.PrepareForArchMutator,
-// android.prepareForPrebuilts,
-// FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
-// ...
-// )
-//
-// package apex
-//
-// var PrepareForApex = GroupFixturePreparers(
-// ...
-// )
-//
-// Use modules and mutators from java, cc and apex. Any duplicate preparers (like
-// android.PrepareForArchMutator) will be automatically deduped.
-//
-// var apexFixtureFactory = android.NewFixtureFactory(
-// PrepareForJava,
-// PrepareForCC,
-// PrepareForApex,
-// )
-
-// Factory for Fixture objects.
-//
-// This is configured with a set of FixturePreparer objects that are used to
-// initialize each Fixture instance this creates.
-//
-// deprecated: Use FixturePreparer instead.
-type FixtureFactory interface {
- FixturePreparer
-}
-
-// Create a new FixtureFactory that will apply the supplied preparers.
-//
-// The buildDirSupplier is a pointer to the package level buildDir variable that is initialized by
-// the package level setUp method. It has to be a pointer to the variable as the variable will not
-// have been initialized at the time the factory is created. If it is nil then a test specific
-// temporary directory will be created instead.
-//
-// deprecated: The functionality provided by FixtureFactory will be merged into FixturePreparer
-func NewFixtureFactory(buildDirSupplier *string, preparers ...FixturePreparer) FixtureFactory {
- f := &fixtureFactory{
- buildDirSupplier: buildDirSupplier,
- compositeFixturePreparer: compositeFixturePreparer{
- preparers: dedupAndFlattenPreparers(nil, preparers),
- },
- }
- f.initBaseFixturePreparer(f)
- return f
-}
// A set of mock files to add to the mock file system.
type MockFS map[string][]byte
@@ -445,17 +367,8 @@
// Return the flattened and deduped list of simpleFixturePreparer pointers.
list() []*simpleFixturePreparer
- // Creates a copy of this instance and adds some additional preparers.
- //
- // Before the preparers are used they are combined with the preparers provided when the factory
- // was created, any groups of preparers are flattened, and the list is deduped so that each
- // preparer is only used once. See the file documentation in android/fixture.go for more details.
- //
- // deprecated: Use GroupFixturePreparers() instead.
- Extend(preparers ...FixturePreparer) FixturePreparer
-
// Create a Fixture.
- Fixture(t *testing.T, preparers ...FixturePreparer) Fixture
+ Fixture(t *testing.T) Fixture
// ExtendWithErrorHandler creates a new FixturePreparer that will use the supplied error handler
// to check the errors (may be 0) reported by the test.
@@ -466,12 +379,13 @@
// Run the test, checking any errors reported and returning a TestResult instance.
//
- // Shorthand for Fixture(t, preparers...).RunTest()
- RunTest(t *testing.T, preparers ...FixturePreparer) *TestResult
+ // Shorthand for Fixture(t).RunTest()
+ RunTest(t *testing.T) *TestResult
// Run the test with the supplied Android.bp file.
//
- // Shorthand for RunTest(t, android.FixtureWithRootAndroidBp(bp))
+ // preparer.RunTestWithBp(t, bp) is shorthand for
+ // android.GroupFixturePreparers(preparer, android.FixtureWithRootAndroidBp(bp)).RunTest(t)
RunTestWithBp(t *testing.T, bp string) *TestResult
// RunTestWithConfig is a temporary method added to help ease the migration of existing tests to
@@ -705,13 +619,11 @@
NinjaDeps []string
}
-func createFixture(t *testing.T, buildDir string, base []*simpleFixturePreparer, extra []FixturePreparer) Fixture {
- all := dedupAndFlattenPreparers(base, extra)
-
+func createFixture(t *testing.T, buildDir string, preparers []*simpleFixturePreparer) Fixture {
config := TestConfig(buildDir, nil, "", nil)
ctx := NewTestContext(config)
fixture := &fixture{
- preparers: all,
+ preparers: preparers,
t: t,
config: config,
ctx: ctx,
@@ -720,7 +632,7 @@
errorHandler: FixtureExpectsNoErrors,
}
- for _, preparer := range all {
+ for _, preparer := range preparers {
preparer.function(fixture)
}
@@ -735,30 +647,25 @@
b.self = self
}
-func (b *baseFixturePreparer) Extend(preparers ...FixturePreparer) FixturePreparer {
- all := dedupAndFlattenPreparers(b.self.list(), preparers)
- return newFixturePreparer(all)
-}
-
-func (b *baseFixturePreparer) Fixture(t *testing.T, preparers ...FixturePreparer) Fixture {
- return createFixture(t, t.TempDir(), b.self.list(), preparers)
+func (b *baseFixturePreparer) Fixture(t *testing.T) Fixture {
+ return createFixture(t, t.TempDir(), b.self.list())
}
func (b *baseFixturePreparer) ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixturePreparer {
- return b.self.Extend(newSimpleFixturePreparer(func(fixture *fixture) {
+ return GroupFixturePreparers(b.self, newSimpleFixturePreparer(func(fixture *fixture) {
fixture.errorHandler = errorHandler
}))
}
-func (b *baseFixturePreparer) RunTest(t *testing.T, preparers ...FixturePreparer) *TestResult {
+func (b *baseFixturePreparer) RunTest(t *testing.T) *TestResult {
t.Helper()
- fixture := b.self.Fixture(t, preparers...)
+ fixture := b.self.Fixture(t)
return fixture.RunTest()
}
func (b *baseFixturePreparer) RunTestWithBp(t *testing.T, bp string) *TestResult {
t.Helper()
- return b.RunTest(t, FixtureWithRootAndroidBp(bp))
+ return GroupFixturePreparers(b.self, FixtureWithRootAndroidBp(bp)).RunTest(t)
}
func (b *baseFixturePreparer) RunTestWithConfig(t *testing.T, config Config) *TestResult {
@@ -783,46 +690,6 @@
return fixture.RunTest()
}
-var _ FixtureFactory = (*fixtureFactory)(nil)
-
-type fixtureFactory struct {
- compositeFixturePreparer
-
- buildDirSupplier *string
-}
-
-// Override to preserve the buildDirSupplier.
-func (f *fixtureFactory) Extend(preparers ...FixturePreparer) FixturePreparer {
- // If there is no buildDirSupplier then just use the default implementation.
- if f.buildDirSupplier == nil {
- return f.baseFixturePreparer.Extend(preparers...)
- }
-
- all := dedupAndFlattenPreparers(f.preparers, preparers)
-
- // Create a new factory which uses the same buildDirSupplier as the previous one.
- extendedFactory := &fixtureFactory{
- buildDirSupplier: f.buildDirSupplier,
- compositeFixturePreparer: compositeFixturePreparer{
- preparers: all,
- },
- }
- extendedFactory.initBaseFixturePreparer(extendedFactory)
- return extendedFactory
-}
-
-func (f *fixtureFactory) Fixture(t *testing.T, preparers ...FixturePreparer) Fixture {
- // If there is no buildDirSupplier then just use the default implementation.
- if f.buildDirSupplier == nil {
- return f.baseFixturePreparer.Fixture(t, preparers...)
- }
-
- // Retrieve the buildDir from the supplier.
- buildDir := *f.buildDirSupplier
-
- return createFixture(t, buildDir, f.preparers, preparers)
-}
-
type fixture struct {
// The preparers used to create this fixture.
preparers []*simpleFixturePreparer
@@ -937,10 +804,10 @@
// that produced this result.
//
// e.g. assuming that this result was created by running:
-// factory.Extend(preparer1, preparer2).RunTest(t, preparer3, preparer4)
+// GroupFixturePreparers(preparer1, preparer2, preparer3).RunTest(t)
//
// Then this method will be equivalent to running:
-// GroupFixturePreparers(preparer1, preparer2, preparer3, preparer4)
+// GroupFixturePreparers(preparer1, preparer2, preparer3)
//
// This is intended for use by tests whose output is Android.bp files to verify that those files
// are valid, e.g. tests of the snapshots produced by the sdk module type.
diff --git a/android/fixture_test.go b/android/fixture_test.go
index 681a034..5b810e0 100644
--- a/android/fixture_test.go
+++ b/android/fixture_test.go
@@ -41,45 +41,42 @@
group := GroupFixturePreparers(preparer1, preparer2, preparer1, preparer1Then2)
- extension := group.Extend(preparer4, preparer2)
+ extension := GroupFixturePreparers(group, preparer4, preparer2)
- extension.Fixture(t, preparer1, preparer2, preparer2Then1, preparer3)
+ GroupFixturePreparers(extension, preparer1, preparer2, preparer2Then1, preparer3).Fixture(t)
AssertDeepEquals(t, "preparers called in wrong order",
[]string{"preparer1", "preparer2", "preparer4", "preparer3"}, list)
}
func TestFixtureValidateMockFS(t *testing.T) {
- buildDir := "<unused>"
- factory := NewFixtureFactory(&buildDir)
-
t.Run("absolute path", func(t *testing.T) {
AssertPanicMessageContains(t, "source path validation failed", "Path is outside directory: /abs/path/Android.bp", func() {
- factory.Fixture(t, FixtureAddFile("/abs/path/Android.bp", nil))
+ FixtureAddFile("/abs/path/Android.bp", nil).Fixture(t)
})
})
t.Run("not canonical", func(t *testing.T) {
AssertPanicMessageContains(t, "source path validation failed", `path "path/with/../in/it/Android.bp" is not a canonical path, use "path/in/it/Android.bp" instead`, func() {
- factory.Fixture(t, FixtureAddFile("path/with/../in/it/Android.bp", nil))
+ FixtureAddFile("path/with/../in/it/Android.bp", nil).Fixture(t)
})
})
t.Run("FixtureAddFile", func(t *testing.T) {
AssertPanicMessageContains(t, "source path validation failed", `cannot add output path "out/Android.bp" to the mock file system`, func() {
- factory.Fixture(t, FixtureAddFile("out/Android.bp", nil))
+ FixtureAddFile("out/Android.bp", nil).Fixture(t)
})
})
t.Run("FixtureMergeMockFs", func(t *testing.T) {
AssertPanicMessageContains(t, "source path validation failed", `cannot add output path "out/Android.bp" to the mock file system`, func() {
- factory.Fixture(t, FixtureMergeMockFs(MockFS{
+ FixtureMergeMockFs(MockFS{
"out/Android.bp": nil,
- }))
+ }).Fixture(t)
})
})
t.Run("FixtureModifyMockFS", func(t *testing.T) {
AssertPanicMessageContains(t, "source path validation failed", `cannot add output path "out/Android.bp" to the mock file system`, func() {
- factory.Fixture(t, FixtureModifyMockFS(func(fs MockFS) {
+ FixtureModifyMockFS(func(fs MockFS) {
fs["out/Android.bp"] = nil
- }))
+ }).Fixture(t)
})
})
}
diff --git a/android/mutator.go b/android/mutator.go
index 9e99bee..e25e2e8 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -202,7 +202,7 @@
RegisterPrebuiltsPostDepsMutators,
RegisterVisibilityRuleEnforcer,
RegisterLicensesDependencyChecker,
- RegisterNeverallowMutator,
+ registerNeverallowMutator,
RegisterOverridePostDepsMutators,
}
@@ -539,7 +539,7 @@
Name: &name,
}
- b := t.CreateModule(factory, &nameProp, attrs).(BazelTargetModule)
+ b := t.createModuleWithoutInheritance(factory, &nameProp, attrs).(BazelTargetModule)
b.SetBazelTargetModuleProperties(bazelProps)
return b
}
@@ -608,6 +608,11 @@
return module
}
+func (t *topDownMutatorContext) createModuleWithoutInheritance(factory ModuleFactory, props ...interface{}) Module {
+ module := t.bp.CreateModule(ModuleFactoryAdaptor(factory), props...).(Module)
+ return module
+}
+
func (b *bottomUpMutatorContext) MutatorName() string {
return b.bp.MutatorName()
}
diff --git a/android/neverallow.go b/android/neverallow.go
index 7455e6a..a385bbc 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -42,7 +42,7 @@
// counts as a match
// - it has none of the "Without" properties matched (same rules as above)
-func RegisterNeverallowMutator(ctx RegisterMutatorsContext) {
+func registerNeverallowMutator(ctx RegisterMutatorsContext) {
ctx.BottomUp("neverallow", neverallowMutator).Parallel()
}
@@ -661,6 +661,22 @@
// Overrides the default neverallow rules for the supplied config.
//
// For testing only.
-func SetTestNeverallowRules(config Config, testRules []Rule) {
+func setTestNeverallowRules(config Config, testRules []Rule) {
config.Once(neverallowRulesKey, func() interface{} { return testRules })
}
+
+// Prepares for a test by setting neverallow rules and enabling the mutator.
+//
+// If the supplied rules are nil then the default rules are used.
+func PrepareForTestWithNeverallowRules(testRules []Rule) FixturePreparer {
+ return GroupFixturePreparers(
+ FixtureModifyConfig(func(config Config) {
+ if testRules != nil {
+ setTestNeverallowRules(config, testRules)
+ }
+ }),
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.PostDepsMutators(registerNeverallowMutator)
+ }),
+ )
+}
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index de0197a..268346a 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -292,7 +292,6 @@
ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule)
ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule)
ctx.RegisterModuleType("makefile_goal", newMockMakefileGoalModule)
- ctx.PostDepsMutators(RegisterNeverallowMutator)
}),
)
@@ -301,12 +300,7 @@
t.Run(test.name, func(t *testing.T) {
GroupFixturePreparers(
prepareForNeverAllowTest,
- FixtureModifyConfig(func(config Config) {
- // If the test has its own rules then use them instead of the default ones.
- if test.rules != nil {
- SetTestNeverallowRules(config, test.rules)
- }
- }),
+ PrepareForTestWithNeverallowRules(test.rules),
test.fs.AddToFixture(),
).
ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
diff --git a/android/paths.go b/android/paths.go
index 1278961..ba1ab11 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -286,6 +286,16 @@
return p.path
}
+// RelativeToTop returns an OptionalPath with the path that was embedded having been replaced by the
+// result of calling Path.RelativeToTop on it.
+func (p OptionalPath) RelativeToTop() 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/prebuilt.go b/android/prebuilt.go
index 04864a1..ebccaa7 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -272,11 +272,9 @@
}
}
-// PrebuiltPostDepsMutator does two operations. It replace dependencies on the
-// source module with dependencies on the prebuilt when both modules exist and
-// the prebuilt should be used. When the prebuilt should not be used, disable
-// installing it. Secondly, it also adds a sourcegroup to any filegroups found
-// in the prebuilt's 'Srcs' property.
+// PrebuiltPostDepsMutator replaces dependencies on the source module with dependencies on the
+// prebuilt when both modules exist and the prebuilt should be used. When the prebuilt should not
+// be used, disable installing it.
func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) {
if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
p := m.Prebuilt()
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/register.go b/android/register.go
index 35469d4..4c8088d 100644
--- a/android/register.go
+++ b/android/register.go
@@ -192,6 +192,15 @@
t.register(ctx)
}
+ if ctx.config.BazelContext.BazelEnabled() {
+ // Hydrate the configuration of bp2build-enabled module types. This is
+ // required as a signal to identify which modules should be deferred to
+ // Bazel in mixed builds, if it is enabled.
+ for t, _ := range bp2buildMutators {
+ ctx.config.bp2buildModuleTypeConfig[t] = true
+ }
+ }
+
mutators := collateGloballyRegisteredMutators()
mutators.registerAll(ctx)
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index 9c5ca41..d2a7d8d 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -645,7 +645,7 @@
rspFile := "out/soong/.intermediates/foo/rsp"
rspFile2 := "out/soong/.intermediates/foo/rsp2"
module := result.ModuleForTests("foo", "")
- check(t, module.Rule("rule").RelativeToTop(), module.Output(rspFile2).RelativeToTop(),
+ check(t, module.Rule("rule"), module.Output(rspFile2),
"cp bar "+outFile+" @"+rspFile+" @"+rspFile2,
outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
})
@@ -662,7 +662,7 @@
cmd := `rm -rf ` + outDir + `/gen && ` +
sbox + ` --sandbox-path ` + sandboxPath + ` --manifest ` + manifest
module := result.ModuleForTests("foo_sbox", "")
- check(t, module.Output("gen/foo_sbox").RelativeToTop(), module.Output(rspFile2).RelativeToTop(),
+ check(t, module.Output("gen/foo_sbox"), module.Output(rspFile2),
cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
})
t.Run("sbox_inputs", func(t *testing.T) {
@@ -679,7 +679,7 @@
sbox + ` --sandbox-path ` + sandboxPath + ` --manifest ` + manifest
module := result.ModuleForTests("foo_sbox_inputs", "")
- check(t, module.Output("gen/foo_sbox_inputs").RelativeToTop(), module.Output(rspFile2).RelativeToTop(),
+ check(t, module.Output("gen/foo_sbox_inputs"), module.Output(rspFile2),
cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
})
t.Run("singleton", func(t *testing.T) {
@@ -687,7 +687,7 @@
rspFile := filepath.Join("out/soong/singleton/rsp")
rspFile2 := filepath.Join("out/soong/singleton/rsp2")
singleton := result.SingletonForTests("rule_builder_test")
- check(t, singleton.Rule("rule").RelativeToTop(), singleton.Output(rspFile2).RelativeToTop(),
+ check(t, singleton.Rule("rule"), singleton.Output(rspFile2),
"cp bar "+outFile+" @"+rspFile+" @"+rspFile2,
outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
})
diff --git a/android/sdk_version.go b/android/sdk_version.go
new file mode 100644
index 0000000..ce22b5f
--- /dev/null
+++ b/android/sdk_version.go
@@ -0,0 +1,311 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+)
+
+type SdkContext interface {
+ // SdkVersion returns SdkSpec that corresponds to the sdk_version property of the current module
+ SdkVersion() SdkSpec
+ // SystemModules returns the system_modules property of the current module, or an empty string if it is not set.
+ SystemModules() string
+ // MinSdkVersion returns SdkSpec that corresponds to the min_sdk_version property of the current module,
+ // or from sdk_version if it is not set.
+ MinSdkVersion() SdkSpec
+ // TargetSdkVersion returns the SdkSpec that corresponds to the target_sdk_version property of the current module,
+ // or from sdk_version if it is not set.
+ TargetSdkVersion() SdkSpec
+}
+
+// SdkKind represents a particular category of an SDK spec like public, system, test, etc.
+type SdkKind int
+
+const (
+ SdkInvalid SdkKind = iota
+ SdkNone
+ SdkCore
+ SdkCorePlatform
+ SdkPublic
+ SdkSystem
+ SdkTest
+ SdkModule
+ SdkSystemServer
+ SdkPrivate
+)
+
+// String returns the string representation of this SdkKind
+func (k SdkKind) String() string {
+ switch k {
+ case SdkPrivate:
+ return "private"
+ case SdkNone:
+ return "none"
+ case SdkPublic:
+ return "public"
+ case SdkSystem:
+ return "system"
+ case SdkTest:
+ return "test"
+ case SdkCore:
+ return "core"
+ case SdkCorePlatform:
+ return "core_platform"
+ case SdkModule:
+ return "module-lib"
+ case SdkSystemServer:
+ return "system-server"
+ default:
+ return "invalid"
+ }
+}
+
+// SdkVersion represents a specific version number of an SDK spec of a particular kind
+type SdkVersion int
+
+const (
+ // special version number for a not-yet-frozen SDK
+ SdkVersionCurrent SdkVersion = SdkVersion(FutureApiLevelInt)
+ // special version number to be used for SDK specs where version number doesn't
+ // make sense, e.g. "none", "", etc.
+ SdkVersionNone SdkVersion = SdkVersion(0)
+)
+
+// IsCurrent checks if the SdkVersion refers to the not-yet-published version of an SdkKind
+func (v SdkVersion) IsCurrent() bool {
+ return v == SdkVersionCurrent
+}
+
+// IsNumbered checks if the SdkVersion refers to the published (a.k.a numbered) version of an SdkKind
+func (v SdkVersion) IsNumbered() bool {
+ return !v.IsCurrent() && v != SdkVersionNone
+}
+
+// String returns the string representation of this SdkVersion.
+func (v SdkVersion) String() string {
+ if v.IsCurrent() {
+ return "current"
+ } else if v.IsNumbered() {
+ return strconv.Itoa(int(v))
+ }
+ return "(no version)"
+}
+
+func (v SdkVersion) ApiLevel(ctx EarlyModuleContext) ApiLevel {
+ return ApiLevelOrPanic(ctx, v.String())
+}
+
+// AsNumberString directly converts the numeric value of this sdk version as a string.
+// When isNumbered() is true, this method is the same as String(). However, for SdkVersionCurrent
+// and SdkVersionNone, this returns 10000 and 0 while String() returns "current" and "(no version"),
+// respectively.
+func (v SdkVersion) AsNumberString() string {
+ return strconv.Itoa(int(v))
+}
+
+// SdkSpec represents the kind and the version of an SDK for a module to build against
+type SdkSpec struct {
+ Kind SdkKind
+ Version SdkVersion
+ Raw string
+}
+
+func (s SdkSpec) String() string {
+ return fmt.Sprintf("%s_%s", s.Kind, s.Version)
+}
+
+// Valid checks if this SdkSpec is well-formed. Note however that true doesn't mean that the
+// specified SDK actually exists.
+func (s SdkSpec) Valid() bool {
+ return s.Kind != SdkInvalid
+}
+
+// Specified checks if this SdkSpec is well-formed and is not "".
+func (s SdkSpec) Specified() bool {
+ return s.Valid() && s.Kind != SdkPrivate
+}
+
+// whether the API surface is managed and versioned, i.e. has .txt file that
+// get frozen on SDK freeze and changes get reviewed by API council.
+func (s SdkSpec) Stable() bool {
+ if !s.Specified() {
+ return false
+ }
+ switch s.Kind {
+ case SdkNone:
+ // there is nothing to manage and version in this case; de facto stable API.
+ return true
+ case SdkCore, SdkPublic, SdkSystem, SdkModule, SdkSystemServer:
+ return true
+ case SdkCorePlatform, SdkTest, SdkPrivate:
+ return false
+ default:
+ panic(fmt.Errorf("unknown SdkKind=%v", s.Kind))
+ }
+ return false
+}
+
+// PrebuiltSdkAvailableForUnbundledBuilt tells whether this SdkSpec can have a prebuilt SDK
+// that can be used for unbundled builds.
+func (s SdkSpec) PrebuiltSdkAvailableForUnbundledBuild() bool {
+ // "", "none", and "core_platform" are not available for unbundled build
+ // as we don't/can't have prebuilt stub for the versions
+ return s.Kind != SdkPrivate && s.Kind != SdkNone && s.Kind != SdkCorePlatform
+}
+
+func (s SdkSpec) ForVendorPartition(ctx EarlyModuleContext) SdkSpec {
+ // If BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES has a numeric value,
+ // use it instead of "current" for the vendor partition.
+ currentSdkVersion := ctx.DeviceConfig().CurrentApiLevelForVendorModules()
+ if currentSdkVersion == "current" {
+ return s
+ }
+
+ if s.Kind == SdkPublic || s.Kind == SdkSystem {
+ if s.Version.IsCurrent() {
+ if i, err := strconv.Atoi(currentSdkVersion); err == nil {
+ version := SdkVersion(i)
+ return SdkSpec{s.Kind, version, s.Raw}
+ }
+ panic(fmt.Errorf("BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES must be either \"current\" or a number, but was %q", currentSdkVersion))
+ }
+ }
+ return s
+}
+
+// UsePrebuilt determines whether prebuilt SDK should be used for this SdkSpec with the given context.
+func (s SdkSpec) UsePrebuilt(ctx EarlyModuleContext) bool {
+ if s.Version.IsCurrent() {
+ // "current" can be built from source and be from prebuilt SDK
+ return ctx.Config().AlwaysUsePrebuiltSdks()
+ } else if s.Version.IsNumbered() {
+ // validation check
+ if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest && s.Kind != SdkModule {
+ panic(fmt.Errorf("prebuilt SDK is not not available for SdkKind=%q", s.Kind))
+ return false
+ }
+ // numbered SDKs are always from prebuilt
+ return true
+ }
+ // "", "none", "core_platform" fall here
+ return false
+}
+
+// EffectiveVersion converts an SdkSpec into the concrete SdkVersion that the module
+// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
+// it returns FutureApiLevel(10000).
+func (s SdkSpec) EffectiveVersion(ctx EarlyModuleContext) (SdkVersion, error) {
+ if !s.Valid() {
+ return s.Version, fmt.Errorf("invalid sdk version %q", s.Raw)
+ }
+
+ if ctx.DeviceSpecific() || ctx.SocSpecific() {
+ s = s.ForVendorPartition(ctx)
+ }
+ if s.Version.IsNumbered() {
+ return s.Version, nil
+ }
+ return SdkVersion(ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt()), nil
+}
+
+// EffectiveVersionString converts an SdkSpec into the concrete version string that the module
+// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
+// it returns the codename (P, Q, R, etc.)
+func (s SdkSpec) EffectiveVersionString(ctx EarlyModuleContext) (string, error) {
+ ver, err := s.EffectiveVersion(ctx)
+ if err == nil && int(ver) == ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt() {
+ return ctx.Config().DefaultAppTargetSdk(ctx).String(), nil
+ }
+ return ver.String(), err
+}
+
+func SdkSpecFrom(str string) SdkSpec {
+ switch str {
+ // special cases first
+ case "":
+ return SdkSpec{SdkPrivate, SdkVersionNone, str}
+ case "none":
+ return SdkSpec{SdkNone, SdkVersionNone, str}
+ case "core_platform":
+ return SdkSpec{SdkCorePlatform, SdkVersionNone, str}
+ default:
+ // the syntax is [kind_]version
+ sep := strings.LastIndex(str, "_")
+
+ var kindString string
+ if sep == 0 {
+ return SdkSpec{SdkInvalid, SdkVersionNone, str}
+ } else if sep == -1 {
+ kindString = ""
+ } else {
+ kindString = str[0:sep]
+ }
+ versionString := str[sep+1 : len(str)]
+
+ var kind SdkKind
+ switch kindString {
+ case "":
+ kind = SdkPublic
+ case "core":
+ kind = SdkCore
+ case "system":
+ kind = SdkSystem
+ case "test":
+ kind = SdkTest
+ case "module":
+ kind = SdkModule
+ case "system_server":
+ kind = SdkSystemServer
+ default:
+ return SdkSpec{SdkInvalid, SdkVersionNone, str}
+ }
+
+ var version SdkVersion
+ if versionString == "current" {
+ version = SdkVersionCurrent
+ } else if i, err := strconv.Atoi(versionString); err == nil {
+ version = SdkVersion(i)
+ } else {
+ return SdkSpec{SdkInvalid, SdkVersionNone, str}
+ }
+
+ return SdkSpec{kind, version, str}
+ }
+}
+
+func (s SdkSpec) ValidateSystemSdk(ctx EarlyModuleContext) bool {
+ // Ensures that the specified system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor/product Java module)
+ // Assuming that BOARD_SYSTEMSDK_VERSIONS := 28 29,
+ // sdk_version of the modules in vendor/product that use system sdk must be either system_28, system_29 or system_current
+ if s.Kind != SdkSystem || !s.Version.IsNumbered() {
+ return true
+ }
+ allowedVersions := ctx.DeviceConfig().PlatformSystemSdkVersions()
+ if ctx.DeviceSpecific() || ctx.SocSpecific() || (ctx.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
+ systemSdkVersions := ctx.DeviceConfig().SystemSdkVersions()
+ if len(systemSdkVersions) > 0 {
+ allowedVersions = systemSdkVersions
+ }
+ }
+ if len(allowedVersions) > 0 && !InList(s.Version.String(), allowedVersions) {
+ ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
+ s.Raw, allowedVersions)
+ return false
+ }
+ return true
+}
diff --git a/android/testing.go b/android/testing.go
index 3f3f769..ce27fca 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -539,8 +539,7 @@
// The parts of this structure which are changed are:
// * BuildParams
// * Args
-// * Path instances are intentionally not modified, use AssertPathRelativeToTopEquals or
-// AssertPathsRelativeToTopEquals instead which do something similar.
+// * All Path, Paths, WritablePath and WritablePaths fields.
//
// * RuleParams
// * Command
@@ -552,6 +551,8 @@
// * CommandOrderOnly
//
// See PathRelativeToTop for more details.
+//
+// deprecated: this is no longer needed as TestingBuildParams are created in this form.
func (p TestingBuildParams) RelativeToTop() TestingBuildParams {
// If this is not a valid params then just return it back. That will make it easy to use with the
// Maybe...() methods.
@@ -559,11 +560,25 @@
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.
bparams := p.BuildParams
+ bparams.Depfile = normalizeWritablePathRelativeToTop(bparams.Depfile)
+ bparams.Output = normalizeWritablePathRelativeToTop(bparams.Output)
+ bparams.Outputs = bparams.Outputs.RelativeToTop()
+ bparams.SymlinkOutput = normalizeWritablePathRelativeToTop(bparams.SymlinkOutput)
+ bparams.SymlinkOutputs = bparams.SymlinkOutputs.RelativeToTop()
+ bparams.ImplicitOutput = normalizeWritablePathRelativeToTop(bparams.ImplicitOutput)
+ bparams.ImplicitOutputs = bparams.ImplicitOutputs.RelativeToTop()
+ bparams.Input = normalizePathRelativeToTop(bparams.Input)
+ bparams.Inputs = bparams.Inputs.RelativeToTop()
+ bparams.Implicit = normalizePathRelativeToTop(bparams.Implicit)
+ bparams.Implicits = bparams.Implicits.RelativeToTop()
+ bparams.OrderOnly = bparams.OrderOnly.RelativeToTop()
+ bparams.Validation = normalizePathRelativeToTop(bparams.Validation)
+ bparams.Validations = bparams.Validations.RelativeToTop()
bparams.Args = normalizeStringMapRelativeToTop(p.config, bparams.Args)
// Ditto for any fields in the RuleParams.
@@ -582,6 +597,20 @@
}
}
+func normalizeWritablePathRelativeToTop(path WritablePath) WritablePath {
+ if path == nil {
+ return nil
+ }
+ return path.RelativeToTop().(WritablePath)
+}
+
+func normalizePathRelativeToTop(path Path) Path {
+ if path == nil {
+ return nil
+ }
+ return path.RelativeToTop()
+}
+
// baseTestingComponent provides functionality common to both TestingModule and TestingSingleton.
type baseTestingComponent struct {
config Config
@@ -643,7 +672,7 @@
config: b.config,
BuildParams: bparams,
RuleParams: b.provider.RuleParamsForTests()[bparams.Rule],
- }
+ }.RelativeToTop()
}
func (b baseTestingComponent) maybeBuildParamsFromRule(rule string) (TestingBuildParams, []string) {
@@ -789,6 +818,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 {
@@ -1013,3 +1058,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/android/variable.go b/android/variable.go
index 2ab51c7..dff48c2 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -448,6 +448,63 @@
}
}
+// ProductConfigContext requires the access to the Module to get product config properties.
+type ProductConfigContext interface {
+ Module() Module
+}
+
+// ProductConfigProperty contains the information for a single property (may be a struct) paired
+// with the appropriate ProductConfigVariable.
+type ProductConfigProperty struct {
+ ProductConfigVariable string
+ Property interface{}
+}
+
+// ProductConfigProperties is a map of property name to a slice of ProductConfigProperty such that
+// all it all product variable-specific versions of a property are easily accessed together
+type ProductConfigProperties map[string][]ProductConfigProperty
+
+// ProductVariableProperties returns a ProductConfigProperties containing only the properties which
+// have been set for the module in the given context.
+func ProductVariableProperties(ctx ProductConfigContext) ProductConfigProperties {
+ module := ctx.Module()
+ moduleBase := module.base()
+
+ productConfigProperties := ProductConfigProperties{}
+
+ if moduleBase.variableProperties == nil {
+ return productConfigProperties
+ }
+
+ variableValues := reflect.ValueOf(moduleBase.variableProperties).Elem().FieldByName("Product_variables")
+ for i := 0; i < variableValues.NumField(); i++ {
+ variableValue := variableValues.Field(i)
+ // Check if any properties were set for the module
+ if variableValue.IsZero() {
+ continue
+ }
+ // e.g. Platform_sdk_version, Unbundled_build, Malloc_not_svelte, etc.
+ productVariableName := variableValues.Type().Field(i).Name
+ for j := 0; j < variableValue.NumField(); j++ {
+ property := variableValue.Field(j)
+ // If the property wasn't set, no need to pass it along
+ if property.IsZero() {
+ continue
+ }
+
+ // e.g. Asflags, Cflags, Enabled, etc.
+ propertyName := variableValue.Type().Field(j).Name
+ productConfigProperties[propertyName] = append(productConfigProperties[propertyName],
+ ProductConfigProperty{
+ ProductConfigVariable: productVariableName,
+ Property: property.Interface(),
+ })
+ }
+ }
+
+ return productConfigProperties
+}
+
func VariableMutator(mctx BottomUpMutatorContext) {
var module Module
var ok bool
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..98b40fd 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -16,13 +16,13 @@
import (
"fmt"
- "io/ioutil"
"os"
"path"
"path/filepath"
"reflect"
"regexp"
"sort"
+ "strconv"
"strings"
"testing"
@@ -38,8 +38,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, " ") {
@@ -52,18 +50,28 @@
func testApexError(t *testing.T, pattern, bp string, preparers ...android.FixturePreparer) {
t.Helper()
- apexFixtureFactory.Extend(preparers...).
+ android.GroupFixturePreparers(
+ prepareForApexTest,
+ android.GroupFixturePreparers(preparers...),
+ ).
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
RunTestWithBp(t, bp)
}
func testApex(t *testing.T, bp string, preparers ...android.FixturePreparer) *android.TestContext {
t.Helper()
- factory := apexFixtureFactory.Extend(preparers...)
+
+ optionalBpPreparer := android.NullFixturePreparer
if bp != "" {
- factory = factory.Extend(android.FixtureWithRootAndroidBp(bp))
+ optionalBpPreparer = android.FixtureWithRootAndroidBp(bp)
}
- result := factory.RunTest(t)
+
+ result := android.GroupFixturePreparers(
+ prepareForApexTest,
+ android.GroupFixturePreparers(preparers...),
+ optionalBpPreparer,
+ ).RunTest(t)
+
return result.TestContext
}
@@ -117,8 +125,16 @@
},
)
-var apexFixtureFactory = android.NewFixtureFactory(
- &buildDir,
+// Legacy preparer used for running tests within the apex package.
+//
+// This includes everything that was needed to run any test in the apex package prior to the
+// introduction of the test fixtures. Tests that are being converted to use fixtures directly
+// rather than through the testApex...() methods should avoid using this and instead use the
+// various preparers directly, using android.GroupFixturePreparers(...) to group them when
+// necessary.
+//
+// deprecated
+var prepareForApexTest = android.GroupFixturePreparers(
// General preparers in alphabetical order as test infrastructure will enforce correct
// registration order.
android.PrepareForTestWithAndroidBuildComponents,
@@ -140,13 +156,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 +220,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) {
@@ -511,7 +519,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"]
@@ -812,7 +820,7 @@
mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
// Ensure that mylib is linking with the latest version of stubs for mylib2
- ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_3/mylib2.so")
+ ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
// ... and not linking to the non-stub (impl) variant of mylib2
ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
@@ -1290,15 +1298,15 @@
name: "unspecified version links to the latest",
minSdkVersion: "",
apexVariant: "apex10000",
- shouldLink: "30",
- shouldNotLink: []string{"29"},
+ shouldLink: "current",
+ shouldNotLink: []string{"29", "30"},
},
{
name: "always use the latest",
minSdkVersion: "min_sdk_version: \"29\",",
apexVariant: "apex29",
- shouldLink: "30",
- shouldNotLink: []string{"29"},
+ shouldLink: "current",
+ shouldNotLink: []string{"29", "30"},
},
}
for _, tc := range testcases {
@@ -1365,7 +1373,11 @@
}
mylibCFlags := ctx.ModuleForTests("mylib", "android_vendor.VER_arm64_armv8-a_static_"+tc.apexVariant).Rule("cc").Args["cFlags"]
- ensureContains(t, mylibCFlags, "__LIBBAR_API__="+tc.shouldLink)
+ ver := tc.shouldLink
+ if tc.shouldLink == "current" {
+ ver = strconv.Itoa(android.FutureApiLevelInt)
+ }
+ ensureContains(t, mylibCFlags, "__LIBBAR_API__="+ver)
})
}
}
@@ -1427,12 +1439,12 @@
// For dependency to libc
// Ensure that mylib is linking with the latest version of stubs
- ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_29/libc.so")
+ ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_current/libc.so")
// ... and not linking to the non-stub (impl) variant
ensureNotContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared/libc.so")
// ... Cflags from stub is correctly exported to mylib
- ensureContains(t, mylibCFlags, "__LIBC_API__=29")
- ensureContains(t, mylibSharedCFlags, "__LIBC_API__=29")
+ ensureContains(t, mylibCFlags, "__LIBC_API__=10000")
+ ensureContains(t, mylibSharedCFlags, "__LIBC_API__=10000")
// For dependency to libm
// Ensure that mylib is linking with the non-stub (impl) variant
@@ -1538,12 +1550,14 @@
}
// platform liba is linked to non-stub version
expectLink("liba", "shared", "libz", "shared")
- // liba in myapex is linked to #30
- expectLink("liba", "shared_apex29", "libz", "shared_30")
+ // liba in myapex is linked to current
+ expectLink("liba", "shared_apex29", "libz", "shared_current")
+ expectNoLink("liba", "shared_apex29", "libz", "shared_30")
expectNoLink("liba", "shared_apex29", "libz", "shared_28")
expectNoLink("liba", "shared_apex29", "libz", "shared")
- // liba in otherapex is linked to #30
- expectLink("liba", "shared_apex30", "libz", "shared_30")
+ // liba in otherapex is linked to current
+ expectLink("liba", "shared_apex30", "libz", "shared_current")
+ expectNoLink("liba", "shared_apex30", "libz", "shared_30")
expectNoLink("liba", "shared_apex30", "libz", "shared_28")
expectNoLink("liba", "shared_apex30", "libz", "shared")
}
@@ -1594,7 +1608,8 @@
ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
- expectLink("libx", "shared_apex10000", "libz", "shared_R")
+ expectLink("libx", "shared_apex10000", "libz", "shared_current")
+ expectNoLink("libx", "shared_apex10000", "libz", "shared_R")
expectNoLink("libx", "shared_apex10000", "libz", "shared_29")
expectNoLink("libx", "shared_apex10000", "libz", "shared")
}
@@ -1640,8 +1655,9 @@
ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
- expectLink("libx", "shared_apex10000", "libz", "shared_2")
+ expectLink("libx", "shared_apex10000", "libz", "shared_current")
expectNoLink("libx", "shared_apex10000", "libz", "shared_1")
+ expectNoLink("libx", "shared_apex10000", "libz", "shared_2")
expectNoLink("libx", "shared_apex10000", "libz", "shared")
}
@@ -1688,7 +1704,8 @@
ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
- expectLink("libz", "shared", "libx", "shared_2")
+ expectLink("libz", "shared", "libx", "shared_current")
+ expectNoLink("libz", "shared", "libx", "shared_2")
expectNoLink("libz", "shared", "libz", "shared_1")
expectNoLink("libz", "shared", "libz", "shared")
}
@@ -1735,7 +1752,7 @@
libFlags := ld.Args["libFlags"]
ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
- expectLink("libx", "shared_hwasan_apex29", "libbar", "shared_30")
+ expectLink("libx", "shared_hwasan_apex29", "libbar", "shared_current")
}
func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
@@ -1819,6 +1836,30 @@
min_sdk_version: "30",
}
`)
+
+ testApexError(t, `module "libfoo".*: should support min_sdk_version\(29\)`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ java_libs: ["libfoo"],
+ min_sdk_version: "29",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_import {
+ name: "libfoo",
+ jars: ["libfoo.jar"],
+ apex_available: [
+ "myapex",
+ ],
+ min_sdk_version: "30",
+ }
+ `)
}
func TestApexMinSdkVersion_Okay(t *testing.T) {
@@ -1856,7 +1897,10 @@
name: "libbar",
sdk_version: "current",
srcs: ["a.java"],
- static_libs: ["libbar_dep"],
+ static_libs: [
+ "libbar_dep",
+ "libbar_import_dep",
+ ],
apex_available: ["myapex"],
min_sdk_version: "29",
}
@@ -1868,6 +1912,13 @@
apex_available: ["myapex"],
min_sdk_version: "29",
}
+
+ java_import {
+ name: "libbar_import_dep",
+ jars: ["libbar.jar"],
+ apex_available: ["myapex"],
+ min_sdk_version: "29",
+ }
`)
}
@@ -2083,7 +2134,7 @@
private_key: "testkey.pem",
}
- // mylib in myapex will link to mylib2#30
+ // mylib in myapex will link to mylib2#current
// mylib in otherapex will link to mylib2(non-stub) in otherapex as well
cc_library {
name: "mylib",
@@ -2117,7 +2168,7 @@
libFlags := ld.Args["libFlags"]
ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
- expectLink("mylib", "shared_apex29", "mylib2", "shared_30")
+ expectLink("mylib", "shared_apex29", "mylib2", "shared_current")
expectLink("mylib", "shared_apex30", "mylib2", "shared_apex30")
}
@@ -2185,10 +2236,10 @@
}
`, withSAsActiveCodeNames)
- // ensure libfoo is linked with "S" version of libbar stub
+ // ensure libfoo is linked with current version of libbar stub
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_apex10000")
libFlags := libfoo.Rule("ld").Args["libFlags"]
- ensureContains(t, libFlags, "android_arm64_armv8-a_shared_T/libbar.so")
+ ensureContains(t, libFlags, "android_arm64_armv8-a_shared_current/libbar.so")
}
func TestFilesInSubDir(t *testing.T) {
@@ -2464,8 +2515,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")
@@ -2512,10 +2563,10 @@
ldRule := ctx.ModuleForTests("mybin", vendorVariant+"_apex10000").Rule("ld")
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 +4139,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)
}
@@ -4490,14 +4541,11 @@
if filepath.Base(output) == base {
foundLibfooJar = true
buildRule := s.Output(output)
- actual := android.NormalizePathForTesting(buildRule.Input)
- if actual != bootDexJarPath {
- t.Errorf("Incorrect boot dex jar path '%s', expected '%s'", actual, bootDexJarPath)
- }
+ android.AssertStringEquals(t, "boot dex jar path", bootDexJarPath, buildRule.Input.String())
}
}
if !foundLibfooJar {
- t.Errorf("Rule for libfoo.jar missing in dex_bootjars singleton outputs")
+ t.Errorf("Rule for libfoo.jar missing in dex_bootjars singleton outputs %q", android.StringPathsRelativeToTop(ctx.Config().BuildDir(), s.AllOutputs()))
}
}
@@ -4539,8 +4587,8 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- checkBootDexJarPath(t, ctx, "libfoo", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
+ checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
@@ -4646,8 +4694,8 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- checkBootDexJarPath(t, ctx, "libfoo", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
+ checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
@@ -4713,8 +4761,8 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- checkBootDexJarPath(t, ctx, "libfoo", ".intermediates/libfoo/android_common_apex10000/hiddenapi/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", ".intermediates/libbar/android_common_myapex/hiddenapi/libbar.jar")
+ checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/libfoo/android_common_apex10000/hiddenapi/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/libbar/android_common_myapex/hiddenapi/libbar.jar")
// Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
@@ -4782,8 +4830,8 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- checkBootDexJarPath(t, ctx, "libfoo", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
+ checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
@@ -5077,7 +5125,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().RelativeToTop()
// ... embedded inside APK (jnilibs.zip)
ensureListContains(t, appZipRule.Implicits.Strings(), jniOutput.String())
// ... and not directly inside the APEX
@@ -5715,7 +5763,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 +5814,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 +5904,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)
}
}
@@ -5889,9 +5937,10 @@
}
func TestCompatConfig(t *testing.T) {
- result := apexFixtureFactory.
- Extend(java.PrepareForTestWithPlatformCompatConfig).
- RunTestWithBp(t, `
+ result := android.GroupFixturePreparers(
+ prepareForApexTest,
+ java.PrepareForTestWithPlatformCompatConfig,
+ ).RunTestWithBp(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -6327,7 +6376,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 {
@@ -6434,68 +6483,46 @@
func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, transformDexpreoptConfig func(*dexpreopt.GlobalConfig)) *android.TestContext {
t.Helper()
- bp += cc.GatherRequiredDepsForTest(android.Android)
- bp += java.GatherRequiredDepsForTest()
-
- fs := map[string][]byte{
- "a.java": nil,
- "a.jar": nil,
- "build/make/target/product/security": nil,
- "apex_manifest.json": nil,
- "AndroidManifest.xml": nil,
+ fs := android.MockFS{
+ "a.java": nil,
+ "a.jar": nil,
+ "apex_manifest.json": nil,
+ "AndroidManifest.xml": nil,
"system/sepolicy/apex/myapex-file_contexts": nil,
"system/sepolicy/apex/some-updatable-apex-file_contexts": nil,
"system/sepolicy/apex/some-non-updatable-apex-file_contexts": nil,
"system/sepolicy/apex/com.android.art.debug-file_contexts": nil,
"framework/aidl/a.aidl": nil,
}
- cc.GatherRequiredFilesForTest(fs)
- for k, v := range filesForSdkLibrary {
- fs[k] = v
- }
- config := android.TestArchConfig(buildDir, nil, bp, fs)
-
- ctx := android.NewTestArchContext(config)
- ctx.RegisterModuleType("apex", BundleFactory)
- ctx.RegisterModuleType("apex_key", ApexKeyFactory)
- ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
- ctx.PreArchMutators(android.RegisterComponentsMutator)
- android.RegisterPrebuiltMutators(ctx)
- cc.RegisterRequiredBuildComponentsForTest(ctx)
- java.RegisterRequiredBuildComponentsForTest(ctx)
- java.RegisterHiddenApiSingletonComponents(ctx)
- ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
- ctx.PreDepsMutators(RegisterPreDepsMutators)
- ctx.PostDepsMutators(RegisterPostDepsMutators)
-
- ctx.Register()
-
- pathCtx := android.PathContextForTesting(config)
- dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
- transformDexpreoptConfig(dexpreoptConfig)
- dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig)
-
- // Make sure that any changes to these dexpreopt properties are mirrored in the corresponding
- // product variables.
- config.TestProductVariables.BootJars = dexpreoptConfig.BootJars
- config.TestProductVariables.UpdatableBootJars = dexpreoptConfig.UpdatableBootJars
-
- _, errs := ctx.ParseBlueprintsFiles("Android.bp")
- android.FailIfErrored(t, errs)
-
- _, errs = ctx.PrepareBuildActions(config)
- if errmsg == "" {
- android.FailIfErrored(t, errs)
- } else if len(errs) > 0 {
- android.FailIfNoMatchingErrors(t, errmsg, errs)
- } else {
- t.Fatalf("missing expected error %q (0 errors are returned)", errmsg)
+ errorHandler := android.FixtureExpectsNoErrors
+ if errmsg != "" {
+ errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(errmsg)
}
- return ctx
+ result := android.GroupFixturePreparers(
+ cc.PrepareForTestWithCcDefaultModules,
+ java.PrepareForTestWithHiddenApiBuildComponents,
+ java.PrepareForTestWithJavaDefaultModules,
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ PrepareForTestWithApexBuildComponents,
+ android.FixtureModifyConfig(func(config android.Config) {
+ pathCtx := android.PathContextForTesting(config)
+ dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
+ transformDexpreoptConfig(dexpreoptConfig)
+ dexpreopt.SetTestGlobalConfig(config, dexpreoptConfig)
+
+ // Make sure that any changes to these dexpreopt properties are mirrored in the corresponding
+ // product variables.
+ config.TestProductVariables.BootJars = dexpreoptConfig.BootJars
+ config.TestProductVariables.UpdatableBootJars = dexpreoptConfig.UpdatableBootJars
+ }),
+ fs.AddToFixture(),
+ ).
+ ExtendWithErrorHandler(errorHandler).
+ RunTestWithBp(t, bp)
+
+ return result.TestContext
}
func TestUpdatable_should_set_min_sdk_version(t *testing.T) {
@@ -6669,45 +6696,33 @@
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}`
- fs := map[string][]byte{
+ fs := android.MockFS{
"lib1/src/A.java": nil,
"lib2/src/B.java": nil,
"system/sepolicy/apex/myapex-file_contexts": nil,
}
- config := android.TestArchConfig(buildDir, nil, bp, fs)
- android.SetTestNeverallowRules(config, rules)
- updatableBootJars := make([]string, 0, len(apexBootJars))
- for _, apexBootJar := range apexBootJars {
- updatableBootJars = append(updatableBootJars, "myapex:"+apexBootJar)
+ errorHandler := android.FixtureExpectsNoErrors
+ if errmsg != "" {
+ errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(errmsg)
}
- config.TestProductVariables.UpdatableBootJars = android.CreateTestConfiguredJarList(updatableBootJars)
- ctx := android.NewTestArchContext(config)
- ctx.RegisterModuleType("apex", BundleFactory)
- ctx.RegisterModuleType("apex_key", ApexKeyFactory)
- ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
- cc.RegisterRequiredBuildComponentsForTest(ctx)
- java.RegisterRequiredBuildComponentsForTest(ctx)
- ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
- ctx.PreDepsMutators(RegisterPreDepsMutators)
- ctx.PostDepsMutators(RegisterPostDepsMutators)
- ctx.PostDepsMutators(android.RegisterNeverallowMutator)
-
- ctx.Register()
-
- _, errs := ctx.ParseBlueprintsFiles("Android.bp")
- android.FailIfErrored(t, errs)
-
- _, errs = ctx.PrepareBuildActions(config)
- if errmsg == "" {
- android.FailIfErrored(t, errs)
- } else if len(errs) > 0 {
- android.FailIfNoMatchingErrors(t, errmsg, errs)
- return
- } else {
- t.Fatalf("missing expected error %q (0 errors are returned)", errmsg)
- }
+ android.GroupFixturePreparers(
+ android.PrepareForTestWithAndroidBuildComponents,
+ java.PrepareForTestWithJavaBuildComponents,
+ PrepareForTestWithApexBuildComponents,
+ android.PrepareForTestWithNeverallowRules(rules),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ updatableBootJars := make([]string, 0, len(apexBootJars))
+ for _, apexBootJar := range apexBootJars {
+ updatableBootJars = append(updatableBootJars, "myapex:"+apexBootJar)
+ }
+ variables.UpdatableBootJars = android.CreateTestConfiguredJarList(updatableBootJars)
+ }),
+ fs.AddToFixture(),
+ ).
+ ExtendWithErrorHandler(errorHandler).
+ RunTestWithBp(t, bp)
}
func TestApexPermittedPackagesRules(t *testing.T) {
@@ -6859,21 +6874,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").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").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 +6975,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 {
@@ -7383,7 +7454,7 @@
t.Errorf("AndroidMk entry for \"stublib\" has LOCAL_NOT_AVAILABLE_FOR_PLATFORM set: %+v", entry.mkEntries)
}
cflags := entry.mkEntries.EntryMap["LOCAL_EXPORT_CFLAGS"]
- expected := "-D__STUBLIB_API__=1"
+ expected := "-D__STUBLIB_API__=10000"
if !android.InList(expected, cflags) {
t.Errorf("LOCAL_EXPORT_CFLAGS expected to have %q, but got %q", expected, cflags)
}
@@ -7395,12 +7466,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/apex/builder.go b/apex/builder.go
index da800d4..2df380b 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -950,6 +950,10 @@
if v := m.MinSdkVersion(); v != "" {
toMinSdkVersion = v
}
+ } else if m, ok := to.(interface{ MinSdkVersionString() string }); ok {
+ if v := m.MinSdkVersionString(); v != "" {
+ toMinSdkVersion = v
+ }
}
depInfos[to.Name()] = android.ApexModuleDepInfo{
diff --git a/apex/testing.go b/apex/testing.go
index e662cad..926125f 100644
--- a/apex/testing.go
+++ b/apex/testing.go
@@ -19,4 +19,11 @@
var PrepareForTestWithApexBuildComponents = android.GroupFixturePreparers(
android.FixtureRegisterWithContext(registerApexBuildComponents),
android.FixtureRegisterWithContext(registerApexKeyBuildComponents),
+ // Additional files needed in tests that disallow non-existent source files.
+ // This includes files that are needed by all, or at least most, instances of an apex module type.
+ android.MockFS{
+ // Needed by apex.
+ "system/core/rootdir/etc/public.libraries.android.txt": nil,
+ "build/soong/scripts/gen_ndk_backedby_apex.sh": nil,
+ }.AddToFixture(),
)
diff --git a/bazel/aquery.go b/bazel/aquery.go
index c82b464..555f1dc 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -74,6 +74,7 @@
// with a Bazel action from Bazel's action graph.
type BuildStatement struct {
Command string
+ Depfile *string
OutputPaths []string
InputPaths []string
Env []KeyValuePair
@@ -133,12 +134,22 @@
continue
}
outputPaths := []string{}
+ var depfile *string
for _, outputId := range actionEntry.OutputIds {
outputPath, exists := artifactIdToPath[outputId]
if !exists {
return nil, fmt.Errorf("undefined outputId %d", outputId)
}
- outputPaths = append(outputPaths, outputPath)
+ ext := filepath.Ext(outputPath)
+ if ext == ".d" {
+ if depfile != nil {
+ return nil, fmt.Errorf("found multiple potential depfiles %q, %q", *depfile, outputPath)
+ } else {
+ depfile = &outputPath
+ }
+ } else {
+ outputPaths = append(outputPaths, outputPath)
+ }
}
inputPaths := []string{}
for _, inputDepSetId := range actionEntry.InputDepSetIds {
@@ -161,12 +172,13 @@
}
buildStatement := BuildStatement{
Command: strings.Join(proptools.ShellEscapeList(actionEntry.Arguments), " "),
+ Depfile: depfile,
OutputPaths: outputPaths,
InputPaths: inputPaths,
Env: actionEntry.EnvironmentVariables,
Mnemonic: actionEntry.Mnemonic}
if len(actionEntry.Arguments) < 1 {
- return nil, fmt.Errorf("received action with no command: [%s]", buildStatement)
+ return nil, fmt.Errorf("received action with no command: [%v]", buildStatement)
continue
}
buildStatements = append(buildStatements, buildStatement)
diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go
index a48e083..fa8810f 100644
--- a/bazel/aquery_test.go
+++ b/bazel/aquery_test.go
@@ -393,6 +393,109 @@
assertError(t, err, "undefined path fragment id 3")
}
+func TestDepfiles(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [{
+ "id": 1,
+ "pathFragmentId": 1
+ }, {
+ "id": 2,
+ "pathFragmentId": 2
+ }, {
+ "id": 3,
+ "pathFragmentId": 3
+ }],
+ "actions": [{
+ "targetId": 1,
+ "actionKey": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "inputDepSetIds": [1],
+ "outputIds": [2, 3],
+ "primaryOutputId": 2
+ }],
+ "depSetOfFiles": [{
+ "id": 1,
+ "directArtifactIds": [1, 2, 3]
+ }],
+ "pathFragments": [{
+ "id": 1,
+ "label": "one"
+ }, {
+ "id": 2,
+ "label": "two"
+ }, {
+ "id": 3,
+ "label": "two.d"
+ }]
+}`
+
+ actual, err := AqueryBuildStatements([]byte(inputString))
+ if err != nil {
+ t.Errorf("Unexpected error %q", err)
+ }
+ if expected := 1; len(actual) != expected {
+ t.Fatalf("Expected %d build statements, got %d", expected, len(actual))
+ }
+
+ bs := actual[0]
+ expectedDepfile := "two.d"
+ if bs.Depfile == nil {
+ t.Errorf("Expected depfile %q, but there was none found", expectedDepfile)
+ } else if *bs.Depfile != expectedDepfile {
+ t.Errorf("Expected depfile %q, but got %q", expectedDepfile, *bs.Depfile)
+ }
+}
+
+func TestMultipleDepfiles(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [{
+ "id": 1,
+ "pathFragmentId": 1
+ }, {
+ "id": 2,
+ "pathFragmentId": 2
+ }, {
+ "id": 3,
+ "pathFragmentId": 3
+ }, {
+ "id": 4,
+ "pathFragmentId": 4
+ }],
+ "actions": [{
+ "targetId": 1,
+ "actionKey": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "inputDepSetIds": [1],
+ "outputIds": [2,3,4],
+ "primaryOutputId": 2
+ }],
+ "depSetOfFiles": [{
+ "id": 1,
+ "directArtifactIds": [1, 2, 3, 4]
+ }],
+ "pathFragments": [{
+ "id": 1,
+ "label": "one"
+ }, {
+ "id": 2,
+ "label": "two"
+ }, {
+ "id": 3,
+ "label": "two.d"
+ }, {
+ "id": 4,
+ "label": "other.d"
+ }]
+}`
+
+ _, err := AqueryBuildStatements([]byte(inputString))
+ assertError(t, err, `found multiple potential depfiles "two.d", "other.d"`)
+}
+
func TestTransitiveInputDepsets(t *testing.T) {
// The input aquery for this test comes from a proof-of-concept starlark rule which registers
// a single action with many inputs given via a deep depset.
@@ -627,7 +730,7 @@
// Build statement equivalence is determined using buildStatementEquals.
func assertBuildStatements(t *testing.T, expected []BuildStatement, actual []BuildStatement) {
if len(expected) != len(actual) {
- t.Errorf("expected %d build statements, but got %d,\n expected: %s,\n actual: %s",
+ t.Errorf("expected %d build statements, but got %d,\n expected: %v,\n actual: %v",
len(expected), len(actual), expected, actual)
return
}
@@ -638,7 +741,7 @@
continue ACTUAL_LOOP
}
}
- t.Errorf("unexpected build statement %s.\n expected: %s",
+ t.Errorf("unexpected build statement %v.\n expected: %v",
actualStatement, expected)
return
}
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index 864db3d..bd1ece1 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -6,7 +6,6 @@
var (
GetOutputFiles RequestType = &getOutputFilesRequestType{}
- GetCcObjectFiles RequestType = &getCcObjectFilesRequestType{}
GetOutputFilesAndCcObjectFiles RequestType = &getOutputFilesAndCcObjectFilesType{}
)
@@ -16,7 +15,9 @@
}
var RequestTypes []RequestType = []RequestType{
- GetOutputFiles, GetCcObjectFiles, GetOutputFilesAndCcObjectFiles}
+ GetOutputFiles,
+ GetOutputFilesAndCcObjectFiles,
+}
type RequestType interface {
// Name returns a string name for this request type. Such request type names must be unique,
@@ -55,28 +56,6 @@
return strings.Split(rawString, ", ")
}
-type getCcObjectFilesRequestType struct{}
-
-func (g getCcObjectFilesRequestType) Name() string {
- return "getCcObjectFiles"
-}
-
-func (g getCcObjectFilesRequestType) StarlarkFunctionBody() string {
- return `
-result = []
-linker_inputs = providers(target)["CcInfo"].linking_context.linker_inputs.to_list()
-
-for linker_input in linker_inputs:
- for library in linker_input.libraries:
- for object in library.objects:
- result += [object.path]
-return ', '.join(result)`
-}
-
-func (g getCcObjectFilesRequestType) ParseResult(rawString string) interface{} {
- return strings.Split(rawString, ", ")
-}
-
type getOutputFilesAndCcObjectFilesType struct{}
func (g getOutputFilesAndCcObjectFilesType) Name() string {
diff --git a/bazel/properties.go b/bazel/properties.go
index abdc107..250fea4 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "regexp"
"sort"
)
@@ -31,6 +32,8 @@
const BazelTargetModuleNamePrefix = "__bp2build__"
+var productVariableSubstitutionPattern = regexp.MustCompile("%(d|s)")
+
// Label is used to represent a Bazel compatible Label. Also stores the original bp text to support
// string replacement.
type Label struct {
@@ -76,6 +79,174 @@
return uniqueLabelList
}
+const (
+ // ArchType names in arch.go
+ ARCH_ARM = "arm"
+ ARCH_ARM64 = "arm64"
+ ARCH_X86 = "x86"
+ ARCH_X86_64 = "x86_64"
+
+ // OsType names in arch.go
+ OS_ANDROID = "android"
+ OS_DARWIN = "darwin"
+ OS_FUCHSIA = "fuchsia"
+ OS_LINUX = "linux_glibc"
+ OS_LINUX_BIONIC = "linux_bionic"
+ OS_WINDOWS = "windows"
+)
+
+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}
+
+ // Likewise, this is the list of target operating systems.
+ selectableTargetOs = []string{
+ OS_ANDROID,
+ OS_DARWIN,
+ OS_FUCHSIA,
+ OS_LINUX,
+ OS_LINUX_BIONIC,
+ OS_WINDOWS,
+ }
+
+ // A map of architectures to the Bazel label of the constraint_value
+ // for the @platforms//cpu:cpu constraint_setting
+ PlatformArchMap = map[string]string{
+ ARCH_ARM: "//build/bazel/platforms/arch:arm",
+ ARCH_ARM64: "//build/bazel/platforms/arch:arm64",
+ ARCH_X86: "//build/bazel/platforms/arch:x86",
+ ARCH_X86_64: "//build/bazel/platforms/arch:x86_64",
+ }
+
+ // A map of target operating systems to the Bazel label of the
+ // constraint_value for the @platforms//os:os constraint_setting
+ PlatformOsMap = map[string]string{
+ OS_ANDROID: "//build/bazel/platforms/os:android",
+ OS_DARWIN: "//build/bazel/platforms/os:darwin",
+ OS_FUCHSIA: "//build/bazel/platforms/os:fuchsia",
+ OS_LINUX: "//build/bazel/platforms/os:linux",
+ OS_LINUX_BIONIC: "//build/bazel/platforms/os:linux_bionic",
+ OS_WINDOWS: "//build/bazel/platforms/os:windows",
+ }
+)
+
+// 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
+ Common LabelList
+}
+
+type labelListOsValues struct {
+ Android LabelList
+ Darwin LabelList
+ Fuchsia LabelList
+ Linux LabelList
+ LinuxBionic LabelList
+ Windows LabelList
+}
+
+// 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
+
+ // The os-specific attribute label list values. Optional. If used, these
+ // are generated in a select statement and appended to the non-os specific
+ // label list Value.
+ OsValues labelListOsValues
+}
+
+// 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) HasConfigurableValues() bool {
+ for _, arch := range selectableArchs {
+ if len(attrs.GetValueForArch(arch).Includes) > 0 {
+ return true
+ }
+ }
+
+ for _, os := range selectableTargetOs {
+ if len(attrs.GetValueForOS(os).Includes) > 0 {
+ return true
+ }
+ }
+ return false
+}
+
+func (attrs *LabelListAttribute) archValuePtrs() map[string]*LabelList {
+ return map[string]*LabelList{
+ ARCH_X86: &attrs.ArchValues.X86,
+ ARCH_X86_64: &attrs.ArchValues.X86_64,
+ ARCH_ARM: &attrs.ArchValues.Arm,
+ ARCH_ARM64: &attrs.ArchValues.Arm64,
+ }
+}
+
+// GetValueForArch returns the label_list attribute value for an architecture.
+func (attrs *LabelListAttribute) GetValueForArch(arch string) LabelList {
+ var v *LabelList
+ if v = attrs.archValuePtrs()[arch]; v == nil {
+ panic(fmt.Errorf("Unknown arch: %s", arch))
+ }
+ return *v
+}
+
+// SetValueForArch sets the label_list attribute value for an architecture.
+func (attrs *LabelListAttribute) SetValueForArch(arch string, value LabelList) {
+ var v *LabelList
+ if v = attrs.archValuePtrs()[arch]; v == nil {
+ panic(fmt.Errorf("Unknown arch: %s", arch))
+ }
+ *v = value
+}
+
+func (attrs *LabelListAttribute) osValuePtrs() map[string]*LabelList {
+ return map[string]*LabelList{
+ OS_ANDROID: &attrs.OsValues.Android,
+ OS_DARWIN: &attrs.OsValues.Darwin,
+ OS_FUCHSIA: &attrs.OsValues.Fuchsia,
+ OS_LINUX: &attrs.OsValues.Linux,
+ OS_LINUX_BIONIC: &attrs.OsValues.LinuxBionic,
+ OS_WINDOWS: &attrs.OsValues.Windows,
+ }
+}
+
+// GetValueForOS returns the label_list attribute value for an OS target.
+func (attrs *LabelListAttribute) GetValueForOS(os string) LabelList {
+ var v *LabelList
+ if v = attrs.osValuePtrs()[os]; v == nil {
+ panic(fmt.Errorf("Unknown os: %s", os))
+ }
+ return *v
+}
+
+// SetValueForArch sets the label_list attribute value for an OS target.
+func (attrs *LabelListAttribute) SetValueForOS(os string, value LabelList) {
+ var v *LabelList
+ if v = attrs.osValuePtrs()[os]; v == nil {
+ panic(fmt.Errorf("Unknown os: %s", os))
+ }
+ *v = value
+}
+
// StringListAttribute corresponds to the string_list Bazel attribute type with
// support for additional metadata, like configurations.
type StringListAttribute struct {
@@ -89,19 +260,17 @@
// 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
- // TODO(b/181299724): this is currently missing the "common" arch, which
- // doesn't have an equivalent platform() definition yet.
+ X86 []string
+ X86_64 []string
+ Arm []string
+ Arm64 []string
+ Common []string
}
-// HasArchSpecificValues returns true if the attribute contains
+// HasConfigurableValues 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"} {
+func (attrs *StringListAttribute) HasConfigurableValues() bool {
+ for _, arch := range selectableArchs {
if len(attrs.GetValueForArch(arch)) > 0 {
return true
}
@@ -109,38 +278,49 @@
return false
}
+func (attrs *StringListAttribute) archValuePtrs() map[string]*[]string {
+ return map[string]*[]string{
+ ARCH_X86: &attrs.ArchValues.X86,
+ ARCH_X86_64: &attrs.ArchValues.X86_64,
+ ARCH_ARM: &attrs.ArchValues.Arm,
+ ARCH_ARM64: &attrs.ArchValues.Arm64,
+ }
+}
+
// GetValueForArch returns the string_list attribute value for an architecture.
func (attrs *StringListAttribute) GetValueForArch(arch string) []string {
- switch arch {
- case "x86":
- return attrs.ArchValues.X86
- case "x86_64":
- return attrs.ArchValues.X86_64
- case "arm":
- return attrs.ArchValues.Arm
- case "arm64":
- return attrs.ArchValues.Arm64
- case "default":
- return attrs.ArchValues.Default
- default:
+ var v *[]string
+ if v = attrs.archValuePtrs()[arch]; v == nil {
panic(fmt.Errorf("Unknown arch: %s", arch))
}
+ return *v
}
// SetValueForArch sets the string_list attribute value for an architecture.
func (attrs *StringListAttribute) SetValueForArch(arch string, value []string) {
- 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
- case "default":
- attrs.ArchValues.Default = value
- default:
+ var v *[]string
+ if v = attrs.archValuePtrs()[arch]; v == nil {
panic(fmt.Errorf("Unknown arch: %s", arch))
}
+ *v = value
+}
+
+// TryVariableSubstitution, replace string substitution formatting within each string in slice with
+// Starlark string.format compatible tag for productVariable.
+func TryVariableSubstitutions(slice []string, productVariable string) ([]string, bool) {
+ ret := make([]string, 0, len(slice))
+ changesMade := false
+ for _, s := range slice {
+ newS, changed := TryVariableSubstitution(s, productVariable)
+ ret = append(ret, newS)
+ changesMade = changesMade || changed
+ }
+ return ret, changesMade
+}
+
+// TryVariableSubstitution, replace string substitution formatting within s with Starlark
+// string.format compatible tag for productVariable.
+func TryVariableSubstitution(s string, productVariable string) (string, bool) {
+ sub := productVariableSubstitutionPattern.ReplaceAllString(s, "{"+productVariable+"}")
+ return sub, s != sub
}
diff --git a/bloaty/Android.bp b/bloaty/Android.bp
index b1f1e39..96cc1a5 100644
--- a/bloaty/Android.bp
+++ b/bloaty/Android.bp
@@ -1,3 +1,7 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
bootstrap_go_package {
name: "soong-bloaty",
pkgPath: "android/soong/bloaty",
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/Android.bp b/bp2build/Android.bp
index c74f902..cc616f2 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -27,6 +27,7 @@
"build_conversion_test.go",
"bzl_conversion_test.go",
"cc_library_headers_conversion_test.go",
+ "cc_library_static_conversion_test.go",
"cc_object_conversion_test.go",
"conversion_test.go",
"python_binary_conversion_test.go",
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 9c98c76..1d254c8 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,40 +415,12 @@
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 {
- // TODO(b/165114590): convert glob syntax
- return prettyPrint(reflect.ValueOf(labels.Includes), indent)
+ if labels, ok := propertyValue.Interface().(bazel.LabelListAttribute); ok {
+ return prettyPrintLabelListAttribute(labels, indent)
} 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 {
- // A Bazel string_list attribute that may contain a select statement.
- ret, err := prettyPrint(reflect.ValueOf(stringList.Value), indent)
- if err != nil {
- return ret, err
- }
-
- if !stringList.HasArchSpecificValues() {
- // Select statement not needed.
- return ret, nil
- }
-
- ret += " + " + "select({\n"
- for _, arch := range android.ArchTypeList() {
- value := stringList.GetValueForArch(arch.Name)
- if len(value) > 0 {
- ret += makeIndent(indent + 1)
- list, _ := prettyPrint(reflect.ValueOf(value), indent+1)
- ret += fmt.Sprintf("\"%s\": %s,\n", platformArchMap[arch], list)
- }
- }
-
- ret += makeIndent(indent + 1)
- list, _ := prettyPrint(reflect.ValueOf(stringList.GetValueForArch("default")), indent+1)
- ret += fmt.Sprintf("\"%s\": %s,\n", "//conditions:default", list)
-
- ret += makeIndent(indent)
- ret += "})"
- return ret, err
+ return prettyPrintStringListAttribute(stringList, indent)
}
ret = "{\n"
@@ -533,6 +516,13 @@
func escapeString(s string) string {
s = strings.ReplaceAll(s, "\\", "\\\\")
+
+ // b/184026959: Reverse the application of some common control sequences.
+ // These must be generated literally in the BUILD file.
+ s = strings.ReplaceAll(s, "\t", "\\t")
+ s = strings.ReplaceAll(s, "\n", "\\n")
+ s = strings.ReplaceAll(s, "\r", "\\r")
+
return strings.ReplaceAll(s, "\"", "\\\"")
}
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index b9b250a..49897b3 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -241,6 +241,22 @@
string_prop = "a",
)`,
},
+ {
+ bp: `custom {
+ name: "control_characters",
+ string_list_prop: ["\t", "\n"],
+ string_prop: "a\t\n\r",
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedBazelTarget: `custom(
+ name = "control_characters",
+ string_list_prop = [
+ "\t",
+ "\n",
+ ],
+ string_prop = "a\t\n\r",
+)`,
+ },
}
dir := "."
@@ -502,8 +518,6 @@
expectedBazelTargets: []string{
`filegroup(
name = "fg_foo",
- srcs = [
- ],
)`,
},
},
@@ -1101,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_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 5bf5c80..d828168 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -110,21 +110,19 @@
cc_library_headers {
name: "lib-1",
export_include_dirs: ["lib-1"],
- bazel_module: { bp2build_available: true },
}
cc_library_headers {
name: "lib-2",
export_include_dirs: ["lib-2"],
- bazel_module: { bp2build_available: true },
}
cc_library_headers {
name: "foo_headers",
export_include_dirs: ["dir-1", "dir-2"],
header_libs: ["lib-1", "lib-2"],
- export_header_lib_headers: ["lib-1", "lib-2"],
- bazel_module: { bp2build_available: true },
+
+ // TODO: Also support export_header_lib_headers
}`,
expectedBazelTargets: []string{`cc_library_headers(
name = "foo_headers",
@@ -162,6 +160,106 @@
],
)`},
},
+ {
+ description: "cc_library_headers test with os-specific header_libs props",
+ moduleTypeUnderTest: "cc_library_headers",
+ moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryHeadersBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+ filesystem: map[string]string{},
+ bp: soongCcLibraryPreamble + `
+cc_library_headers { name: "android-lib" }
+cc_library_headers { name: "base-lib" }
+cc_library_headers { name: "darwin-lib" }
+cc_library_headers { name: "fuchsia-lib" }
+cc_library_headers { name: "linux-lib" }
+cc_library_headers { name: "linux_bionic-lib" }
+cc_library_headers { name: "windows-lib" }
+cc_library_headers {
+ name: "foo_headers",
+ header_libs: ["base-lib"],
+ target: {
+ android: { header_libs: ["android-lib"] },
+ darwin: { header_libs: ["darwin-lib"] },
+ fuchsia: { header_libs: ["fuchsia-lib"] },
+ linux_bionic: { header_libs: ["linux_bionic-lib"] },
+ linux_glibc: { header_libs: ["linux-lib"] },
+ windows: { header_libs: ["windows-lib"] },
+ },
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedBazelTargets: []string{`cc_library_headers(
+ name = "android-lib",
+)`, `cc_library_headers(
+ name = "base-lib",
+)`, `cc_library_headers(
+ name = "darwin-lib",
+)`, `cc_library_headers(
+ name = "foo_headers",
+ deps = [
+ ":base-lib",
+ ] + select({
+ "//build/bazel/platforms/os:android": [
+ ":android-lib",
+ ],
+ "//build/bazel/platforms/os:darwin": [
+ ":darwin-lib",
+ ],
+ "//build/bazel/platforms/os:fuchsia": [
+ ":fuchsia-lib",
+ ],
+ "//build/bazel/platforms/os:linux": [
+ ":linux-lib",
+ ],
+ "//build/bazel/platforms/os:linux_bionic": [
+ ":linux_bionic-lib",
+ ],
+ "//build/bazel/platforms/os:windows": [
+ ":windows-lib",
+ ],
+ "//conditions:default": [],
+ }),
+)`, `cc_library_headers(
+ name = "fuchsia-lib",
+)`, `cc_library_headers(
+ name = "linux-lib",
+)`, `cc_library_headers(
+ name = "linux_bionic-lib",
+)`, `cc_library_headers(
+ name = "windows-lib",
+)`},
+ },
+ {
+ description: "cc_library_headers test with os-specific header_libs and export_header_lib_headers props",
+ moduleTypeUnderTest: "cc_library_headers",
+ moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryHeadersBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+ filesystem: map[string]string{},
+ bp: soongCcLibraryPreamble + `
+cc_library_headers { name: "android-lib" }
+cc_library_headers { name: "exported-lib" }
+cc_library_headers {
+ name: "foo_headers",
+ target: {
+ android: { header_libs: ["android-lib"], export_header_lib_headers: ["exported-lib"] },
+ },
+}`,
+ expectedBazelTargets: []string{`cc_library_headers(
+ name = "android-lib",
+)`, `cc_library_headers(
+ name = "exported-lib",
+)`, `cc_library_headers(
+ name = "foo_headers",
+ deps = [] + select({
+ "//build/bazel/platforms/os:android": [
+ ":android-lib",
+ ":exported-lib",
+ ],
+ "//conditions:default": [],
+ }),
+)`},
+ },
}
dir := "."
@@ -179,6 +277,9 @@
config := android.TestConfig(buildDir, nil, testCase.bp, filesystem)
ctx := android.NewTestContext(config)
+ // TODO(jingwen): make this default for all bp2build tests
+ ctx.RegisterBp2BuildConfig(bp2buildConfig)
+
cc.RegisterCCBuildComponents(ctx)
ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory)
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
new file mode 100644
index 0000000..7bf5fd3
--- /dev/null
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -0,0 +1,307 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bp2build
+
+import (
+ "android/soong/android"
+ "android/soong/cc"
+ "strings"
+ "testing"
+)
+
+const (
+ // See cc/testing.go for more context
+ soongCcLibraryStaticPreamble = `
+cc_defaults {
+ name: "linux_bionic_supported",
+}
+
+toolchain_library {
+ name: "libclang_rt.builtins-x86_64-android",
+ defaults: ["linux_bionic_supported"],
+ vendor_available: true,
+ vendor_ramdisk_available: true,
+ product_available: true,
+ recovery_available: true,
+ native_bridge_supported: true,
+ src: "",
+}
+
+toolchain_library {
+ name: "libatomic",
+ defaults: ["linux_bionic_supported"],
+ vendor_available: true,
+ vendor_ramdisk_available: true,
+ product_available: true,
+ recovery_available: true,
+ native_bridge_supported: true,
+ src: "",
+}`
+)
+
+func TestCcLibraryStaticLoadStatement(t *testing.T) {
+ testCases := []struct {
+ bazelTargets BazelTargets
+ expectedLoadStatements string
+ }{
+ {
+ bazelTargets: BazelTargets{
+ BazelTarget{
+ name: "cc_library_static_target",
+ ruleClass: "cc_library_static",
+ // NOTE: No bzlLoadLocation for native rules
+ },
+ },
+ expectedLoadStatements: ``,
+ },
+ }
+
+ for _, testCase := range testCases {
+ actual := testCase.bazelTargets.LoadStatements()
+ expected := testCase.expectedLoadStatements
+ if actual != expected {
+ t.Fatalf("Expected load statements to be %s, got %s", expected, actual)
+ }
+ }
+
+}
+
+func TestCcLibraryStaticBp2Build(t *testing.T) {
+ testCases := []struct {
+ description string
+ moduleTypeUnderTest string
+ moduleTypeUnderTestFactory android.ModuleFactory
+ moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
+ preArchMutators []android.RegisterMutatorFunc
+ depsMutators []android.RegisterMutatorFunc
+ bp string
+ expectedBazelTargets []string
+ filesystem map[string]string
+ dir string
+ }{
+ {
+ description: "cc_library_static test",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ filesystem: map[string]string{
+ // NOTE: include_dir headers *should not* appear in Bazel hdrs later (?)
+ "include_dir_1/include_dir_1_a.h": "",
+ "include_dir_1/include_dir_1_b.h": "",
+ "include_dir_2/include_dir_2_a.h": "",
+ "include_dir_2/include_dir_2_b.h": "",
+ // NOTE: local_include_dir headers *should not* appear in Bazel hdrs later (?)
+ "local_include_dir_1/local_include_dir_1_a.h": "",
+ "local_include_dir_1/local_include_dir_1_b.h": "",
+ "local_include_dir_2/local_include_dir_2_a.h": "",
+ "local_include_dir_2/local_include_dir_2_b.h": "",
+ // NOTE: export_include_dir headers *should* appear in Bazel hdrs later
+ "export_include_dir_1/export_include_dir_1_a.h": "",
+ "export_include_dir_1/export_include_dir_1_b.h": "",
+ "export_include_dir_2/export_include_dir_2_a.h": "",
+ "export_include_dir_2/export_include_dir_2_b.h": "",
+ },
+ bp: soongCcLibraryStaticPreamble + `
+cc_library_headers {
+ name: "header_lib_1",
+ export_include_dirs: ["header_lib_1"],
+}
+
+cc_library_headers {
+ name: "header_lib_2",
+ export_include_dirs: ["header_lib_2"],
+}
+
+cc_library_static {
+ name: "static_lib_1",
+ srcs: ["static_lib_1.cc"],
+ bazel_module: { bp2build_available: true },
+}
+
+cc_library_static {
+ name: "static_lib_2",
+ srcs: ["static_lib_2.cc"],
+ bazel_module: { bp2build_available: true },
+}
+
+cc_library_static {
+ name: "whole_static_lib_1",
+ srcs: ["whole_static_lib_1.cc"],
+ bazel_module: { bp2build_available: true },
+}
+
+cc_library_static {
+ name: "whole_static_lib_2",
+ srcs: ["whole_static_lib_2.cc"],
+ bazel_module: { bp2build_available: true },
+}
+
+cc_library_static {
+ name: "foo_static",
+ srcs: [
+ "foo_static1.cc",
+ "foo_static2.cc",
+ ],
+ cflags: [
+ "-Dflag1",
+ "-Dflag2"
+ ],
+ static_libs: [
+ "static_lib_1",
+ "static_lib_2"
+ ],
+ whole_static_libs: [
+ "whole_static_lib_1",
+ "whole_static_lib_2"
+ ],
+ include_dirs: [
+ "include_dir_1",
+ "include_dir_2",
+ ],
+ local_include_dirs: [
+ "local_include_dir_1",
+ "local_include_dir_2",
+ ],
+ export_include_dirs: [
+ "export_include_dir_1",
+ "export_include_dir_2"
+ ],
+ header_libs: [
+ "header_lib_1",
+ "header_lib_2"
+ ],
+
+ // TODO: Also support export_header_lib_headers
+
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedBazelTargets: []string{`cc_library_static(
+ name = "foo_static",
+ copts = [
+ "-Dflag1",
+ "-Dflag2",
+ ],
+ deps = [
+ ":header_lib_1",
+ ":header_lib_2",
+ ":static_lib_1",
+ ":static_lib_2",
+ ":whole_static_lib_1",
+ ":whole_static_lib_2",
+ ],
+ hdrs = [
+ "export_include_dir_1/export_include_dir_1_a.h",
+ "export_include_dir_1/export_include_dir_1_b.h",
+ "export_include_dir_2/export_include_dir_2_a.h",
+ "export_include_dir_2/export_include_dir_2_b.h",
+ ],
+ includes = [
+ "export_include_dir_1",
+ "export_include_dir_2",
+ "include_dir_1",
+ "include_dir_2",
+ "local_include_dir_1",
+ "local_include_dir_2",
+ ],
+ linkstatic = True,
+ srcs = [
+ "foo_static1.cc",
+ "foo_static2.cc",
+ ],
+)`, `cc_library_static(
+ name = "static_lib_1",
+ linkstatic = True,
+ srcs = [
+ "static_lib_1.cc",
+ ],
+)`, `cc_library_static(
+ name = "static_lib_2",
+ linkstatic = True,
+ srcs = [
+ "static_lib_2.cc",
+ ],
+)`, `cc_library_static(
+ name = "whole_static_lib_1",
+ linkstatic = True,
+ srcs = [
+ "whole_static_lib_1.cc",
+ ],
+)`, `cc_library_static(
+ name = "whole_static_lib_2",
+ linkstatic = True,
+ srcs = [
+ "whole_static_lib_2.cc",
+ ],
+)`},
+ },
+ }
+
+ dir := "."
+ for _, testCase := range testCases {
+ filesystem := make(map[string][]byte)
+ toParse := []string{
+ "Android.bp",
+ }
+ for f, content := range testCase.filesystem {
+ if strings.HasSuffix(f, "Android.bp") {
+ toParse = append(toParse, f)
+ }
+ filesystem[f] = []byte(content)
+ }
+ config := android.TestConfig(buildDir, nil, testCase.bp, filesystem)
+ ctx := android.NewTestContext(config)
+
+ cc.RegisterCCBuildComponents(ctx)
+ ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory)
+ ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
+
+ ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
+ for _, m := range testCase.depsMutators {
+ ctx.DepsBp2BuildMutators(m)
+ }
+ ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
+ ctx.RegisterForBazelConversion()
+
+ _, errs := ctx.ParseFileList(dir, toParse)
+ if Errored(t, testCase.description, errs) {
+ continue
+ }
+ _, errs = ctx.ResolveDependencies(config)
+ if Errored(t, testCase.description, errs) {
+ continue
+ }
+
+ checkDir := dir
+ if testCase.dir != "" {
+ checkDir = testCase.dir
+ }
+ codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
+ if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
+ t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
+ } else {
+ for i, target := range bazelTargets {
+ if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
+ t.Errorf(
+ "%s: Expected generated Bazel target to be '%s', got '%s'",
+ testCase.description,
+ w,
+ g,
+ )
+ }
+ }
+ }
+ }
+}
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index 1c058ba..fcc3080 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",
],
)`,
},
@@ -209,6 +209,34 @@
)`,
},
},
+ {
+ description: "cc_object with product variable",
+ moduleTypeUnderTest: "cc_object",
+ moduleTypeUnderTestFactory: cc.ObjectFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ blueprint: `cc_object {
+ name: "foo",
+ include_build_directory: false,
+ product_variables: {
+ platform_sdk_version: {
+ asflags: ["-DPLATFORM_SDK_VERSION=%d"],
+ },
+ },
+
+ bazel_module: { bp2build_available: true },
+}
+`,
+ expectedBazelTargets: []string{`cc_object(
+ name = "foo",
+ asflags = [
+ "-DPLATFORM_SDK_VERSION={Platform_sdk_version}",
+ ],
+ copts = [
+ "-fno-addrsig",
+ ],
+)`,
+ },
+ },
}
dir := "."
@@ -278,9 +306,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 },
@@ -292,15 +324,22 @@
copts = [
"-fno-addrsig",
] + select({
- "@bazel_tools//platforms:x86_32": [
+ "//build/bazel/platforms/arch:x86": [
"-fPIC",
],
- "//conditions:default": [
- ],
+ "//conditions:default": [],
}),
local_include_dirs = [
".",
],
+ srcs = [
+ "a.cpp",
+ ] + select({
+ "//build/bazel/platforms/arch:arm": [
+ "arch/arm/file.S",
+ ],
+ "//conditions:default": [],
+ }),
)`,
},
},
@@ -311,17 +350,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"],
},
},
@@ -334,24 +378,40 @@
copts = [
"-fno-addrsig",
] + select({
- "@bazel_tools//platforms:arm": [
+ "//build/bazel/platforms/arch:arm": [
"-Wall",
],
- "@bazel_tools//platforms:aarch64": [
+ "//build/bazel/platforms/arch:arm64": [
"-Wall",
],
- "@bazel_tools//platforms:x86_32": [
+ "//build/bazel/platforms/arch:x86": [
"-fPIC",
],
- "@bazel_tools//platforms:x86_64": [
+ "//build/bazel/platforms/arch:x86_64": [
"-fPIC",
],
- "//conditions:default": [
- ],
+ "//conditions:default": [],
}),
local_include_dirs = [
".",
],
+ srcs = [
+ "base.cpp",
+ ] + select({
+ "//build/bazel/platforms/arch:arm": [
+ "arm.cpp",
+ ],
+ "//build/bazel/platforms/arch:arm64": [
+ "arm64.cpp",
+ ],
+ "//build/bazel/platforms/arch:x86": [
+ "x86.cpp",
+ ],
+ "//build/bazel/platforms/arch:x86_64": [
+ "x86_64.cpp",
+ ],
+ "//conditions:default": [],
+ }),
)`,
},
},
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
index 47cf3c6..6ca0d6d 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -1,15 +1,112 @@
package bp2build
-import "android/soong/android"
+import (
+ "android/soong/android"
+ "android/soong/bazel"
+ "fmt"
+ "reflect"
+)
// Configurability support for bp2build.
-var (
- // A map of architectures to the Bazel label of the constraint_value.
- platformArchMap = map[android.ArchType]string{
- android.Arm: "@bazel_tools//platforms:arm",
- android.Arm64: "@bazel_tools//platforms:aarch64",
- android.X86: "@bazel_tools//platforms:x86_32",
- android.X86_64: "@bazel_tools//platforms:x86_64",
+// prettyPrintStringListAttribute converts a StringListAttribute to its Bazel
+// syntax. May contain a select statement.
+func prettyPrintStringListAttribute(stringList bazel.StringListAttribute, indent int) (string, error) {
+ ret, err := prettyPrint(reflect.ValueOf(stringList.Value), indent)
+ if err != nil {
+ return ret, err
}
-)
+
+ if !stringList.HasConfigurableValues() {
+ // Select statement not needed.
+ return ret, nil
+ }
+
+ // Create the selects for arch specific values.
+ selects := map[string]reflect.Value{}
+ for arch, selectKey := range bazel.PlatformArchMap {
+ selects[selectKey] = reflect.ValueOf(stringList.GetValueForArch(arch))
+ }
+
+ selectMap, err := prettyPrintSelectMap(selects, "[]", indent)
+ return ret + selectMap, err
+}
+
+// prettyPrintLabelListAttribute converts a LabelListAttribute to its Bazel
+// syntax. May contain select statements.
+func prettyPrintLabelListAttribute(labels bazel.LabelListAttribute, indent int) (string, error) {
+ // TODO(b/165114590): convert glob syntax
+ ret, err := prettyPrint(reflect.ValueOf(labels.Value.Includes), indent)
+ if err != nil {
+ return ret, err
+ }
+
+ if !labels.HasConfigurableValues() {
+ // Select statements not needed.
+ return ret, nil
+ }
+
+ // Create the selects for arch specific values.
+ archSelects := map[string]reflect.Value{}
+ for arch, selectKey := range bazel.PlatformArchMap {
+ archSelects[selectKey] = reflect.ValueOf(labels.GetValueForArch(arch).Includes)
+ }
+ selectMap, err := prettyPrintSelectMap(archSelects, "[]", indent)
+ if err != nil {
+ return "", err
+ }
+ ret += selectMap
+
+ // Create the selects for target os specific values.
+ osSelects := map[string]reflect.Value{}
+ for os, selectKey := range bazel.PlatformOsMap {
+ osSelects[selectKey] = reflect.ValueOf(labels.GetValueForOS(os).Includes)
+ }
+ selectMap, err = prettyPrintSelectMap(osSelects, "[]", indent)
+ return ret + selectMap, err
+}
+
+// prettyPrintSelectMap converts a map of select keys to reflected Values as a generic way
+// to construct a select map for any kind of attribute type.
+func prettyPrintSelectMap(selectMap map[string]reflect.Value, defaultValue string, indent int) (string, error) {
+ var selects string
+ for _, selectKey := range android.SortedStringKeys(selectMap) {
+ value := selectMap[selectKey]
+ if isZero(value) {
+ // Ignore zero values to not generate empty lists.
+ continue
+ }
+ s, err := prettyPrintSelectEntry(value, selectKey, indent)
+ if err != nil {
+ return "", err
+ }
+ selects += s + ",\n"
+ }
+
+ if len(selects) == 0 {
+ // No conditions (or all values are empty lists), so no need for a map.
+ return "", nil
+ }
+
+ // Create the map.
+ ret := " + select({\n"
+ ret += selects
+ // default condition comes last.
+ ret += fmt.Sprintf("%s\"%s\": %s,\n", makeIndent(indent+1), "//conditions:default", defaultValue)
+ ret += makeIndent(indent)
+ ret += "})"
+
+ return ret, nil
+}
+
+// prettyPrintSelectEntry converts a reflect.Value into an entry in a select map
+// with a provided key.
+func prettyPrintSelectEntry(value reflect.Value, key string, indent int) (string, error) {
+ s := makeIndent(indent + 1)
+ v, err := prettyPrint(value, indent+1)
+ if err != nil {
+ return "", err
+ }
+ s += fmt.Sprintf("\"%s\": %s", key, v)
+ return s, nil
+}
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/bp2build/conversion.go b/bp2build/conversion.go
index 787222d..6b47cd1 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -19,12 +19,13 @@
ruleShims map[string]RuleShim,
buildToTargets map[string]BazelTargets,
mode CodegenMode) []BazelFile {
- files := make([]BazelFile, 0, len(ruleShims)+len(buildToTargets)+numAdditionalFiles)
- // Write top level files: WORKSPACE. These files are empty.
- files = append(files, newFile("", "WORKSPACE", ""))
+ var files []BazelFile
if mode == QueryView {
+ // Write top level WORKSPACE.
+ files = append(files, newFile("", "WORKSPACE", ""))
+
// Used to denote that the top level directory is a package.
files = append(files, newFile("", GeneratedBuildFileName, ""))
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index a115ddc..9fd6817 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -24,36 +24,6 @@
basename string
}
-func assertFilecountsAreEqual(t *testing.T, actual []BazelFile, expected []filepath) {
- if a, e := len(actual), len(expected); a != e {
- t.Errorf("Expected %d files, got %d", e, a)
- }
-}
-
-func assertFileContent(t *testing.T, actual []BazelFile, expected []filepath) {
- for i := range actual {
- if g, w := actual[i], expected[i]; g.Dir != w.dir || g.Basename != w.basename {
- t.Errorf("Did not find expected file %s/%s", g.Dir, g.Basename)
- } else if g.Basename == "BUILD" || g.Basename == "WORKSPACE" {
- if g.Contents != "" {
- t.Errorf("Expected %s to have no content.", g)
- }
- } else if g.Contents == "" {
- t.Errorf("Contents of %s unexpected empty.", g)
- }
- }
-}
-
-func sortFiles(files []BazelFile) {
- sort.Slice(files, func(i, j int) bool {
- if dir1, dir2 := files[i].Dir, files[j].Dir; dir1 == dir2 {
- return files[i].Basename < files[j].Basename
- } else {
- return dir1 < dir2
- }
- })
-}
-
func TestCreateBazelFiles_QueryView_AddsTopLevelFiles(t *testing.T) {
files := CreateBazelFiles(map[string]RuleShim{}, map[string]BazelTargets{}, QueryView)
expectedFilePaths := []filepath{
@@ -79,21 +49,39 @@
},
}
- assertFilecountsAreEqual(t, files, expectedFilePaths)
- sortFiles(files)
- assertFileContent(t, files, expectedFilePaths)
-}
-
-func TestCreateBazelFiles_Bp2Build_AddsTopLevelFiles(t *testing.T) {
- files := CreateBazelFiles(map[string]RuleShim{}, map[string]BazelTargets{}, Bp2Build)
- expectedFilePaths := []filepath{
- {
- dir: "",
- basename: "WORKSPACE",
- },
+ // Compare number of files
+ if a, e := len(files), len(expectedFilePaths); a != e {
+ t.Errorf("Expected %d files, got %d", e, a)
}
- assertFilecountsAreEqual(t, files, expectedFilePaths)
- sortFiles(files)
- assertFileContent(t, files, expectedFilePaths)
+ // Sort the files to be deterministic
+ sort.Slice(files, func(i, j int) bool {
+ if dir1, dir2 := files[i].Dir, files[j].Dir; dir1 == dir2 {
+ return files[i].Basename < files[j].Basename
+ } else {
+ return dir1 < dir2
+ }
+ })
+
+ // Compare the file contents
+ for i := range files {
+ actualFile, expectedFile := files[i], expectedFilePaths[i]
+
+ if actualFile.Dir != expectedFile.dir || actualFile.Basename != expectedFile.basename {
+ t.Errorf("Did not find expected file %s/%s", actualFile.Dir, actualFile.Basename)
+ } else if actualFile.Basename == "BUILD" || actualFile.Basename == "WORKSPACE" {
+ if actualFile.Contents != "" {
+ t.Errorf("Expected %s to have no content.", actualFile)
+ }
+ } else if actualFile.Contents == "" {
+ t.Errorf("Contents of %s unexpected empty.", actualFile)
+ }
+ }
+}
+
+func TestCreateBazelFiles_Bp2Build_CreatesNoFilesWithNoTargets(t *testing.T) {
+ files := CreateBazelFiles(map[string]RuleShim{}, map[string]BazelTargets{}, Bp2Build)
+ if len(files) != 0 {
+ t.Errorf("Expected no files, got %d", len(files))
+ }
}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index ede8044..ef3a78f 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -5,6 +5,13 @@
"android/soong/bazel"
)
+var (
+ // A default configuration for tests to not have to specify bp2build_available on top level targets.
+ bp2buildConfig = android.Bp2BuildConfig{
+ android.BP2BUILD_TOPLEVEL: android.Bp2BuildDefaultTrueRecursively,
+ }
+)
+
type nestedProps struct {
Nested_prop string
}
diff --git a/cc/Android.bp b/cc/Android.bp
index bdbb3c0..cc4d9bc 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -10,6 +10,7 @@
"blueprint-pathtools",
"soong",
"soong-android",
+ "soong-bazel",
"soong-cc-config",
"soong-etc",
"soong-genrule",
@@ -19,6 +20,7 @@
"androidmk.go",
"api_level.go",
"builder.go",
+ "bp2build.go",
"cc.go",
"ccdeps.go",
"check.go",
diff --git a/cc/bp2build.go b/cc/bp2build.go
new file mode 100644
index 0000000..2a590eb
--- /dev/null
+++ b/cc/bp2build.go
@@ -0,0 +1,106 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package cc
+
+import (
+ "android/soong/android"
+ "android/soong/bazel"
+)
+
+// bp2build functions and helpers for converting cc_* modules to Bazel.
+
+func init() {
+ android.DepsBp2BuildMutators(RegisterDepsBp2Build)
+}
+
+func RegisterDepsBp2Build(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("cc_bp2build_deps", depsBp2BuildMutator)
+}
+
+// A naive deps mutator to add deps on all modules across all combinations of
+// target props for cc modules. This is needed to make module -> bazel label
+// resolution work in the bp2build mutator later. This is probably
+// the wrong way to do it, but it works.
+//
+// TODO(jingwen): can we create a custom os mutator in depsBp2BuildMutator to do this?
+func depsBp2BuildMutator(ctx android.BottomUpMutatorContext) {
+ module, ok := ctx.Module().(*Module)
+ if !ok {
+ // Not a cc module
+ return
+ }
+
+ if !module.ConvertWithBp2build(ctx) {
+ return
+ }
+
+ var allDeps []string
+
+ for _, p := range module.GetTargetProperties(&BaseLinkerProperties{}) {
+ // arch specific linker props
+ if baseLinkerProps, ok := p.(*BaseLinkerProperties); ok {
+ allDeps = append(allDeps, baseLinkerProps.Header_libs...)
+ allDeps = append(allDeps, baseLinkerProps.Export_header_lib_headers...)
+ }
+ }
+
+ ctx.AddDependency(module, nil, android.SortedUniqueStrings(allDeps)...)
+}
+
+// bp2BuildParseHeaderLibs creates a label list attribute containing the header library deps of a module, including
+// configurable attribute values.
+func bp2BuildParseHeaderLibs(ctx android.TopDownMutatorContext, module *Module) bazel.LabelListAttribute {
+ var ret bazel.LabelListAttribute
+ for _, linkerProps := range module.linker.linkerProps() {
+ if baseLinkerProps, ok := linkerProps.(*BaseLinkerProperties); ok {
+ libs := baseLinkerProps.Header_libs
+ libs = append(libs, baseLinkerProps.Export_header_lib_headers...)
+ ret = bazel.MakeLabelListAttribute(
+ android.BazelLabelForModuleDeps(ctx, android.SortedUniqueStrings(libs)))
+ break
+ }
+ }
+
+ for os, p := range module.GetTargetProperties(&BaseLinkerProperties{}) {
+ if baseLinkerProps, ok := p.(*BaseLinkerProperties); ok {
+ libs := baseLinkerProps.Header_libs
+ libs = append(libs, baseLinkerProps.Export_header_lib_headers...)
+ libs = android.SortedUniqueStrings(libs)
+ ret.SetValueForOS(os.Name, android.BazelLabelForModuleDeps(ctx, libs))
+ }
+ }
+
+ return ret
+}
+
+// bp2BuildParseExportedIncludes creates a label list attribute contains the
+// exported included directories of a module.
+func bp2BuildParseExportedIncludes(ctx android.TopDownMutatorContext, module *Module) (bazel.LabelListAttribute, bazel.LabelListAttribute) {
+ libraryDecorator := module.linker.(*libraryDecorator)
+
+ includeDirs := libraryDecorator.flagExporter.Properties.Export_system_include_dirs
+ includeDirs = append(includeDirs, libraryDecorator.flagExporter.Properties.Export_include_dirs...)
+
+ includeDirsLabels := android.BazelLabelForModuleSrc(ctx, includeDirs)
+
+ var includeDirGlobs []string
+ for _, includeDir := range includeDirs {
+ includeDirGlobs = append(includeDirGlobs, includeDir+"/**/*.h")
+ includeDirGlobs = append(includeDirGlobs, includeDir+"/**/*.inc")
+ includeDirGlobs = append(includeDirGlobs, includeDir+"/**/*.hpp")
+ }
+
+ headersLabels := android.BazelLabelForModuleSrc(ctx, includeDirGlobs)
+ return bazel.MakeLabelListAttribute(includeDirsLabels), bazel.MakeLabelListAttribute(headersLabels)
+}
diff --git a/cc/builder.go b/cc/builder.go
index 4771b89..8c9743f 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -182,11 +182,11 @@
blueprint.RuleParams{
Depfile: "${out}.d",
Deps: blueprint.DepsGCC,
- Command: "CROSS_COMPILE=$crossCompile $tocPath $format -i ${in} -o ${out} -d ${out}.d",
+ Command: "CLANG_BIN=$clangBin $tocPath $format -i ${in} -o ${out} -d ${out}.d",
CommandDeps: []string{"$tocPath"},
Restat: true,
},
- "crossCompile", "format")
+ "clangBin", "format")
// Rule for invoking clang-tidy (a clang-based linter).
clangTidy, clangTidyRE = pctx.RemoteStaticRules("clangTidy",
@@ -918,16 +918,12 @@
outputFile android.WritablePath, flags builderFlags) {
var format string
- var crossCompile string
if ctx.Darwin() {
format = "--macho"
- crossCompile = "${config.MacToolPath}"
} else if ctx.Windows() {
format = "--pe"
- crossCompile = gccCmd(flags.toolchain, "")
} else {
format = "--elf"
- crossCompile = gccCmd(flags.toolchain, "")
}
ctx.Build(pctx, android.BuildParams{
@@ -936,8 +932,8 @@
Output: outputFile,
Input: inputFile,
Args: map[string]string{
- "crossCompile": crossCompile,
- "format": format,
+ "clangBin": "${config.ClangBin}",
+ "format": format,
},
})
}
diff --git a/cc/cc.go b/cc/cc.go
index 0c46b24..0f9a556 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 {
@@ -1363,6 +1363,19 @@
if ver == "apex_inherit" || ver == "" {
ver = ctx.sdkVersion()
}
+ // For crt objects, the meaning of min_sdk_version is very different from other types of
+ // module. For them, min_sdk_version defines the oldest version that the build system will
+ // create versioned variants for. For example, if min_sdk_version is 16, then sdk variant of
+ // the crt object has local variants of 16, 17, ..., up to the latest version. sdk_version
+ // and min_sdk_version properties of the variants are set to the corresponding version
+ // numbers. However, the platform (non-sdk) variant of the crt object is left untouched.
+ // min_sdk_version: 16 doesn't actually mean that the platform variant has to support such
+ // an old version. Since the variant is for the platform, it's preferred to target the
+ // latest version.
+ if ctx.mod.SplitPerApiLevel() && !ctx.isSdkVariant() {
+ ver = strconv.Itoa(android.FutureApiLevelInt)
+ }
+
// Also make sure that minSdkVersion is not greater than sdkVersion, if they are both numbers
sdkVersionInt, err := strconv.Atoi(ctx.sdkVersion())
minSdkVersionInt, err2 := strconv.Atoi(ver)
@@ -1879,8 +1892,8 @@
}
for _, lib := range deps.ReexportStaticLibHeaders {
- if !inList(lib, deps.StaticLibs) {
- ctx.PropertyErrorf("export_static_lib_headers", "Static library not in static_libs: '%s'", lib)
+ if !inList(lib, deps.StaticLibs) && !inList(lib, deps.WholeStaticLibs) {
+ ctx.PropertyErrorf("export_static_lib_headers", "Static library not in static_libs or whole_static_libs: '%s'", lib)
}
}
@@ -1927,9 +1940,14 @@
return nil
}
if m.UseSdk() {
+ // Choose the CRT that best satisfies the min_sdk_version requirement of this module
+ minSdkVersion := m.MinSdkVersion()
+ if minSdkVersion == "" || minSdkVersion == "apex_inherit" {
+ minSdkVersion = m.SdkVersion()
+ }
return []blueprint.Variation{
{Mutator: "sdk", Variation: "sdk"},
- {Mutator: "version", Variation: m.SdkVersion()},
+ {Mutator: "version", Variation: minSdkVersion},
}
}
return []blueprint.Variation{
@@ -2613,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 {
@@ -3249,6 +3284,10 @@
type Defaults struct {
android.ModuleBase
android.DefaultsModuleBase
+ // Included to support setting bazel_module.label for multiple Soong modules to the same Bazel
+ // target. This is primarily useful for modules that were architecture specific and instead are
+ // handled in Bazel as a select().
+ android.BazelModuleBase
android.ApexModuleBase
}
@@ -3295,6 +3334,8 @@
&RustBindgenClangProperties{},
)
+ // Bazel module must be initialized _before_ Defaults to be included in cc_defaults module.
+ android.InitBazelModule(module)
android.InitDefaultsModule(module)
return module
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 7196615..675c020 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -16,7 +16,6 @@
import (
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"reflect"
@@ -27,33 +26,11 @@
"android/soong/android"
)
-var buildDir string
-
-func setUp() {
- var err error
- buildDir, err = ioutil.TempDir("", "soong_cc_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())
}
-var ccFixtureFactory = android.NewFixtureFactory(
- &buildDir,
+var prepareForCcTest = android.GroupFixturePreparers(
PrepareForTestWithCcIncludeVndk,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.DeviceVndkVersion = StringPtr("current")
@@ -62,62 +39,62 @@
}),
)
-// testCcWithConfig runs tests using the ccFixtureFactory
+// testCcWithConfig runs tests using the prepareForCcTest
//
// See testCc for an explanation as to how to stop using this deprecated method.
//
// deprecated
func testCcWithConfig(t *testing.T, config android.Config) *android.TestContext {
t.Helper()
- result := ccFixtureFactory.RunTestWithConfig(t, config)
+ result := prepareForCcTest.RunTestWithConfig(t, config)
return result.TestContext
}
-// testCc runs tests using the ccFixtureFactory
+// testCc runs tests using the prepareForCcTest
//
-// Do not add any new usages of this, instead use the ccFixtureFactory directly as it makes it much
+// Do not add any new usages of this, instead use the prepareForCcTest directly as it makes it much
// easier to customize the test behavior.
//
// If it is necessary to customize the behavior of an existing test that uses this then please first
-// convert the test to using ccFixtureFactory first and then in a following change add the
+// convert the test to using prepareForCcTest first and then in a following change add the
// appropriate fixture preparers. Keeping the conversion change separate makes it easy to verify
// that it did not change the test behavior unexpectedly.
//
// deprecated
func testCc(t *testing.T, bp string) *android.TestContext {
t.Helper()
- result := ccFixtureFactory.RunTestWithBp(t, bp)
+ result := prepareForCcTest.RunTestWithBp(t, bp)
return result.TestContext
}
-// testCcNoVndk runs tests using the ccFixtureFactory
+// testCcNoVndk runs tests using the prepareForCcTest
//
// See testCc for an explanation as to how to stop using this deprecated method.
//
// deprecated
func testCcNoVndk(t *testing.T, bp string) *android.TestContext {
t.Helper()
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
return testCcWithConfig(t, config)
}
-// testCcNoProductVndk runs tests using the ccFixtureFactory
+// testCcNoProductVndk runs tests using the prepareForCcTest
//
// See testCc for an explanation as to how to stop using this deprecated method.
//
// deprecated
func testCcNoProductVndk(t *testing.T, bp string) *android.TestContext {
t.Helper()
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
return testCcWithConfig(t, config)
}
-// testCcErrorWithConfig runs tests using the ccFixtureFactory
+// testCcErrorWithConfig runs tests using the prepareForCcTest
//
// See testCc for an explanation as to how to stop using this deprecated method.
//
@@ -125,33 +102,33 @@
func testCcErrorWithConfig(t *testing.T, pattern string, config android.Config) {
t.Helper()
- ccFixtureFactory.Extend().
+ prepareForCcTest.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
RunTestWithConfig(t, config)
}
-// testCcError runs tests using the ccFixtureFactory
+// testCcError runs tests using the prepareForCcTest
//
// See testCc for an explanation as to how to stop using this deprecated method.
//
// deprecated
func testCcError(t *testing.T, pattern string, bp string) {
t.Helper()
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
testCcErrorWithConfig(t, pattern, config)
return
}
-// testCcErrorProductVndk runs tests using the ccFixtureFactory
+// testCcErrorProductVndk runs tests using the prepareForCcTest
//
// See testCc for an explanation as to how to stop using this deprecated method.
//
// deprecated
func testCcErrorProductVndk(t *testing.T, pattern string, bp string) {
t.Helper()
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.ProductVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
@@ -166,6 +143,15 @@
recoveryVariant = "android_recovery_arm64_armv8-a_shared"
)
+// Test that the PrepareForTestWithCcDefaultModules provides all the files that it uses by
+// running it in a fixture that requires all source files to exist.
+func TestPrepareForTestWithCcDefaultModules(t *testing.T) {
+ android.GroupFixturePreparers(
+ PrepareForTestWithCcDefaultModules,
+ android.PrepareForTestDisallowNonExistentPaths,
+ ).RunTest(t)
+}
+
func TestFuchsiaDeps(t *testing.T) {
t.Helper()
@@ -180,7 +166,10 @@
},
}`
- result := ccFixtureFactory.Extend(PrepareForTestOnFuchsia).RunTestWithBp(t, bp)
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ PrepareForTestOnFuchsia,
+ ).RunTestWithBp(t, bp)
rt := false
fb := false
@@ -216,7 +205,10 @@
},
}`
- result := ccFixtureFactory.Extend(PrepareForTestOnFuchsia).RunTestWithBp(t, bp)
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ PrepareForTestOnFuchsia,
+ ).RunTestWithBp(t, bp)
ld := result.ModuleForTests("libTest", "fuchsia_arm64_shared").Rule("ld")
var objs []string
for _, o := range ld.Inputs {
@@ -292,13 +284,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
}
@@ -324,14 +312,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)
}
@@ -462,7 +453,7 @@
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.ProductVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
@@ -483,7 +474,7 @@
// Check VNDK snapshot output.
snapshotDir := "vndk-snapshot"
- snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
vndkLibPath := filepath.Join(snapshotVariantPath, fmt.Sprintf("arch-%s-%s",
"arm64", "armv8-a"))
@@ -584,7 +575,7 @@
name: "llndk.libraries.txt",
insert_vndk_version: true,
}`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
ctx := testCcWithConfig(t, config)
@@ -634,7 +625,7 @@
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
@@ -661,7 +652,7 @@
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
@@ -712,7 +703,7 @@
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
@@ -1337,7 +1328,7 @@
nocrt: true,
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.ProductVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
@@ -1782,7 +1773,7 @@
nocrt: true,
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.ProductVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
@@ -2109,7 +2100,7 @@
}
`
- ctx := ccFixtureFactory.RunTestWithBp(t, bp).TestContext
+ ctx := prepareForCcTest.RunTestWithBp(t, bp).TestContext
checkVndkModule(t, ctx, "libvndk", "", false, "", productVariant)
checkVndkModule(t, ctx, "libvndk_sp", "", true, "", productVariant)
@@ -2337,7 +2328,7 @@
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
// native:vndk
@@ -2543,7 +2534,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
@@ -2574,7 +2565,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) {
@@ -2608,7 +2600,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) {
@@ -2679,9 +2672,11 @@
expected := []string{
"android_vendor.VER_arm64_armv8-a_shared_1",
"android_vendor.VER_arm64_armv8-a_shared_2",
+ "android_vendor.VER_arm64_armv8-a_shared_current",
"android_vendor.VER_arm64_armv8-a_shared",
"android_vendor.VER_arm_armv7-a-neon_shared_1",
"android_vendor.VER_arm_armv7-a-neon_shared_2",
+ "android_vendor.VER_arm_armv7-a-neon_shared_current",
"android_vendor.VER_arm_armv7-a-neon_shared",
}
checkEquals(t, "variants for llndk stubs", expected, actual)
@@ -3127,7 +3122,7 @@
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
@@ -3181,10 +3176,12 @@
"android_arm64_armv8-a_shared_1",
"android_arm64_armv8-a_shared_2",
"android_arm64_armv8-a_shared_3",
+ "android_arm64_armv8-a_shared_current",
"android_arm_armv7-a-neon_shared",
"android_arm_armv7-a-neon_shared_1",
"android_arm_armv7-a-neon_shared_2",
"android_arm_armv7-a-neon_shared_3",
+ "android_arm_armv7-a-neon_shared_current",
}
variantsMismatch := false
if len(variants) != len(expectedVariants) {
@@ -3371,6 +3368,9 @@
shared: {
srcs: ["baz.c"],
},
+ bazel_module: {
+ bp2build_available: true,
+ },
}
cc_library_static {
@@ -3443,7 +3443,8 @@
}
`
- result := ccFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
android.PrepareForTestWithVariables,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
@@ -3470,7 +3471,8 @@
}
`
- result := ccFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
android.PrepareForTestWithAllowMissingDependencies,
).RunTestWithBp(t, bp)
@@ -3522,7 +3524,7 @@
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
ctx := testCcWithConfig(t, config)
hostBin := ctx.ModuleForTests("bin", config.BuildOSTarget.String()).Description("install")
@@ -3628,6 +3630,71 @@
}
}
+func TestMinSdkVersionInClangTriple(t *testing.T) {
+ ctx := testCc(t, `
+ cc_library_shared {
+ name: "libfoo",
+ srcs: ["foo.c"],
+ min_sdk_version: "29",
+ }`)
+
+ cFlags := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"]
+ android.AssertStringDoesContain(t, "min sdk version", cFlags, "-target aarch64-linux-android29")
+}
+
+func TestMinSdkVersionsOfCrtObjects(t *testing.T) {
+ ctx := testCc(t, `
+ cc_object {
+ name: "crt_foo",
+ srcs: ["foo.c"],
+ crt: true,
+ stl: "none",
+ min_sdk_version: "28",
+
+ }`)
+
+ arch := "android_arm64_armv8-a"
+ for _, v := range []string{"", "28", "29", "30", "current"} {
+ var variant string
+ if v == "" {
+ variant = arch
+ } else {
+ variant = arch + "_sdk_" + v
+ }
+ cflags := ctx.ModuleForTests("crt_foo", variant).Rule("cc").Args["cFlags"]
+ vNum := v
+ if v == "current" || v == "" {
+ vNum = "10000"
+ }
+ expected := "-target aarch64-linux-android" + vNum + " "
+ android.AssertStringDoesContain(t, "cflag", cflags, expected)
+ }
+}
+
+func TestUseCrtObjectOfCorrectVersion(t *testing.T) {
+ ctx := testCc(t, `
+ cc_binary {
+ name: "bin",
+ srcs: ["foo.c"],
+ stl: "none",
+ min_sdk_version: "29",
+ sdk_version: "current",
+ }
+ `)
+
+ // Sdk variant uses the crt object of the matching min_sdk_version
+ variant := "android_arm64_armv8-a_sdk"
+ crt := ctx.ModuleForTests("bin", variant).Rule("ld").Args["crtBegin"]
+ android.AssertStringDoesContain(t, "crt dep of sdk variant", crt,
+ variant+"_29/crtbegin_dynamic.o")
+
+ // platform variant uses the crt object built for platform
+ variant = "android_arm64_armv8-a"
+ crt = ctx.ModuleForTests("bin", variant).Rule("ld").Args["crtBegin"]
+ android.AssertStringDoesContain(t, "crt dep of platform variant", crt,
+ variant+"/crtbegin_dynamic.o")
+}
+
type MemtagNoteType int
const (
@@ -3748,7 +3815,10 @@
func TestSanitizeMemtagHeap(t *testing.T) {
variant := "android_arm64_armv8-a"
- result := ccFixtureFactory.Extend(prepareForTestWithMemtagHeap).RunTest(t)
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ prepareForTestWithMemtagHeap,
+ ).RunTest(t)
ctx := result.TestContext
checkHasMemtagNote(t, ctx.ModuleForTests("default_test", variant), Sync)
@@ -3803,7 +3873,8 @@
func TestSanitizeMemtagHeapWithSanitizeDevice(t *testing.T) {
variant := "android_arm64_armv8-a"
- result := ccFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
prepareForTestWithMemtagHeap,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.SanitizeDevice = []string{"memtag_heap"}
@@ -3863,7 +3934,8 @@
func TestSanitizeMemtagHeapWithSanitizeDeviceDiag(t *testing.T) {
variant := "android_arm64_armv8-a"
- result := ccFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
prepareForTestWithMemtagHeap,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.SanitizeDevice = []string{"memtag_heap"}
diff --git a/cc/compiler.go b/cc/compiler.go
index b09b58e..78a5a5d 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -414,12 +414,7 @@
target := "-target " + tc.ClangTriple()
if ctx.Os().Class == android.Device {
- // When built for the non-updateble part of platform, minSdkVersion doesn't matter.
- // It matters only when building we are building for modules that can be unbundled.
- version := "current"
- if !ctx.isForPlatform() || ctx.isSdkVariant() {
- version = ctx.minSdkVersion()
- }
+ version := ctx.minSdkVersion()
if version == "" || version == "current" {
target += strconv.Itoa(android.FutureApiLevelInt)
} else {
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/genrule_test.go b/cc/genrule_test.go
index fa0c6f2..45b343b 100644
--- a/cc/genrule_test.go
+++ b/cc/genrule_test.go
@@ -52,7 +52,7 @@
},
}
`
- config := android.TestArchConfig(buildDir, nil, bp, fs)
+ config := android.TestArchConfig(t.TempDir(), nil, bp, fs)
ctx := testGenruleContext(config)
diff --git a/cc/library.go b/cc/library.go
index 22a36c6..50fff7f 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -27,6 +27,7 @@
"github.com/google/blueprint/pathtools"
"android/soong/android"
+ "android/soong/bazel"
"android/soong/cc/config"
)
@@ -64,7 +65,8 @@
// symbols that are exported for stubs variant of this library.
Symbol_file *string `android:"path"`
- // List versions to generate stubs libs for.
+ // List versions to generate stubs libs for. The version name "current" is always
+ // implicitly added.
Versions []string
}
@@ -170,6 +172,8 @@
// This variant is a stubs lib
BuildStubs bool `blueprint:"mutated"`
+ // This variant is the latest version
+ IsLatestVersion bool `blueprint:"mutated"`
// Version of the stubs lib
StubsVersion string `blueprint:"mutated"`
// List of all stubs versions associated with an implementation lib
@@ -200,6 +204,8 @@
func init() {
RegisterLibraryBuildComponents(android.InitRegistrationContext)
+
+ android.RegisterBp2BuildMutator("cc_library_static", CcLibraryStaticBp2Build)
}
func RegisterLibraryBuildComponents(ctx android.RegistrationContext) {
@@ -501,12 +507,11 @@
return
}
isLibcxx := strings.HasPrefix(dir, "external/libcxx/include")
- j := 0
- for i, header := range glob {
+ for _, header := range glob {
if isLibcxx {
// Glob all files under this special directory, because of C++ headers with no
// extension.
- if !strings.HasSuffix(header, "/") {
+ if strings.HasSuffix(header, "/") {
continue
}
} else {
@@ -522,12 +527,8 @@
continue
}
}
- if i != j {
- glob[j] = glob[i]
- }
- j++
+ ret = append(ret, android.PathForSource(ctx, header))
}
- glob = glob[:j]
}
// Collect generated headers
@@ -777,7 +778,7 @@
type versionedInterface interface {
buildStubs() bool
- setBuildStubs()
+ setBuildStubs(isLatest bool)
hasStubsVariants() bool
setStubsVersion(string)
stubsVersion() string
@@ -1495,7 +1496,7 @@
if ctx.isVndk() && !ctx.IsVndkExt() {
return
}
- } else if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.directlyInAnyApex() {
+ } else if library.hasStubsVariants() && !ctx.Host() && ctx.directlyInAnyApex() {
// Bionic libraries (e.g. libc.so) is installed to the bootstrap subdirectory.
// The original path becomes a symlink to the corresponding file in the
// runtime APEX.
@@ -1611,11 +1612,29 @@
}
func (library *libraryDecorator) hasStubsVariants() bool {
- return len(library.Properties.Stubs.Versions) > 0
+ // Just having stubs.symbol_file is enough to create a stub variant. In that case
+ // the stub for the future API level is created.
+ return library.Properties.Stubs.Symbol_file != nil ||
+ len(library.Properties.Stubs.Versions) > 0
}
func (library *libraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
- return library.Properties.Stubs.Versions
+ if !library.hasStubsVariants() {
+ return nil
+ }
+
+ // Future API level is implicitly added if there isn't
+ vers := library.Properties.Stubs.Versions
+ if inList(android.FutureApiLevel.String(), vers) {
+ return vers
+ }
+ // In some cases, people use the raw value "10000" in the versions property.
+ // We shouldn't add the future API level in that case, otherwise there will
+ // be two identical versions.
+ if inList(strconv.Itoa(android.FutureApiLevel.FinalOrFutureInt()), vers) {
+ return vers
+ }
+ return append(vers, android.FutureApiLevel.String())
}
func (library *libraryDecorator) setStubsVersion(version string) {
@@ -1626,8 +1645,9 @@
return library.MutatedProperties.StubsVersion
}
-func (library *libraryDecorator) setBuildStubs() {
+func (library *libraryDecorator) setBuildStubs(isLatest bool) {
library.MutatedProperties.BuildStubs = true
+ library.MutatedProperties.IsLatestVersion = isLatest
}
func (library *libraryDecorator) setAllStubsVersions(versions []string) {
@@ -1639,8 +1659,7 @@
}
func (library *libraryDecorator) isLatestStubVersion() bool {
- versions := library.Properties.Stubs.Versions
- return versions[len(versions)-1] == library.stubsVersion()
+ return library.MutatedProperties.IsLatestVersion
}
func (library *libraryDecorator) availableFor(what string) bool {
@@ -1883,7 +1902,8 @@
c.stl = nil
c.Properties.PreventInstall = true
lib := moduleLibraryInterface(m)
- lib.setBuildStubs()
+ isLatest := i == (len(versions) - 1)
+ lib.setBuildStubs(isLatest)
if variants[i] != "" {
// A non-LLNDK stubs module is hidden from make and has a dependency from the
@@ -1914,6 +1934,7 @@
for i, module := range modules {
module.(*Module).Properties.Sdk_version = StringPtr(versionStrs[i])
+ module.(*Module).Properties.Min_sdk_version = StringPtr(versionStrs[i])
}
}
@@ -2024,3 +2045,103 @@
return outputFile
}
+
+type bazelCcLibraryStaticAttributes struct {
+ Copts []string
+ Srcs bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Linkstatic bool
+ Includes bazel.LabelListAttribute
+ Hdrs bazel.LabelListAttribute
+}
+
+type bazelCcLibraryStatic struct {
+ android.BazelTargetModuleBase
+ bazelCcLibraryStaticAttributes
+}
+
+func BazelCcLibraryStaticFactory() android.Module {
+ module := &bazelCcLibraryStatic{}
+ module.AddProperties(&module.bazelCcLibraryStaticAttributes)
+ android.InitBazelTargetModule(module)
+ return module
+}
+
+func CcLibraryStaticBp2Build(ctx android.TopDownMutatorContext) {
+ module, ok := ctx.Module().(*Module)
+ if !ok {
+ // Not a cc module
+ return
+ }
+ if !module.ConvertWithBp2build(ctx) {
+ return
+ }
+ if ctx.ModuleType() != "cc_library_static" {
+ return
+ }
+
+ var copts []string
+ var srcs []string
+ var includeDirs []string
+ var localIncludeDirs []string
+ for _, props := range module.compiler.compilerProps() {
+ if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
+ copts = baseCompilerProps.Cflags
+ srcs = baseCompilerProps.Srcs
+ includeDirs = baseCompilerProps.Include_dirs
+ localIncludeDirs = baseCompilerProps.Local_include_dirs
+ break
+ }
+ }
+ srcsLabels := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, srcs))
+
+ var staticLibs []string
+ var wholeStaticLibs []string
+ for _, props := range module.linker.linkerProps() {
+ if baseLinkerProperties, ok := props.(*BaseLinkerProperties); ok {
+ staticLibs = baseLinkerProperties.Static_libs
+ wholeStaticLibs = baseLinkerProperties.Whole_static_libs
+ break
+ }
+ }
+
+ // FIXME: Treat Static_libs and Whole_static_libs differently?
+ allDeps := staticLibs
+ allDeps = append(allDeps, wholeStaticLibs...)
+
+ depsLabels := android.BazelLabelForModuleDeps(ctx, allDeps)
+
+ // FIXME: Unify absolute vs relative paths
+ // FIXME: Use -I copts instead of setting includes= ?
+ allIncludes := includeDirs
+ allIncludes = append(allIncludes, localIncludeDirs...)
+ includesLabels := android.BazelLabelForModuleSrc(ctx, allIncludes)
+
+ exportedIncludesLabels, exportedIncludesHeadersLabels := bp2BuildParseExportedIncludes(ctx, module)
+ includesLabels.Append(exportedIncludesLabels.Value)
+
+ headerLibsLabels := bp2BuildParseHeaderLibs(ctx, module)
+ depsLabels.Append(headerLibsLabels.Value)
+
+ attrs := &bazelCcLibraryStaticAttributes{
+ Copts: copts,
+ Srcs: srcsLabels,
+ Deps: bazel.MakeLabelListAttribute(depsLabels),
+ Linkstatic: true,
+ Includes: bazel.MakeLabelListAttribute(includesLabels),
+ Hdrs: exportedIncludesHeadersLabels,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_library_static",
+ Bzl_load_location: "//build/bazel/rules:cc_library_static.bzl",
+ }
+
+ ctx.CreateBazelTargetModule(BazelCcLibraryStaticFactory, module.Name(), props, attrs)
+}
+
+func (m *bazelCcLibraryStatic) Name() string {
+ return m.BaseModuleName()
+}
+
+func (m *bazelCcLibraryStatic) GenerateAndroidBuildActions(ctx android.ModuleContext) {}
diff --git a/cc/library_headers.go b/cc/library_headers.go
index 0f4d8a6..c8dd2c2 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 {
@@ -94,35 +94,14 @@
return
}
- lib, _ := module.linker.(*libraryDecorator)
+ exportedIncludesLabels, exportedIncludesHeadersLabels := bp2BuildParseExportedIncludes(ctx, module)
- // list of directories that will be added to the include path (using -I) for this
- // module and any module that links against this module.
- includeDirs := lib.flagExporter.Properties.Export_system_include_dirs
- includeDirs = append(includeDirs, lib.flagExporter.Properties.Export_include_dirs...)
- includeDirLabels := android.BazelLabelForModuleSrc(ctx, includeDirs)
-
- var includeDirGlobs []string
- for _, includeDir := range includeDirs {
- includeDirGlobs = append(includeDirGlobs, includeDir+"/**/*.h")
- }
-
- headerLabels := android.BazelLabelForModuleSrc(ctx, includeDirGlobs)
-
- // list of modules that should only provide headers for this module.
- var headerLibs []string
- for _, linkerProps := range lib.linkerProps() {
- if baseLinkerProps, ok := linkerProps.(*BaseLinkerProperties); ok {
- headerLibs = baseLinkerProps.Export_header_lib_headers
- break
- }
- }
- headerLibLabels := android.BazelLabelForModuleDeps(ctx, headerLibs)
+ headerLibsLabels := bp2BuildParseHeaderLibs(ctx, module)
attrs := &bazelCcLibraryHeadersAttributes{
- Includes: includeDirLabels,
- Hdrs: headerLabels,
- Deps: headerLibLabels,
+ Includes: exportedIncludesLabels,
+ Hdrs: exportedIncludesHeadersLabels,
+ Deps: headerLibsLabels,
}
props := bazel.BazelTargetModuleProperties{
diff --git a/cc/library_test.go b/cc/library_test.go
index 49838b4..7975275 100644
--- a/cc/library_test.go
+++ b/cc/library_test.go
@@ -199,7 +199,7 @@
},
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
ctx := testCcWithConfig(t, config)
@@ -222,7 +222,7 @@
},
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.Platform_version_active_codenames = []string{"R"}
testCcErrorWithConfig(t, `"libfoo" .*: versions: not sorted`, config)
}
diff --git a/cc/linkable.go b/cc/linkable.go
index 58919a0..6aa238b 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -111,6 +111,7 @@
InProduct() bool
SdkVersion() string
+ MinSdkVersion() string
AlwaysSdk() bool
IsSdkVariant() bool
@@ -157,8 +158,16 @@
}
// StaticDepTag returns the dependency tag for any C++ static libraries.
-func StaticDepTag() blueprint.DependencyTag {
- return libraryDependencyTag{Kind: staticLibraryDependency}
+func StaticDepTag(wholeStatic bool) blueprint.DependencyTag {
+ return libraryDependencyTag{Kind: staticLibraryDependency, wholeStatic: wholeStatic}
+}
+
+// IsWholeStaticLib whether a dependency tag is a whole static library dependency.
+func IsWholeStaticLib(depTag blueprint.DependencyTag) bool {
+ if tag, ok := depTag.(libraryDependencyTag); ok {
+ return tag.wholeStatic
+ }
+ return false
}
// HeaderDepTag returns the dependency tag for any C++ "header-only" libraries.
diff --git a/cc/linker.go b/cc/linker.go
index 6d0d416..21281d2 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -599,21 +599,20 @@
_ = pctx.SourcePathVariable("genSortedBssSymbolsPath", "build/soong/scripts/gen_sorted_bss_symbols.sh")
genSortedBssSymbols = pctx.AndroidStaticRule("gen_sorted_bss_symbols",
blueprint.RuleParams{
- Command: "CROSS_COMPILE=$crossCompile $genSortedBssSymbolsPath ${in} ${out}",
- CommandDeps: []string{"$genSortedBssSymbolsPath", "${crossCompile}nm"},
+ Command: "CLANG_BIN=${clangBin} $genSortedBssSymbolsPath ${in} ${out}",
+ CommandDeps: []string{"$genSortedBssSymbolsPath", "${clangBin}/llvm-nm"},
},
- "crossCompile")
+ "clangBin")
)
func (linker *baseLinker) sortBssSymbolsBySize(ctx ModuleContext, in android.Path, symbolOrderingFile android.ModuleOutPath, flags builderFlags) string {
- crossCompile := gccCmd(flags.toolchain, "")
ctx.Build(pctx, android.BuildParams{
Rule: genSortedBssSymbols,
Description: "generate bss symbol order " + symbolOrderingFile.Base(),
Output: symbolOrderingFile,
Input: in,
Args: map[string]string{
- "crossCompile": crossCompile,
+ "clangBin": "${config.ClangBin}",
},
})
return "-Wl,--symbol-ordering-file," + symbolOrderingFile.String()
diff --git a/cc/object.go b/cc/object.go
index 664be8d..ea8d7d3 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -53,8 +53,17 @@
}
func (handler *objectBazelHandler) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
- // TODO(b/181794963): restore mixed builds once cc_object incompatibility resolved
- return false
+ bazelCtx := ctx.Config().BazelContext
+ objPaths, ok := bazelCtx.GetOutputFiles(label, ctx.Arch().ArchType)
+ if ok {
+ if len(objPaths) != 1 {
+ ctx.ModuleErrorf("expected exactly one object file for '%s', but got %s", label, objPaths)
+ return false
+ }
+
+ handler.module.outputFile = android.OptionalPathForPath(android.PathForBazelOut(ctx, objPaths[0]))
+ }
+ return ok
}
type ObjectLinkerProperties struct {
@@ -103,9 +112,10 @@
// For bp2build conversion.
type bazelObjectAttributes struct {
- Srcs bazel.LabelList
- Deps bazel.LabelList
+ Srcs bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
Copts bazel.StringListAttribute
+ Asflags []string
Local_include_dirs []string
}
@@ -147,14 +157,17 @@
// Set arch-specific configurable attributes
var copts bazel.StringListAttribute
- var srcs []string
- var excludeSrcs []string
+ var srcs bazel.LabelListAttribute
var localIncludeDirs []string
+ var asFlags []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,24 +177,43 @@
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))
}
}
+ productVariableProps := android.ProductVariableProperties(ctx)
+ if props, exists := productVariableProps["Asflags"]; exists {
+ // TODO(b/183595873): consider deduplicating handling of product variable properties
+ for _, prop := range props {
+ flags, ok := prop.Property.([]string)
+ if !ok {
+ ctx.ModuleErrorf("Could not convert product variable asflag property")
+ return
+ }
+ // TODO(b/183595873) handle other product variable usages -- as selects?
+ if newFlags, subbed := bazel.TryVariableSubstitutions(flags, prop.ProductConfigVariable); subbed {
+ asFlags = append(asFlags, newFlags...)
+ }
+ }
+ }
+ // TODO(b/183595872) warn/error if we're not handling product variables
+
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,
+ Asflags: asFlags,
Local_include_dirs: localIncludeDirs,
}
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 20274b2..fa6dd87 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -15,7 +15,6 @@
package cc
import (
- "path/filepath"
"testing"
"android/soong/android"
@@ -23,14 +22,17 @@
"github.com/google/blueprint"
)
-var prebuiltFixtureFactory = ccFixtureFactory.Extend(
+var prepareForPrebuiltTest = android.GroupFixturePreparers(
+ prepareForCcTest,
android.PrepareForTestWithAndroidMk,
)
func testPrebuilt(t *testing.T, bp string, fs android.MockFS, handlers ...android.FixturePreparer) *android.TestContext {
- result := prebuiltFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
+ prepareForPrebuiltTest,
fs.AddToFixture(),
- ).Extend(handlers...).RunTestWithBp(t, bp)
+ android.GroupFixturePreparers(handlers...),
+ ).RunTestWithBp(t, bp)
return result.TestContext
}
@@ -302,8 +304,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 +314,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..b9c89c7 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().RelativeToTop().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/cc/testing.go b/cc/testing.go
index d8adc61..6e35655 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -619,11 +619,26 @@
RegisterVndkLibraryTxtTypes(ctx)
}),
+
+ // Additional files needed in tests that disallow non-existent source files.
+ // This includes files that are needed by all, or at least most, instances of a cc module type.
+ android.MockFS{
+ // Needed for ndk_prebuilt_(shared|static)_stl.
+ "prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs": nil,
+ }.AddToFixture(),
)
// Preparer that will define default cc modules, e.g. standard prebuilt modules.
var PrepareForTestWithCcDefaultModules = android.GroupFixturePreparers(
PrepareForTestWithCcBuildComponents,
+
+ // Additional files needed in tests that disallow non-existent source.
+ android.MockFS{
+ "defaults/cc/common/libc.map.txt": nil,
+ "defaults/cc/common/libdl.map.txt": nil,
+ "defaults/cc/common/libm.map.txt": nil,
+ }.AddToFixture(),
+
// Place the default cc test modules that are common to all platforms in a location that will not
// conflict with default test modules defined by other packages.
android.FixtureAddTextFile(DefaultCcCommonTestModulesDir+"Android.bp", commonDefaultModules()),
diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go
index 0833277..8d13ceb 100644
--- a/cc/vendor_snapshot_test.go
+++ b/cc/vendor_snapshot_test.go
@@ -86,7 +86,7 @@
symbol_file: "",
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
ctx := testCcWithConfig(t, config)
@@ -94,7 +94,7 @@
// Check Vendor snapshot output.
snapshotDir := "vendor-snapshot"
- snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
var jsonFiles []string
@@ -212,7 +212,7 @@
nocrt: true,
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
config.TestProductVariables.DirectedVendorSnapshot = true
@@ -224,7 +224,7 @@
// Check Vendor snapshot output.
snapshotDir := "vendor-snapshot"
- snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
var includeJsonFiles []string
@@ -516,7 +516,7 @@
"vndk/libvndk.so": nil,
}
- config := TestConfig(buildDir, android.Android, nil, "", mockFS)
+ config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
config.TestProductVariables.DeviceVndkVersion = StringPtr("BOARD")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
ctx := CreateTestContext(config)
@@ -628,7 +628,7 @@
},
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("BOARD")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
ctx := testCcWithConfig(t, config)
@@ -707,7 +707,7 @@
"device/vendor.cpp": nil,
}
- config := TestConfig(buildDir, android.Android, nil, "", mockFS)
+ config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
ctx := CreateTestContext(config)
@@ -730,7 +730,7 @@
// Verify the content of the vendor snapshot.
snapshotDir := "vendor-snapshot"
- snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
var includeJsonFiles []string
@@ -799,7 +799,7 @@
"device/vendor.cpp": nil,
}
- config := TestConfig(buildDir, android.Android, nil, "", mockFS)
+ config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
ctx := CreateTestContext(config)
@@ -873,7 +873,7 @@
recovery_available: true,
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
ctx := testCcWithConfig(t, config)
@@ -881,7 +881,7 @@
// Check Recovery snapshot output.
snapshotDir := "recovery-snapshot"
- snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
var jsonFiles []string
@@ -991,7 +991,7 @@
"device/recovery.cpp": nil,
}
- config := TestConfig(buildDir, android.Android, nil, "", mockFS)
+ config := TestConfig(t.TempDir(), android.Android, nil, "", mockFS)
config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
ctx := CreateTestContext(config)
@@ -1014,7 +1014,7 @@
// Verify the content of the recovery snapshot.
snapshotDir := "recovery-snapshot"
- snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
var includeJsonFiles []string
@@ -1091,7 +1091,7 @@
nocrt: true,
}
`
- config := TestConfig(buildDir, android.Android, nil, bp, nil)
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.RecoverySnapshotVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("VER")
@@ -1104,7 +1104,7 @@
// Check recovery snapshot output.
snapshotDir := "recovery-snapshot"
- snapshotVariantPath := filepath.Join(buildDir, snapshotDir, "arm64")
+ snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
snapshotSingleton := ctx.SingletonForTests("recovery-snapshot")
var includeJsonFiles []string
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/cmd/soong_build/main.go b/cmd/soong_build/main.go
index e2fc78c..3abf978 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -24,7 +24,6 @@
"time"
"android/soong/shared"
-
"github.com/google/blueprint/bootstrap"
"android/soong/android"
@@ -65,16 +64,10 @@
return android.NewNameResolver(exportFilter)
}
-// bazelConversionRequested checks that the user is intending to convert
-// Blueprint to Bazel BUILD files.
-func bazelConversionRequested(configuration android.Config) bool {
- return configuration.IsEnvTrue("GENERATE_BAZEL_FILES")
-}
-
-func newContext(configuration android.Config) *android.Context {
+func newContext(configuration android.Config, prepareBuildActions bool) *android.Context {
ctx := android.NewContext(configuration)
ctx.Register()
- if !shouldPrepareBuildActions(configuration) {
+ if !prepareBuildActions {
configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
}
ctx.SetNameInterface(newNameResolver(configuration))
@@ -91,6 +84,84 @@
return configuration
}
+// Bazel-enabled mode. Soong runs in two passes.
+// First pass: Analyze the build tree, but only store all bazel commands
+// needed to correctly evaluate the tree in the second pass.
+// TODO(cparsons): Don't output any ninja file, as the second pass will overwrite
+// the incorrect results from the first pass, and file I/O is expensive.
+func runMixedModeBuild(configuration android.Config, firstCtx *android.Context, extraNinjaDeps []string) {
+ configuration.SetStopBefore(bootstrap.StopBeforeWriteNinja)
+ bootstrap.Main(firstCtx.Context, configuration, false, extraNinjaDeps...)
+ // Invoke bazel commands and save results for second pass.
+ if err := configuration.BazelContext.InvokeBazel(); err != nil {
+ fmt.Fprintf(os.Stderr, "%s", err)
+ os.Exit(1)
+ }
+ // Second pass: Full analysis, using the bazel command results. Output ninja file.
+ secondPassConfig, err := android.ConfigForAdditionalRun(configuration)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s", err)
+ os.Exit(1)
+ }
+ secondCtx := newContext(secondPassConfig, true)
+ bootstrap.Main(secondCtx.Context, secondPassConfig, false, extraNinjaDeps...)
+}
+
+// Run the code-generation phase to convert BazelTargetModules to BUILD files.
+func runQueryView(configuration android.Config, ctx *android.Context) {
+ codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.QueryView)
+ absoluteQueryViewDir := shared.JoinPath(topDir, bazelQueryViewDir)
+ if err := createBazelQueryView(codegenContext, absoluteQueryViewDir); err != nil {
+ fmt.Fprintf(os.Stderr, "%s", err)
+ os.Exit(1)
+ }
+}
+
+func runSoongDocs(configuration android.Config, extraNinjaDeps []string) {
+ ctx := newContext(configuration, false)
+ bootstrap.Main(ctx.Context, configuration, false, extraNinjaDeps...)
+ if err := writeDocs(ctx, configuration, docFile); err != nil {
+ fmt.Fprintf(os.Stderr, "%s", err)
+ os.Exit(1)
+ }
+}
+
+func writeMetrics(configuration android.Config) {
+ metricsFile := filepath.Join(bootstrap.CmdlineBuildDir(), "soong_build_metrics.pb")
+ err := android.WriteMetrics(configuration, metricsFile)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error writing soong_build metrics %s: %s", metricsFile, err)
+ os.Exit(1)
+ }
+}
+
+func doChosenActivity(configuration android.Config, extraNinjaDeps []string) {
+ bazelConversionRequested := configuration.IsEnvTrue("GENERATE_BAZEL_FILES")
+ mixedModeBuild := configuration.BazelContext.BazelEnabled()
+ generateQueryView := bazelQueryViewDir != ""
+
+ if bazelConversionRequested {
+ // Run the alternate pipeline of bp2build mutators and singleton to convert
+ // Blueprint to BUILD files before everything else.
+ runBp2Build(configuration, extraNinjaDeps)
+ return
+ }
+
+ ctx := newContext(configuration, !generateQueryView)
+ if mixedModeBuild {
+ runMixedModeBuild(configuration, ctx, extraNinjaDeps)
+ } else {
+ bootstrap.Main(ctx.Context, configuration, false, extraNinjaDeps...)
+ }
+
+ // Convert the Soong module graph into Bazel BUILD files.
+ if generateQueryView {
+ runQueryView(configuration, ctx)
+ return
+ }
+ writeMetrics(configuration)
+}
+
func main() {
flag.Parse()
@@ -101,7 +172,6 @@
usedVariablesFile := shared.JoinPath(outDir, "soong.environment.used")
// The top-level Blueprints file is passed as the first argument.
srcDir := filepath.Dir(flag.Arg(0))
- var ctx *android.Context
configuration := newConfig(srcDir)
extraNinjaDeps := []string{
configuration.ProductVariablesFileName,
@@ -122,72 +192,17 @@
extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve"))
}
- bazelConversionRequested := bazelConversionRequested(configuration)
- if bazelConversionRequested {
- // Run the alternate pipeline of bp2build mutators and singleton to convert Blueprint to BUILD files
- // before everything else.
- runBp2Build(srcDir, configuration, extraNinjaDeps)
- } else if configuration.BazelContext.BazelEnabled() {
- // Bazel-enabled mode. Soong runs in two passes.
- // First pass: Analyze the build tree, but only store all bazel commands
- // needed to correctly evaluate the tree in the second pass.
- // TODO(cparsons): Don't output any ninja file, as the second pass will overwrite
- // the incorrect results from the first pass, and file I/O is expensive.
- firstCtx := newContext(configuration)
- configuration.SetStopBefore(bootstrap.StopBeforeWriteNinja)
- bootstrap.Main(firstCtx.Context, configuration, false, extraNinjaDeps...)
- // Invoke bazel commands and save results for second pass.
- if err := configuration.BazelContext.InvokeBazel(); err != nil {
- fmt.Fprintf(os.Stderr, "%s", err)
- os.Exit(1)
- }
- // Second pass: Full analysis, using the bazel command results. Output ninja file.
- secondPassConfig, err := android.ConfigForAdditionalRun(configuration)
- if err != nil {
- fmt.Fprintf(os.Stderr, "%s", err)
- os.Exit(1)
- }
- ctx = newContext(secondPassConfig)
- bootstrap.Main(ctx.Context, secondPassConfig, false, extraNinjaDeps...)
- } else {
- ctx = newContext(configuration)
- bootstrap.Main(ctx.Context, configuration, false, extraNinjaDeps...)
+ if docFile != "" {
+ // We don't write an used variables file when generating documentation
+ // because that is done from within the actual builds as a Ninja action and
+ // thus it would overwrite the actual used variables file so this is
+ // special-cased.
+ runSoongDocs(configuration, extraNinjaDeps)
+ return
}
- // Convert the Soong module graph into Bazel BUILD files.
- if !bazelConversionRequested && bazelQueryViewDir != "" {
- // Run the code-generation phase to convert BazelTargetModules to BUILD files.
- codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.QueryView)
- absoluteQueryViewDir := shared.JoinPath(topDir, bazelQueryViewDir)
- if err := createBazelQueryView(codegenContext, absoluteQueryViewDir); err != nil {
- fmt.Fprintf(os.Stderr, "%s", err)
- os.Exit(1)
- }
- }
-
- if !bazelConversionRequested && docFile != "" {
- if err := writeDocs(ctx, configuration, docFile); err != nil {
- fmt.Fprintf(os.Stderr, "%s", err)
- os.Exit(1)
- }
- }
-
- // TODO(ccross): make this a command line argument. Requires plumbing through blueprint
- // to affect the command line of the primary builder.
- if !bazelConversionRequested && shouldPrepareBuildActions(configuration) {
- metricsFile := filepath.Join(bootstrap.CmdlineBuildDir(), "soong_build_metrics.pb")
- err := android.WriteMetrics(configuration, metricsFile)
- if err != nil {
- fmt.Fprintf(os.Stderr, "error writing soong_build metrics %s: %s", metricsFile, err)
- os.Exit(1)
- }
- }
-
- if docFile == "" {
- // Let's not overwrite the used variables file when generating
- // documentation
- writeUsedVariablesFile(shared.JoinPath(topDir, usedVariablesFile), configuration)
- }
+ doChosenActivity(configuration, extraNinjaDeps)
+ writeUsedVariablesFile(shared.JoinPath(topDir, usedVariablesFile), configuration)
}
func writeUsedVariablesFile(path string, configuration android.Config) {
@@ -218,7 +233,7 @@
// Run Soong in the bp2build mode. This creates a standalone context that registers
// an alternate pipeline of mutators and singletons specifically for generating
// Bazel BUILD files instead of Ninja files.
-func runBp2Build(srcDir string, configuration android.Config, extraNinjaDeps []string) {
+func runBp2Build(configuration android.Config, extraNinjaDeps []string) {
// Register an alternate set of singletons and mutators for bazel
// conversion for Bazel conversion.
bp2buildCtx := android.NewContext(configuration)
@@ -233,7 +248,7 @@
// configurations or variables, since those will generate different BUILD
// files based on how the user has configured their tree.
bp2buildCtx.SetModuleListFile(bootstrap.CmdlineModuleListFile())
- modulePaths, err := bp2buildCtx.ListModulePaths(srcDir)
+ modulePaths, err := bp2buildCtx.ListModulePaths(configuration.SrcDir())
if err != nil {
panic(err)
}
@@ -283,20 +298,3 @@
[]byte(fmt.Sprintf("%s: \\\n %s\n", ninjaFileName, extraNinjaDepsString)),
0666)
}
-
-// shouldPrepareBuildActions reads configuration and flags if build actions
-// should be generated.
-func shouldPrepareBuildActions(configuration android.Config) bool {
- // Generating Soong docs
- if docFile != "" {
- return false
- }
-
- // Generating a directory for Soong query (queryview)
- if bazelQueryViewDir != "" {
- return false
- }
-
- // Generating a directory for converted Bazel BUILD files
- return !bazelConversionRequested(configuration)
-}
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/filesystem/logical_partition.go b/filesystem/logical_partition.go
index 20d9622..739e609 100644
--- a/filesystem/logical_partition.go
+++ b/filesystem/logical_partition.go
@@ -40,9 +40,14 @@
// Set the name of the output. Defaults to <module_name>.img.
Stem *string
- // Total size of the logical partition
+ // Total size of the logical partition. If set to "auto", total size is automatically
+ // calcaulted as minimum.
Size *string
+ // List of partitions for default group. Default group has no size limit and automatically
+ // minimized when creating an image.
+ Default_group []partitionProperties
+
// List of groups. A group defines a fixed sized region. It can host one or more logical
// partitions and their total size is limited by the size of the group they are in.
Groups []groupProperties
@@ -52,7 +57,7 @@
}
type groupProperties struct {
- // Name of the partition group
+ // Name of the partition group. Can't be "default"; use default_group instead.
Name *string
// Size of the partition group
@@ -92,8 +97,9 @@
// Sparse the filesystem images and calculate their sizes
sparseImages := make(map[string]android.OutputPath)
sparseImageSizes := make(map[string]android.OutputPath)
- for _, group := range l.properties.Groups {
- for _, part := range group.Partitions {
+
+ sparsePartitions := func(partitions []partitionProperties) {
+ for _, part := range partitions {
sparseImg, sizeTxt := sparseFilesystem(ctx, part, builder)
pName := proptools.String(part.Name)
sparseImages[pName] = sparseImg
@@ -101,14 +107,19 @@
}
}
+ for _, group := range l.properties.Groups {
+ sparsePartitions(group.Partitions)
+ }
+
+ sparsePartitions(l.properties.Default_group)
+
cmd := builder.Command().BuiltTool("lpmake")
size := proptools.String(l.properties.Size)
if size == "" {
ctx.PropertyErrorf("size", "must be set")
- }
- if _, err := strconv.Atoi(size); err != nil {
- ctx.PropertyErrorf("size", "must be a number")
+ } else if _, err := strconv.Atoi(size); err != nil && size != "auto" {
+ ctx.PropertyErrorf("size", `must be a number or "auto"`)
}
cmd.FlagWithArg("--device-size=", size)
@@ -123,10 +134,32 @@
groupNames := make(map[string]bool)
partitionNames := make(map[string]bool)
+ addPartitionsToGroup := func(partitions []partitionProperties, gName string) {
+ for _, part := range partitions {
+ pName := proptools.String(part.Name)
+ if pName == "" {
+ ctx.PropertyErrorf("groups.partitions.name", "must be set")
+ }
+ if _, ok := partitionNames[pName]; ok {
+ ctx.PropertyErrorf("groups.partitions.name", "already exists")
+ } else {
+ partitionNames[pName] = true
+ }
+ // Get size of the partition by reading the -size.txt file
+ pSize := fmt.Sprintf("$(cat %s)", sparseImageSizes[pName])
+ cmd.FlagWithArg("--partition=", fmt.Sprintf("%s:readonly:%s:%s", pName, pSize, gName))
+ cmd.FlagWithInput("--image="+pName+"=", sparseImages[pName])
+ }
+ }
+
+ addPartitionsToGroup(l.properties.Default_group, "default")
+
for _, group := range l.properties.Groups {
gName := proptools.String(group.Name)
if gName == "" {
ctx.PropertyErrorf("groups.name", "must be set")
+ } else if gName == "default" {
+ ctx.PropertyErrorf("groups.name", `can't use "default" as a group name. Use default_group instead`)
}
if _, ok := groupNames[gName]; ok {
ctx.PropertyErrorf("group.name", "already exists")
@@ -142,21 +175,7 @@
}
cmd.FlagWithArg("--group=", gName+":"+gSize)
- for _, part := range group.Partitions {
- pName := proptools.String(part.Name)
- if pName == "" {
- ctx.PropertyErrorf("groups.partitions.name", "must be set")
- }
- if _, ok := partitionNames[pName]; ok {
- ctx.PropertyErrorf("groups.partitions.name", "already exists")
- } else {
- partitionNames[pName] = true
- }
- // Get size of the partition by reading the -size.txt file
- pSize := fmt.Sprintf("$(cat %s)", sparseImageSizes[pName])
- cmd.FlagWithArg("--partition=", fmt.Sprintf("%s:readonly:%s:%s", pName, pSize, gName))
- cmd.FlagWithInput("--image="+pName+"=", sparseImages[pName])
- }
+ addPartitionsToGroup(group.Partitions, gName)
}
l.output = android.PathForModuleOut(ctx, l.installFileName()).OutputPath
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 9019a83..d07b002 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -229,11 +229,16 @@
filePaths, ok := bazelCtx.GetOutputFiles(label, ctx.Arch().ArchType)
if ok {
var bazelOutputFiles android.Paths
+ exportIncludeDirs := map[string]bool{}
for _, bazelOutputFile := range filePaths {
bazelOutputFiles = append(bazelOutputFiles, android.PathForBazelOut(ctx, bazelOutputFile))
+ exportIncludeDirs[filepath.Dir(bazelOutputFile)] = true
}
c.outputFiles = bazelOutputFiles
c.outputDeps = bazelOutputFiles
+ for includePath, _ := range exportIncludeDirs {
+ c.exportedIncludeDirs = append(c.exportedIncludeDirs, android.PathForBazelOut(ctx, includePath))
+ }
}
return ok
}
@@ -798,9 +803,9 @@
}
type bazelGenruleAttributes struct {
- Srcs bazel.LabelList
+ Srcs bazel.LabelListAttribute
Outs []string
- Tools bazel.LabelList
+ Tools bazel.LabelListAttribute
Cmd string
}
@@ -828,15 +833,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 +850,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/genrule/genrule_test.go b/genrule/genrule_test.go
index 2ee456d..3f1e9f3 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -670,7 +670,8 @@
cmd: "cat $(in) > $(out)",
}
`
- result := prepareForGenRuleTest.Extend(
+ result := android.GroupFixturePreparers(
+ prepareForGenRuleTest,
android.FixtureModifyConfigAndContext(
func(config android.Config, ctx *android.TestContext) {
config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
diff --git a/java/Android.bp b/java/Android.bp
index b6c14ac..8334b85 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -50,6 +50,7 @@
"kotlin.go",
"lint.go",
"legacy_core_platform_api_usage.go",
+ "platform_bootclasspath.go",
"platform_compat_config.go",
"plugin.go",
"prebuilt_apis.go",
@@ -79,6 +80,7 @@
"java_test.go",
"jdeps_test.go",
"kotlin_test.go",
+ "platform_bootclasspath_test.go",
"platform_compat_config_test.go",
"plugin_test.go",
"rro_test.go",
diff --git a/java/aar.go b/java/aar.go
index 67b9ef0..a122a94 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -163,7 +163,7 @@
a.aaptProperties.RROEnforcedForDependent
}
-func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext,
+func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext android.SdkContext,
manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths,
resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) {
@@ -218,7 +218,7 @@
linkDeps = append(linkDeps, assetDeps...)
// SDK version flags
- minSdkVersion, err := sdkContext.minSdkVersion().effectiveVersionString(ctx)
+ minSdkVersion, err := sdkContext.MinSdkVersion().EffectiveVersionString(ctx)
if err != nil {
ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
}
@@ -266,7 +266,7 @@
CommandDeps: []string{"${config.Zip2ZipCmd}"},
})
-func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext,
+func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkContext,
classLoaderContexts dexpreopt.ClassLoaderContextMap, extraLinkFlags ...string) {
transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags :=
@@ -397,7 +397,7 @@
}
// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
-func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext, classLoaderContexts dexpreopt.ClassLoaderContextMap) (
+func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoaderContexts dexpreopt.ClassLoaderContextMap) (
transitiveStaticLibs, transitiveStaticLibManifests android.Paths, staticRRODirs []rroDir, assets, deps android.Paths, flags []string) {
var sharedLibs android.Paths
@@ -498,7 +498,7 @@
func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
a.Module.deps(ctx)
- sdkDep := decodeSdkDep(ctx, sdkContext(a))
+ sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
if sdkDep.hasFrameworkLibs() {
a.aapt.deps(ctx, sdkDep)
}
@@ -507,7 +507,7 @@
func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.aapt.isLibrary = true
a.classLoaderContexts = make(dexpreopt.ClassLoaderContextMap)
- a.aapt.buildActions(ctx, sdkContext(a), a.classLoaderContexts)
+ a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts)
a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
@@ -625,23 +625,23 @@
}
}
-func (a *AARImport) sdkVersion() sdkSpec {
- return sdkSpecFrom(String(a.properties.Sdk_version))
+func (a *AARImport) SdkVersion() android.SdkSpec {
+ return android.SdkSpecFrom(String(a.properties.Sdk_version))
}
-func (a *AARImport) systemModules() string {
+func (a *AARImport) SystemModules() string {
return ""
}
-func (a *AARImport) minSdkVersion() sdkSpec {
+func (a *AARImport) MinSdkVersion() android.SdkSpec {
if a.properties.Min_sdk_version != nil {
- return sdkSpecFrom(*a.properties.Min_sdk_version)
+ return android.SdkSpecFrom(*a.properties.Min_sdk_version)
}
- return a.sdkVersion()
+ return a.SdkVersion()
}
-func (a *AARImport) targetSdkVersion() sdkSpec {
- return a.sdkVersion()
+func (a *AARImport) TargetSdkVersion() android.SdkSpec {
+ return a.SdkVersion()
}
func (a *AARImport) javaVersion() string {
@@ -700,7 +700,7 @@
func (a *AARImport) DepsMutator(ctx android.BottomUpMutatorContext) {
if !ctx.Config().AlwaysUsePrebuiltSdks() {
- sdkDep := decodeSdkDep(ctx, sdkContext(a))
+ sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
if sdkDep.useModule && sdkDep.frameworkResModule != "" {
ctx.AddVariationDependencies(nil, frameworkResTag, sdkDep.frameworkResModule)
}
@@ -780,7 +780,7 @@
linkDeps = append(linkDeps, a.manifest)
transitiveStaticLibs, staticLibManifests, staticRRODirs, transitiveAssets, libDeps, libFlags :=
- aaptLibs(ctx, sdkContext(a), nil)
+ aaptLibs(ctx, android.SdkContext(a), nil)
_ = staticLibManifests
_ = staticRRODirs
diff --git a/java/android_manifest.go b/java/android_manifest.go
index b30f3d2..6b7395b 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -43,7 +43,7 @@
"args", "libs")
// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
-func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext,
+func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext android.SdkContext,
classLoaderContexts dexpreopt.ClassLoaderContextMap, isLibrary, useEmbeddedNativeLibs, usesNonSdkApis,
useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path {
@@ -51,7 +51,7 @@
if isLibrary {
args = append(args, "--library")
} else {
- minSdkVersion, err := sdkContext.minSdkVersion().effectiveVersion(ctx)
+ minSdkVersion, err := sdkContext.MinSdkVersion().EffectiveVersion(ctx)
if err != nil {
ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
}
@@ -87,7 +87,7 @@
args = append(args, "--logging-parent", loggingParent)
}
var deps android.Paths
- targetSdkVersion, err := sdkContext.targetSdkVersion().effectiveVersionString(ctx)
+ targetSdkVersion, err := sdkContext.TargetSdkVersion().EffectiveVersionString(ctx)
if err != nil {
ctx.ModuleErrorf("invalid targetSdkVersion: %s", err)
}
@@ -96,7 +96,7 @@
deps = append(deps, ApiFingerprintPath(ctx))
}
- minSdkVersion, err := sdkContext.minSdkVersion().effectiveVersionString(ctx)
+ minSdkVersion, err := sdkContext.MinSdkVersion().EffectiveVersionString(ctx)
if err != nil {
ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
}
diff --git a/java/androidmk.go b/java/androidmk.go
index 3d3eae5..75661a7 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -106,7 +106,7 @@
if len(library.dexpreopter.builtInstalled) > 0 {
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", library.dexpreopter.builtInstalled)
}
- entries.SetString("LOCAL_SDK_VERSION", library.sdkVersion().raw)
+ entries.SetString("LOCAL_SDK_VERSION", library.SdkVersion().Raw)
entries.SetPath("LOCAL_SOONG_CLASSES_JAR", library.implementationAndResourcesJar)
entries.SetPath("LOCAL_SOONG_HEADER_JAR", library.headerJarFile)
@@ -255,7 +255,7 @@
entries.SetPath("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", prebuilt.proguardFlags)
entries.SetPath("LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES", prebuilt.extraAaptPackagesFile)
entries.SetPath("LOCAL_FULL_MANIFEST_FILE", prebuilt.manifest)
- entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion().raw)
+ entries.SetString("LOCAL_SDK_VERSION", prebuilt.SdkVersion().Raw)
},
},
}}
diff --git a/java/app.go b/java/app.go
index 1b6e0e3..ec30b49 100755
--- a/java/app.go
+++ b/java/app.go
@@ -213,16 +213,16 @@
func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
a.Module.deps(ctx)
- if String(a.appProperties.Stl) == "c++_shared" && !a.sdkVersion().specified() {
+ if String(a.appProperties.Stl) == "c++_shared" && !a.SdkVersion().Specified() {
ctx.PropertyErrorf("stl", "sdk_version must be set in order to use c++_shared")
}
- sdkDep := decodeSdkDep(ctx, sdkContext(a))
+ sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
if sdkDep.hasFrameworkLibs() {
a.aapt.deps(ctx, sdkDep)
}
- usesSDK := a.sdkVersion().specified() && a.sdkVersion().kind != sdkCorePlatform
+ usesSDK := a.SdkVersion().Specified() && a.SdkVersion().Kind != android.SdkCorePlatform
if usesSDK && Bool(a.appProperties.Jni_uses_sdk_apis) {
ctx.PropertyErrorf("jni_uses_sdk_apis",
@@ -279,14 +279,14 @@
func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
if a.Updatable() {
- if !a.sdkVersion().stable() {
- ctx.PropertyErrorf("sdk_version", "Updatable apps must use stable SDKs, found %v", a.sdkVersion())
+ if !a.SdkVersion().Stable() {
+ ctx.PropertyErrorf("sdk_version", "Updatable apps must use stable SDKs, found %v", a.SdkVersion())
}
if String(a.deviceProperties.Min_sdk_version) == "" {
ctx.PropertyErrorf("updatable", "updatable apps must set min_sdk_version.")
}
- if minSdkVersion, err := a.minSdkVersion().effectiveVersion(ctx); err == nil {
+ if minSdkVersion, err := a.MinSdkVersion().EffectiveVersion(ctx); err == nil {
a.checkJniLibsSdkVersion(ctx, minSdkVersion)
android.CheckMinSdkVersion(a, ctx, minSdkVersion.ApiLevel(ctx))
} else {
@@ -304,7 +304,7 @@
// because, sdk_version is overridden by min_sdk_version (if set as smaller)
// and sdkLinkType is checked with dependencies so we can be sure that the whole dependency tree
// will meet the requirements.
-func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion sdkVersion) {
+func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion android.SdkVersion) {
// It's enough to check direct JNI deps' sdk_version because all transitive deps from JNI deps are checked in cc.checkLinkType()
ctx.VisitDirectDeps(func(m android.Module) {
if !IsJniDepTag(ctx.OtherModuleDependencyTag(m)) {
@@ -312,9 +312,9 @@
}
dep, _ := m.(*cc.Module)
// The domain of cc.sdk_version is "current" and <number>
- // We can rely on sdkSpec to convert it to <number> so that "current" is handled
- // properly regardless of sdk finalization.
- jniSdkVersion, err := sdkSpecFrom(dep.SdkVersion()).effectiveVersion(ctx)
+ // We can rely on android.SdkSpec to convert it to <number> so that "current" is
+ // handled properly regardless of sdk finalization.
+ jniSdkVersion, err := android.SdkSpecFrom(dep.SdkVersion()).EffectiveVersion(ctx)
if err != nil || minSdkVersion < jniSdkVersion {
ctx.OtherModuleErrorf(dep, "sdk_version(%v) is higher than min_sdk_version(%v) of the containing android_app(%v)",
dep.SdkVersion(), minSdkVersion, ctx.ModuleName())
@@ -327,9 +327,9 @@
// Returns true if the native libraries should be stored in the APK uncompressed and the
// extractNativeLibs application flag should be set to false in the manifest.
func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool {
- minSdkVersion, err := a.minSdkVersion().effectiveVersion(ctx)
+ minSdkVersion, err := a.MinSdkVersion().EffectiveVersion(ctx)
if err != nil {
- ctx.PropertyErrorf("min_sdk_version", "invalid value %q: %s", a.minSdkVersion(), err)
+ ctx.PropertyErrorf("min_sdk_version", "invalid value %q: %s", a.MinSdkVersion(), err)
}
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
@@ -419,7 +419,7 @@
a.aapt.splitNames = a.appProperties.Package_splits
a.aapt.LoggingParent = String(a.overridableAppProperties.Logging_parent)
- a.aapt.buildActions(ctx, sdkContext(a), a.classLoaderContexts, aaptLinkFlags...)
+ a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts, aaptLinkFlags...)
// apps manifests are handled by aapt, don't let Module see them
a.properties.Manifest = nil
@@ -720,8 +720,8 @@
}
type appDepsInterface interface {
- sdkVersion() sdkSpec
- minSdkVersion() sdkSpec
+ SdkVersion() android.SdkSpec
+ MinSdkVersion() android.SdkSpec
RequiresStableAPIs(ctx android.BaseModuleContext) bool
}
@@ -734,8 +734,8 @@
seenModulePaths := make(map[string]bool)
if checkNativeSdkVersion {
- checkNativeSdkVersion = app.sdkVersion().specified() &&
- app.sdkVersion().kind != sdkCorePlatform && !app.RequiresStableAPIs(ctx)
+ checkNativeSdkVersion = app.SdkVersion().Specified() &&
+ app.SdkVersion().Kind != android.SdkCorePlatform && !app.RequiresStableAPIs(ctx)
}
ctx.WalkDeps(func(module android.Module, parent android.Module) bool {
@@ -829,6 +829,10 @@
if v := m.MinSdkVersion(); v != "" {
toMinSdkVersion = v
}
+ } else if m, ok := to.(interface{ MinSdkVersionString() string }); ok {
+ if v := m.MinSdkVersionString(); v != "" {
+ toMinSdkVersion = v
+ }
}
depsInfo[depName] = android.ApexModuleDepInfo{
To: depName,
@@ -840,7 +844,7 @@
return true
})
- a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(), depsInfo)
+ a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersionString(), depsInfo)
}
func (a *AndroidApp) Updatable() bool {
@@ -1294,7 +1298,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/app_import.go b/java/app_import.go
index d4da64d..32cec23 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -394,12 +394,12 @@
return false
}
-func (a *AndroidAppImport) sdkVersion() sdkSpec {
- return sdkSpecFrom("")
+func (a *AndroidAppImport) SdkVersion() android.SdkSpec {
+ return android.SdkSpecFrom("")
}
-func (a *AndroidAppImport) minSdkVersion() sdkSpec {
- return sdkSpecFrom("")
+func (a *AndroidAppImport) MinSdkVersion() android.SdkSpec {
+ return android.SdkSpecFrom("")
}
var _ android.ApexModule = (*AndroidAppImport)(nil)
diff --git a/java/app_test.go b/java/app_test.go
index 825ad20..a99ac62 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -652,7 +652,7 @@
} else {
aapt2link = m.Output("package-res.apk")
}
- aapt2link = aapt2link.RelativeToTop()
+ aapt2link = aapt2link
aapt2Flags := aapt2link.Args["flags"]
if test.assetFlag != "" {
android.AssertStringDoesContain(t, "asset flag", aapt2Flags, test.assetFlag)
@@ -1993,14 +1993,14 @@
`)
// Verify baz, which depends on the overridden module foo, has the correct classpath javac arg.
- javac := ctx.ModuleForTests("baz", "android_common").Rule("javac").RelativeToTop()
+ javac := ctx.ModuleForTests("baz", "android_common").Rule("javac")
fooTurbine := "out/soong/.intermediates/foo/android_common/turbine-combined/foo.jar"
if !strings.Contains(javac.Args["classpath"], fooTurbine) {
t.Errorf("baz classpath %v does not contain %q", javac.Args["classpath"], fooTurbine)
}
// Verify qux, which depends on the overriding module bar, has the correct classpath javac arg.
- javac = ctx.ModuleForTests("qux", "android_common").Rule("javac").RelativeToTop()
+ javac = ctx.ModuleForTests("qux", "android_common").Rule("javac")
barTurbine := "out/soong/.intermediates/foo/android_common_bar/turbine-combined/foo.jar"
if !strings.Contains(javac.Args["classpath"], barTurbine) {
t.Errorf("qux classpath %v does not contain %q", javac.Args["classpath"], barTurbine)
@@ -2077,7 +2077,7 @@
}
// Check if javac classpath has the correct jar file path. This checks instrumentation_for overrides.
- javac := variant.Rule("javac").RelativeToTop()
+ javac := variant.Rule("javac")
turbine := filepath.Join("out", "soong", ".intermediates", "foo", expected.targetVariant, "turbine-combined", "foo.jar")
if !strings.Contains(javac.Args["classpath"], turbine) {
t.Errorf("classpath %q does not contain %q", javac.Args["classpath"], turbine)
@@ -2151,7 +2151,7 @@
for _, test := range testCases {
variant := ctx.ModuleForTests(test.moduleName, test.variantName)
- params := variant.MaybeOutput("test_config_fixer/AndroidTest.xml").RelativeToTop()
+ params := variant.MaybeOutput("test_config_fixer/AndroidTest.xml")
if len(test.expectedFlags) > 0 {
if params.Rule == nil {
@@ -2647,14 +2647,14 @@
t.Errorf("GENRULE_NOTICE is missing from notice files, %q", noticeInputs)
}
// aapt2 flags should include -A <NOTICE dir> so that its contents are put in the APK's /assets.
- res := foo.Output("package-res.apk").RelativeToTop()
+ res := foo.Output("package-res.apk")
aapt2Flags := res.Args["flags"]
e := "-A out/soong/.intermediates/foo/android_common/NOTICE"
android.AssertStringDoesContain(t, "expected.apkPath", aapt2Flags, e)
// bar has NOTICE files to process, but embed_notices is not set.
bar := result.ModuleForTests("bar", "android_common")
- res = bar.Output("package-res.apk").RelativeToTop()
+ res = bar.Output("package-res.apk")
aapt2Flags = res.Args["flags"]
e = "-A out/soong/.intermediates/bar/android_common/NOTICE"
android.AssertStringDoesNotContain(t, "bar shouldn't have the asset dir flag for NOTICE", aapt2Flags, e)
diff --git a/java/base.go b/java/base.go
index bd394af..73e5352 100644
--- a/java/base.go
+++ b/java/base.go
@@ -373,11 +373,11 @@
}
func (j *Module) CheckStableSdkVersion() error {
- sdkVersion := j.sdkVersion()
- if sdkVersion.stable() {
+ sdkVersion := j.SdkVersion()
+ if sdkVersion.Stable() {
return nil
}
- if sdkVersion.kind == sdkCorePlatform {
+ if sdkVersion.Kind == android.SdkCorePlatform {
if useLegacyCorePlatformApiByName(j.BaseModuleName()) {
return fmt.Errorf("non stable SDK %v - uses legacy core platform", sdkVersion)
} else {
@@ -392,8 +392,8 @@
// checkSdkVersions enforces restrictions around SDK dependencies.
func (j *Module) checkSdkVersions(ctx android.ModuleContext) {
if j.RequiresStableAPIs(ctx) {
- if sc, ok := ctx.Module().(sdkContext); ok {
- if !sc.sdkVersion().specified() {
+ if sc, ok := ctx.Module().(android.SdkContext); ok {
+ if !sc.SdkVersion().Specified() {
ctx.PropertyErrorf("sdk_version",
"sdk_version must have a value when the module is located at vendor or product(only if PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE is set).")
}
@@ -416,9 +416,9 @@
}
func (j *Module) checkPlatformAPI(ctx android.ModuleContext) {
- if sc, ok := ctx.Module().(sdkContext); ok {
+ if sc, ok := ctx.Module().(android.SdkContext); ok {
usePlatformAPI := proptools.Bool(j.deviceProperties.Platform_apis)
- sdkVersionSpecified := sc.sdkVersion().specified()
+ sdkVersionSpecified := sc.SdkVersion().Specified()
if usePlatformAPI && sdkVersionSpecified {
ctx.PropertyErrorf("platform_apis", "platform_apis must be false when sdk_version is not empty.")
} else if !usePlatformAPI && !sdkVersionSpecified {
@@ -512,30 +512,30 @@
return false
}
-func (j *Module) sdkVersion() sdkSpec {
- return sdkSpecFrom(String(j.deviceProperties.Sdk_version))
+func (j *Module) SdkVersion() android.SdkSpec {
+ return android.SdkSpecFrom(String(j.deviceProperties.Sdk_version))
}
-func (j *Module) systemModules() string {
+func (j *Module) SystemModules() string {
return proptools.String(j.deviceProperties.System_modules)
}
-func (j *Module) minSdkVersion() sdkSpec {
+func (j *Module) MinSdkVersion() android.SdkSpec {
if j.deviceProperties.Min_sdk_version != nil {
- return sdkSpecFrom(*j.deviceProperties.Min_sdk_version)
+ return android.SdkSpecFrom(*j.deviceProperties.Min_sdk_version)
}
- return j.sdkVersion()
+ return j.SdkVersion()
}
-func (j *Module) targetSdkVersion() sdkSpec {
+func (j *Module) TargetSdkVersion() android.SdkSpec {
if j.deviceProperties.Target_sdk_version != nil {
- return sdkSpecFrom(*j.deviceProperties.Target_sdk_version)
+ return android.SdkSpecFrom(*j.deviceProperties.Target_sdk_version)
}
- return j.sdkVersion()
+ return j.SdkVersion()
}
-func (j *Module) MinSdkVersion() string {
- return j.minSdkVersion().version.String()
+func (j *Module) MinSdkVersionString() string {
+ return j.MinSdkVersion().Version.String()
}
func (j *Module) AvailableFor(what string) bool {
@@ -552,7 +552,7 @@
if ctx.Device() {
j.linter.deps(ctx)
- sdkDeps(ctx, sdkContext(j), j.dexer)
+ sdkDeps(ctx, android.SdkContext(j), j.dexer)
if j.deviceProperties.SyspropPublicStub != "" {
// This is a sysprop implementation library that has a corresponding sysprop public
@@ -702,7 +702,7 @@
var flags javaBuilderFlags
// javaVersion flag.
- flags.javaVersion = getJavaVersion(ctx, String(j.properties.Java_version), sdkContext(j))
+ flags.javaVersion = getJavaVersion(ctx, String(j.properties.Java_version), android.SdkContext(j))
if ctx.Config().RunErrorProne() {
if config.ErrorProneClasspath == nil && ctx.Config().TestProductVariables == nil {
@@ -731,7 +731,7 @@
flags.processors = android.FirstUniqueStrings(flags.processors)
if len(flags.bootClasspath) == 0 && ctx.Host() && !flags.javaVersion.usesJavaModules() &&
- decodeSdkDep(ctx, sdkContext(j)).hasStandardLibs() {
+ decodeSdkDep(ctx, android.SdkContext(j)).hasStandardLibs() {
// Give host-side tools a version of OpenJDK's standard libraries
// close to what they're targeting. As of Dec 2017, AOSP is only
// bundling OpenJDK 8 and 9, so nothing < 8 is available.
@@ -1209,7 +1209,7 @@
}
// Dex compilation
var dexOutputFile android.OutputPath
- dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
+ dexOutputFile = j.dexer.compileDex(ctx, flags, j.MinSdkVersion(), outputFile, jarName)
if ctx.Failed() {
return
}
@@ -1254,8 +1254,8 @@
}
if ctx.Device() {
- lintSDKVersionString := func(sdkSpec sdkSpec) string {
- if v := sdkSpec.version; v.isNumbered() {
+ lintSDKVersionString := func(sdkSpec android.SdkSpec) string {
+ if v := sdkSpec.Version; v.IsNumbered() {
return v.String()
} else {
return ctx.Config().DefaultAppTargetSdk(ctx).String()
@@ -1267,9 +1267,9 @@
j.linter.srcJars = srcJars
j.linter.classpath = append(append(android.Paths(nil), flags.bootClasspath...), flags.classpath...)
j.linter.classes = j.implementationJarFile
- j.linter.minSdkVersion = lintSDKVersionString(j.minSdkVersion())
- j.linter.targetSdkVersion = lintSDKVersionString(j.targetSdkVersion())
- j.linter.compileSdkVersion = lintSDKVersionString(j.sdkVersion())
+ j.linter.minSdkVersion = lintSDKVersionString(j.MinSdkVersion())
+ j.linter.targetSdkVersion = lintSDKVersionString(j.TargetSdkVersion())
+ j.linter.compileSdkVersion = lintSDKVersionString(j.SdkVersion())
j.linter.javaLanguageLevel = flags.javaVersion.String()
j.linter.kotlinLanguageLevel = "1.3"
if !apexInfo.IsForPlatform() && ctx.Config().UnbundledBuildApps() {
@@ -1471,14 +1471,14 @@
// Implements android.ApexModule
func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
sdkVersion android.ApiLevel) error {
- sdkSpec := j.minSdkVersion()
- if !sdkSpec.specified() {
+ sdkSpec := j.MinSdkVersion()
+ if !sdkSpec.Specified() {
return fmt.Errorf("min_sdk_version is not specified")
}
- if sdkSpec.kind == sdkCore {
+ if sdkSpec.Kind == android.SdkCore {
return nil
}
- ver, err := sdkSpec.effectiveVersion(ctx)
+ ver, err := sdkSpec.EffectiveVersion(ctx)
if err != nil {
return err
}
@@ -1576,24 +1576,24 @@
return linkType, true
}
- ver := m.sdkVersion()
- switch ver.kind {
- case sdkCore:
+ ver := m.SdkVersion()
+ switch ver.Kind {
+ case android.SdkCore:
return javaCore, false
- case sdkSystem:
+ case android.SdkSystem:
return javaSystem, false
- case sdkPublic:
+ case android.SdkPublic:
return javaSdk, false
- case sdkModule:
+ case android.SdkModule:
return javaModule, false
- case sdkSystemServer:
+ case android.SdkSystemServer:
return javaSystemServer, false
- case sdkPrivate, sdkNone, sdkCorePlatform, sdkTest:
+ case android.SdkPrivate, android.SdkNone, android.SdkCorePlatform, android.SdkTest:
return javaPlatform, false
}
- if !ver.valid() {
- panic(fmt.Errorf("sdk_version is invalid. got %q", ver.raw))
+ if !ver.Valid() {
+ panic(fmt.Errorf("sdk_version is invalid. got %q", ver.Raw))
}
return javaSdk, false
}
@@ -1625,7 +1625,7 @@
var deps deps
if ctx.Device() {
- sdkDep := decodeSdkDep(ctx, sdkContext(j))
+ sdkDep := decodeSdkDep(ctx, android.SdkContext(j))
if sdkDep.invalidVersion {
ctx.AddMissingDependencies(sdkDep.bootclasspath)
ctx.AddMissingDependencies(sdkDep.java9Classpath)
@@ -1656,7 +1656,7 @@
if dep, ok := module.(SdkLibraryDependency); ok {
switch tag {
case libTag:
- deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
+ deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion())...)
case staticLibTag:
ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
}
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/dex.go b/java/dex.go
index b042f13..5c6d41d 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -157,7 +157,7 @@
}, []string{"outDir", "outDict", "outUsage", "outUsageZip", "outUsageDir",
"r8Flags", "zipFlags"}, []string{"implicits"})
-func (d *dexer) dexCommonFlags(ctx android.ModuleContext, minSdkVersion sdkSpec) []string {
+func (d *dexer) dexCommonFlags(ctx android.ModuleContext, minSdkVersion android.SdkSpec) []string {
flags := d.dexProperties.Dxflags
// Translate all the DX flags to D8 ones until all the build files have been migrated
// to D8 flags. See: b/69377755
@@ -174,12 +174,12 @@
"--verbose")
}
- effectiveVersion, err := minSdkVersion.effectiveVersion(ctx)
+ effectiveVersion, err := minSdkVersion.EffectiveVersion(ctx)
if err != nil {
ctx.PropertyErrorf("min_sdk_version", "%s", err)
}
- flags = append(flags, "--min-api "+effectiveVersion.asNumberString())
+ flags = append(flags, "--min-api "+effectiveVersion.AsNumberString())
return flags
}
@@ -266,7 +266,7 @@
return r8Flags, r8Deps
}
-func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, minSdkVersion sdkSpec,
+func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, minSdkVersion android.SdkSpec,
classesJar android.Path, jarName string) android.OutputPath {
// Compile classes.jar into classes.dex and then javalib.jar
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 44308d9..e527d59 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -261,25 +261,25 @@
var _ android.OutputFileProducer = (*Javadoc)(nil)
-func (j *Javadoc) sdkVersion() sdkSpec {
- return sdkSpecFrom(String(j.properties.Sdk_version))
+func (j *Javadoc) SdkVersion() android.SdkSpec {
+ return android.SdkSpecFrom(String(j.properties.Sdk_version))
}
-func (j *Javadoc) systemModules() string {
+func (j *Javadoc) SystemModules() string {
return proptools.String(j.properties.System_modules)
}
-func (j *Javadoc) minSdkVersion() sdkSpec {
- return j.sdkVersion()
+func (j *Javadoc) MinSdkVersion() android.SdkSpec {
+ return j.SdkVersion()
}
-func (j *Javadoc) targetSdkVersion() sdkSpec {
- return j.sdkVersion()
+func (j *Javadoc) TargetSdkVersion() android.SdkSpec {
+ return j.SdkVersion()
}
func (j *Javadoc) addDeps(ctx android.BottomUpMutatorContext) {
if ctx.Device() {
- sdkDep := decodeSdkDep(ctx, sdkContext(j))
+ sdkDep := decodeSdkDep(ctx, android.SdkContext(j))
if sdkDep.useModule {
ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...)
ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
@@ -357,7 +357,7 @@
func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps {
var deps deps
- sdkDep := decodeSdkDep(ctx, sdkContext(j))
+ sdkDep := decodeSdkDep(ctx, android.SdkContext(j))
if sdkDep.invalidVersion {
ctx.AddMissingDependencies(sdkDep.bootclasspath)
ctx.AddMissingDependencies(sdkDep.java9Classpath)
@@ -386,7 +386,7 @@
}
case libTag:
if dep, ok := module.(SdkLibraryDependency); ok {
- deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
+ deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion())...)
} else if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
deps.classpath = append(deps.classpath, dep.HeaderJars...)
@@ -551,7 +551,7 @@
srcJarList := zipSyncCmd(ctx, rule, srcJarDir, j.srcJars)
- javaVersion := getJavaVersion(ctx, String(j.properties.Java_version), sdkContext(j))
+ javaVersion := getJavaVersion(ctx, String(j.properties.Java_version), android.SdkContext(j))
cmd := javadocSystemModulesCmd(ctx, rule, j.srcFiles, outDir, srcJarDir, srcJarList,
deps.systemModules, deps.classpath, j.sourcepaths)
diff --git a/java/droiddoc_test.go b/java/droiddoc_test.go
index 2b324ae..8d1f591 100644
--- a/java/droiddoc_test.go
+++ b/java/droiddoc_test.go
@@ -80,7 +80,7 @@
barStubsOutput := barStubsOutputs[0]
barDoc := ctx.ModuleForTests("bar-doc", "android_common")
- javaDoc := barDoc.Rule("javadoc").RelativeToTop()
+ javaDoc := barDoc.Rule("javadoc")
if g, w := android.PathsRelativeToTop(javaDoc.Implicits), android.PathRelativeToTop(barStubsOutput); !inList(w, g) {
t.Errorf("implicits of bar-doc must contain %q, but was %q.", w, g)
}
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 9644a35..a9e2749 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -439,7 +439,7 @@
func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
deps := d.Javadoc.collectDeps(ctx)
- javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), sdkContext(d))
+ javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
// Create rule for metalava
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index d6c6a2d..5c449e5 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -39,7 +39,8 @@
prepareForJavaTest, PrepareForTestWithHiddenApiBuildComponents)
func TestHiddenAPISingleton(t *testing.T) {
- result := hiddenApiFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
+ hiddenApiFixtureFactory,
fixtureSetBootJarsProductVariable("platform:foo"),
).RunTestWithBp(t, `
java_library {
@@ -50,13 +51,14 @@
`)
hiddenAPI := result.SingletonForTests("hiddenapi")
- hiddenapiRule := hiddenAPI.Rule("hiddenapi").RelativeToTop()
+ hiddenapiRule := hiddenAPI.Rule("hiddenapi")
want := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, want)
}
func TestHiddenAPIIndexSingleton(t *testing.T) {
- result := hiddenApiFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
+ hiddenApiFixtureFactory,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("bar"),
fixtureSetBootJarsProductVariable("platform:foo", "platform:bar"),
@@ -115,7 +117,8 @@
" replaced by the prebuilt module \"prebuilt_foo\" but unfortunately it does not provide a" +
" suitable boot dex jar"
- hiddenApiFixtureFactory.Extend(
+ android.GroupFixturePreparers(
+ hiddenApiFixtureFactory,
fixtureSetBootJarsProductVariable("platform:foo"),
).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(expectedErrorMessage)).
RunTestWithBp(t, `
@@ -134,7 +137,8 @@
}
func TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
- result := hiddenApiFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
+ hiddenApiFixtureFactory,
fixtureSetBootJarsProductVariable("platform:foo"),
).RunTestWithBp(t, `
java_import {
@@ -145,13 +149,14 @@
`)
hiddenAPI := result.SingletonForTests("hiddenapi")
- hiddenapiRule := hiddenAPI.Rule("hiddenapi").RelativeToTop()
+ hiddenapiRule := hiddenAPI.Rule("hiddenapi")
want := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, want)
}
func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) {
- result := hiddenApiFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
+ hiddenApiFixtureFactory,
fixtureSetBootJarsProductVariable("platform:foo"),
).RunTestWithBp(t, `
java_library {
@@ -169,7 +174,7 @@
`)
hiddenAPI := result.SingletonForTests("hiddenapi")
- hiddenapiRule := hiddenAPI.Rule("hiddenapi").RelativeToTop()
+ hiddenapiRule := hiddenAPI.Rule("hiddenapi")
fromSourceJarArg := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, fromSourceJarArg)
@@ -178,7 +183,8 @@
}
func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) {
- result := hiddenApiFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
+ hiddenApiFixtureFactory,
fixtureSetBootJarsProductVariable("platform:foo"),
).RunTestWithBp(t, `
java_library {
@@ -196,7 +202,7 @@
`)
hiddenAPI := result.SingletonForTests("hiddenapi")
- hiddenapiRule := hiddenAPI.Rule("hiddenapi").RelativeToTop()
+ hiddenapiRule := hiddenAPI.Rule("hiddenapi")
prebuiltJarArg := "--boot-dex=out/soong/.intermediates/prebuilt_foo/android_common/dex/foo.jar"
android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, prebuiltJarArg)
@@ -236,7 +242,8 @@
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
- result := hiddenApiFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
+ hiddenApiFixtureFactory,
tc.preparer,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.Always_use_prebuilt_sdks = proptools.BoolPtr(tc.unbundledBuild)
@@ -244,7 +251,7 @@
).RunTest(t)
hiddenAPI := result.SingletonForTests("hiddenapi")
- hiddenapiRule := hiddenAPI.Rule("hiddenapi").RelativeToTop()
+ hiddenapiRule := hiddenAPI.Rule("hiddenapi")
wantPublicStubs := "--public-stub-classpath=" + generateSdkDexPath(tc.publicStub, tc.unbundledBuild)
android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, wantPublicStubs)
@@ -286,7 +293,8 @@
// Where to find the prebuilt hiddenapi files:
prebuiltHiddenApiDir := "path/to/prebuilt/hiddenapi"
- result := hiddenApiFixtureFactory.Extend(
+ result := android.GroupFixturePreparers(
+ hiddenApiFixtureFactory,
fixtureSetBootJarsProductVariable("platform:foo"),
fixtureSetPrebuiltHiddenApiDirProductVariable(&prebuiltHiddenApiDir),
).RunTestWithBp(t, `
@@ -307,7 +315,7 @@
cpRule := hiddenAPI.Rule("Cp")
actualCpInput := cpRule.BuildParams.Input
actualCpOutput := cpRule.BuildParams.Output
- encodeDexRule := foo.Rule("hiddenAPIEncodeDex").RelativeToTop()
+ encodeDexRule := foo.Rule("hiddenAPIEncodeDex")
actualFlagsCsv := encodeDexRule.BuildParams.Args["flagsCsv"]
android.AssertPathRelativeToTopEquals(t, "hiddenapi cp rule input", expectedCpInput, actualCpInput)
diff --git a/java/java.go b/java/java.go
index 9786947..5fe8814 100644
--- a/java/java.go
+++ b/java/java.go
@@ -33,12 +33,12 @@
)
func init() {
- RegisterJavaBuildComponents(android.InitRegistrationContext)
+ registerJavaBuildComponents(android.InitRegistrationContext)
RegisterJavaSdkMemberTypes()
}
-func RegisterJavaBuildComponents(ctx android.RegistrationContext) {
+func registerJavaBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("java_defaults", DefaultsFactory)
ctx.RegisterModuleType("java_library", LibraryFactory)
@@ -304,7 +304,7 @@
unstrippedFile android.Path
}
-func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext sdkContext, d dexer) {
+func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, d dexer) {
sdkDep := decodeSdkDep(ctx, sdkContext)
if sdkDep.useModule {
ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...)
@@ -352,11 +352,11 @@
}
}
-func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext sdkContext) javaVersion {
+func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext android.SdkContext) javaVersion {
if javaVersion != "" {
return normalizeJavaVersion(ctx, javaVersion)
} else if ctx.Device() {
- return sdkContext.sdkVersion().defaultJavaLanguageVersion(ctx)
+ return defaultJavaLanguageVersion(ctx, sdkContext.SdkVersion())
} else {
return JAVA_VERSION_9
}
@@ -776,7 +776,7 @@
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if j.testProperties.Test_options.Unit_test == nil && ctx.Host() {
// TODO(b/): Clean temporary heuristic to avoid unexpected onboarding.
- defaultUnitTest := !inList("tradefed", j.properties.Static_libs) && !inList("tradefed", j.properties.Libs) && !inList("cts", j.testProperties.Test_suites)
+ defaultUnitTest := !inList("tradefed", j.properties.Libs) && !inList("cts", j.testProperties.Test_suites)
j.testProperties.Test_options.Unit_test = proptools.BoolPtr(defaultUnitTest)
}
j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template,
@@ -1074,8 +1074,14 @@
type ImportProperties struct {
Jars []string `android:"path,arch_variant"`
+ // The version of the SDK that the source prebuilt file was built against. Defaults to the
+ // current version if not specified.
Sdk_version *string
+ // The minimum version of the SDK that this module supports. Defaults to sdk_version if not
+ // specified.
+ Min_sdk_version *string
+
Installable *bool
// List of shared java libs that this module has dependencies to
@@ -1126,28 +1132,31 @@
hideApexVariantFromMake bool
}
-func (j *Import) sdkVersion() sdkSpec {
- return sdkSpecFrom(String(j.properties.Sdk_version))
+func (j *Import) SdkVersion() android.SdkSpec {
+ return android.SdkSpecFrom(String(j.properties.Sdk_version))
}
func (j *Import) makeSdkVersion() string {
- return j.sdkVersion().raw
+ return j.SdkVersion().Raw
}
-func (j *Import) systemModules() string {
+func (j *Import) SystemModules() string {
return "none"
}
-func (j *Import) minSdkVersion() sdkSpec {
- return j.sdkVersion()
+func (j *Import) MinSdkVersion() android.SdkSpec {
+ if j.properties.Min_sdk_version != nil {
+ return android.SdkSpecFrom(*j.properties.Min_sdk_version)
+ }
+ return j.SdkVersion()
}
-func (j *Import) targetSdkVersion() sdkSpec {
- return j.sdkVersion()
+func (j *Import) TargetSdkVersion() android.SdkSpec {
+ return j.SdkVersion()
}
-func (j *Import) MinSdkVersion() string {
- return j.minSdkVersion().version.String()
+func (j *Import) MinSdkVersionString() string {
+ return j.MinSdkVersion().Version.String()
}
func (j *Import) Prebuilt() *android.Prebuilt {
@@ -1178,7 +1187,7 @@
ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
if ctx.Device() && Bool(j.dexProperties.Compile_dex) {
- sdkDeps(ctx, sdkContext(j), j.dexer)
+ sdkDeps(ctx, android.SdkContext(j), j.dexer)
}
}
@@ -1221,7 +1230,7 @@
} else if dep, ok := module.(SdkLibraryDependency); ok {
switch tag {
case libTag:
- flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
+ flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion())...)
}
}
@@ -1263,7 +1272,7 @@
ctx.ModuleErrorf("internal error: no dex implementation jar available from prebuilt_apex %q", deapexerModule.Name())
}
} else if Bool(j.dexProperties.Compile_dex) {
- sdkDep := decodeSdkDep(ctx, sdkContext(j))
+ sdkDep := decodeSdkDep(ctx, android.SdkContext(j))
if sdkDep.invalidVersion {
ctx.AddMissingDependencies(sdkDep.bootclasspath)
ctx.AddMissingDependencies(sdkDep.java9Classpath)
@@ -1282,7 +1291,7 @@
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
var dexOutputFile android.OutputPath
- dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
+ dexOutputFile = j.dexer.compileDex(ctx, flags, j.MinSdkVersion(), outputFile, jarName)
if ctx.Failed() {
return
}
@@ -1350,7 +1359,20 @@
// Implements android.ApexModule
func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
sdkVersion android.ApiLevel) error {
- // Do not check for prebuilts against the min_sdk_version of enclosing APEX
+ sdkSpec := j.MinSdkVersion()
+ if !sdkSpec.Specified() {
+ return fmt.Errorf("min_sdk_version is not specified")
+ }
+ if sdkSpec.Kind == android.SdkCore {
+ return nil
+ }
+ ver, err := sdkSpec.EffectiveVersion(ctx)
+ if err != nil {
+ return err
+ }
+ if ver.ApiLevel(ctx).GreaterThan(sdkVersion) {
+ return fmt.Errorf("newer SDK(%v)", ver)
+ }
return nil
}
diff --git a/java/java_test.go b/java/java_test.go
index 2ade0fe..fdf7579 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -74,23 +74,6 @@
return result.TestContext, result.Config
}
-// testJavaErrorWithConfig is a legacy way of running tests of java modules that expect errors.
-//
-// See testJava for an explanation as to how to stop using this deprecated method.
-//
-// deprecated
-func testJavaErrorWithConfig(t *testing.T, pattern string, config android.Config) (*android.TestContext, android.Config) {
- t.Helper()
- // This must be done on the supplied config and not as part of the fixture because any changes to
- // the fixture's config will be ignored when RunTestWithConfig replaces it.
- pathCtx := android.PathContextForTesting(config)
- dexpreopt.SetTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
- result := prepareForJavaTest.
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
- RunTestWithConfig(t, config)
- return result.TestContext, result.Config
-}
-
// testJavaWithFS runs tests using the prepareForJavaTest
//
// See testJava for an explanation as to how to stop using this deprecated method.
@@ -250,7 +233,7 @@
}
`)
- javac := ctx.ModuleForTests("foo", "android_common").Rule("javac").RelativeToTop()
+ javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
@@ -845,7 +828,12 @@
if expectedErrorPattern != "" {
errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(expectedErrorPattern)
}
- prepareForJavaTest.ExtendWithErrorHandler(errorHandler).RunTest(t, createPreparer(info))
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ createPreparer(info),
+ ).
+ ExtendWithErrorHandler(errorHandler).
+ RunTest(t)
})
}
@@ -976,7 +964,7 @@
}
`)
- javac := ctx.ModuleForTests("foo", "android_common").Rule("javac").RelativeToTop()
+ javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
combineJar := ctx.ModuleForTests("foo", "android_common").Description("for javac")
if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
@@ -1336,11 +1324,11 @@
}
`)
- fooTurbine := result.ModuleForTests("foo", "android_common").Rule("turbine").RelativeToTop()
- barTurbine := result.ModuleForTests("bar", "android_common").Rule("turbine").RelativeToTop()
- barJavac := result.ModuleForTests("bar", "android_common").Rule("javac").RelativeToTop()
- barTurbineCombined := result.ModuleForTests("bar", "android_common").Description("for turbine").RelativeToTop()
- bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac").RelativeToTop()
+ fooTurbine := result.ModuleForTests("foo", "android_common").Rule("turbine")
+ barTurbine := result.ModuleForTests("bar", "android_common").Rule("turbine")
+ barJavac := result.ModuleForTests("bar", "android_common").Rule("javac")
+ barTurbineCombined := result.ModuleForTests("bar", "android_common").Description("for turbine")
+ bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac")
android.AssertPathsRelativeToTopEquals(t, "foo inputs", []string{"a.java"}, fooTurbine.Inputs)
@@ -1363,7 +1351,7 @@
barHeaderJar := filepath.Join("out", "soong", ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar")
for i := 0; i < 3; i++ {
- barJavac := ctx.ModuleForTests("bar", "android_common").Description("javac" + strconv.Itoa(i)).RelativeToTop()
+ barJavac := ctx.ModuleForTests("bar", "android_common").Description("javac" + strconv.Itoa(i))
if !strings.Contains(barJavac.Args["classpath"], barHeaderJar) {
t.Errorf("bar javac classpath %v does not contain %q", barJavac.Args["classpath"], barHeaderJar)
}
@@ -1670,7 +1658,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 +1961,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/platform_bootclasspath.go b/java/platform_bootclasspath.go
new file mode 100644
index 0000000..5507077
--- /dev/null
+++ b/java/platform_bootclasspath.go
@@ -0,0 +1,74 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+ "android/soong/android"
+ "android/soong/dexpreopt"
+)
+
+func init() {
+ registerPlatformBootclasspathBuildComponents(android.InitRegistrationContext)
+}
+
+func registerPlatformBootclasspathBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("platform_bootclasspath", platformBootclasspathFactory)
+}
+
+type platformBootclasspathModule struct {
+ android.ModuleBase
+}
+
+func platformBootclasspathFactory() android.Module {
+ m := &platformBootclasspathModule{}
+ android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
+ return m
+}
+
+func (b *platformBootclasspathModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if SkipDexpreoptBootJars(ctx) {
+ return
+ }
+
+ // Add a dependency onto the dex2oat tool which is needed for creating the boot image. The
+ // path is retrieved from the dependency by GetGlobalSoongConfig(ctx).
+ dexpreopt.RegisterToolDeps(ctx)
+}
+
+func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ // Nothing to do if skipping the dexpreopt of boot image jars.
+ if SkipDexpreoptBootJars(ctx) {
+ return
+ }
+
+ // Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
+ // GenerateSingletonBuildActions method as it cannot create it for itself.
+ dexpreopt.GetGlobalSoongConfig(ctx)
+
+ imageConfig := b.getImageConfig(ctx)
+ if imageConfig == nil {
+ return
+ }
+
+ // Construct the boot image info from the config.
+ info := BootImageInfo{imageConfig: imageConfig}
+
+ // Make it available for other modules.
+ ctx.SetProvider(BootImageInfoProvider, info)
+}
+
+func (b *platformBootclasspathModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
+ return defaultBootImageConfig(ctx)
+}
diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go
new file mode 100644
index 0000000..1c81cfd
--- /dev/null
+++ b/java/platform_bootclasspath_test.go
@@ -0,0 +1,38 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+ "testing"
+
+ "android/soong/android"
+ "android/soong/dexpreopt"
+)
+
+// Contains some simple tests for platform_bootclasspath.
+
+var prepareForTestWithPlatformBootclasspath = android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ dexpreopt.PrepareForTestByEnablingDexpreopt,
+)
+
+func TestPlatformBootclasspath(t *testing.T) {
+ prepareForTestWithPlatformBootclasspath.
+ RunTestWithBp(t, `
+ platform_bootclasspath {
+ name: "platform-bootclasspath",
+ }
+ `)
+}
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 03e82c2..c3d13ae 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -221,12 +221,40 @@
metadata android.Path
}
+// isModulePreferredByCompatConfig checks to see whether the module is preferred for use by
+// platform compat config.
+func isModulePreferredByCompatConfig(module android.Module) bool {
+ // A versioned prebuilt_platform_compat_config, i.e. foo-platform-compat-config@current should be
+ // ignored.
+ if s, ok := module.(android.SdkAware); ok {
+ if !s.ContainingSdk().Unversioned() {
+ return false
+ }
+ }
+
+ // A prebuilt module should only be used when it is preferred.
+ if pi, ok := module.(android.PrebuiltInterface); ok {
+ if p := pi.Prebuilt(); p != nil {
+ return p.UsePrebuilt()
+ }
+ }
+
+ // Otherwise, a module should only be used if it has not been replaced by a prebuilt.
+ return !module.IsReplacedByPrebuilt()
+}
+
func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var compatConfigMetadata android.Paths
ctx.VisitAllModules(func(module android.Module) {
+ if !module.Enabled() {
+ return
+ }
if c, ok := module.(platformCompatConfigMetadataProvider); ok {
+ if !isModulePreferredByCompatConfig(module) {
+ return
+ }
metadata := c.compatConfigMetadata()
compatConfigMetadata = append(compatConfigMetadata, metadata)
}
diff --git a/java/rro.go b/java/rro.go
index aafa88e..4ae0014 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -91,7 +91,7 @@
}
func (r *RuntimeResourceOverlay) DepsMutator(ctx android.BottomUpMutatorContext) {
- sdkDep := decodeSdkDep(ctx, sdkContext(r))
+ sdkDep := decodeSdkDep(ctx, android.SdkContext(r))
if sdkDep.hasFrameworkLibs() {
r.aapt.deps(ctx, sdkDep)
}
@@ -141,23 +141,23 @@
ctx.InstallFile(r.installDir, r.outputFile.Base(), r.outputFile)
}
-func (r *RuntimeResourceOverlay) sdkVersion() sdkSpec {
- return sdkSpecFrom(String(r.properties.Sdk_version))
+func (r *RuntimeResourceOverlay) SdkVersion() android.SdkSpec {
+ return android.SdkSpecFrom(String(r.properties.Sdk_version))
}
-func (r *RuntimeResourceOverlay) systemModules() string {
+func (r *RuntimeResourceOverlay) SystemModules() string {
return ""
}
-func (r *RuntimeResourceOverlay) minSdkVersion() sdkSpec {
+func (r *RuntimeResourceOverlay) MinSdkVersion() android.SdkSpec {
if r.properties.Min_sdk_version != nil {
- return sdkSpecFrom(*r.properties.Min_sdk_version)
+ return android.SdkSpecFrom(*r.properties.Min_sdk_version)
}
- return r.sdkVersion()
+ return r.SdkVersion()
}
-func (r *RuntimeResourceOverlay) targetSdkVersion() sdkSpec {
- return r.sdkVersion()
+func (r *RuntimeResourceOverlay) TargetSdkVersion() android.SdkSpec {
+ return r.SdkVersion()
}
func (r *RuntimeResourceOverlay) Certificate() Certificate {
diff --git a/java/rro_test.go b/java/rro_test.go
index 0a10d93..bad60bc 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -68,7 +68,7 @@
m := result.ModuleForTests("foo", "android_common")
// Check AAPT2 link flags.
- aapt2Flags := m.Output("package-res.apk").RelativeToTop().Args["flags"]
+ aapt2Flags := m.Output("package-res.apk").Args["flags"]
expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"}
absentFlags := android.RemoveListFromList(expectedFlags, strings.Split(aapt2Flags, " "))
if len(absentFlags) > 0 {
diff --git a/java/sdk.go b/java/sdk.go
index 74d5a81..b546ca0 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -19,7 +19,6 @@
"path/filepath"
"sort"
"strconv"
- "strings"
"android/soong/android"
"android/soong/java/config"
@@ -38,19 +37,6 @@
var nonUpdatableFrameworkAidlPathKey = android.NewOnceKey("nonUpdatableFrameworkAidlPathKey")
var apiFingerprintPathKey = android.NewOnceKey("apiFingerprintPathKey")
-type sdkContext interface {
- // sdkVersion returns sdkSpec that corresponds to the sdk_version property of the current module
- sdkVersion() sdkSpec
- // systemModules returns the system_modules property of the current module, or an empty string if it is not set.
- systemModules() string
- // minSdkVersion returns sdkSpec that corresponds to the min_sdk_version property of the current module,
- // or from sdk_version if it is not set.
- minSdkVersion() sdkSpec
- // targetSdkVersion returns the sdkSpec that corresponds to the target_sdk_version property of the current module,
- // or from sdk_version if it is not set.
- targetSdkVersion() sdkSpec
-}
-
func UseApiFingerprint(ctx android.BaseModuleContext) bool {
if ctx.Config().UnbundledBuild() &&
!ctx.Config().AlwaysUsePrebuiltSdks() &&
@@ -60,209 +46,8 @@
return false
}
-// sdkKind represents a particular category of an SDK spec like public, system, test, etc.
-type sdkKind int
-
-const (
- sdkInvalid sdkKind = iota
- sdkNone
- sdkCore
- sdkCorePlatform
- sdkPublic
- sdkSystem
- sdkTest
- sdkModule
- sdkSystemServer
- sdkPrivate
-)
-
-// String returns the string representation of this sdkKind
-func (k sdkKind) String() string {
- switch k {
- case sdkPrivate:
- return "private"
- case sdkNone:
- return "none"
- case sdkPublic:
- return "public"
- case sdkSystem:
- return "system"
- case sdkTest:
- return "test"
- case sdkCore:
- return "core"
- case sdkCorePlatform:
- return "core_platform"
- case sdkModule:
- return "module-lib"
- case sdkSystemServer:
- return "system-server"
- default:
- return "invalid"
- }
-}
-
-// sdkVersion represents a specific version number of an SDK spec of a particular kind
-type sdkVersion int
-
-const (
- // special version number for a not-yet-frozen SDK
- sdkVersionCurrent sdkVersion = sdkVersion(android.FutureApiLevelInt)
- // special version number to be used for SDK specs where version number doesn't
- // make sense, e.g. "none", "", etc.
- sdkVersionNone sdkVersion = sdkVersion(0)
-)
-
-// isCurrent checks if the sdkVersion refers to the not-yet-published version of an sdkKind
-func (v sdkVersion) isCurrent() bool {
- return v == sdkVersionCurrent
-}
-
-// isNumbered checks if the sdkVersion refers to the published (a.k.a numbered) version of an sdkKind
-func (v sdkVersion) isNumbered() bool {
- return !v.isCurrent() && v != sdkVersionNone
-}
-
-// String returns the string representation of this sdkVersion.
-func (v sdkVersion) String() string {
- if v.isCurrent() {
- return "current"
- } else if v.isNumbered() {
- return strconv.Itoa(int(v))
- }
- return "(no version)"
-}
-
-func (v sdkVersion) ApiLevel(ctx android.EarlyModuleContext) android.ApiLevel {
- return android.ApiLevelOrPanic(ctx, v.String())
-}
-
-// asNumberString directly converts the numeric value of this sdk version as a string.
-// When isNumbered() is true, this method is the same as String(). However, for sdkVersionCurrent
-// and sdkVersionNone, this returns 10000 and 0 while String() returns "current" and "(no version"),
-// respectively.
-func (v sdkVersion) asNumberString() string {
- return strconv.Itoa(int(v))
-}
-
-// sdkSpec represents the kind and the version of an SDK for a module to build against
-type sdkSpec struct {
- kind sdkKind
- version sdkVersion
- raw string
-}
-
-func (s sdkSpec) String() string {
- return fmt.Sprintf("%s_%s", s.kind, s.version)
-}
-
-// valid checks if this sdkSpec is well-formed. Note however that true doesn't mean that the
-// specified SDK actually exists.
-func (s sdkSpec) valid() bool {
- return s.kind != sdkInvalid
-}
-
-// specified checks if this sdkSpec is well-formed and is not "".
-func (s sdkSpec) specified() bool {
- return s.valid() && s.kind != sdkPrivate
-}
-
-// whether the API surface is managed and versioned, i.e. has .txt file that
-// get frozen on SDK freeze and changes get reviewed by API council.
-func (s sdkSpec) stable() bool {
- if !s.specified() {
- return false
- }
- switch s.kind {
- case sdkNone:
- // there is nothing to manage and version in this case; de facto stable API.
- return true
- case sdkCore, sdkPublic, sdkSystem, sdkModule, sdkSystemServer:
- return true
- case sdkCorePlatform, sdkTest, sdkPrivate:
- return false
- default:
- panic(fmt.Errorf("unknown sdkKind=%v", s.kind))
- }
- return false
-}
-
-// prebuiltSdkAvailableForUnbundledBuilt tells whether this sdkSpec can have a prebuilt SDK
-// that can be used for unbundled builds.
-func (s sdkSpec) prebuiltSdkAvailableForUnbundledBuild() bool {
- // "", "none", and "core_platform" are not available for unbundled build
- // as we don't/can't have prebuilt stub for the versions
- return s.kind != sdkPrivate && s.kind != sdkNone && s.kind != sdkCorePlatform
-}
-
-func (s sdkSpec) forVendorPartition(ctx android.EarlyModuleContext) sdkSpec {
- // If BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES has a numeric value,
- // use it instead of "current" for the vendor partition.
- currentSdkVersion := ctx.DeviceConfig().CurrentApiLevelForVendorModules()
- if currentSdkVersion == "current" {
- return s
- }
-
- if s.kind == sdkPublic || s.kind == sdkSystem {
- if s.version.isCurrent() {
- if i, err := strconv.Atoi(currentSdkVersion); err == nil {
- version := sdkVersion(i)
- return sdkSpec{s.kind, version, s.raw}
- }
- panic(fmt.Errorf("BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES must be either \"current\" or a number, but was %q", currentSdkVersion))
- }
- }
- return s
-}
-
-// usePrebuilt determines whether prebuilt SDK should be used for this sdkSpec with the given context.
-func (s sdkSpec) usePrebuilt(ctx android.EarlyModuleContext) bool {
- if s.version.isCurrent() {
- // "current" can be built from source and be from prebuilt SDK
- return ctx.Config().AlwaysUsePrebuiltSdks()
- } else if s.version.isNumbered() {
- // validation check
- if s.kind != sdkPublic && s.kind != sdkSystem && s.kind != sdkTest && s.kind != sdkModule {
- panic(fmt.Errorf("prebuilt SDK is not not available for sdkKind=%q", s.kind))
- return false
- }
- // numbered SDKs are always from prebuilt
- return true
- }
- // "", "none", "core_platform" fall here
- return false
-}
-
-// effectiveVersion converts an sdkSpec into the concrete sdkVersion that the module
-// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
-// it returns android.FutureApiLevel(10000).
-func (s sdkSpec) effectiveVersion(ctx android.EarlyModuleContext) (sdkVersion, error) {
- if !s.valid() {
- return s.version, fmt.Errorf("invalid sdk version %q", s.raw)
- }
-
- if ctx.DeviceSpecific() || ctx.SocSpecific() {
- s = s.forVendorPartition(ctx)
- }
- if s.version.isNumbered() {
- return s.version, nil
- }
- return sdkVersion(ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt()), nil
-}
-
-// effectiveVersionString converts an sdkSpec into the concrete version string that the module
-// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
-// it returns the codename (P, Q, R, etc.)
-func (s sdkSpec) effectiveVersionString(ctx android.EarlyModuleContext) (string, error) {
- ver, err := s.effectiveVersion(ctx)
- if err == nil && int(ver) == ctx.Config().DefaultAppTargetSdk(ctx).FinalOrFutureInt() {
- return ctx.Config().DefaultAppTargetSdk(ctx).String(), nil
- }
- return ver.String(), err
-}
-
-func (s sdkSpec) defaultJavaLanguageVersion(ctx android.EarlyModuleContext) javaVersion {
- sdk, err := s.effectiveVersion(ctx)
+func defaultJavaLanguageVersion(ctx android.EarlyModuleContext, s android.SdkSpec) javaVersion {
+ sdk, err := s.EffectiveVersion(ctx)
if err != nil {
ctx.PropertyErrorf("sdk_version", "%s", err)
}
@@ -275,103 +60,27 @@
}
}
-func sdkSpecFrom(str string) sdkSpec {
- switch str {
- // special cases first
- case "":
- return sdkSpec{sdkPrivate, sdkVersionNone, str}
- case "none":
- return sdkSpec{sdkNone, sdkVersionNone, str}
- case "core_platform":
- return sdkSpec{sdkCorePlatform, sdkVersionNone, str}
- default:
- // the syntax is [kind_]version
- sep := strings.LastIndex(str, "_")
-
- var kindString string
- if sep == 0 {
- return sdkSpec{sdkInvalid, sdkVersionNone, str}
- } else if sep == -1 {
- kindString = ""
- } else {
- kindString = str[0:sep]
- }
- versionString := str[sep+1 : len(str)]
-
- var kind sdkKind
- switch kindString {
- case "":
- kind = sdkPublic
- case "core":
- kind = sdkCore
- case "system":
- kind = sdkSystem
- case "test":
- kind = sdkTest
- case "module":
- kind = sdkModule
- case "system_server":
- kind = sdkSystemServer
- default:
- return sdkSpec{sdkInvalid, sdkVersionNone, str}
- }
-
- var version sdkVersion
- if versionString == "current" {
- version = sdkVersionCurrent
- } else if i, err := strconv.Atoi(versionString); err == nil {
- version = sdkVersion(i)
- } else {
- return sdkSpec{sdkInvalid, sdkVersionNone, str}
- }
-
- return sdkSpec{kind, version, str}
- }
-}
-
-func (s sdkSpec) validateSystemSdk(ctx android.EarlyModuleContext) bool {
- // Ensures that the specified system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor/product Java module)
- // Assuming that BOARD_SYSTEMSDK_VERSIONS := 28 29,
- // sdk_version of the modules in vendor/product that use system sdk must be either system_28, system_29 or system_current
- if s.kind != sdkSystem || !s.version.isNumbered() {
- return true
- }
- allowedVersions := ctx.DeviceConfig().PlatformSystemSdkVersions()
- if ctx.DeviceSpecific() || ctx.SocSpecific() || (ctx.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
- systemSdkVersions := ctx.DeviceConfig().SystemSdkVersions()
- if len(systemSdkVersions) > 0 {
- allowedVersions = systemSdkVersions
- }
- }
- if len(allowedVersions) > 0 && !android.InList(s.version.String(), allowedVersions) {
- ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
- s.raw, allowedVersions)
- return false
- }
- return true
-}
-
-func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep {
- sdkVersion := sdkContext.sdkVersion()
- if !sdkVersion.valid() {
- ctx.PropertyErrorf("sdk_version", "invalid version %q", sdkVersion.raw)
+func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext android.SdkContext) sdkDep {
+ sdkVersion := sdkContext.SdkVersion()
+ if !sdkVersion.Valid() {
+ ctx.PropertyErrorf("sdk_version", "invalid version %q", sdkVersion.Raw)
return sdkDep{}
}
if ctx.DeviceSpecific() || ctx.SocSpecific() {
- sdkVersion = sdkVersion.forVendorPartition(ctx)
+ sdkVersion = sdkVersion.ForVendorPartition(ctx)
}
- if !sdkVersion.validateSystemSdk(ctx) {
+ if !sdkVersion.ValidateSystemSdk(ctx) {
return sdkDep{}
}
- if sdkVersion.usePrebuilt(ctx) {
- dir := filepath.Join("prebuilts", "sdk", sdkVersion.version.String(), sdkVersion.kind.String())
+ if sdkVersion.UsePrebuilt(ctx) {
+ dir := filepath.Join("prebuilts", "sdk", sdkVersion.Version.String(), sdkVersion.Kind.String())
jar := filepath.Join(dir, "android.jar")
// There's no aidl for other SDKs yet.
// TODO(77525052): Add aidl files for other SDKs too.
- publicDir := filepath.Join("prebuilts", "sdk", sdkVersion.version.String(), "public")
+ publicDir := filepath.Join("prebuilts", "sdk", sdkVersion.Version.String(), "public")
aidl := filepath.Join(publicDir, "framework.aidl")
jarPath := android.ExistentPathForSource(ctx, jar)
aidlPath := android.ExistentPathForSource(ctx, aidl)
@@ -380,23 +89,23 @@
if (!jarPath.Valid() || !aidlPath.Valid()) && ctx.Config().AllowMissingDependencies() {
return sdkDep{
invalidVersion: true,
- bootclasspath: []string{fmt.Sprintf("sdk_%s_%s_android", sdkVersion.kind, sdkVersion.version.String())},
+ bootclasspath: []string{fmt.Sprintf("sdk_%s_%s_android", sdkVersion.Kind, sdkVersion.Version.String())},
}
}
if !jarPath.Valid() {
- ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", sdkVersion.raw, jar)
+ ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", sdkVersion.Raw, jar)
return sdkDep{}
}
if !aidlPath.Valid() {
- ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", sdkVersion.raw, aidl)
+ ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", sdkVersion.Raw, aidl)
return sdkDep{}
}
var systemModules string
- if sdkVersion.defaultJavaLanguageVersion(ctx).usesJavaModules() {
- systemModules = "sdk_public_" + sdkVersion.version.String() + "_system_modules"
+ if defaultJavaLanguageVersion(ctx, sdkVersion).usesJavaModules() {
+ systemModules = "sdk_public_" + sdkVersion.Version.String() + "_system_modules"
}
return sdkDep{
@@ -418,8 +127,8 @@
}
}
- switch sdkVersion.kind {
- case sdkPrivate:
+ switch sdkVersion.Kind {
+ case android.SdkPrivate:
return sdkDep{
useModule: true,
systemModules: corePlatformSystemModules(ctx),
@@ -427,8 +136,8 @@
classpath: config.FrameworkLibraries,
frameworkResModule: "framework-res",
}
- case sdkNone:
- systemModules := sdkContext.systemModules()
+ case android.SdkNone:
+ systemModules := sdkContext.SystemModules()
if systemModules == "" {
ctx.PropertyErrorf("sdk_version",
`system_modules is required to be set to a non-empty value when sdk_version is "none", did you mean sdk_version: "core_platform"?`)
@@ -444,34 +153,34 @@
systemModules: systemModules,
bootclasspath: []string{systemModules},
}
- case sdkCorePlatform:
+ case android.SdkCorePlatform:
return sdkDep{
useModule: true,
systemModules: corePlatformSystemModules(ctx),
bootclasspath: corePlatformBootclasspathLibraries(ctx),
noFrameworksLibs: true,
}
- case sdkPublic:
+ case android.SdkPublic:
return toModule([]string{"android_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
- case sdkSystem:
+ case android.SdkSystem:
return toModule([]string{"android_system_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
- case sdkTest:
+ case android.SdkTest:
return toModule([]string{"android_test_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
- case sdkCore:
+ case android.SdkCore:
return sdkDep{
useModule: true,
bootclasspath: []string{"core.current.stubs", config.DefaultLambdaStubsLibrary},
systemModules: "core-current-stubs-system-modules",
noFrameworksLibs: true,
}
- case sdkModule:
+ case android.SdkModule:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
return toModule([]string{"android_module_lib_stubs_current"}, "framework-res", nonUpdatableFrameworkAidlPath(ctx))
- case sdkSystemServer:
+ case android.SdkSystemServer:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
return toModule([]string{"android_system_server_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx))
default:
- panic(fmt.Errorf("invalid sdk %q", sdkVersion.raw))
+ panic(fmt.Errorf("invalid sdk %q", sdkVersion.Raw))
}
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index e1ca77d..ebb2154 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -814,22 +814,22 @@
return nil
}
-func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
+func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
// If a specific numeric version has been requested then use prebuilt versions of the sdk.
- if sdkVersion.version.isNumbered() {
+ if sdkVersion.Version.IsNumbered() {
return PrebuiltJars(ctx, c.moduleBase.BaseModuleName(), sdkVersion)
}
var apiScope *apiScope
- switch sdkVersion.kind {
- case sdkSystem:
+ switch sdkVersion.Kind {
+ case android.SdkSystem:
apiScope = apiScopeSystem
- case sdkModule:
+ case android.SdkModule:
apiScope = apiScopeModuleLib
- case sdkTest:
+ case android.SdkTest:
apiScope = apiScopeTest
- case sdkSystemServer:
+ case android.SdkSystemServer:
apiScope = apiScopeSystemServer
default:
apiScope = apiScopePublic
@@ -932,14 +932,14 @@
//
// These are turbine generated jars so they only change if the externals of the
// class changes but it does not contain and implementation or JavaDoc.
- SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths
+ SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths
// Get the implementation jars appropriate for the supplied sdk version.
//
// These are either the implementation jar for the whole sdk library or the implementation
// jars for the stubs. The latter should only be needed when generating JavaDoc as otherwise
// they are identical to the corresponding header jars.
- SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths
+ SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths
}
type SdkLibrary struct {
@@ -1147,7 +1147,7 @@
return proptools.String(scopeProperties.Sdk_version)
}
- sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
+ sdkDep := decodeSdkDep(mctx, android.SdkContext(&module.Library))
if sdkDep.hasStandardLibs() {
// If building against a standard sdk then use the sdk version appropriate for the scope.
return apiScope.sdkVersion
@@ -1465,17 +1465,17 @@
mctx.CreateModule(sdkLibraryXmlFactory, &props)
}
-func PrebuiltJars(ctx android.BaseModuleContext, baseName string, s sdkSpec) android.Paths {
- var ver sdkVersion
- var kind sdkKind
- if s.usePrebuilt(ctx) {
- ver = s.version
- kind = s.kind
+func PrebuiltJars(ctx android.BaseModuleContext, baseName string, s android.SdkSpec) android.Paths {
+ var ver android.SdkVersion
+ var kind android.SdkKind
+ if s.UsePrebuilt(ctx) {
+ ver = s.Version
+ kind = s.Kind
} else {
// We don't have prebuilt SDK for the specific sdkVersion.
// Instead of breaking the build, fallback to use "system_current"
- ver = sdkVersionCurrent
- kind = sdkSystem
+ ver = android.SdkVersionCurrent
+ kind = android.SdkSystem
}
dir := filepath.Join("prebuilts", "sdk", ver.String(), kind.String())
@@ -1485,7 +1485,7 @@
if ctx.Config().AllowMissingDependencies() {
return android.Paths{android.PathForSource(ctx, jar)}
} else {
- ctx.PropertyErrorf("sdk_library", "invalid sdk version %q, %q does not exist", s.raw, jar)
+ ctx.PropertyErrorf("sdk_library", "invalid sdk version %q, %q does not exist", s.Raw, jar)
}
return nil
}
@@ -1502,13 +1502,13 @@
return len(otherApexInfo.InApexes) > 0 && reflect.DeepEqual(apexInfo.InApexes, otherApexInfo.InApexes)
}
-func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec, headerJars bool) android.Paths {
+func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec, headerJars bool) android.Paths {
// If the client doesn't set sdk_version, but if this library prefers stubs over
// the impl library, let's provide the widest API surface possible. To do so,
// force override sdk_version to module_current so that the closest possible API
// surface could be found in selectHeaderJarsForSdkVersion
- if module.defaultsToStubs() && !sdkVersion.specified() {
- sdkVersion = sdkSpecFrom("module_current")
+ if module.defaultsToStubs() && !sdkVersion.Specified() {
+ sdkVersion = android.SdkSpecFrom("module_current")
}
// Only provide access to the implementation library if it is actually built.
@@ -1518,7 +1518,7 @@
// Only allow access to the implementation library in the following condition:
// * No sdk_version specified on the referencing module.
// * The referencing module is in the same apex as this.
- if sdkVersion.kind == sdkPrivate || withinSameApexesAs(ctx, module) {
+ if sdkVersion.Kind == android.SdkPrivate || withinSameApexesAs(ctx, module) {
if headerJars {
return module.HeaderJars()
} else {
@@ -1531,12 +1531,12 @@
}
// to satisfy SdkLibraryDependency interface
-func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
+func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
return module.sdkJars(ctx, sdkVersion, true /*headerJars*/)
}
// to satisfy SdkLibraryDependency interface
-func (module *SdkLibrary) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
+func (module *SdkLibrary) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
return module.sdkJars(ctx, sdkVersion, false /*headerJars*/)
}
@@ -1568,7 +1568,7 @@
// If this builds against standard libraries (i.e. is not part of the core libraries)
// then assume it provides both system and test apis.
- sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
+ sdkDep := decodeSdkDep(mctx, android.SdkContext(&module.Library))
hasSystemAndTestApis := sdkDep.hasStandardLibs()
module.sdkLibraryProperties.Generate_system_and_test_apis = hasSystemAndTestApis
@@ -2069,7 +2069,7 @@
}
}
-func (module *SdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec, headerJars bool) android.Paths {
+func (module *SdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec, headerJars bool) android.Paths {
// For consistency with SdkLibrary make the implementation jar available to libraries that
// are within the same APEX.
@@ -2086,13 +2086,13 @@
}
// to satisfy SdkLibraryDependency interface
-func (module *SdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
+func (module *SdkLibraryImport) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
// This module is just a wrapper for the prebuilt stubs.
return module.sdkJars(ctx, sdkVersion, true)
}
// to satisfy SdkLibraryDependency interface
-func (module *SdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
+func (module *SdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths {
// This module is just a wrapper for the stubs.
return module.sdkJars(ctx, sdkVersion, false)
}
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 028c4fe..2b18465 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -313,10 +313,10 @@
checkClasspath := func(t *testing.T, result *android.TestResult, isJava8 bool) {
foo := result.ModuleForTests("foo", variant)
- javac := foo.Rule("javac").RelativeToTop()
+ javac := foo.Rule("javac")
var deps []string
- aidl := foo.MaybeRule("aidl").RelativeToTop()
+ aidl := foo.MaybeRule("aidl")
if aidl.Rule != nil {
deps = append(deps, android.PathRelativeToTop(aidl.Output))
}
@@ -376,7 +376,7 @@
checkClasspath(t, result, true /* isJava8 */)
if testcase.host != android.Host {
- aidl := result.ModuleForTests("foo", variant).Rule("aidl").RelativeToTop()
+ aidl := result.ModuleForTests("foo", variant).Rule("aidl")
android.AssertStringDoesContain(t, "aidl command", aidl.RuleParams.Command, testcase.aidl+" -I.")
}
@@ -389,7 +389,7 @@
checkClasspath(t, result, false /* isJava8 */)
if testcase.host != android.Host {
- aidl := result.ModuleForTests("foo", variant).Rule("aidl").RelativeToTop()
+ aidl := result.ModuleForTests("foo", variant).Rule("aidl")
android.AssertStringDoesContain(t, "aidl command", aidl.RuleParams.Command, testcase.aidl+" -I.")
}
@@ -402,14 +402,16 @@
// Test again with PLATFORM_VERSION_CODENAME=REL, javac -source 8 -target 8
t.Run("REL + Java language level 8", func(t *testing.T) {
- result := fixtureFactory.Extend(prepareWithPlatformVersionRel).RunTestWithBp(t, bpJava8)
+ result := android.GroupFixturePreparers(
+ fixtureFactory, prepareWithPlatformVersionRel).RunTestWithBp(t, bpJava8)
checkClasspath(t, result, true /* isJava8 */)
})
// Test again with PLATFORM_VERSION_CODENAME=REL, javac -source 9 -target 9
t.Run("REL + Java language level 9", func(t *testing.T) {
- result := fixtureFactory.Extend(prepareWithPlatformVersionRel).RunTestWithBp(t, bp)
+ result := android.GroupFixturePreparers(
+ fixtureFactory, prepareWithPlatformVersionRel).RunTestWithBp(t, bp)
checkClasspath(t, result, false /* isJava8 */)
})
diff --git a/java/system_modules_test.go b/java/system_modules_test.go
index 7d8935a..7b5a386 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
}
@@ -50,15 +50,15 @@
`)
func TestJavaSystemModules(t *testing.T) {
- result := prepareForJavaTest.RunTest(t, addSourceSystemModules)
+ result := android.GroupFixturePreparers(prepareForJavaTest, addSourceSystemModules).RunTest(t)
// check the existence of the source module
sourceSystemModules := result.ModuleForTests("system-modules", "android_common")
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", `
@@ -77,36 +77,37 @@
`)
func TestJavaSystemModulesImport(t *testing.T) {
- result := prepareForJavaTest.RunTest(t, addPrebuiltSystemModules)
+ result := android.GroupFixturePreparers(prepareForJavaTest, addPrebuiltSystemModules).RunTest(t)
// check the existence of the renamed prebuilt module
prebuiltSystemModules := result.ModuleForTests("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, "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) {
- result := prepareForJavaTest.RunTest(t,
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
addSourceSystemModules,
addPrebuiltSystemModules,
- )
+ ).RunTest(t)
// check the existence of the source module
sourceSystemModules := result.ModuleForTests("system-modules", "android_common")
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/java/testing.go b/java/testing.go
index 221ceb1..80c107d 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -160,28 +160,6 @@
)
}
-func TestConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) android.Config {
- bp += GatherRequiredDepsForTest()
-
- mockFS := android.MockFS{}
-
- cc.GatherRequiredFilesForTest(mockFS)
-
- for k, v := range fs {
- mockFS[k] = v
- }
-
- if env == nil {
- env = make(map[string]string)
- }
- if env["ANDROID_JAVA8_HOME"] == "" {
- env["ANDROID_JAVA8_HOME"] = "jdk8"
- }
- config := android.TestArchConfig(buildDir, env, bp, mockFS)
-
- return config
-}
-
func prebuiltApisFilesForLibs(apiLevels []string, sdkLibs []string) map[string][]byte {
fs := make(map[string][]byte)
for _, level := range apiLevels {
@@ -200,19 +178,6 @@
return fs
}
-// Register build components provided by this package that are needed by tests.
-//
-// In particular this must register all the components that are used in the `Android.bp` snippet
-// returned by GatherRequiredDepsForTest()
-//
-// deprecated: Use test fixtures instead, e.g. PrepareForTestWithJavaBuildComponents
-func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
- registerRequiredBuildComponentsForTest(ctx)
-
- // Make sure that any tool related module types needed by dexpreopt have been registered.
- dexpreopt.RegisterToolModulesForTest(ctx)
-}
-
// registerRequiredBuildComponentsForTest registers the build components used by
// PrepareForTestWithJavaDefaultModules.
//
@@ -228,7 +193,8 @@
RegisterDexpreoptBootJarsComponents(ctx)
RegisterDocsBuildComponents(ctx)
RegisterGenRuleBuildComponents(ctx)
- RegisterJavaBuildComponents(ctx)
+ registerJavaBuildComponents(ctx)
+ registerPlatformBootclasspathBuildComponents(ctx)
RegisterPrebuiltApisBuildComponents(ctx)
RegisterRuntimeResourceOverlayBuildComponents(ctx)
RegisterSdkLibraryBuildComponents(ctx)
@@ -236,23 +202,6 @@
RegisterSystemModulesBuildComponents(ctx)
}
-// Gather the module definitions needed by tests that depend upon code from this package.
-//
-// Returns an `Android.bp` snippet that defines the modules that are needed by this package.
-//
-// deprecated: Use test fixtures instead, e.g. PrepareForTestWithJavaDefaultModules
-func GatherRequiredDepsForTest() string {
- bp := gatherRequiredDepsForTest()
-
- // For class loader context and <uses-library> tests.
- bp += dexpreopt.CompatLibDefinitionsForTest()
-
- // Make sure that any tools needed for dexpreopting are defined.
- bp += dexpreopt.BpToolModulesForTest()
-
- return bp
-}
-
// gatherRequiredDepsForTest gathers the module definitions used by
// PrepareForTestWithJavaDefaultModules.
//
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/clippy_test.go b/rust/clippy_test.go
index e90564f..bd3bfb1 100644
--- a/rust/clippy_test.go
+++ b/rust/clippy_test.go
@@ -18,7 +18,6 @@
"testing"
"android/soong/android"
- "android/soong/cc"
)
func TestClippy(t *testing.T) {
@@ -45,15 +44,6 @@
clippy_lints: "none",
}`
- bp = bp + GatherRequiredDepsForTest()
- bp = bp + cc.GatherRequiredDepsForTest(android.NoOsType)
-
- fs := map[string][]byte{
- // Reuse the same blueprint file for subdirectories.
- "external/Android.bp": []byte(bp),
- "hardware/Android.bp": []byte(bp),
- }
-
var clippyLintTests = []struct {
modulePath string
fooFlags string
@@ -66,29 +56,22 @@
for _, tc := range clippyLintTests {
t.Run("path="+tc.modulePath, func(t *testing.T) {
- config := android.TestArchConfig(t.TempDir(), nil, bp, fs)
- ctx := CreateTestContext(config)
- ctx.Register()
- _, errs := ctx.ParseFileList(".", []string{tc.modulePath + "Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
+ result := android.GroupFixturePreparers(
+ prepareForRustTest,
+ // Test with the blueprint file in different directories.
+ android.FixtureAddTextFile(tc.modulePath+"Android.bp", bp),
+ ).RunTest(t)
- r := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
- if r.Args["clippyFlags"] != tc.fooFlags {
- t.Errorf("Incorrect flags for libfoo: %q, want %q", r.Args["clippyFlags"], tc.fooFlags)
- }
+ r := result.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
+ android.AssertStringEquals(t, "libfoo flags", tc.fooFlags, r.Args["clippyFlags"])
- r = ctx.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
- if r.Args["clippyFlags"] != "${config.ClippyDefaultLints}" {
- t.Errorf("Incorrect flags for libbar: %q, want %q", r.Args["clippyFlags"], "${config.ClippyDefaultLints}")
- }
+ r = result.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
+ android.AssertStringEquals(t, "libbar flags", "${config.ClippyDefaultLints}", r.Args["clippyFlags"])
- r = ctx.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
+ r = result.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
if r.Rule != nil {
t.Errorf("libfoobar is setup to use clippy when explicitly disabled: clippyFlags=%q", r.Args["clippyFlags"])
}
-
})
}
}
diff --git a/rust/compiler.go b/rust/compiler.go
index 200af90..41b7371 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -97,13 +97,25 @@
// list of C shared library dependencies
Shared_libs []string `android:"arch_variant"`
- // list of C static library dependencies. Note, static libraries prefixed by "lib" will be passed to rustc
- // along with "-lstatic=<name>". This will bundle the static library into rlib/static libraries so dependents do
- // not need to also declare the static library as a dependency. Static libraries which are not prefixed by "lib"
- // cannot be passed to rustc with this flag and will not be bundled into rlib/static libraries, and thus must
- // be redeclared in dependents.
+ // list of C static library dependencies. These dependencies do not normally propagate to dependents
+ // and may need to be redeclared. See whole_static_libs for bundling static dependencies into a library.
Static_libs []string `android:"arch_variant"`
+ // Similar to static_libs, but will bundle the static library dependency into a library. This is helpful
+ // to avoid having to redeclare the dependency for dependents of this library, but in some cases may also
+ // result in bloat if multiple dependencies all include the same static library whole.
+ //
+ // The common use case for this is when the static library is unlikely to be a dependency of other modules to avoid
+ // having to redeclare the static library dependency for every dependent module.
+ // If you are not sure what to, for rust_library modules most static dependencies should go in static_libraries,
+ // and for rust_ffi modules most static dependencies should go into whole_static_libraries.
+ //
+ // For rust_ffi static variants, these libraries will be included in the resulting static library archive.
+ //
+ // For rust_library rlib variants, these libraries will be bundled into the resulting rlib library. This will
+ // include all of the static libraries symbols in any dylibs or binaries which use this rlib as well.
+ Whole_static_libs []string `android:"arch_variant"`
+
// crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider
// modules which create library variants (rust_bindgen). This must be the expected extern crate name used in
// source, and is required to conform to an enforced format matching library output files (if the output file is
@@ -266,6 +278,7 @@
deps.Rustlibs = append(deps.Rustlibs, compiler.Properties.Rustlibs...)
deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros...)
deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...)
+ deps.WholeStaticLibs = append(deps.WholeStaticLibs, compiler.Properties.Whole_static_libs...)
deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs...)
if !Bool(compiler.Properties.No_stdlibs) {
diff --git a/rust/compiler_test.go b/rust/compiler_test.go
index 3ed086f..c752762 100644
--- a/rust/compiler_test.go
+++ b/rust/compiler_test.go
@@ -19,7 +19,6 @@
"testing"
"android/soong/android"
- "android/soong/cc"
)
// Test that feature flags are being correctly generated.
@@ -132,15 +131,6 @@
lints: "none",
}`
- bp = bp + GatherRequiredDepsForTest()
- bp = bp + cc.GatherRequiredDepsForTest(android.NoOsType)
-
- fs := map[string][]byte{
- // Reuse the same blueprint file for subdirectories.
- "external/Android.bp": []byte(bp),
- "hardware/Android.bp": []byte(bp),
- }
-
var lintTests = []struct {
modulePath string
fooFlags string
@@ -153,29 +143,20 @@
for _, tc := range lintTests {
t.Run("path="+tc.modulePath, func(t *testing.T) {
- config := android.TestArchConfig(t.TempDir(), nil, bp, fs)
- ctx := CreateTestContext(config)
- ctx.Register()
- _, errs := ctx.ParseFileList(".", []string{tc.modulePath + "Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
+ result := android.GroupFixturePreparers(
+ prepareForRustTest,
+ // Test with the blueprint file in different directories.
+ android.FixtureAddTextFile(tc.modulePath+"Android.bp", bp),
+ ).RunTest(t)
- r := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
- if !strings.Contains(r.Args["rustcFlags"], tc.fooFlags) {
- t.Errorf("Incorrect flags for libfoo: %q, want %q", r.Args["rustcFlags"], tc.fooFlags)
- }
+ r := result.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
+ android.AssertStringDoesContain(t, "libfoo flags", r.Args["rustcFlags"], tc.fooFlags)
- r = ctx.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
- if !strings.Contains(r.Args["rustcFlags"], "${config.RustDefaultLints}") {
- t.Errorf("Incorrect flags for libbar: %q, want %q", r.Args["rustcFlags"], "${config.RustDefaultLints}")
- }
+ r = result.ModuleForTests("libbar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
+ android.AssertStringDoesContain(t, "libbar flags", r.Args["rustcFlags"], "${config.RustDefaultLints}")
- r = ctx.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
- if !strings.Contains(r.Args["rustcFlags"], "${config.RustAllowAllLints}") {
- t.Errorf("Incorrect flags for libfoobar: %q, want %q", r.Args["rustcFlags"], "${config.RustAllowAllLints}")
- }
-
+ r = result.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("rustc")
+ android.AssertStringDoesContain(t, "libfoobar flags", r.Args["rustcFlags"], "${config.RustAllowAllLints}")
})
}
}
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index 408d433..1c8e43e 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -19,6 +19,7 @@
"packages/modules/Virtualization",
"prebuilts/rust",
"system/bt",
+ "system/core/libstats/pull_rust",
"system/extras/profcollectd",
"system/extras/simpleperf",
"system/hardware/interfaces/keystore2",
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..09d30db 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"
@@ -27,9 +28,10 @@
// testProjectJson run the generation of rust-project.json. It returns the raw
// content of the generated file.
func testProjectJson(t *testing.T, bp string) []byte {
- result := prepareForRustTest.
- Extend(android.FixtureMergeEnv(map[string]string{"SOONG_GEN_RUST_PROJECT": "1"})).
- RunTestWithBp(t, bp)
+ result := android.GroupFixturePreparers(
+ prepareForRustTest,
+ android.FixtureMergeEnv(map[string]string{"SOONG_GEN_RUST_PROJECT": "1"}),
+ ).RunTestWithBp(t, bp)
// The JSON file is generated via WriteFileToOutputDir. Therefore, it
// won't appear in the Output of the TestingSingleton. Manually verify
@@ -115,6 +117,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/rust/rust.go b/rust/rust.go
index 8ebdb72..f0d0e36 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -256,6 +256,10 @@
return ""
}
+func (mod *Module) MinSdkVersion() string {
+ return ""
+}
+
func (mod *Module) AlwaysSdk() bool {
return false
}
@@ -269,14 +273,15 @@
}
type Deps struct {
- Dylibs []string
- Rlibs []string
- Rustlibs []string
- Stdlibs []string
- ProcMacros []string
- SharedLibs []string
- StaticLibs []string
- HeaderLibs []string
+ Dylibs []string
+ Rlibs []string
+ Rustlibs []string
+ Stdlibs []string
+ ProcMacros []string
+ SharedLibs []string
+ StaticLibs []string
+ WholeStaticLibs []string
+ HeaderLibs []string
CrtBegin, CrtEnd string
}
@@ -751,7 +756,7 @@
deps.ProcMacros = android.LastUniqueStrings(deps.ProcMacros)
deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs)
deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs)
-
+ deps.WholeStaticLibs = android.LastUniqueStrings(deps.WholeStaticLibs)
return deps
}
@@ -911,16 +916,13 @@
exportDep := false
switch {
case cc.IsStaticDepTag(depTag):
- // Only pass -lstatic for rlibs as it results in dylib bloat.
- if lib, ok := ctx.Module().(*Module).compiler.(libraryInterface); ok && lib.rlib() {
- // Link cc static libraries using "-lstatic" so rustc can reason about how to handle these
- // (for example, bundling them into rlibs).
- //
- // rustc does not support linking libraries with the "-l" flag unless they are prefixed by "lib".
- // If we need to link a library that isn't prefixed by "lib", we'll just link to it directly through
- // linkObjects; such a library may need to be redeclared by static dependents.
+ if cc.IsWholeStaticLib(depTag) {
+ // rustc will bundle static libraries when they're passed with "-lstatic=<lib>". This will fail
+ // if the library is not prefixed by "lib".
if libName, ok := libNameFromFilePath(linkObject.Path()); ok {
depPaths.depFlags = append(depPaths.depFlags, "-lstatic="+libName)
+ } else {
+ ctx.ModuleErrorf("'%q' cannot be listed as a whole_static_library in Rust modules unless the output is prefixed by 'lib'", depName, ctx.ModuleName())
}
}
@@ -1099,7 +1101,10 @@
cc.SharedDepTag(), deps.SharedLibs...)
actx.AddVariationDependencies(append(commonDepVariations,
blueprint.Variation{Mutator: "link", Variation: "static"}),
- cc.StaticDepTag(), deps.StaticLibs...)
+ cc.StaticDepTag(false), deps.StaticLibs...)
+ actx.AddVariationDependencies(append(commonDepVariations,
+ blueprint.Variation{Mutator: "link", Variation: "static"}),
+ cc.StaticDepTag(true), deps.WholeStaticLibs...)
actx.AddVariationDependencies(nil, cc.HeaderDepTag(), deps.HeaderLibs...)
diff --git a/rust/rust_test.go b/rust/rust_test.go
index bed28ec..418bd93 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -149,6 +149,11 @@
srcs: ["foo.rs"],
crate_name: "static",
}
+ rust_ffi_host_static {
+ name: "libwholestatic",
+ srcs: ["foo.rs"],
+ crate_name: "wholestatic",
+ }
rust_ffi_host_shared {
name: "libshared",
srcs: ["foo.rs"],
@@ -164,6 +169,7 @@
srcs: ["foo.rs"],
crate_name: "rlib",
static_libs: ["libstatic"],
+ whole_static_libs: ["libwholestatic"],
}
rust_proc_macro {
name: "libpm",
@@ -204,8 +210,8 @@
t.Errorf("Static library dependency not detected (dependency missing from AndroidMkStaticLibs)")
}
- if !strings.Contains(rustc.Args["rustcFlags"], "-lstatic=static") {
- t.Errorf("-lstatic flag not being passed to rustc for static library")
+ if !strings.Contains(rustc.Args["rustcFlags"], "-lstatic=wholestatic") {
+ t.Errorf("-lstatic flag not being passed to rustc for static library %#v", rustc.Args["rustcFlags"])
}
}
diff --git a/rust/sanitize.go b/rust/sanitize.go
index 2f44b20..2498aa1 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -40,12 +40,12 @@
"-C passes='sancov'",
"--cfg fuzzing",
- "-C llvm-args=-sanitizer-coverage-level=4",
+ "-C llvm-args=-sanitizer-coverage-level=3",
"-C llvm-args=-sanitizer-coverage-trace-compares",
"-C llvm-args=-sanitizer-coverage-inline-8bit-counters",
+ "-C llvm-args=-sanitizer-coverage-stack-depth",
"-C llvm-args=-sanitizer-coverage-trace-geps",
"-C llvm-args=-sanitizer-coverage-prune-blocks=0",
- "-C llvm-args=-sanitizer-coverage-pc-table",
"-Z sanitizer=address",
// Sancov breaks with lto
diff --git a/rust/testing.go b/rust/testing.go
index 5be71c9..75adcfc 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -17,13 +17,12 @@
import (
"android/soong/android"
"android/soong/cc"
- "android/soong/genrule"
)
// Preparer that will define all cc module types and a limited set of mutators and singletons that
// make those module types usable.
var PrepareForTestWithRustBuildComponents = android.GroupFixturePreparers(
- android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
+ android.FixtureRegisterWithContext(registerRequiredBuildComponentsForTest),
)
// The directory in which rust test default modules will be defined.
@@ -197,7 +196,7 @@
return bp
}
-func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
+func registerRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
ctx.RegisterModuleType("rust_binary", RustBinaryFactory)
ctx.RegisterModuleType("rust_binary_host", RustBinaryHostFactory)
ctx.RegisterModuleType("rust_bindgen", RustBindgenFactory)
@@ -231,14 +230,3 @@
})
ctx.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
}
-
-func CreateTestContext(config android.Config) *android.TestContext {
- ctx := android.NewTestArchContext(config)
- android.RegisterPrebuiltMutators(ctx)
- ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
- genrule.RegisterGenruleBuildComponents(ctx)
- cc.RegisterRequiredBuildComponentsForTest(ctx)
- RegisterRequiredBuildComponentsForTest(ctx)
-
- return ctx
-}
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/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index 18174a4..30cb937 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -27,7 +27,6 @@
platform-mainline-test-exports
runtime-module-host-exports
runtime-module-sdk
- stats-log-api-gen-exports
statsd-module-sdk
statsd-module-sdk-for-art
tzdata-module-test-exports
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/gen_sorted_bss_symbols.sh b/scripts/gen_sorted_bss_symbols.sh
index 244ed0d..a9b61a1 100755
--- a/scripts/gen_sorted_bss_symbols.sh
+++ b/scripts/gen_sorted_bss_symbols.sh
@@ -18,11 +18,11 @@
# their sizes.
# Inputs:
# Environment:
-# CROSS_COMPILE: prefix added to nm tools
+# CLANG_BIN: path to the clang bin directory
# Arguments:
# $1: Input ELF file
# $2: Output symbol ordering file
set -o pipefail
-${CROSS_COMPILE}nm --size-sort $1 | awk '{if ($2 == "b" || $2 == "B") print $3}' > $2
+${CLANG_BIN}/llvm-nm --size-sort $1 | awk '{if ($2 == "b" || $2 == "B") print $3}' > $2
diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py
index 1343f35..8168fbf 100755
--- a/scripts/manifest_check.py
+++ b/scripts/manifest_check.py
@@ -74,7 +74,7 @@
return parser.parse_args()
-def enforce_uses_libraries(manifest, required, optional, relax, is_apk = False):
+def enforce_uses_libraries(manifest, required, optional, relax, is_apk, path):
"""Verify that the <uses-library> tags in the manifest match those provided
by the build system.
@@ -86,26 +86,36 @@
is_apk: if the manifest comes from an APK or an XML file
"""
if is_apk:
- manifest_required, manifest_optional = extract_uses_libs_apk(manifest)
+ manifest_required, manifest_optional, tags = extract_uses_libs_apk(manifest)
else:
- manifest_required, manifest_optional = extract_uses_libs_xml(manifest)
+ manifest_required, manifest_optional, tags = extract_uses_libs_xml(manifest)
- err = []
- if manifest_required != required:
- err.append('Expected required <uses-library> tags "%s", got "%s"' %
- (', '.join(required), ', '.join(manifest_required)))
+ if manifest_required == required and manifest_optional == optional:
+ return None
- if manifest_optional != optional:
- err.append('Expected optional <uses-library> tags "%s", got "%s"' %
- (', '.join(optional), ', '.join(manifest_optional)))
+ errmsg = ''.join([
+ 'mismatch in the <uses-library> tags between the build system and the '
+ 'manifest:\n',
+ '\t- required libraries in build system: [%s]\n' % ', '.join(required),
+ '\t vs. in the manifest: [%s]\n' % ', '.join(manifest_required),
+ '\t- optional libraries in build system: [%s]\n' % ', '.join(optional),
+ '\t vs. in the manifest: [%s]\n' % ', '.join(manifest_optional),
+ '\t- tags in the manifest (%s):\n' % path,
+ '\t\t%s\n' % '\t\t'.join(tags),
+ 'note: the following options are available:\n',
+ '\t- to temporarily disable the check on command line, rebuild with ',
+ 'RELAX_USES_LIBRARY_CHECK=true (this will set compiler filter "verify" ',
+ 'and disable AOT-compilation in dexpreopt)\n',
+ '\t- to temporarily disable the check for the whole product, set ',
+ 'PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true in the product makefiles\n',
+ '\t- to fix the check, make build system properties coherent with the '
+ 'manifest\n',
+ '\t- see build/make/Changes.md for details\n'])
- if err:
- errmsg = '\n'.join(err)
- if not relax:
- raise ManifestMismatchError(errmsg)
- return errmsg
+ if not relax:
+ raise ManifestMismatchError(errmsg)
- return None
+ return errmsg
def extract_uses_libs_apk(badging):
@@ -115,14 +125,19 @@
required = []
optional = []
+ lines = []
for match in re.finditer(pattern, badging):
+ lines.append(match.group(0))
libname = match.group(2)
if match.group(1) == None:
required.append(libname)
else:
optional.append(libname)
- return first_unique_elements(required), first_unique_elements(optional)
+ required = first_unique_elements(required)
+ optional = first_unique_elements(optional)
+ tags = first_unique_elements(lines)
+ return required, optional, tags
def extract_uses_libs_xml(xml):
@@ -143,7 +158,15 @@
required = [uses_library_name(x) for x in libs if uses_library_required(x)]
optional = [uses_library_name(x) for x in libs if not uses_library_required(x)]
- return first_unique_elements(required), first_unique_elements(optional)
+ # render <uses-library> tags as XML for a pretty error message
+ tags = []
+ for lib in libs:
+ tags.append(lib.toprettyxml())
+
+ required = first_unique_elements(required)
+ optional = first_unique_elements(optional)
+ tags = first_unique_elements(tags)
+ return required, optional, tags
def first_unique_elements(l):
@@ -278,7 +301,7 @@
# in the manifest. Raise an exception on mismatch, unless the script was
# passed a special parameter to suppress exceptions.
errmsg = enforce_uses_libraries(manifest, required, optional,
- args.enforce_uses_libraries_relax, is_apk)
+ args.enforce_uses_libraries_relax, is_apk, args.input)
# Create a status file that is empty on success, or contains an error
# message on failure. When exceptions are suppressed, dexpreopt command
@@ -289,7 +312,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/scripts/manifest_check_test.py b/scripts/manifest_check_test.py
index 635ba9d..7159bdd 100755
--- a/scripts/manifest_check_test.py
+++ b/scripts/manifest_check_test.py
@@ -49,9 +49,9 @@
try:
relax = False
manifest_check.enforce_uses_libraries(doc, uses_libraries,
- optional_uses_libraries, relax, is_apk=False)
+ optional_uses_libraries, relax, False, 'path/to/X/AndroidManifest.xml')
manifest_check.enforce_uses_libraries(apk, uses_libraries,
- optional_uses_libraries, relax, is_apk=True)
+ optional_uses_libraries, relax, True, 'path/to/X/X.apk')
return True
except manifest_check.ManifestMismatchError:
return False
diff --git a/scripts/toc.sh b/scripts/toc.sh
index 8b1d25f..c6b7866 100755
--- a/scripts/toc.sh
+++ b/scripts/toc.sh
@@ -17,7 +17,7 @@
# Script to handle generating a .toc file from a .so file
# Inputs:
# Environment:
-# CROSS_COMPILE: prefix added to readelf tool
+# CLANG_BIN: path to the clang bin directory
# Arguments:
# -i ${file}: input file (required)
# -o ${file}: output file (required)
@@ -35,34 +35,34 @@
}
do_elf() {
- ("${CROSS_COMPILE}readelf" -d "${infile}" | grep SONAME || echo "No SONAME for ${infile}") > "${outfile}.tmp"
- "${CROSS_COMPILE}readelf" --dyn-syms "${infile}" | awk '{$2=""; $3=""; print}' >> "${outfile}.tmp"
+ ("${CLANG_BIN}/llvm-readelf" -d "${infile}" | grep SONAME || echo "No SONAME for ${infile}") > "${outfile}.tmp"
+ "${CLANG_BIN}/llvm-readelf" --dyn-syms "${infile}" | awk '{$2=""; $3=""; print}' >> "${outfile}.tmp"
cat <<EOF > "${depsfile}"
${outfile}: \\
- ${CROSS_COMPILE}readelf \\
+ ${CLANG_BIN}/llvm-readelf \\
EOF
}
do_macho() {
- "${CROSS_COMPILE}/otool" -l "${infile}" | grep LC_ID_DYLIB -A 5 > "${outfile}.tmp"
- "${CROSS_COMPILE}/nm" -gP "${infile}" | cut -f1-2 -d" " | (grep -v 'U$' >> "${outfile}.tmp" || true)
+ "${CLANG_BIN}/llvm-objdump" -p "${infile}" | grep LC_ID_DYLIB -A 5 > "${outfile}.tmp"
+ "${CLANG_BIN}/llvm-nm" -gP "${infile}" | cut -f1-2 -d" " | (grep -v 'U$' >> "${outfile}.tmp" || true)
cat <<EOF > "${depsfile}"
${outfile}: \\
- ${CROSS_COMPILE}/otool \\
- ${CROSS_COMPILE}/nm \\
+ ${CLANG_BIN}/llvm-objdump \\
+ ${CLANG_BIN}/llvm-nm \\
EOF
}
do_pe() {
- "${CROSS_COMPILE}objdump" -x "${infile}" | grep "^Name" | cut -f3 -d" " > "${outfile}.tmp"
- "${CROSS_COMPILE}nm" -g -f p "${infile}" | cut -f1-2 -d" " >> "${outfile}.tmp"
+ "${CLANG_BIN}/llvm-objdump" -x "${infile}" | grep "^Name" | cut -f3 -d" " > "${outfile}.tmp"
+ "${CLANG_BIN}/llvm-nm" -gP "${infile}" | cut -f1-2 -d" " >> "${outfile}.tmp"
cat <<EOF > "${depsfile}"
${outfile}: \\
- ${CROSS_COMPILE}objdump \\
- ${CROSS_COMPILE}nm \\
+ ${CLANG_BIN}/llvm-objdump \\
+ ${CLANG_BIN}/llvm-nm \\
EOF
}
@@ -98,8 +98,8 @@
usage
fi
-if [ -z "${CROSS_COMPILE:-}" ]; then
- echo "CROSS_COMPILE environment variable must be set"
+if [ -z "${CLANG_BIN:-}" ]; then
+ echo "CLANG_BIN environment variable must be set"
usage
fi
@@ -107,7 +107,7 @@
cat <<EOF > "${depsfile}"
${outfile}: \\
- ${CROSS_COMPILE}readelf \\
+ ${CLANG_BIN}/llvm-readelf \\
EOF
if [ -n "${elf:-}" ]; then
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 9626a04..b19fcc5 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -486,6 +486,9 @@
}
`)
+ // TODO(b/183322862): Remove this and fix the issue.
+ errorHandler := android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module source path "snapshot/include_gen/generated_foo/gen/protos" does not exist`)
+
CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -518,6 +521,9 @@
.intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so
`),
+ snapshotTestErrorHandler(checkSnapshotWithoutSource, errorHandler),
+ snapshotTestErrorHandler(checkSnapshotWithSourcePreferred, errorHandler),
+ snapshotTestErrorHandler(checkSnapshotPreferredWithSource, errorHandler),
)
}
@@ -1816,7 +1822,10 @@
.intermediates/mynativelib/android_arm64_armv8-a_static/mynativelib.a -> arm64/lib/mynativelib.a
.intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
.intermediates/mynativelib/android_arm_armv7-a-neon_static/mynativelib.a -> arm/lib/mynativelib.a
-.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so`),
+.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so
+`),
+ // TODO(b/183315522): Remove this and fix the issue.
+ snapshotTestErrorHandler(checkSnapshotPreferredWithSource, android.FixtureExpectsAtLeastOneErrorMatchingPattern(`\Qunrecognized property "arch.arm.shared.export_include_dirs"\E`)),
)
}
@@ -2398,6 +2407,7 @@
"1",
"2",
"3",
+ "current",
],
},
arch: {
@@ -2452,6 +2462,7 @@
"1",
"2",
"3",
+ "current",
],
},
target: {
@@ -2491,6 +2502,7 @@
"1",
"2",
"3",
+ "current",
],
},
target: {
@@ -2664,6 +2676,11 @@
}
`)
+ // Mixing the snapshot with the source (irrespective of which one is preferred) causes a problem
+ // due to missing variants.
+ // TODO(b/183204176): Remove this and fix the cause.
+ snapshotWithSourceErrorHandler := android.FixtureExpectsAtLeastOneErrorMatchingPattern(`\QReplaceDependencies could not find identical variant {os:android,image:,arch:arm64_armv8-a,sdk:,link:shared,version:} for module mynativelib\E`)
+
CheckSnapshot(t, result, "mysdk", "",
checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -2688,6 +2705,9 @@
checkAllCopyRules(`
myinclude/Test.h -> include/myinclude/Test.h
arm64/include/Arm64Test.h -> arm64/include/arm64/include/Arm64Test.h
-.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so`),
+.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so
+`),
+ snapshotTestErrorHandler(checkSnapshotWithSourcePreferred, snapshotWithSourceErrorHandler),
+ snapshotTestErrorHandler(checkSnapshotPreferredWithSource, snapshotWithSourceErrorHandler),
)
}
diff --git a/sdk/compat_config_sdk_test.go b/sdk/compat_config_sdk_test.go
index dffc02a..00073c2 100644
--- a/sdk/compat_config_sdk_test.go
+++ b/sdk/compat_config_sdk_test.go
@@ -66,5 +66,26 @@
checkAllCopyRules(`
.intermediates/myconfig/android_common/myconfig_meta.xml -> compat_configs/myconfig/myconfig_meta.xml
`),
+ snapshotTestChecker(checkSnapshotWithoutSource,
+ func(t *testing.T, result *android.TestResult) {
+ // Make sure that the snapshot metadata is collated by the platform compat config singleton.
+ java.CheckMergedCompatConfigInputs(t, result, "snapshot module", "snapshot/compat_configs/myconfig/myconfig_meta.xml")
+ }),
+
+ snapshotTestChecker(checkSnapshotWithSourcePreferred,
+ func(t *testing.T, result *android.TestResult) {
+ // Make sure that the snapshot metadata is collated by the platform compat config singleton.
+ java.CheckMergedCompatConfigInputs(t, result, "snapshot module",
+ "out/soong/.intermediates/myconfig/android_common/myconfig_meta.xml",
+ )
+ }),
+
+ snapshotTestChecker(checkSnapshotPreferredWithSource,
+ func(t *testing.T, result *android.TestResult) {
+ // Make sure that the snapshot metadata is collated by the platform compat config singleton.
+ java.CheckMergedCompatConfigInputs(t, result, "snapshot module",
+ "snapshot/compat_configs/myconfig/myconfig_meta.xml",
+ )
+ }),
)
}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index ad45131..208cd58 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -24,6 +24,16 @@
var prepareForSdkTestWithJava = android.GroupFixturePreparers(
java.PrepareForTestWithJavaBuildComponents,
PrepareForTestWithSdkBuildComponents,
+
+ // Ensure that all source paths are provided. This helps ensure that the snapshot generation is
+ // consistent and all files referenced from the snapshot's Android.bp file have actually been
+ // copied into the snapshot.
+ android.PrepareForTestDisallowNonExistentPaths,
+
+ // Files needs by most of the tests.
+ android.MockFS{
+ "Test.java": nil,
+ }.AddToFixture(),
)
var prepareForSdkTestWithJavaSdkLibrary = android.GroupFixturePreparers(
@@ -48,42 +58,17 @@
system_modules: "none",
sdk_version: "none",
}
-
- java_import {
- name: "sdkmember",
- prefer: true,
- jars: ["prebuilt.jar"],
- }
`)
// Make sure that the mysdk module depends on "sdkmember" and not "prebuilt_sdkmember".
- java.CheckModuleDependencies(t, result.TestContext, "mysdk", "android_common", []string{"sdkmember"})
+ sdkChecker := func(t *testing.T, result *android.TestResult) {
+ java.CheckModuleDependencies(t, result.TestContext, "mysdk", "android_common", []string{"sdkmember"})
+ }
CheckSnapshot(t, result, "mysdk", "",
- checkAndroidBpContents(`// This is auto-generated. DO NOT EDIT.
-
-java_import {
- name: "mysdk_sdkmember@current",
- sdk_member_name: "sdkmember",
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
- jars: ["java/sdkmember.jar"],
-}
-
-java_import {
- name: "sdkmember",
- prefer: false,
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
- jars: ["java/sdkmember.jar"],
-}
-
-sdk_snapshot {
- name: "mysdk@current",
- visibility: ["//visibility:public"],
- java_header_libs: ["mysdk_sdkmember@current"],
-}
-`))
+ snapshotTestChecker(checkSnapshotWithSourcePreferred, sdkChecker),
+ snapshotTestChecker(checkSnapshotPreferredWithSource, sdkChecker),
+ )
}
func TestBasicSdkWithJavaLibrary(t *testing.T) {
@@ -364,6 +349,7 @@
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
android.FixtureAddFile("aidl/foo/bar/Test.aidl", nil),
+ android.FixtureAddFile("resource.txt", nil),
).RunTestWithBp(t, `
module_exports {
name: "myexports",
@@ -419,7 +405,11 @@
}
func TestSnapshotWithJavaBootLibrary(t *testing.T) {
- result := android.GroupFixturePreparers(prepareForSdkTestWithJava).RunTestWithBp(t, `
+ result := android.GroupFixturePreparers(
+ prepareForSdkTestWithJava,
+ android.FixtureAddFile("aidl", nil),
+ android.FixtureAddFile("resource.txt", nil),
+ ).RunTestWithBp(t, `
module_exports {
name: "myexports",
java_boot_libs: ["myjavalib"],
@@ -1564,7 +1554,10 @@
}
func TestSnapshotWithJavaSdkLibrary_DoctagFiles(t *testing.T) {
- result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
+ result := android.GroupFixturePreparers(
+ prepareForSdkTestWithJavaSdkLibrary,
+ android.FixtureAddFile("docs/known_doctags", nil),
+ ).RunTestWithBp(t, `
sdk {
name: "mysdk",
java_sdk_libs: ["myjavalib"],
diff --git a/sdk/sdk.go b/sdk/sdk.go
index e561529..b60fb18 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -486,6 +486,15 @@
// sdk containing sdkmember.
memberName := versionedSdkMember.MemberName()
+ // Convert a panic into a normal error to allow it to be more easily tested for. This is a
+ // temporary workaround, once http://b/183204176 has been fixed this can be removed.
+ // TODO(b/183204176): Remove this after fixing.
+ defer func() {
+ if r := recover(); r != nil {
+ mctx.ModuleErrorf("%s", r)
+ }
+ }()
+
// Replace dependencies on sdkmember with a dependency on the current module which
// is a versioned prebuilt of the sdkmember if required.
mctx.ReplaceDependenciesIf(memberName, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool {
diff --git a/sdk/testing.go b/sdk/testing.go
index ba40f67..9465e13 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -48,10 +48,10 @@
"system/sepolicy/apex/myapex-file_contexts": nil,
"system/sepolicy/apex/myapex2-file_contexts": nil,
"system/sepolicy/apex/mysdkapex-file_contexts": nil,
- "myapex.avbpubkey": nil,
- "myapex.pem": nil,
- "myapex.x509.pem": nil,
- "myapex.pk8": nil,
+ "sdk/tests/myapex.avbpubkey": nil,
+ "sdk/tests/myapex.pem": nil,
+ "sdk/tests/myapex.x509.pem": nil,
+ "sdk/tests/myapex.pk8": nil,
}),
)
@@ -80,6 +80,12 @@
{android.Windows, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", "", true},
}
}),
+
+ // Make sure that every test provides all the source files.
+ android.PrepareForTestDisallowNonExistentPaths,
+ android.MockFS{
+ "Test.java": nil,
+ }.AddToFixture(),
)
var PrepareForTestWithSdkBuildComponents = android.GroupFixturePreparers(
@@ -89,7 +95,10 @@
func testSdkWithFs(t *testing.T, bp string, fs android.MockFS) *android.TestResult {
t.Helper()
- return prepareForSdkTest.RunTest(t, fs.AddToFixture(), android.FixtureWithRootAndroidBp(bp))
+ return android.GroupFixturePreparers(
+ prepareForSdkTest,
+ fs.AddToFixture(),
+ ).RunTestWithBp(t, bp)
}
func testSdkError(t *testing.T, pattern, bp string) {
@@ -125,6 +134,7 @@
androidBpContents: sdk.GetAndroidBpContentsForTests(),
androidUnversionedBpContents: sdk.GetUnversionedAndroidBpContentsForTests(),
androidVersionedBpContents: sdk.GetVersionedAndroidBpContentsForTests(),
+ snapshotTestCustomizations: map[snapshotTest]*snapshotTestCustomization{},
}
buildParams := sdk.BuildParamsForTests()
@@ -183,6 +193,24 @@
return info
}
+// The enum of different sdk snapshot tests performed by CheckSnapshot.
+type snapshotTest int
+
+const (
+ // The enumeration of the different test configurations.
+ // A test with the snapshot/Android.bp file but without the original Android.bp file.
+ checkSnapshotWithoutSource snapshotTest = iota
+
+ // A test with both the original source and the snapshot, with the source preferred.
+ checkSnapshotWithSourcePreferred
+
+ // A test with both the original source and the snapshot, with the snapshot preferred.
+ checkSnapshotPreferredWithSource
+
+ // The directory into which the snapshot will be 'unpacked'.
+ snapshotSubDir = "snapshot"
+)
+
// Check the snapshot build rules.
//
// Takes a list of functions which check different facets of the snapshot build rules.
@@ -214,31 +242,58 @@
// Populate a mock filesystem with the files that would have been copied by
// the rules.
fs := android.MockFS{}
- snapshotSubDir := "snapshot"
for _, dest := range snapshotBuildInfo.snapshotContents {
fs[filepath.Join(snapshotSubDir, dest)] = nil
}
fs[filepath.Join(snapshotSubDir, "Android.bp")] = []byte(snapshotBuildInfo.androidBpContents)
- preparer := result.Preparer()
+ // The preparers from the original source fixture.
+ sourcePreparers := result.Preparer()
- // Process the generated bp file to make sure it is valid. Use the same preparer as was used to
- // produce this result.
+ // Preparer to combine the snapshot and the source.
+ snapshotPreparer := android.GroupFixturePreparers(sourcePreparers, fs.AddToFixture())
+
+ var runSnapshotTestWithCheckers = func(t *testing.T, testConfig snapshotTest, extraPreparer android.FixturePreparer) {
+ customization := snapshotBuildInfo.snapshotTestCustomization(testConfig)
+
+ // TODO(b/183184375): Set Config.TestAllowNonExistentPaths = false to verify that all the
+ // files the snapshot needs are actually copied into the snapshot.
+
+ // Run the snapshot with the snapshot preparer and the extra preparer, which must come after as
+ // it may need to modify parts of the MockFS populated by the snapshot preparer.
+ result := android.GroupFixturePreparers(snapshotPreparer, extraPreparer).
+ ExtendWithErrorHandler(customization.errorHandler).
+ RunTest(t)
+
+ // Perform any additional checks the test need on the result of processing the snapshot.
+ for _, checker := range customization.checkers {
+ checker(t, result)
+ }
+ }
+
t.Run("snapshot without source", func(t *testing.T) {
- android.GroupFixturePreparers(
- preparer,
- // TODO(b/183184375): Set Config.TestAllowNonExistentPaths = false to verify that all the
- // files the snapshot needs are actually copied into the snapshot.
+ // Remove the source Android.bp file to make sure it works without.
+ removeSourceAndroidBp := android.FixtureModifyMockFS(func(fs android.MockFS) {
+ delete(fs, "Android.bp")
+ })
- // Add the files (including bp) created for this snapshot to the test fixture.
- fs.AddToFixture(),
+ runSnapshotTestWithCheckers(t, checkSnapshotWithoutSource, removeSourceAndroidBp)
+ })
- // Remove the source Android.bp file to make sure it works without.
- // TODO(b/183184375): Add a test with the source.
- android.FixtureModifyMockFS(func(fs android.MockFS) {
- delete(fs, "Android.bp")
- }),
- ).RunTest(t)
+ t.Run("snapshot with source preferred", func(t *testing.T) {
+ runSnapshotTestWithCheckers(t, checkSnapshotWithSourcePreferred, android.NullFixturePreparer)
+ })
+
+ t.Run("snapshot preferred with source", func(t *testing.T) {
+ // Replace the snapshot/Android.bp file with one where "prefer: false," has been replaced with
+ // "prefer: true,"
+ preferPrebuilts := android.FixtureModifyMockFS(func(fs android.MockFS) {
+ snapshotBpFile := filepath.Join(snapshotSubDir, "Android.bp")
+ unpreferred := string(fs[snapshotBpFile])
+ fs[snapshotBpFile] = []byte(strings.ReplaceAll(unpreferred, "prefer: false,", "prefer: true,"))
+ })
+
+ runSnapshotTestWithCheckers(t, checkSnapshotPreferredWithSource, preferPrebuilts)
})
}
@@ -312,6 +367,46 @@
}
}
+type resultChecker func(t *testing.T, result *android.TestResult)
+
+// snapshotTestChecker registers a checker that will be run against the result of processing the
+// generated snapshot for the specified snapshotTest.
+func snapshotTestChecker(snapshotTest snapshotTest, checker resultChecker) snapshotBuildInfoChecker {
+ return func(info *snapshotBuildInfo) {
+ customization := info.snapshotTestCustomization(snapshotTest)
+ customization.checkers = append(customization.checkers, checker)
+ }
+}
+
+// snapshotTestErrorHandler registers an error handler to use when processing the snapshot
+// in the specific test case.
+//
+// Generally, the snapshot should work with all the test cases but some do not and just in case
+// there are a lot of issues to resolve, or it will take a lot of time this is a
+// get-out-of-jail-free card that allows progress to be made.
+//
+// deprecated: should only be used as a temporary workaround with an attached to do and bug.
+func snapshotTestErrorHandler(snapshotTest snapshotTest, handler android.FixtureErrorHandler) snapshotBuildInfoChecker {
+ return func(info *snapshotBuildInfo) {
+ customization := info.snapshotTestCustomization(snapshotTest)
+ customization.errorHandler = handler
+ }
+}
+
+// Encapsulates information provided by each test to customize a specific snapshotTest.
+type snapshotTestCustomization struct {
+ // Checkers that are run on the result of processing the preferred snapshot in a specific test
+ // case.
+ checkers []resultChecker
+
+ // Specify an error handler for when processing a specific test case.
+ //
+ // In some cases the generated snapshot cannot be used in a test configuration. Those cases are
+ // invariably bugs that need to be resolved but sometimes that can take a while. This provides a
+ // mechanism to temporarily ignore that error.
+ errorHandler android.FixtureErrorHandler
+}
+
// Encapsulates information about the snapshot build structure in order to insulate tests from
// knowing too much about internal structures.
//
@@ -355,4 +450,21 @@
// The final output zip.
outputZip string
+
+ // The test specific customizations for each snapshot test.
+ snapshotTestCustomizations map[snapshotTest]*snapshotTestCustomization
+}
+
+// snapshotTestCustomization gets the test specific customization for the specified snapshotTest.
+//
+// If no customization was created previously then it creates a default customization.
+func (i *snapshotBuildInfo) snapshotTestCustomization(snapshotTest snapshotTest) *snapshotTestCustomization {
+ customization := i.snapshotTestCustomizations[snapshotTest]
+ if customization == nil {
+ customization = &snapshotTestCustomization{
+ errorHandler: android.FixtureExpectsNoErrors,
+ }
+ i.snapshotTestCustomizations[snapshotTest] = customization
+ }
+ return customization
}
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,
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index e9d9051..f42f9e9 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -371,6 +371,6 @@
android.AssertStringEquals(t, "min_sdk_version forwarding to cc module", "29", propFromCc)
javaModule := result.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
- propFromJava := javaModule.MinSdkVersion()
+ propFromJava := javaModule.MinSdkVersionString()
android.AssertStringEquals(t, "min_sdk_version forwarding to java module", "30", propFromJava)
}
diff --git a/ui/build/bazel.go b/ui/build/bazel.go
index ec561d5..0ebfcd8 100644
--- a/ui/build/bazel.go
+++ b/ui/build/bazel.go
@@ -149,6 +149,9 @@
cmd.Args = append(cmd.Args, "--action_env=PATH="+pathEnvValue)
}
+ // Allow Bazel actions to see the SHELL variable (passed to Bazel above)
+ cmd.Args = append(cmd.Args, "--action_env=SHELL")
+
// Append custom build flags to the Bazel command. Changes to these flags
// may invalidate Bazel's analysis cache.
// These should be appended as the final args, so that they take precedence.