Merge "rust: Fix Host multilib prop for rust_test modules."
diff --git a/android/Android.bp b/android/Android.bp
index cfa2be3..da36959 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -47,6 +47,7 @@
"image.go",
"license.go",
"license_kind.go",
+ "license_metadata.go",
"license_sdk_member.go",
"licenses.go",
"makefile_goal.go",
@@ -113,6 +114,7 @@
"paths_test.go",
"prebuilt_test.go",
"rule_builder_test.go",
+ "sdk_version_test.go",
"sdk_test.go",
"singleton_module_test.go",
"soong_config_modules_test.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index 0adc2a6..4f6e24c 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -474,6 +474,7 @@
ModuleDir(module blueprint.Module) string
Config() Config
ModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{}
+ ModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool
}
func (a *AndroidMkEntries) fillInEntries(ctx fillInEntriesContext, mod blueprint.Module) {
@@ -609,6 +610,11 @@
}
}
+ if ctx.ModuleHasProvider(mod, LicenseMetadataProvider) {
+ licenseMetadata := ctx.ModuleProvider(mod, LicenseMetadataProvider).(*LicenseMetadataInfo)
+ a.SetPath("LOCAL_SOONG_LICENSE_METADATA", licenseMetadata.LicenseMetadataPath)
+ }
+
extraCtx := &androidMkExtraEntriesContext{
ctx: ctx,
mod: mod,
@@ -887,6 +893,10 @@
return nil
}
+func ShouldSkipAndroidMkProcessing(module Module) bool {
+ return shouldSkipAndroidMkProcessing(module.base())
+}
+
func shouldSkipAndroidMkProcessing(module *ModuleBase) bool {
if !module.commonProperties.NamespaceExportedToMake {
// TODO(jeffrygaston) do we want to validate that there are no modules being
diff --git a/android/apex.go b/android/apex.go
index 6b4054d..cf1bcfe 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -878,12 +878,8 @@
"kotlinx-coroutines-android-nodeps": 30,
"kotlinx-coroutines-core": 28,
"kotlinx-coroutines-core-nodeps": 30,
- "libasyncio": 30,
"libbrotli": 30,
- "libbuildversion": 30,
"libcrypto_static": 30,
- "libcrypto_utils": 30,
- "libdiagnose_usb": 30,
"libeigen": 30,
"liblz4": 30,
"libmdnssd": 30,
@@ -893,7 +889,6 @@
"libprocpartition": 30,
"libprotobuf-java-lite": 30,
"libprotoutil": 30,
- "libsync": 30,
"libtextclassifier_hash_headers": 30,
"libtextclassifier_hash_static": 30,
"libtflite_kernel_utils": 30,
@@ -913,16 +908,18 @@
//
// Return true if the `to` module should be visited, false otherwise.
type PayloadDepsCallback func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool
+type WalkPayloadDepsFunc func(ctx ModuleContext, do PayloadDepsCallback)
-// UpdatableModule represents updatable APEX/APK
-type UpdatableModule interface {
+// ModuleWithMinSdkVersionCheck represents a module that implements min_sdk_version checks
+type ModuleWithMinSdkVersionCheck interface {
Module
- WalkPayloadDeps(ctx ModuleContext, do PayloadDepsCallback)
+ MinSdkVersion(ctx EarlyModuleContext) SdkSpec
+ CheckMinSdkVersion(ctx ModuleContext)
}
// CheckMinSdkVersion checks if every dependency of an updatable module sets min_sdk_version
// accordingly
-func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion ApiLevel) {
+func CheckMinSdkVersion(ctx ModuleContext, minSdkVersion ApiLevel, walk WalkPayloadDepsFunc) {
// do not enforce min_sdk_version for host
if ctx.Host() {
return
@@ -938,7 +935,7 @@
return
}
- m.WalkPayloadDeps(ctx, func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool {
+ walk(ctx, func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool {
if externalDep {
// external deps are outside the payload boundary, which is "stable"
// interface. We don't have to check min_sdk_version for external
@@ -948,6 +945,14 @@
if am, ok := from.(DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
return false
}
+ if m, ok := to.(ModuleWithMinSdkVersionCheck); ok {
+ // This dependency performs its own min_sdk_version check, just make sure it sets min_sdk_version
+ // to trigger the check.
+ if !m.MinSdkVersion(ctx).Specified() {
+ ctx.OtherModuleErrorf(m, "must set min_sdk_version")
+ }
+ return false
+ }
if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil {
toName := ctx.OtherModuleName(to)
if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver.GreaterThan(minSdkVersion) {
diff --git a/android/api_levels.go b/android/api_levels.go
index c1b3ba2..1fbbc15 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -192,8 +192,8 @@
// * "30" -> "30"
// * "R" -> "30"
// * "S" -> "S"
-func ReplaceFinalizedCodenames(ctx PathContext, raw string) string {
- num, ok := getFinalCodenamesMap(ctx.Config())[raw]
+func ReplaceFinalizedCodenames(config Config, raw string) string {
+ num, ok := getFinalCodenamesMap(config)[raw]
if !ok {
return raw
}
@@ -201,7 +201,7 @@
return strconv.Itoa(num)
}
-// Converts the given string `raw` to an ApiLevel, possibly returning an error.
+// ApiLevelFromUser converts the given string `raw` to an ApiLevel, possibly returning an error.
//
// `raw` must be non-empty. Passing an empty string results in a panic.
//
@@ -216,6 +216,12 @@
// Inputs that are not "current", known previews, or convertible to an integer
// will return an error.
func ApiLevelFromUser(ctx PathContext, raw string) (ApiLevel, error) {
+ return ApiLevelFromUserWithConfig(ctx.Config(), raw)
+}
+
+// ApiLevelFromUserWithConfig implements ApiLevelFromUser, see comments for
+// ApiLevelFromUser for more details.
+func ApiLevelFromUserWithConfig(config Config, raw string) (ApiLevel, error) {
if raw == "" {
panic("API level string must be non-empty")
}
@@ -224,13 +230,13 @@
return FutureApiLevel, nil
}
- for _, preview := range ctx.Config().PreviewApiLevels() {
+ for _, preview := range config.PreviewApiLevels() {
if raw == preview.String() {
return preview, nil
}
}
- canonical := ReplaceFinalizedCodenames(ctx, raw)
+ canonical := ReplaceFinalizedCodenames(config, raw)
asInt, err := strconv.Atoi(canonical)
if err != nil {
return NoneApiLevel, fmt.Errorf("%q could not be parsed as an integer and is not a recognized codename", canonical)
diff --git a/android/arch.go b/android/arch.go
index 3bf54b7..3cc5e82 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -566,6 +566,8 @@
return variants
}
+var DarwinUniversalVariantTag = archDepTag{name: "darwin universal binary"}
+
// archMutator splits a module into a variant for each Target requested by the module. Target selection
// for a module is in three levels, OsClass, multilib, and then Target.
// OsClass selection is determined by:
@@ -652,7 +654,7 @@
prefer32 := os == Windows
// Determine the multilib selection for this module.
- multilib, extraMultilib := decodeMultilib(base, os.Class)
+ multilib, extraMultilib := decodeMultilib(base, os)
// Convert the multilib selection into a list of Targets.
targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
@@ -702,6 +704,16 @@
m.base().commonProperties.SkipInstall = true
}
}
+
+ // Create a dependency for Darwin Universal binaries from the primary to secondary
+ // architecture. The module itself will be responsible for calling lipo to merge the outputs.
+ if os == Darwin {
+ if multilib == "darwin_universal" && len(modules) == 2 {
+ mctx.AddInterVariantDependency(DarwinUniversalVariantTag, modules[1], modules[0])
+ } else if multilib == "darwin_universal_common_first" && len(modules) == 3 {
+ mctx.AddInterVariantDependency(DarwinUniversalVariantTag, modules[2], modules[1])
+ }
+ }
}
// addTargetProperties annotates a variant with the Target is is being compiled for, the list
@@ -717,9 +729,9 @@
// multilib from the factory's call to InitAndroidArchModule if none was set. For modules that
// called InitAndroidMultiTargetsArchModule it always returns "common" for multilib, and returns
// the actual multilib in extraMultilib.
-func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib string) {
+func decodeMultilib(base *ModuleBase, os OsType) (multilib, extraMultilib string) {
// First check the "android.compile_multilib" or "host.compile_multilib" properties.
- switch class {
+ switch os.Class {
case Device:
multilib = String(base.commonProperties.Target.Android.Compile_multilib)
case Host:
@@ -737,6 +749,26 @@
}
if base.commonProperties.UseTargetVariants {
+ // Darwin has the concept of "universal binaries" which is implemented in Soong by
+ // building both x86_64 and arm64 variants, and having select module types know how to
+ // merge the outputs of their corresponding variants together into a final binary. Most
+ // module types don't need to understand this logic, as we only build a small portion
+ // of the tree for Darwin, and only module types writing macho files need to do the
+ // merging.
+ //
+ // This logic is not enabled for:
+ // "common", as it's not an arch-specific variant
+ // "32", as Darwin never has a 32-bit variant
+ // !UseTargetVariants, as the module has opted into handling the arch-specific logic on
+ // its own.
+ if os == Darwin && multilib != "common" && multilib != "32" {
+ if multilib == "common_first" {
+ multilib = "darwin_universal_common_first"
+ } else {
+ multilib = "darwin_universal"
+ }
+ }
+
return multilib, ""
} else {
// For app modules a single arch variant will be created per OS class which is expected to handle all the
@@ -1793,6 +1825,15 @@
if len(buildTargets) == 0 {
buildTargets = filterMultilibTargets(targets, "lib64")
}
+ case "darwin_universal":
+ buildTargets = filterMultilibTargets(targets, "lib64")
+ // Reverse the targets so that the first architecture can depend on the second
+ // architecture module in order to merge the outputs.
+ reverseSliceInPlace(buildTargets)
+ case "darwin_universal_common_first":
+ archTargets := filterMultilibTargets(targets, "lib64")
+ reverseSliceInPlace(archTargets)
+ buildTargets = append(getCommonTargets(targets), archTargets...)
default:
return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", "prefer32" or "first_prefer32" found %q`,
multilib)
diff --git a/android/bazel.go b/android/bazel.go
index e97acff..8c63204 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -15,6 +15,8 @@
package android
import (
+ "bufio"
+ "errors"
"fmt"
"io/ioutil"
"path/filepath"
@@ -39,6 +41,10 @@
// To opt-out a module, set bazel_module: { bp2build_available: false }
// To defer the default setting for the directory, do not set the value.
Bp2build_available *bool
+
+ // CanConvertToBazel is set via InitBazelModule to indicate that a module type can be converted to
+ // Bazel with Bp2build.
+ CanConvertToBazel bool `blueprint:"mutated"`
}
// Properties contains common module properties for Bazel migration purposes.
@@ -80,9 +86,10 @@
HasHandcraftedLabel() bool
HandcraftedLabel() string
GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string
- ConvertWithBp2build(ctx BazelConversionContext) bool
- convertWithBp2build(ctx BazelConversionContext, module blueprint.Module) bool
+ ShouldConvertWithBp2build(ctx BazelConversionContext) bool
+ shouldConvertWithBp2build(ctx BazelConversionContext, module blueprint.Module) bool
GetBazelBuildFileContents(c Config, path, name string) (string, error)
+ ConvertWithBp2build(ctx TopDownMutatorContext)
// namespacedVariableProps is a map from a soong config variable namespace
// (e.g. acme, android) to a map of interfaces{}, which are really
@@ -109,6 +116,7 @@
// properties.
func InitBazelModule(module BazelModule) {
module.AddProperties(module.bazelProps())
+ module.bazelProps().Bazel_module.CanConvertToBazel = true
}
// bazelProps returns the Bazel properties for the given BazelModuleBase.
@@ -147,7 +155,7 @@
if b.HasHandcraftedLabel() {
return b.HandcraftedLabel()
}
- if b.ConvertWithBp2build(ctx) {
+ if b.ShouldConvertWithBp2build(ctx) {
return bp2buildModuleLabel(ctx, module)
}
return "" // no label for unconverted module
@@ -200,7 +208,8 @@
"build/bazel/platforms":/* recursive = */ true,
"build/bazel/product_variables":/* recursive = */ true,
"build/bazel_common_rules":/* recursive = */ true,
- "build/make/tools":/* recursive = */ true,
+ // build/make/tools/signapk BUILD file is generated, so build/make/tools is not recursive.
+ "build/make/tools":/* recursive = */ false,
"build/pesto":/* recursive = */ true,
// external/bazelbuild-rules_android/... is needed by mixed builds, otherwise mixed builds analysis fails
@@ -226,33 +235,92 @@
// Configure modules in these directories to enable bp2build_available: true or false by default.
bp2buildDefaultConfig = Bp2BuildConfig{
- "bionic": Bp2BuildDefaultTrueRecursively,
+ "art/libdexfile": Bp2BuildDefaultTrueRecursively,
+ "bionic": Bp2BuildDefaultTrueRecursively,
+ "bootable/recovery/tools/recovery_l10n": Bp2BuildDefaultTrue,
+ "build/bazel/examples/soong_config_variables": Bp2BuildDefaultTrueRecursively,
"build/bazel/examples/apex/minimal": Bp2BuildDefaultTrueRecursively,
+ "build/make/tools/signapk": Bp2BuildDefaultTrue,
+ "build/soong": Bp2BuildDefaultTrue,
"build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir
+ "build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue,
+ "build/soong/cc/symbolfile": Bp2BuildDefaultTrue,
+ "cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively,
+ "development/apps/DevelopmentSettings": Bp2BuildDefaultTrue,
+ "development/apps/Fallback": Bp2BuildDefaultTrue,
+ "development/apps/WidgetPreview": Bp2BuildDefaultTrue,
+ "development/samples/BasicGLSurfaceView": Bp2BuildDefaultTrue,
+ "development/samples/BluetoothChat": Bp2BuildDefaultTrue,
+ "development/samples/BrokenKeyDerivation": Bp2BuildDefaultTrue,
+ "development/samples/Compass": Bp2BuildDefaultTrue,
+ "development/samples/ContactManager": Bp2BuildDefaultTrue,
+ "development/samples/FixedGridLayout": Bp2BuildDefaultTrue,
+ "development/samples/HelloEffects": Bp2BuildDefaultTrue,
+ "development/samples/Home": Bp2BuildDefaultTrue,
+ "development/samples/HoneycombGallery": Bp2BuildDefaultTrue,
+ "development/samples/JetBoy": Bp2BuildDefaultTrue,
+ "development/samples/KeyChainDemo": Bp2BuildDefaultTrue,
+ "development/samples/LceDemo": Bp2BuildDefaultTrue,
+ "development/samples/LunarLander": Bp2BuildDefaultTrue,
+ "development/samples/MultiResolution": Bp2BuildDefaultTrue,
+ "development/samples/MultiWindow": Bp2BuildDefaultTrue,
+ "development/samples/NotePad": Bp2BuildDefaultTrue,
+ "development/samples/Obb": Bp2BuildDefaultTrue,
+ "development/samples/RSSReader": Bp2BuildDefaultTrue,
+ "development/samples/ReceiveShareDemo": Bp2BuildDefaultTrue,
+ "development/samples/SearchableDictionary": Bp2BuildDefaultTrue,
+ "development/samples/SipDemo": Bp2BuildDefaultTrue,
+ "development/samples/SkeletonApp": Bp2BuildDefaultTrue,
+ "development/samples/Snake": Bp2BuildDefaultTrue,
+ "development/samples/SpellChecker/": Bp2BuildDefaultTrueRecursively,
+ "development/samples/ThemedNavBarKeyboard": Bp2BuildDefaultTrue,
+ "development/samples/ToyVpn": Bp2BuildDefaultTrue,
+ "development/samples/TtsEngine": Bp2BuildDefaultTrue,
+ "development/samples/USB/AdbTest": Bp2BuildDefaultTrue,
+ "development/samples/USB/MissileLauncher": Bp2BuildDefaultTrue,
+ "development/samples/VoiceRecognitionService": Bp2BuildDefaultTrue,
+ "development/samples/VoicemailProviderDemo": Bp2BuildDefaultTrue,
"development/sdk": Bp2BuildDefaultTrueRecursively,
"external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
"external/boringssl": Bp2BuildDefaultTrueRecursively,
+ "external/bouncycastle": Bp2BuildDefaultTrue,
"external/brotli": Bp2BuildDefaultTrue,
+ "external/conscrypt": Bp2BuildDefaultTrue,
"external/fmtlib": Bp2BuildDefaultTrueRecursively,
"external/google-benchmark": Bp2BuildDefaultTrueRecursively,
- "external/googletest/googletest": Bp2BuildDefaultTrueRecursively,
+ "external/googletest": Bp2BuildDefaultTrueRecursively,
"external/gwp_asan": Bp2BuildDefaultTrueRecursively,
"external/jemalloc_new": Bp2BuildDefaultTrueRecursively,
"external/jsoncpp": Bp2BuildDefaultTrueRecursively,
"external/libcap": Bp2BuildDefaultTrueRecursively,
"external/libcxx": Bp2BuildDefaultTrueRecursively,
"external/libcxxabi": Bp2BuildDefaultTrueRecursively,
+ "external/libevent": Bp2BuildDefaultTrueRecursively,
"external/lz4/lib": Bp2BuildDefaultTrue,
+ "external/lzma/C": Bp2BuildDefaultTrueRecursively,
"external/mdnsresponder": Bp2BuildDefaultTrueRecursively,
"external/minijail": Bp2BuildDefaultTrueRecursively,
"external/pcre": Bp2BuildDefaultTrueRecursively,
"external/protobuf": Bp2BuildDefaultTrueRecursively,
"external/python/six": Bp2BuildDefaultTrueRecursively,
+ "external/selinux/libsepol": Bp2BuildDefaultTrueRecursively,
"external/scudo": Bp2BuildDefaultTrueRecursively,
"external/selinux/libselinux": Bp2BuildDefaultTrueRecursively,
"external/zlib": Bp2BuildDefaultTrueRecursively,
"external/zstd": Bp2BuildDefaultTrueRecursively,
+ "frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue,
+ "frameworks/base/startop/apps/test": Bp2BuildDefaultTrue,
"frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively,
+ "frameworks/native/opengl/tests/gl2_cameraeye": Bp2BuildDefaultTrue,
+ "frameworks/native/opengl/tests/gl2_java": Bp2BuildDefaultTrue,
+ "frameworks/native/opengl/tests/testLatency": Bp2BuildDefaultTrue,
+ "frameworks/native/opengl/tests/testPauseResume": Bp2BuildDefaultTrue,
+ "frameworks/native/opengl/tests/testViewport": Bp2BuildDefaultTrue,
+ "frameworks/proto_logging/stats/stats_log_api_gen": Bp2BuildDefaultTrueRecursively,
+ "libnativehelper": Bp2BuildDefaultTrueRecursively,
+ "packages/apps/DevCamera": Bp2BuildDefaultTrue,
+ "packages/apps/HTMLViewer": Bp2BuildDefaultTrue,
+ "packages/apps/Protips": Bp2BuildDefaultTrue,
"packages/modules/adb": Bp2BuildDefaultTrue,
"packages/modules/adb/crypto": Bp2BuildDefaultTrueRecursively,
"packages/modules/adb/libs": Bp2BuildDefaultTrueRecursively,
@@ -260,8 +328,12 @@
"packages/modules/adb/pairing_connection": Bp2BuildDefaultTrueRecursively,
"packages/modules/adb/proto": Bp2BuildDefaultTrueRecursively,
"packages/modules/adb/tls": Bp2BuildDefaultTrueRecursively,
+ "packages/providers/MediaProvider/tools/dialogs": Bp2BuildDefaultTrue,
+ "packages/screensavers/Basic": Bp2BuildDefaultTrue,
+ "packages/services/Car/tests/SampleRearViewCamera": Bp2BuildDefaultTrue,
"prebuilts/clang/host/linux-x86": Bp2BuildDefaultTrueRecursively,
"system/apex": Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures
+ "system/core/debuggerd": Bp2BuildDefaultTrue,
"system/core/diagnose_usb": Bp2BuildDefaultTrueRecursively,
"system/core/libasyncio": Bp2BuildDefaultTrue,
"system/core/libcrypto_utils": Bp2BuildDefaultTrueRecursively,
@@ -270,29 +342,84 @@
"system/core/libprocessgroup": Bp2BuildDefaultTrue,
"system/core/libprocessgroup/cgrouprc": Bp2BuildDefaultTrue,
"system/core/libprocessgroup/cgrouprc_format": Bp2BuildDefaultTrue,
+ "system/core/libsystem": Bp2BuildDefaultTrueRecursively,
+ "system/core/libutils": Bp2BuildDefaultTrueRecursively,
+ "system/core/libvndksupport": Bp2BuildDefaultTrueRecursively,
"system/core/property_service/libpropertyinfoparser": Bp2BuildDefaultTrueRecursively,
"system/libbase": Bp2BuildDefaultTrueRecursively,
+ "system/libprocinfo": Bp2BuildDefaultTrue,
"system/libziparchive": Bp2BuildDefaultTrueRecursively,
"system/logging/liblog": Bp2BuildDefaultTrueRecursively,
"system/sepolicy/apex": Bp2BuildDefaultTrueRecursively,
"system/timezone/apex": Bp2BuildDefaultTrueRecursively,
"system/timezone/output_data": Bp2BuildDefaultTrueRecursively,
+ "system/unwinding/libbacktrace": Bp2BuildDefaultTrueRecursively,
+ "system/unwinding/libunwindstack": Bp2BuildDefaultTrueRecursively,
+ "tools/apksig": Bp2BuildDefaultTrue,
+ "tools/platform-compat/java/android/compat": Bp2BuildDefaultTrueRecursively,
}
// Per-module denylist to always opt modules out of both bp2build and mixed builds.
bp2buildModuleDoNotConvertList = []string{
- "libprotobuf-cpp-full", "libprotobuf-cpp-lite", // Unsupported product&vendor suffix. b/204811222 and b/204810610.
+ "libnativehelper_compat_libc++", // Broken compile: implicit declaration of function 'strerror_r' is invalid in C99
+ "art_libdexfile_dex_instruction_list_header", // breaks libart_mterp.armng, header not found
- "libc_malloc_debug", // depends on libunwindstack, which depends on unsupported module art_cc_library_statics
+ "libandroid_runtime_lazy", // depends on unconverted modules: libbinder_headers
+ "libcmd", // depends on unconverted modules: libbinder
+
+ "chkcon", "sefcontext_compile", // depends on unconverted modules: libsepol
+
+ "libsepol", // TODO(b/207408632): Unsupported case of .l sources in cc library rules
+
+ "get_clang_version_test", // depends on unconverted module: get_clang_version
+
+ "libbinder", // TODO(b/188503688): Disabled for some archs,
+ "libactivitymanager_aidl", // TODO(b/207426160): Depends on activity_manager_procstate_aidl, which is an aidl filegroup.
+
+ "libnativehelper_lazy_mts_jni", // depends on unconverted modules: libgmock_ndk
+ "libnativehelper_mts_jni", // depends on unconverted modules: libgmock_ndk
+ "libnativetesthelper_jni", // depends on unconverted modules: libgtest_ndk_c++
+
+ "statslog-framework-java-gen", "statslog.cpp", "statslog.h", "statslog.rs", "statslog_header.rs", // depends on unconverted modules: stats-log-api-gen
+
+ "stats-log-api-gen", // depends on unconverted modules: libstats_proto_host, libprotobuf-cpp-full
+
+ "libstatslog", // depends on unconverted modules: statslog.cpp, statslog.h, ...
+
+ "libgmock_main_ndk", "libgmock_ndk", // depends on unconverted module: libgtest_ndk_c++
+
+ "cmd", // depends on unconverted module packagemanager_aidl-cpp, of unsupported type aidl_interface
+ "servicedispatcher", // depends on unconverted module android.debug_aidl, of unsupported type aidl_interface
+ "libutilscallstack", // depends on unconverted module libbacktrace
+ "libbacktrace", // depends on unconverted module libunwindstack
+ "libdebuggerd_handler", // depends on unconverted module libdebuggerd_handler_core
+ "libdebuggerd_handler_core", "libdebuggerd_handler_fallback", // depends on unconverted module libdebuggerd
+ "unwind_for_offline", // depends on unconverted module libunwindstack_utils
+ "libdebuggerd", // depends on unconverted modules libdexfile_support, libunwindstack, gwp_asan_crash_handler, libtombstone_proto, libprotobuf-cpp-lite
+ "libdexfile_static", // depends on libartpalette, libartbase, libdexfile, which are of unsupported type: art_cc_library.
+ "host_bionic_linker_asm", // depends on extract_linker, a go binary.
+ "host_bionic_linker_script", // depends on extract_linker, a go binary.
+
+ "pbtombstone", // depends on libprotobuf-cpp-lite, libtombstone_proto
+ "crash_dump", // depends on unconverted module libprotobuf-cpp-lite
+
+ "libunwindstack_local", "libunwindstack_utils", // depends on unconverted module libunwindstack
+ "libunwindstack", // depends on libdexfile_support, of unsupported module type art_cc_library_static
+ "libc_malloc_debug", // depends on unconverted module libunwindstack
"libbase_ndk", // http://b/186826477, fails to link libctscamera2_jni for device (required for CtsCameraTestCases)
+ "lib_linker_config_proto_lite", // contains .proto sources
+
"libprotobuf-python", // contains .proto sources
- "libprotobuf-internal-protos", // we don't handle path property for fileegroups
- "libprotobuf-internal-python-srcs", // we don't handle path property for fileegroups
+ "libprotobuf-internal-protos", // b/210751803, we don't handle path property for filegroups
+ "libprotobuf-internal-python-srcs", // b/210751803, we don't handle path property for filegroups
+ "libprotobuf-java-full", // b/210751803, we don't handle path property for filegroups
+ "libprotobuf-java-util-full", // b/210751803, we don't handle path property for filegroups
+ "conscrypt", // b/210751803, we don't handle path property for filegroups
"libseccomp_policy", // b/201094425: depends on func_to_syscall_nrs, which depends on py_binary, which is unsupported in mixed builds.
- "libfdtrack", // depends on libunwindstack, which depends on unsupported module art_cc_library_statics
+ "libfdtrack", // depends on unconverted module libunwindstack
"gwp_asan_crash_handler", // cc_library, ld.lld: error: undefined symbol: memset
@@ -303,10 +430,6 @@
"platform_tools_properties",
"build_tools_source_properties",
- "libminijail", // b/202491296: Uses unsupported c_std property.
- "minijail0", // depends on unconverted modules: libminijail
- "drop_privs", // depends on unconverted modules: libminijail
-
// Tests. Handle later.
"libbionic_tests_headers_posix", // http://b/186024507, cc_library_static, sched.h, time.h not found
"libjemalloc5_integrationtest",
@@ -316,36 +439,23 @@
// APEX support
"com.android.runtime", // http://b/194746715, apex, depends on 'libc_malloc_debug'
- "libadb_crypto", // Depends on libadb_protos
- "libadb_crypto_static", // Depends on libadb_protos_static
- "libadb_pairing_connection", // Depends on libadb_protos
- "libadb_pairing_connection_static", // Depends on libadb_protos_static
- "libadb_pairing_server", // Depends on libadb_protos
- "libadb_pairing_server_static", // Depends on libadb_protos_static
- "libadbd", // Depends on libadbd_core
- "libadbd_core", // Depends on libadb_protos
- "libadbd_services", // Depends on libadb_protos
-
- "libadb_protos_static", // b/200601772: Requires cc_library proto support
- "libadb_protos", // b/200601772: Requires cc_library proto support
- "libapp_processes_protos_lite", // b/200601772: Requires cc_library proto support
-
"libgtest_ndk_c++", // b/201816222: Requires sdk_version support.
"libgtest_main_ndk_c++", // b/201816222: Requires sdk_version support.
- "abb", // depends on unconverted modules: libadbd_core, libadbd_services, libcmd, libbinder, libutils, libselinux
- "adb", // depends on unconverted modules: bin2c_fastdeployagent, libadb_crypto, libadb_host, libadb_pairing_connection, libadb_protos, libandroidfw, libapp_processes_protos_full, libfastdeploy_host, libmdnssd, libopenscreen-discovery, libopenscreen-platform-impl, libusb, libutils, libziparchive, libzstd, AdbWinApi
- "adbd", // depends on unconverted modules: libadb_crypto, libadb_pairing_connection, libadb_protos, libadbd, libadbd_core, libapp_processes_protos_lite, libmdnssd, libzstd, libadbd_services, libcap, libminijail, libselinux
- "bionic_tests_zipalign", // depends on unconverted modules: libziparchive, libutils
- "linker", // depends on unconverted modules: liblinker_debuggerd_stub, libdebuggerd_handler_fallback, libziparchive, liblinker_main, liblinker_malloc
+ "abb", // depends on unconverted modules: libcmd, libbinder
+ "adb", // depends on unconverted modules: AdbWinApi, libadb_host, libandroidfw, libapp_processes_protos_full, libfastdeploy_host, libopenscreen-discovery, libopenscreen-platform-impl, libusb, bin2c_fastdeployagent, AdbWinUsbApi
+ "linker", // depends on unconverted modules: libdebuggerd_handler_fallback
"linker_reloc_bench_main", // depends on unconverted modules: liblinker_reloc_bench_*
- "sefcontext_compile", // depends on unconverted modules: libsepol
- "versioner", // depends on unconverted modules: libclang_cxx_host, libLLVM_host
+ "versioner", // depends on unconverted modules: libclang_cxx_host, libLLVM_host, of unsupported type llvm_host_prebuilt_library_shared
"linkerconfig", // http://b/202876379 has arch-variant static_executable
"mdnsd", // http://b/202876379 has arch-variant static_executable
"acvp_modulewrapper", // disabled for android x86/x86_64
+ "CarHTMLViewer", // depends on unconverted modules android.car-stubs, car-ui-lib
+
+ "libdexfile", // depends on unconverted modules: dexfile_operator_srcs, libartbase, libartpalette,
+ "libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette
}
// Per-module denylist of cc_library modules to only generate the static
@@ -360,8 +470,14 @@
"libbrotli", // http://b/198585397, ld.lld: error: bionic/libc/arch-arm64/generic/bionic/memmove.S:95:(.text+0x10): relocation R_AARCH64_CONDBR19 out of range: -1404176 is not in [-1048576, 1048575]; references __memcpy
"minijail_constants_json", // http://b/200899432, bazel-built cc_genrule does not work in mixed build when it is a dependency of another soong module.
- "cap_names.h", // TODO(b/204913827) runfiles need to be handled in mixed builds
- "libcap", // TODO(b/204913827) runfiles need to be handled in mixed builds
+ "cap_names.h", // TODO(b/204913827) runfiles need to be handled in mixed builds
+ "libcap", // TODO(b/204913827) runfiles need to be handled in mixed builds
+ "libprotobuf-cpp-full", "libprotobuf-cpp-lite", // Unsupported product&vendor suffix. b/204811222 and b/204810610.
+
+ // Depends on libprotobuf-cpp-*
+ "libadb_pairing_connection",
+ "libadb_pairing_connection_static",
+ "libadb_pairing_server", "libadb_pairing_server_static",
}
// Used for quicker lookups
@@ -434,32 +550,21 @@
if !ok {
return false
}
- return b.convertWithBp2build(ctx, module) || b.HasHandcraftedLabel()
+ return b.shouldConvertWithBp2build(ctx, module) || b.HasHandcraftedLabel()
}
-// ConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build.
-func (b *BazelModuleBase) ConvertWithBp2build(ctx BazelConversionContext) bool {
- return b.convertWithBp2build(ctx, ctx.Module())
+// ShouldConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build.
+func (b *BazelModuleBase) ShouldConvertWithBp2build(ctx BazelConversionContext) bool {
+ return b.shouldConvertWithBp2build(ctx, ctx.Module())
}
-func (b *BazelModuleBase) convertWithBp2build(ctx BazelConversionContext, module blueprint.Module) bool {
+func (b *BazelModuleBase) shouldConvertWithBp2build(ctx BazelConversionContext, module blueprint.Module) bool {
if bp2buildModuleDoNotConvert[module.Name()] {
return false
}
- // Ensure that the module type of this module has a bp2build converter. This
- // prevents mixed builds from using auto-converted modules just by matching
- // the package dir; it also has to have a bp2build mutator as well.
- if ctx.Config().bp2buildModuleTypeConfig[ctx.OtherModuleType(module)] == false {
- if b, ok := module.(Bazelable); ok && b.BaseModuleType() != "" {
- // For modules with custom types from soong_config_module_types,
- // check that their _base module type_ has a bp2build mutator.
- if ctx.Config().bp2buildModuleTypeConfig[b.BaseModuleType()] == false {
- return false
- }
- } else {
- return false
- }
+ if !b.bazelProps().Bazel_module.CanConvertToBazel {
+ return false
}
packagePath := ctx.OtherModuleDir(module)
@@ -533,3 +638,35 @@
}
return string(data[:]), nil
}
+
+func registerBp2buildConversionMutator(ctx RegisterMutatorsContext) {
+ ctx.TopDown("bp2build_conversion", convertWithBp2build).Parallel()
+}
+
+func convertWithBp2build(ctx TopDownMutatorContext) {
+ bModule, ok := ctx.Module().(Bazelable)
+ if !ok || !bModule.shouldConvertWithBp2build(ctx, ctx.Module()) {
+ return
+ }
+
+ bModule.ConvertWithBp2build(ctx)
+}
+
+// GetMainClassInManifest scans the manifest file specified in filepath and returns
+// the value of attribute Main-Class in the manifest file if it exists, or returns error.
+// WARNING: this is for bp2build converters of java_* modules only.
+func GetMainClassInManifest(c Config, filepath string) (string, error) {
+ file, err := c.fs.Open(filepath)
+ if err != nil {
+ return "", err
+ }
+ scanner := bufio.NewScanner(file)
+ for scanner.Scan() {
+ line := scanner.Text()
+ if strings.HasPrefix(line, "Main-Class:") {
+ return strings.TrimSpace(line[len("Main-Class:"):]), nil
+ }
+ }
+
+ return "", errors.New("Main-Class is not found.")
+}
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 729c73c..62e6156 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -279,6 +279,16 @@
return newPaths
}
+// Converts root-relative Paths to a list of bazel.Label relative to the module in ctx.
+func RootToModuleRelativePaths(ctx BazelConversionPathContext, paths Paths) []bazel.Label {
+ var newPaths []bazel.Label
+ for _, path := range PathsWithModuleSrcSubDir(ctx, paths, "") {
+ s := path.Rel()
+ newPaths = append(newPaths, bazel.Label{Label: s})
+ }
+ return newPaths
+}
+
// expandSrcsForBazel returns bazel.LabelList with paths rooted from the module's local source
// directory and Bazel target labels, excluding those included in the excludes argument (which
// should already be expanded to resolve references to Soong-modules). Valid elements of paths
@@ -328,12 +338,7 @@
// e.g. turn "math/*.c" in
// external/arm-optimized-routines to external/arm-optimized-routines/math/*.c
rootRelativeGlobPath := pathForModuleSrc(ctx, p).String()
- globbedPaths := GlobFiles(ctx, rootRelativeGlobPath, rootRelativeExpandedExcludes)
- globbedPaths = PathsWithModuleSrcSubDir(ctx, globbedPaths, "")
- for _, path := range globbedPaths {
- s := path.Rel()
- expandedPaths = append(expandedPaths, bazel.Label{Label: s})
- }
+ expandedPaths = RootToModuleRelativePaths(ctx, GlobFiles(ctx, rootRelativeGlobPath, rootRelativeExpandedExcludes))
} else {
if !InList(p, expandedExcludes) {
expandedPaths = append(expandedPaths, bazel.Label{Label: p})
diff --git a/android/config.go b/android/config.go
index 5ee28e7..5d90fd2 100644
--- a/android/config.go
+++ b/android/config.go
@@ -157,7 +157,6 @@
runningAsBp2Build bool
bp2buildPackageConfig Bp2BuildConfig
- bp2buildModuleTypeConfig map[string]bool
Bp2buildSoongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions
// If testAllowNonExistentPaths is true then PathForSource and PathForModuleSrc won't error
@@ -324,7 +323,7 @@
DeviceName: stringPtr("test_device"),
Platform_sdk_version: intPtr(30),
Platform_sdk_codename: stringPtr("S"),
- Platform_version_active_codenames: []string{"S"},
+ Platform_version_active_codenames: []string{"S", "Tiramisu"},
DeviceSystemSdkVersions: []string{"14", "15"},
Platform_systemsdk_versions: []string{"29", "30"},
AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
@@ -353,8 +352,6 @@
config.mockFileSystem(bp, fs)
- config.bp2buildModuleTypeConfig = map[string]bool{}
-
determineBuildOS(config)
return Config{config}
@@ -522,7 +519,6 @@
config.BazelContext, err = NewBazelContext(config)
config.bp2buildPackageConfig = bp2buildDefaultConfig
- config.bp2buildModuleTypeConfig = make(map[string]bool)
return Config{config}, err
}
@@ -765,6 +761,16 @@
return levels
}
+func (c *config) LatestPreviewApiLevel() ApiLevel {
+ level := NoneApiLevel
+ for _, l := range c.PreviewApiLevels() {
+ if l.GreaterThan(level) {
+ level = l
+ }
+ }
+ return level
+}
+
func (c *config) AllSupportedApiLevels() []ApiLevel {
var levels []ApiLevel
levels = append(levels, c.FinalApiLevels()...)
@@ -856,7 +862,7 @@
// Returns true if building apps that aren't bundled with the platform.
// UnbundledBuild() is always true when this is true.
func (c *config) UnbundledBuildApps() bool {
- return Bool(c.productVariables.Unbundled_build_apps)
+ return len(c.productVariables.Unbundled_build_apps) > 0
}
// Returns true if building image that aren't bundled with the platform.
@@ -882,8 +888,13 @@
return Bool(c.productVariables.Eng)
}
+// DevicePrimaryArchType returns the ArchType for the first configured device architecture, or
+// Common if there are no device architectures.
func (c *config) DevicePrimaryArchType() ArchType {
- return c.Targets[Android][0].Arch.ArchType
+ if androidTargets := c.Targets[Android]; len(androidTargets) > 0 {
+ return androidTargets[0].Arch.ArchType
+ }
+ return Common
}
func (c *config) SanitizeHost() []string {
@@ -1184,10 +1195,6 @@
return c.config.productVariables.DeviceKernelHeaders
}
-func (c *deviceConfig) SamplingPGO() bool {
- return Bool(c.config.productVariables.SamplingPGO)
-}
-
// JavaCoverageEnabledForPath returns whether Java code coverage is enabled for
// path. Coverage is enabled by default when the product variable
// JavaCoveragePaths is empty. If JavaCoveragePaths is not empty, coverage is
@@ -1470,6 +1477,10 @@
return c.PlatformSepolicyVersion()
}
+func (c *deviceConfig) BoardPlatVendorPolicy() []string {
+ return c.config.productVariables.BoardPlatVendorPolicy
+}
+
func (c *deviceConfig) BoardReqdMaskPolicy() []string {
return c.config.productVariables.BoardReqdMaskPolicy
}
diff --git a/android/deapexer.go b/android/deapexer.go
index bed6574..265f531 100644
--- a/android/deapexer.go
+++ b/android/deapexer.go
@@ -143,12 +143,16 @@
}
// FindDeapexerProviderForModule searches through the direct dependencies of the current context
-// module for a DeapexerTag dependency and returns its DeapexerInfo. If there is an error then it is
-// reported with ctx.ModuleErrorf and nil is returned.
+// module for a DeapexerTag dependency and returns its DeapexerInfo. If a single nonambiguous
+// deapexer module isn't found then errors are reported with ctx.ModuleErrorf and nil is returned.
func FindDeapexerProviderForModule(ctx ModuleContext) *DeapexerInfo {
var di *DeapexerInfo
ctx.VisitDirectDepsWithTag(DeapexerTag, func(m Module) {
p := ctx.OtherModuleProvider(m, DeapexerProvider).(DeapexerInfo)
+ if di != nil {
+ ctx.ModuleErrorf("Multiple installable prebuilt APEXes provide ambiguous deapexers: %s and %s",
+ di.ApexModuleName(), p.ApexModuleName())
+ }
di = &p
})
if di != nil {
diff --git a/android/defaults.go b/android/defaults.go
index 9046002..7b3d38c 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -89,10 +89,10 @@
var _ Defaultable = (*DefaultableModuleBase)(nil)
func InitDefaultableModule(module DefaultableModule) {
- if module.(Module).base().module == nil {
+ if module.base().module == nil {
panic("InitAndroidModule must be called before InitDefaultableModule")
}
- module.setProperties(module.(Module).GetProperties(), module.(Module).base().variableProperties)
+ module.setProperties(module.GetProperties(), module.base().variableProperties)
module.AddProperties(module.defaults())
@@ -173,6 +173,10 @@
func (d *DefaultsModuleBase) GenerateAndroidBuildActions(ctx ModuleContext) {
}
+// ConvertWithBp2build to fulfill Bazelable interface; however, at this time defaults module are
+// *NOT* converted with bp2build
+func (defaultable *DefaultsModuleBase) ConvertWithBp2build(ctx TopDownMutatorContext) {}
+
func InitDefaultsModule(module DefaultsModule) {
commonProperties := &commonProperties{}
diff --git a/android/filegroup.go b/android/filegroup.go
index a79374d..c932ffa 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -22,7 +22,6 @@
func init() {
RegisterModuleType("filegroup", FileGroupFactory)
- RegisterBp2BuildMutator("filegroup", FilegroupBp2Build)
}
var PrepareForTestWithFilegroup = FixtureRegisterWithContext(func(ctx RegistrationContext) {
@@ -34,12 +33,8 @@
Srcs bazel.LabelListAttribute
}
-func FilegroupBp2Build(ctx TopDownMutatorContext) {
- fg, ok := ctx.Module().(*fileGroup)
- if !ok || !fg.ConvertWithBp2build(ctx) {
- return
- }
-
+// ConvertWithBp2build performs bp2build conversion of filegroup
+func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) {
srcs := bazel.MakeLabelListAttribute(
BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs))
diff --git a/android/license_metadata.go b/android/license_metadata.go
new file mode 100644
index 0000000..3bc53d6
--- /dev/null
+++ b/android/license_metadata.go
@@ -0,0 +1,231 @@
+// 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"
+ "sort"
+ "strings"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+var (
+ _ = pctx.HostBinToolVariable("licenseMetadataCmd", "build_license_metadata")
+
+ licenseMetadataRule = pctx.AndroidStaticRule("licenseMetadataRule", blueprint.RuleParams{
+ Command: "${licenseMetadataCmd} -o $out @${out}.rsp",
+ CommandDeps: []string{"${licenseMetadataCmd}"},
+ Rspfile: "${out}.rsp",
+ RspfileContent: "${args}",
+ }, "args")
+)
+
+func buildLicenseMetadata(ctx ModuleContext) {
+ base := ctx.Module().base()
+
+ if !base.Enabled() {
+ return
+ }
+
+ if exemptFromRequiredApplicableLicensesProperty(ctx.Module()) {
+ return
+ }
+
+ var allDepMetadataFiles Paths
+ var allDepMetadataArgs []string
+ var allDepOutputFiles Paths
+
+ ctx.VisitDirectDepsBlueprint(func(bpdep blueprint.Module) {
+ dep, _ := bpdep.(Module)
+ if dep == nil {
+ return
+ }
+ if !dep.Enabled() {
+ return
+ }
+
+ if ctx.OtherModuleHasProvider(dep, LicenseMetadataProvider) {
+ info := ctx.OtherModuleProvider(dep, LicenseMetadataProvider).(*LicenseMetadataInfo)
+ allDepMetadataFiles = append(allDepMetadataFiles, info.LicenseMetadataPath)
+
+ depAnnotations := licenseAnnotationsFromTag(ctx.OtherModuleDependencyTag(dep))
+
+ allDepMetadataArgs = append(allDepMetadataArgs, info.LicenseMetadataPath.String()+depAnnotations)
+
+ if depInstallFiles := dep.base().installFiles; len(depInstallFiles) > 0 {
+ allDepOutputFiles = append(allDepOutputFiles, depInstallFiles.Paths()...)
+ } else if depOutputFiles, err := outputFilesForModule(ctx, dep, ""); err == nil {
+ depOutputFiles = PathsIfNonNil(depOutputFiles...)
+ allDepOutputFiles = append(allDepOutputFiles, depOutputFiles...)
+ }
+ }
+ })
+
+ allDepMetadataFiles = SortedUniquePaths(allDepMetadataFiles)
+ sort.Strings(allDepMetadataArgs)
+ allDepOutputFiles = SortedUniquePaths(allDepOutputFiles)
+
+ var orderOnlyDeps Paths
+ var args []string
+
+ if t := ctx.ModuleType(); t != "" {
+ args = append(args,
+ "-mt "+proptools.NinjaAndShellEscape(t))
+ }
+
+ args = append(args,
+ "-r "+proptools.NinjaAndShellEscape(ctx.ModuleDir()),
+ "-mc UNKNOWN")
+
+ if p := base.commonProperties.Effective_package_name; p != nil {
+ args = append(args,
+ "-p "+proptools.NinjaAndShellEscape(*p))
+ }
+
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_kinds), "-k "))
+
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_conditions), "-c "))
+
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_text.Strings()), "-n "))
+
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepMetadataArgs), "-d "))
+ orderOnlyDeps = append(orderOnlyDeps, allDepMetadataFiles...)
+
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepOutputFiles.Strings()), "-s "))
+
+ // Install map
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.licenseInstallMap), "-m "))
+
+ // Built files
+ var outputFiles Paths
+ if outputFileProducer, ok := ctx.Module().(OutputFileProducer); ok {
+ outputFiles, _ = outputFileProducer.OutputFiles("")
+ outputFiles = PathsIfNonNil(outputFiles...)
+ }
+
+ if len(outputFiles) > 0 {
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(outputFiles.Strings()), "-t "))
+ } else {
+ args = append(args, fmt.Sprintf("-t //%s:%s", ctx.ModuleDir(), ctx.ModuleName()))
+ }
+
+ // Installed files
+ args = append(args,
+ JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.installFiles.Strings()), "-i "))
+
+ isContainer := isContainerFromFileExtensions(base.installFiles, outputFiles)
+ if isContainer {
+ args = append(args, "--is_container")
+ }
+
+ licenseMetadataFile := PathForModuleOut(ctx, "meta_lic")
+
+ ctx.Build(pctx, BuildParams{
+ Rule: licenseMetadataRule,
+ Output: licenseMetadataFile,
+ OrderOnly: orderOnlyDeps,
+ Description: "license metadata",
+ Args: map[string]string{
+ "args": strings.Join(args, " "),
+ },
+ })
+
+ ctx.SetProvider(LicenseMetadataProvider, &LicenseMetadataInfo{
+ LicenseMetadataPath: licenseMetadataFile,
+ })
+}
+
+func isContainerFromFileExtensions(installPaths InstallPaths, builtPaths Paths) bool {
+ var paths Paths
+ if len(installPaths) > 0 {
+ paths = installPaths.Paths()
+ } else {
+ paths = builtPaths
+ }
+
+ for _, path := range paths {
+ switch path.Ext() {
+ case ".zip", ".tar", ".tgz", ".tar.gz", ".img", ".srcszip", ".apex":
+ return true
+ }
+ }
+
+ return false
+}
+
+// LicenseMetadataProvider is used to propagate license metadata paths between modules.
+var LicenseMetadataProvider = blueprint.NewProvider(&LicenseMetadataInfo{})
+
+// LicenseMetadataInfo stores the license metadata path for a module.
+type LicenseMetadataInfo struct {
+ LicenseMetadataPath Path
+}
+
+// licenseAnnotationsFromTag returns the LicenseAnnotations for a tag (if any) converted into
+// a string, or an empty string if there are none.
+func licenseAnnotationsFromTag(tag blueprint.DependencyTag) string {
+ if annoTag, ok := tag.(LicenseAnnotationsDependencyTag); ok {
+ annos := annoTag.LicenseAnnotations()
+ if len(annos) > 0 {
+ annoStrings := make([]string, len(annos))
+ for i, s := range annos {
+ annoStrings[i] = string(s)
+ }
+ return ":" + strings.Join(annoStrings, ",")
+ }
+ }
+ return ""
+}
+
+// LicenseAnnotationsDependencyTag is implemented by dependency tags in order to provide a
+// list of license dependency annotations.
+type LicenseAnnotationsDependencyTag interface {
+ LicenseAnnotations() []LicenseAnnotation
+}
+
+// LicenseAnnotation is an enum of annotations that can be applied to dependencies for propagating
+// license information.
+type LicenseAnnotation string
+
+const (
+ // LicenseAnnotationSharedDependency should be returned by LicenseAnnotations implementations
+ // of dependency tags when the usage of the dependency is dynamic, for example a shared library
+ // linkage for native modules or as a classpath library for java modules.
+ LicenseAnnotationSharedDependency LicenseAnnotation = "dynamic"
+
+ // LicenseAnnotationToolchain should be returned by LicenseAnnotations implementations of
+ // dependency tags when the dependency is used as a toolchain.
+ //
+ // Dependency tags that need to always return LicenseAnnotationToolchain
+ // can embed LicenseAnnotationToolchainDependencyTag to implement LicenseAnnotations.
+ LicenseAnnotationToolchain LicenseAnnotation = "toolchain"
+)
+
+// LicenseAnnotationToolchainDependencyTag can be embedded in a dependency tag to implement
+// LicenseAnnotations that always returns LicenseAnnotationToolchain.
+type LicenseAnnotationToolchainDependencyTag struct{}
+
+func (LicenseAnnotationToolchainDependencyTag) LicenseAnnotations() []LicenseAnnotation {
+ return []LicenseAnnotation{LicenseAnnotationToolchain}
+}
diff --git a/android/module.go b/android/module.go
index 4a388b5..189781a 100644
--- a/android/module.go
+++ b/android/module.go
@@ -419,7 +419,6 @@
PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec
CheckbuildFile(srcPath Path)
- TidyFile(srcPath WritablePath)
InstallInData() bool
InstallInTestcases() bool
@@ -1200,7 +1199,6 @@
installFiles InstallPaths
installFilesDepSet *installPathsDepSet
checkbuildFiles Paths
- tidyFiles WritablePaths
packagingSpecs []PackagingSpec
packagingSpecsDepSet *packagingSpecsDepSet
noticeFiles Paths
@@ -1216,7 +1214,6 @@
// Only set on the final variant of each module
installTarget WritablePath
checkbuildTarget WritablePath
- tidyTarget WritablePath
blueprintDir string
hooks hooks
@@ -1230,6 +1227,10 @@
initRcPaths Paths
vintfFragmentsPaths Paths
+
+ // set of dependency module:location mappings used to populate the license metadata for
+ // apex containers.
+ licenseInstallMap []string
}
// A struct containing all relevant information about a Bazel target converted via bp2build.
@@ -1289,7 +1290,7 @@
// GetUnconvertedBp2buildDeps returns the list of module names of this module's direct dependencies that
// were not converted to Bazel.
func (m *ModuleBase) GetUnconvertedBp2buildDeps() []string {
- return m.commonProperties.UnconvertedBp2buildDeps
+ return FirstUniqueStrings(m.commonProperties.UnconvertedBp2buildDeps)
}
func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
@@ -1300,6 +1301,8 @@
func (m *ModuleBase) DepsMutator(BottomUpMutatorContext) {}
+// AddProperties "registers" the provided props
+// each value in props MUST be a pointer to a struct
func (m *ModuleBase) AddProperties(props ...interface{}) {
m.registerProps = append(m.registerProps, props...)
}
@@ -1702,7 +1705,7 @@
}
func (m *ModuleBase) InstallBypassMake() bool {
- return false
+ return true
}
func (m *ModuleBase) InstallForceOS() (*OsType, *ArchType) {
@@ -1774,20 +1777,24 @@
return append(Paths{}, m.vintfFragmentsPaths...)
}
+// SetLicenseInstallMap stores the set of dependency module:location mappings for files in an
+// apex container for use when generation the license metadata file.
+func (m *ModuleBase) SetLicenseInstallMap(installMap []string) {
+ m.licenseInstallMap = append(m.licenseInstallMap, installMap...)
+}
+
func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
var allInstalledFiles InstallPaths
var allCheckbuildFiles Paths
- var allTidyFiles WritablePaths
ctx.VisitAllModuleVariants(func(module Module) {
a := module.base()
allInstalledFiles = append(allInstalledFiles, a.installFiles...)
- // A module's -{checkbuild,tidy} phony targets should
+ // A module's -checkbuild phony targets should
// not be created if the module is not exported to make.
// Those could depend on the build target and fail to compile
// for the current build target.
if !ctx.Config().KatiEnabled() || !shouldSkipAndroidMkProcessing(a) {
allCheckbuildFiles = append(allCheckbuildFiles, a.checkbuildFiles...)
- allTidyFiles = append(allTidyFiles, a.tidyFiles...)
}
})
@@ -1812,13 +1819,6 @@
deps = append(deps, m.checkbuildTarget)
}
- if len(allTidyFiles) > 0 {
- name := namespacePrefix + ctx.ModuleName() + "-tidy"
- ctx.Phony(name, allTidyFiles.Paths()...)
- m.tidyTarget = PathForPhony(ctx, name)
- deps = append(deps, m.tidyTarget)
- }
-
if len(deps) > 0 {
suffix := ""
if ctx.Config().KatiEnabled() {
@@ -2027,7 +2027,6 @@
m.installFiles = append(m.installFiles, ctx.installFiles...)
m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
- m.tidyFiles = append(m.tidyFiles, ctx.tidyFiles...)
m.packagingSpecs = append(m.packagingSpecs, ctx.packagingSpecs...)
m.katiInstalls = append(m.katiInstalls, ctx.katiInstalls...)
m.katiSymlinks = append(m.katiSymlinks, ctx.katiSymlinks...)
@@ -2049,6 +2048,8 @@
m.installFilesDepSet = newInstallPathsDepSet(m.installFiles, dependencyInstallFiles)
m.packagingSpecsDepSet = newPackagingSpecsDepSet(m.packagingSpecs, dependencyPackagingSpecs)
+ buildLicenseMetadata(ctx)
+
m.buildParams = ctx.buildParams
m.ruleParams = ctx.ruleParams
m.variables = ctx.variables
@@ -2225,7 +2226,6 @@
packagingSpecs []PackagingSpec
installFiles InstallPaths
checkbuildFiles Paths
- tidyFiles WritablePaths
module Module
phonies map[string]Paths
@@ -3063,10 +3063,6 @@
m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
}
-func (m *moduleContext) TidyFile(srcPath WritablePath) {
- m.tidyFiles = append(m.tidyFiles, srcPath)
-}
-
func (m *moduleContext) blueprintModuleContext() blueprint.ModuleContext {
return m.bp
}
@@ -3325,9 +3321,10 @@
type buildTargetSingleton struct{}
-func addAncestors(ctx SingletonContext, dirMap map[string]Paths, mmName func(string) string) []string {
+func AddAncestors(ctx SingletonContext, dirMap map[string]Paths, mmName func(string) string) ([]string, []string) {
// Ensure ancestor directories are in dirMap
// Make directories build their direct subdirectories
+ // Returns a slice of all directories and a slice of top-level directories.
dirs := SortedStringKeys(dirMap)
for _, dir := range dirs {
dir := parentDir(dir)
@@ -3340,34 +3337,31 @@
}
}
dirs = SortedStringKeys(dirMap)
+ var topDirs []string
for _, dir := range dirs {
p := parentDir(dir)
if p != "." && p != "/" {
dirMap[p] = append(dirMap[p], PathForPhony(ctx, mmName(dir)))
+ } else if dir != "." && dir != "/" && dir != "" {
+ topDirs = append(topDirs, dir)
}
}
- return SortedStringKeys(dirMap)
+ return SortedStringKeys(dirMap), topDirs
}
func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) {
var checkbuildDeps Paths
- var tidyDeps Paths
mmTarget := func(dir string) string {
return "MODULES-IN-" + strings.Replace(filepath.Clean(dir), "/", "-", -1)
}
- mmTidyTarget := func(dir string) string {
- return "tidy-" + strings.Replace(filepath.Clean(dir), "/", "-", -1)
- }
modulesInDir := make(map[string]Paths)
- tidyModulesInDir := make(map[string]Paths)
ctx.VisitAllModules(func(module Module) {
blueprintDir := module.base().blueprintDir
installTarget := module.base().installTarget
checkbuildTarget := module.base().checkbuildTarget
- tidyTarget := module.base().tidyTarget
if checkbuildTarget != nil {
checkbuildDeps = append(checkbuildDeps, checkbuildTarget)
@@ -3377,16 +3371,6 @@
if installTarget != nil {
modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], installTarget)
}
-
- if tidyTarget != nil {
- tidyDeps = append(tidyDeps, tidyTarget)
- // tidyTarget is in modulesInDir so it will be built with "mm".
- modulesInDir[blueprintDir] = append(modulesInDir[blueprintDir], tidyTarget)
- // tidyModulesInDir contains tidyTarget but not checkbuildTarget
- // or installTarget, so tidy targets in a directory can be built
- // without other checkbuild or install targets.
- tidyModulesInDir[blueprintDir] = append(tidyModulesInDir[blueprintDir], tidyTarget)
- }
})
suffix := ""
@@ -3397,24 +3381,12 @@
// Create a top-level checkbuild target that depends on all modules
ctx.Phony("checkbuild"+suffix, checkbuildDeps...)
- // Create a top-level tidy target that depends on all modules
- ctx.Phony("tidy"+suffix, tidyDeps...)
-
- dirs := addAncestors(ctx, tidyModulesInDir, mmTidyTarget)
-
- // Kati does not generate tidy-* phony targets yet.
- // Create a tidy-<directory> target that depends on all subdirectories
- // and modules in the directory.
- for _, dir := range dirs {
- ctx.Phony(mmTidyTarget(dir), tidyModulesInDir[dir]...)
- }
-
// Make will generate the MODULES-IN-* targets
if ctx.Config().KatiEnabled() {
return
}
- dirs = addAncestors(ctx, modulesInDir, mmTarget)
+ dirs, _ := AddAncestors(ctx, modulesInDir, mmTarget)
// Create a MODULES-IN-<directory> target that depends on all modules in a directory, and
// depends on the MODULES-IN-* targets of all of its subdirectories that contain Android.bp
diff --git a/android/mutator.go b/android/mutator.go
index 461cb17..dbd8c04 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -16,7 +16,6 @@
import (
"reflect"
- "sync"
"android/soong/bazel"
@@ -34,12 +33,12 @@
// continue on to GenerateAndroidBuildActions
// RegisterMutatorsForBazelConversion is a alternate registration pipeline for bp2build. Exported for testing.
-func RegisterMutatorsForBazelConversion(ctx *Context, preArchMutators, bp2buildMutators []RegisterMutatorFunc) {
+func RegisterMutatorsForBazelConversion(ctx *Context, preArchMutators []RegisterMutatorFunc) {
mctx := ®isterMutatorsContext{
bazelConversionMode: true,
}
- bp2buildPreArchMutators = append([]RegisterMutatorFunc{
+ bp2buildMutators := append([]RegisterMutatorFunc{
RegisterNamespaceMutator,
RegisterDefaultsPreArchMutators,
// TODO(b/165114590): this is required to resolve deps that are only prebuilts, but we should
@@ -47,10 +46,7 @@
RegisterPrebuiltsPreArchMutators,
},
preArchMutators...)
-
- for _, f := range bp2buildPreArchMutators {
- f(mctx)
- }
+ bp2buildMutators = append(bp2buildMutators, registerBp2buildConversionMutator)
// Register bp2build mutators
for _, f := range bp2buildMutators {
@@ -216,24 +212,12 @@
}
var bp2buildPreArchMutators = []RegisterMutatorFunc{}
-var bp2buildMutators = map[string]RegisterMutatorFunc{}
-// See http://b/192523357
-var bp2buildLock sync.Mutex
+// A minimal context for Bp2build conversion
+type Bp2buildMutatorContext interface {
+ BazelConversionPathContext
-// RegisterBp2BuildMutator registers specially crafted mutators for
-// converting Blueprint/Android modules into special modules that can
-// be code-generated into Bazel BUILD targets.
-//
-// TODO(b/178068862): bring this into TestContext.
-func RegisterBp2BuildMutator(moduleType string, m func(TopDownMutatorContext)) {
- f := func(ctx RegisterMutatorsContext) {
- ctx.TopDown(moduleType, m)
- }
- // Use a lock to avoid a concurrent map write if RegisterBp2BuildMutator is called in parallel
- bp2buildLock.Lock()
- defer bp2buildLock.Unlock()
- bp2buildMutators[moduleType] = f
+ CreateBazelTargetModule(bazel.BazelTargetModuleProperties, CommonAttributes, interface{})
}
// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
@@ -529,28 +513,6 @@
mod.base().addBp2buildInfo(info)
}
-func (t *topDownMutatorContext) appendPrependHelper(props []interface{},
- extendFn func([]interface{}, interface{}, proptools.ExtendPropertyFilterFunc) error) {
- for _, p := range props {
- err := extendFn(t.Module().base().customizableProperties, p, nil)
- if err != nil {
- if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
- t.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
- } else {
- panic(err)
- }
- }
- }
-}
-
-func (t *topDownMutatorContext) AppendProperties(props ...interface{}) {
- t.appendPrependHelper(props, proptools.AppendMatchingProperties)
-}
-
-func (t *topDownMutatorContext) PrependProperties(props ...interface{}) {
- t.appendPrependHelper(props, proptools.PrependMatchingProperties)
-}
-
// android.topDownMutatorContext either has to embed blueprint.TopDownMutatorContext, in which case every method that
// has an overridden version in android.BaseModuleContext has to be manually forwarded to BaseModuleContext to avoid
// ambiguous method errors, or it has to store a blueprint.TopDownMutatorContext non-embedded, in which case every
diff --git a/android/neverallow.go b/android/neverallow.go
index b36bf04..0348619 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -252,7 +252,7 @@
continue
}
- if !n.appliesToProperties(properties) {
+ if !n.appliesToProperties(ctx, properties) {
continue
}
@@ -272,8 +272,12 @@
}
}
+type ValueMatcherContext interface {
+ Config() Config
+}
+
type ValueMatcher interface {
- Test(string) bool
+ Test(ValueMatcherContext, string) bool
String() string
}
@@ -281,7 +285,7 @@
expected string
}
-func (m *equalMatcher) Test(value string) bool {
+func (m *equalMatcher) Test(ctx ValueMatcherContext, value string) bool {
return m.expected == value
}
@@ -292,7 +296,7 @@
type anyMatcher struct {
}
-func (m *anyMatcher) Test(value string) bool {
+func (m *anyMatcher) Test(ctx ValueMatcherContext, value string) bool {
return true
}
@@ -306,7 +310,7 @@
prefix string
}
-func (m *startsWithMatcher) Test(value string) bool {
+func (m *startsWithMatcher) Test(ctx ValueMatcherContext, value string) bool {
return strings.HasPrefix(value, m.prefix)
}
@@ -318,7 +322,7 @@
re *regexp.Regexp
}
-func (m *regexMatcher) Test(value string) bool {
+func (m *regexMatcher) Test(ctx ValueMatcherContext, value string) bool {
return m.re.MatchString(value)
}
@@ -330,7 +334,7 @@
allowed []string
}
-func (m *notInListMatcher) Test(value string) bool {
+func (m *notInListMatcher) Test(ctx ValueMatcherContext, value string) bool {
return !InList(value, m.allowed)
}
@@ -340,7 +344,7 @@
type isSetMatcher struct{}
-func (m *isSetMatcher) Test(value string) bool {
+func (m *isSetMatcher) Test(ctx ValueMatcherContext, value string) bool {
return value != ""
}
@@ -350,6 +354,19 @@
var isSetMatcherInstance = &isSetMatcher{}
+type sdkVersionMatcher struct {
+ condition func(ctx ValueMatcherContext, spec SdkSpec) bool
+ description string
+}
+
+func (m *sdkVersionMatcher) Test(ctx ValueMatcherContext, value string) bool {
+ return m.condition(ctx, SdkSpecFromWithConfig(ctx.Config(), value))
+}
+
+func (m *sdkVersionMatcher) String() string {
+ return ".sdk-version(" + m.description + ")"
+}
+
type ruleProperty struct {
fields []string // e.x.: Vndk.Enabled
matcher ValueMatcher
@@ -563,9 +580,10 @@
return (len(r.moduleTypes) == 0 || InList(moduleType, r.moduleTypes)) && !InList(moduleType, r.unlessModuleTypes)
}
-func (r *rule) appliesToProperties(properties []interface{}) bool {
- includeProps := hasAllProperties(properties, r.props)
- excludeProps := hasAnyProperty(properties, r.unlessProps)
+func (r *rule) appliesToProperties(ctx ValueMatcherContext,
+ properties []interface{}) bool {
+ includeProps := hasAllProperties(ctx, properties, r.props)
+ excludeProps := hasAnyProperty(ctx, properties, r.unlessProps)
return includeProps && !excludeProps
}
@@ -585,6 +603,16 @@
return ¬InListMatcher{allowed}
}
+func LessThanSdkVersion(sdk string) ValueMatcher {
+ return &sdkVersionMatcher{
+ condition: func(ctx ValueMatcherContext, spec SdkSpec) bool {
+ return spec.ApiLevel.LessThan(
+ SdkSpecFromWithConfig(ctx.Config(), sdk).ApiLevel)
+ },
+ description: "lessThan=" + sdk,
+ }
+}
+
// assorted utils
func cleanPaths(paths []string) []string {
@@ -603,25 +631,28 @@
return names
}
-func hasAnyProperty(properties []interface{}, props []ruleProperty) bool {
+func hasAnyProperty(ctx ValueMatcherContext, properties []interface{},
+ props []ruleProperty) bool {
for _, v := range props {
- if hasProperty(properties, v) {
+ if hasProperty(ctx, properties, v) {
return true
}
}
return false
}
-func hasAllProperties(properties []interface{}, props []ruleProperty) bool {
+func hasAllProperties(ctx ValueMatcherContext, properties []interface{},
+ props []ruleProperty) bool {
for _, v := range props {
- if !hasProperty(properties, v) {
+ if !hasProperty(ctx, properties, v) {
return false
}
}
return true
}
-func hasProperty(properties []interface{}, prop ruleProperty) bool {
+func hasProperty(ctx ValueMatcherContext, properties []interface{},
+ prop ruleProperty) bool {
for _, propertyStruct := range properties {
propertiesValue := reflect.ValueOf(propertyStruct).Elem()
for _, v := range prop.fields {
@@ -635,7 +666,7 @@
}
check := func(value string) bool {
- return prop.matcher.Test(value)
+ return prop.matcher.Test(ctx, value)
}
if matchValue(propertiesValue, check) {
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index edda244..18a8705 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -296,6 +296,48 @@
"Only boot images and seapp contexts may be imported as a makefile goal.",
},
},
+ {
+ name: "min_sdk too low",
+ fs: map[string][]byte{
+ "Android.bp": []byte(`
+ java_library {
+ name: "min_sdk_too_low",
+ min_sdk_version: "30",
+ }`),
+ },
+ rules: []Rule{
+ NeverAllow().WithMatcher("min_sdk_version", LessThanSdkVersion("31")),
+ },
+ expectedErrors: []string{
+ "module \"min_sdk_too_low\": violates neverallow",
+ },
+ },
+ {
+ name: "min_sdk high enough",
+ fs: map[string][]byte{
+ "Android.bp": []byte(`
+ java_library {
+ name: "min_sdk_high_enough",
+ min_sdk_version: "31",
+ }`),
+ },
+ rules: []Rule{
+ NeverAllow().WithMatcher("min_sdk_version", LessThanSdkVersion("31")),
+ },
+ },
+ {
+ name: "current min_sdk high enough",
+ fs: map[string][]byte{
+ "Android.bp": []byte(`
+ java_library {
+ name: "current_min_sdk_high_enough",
+ min_sdk_version: "current",
+ }`),
+ },
+ rules: []Rule{
+ NeverAllow().WithMatcher("min_sdk_version", LessThanSdkVersion("31")),
+ },
+ },
}
var prepareForNeverAllowTest = GroupFixturePreparers(
@@ -379,9 +421,10 @@
}
type mockJavaLibraryProperties struct {
- Libs []string
- Sdk_version *string
- Uncompress_dex *bool
+ Libs []string
+ Min_sdk_version *string
+ Sdk_version *string
+ Uncompress_dex *bool
}
type mockJavaLibraryModule struct {
diff --git a/android/package_ctx.go b/android/package_ctx.go
index c19debb..f354db8 100644
--- a/android/package_ctx.go
+++ b/android/package_ctx.go
@@ -19,6 +19,7 @@
"strings"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
"android/soong/remoteexec"
)
@@ -173,7 +174,7 @@
// package-scoped variable's initialization.
func (p PackageContext) HostBinToolVariable(name, path string) blueprint.Variable {
return p.VariableFunc(name, func(ctx PackageVarContext) string {
- return ctx.Config().HostToolPath(ctx, path).String()
+ return proptools.NinjaAndShellEscape(ctx.Config().HostToolPath(ctx, path).String())
})
}
@@ -183,7 +184,7 @@
// package-scoped variable's initialization.
func (p PackageContext) HostJNIToolVariable(name, path string) blueprint.Variable {
return p.VariableFunc(name, func(ctx PackageVarContext) string {
- return ctx.Config().HostJNIToolPath(ctx, path).String()
+ return proptools.NinjaAndShellEscape(ctx.Config().HostJNIToolPath(ctx, path).String())
})
}
@@ -193,7 +194,7 @@
// part of a package-scoped variable's initialization.
func (p PackageContext) HostJavaToolVariable(name, path string) blueprint.Variable {
return p.VariableFunc(name, func(ctx PackageVarContext) string {
- return ctx.Config().HostJavaToolPath(ctx, path).String()
+ return proptools.NinjaAndShellEscape(ctx.Config().HostJavaToolPath(ctx, path).String())
})
}
diff --git a/android/prebuilt.go b/android/prebuilt.go
index e189892..b0a4f43 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -97,7 +97,10 @@
type Prebuilt struct {
properties PrebuiltProperties
- srcsSupplier PrebuiltSrcsSupplier
+ // nil if the prebuilt has no srcs property at all. See InitPrebuiltModuleWithoutSrcs.
+ srcsSupplier PrebuiltSrcsSupplier
+
+ // "-" if the prebuilt has no srcs property at all. See InitPrebuiltModuleWithoutSrcs.
srcsPropertyName string
}
@@ -177,6 +180,23 @@
// Return the src value or nil if it is not available.
type PrebuiltSrcsSupplier func(ctx BaseModuleContext, prebuilt Module) []string
+func initPrebuiltModuleCommon(module PrebuiltInterface) *Prebuilt {
+ p := module.Prebuilt()
+ module.AddProperties(&p.properties)
+ module.base().customizableProperties = module.GetProperties()
+ return p
+}
+
+// Initialize the module as a prebuilt module that has no dedicated property that lists its
+// sources. SingleSourcePathFromSupplier should not be called for this module.
+//
+// This is the case e.g. for header modules, which provides the headers in source form
+// regardless whether they are prebuilt or not.
+func InitPrebuiltModuleWithoutSrcs(module PrebuiltInterface) {
+ p := initPrebuiltModuleCommon(module)
+ p.srcsPropertyName = "-"
+}
+
// Initialize the module as a prebuilt module that uses the provided supplier to access the
// prebuilt sources of the module.
//
@@ -190,10 +210,6 @@
// The provided property name is used to provide helpful error messages in the event that
// a problem arises, e.g. calling SingleSourcePath() when more than one source is provided.
func InitPrebuiltModuleWithSrcSupplier(module PrebuiltInterface, srcsSupplier PrebuiltSrcsSupplier, srcsPropertyName string) {
- p := module.Prebuilt()
- module.AddProperties(&p.properties)
- module.base().customizableProperties = module.GetProperties()
-
if srcsSupplier == nil {
panic(fmt.Errorf("srcsSupplier must not be nil"))
}
@@ -201,6 +217,7 @@
panic(fmt.Errorf("srcsPropertyName must not be empty"))
}
+ p := initPrebuiltModuleCommon(module)
p.srcsSupplier = srcsSupplier
p.srcsPropertyName = srcsPropertyName
}
@@ -336,7 +353,7 @@
func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) {
m := ctx.Module()
if p := GetEmbeddedPrebuilt(m); p != nil {
- if p.srcsSupplier == nil {
+ if p.srcsSupplier == nil && p.srcsPropertyName == "" {
panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it"))
}
if !p.properties.SourceExists {
diff --git a/android/proto.go b/android/proto.go
index 0be7893..64d4d05 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -15,12 +15,17 @@
package android
import (
+ "android/soong/bazel"
"strings"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
+const (
+ canonicalPathFromRootDefault = true
+)
+
// TODO(ccross): protos are often used to communicate between multiple modules. If the only
// way to convert a proto to source is to reference it as a source file, and external modules cannot
// reference source files in other modules, then every module that owns a proto file will need to
@@ -90,7 +95,7 @@
Flags: flags,
Deps: deps,
OutTypeFlag: protoOutFlag,
- CanonicalPathFromRoot: proptools.BoolDefault(p.Proto.Canonical_path_from_root, true),
+ CanonicalPathFromRoot: proptools.BoolDefault(p.Proto.Canonical_path_from_root, canonicalPathFromRootDefault),
Dir: PathForModuleGen(ctx, "proto"),
SubDir: PathForModuleGen(ctx, "proto", ctx.ModuleDir()),
}
@@ -146,3 +151,57 @@
rule.Command().
BuiltTool("dep_fixer").Flag(depFile.String())
}
+
+// Bp2buildProtoInfo contains information necessary to pass on to language specific conversion.
+type Bp2buildProtoInfo struct {
+ Type *string
+ Name string
+}
+
+type protoAttrs struct {
+ Srcs bazel.LabelListAttribute
+ Strip_import_prefix *string
+}
+
+// Bp2buildProtoProperties converts proto properties, creating a proto_library and returning the
+// information necessary for language-specific handling.
+func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, module Module, srcs bazel.LabelListAttribute) (Bp2buildProtoInfo, bool) {
+ var info Bp2buildProtoInfo
+ if srcs.IsEmpty() {
+ return info, false
+ }
+ m := module.base()
+
+ info.Name = m.Name() + "_proto"
+ attrs := protoAttrs{
+ Srcs: srcs,
+ }
+
+ for axis, configToProps := range m.GetArchVariantProperties(ctx, &ProtoProperties{}) {
+ for _, rawProps := range configToProps {
+ var props *ProtoProperties
+ var ok bool
+ if props, ok = rawProps.(*ProtoProperties); !ok {
+ ctx.ModuleErrorf("Could not cast ProtoProperties to expected type")
+ }
+ if axis == bazel.NoConfigAxis {
+ info.Type = props.Proto.Type
+
+ if proptools.BoolDefault(props.Proto.Canonical_path_from_root, canonicalPathFromRootDefault) {
+ // an empty string indicates to strips the package path
+ path := ""
+ attrs.Strip_import_prefix = &path
+ }
+ } else if props.Proto.Type != info.Type && props.Proto.Type != nil {
+ ctx.ModuleErrorf("Cannot handle arch-variant types for protos at this time.")
+ }
+ }
+ }
+
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
+ CommonAttributes{Name: info.Name},
+ &attrs)
+
+ return info, true
+}
diff --git a/android/register.go b/android/register.go
index 4244398..1ac4440 100644
--- a/android/register.go
+++ b/android/register.go
@@ -178,13 +178,7 @@
t.register(ctx)
}
- bp2buildMutatorList := []RegisterMutatorFunc{}
- for t, f := range bp2buildMutators {
- ctx.config.bp2buildModuleTypeConfig[t] = true
- bp2buildMutatorList = append(bp2buildMutatorList, f)
- }
-
- RegisterMutatorsForBazelConversion(ctx, bp2buildPreArchMutators, bp2buildMutatorList)
+ RegisterMutatorsForBazelConversion(ctx, bp2buildPreArchMutators)
}
// Register the pipeline of singletons, module types, and mutators for
@@ -196,15 +190,6 @@
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/sdk_version.go b/android/sdk_version.go
index 1813e7e..2004c92 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -117,7 +117,7 @@
return false
}
-// PrebuiltSdkAvailableForUnbundledBuilt tells whether this SdkSpec can have a prebuilt SDK
+// PrebuiltSdkAvailableForUnbundledBuild 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
@@ -212,6 +212,10 @@
)
func SdkSpecFrom(ctx EarlyModuleContext, str string) SdkSpec {
+ return SdkSpecFromWithConfig(ctx.Config(), str)
+}
+
+func SdkSpecFromWithConfig(config Config, str string) SdkSpec {
switch str {
// special cases first
case "":
@@ -252,7 +256,7 @@
return SdkSpec{SdkInvalid, NoneApiLevel, str}
}
- apiLevel, err := ApiLevelFromUser(ctx, versionString)
+ apiLevel, err := ApiLevelFromUserWithConfig(config, versionString)
if err != nil {
return SdkSpec{SdkInvalid, apiLevel, str}
}
diff --git a/android/sdk_version_test.go b/android/sdk_version_test.go
new file mode 100644
index 0000000..ec81782
--- /dev/null
+++ b/android/sdk_version_test.go
@@ -0,0 +1,89 @@
+// Copyright 2015 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 (
+ "testing"
+)
+
+func TestSdkSpecFrom(t *testing.T) {
+ testCases := []struct {
+ input string
+ expected string
+ }{
+ {
+ input: "",
+ expected: "private_current",
+ },
+ {
+ input: "none",
+ expected: "none_(no version)",
+ },
+ {
+ input: "core_platform",
+ expected: "core_platform_current",
+ },
+ {
+ input: "_",
+ expected: "invalid_(no version)",
+ },
+ {
+ input: "_31",
+ expected: "invalid_(no version)",
+ },
+ {
+ input: "system_R",
+ expected: "system_30",
+ },
+ {
+ input: "test_31",
+ expected: "test_31",
+ },
+ {
+ input: "module_current",
+ expected: "module-lib_current",
+ },
+ {
+ input: "31",
+ expected: "public_31",
+ },
+ {
+ input: "S",
+ expected: "public_31",
+ },
+ {
+ input: "current",
+ expected: "public_current",
+ },
+ {
+ input: "Tiramisu",
+ expected: "public_Tiramisu",
+ },
+ }
+
+ config := NullConfig("", "")
+
+ config.productVariables = productVariables{
+ Platform_sdk_version: intPtr(31),
+ Platform_sdk_codename: stringPtr("Tiramisu"),
+ Platform_version_active_codenames: []string{"Tiramisu"},
+ }
+
+ for _, tc := range testCases {
+ if got := SdkSpecFromWithConfig(config, tc.input).String(); tc.expected != got {
+ t.Errorf("Expected %v, got %v", tc.expected, got)
+ }
+ }
+}
diff --git a/android/testing.go b/android/testing.go
index 6290d43..8daf6b7 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -208,16 +208,6 @@
ctx.config.bp2buildPackageConfig = config
}
-// RegisterBp2BuildMutator registers a BazelTargetModule mutator for converting a module
-// type to the equivalent Bazel target.
-func (ctx *TestContext) RegisterBp2BuildMutator(moduleType string, m func(TopDownMutatorContext)) {
- f := func(ctx RegisterMutatorsContext) {
- ctx.TopDown(moduleType, m)
- }
- ctx.config.bp2buildModuleTypeConfig[moduleType] = true
- ctx.bp2buildMutators = append(ctx.bp2buildMutators, f)
-}
-
// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
// into Bazel BUILD targets that should run prior to deps and conversion.
func (ctx *TestContext) PreArchBp2BuildMutators(f RegisterMutatorFunc) {
@@ -459,7 +449,7 @@
// RegisterForBazelConversion prepares a test context for bp2build conversion.
func (ctx *TestContext) RegisterForBazelConversion() {
ctx.SetRunningAsBp2build()
- RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch, ctx.bp2buildMutators)
+ RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch)
}
func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
diff --git a/android/variable.go b/android/variable.go
index fe828d3..a7068108 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -15,13 +15,14 @@
package android
import (
- "android/soong/android/soongconfig"
- "android/soong/bazel"
"fmt"
"reflect"
"runtime"
"strings"
+ "android/soong/android/soongconfig"
+ "android/soong/bazel"
+
"github.com/google/blueprint/proptools"
)
@@ -245,30 +246,30 @@
AppsDefaultVersionName *string `json:",omitempty"`
- Allow_missing_dependencies *bool `json:",omitempty"`
- Unbundled_build *bool `json:",omitempty"`
- Unbundled_build_apps *bool `json:",omitempty"`
- Unbundled_build_image *bool `json:",omitempty"`
- Always_use_prebuilt_sdks *bool `json:",omitempty"`
- Skip_boot_jars_check *bool `json:",omitempty"`
- Malloc_not_svelte *bool `json:",omitempty"`
- Malloc_zero_contents *bool `json:",omitempty"`
- Malloc_pattern_fill_contents *bool `json:",omitempty"`
- Safestack *bool `json:",omitempty"`
- HostStaticBinaries *bool `json:",omitempty"`
- Binder32bit *bool `json:",omitempty"`
- UseGoma *bool `json:",omitempty"`
- UseRBE *bool `json:",omitempty"`
- UseRBEJAVAC *bool `json:",omitempty"`
- UseRBER8 *bool `json:",omitempty"`
- UseRBED8 *bool `json:",omitempty"`
- Debuggable *bool `json:",omitempty"`
- Eng *bool `json:",omitempty"`
- Treble_linker_namespaces *bool `json:",omitempty"`
- Enforce_vintf_manifest *bool `json:",omitempty"`
- Uml *bool `json:",omitempty"`
- Arc *bool `json:",omitempty"`
- MinimizeJavaDebugInfo *bool `json:",omitempty"`
+ Allow_missing_dependencies *bool `json:",omitempty"`
+ Unbundled_build *bool `json:",omitempty"`
+ Unbundled_build_apps []string `json:",omitempty"`
+ Unbundled_build_image *bool `json:",omitempty"`
+ Always_use_prebuilt_sdks *bool `json:",omitempty"`
+ Skip_boot_jars_check *bool `json:",omitempty"`
+ Malloc_not_svelte *bool `json:",omitempty"`
+ Malloc_zero_contents *bool `json:",omitempty"`
+ Malloc_pattern_fill_contents *bool `json:",omitempty"`
+ Safestack *bool `json:",omitempty"`
+ HostStaticBinaries *bool `json:",omitempty"`
+ Binder32bit *bool `json:",omitempty"`
+ UseGoma *bool `json:",omitempty"`
+ UseRBE *bool `json:",omitempty"`
+ UseRBEJAVAC *bool `json:",omitempty"`
+ UseRBER8 *bool `json:",omitempty"`
+ UseRBED8 *bool `json:",omitempty"`
+ Debuggable *bool `json:",omitempty"`
+ Eng *bool `json:",omitempty"`
+ Treble_linker_namespaces *bool `json:",omitempty"`
+ Enforce_vintf_manifest *bool `json:",omitempty"`
+ Uml *bool `json:",omitempty"`
+ Arc *bool `json:",omitempty"`
+ MinimizeJavaDebugInfo *bool `json:",omitempty"`
Check_elf_files *bool `json:",omitempty"`
@@ -298,8 +299,6 @@
ClangTidy *bool `json:",omitempty"`
TidyChecks *string `json:",omitempty"`
- SamplingPGO *bool `json:",omitempty"`
-
JavaCoveragePaths []string `json:",omitempty"`
JavaCoverageExcludePaths []string `json:",omitempty"`
@@ -348,6 +347,7 @@
BoardVendorSepolicyDirs []string `json:",omitempty"`
BoardOdmSepolicyDirs []string `json:",omitempty"`
BoardReqdMaskPolicy []string `json:",omitempty"`
+ BoardPlatVendorPolicy []string `json:",omitempty"`
SystemExtPublicSepolicyDirs []string `json:",omitempty"`
SystemExtPrivateSepolicyDirs []string `json:",omitempty"`
BoardSepolicyM4Defs []string `json:",omitempty"`
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index ca40aaa..a2d6992 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -1537,9 +1537,11 @@
},
{
desc: "LOCAL_LICENSE_KINDS, LOCAL_LICENSE_CONDITIONS, LOCAL_NOTICE_FILE",
- // TODO(b/205615944): When valid "android_license_files" exists, the test requires an Android.mk
- // file (and an Android.bp file is required as well if the license files locates outside the current
- // directory). So plan to use a mock file system to mock the Android.mk and Android.bp files.
+ // When "android_license_files" is valid, the test requires an Android.mk file
+ // outside the current (and an Android.bp file is required as well if the license
+ // files locates directory), thus a mock file system is needed. The integration
+ // test cases for these scenarios have been added in
+ // $(ANDROID_BUILD_TOP)/build/soong/tests/androidmk_test.sh.
in: `
include $(CLEAR_VARS)
LOCAL_MODULE := foo
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 7764b6b..f001fa2 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -309,19 +309,17 @@
return moduleNames
}
-func (a *apexBundle) writeRequiredModules(w io.Writer, apexBundleName string) {
+func (a *apexBundle) writeRequiredModules(w io.Writer) {
var required []string
var targetRequired []string
var hostRequired []string
required = append(required, a.RequiredModuleNames()...)
targetRequired = append(targetRequired, a.TargetRequiredModuleNames()...)
hostRequired = append(hostRequired, a.HostRequiredModuleNames()...)
- installMapSet := make(map[string]bool) // set of dependency module:location mappings
for _, fi := range a.filesInfo {
required = append(required, fi.requiredModuleNames...)
targetRequired = append(targetRequired, fi.targetRequiredModuleNames...)
hostRequired = append(hostRequired, fi.hostRequiredModuleNames...)
- installMapSet[a.fullModuleName(apexBundleName, &fi)+":"+fi.installDir+"/"+fi.builtFile.Base()] = true
}
if len(required) > 0 {
@@ -333,11 +331,6 @@
if len(hostRequired) > 0 {
fmt.Fprintln(w, "LOCAL_HOST_REQUIRED_MODULES +=", strings.Join(hostRequired, " "))
}
- if len(installMapSet) > 0 {
- var installs []string
- installs = append(installs, android.SortedStringKeys(installMapSet)...)
- fmt.Fprintln(w, "LOCAL_LICENSE_INSTALL_MAP +=", strings.Join(installs, " "))
- }
}
func (a *apexBundle) androidMkForType() android.AndroidMkData {
@@ -359,7 +352,7 @@
if len(moduleNames) > 0 {
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(moduleNames, " "))
}
- a.writeRequiredModules(w, name)
+ a.writeRequiredModules(w)
fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
} else {
@@ -401,7 +394,7 @@
if len(a.requiredDeps) > 0 {
fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(a.requiredDeps, " "))
}
- a.writeRequiredModules(w, name)
+ a.writeRequiredModules(w)
if a.mergedNotices.Merged.Valid() {
fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", a.mergedNotices.Merged.Path().String())
diff --git a/apex/apex.go b/apex/apex.go
index c1a4b40..b7faa5b 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -54,8 +54,6 @@
ctx.PreArchMutators(registerPreArchMutators)
ctx.PreDepsMutators(RegisterPreDepsMutators)
ctx.PostDepsMutators(RegisterPostDepsMutators)
-
- android.RegisterBp2BuildMutator("apex", ApexBundleBp2Build)
}
func registerPreArchMutators(ctx android.RegisterMutatorsContext) {
@@ -98,6 +96,14 @@
// /system/sepolicy/apex/<module_name>_file_contexts.
File_contexts *string `android:"path"`
+ // Path to the canned fs config file for customizing file's uid/gid/mod/capabilities. The
+ // format is /<path_or_glob> <uid> <gid> <mode> [capabilities=0x<cap>], where path_or_glob is a
+ // path or glob pattern for a file or set of files, uid/gid are numerial values of user ID
+ // and group ID, mode is octal value for the file mode, and cap is hexadecimal value for the
+ // capability. If this property is not set, or a file is missing in the file, default config
+ // is used.
+ Canned_fs_config *string `android:"path"`
+
ApexNativeDependencies
Multilib apexMultilibProperties
@@ -111,6 +117,9 @@
// List of java libraries that are embedded inside this APEX bundle.
Java_libs []string
+ // List of sh binaries that are embedded inside this APEX bundle.
+ Sh_binaries []string
+
// List of platform_compat_config files that are embedded inside this APEX bundle.
Compat_configs []string
@@ -127,6 +136,13 @@
// symlinking to the system libs. Default is true.
Updatable *bool
+ // Marks that this APEX is designed to be updatable in the future, although it's not
+ // updatable yet. This is used to mimic some of the build behaviors that are applied only to
+ // updatable APEXes. Currently, this disables the size optimization, so that the size of
+ // APEX will not increase when the APEX is actually marked as truly updatable. Default is
+ // false.
+ Future_updatable *bool
+
// Whether this APEX can use platform APIs or not. Can be set to true only when `updatable:
// false`. Default is false.
Platform_apis *bool
@@ -618,6 +634,7 @@
sharedLibTag = dependencyTag{name: "sharedLib", payload: true}
testForTag = dependencyTag{name: "test for"}
testTag = dependencyTag{name: "test", payload: true}
+ shBinaryTag = dependencyTag{name: "shBinary", payload: true}
)
// TODO(jiyong): shorten this function signature
@@ -762,6 +779,10 @@
for _, d := range depsList {
addDependenciesForNativeModules(ctx, d, target, imageVariation)
}
+ ctx.AddFarVariationDependencies([]blueprint.Variation{
+ {Mutator: "os", Variation: target.OsVariation()},
+ {Mutator: "arch", Variation: target.ArchVariation()},
+ }, shBinaryTag, a.properties.Sh_binaries...)
}
// Common-arch dependencies come next
@@ -1298,6 +1319,10 @@
return proptools.BoolDefault(a.properties.Updatable, true)
}
+func (a *apexBundle) FutureUpdatable() bool {
+ return proptools.BoolDefault(a.properties.Future_updatable, false)
+}
+
func (a *apexBundle) UsePlatformApis() bool {
return proptools.BoolDefault(a.properties.Platform_apis, false)
}
@@ -1482,6 +1507,9 @@
func apexFileForShBinary(ctx android.BaseModuleContext, sh *sh.ShBinary) apexFile {
dirInApex := filepath.Join("bin", sh.SubDir())
+ if sh.Target().NativeBridge == android.NativeBridgeEnabled {
+ dirInApex = filepath.Join(dirInApex, sh.Target().NativeBridgeRelativePath)
+ }
fileToCopy := sh.OutputFile()
af := newApexFile(ctx, fileToCopy, sh.BaseModuleName(), dirInApex, shBinary, sh)
af.symlinks = sh.Symlinks()
@@ -1659,7 +1687,7 @@
// 1) do some validity checks such as apex_available, min_sdk_version, etc.
a.checkApexAvailability(ctx)
a.checkUpdatable(ctx)
- a.checkMinSdkVersion(ctx)
+ a.CheckMinSdkVersion(ctx)
a.checkStaticLinkingToStubLibraries(ctx)
a.checkStaticExecutables(ctx)
if len(a.properties.Tests) > 0 && !a.testApex {
@@ -1710,6 +1738,7 @@
return true // track transitive dependencies
} else if r, ok := child.(*rust.Module); ok {
fi := apexFileForRustLibrary(ctx, r)
+ fi.isJniLib = isJniLib
filesInfo = append(filesInfo, fi)
} else {
propertyName := "native_shared_libs"
@@ -1722,8 +1751,6 @@
if cc, ok := child.(*cc.Module); ok {
filesInfo = append(filesInfo, apexFileForExecutable(ctx, cc))
return true // track transitive dependencies
- } else if sh, ok := child.(*sh.ShBinary); ok {
- filesInfo = append(filesInfo, apexFileForShBinary(ctx, sh))
} else if py, ok := child.(*python.Module); ok && py.HostToolPath().Valid() {
filesInfo = append(filesInfo, apexFileForPyBinary(ctx, py))
} else if gb, ok := child.(bootstrap.GoBinaryTool); ok && a.Host() {
@@ -1732,7 +1759,13 @@
filesInfo = append(filesInfo, apexFileForRustExecutable(ctx, rust))
return true // track transitive dependencies
} else {
- ctx.PropertyErrorf("binaries", "%q is neither cc_binary, rust_binary, (embedded) py_binary, (host) blueprint_go_binary, (host) bootstrap_go_binary, nor sh_binary", depName)
+ ctx.PropertyErrorf("binaries", "%q is neither cc_binary, rust_binary, (embedded) py_binary, (host) blueprint_go_binary, nor (host) bootstrap_go_binary", depName)
+ }
+ case shBinaryTag:
+ if sh, ok := child.(*sh.ShBinary); ok {
+ filesInfo = append(filesInfo, apexFileForShBinary(ctx, sh))
+ } else {
+ ctx.PropertyErrorf("sh_binaries", "%q is not a sh_binary module", depName)
}
case bcpfTag:
{
@@ -1988,6 +2021,8 @@
}
} else if _, ok := depTag.(android.CopyDirectlyInAnyApexTag); ok {
// nothing
+ } else if depTag == android.DarwinUniversalVariantTag {
+ // nothing
} else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName)
}
@@ -2089,10 +2124,11 @@
}
forced := ctx.Config().ForceApexSymlinkOptimization()
+ updatable := a.Updatable() || a.FutureUpdatable()
// We don't need the optimization for updatable APEXes, as it might give false signal
// to the system health when the APEXes are still bundled (b/149805758).
- if !forced && a.Updatable() && a.properties.ApexType == imageApex {
+ if !forced && updatable && a.properties.ApexType == imageApex {
a.linkToSystemLib = false
}
@@ -2158,6 +2194,40 @@
filesToAdd = append(filesToAdd, *af)
}
+ if pathInApex := bootclasspathFragmentInfo.ProfileInstallPathInApex(); pathInApex != "" {
+ pathOnHost := bootclasspathFragmentInfo.ProfilePathOnHost()
+ tempPath := android.PathForModuleOut(ctx, "boot_image_profile", pathInApex)
+
+ if pathOnHost != nil {
+ // We need to copy the profile to a temporary path with the right filename because the apexer
+ // will take the filename as is.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: pathOnHost,
+ Output: tempPath,
+ })
+ } else {
+ // At this point, the boot image profile cannot be generated. It is probably because the boot
+ // image profile source file does not exist on the branch, or it is not available for the
+ // current build target.
+ // However, we cannot enforce the boot image profile to be generated because some build
+ // targets (such as module SDK) do not need it. It is only needed when the APEX is being
+ // built. Therefore, we create an error rule so that an error will occur at the ninja phase
+ // only if the APEX is being built.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.ErrorRule,
+ Output: tempPath,
+ Args: map[string]string{
+ "error": "Boot image profile cannot be generated",
+ },
+ })
+ }
+
+ androidMkModuleName := filepath.Base(pathInApex)
+ af := newApexFile(ctx, tempPath, androidMkModuleName, filepath.Dir(pathInApex), etc, nil)
+ filesToAdd = append(filesToAdd, af)
+ }
+
return filesToAdd
}
@@ -2284,18 +2354,28 @@
//
// TODO(jiyong): move these checks to a separate go file.
+var _ android.ModuleWithMinSdkVersionCheck = (*apexBundle)(nil)
+
// Entures that min_sdk_version of the included modules are equal or less than the min_sdk_version
// of this apexBundle.
-func (a *apexBundle) checkMinSdkVersion(ctx android.ModuleContext) {
+func (a *apexBundle) CheckMinSdkVersion(ctx android.ModuleContext) {
if a.testApex || a.vndkApex {
return
}
// apexBundle::minSdkVersion reports its own errors.
minSdkVersion := a.minSdkVersion(ctx)
- android.CheckMinSdkVersion(a, ctx, minSdkVersion)
+ android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps)
}
-func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) android.ApiLevel {
+func (a *apexBundle) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+ return android.SdkSpec{
+ Kind: android.SdkNone,
+ ApiLevel: a.minSdkVersion(ctx),
+ Raw: String(a.properties.Min_sdk_version),
+ }
+}
+
+func (a *apexBundle) minSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
ver := proptools.String(a.properties.Min_sdk_version)
if ver == "" {
return android.NoneApiLevel
@@ -2361,6 +2441,12 @@
if a.UsePlatformApis() {
ctx.PropertyErrorf("updatable", "updatable APEXes can't use platform APIs")
}
+ if a.SocSpecific() || a.DeviceSpecific() {
+ ctx.PropertyErrorf("updatable", "vendor APEXes are not updatable")
+ }
+ if a.FutureUpdatable() {
+ ctx.PropertyErrorf("future_updatable", "Already updatable. Remove `future_updatable: true:`")
+ }
a.checkJavaStableSdkVersion(ctx)
a.checkClasspathFragments(ctx)
}
@@ -3120,15 +3206,16 @@
BootclasspathJar().
With("apex_available", module_name).
WithMatcher("permitted_packages", android.NotInList(module_packages)).
+ WithMatcher("min_sdk_version", android.LessThanSdkVersion("Tiramisu")).
Because("jars that are part of the " + module_name +
" module may only allow these packages: " + strings.Join(module_packages, ",") +
- ". Please jarjar or move code around.")
+ " with min_sdk < T. Please jarjar or move code around.")
rules = append(rules, permittedPackagesRule)
}
return rules
}
-// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART.
+// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART on Q/R/S.
// Adding code to the bootclasspath in new packages will cause issues on module update.
func qModulesPackages() map[string][]string {
return map[string][]string{
@@ -3142,7 +3229,7 @@
}
}
-// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART.
+// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART on R/S.
// Adding code to the bootclasspath in new packages will cause issues on module update.
func rModulesPackages() map[string][]string {
return map[string][]string{
@@ -3185,80 +3272,70 @@
File_contexts bazel.LabelAttribute
Key bazel.LabelAttribute
Certificate bazel.LabelAttribute
- Min_sdk_version string
+ Min_sdk_version *string
Updatable bazel.BoolAttribute
Installable bazel.BoolAttribute
Native_shared_libs bazel.LabelListAttribute
- Binaries bazel.StringListAttribute
+ Binaries bazel.LabelListAttribute
Prebuilts bazel.LabelListAttribute
}
-func ApexBundleBp2Build(ctx android.TopDownMutatorContext) {
- module, ok := ctx.Module().(*apexBundle)
- if !ok {
- // Not an APEX bundle
- return
- }
- if !module.ConvertWithBp2build(ctx) {
- return
- }
+// ConvertWithBp2build performs bp2build conversion of an apex
+func (a *apexBundle) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ // We do not convert apex_test modules at this time
if ctx.ModuleType() != "apex" {
return
}
- apexBundleBp2BuildInternal(ctx, module)
-}
-
-func apexBundleBp2BuildInternal(ctx android.TopDownMutatorContext, module *apexBundle) {
var manifestLabelAttribute bazel.LabelAttribute
- if module.properties.Manifest != nil {
- manifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *module.properties.Manifest))
+ if a.properties.Manifest != nil {
+ manifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.Manifest))
}
var androidManifestLabelAttribute bazel.LabelAttribute
- if module.properties.AndroidManifest != nil {
- androidManifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *module.properties.AndroidManifest))
+ if a.properties.AndroidManifest != nil {
+ androidManifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.AndroidManifest))
}
var fileContextsLabelAttribute bazel.LabelAttribute
- if module.properties.File_contexts != nil {
- fileContextsLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *module.properties.File_contexts))
+ if a.properties.File_contexts != nil {
+ fileContextsLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *a.properties.File_contexts))
}
- var minSdkVersion string
- if module.properties.Min_sdk_version != nil {
- minSdkVersion = *module.properties.Min_sdk_version
+ var minSdkVersion *string
+ if a.properties.Min_sdk_version != nil {
+ minSdkVersion = a.properties.Min_sdk_version
}
var keyLabelAttribute bazel.LabelAttribute
- if module.overridableProperties.Key != nil {
- keyLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *module.overridableProperties.Key))
+ if a.overridableProperties.Key != nil {
+ keyLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *a.overridableProperties.Key))
}
var certificateLabelAttribute bazel.LabelAttribute
- if module.overridableProperties.Certificate != nil {
- certificateLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *module.overridableProperties.Certificate))
+ if a.overridableProperties.Certificate != nil {
+ certificateLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *a.overridableProperties.Certificate))
}
- nativeSharedLibs := module.properties.ApexNativeDependencies.Native_shared_libs
+ nativeSharedLibs := a.properties.ApexNativeDependencies.Native_shared_libs
nativeSharedLibsLabelList := android.BazelLabelForModuleDeps(ctx, nativeSharedLibs)
nativeSharedLibsLabelListAttribute := bazel.MakeLabelListAttribute(nativeSharedLibsLabelList)
- prebuilts := module.overridableProperties.Prebuilts
+ prebuilts := a.overridableProperties.Prebuilts
prebuiltsLabelList := android.BazelLabelForModuleDeps(ctx, prebuilts)
prebuiltsLabelListAttribute := bazel.MakeLabelListAttribute(prebuiltsLabelList)
- binaries := module.properties.ApexNativeDependencies.Binaries
- binariesStringListAttribute := bazel.MakeStringListAttribute(binaries)
+ binaries := android.BazelLabelForModuleDeps(ctx, a.properties.ApexNativeDependencies.Binaries)
+ binariesLabelListAttribute := bazel.MakeLabelListAttribute(binaries)
var updatableAttribute bazel.BoolAttribute
- if module.properties.Updatable != nil {
- updatableAttribute.Value = module.properties.Updatable
+ if a.properties.Updatable != nil {
+ updatableAttribute.Value = a.properties.Updatable
}
var installableAttribute bazel.BoolAttribute
- if module.properties.Installable != nil {
- installableAttribute.Value = module.properties.Installable
+ if a.properties.Installable != nil {
+ installableAttribute.Value = a.properties.Installable
}
attrs := &bazelApexBundleAttributes{
@@ -3271,7 +3348,7 @@
Updatable: updatableAttribute,
Installable: installableAttribute,
Native_shared_libs: nativeSharedLibsLabelListAttribute,
- Binaries: binariesStringListAttribute,
+ Binaries: binariesLabelListAttribute,
Prebuilts: prebuiltsLabelListAttribute,
}
@@ -3280,5 +3357,5 @@
Bzl_load_location: "//build/bazel/rules:apex.bzl",
}
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: a.Name()}, attrs)
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 59ea206..a749ea1 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -215,7 +215,9 @@
variables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"}
variables.Platform_sdk_codename = proptools.StringPtr("Q")
variables.Platform_sdk_final = proptools.BoolPtr(false)
- variables.Platform_version_active_codenames = []string{"Q"}
+ // "Tiramisu" needs to be in the next line for compatibility with soong code,
+ // not because of these tests specifically (it's not used by the tests)
+ variables.Platform_version_active_codenames = []string{"Q", "Tiramisu"}
variables.Platform_vndk_version = proptools.StringPtr("29")
}),
)
@@ -2579,22 +2581,21 @@
`)
generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("generateFsConfig")
- dirs := strings.Split(generateFsRule.Args["exec_paths"], " ")
+ cmd := generateFsRule.RuleParams.Command
// Ensure that the subdirectories are all listed
- ensureListContains(t, dirs, "etc")
- ensureListContains(t, dirs, "etc/foo")
- ensureListContains(t, dirs, "etc/foo/bar")
- ensureListContains(t, dirs, "lib64")
- ensureListContains(t, dirs, "lib64/foo")
- ensureListContains(t, dirs, "lib64/foo/bar")
- ensureListContains(t, dirs, "lib")
- ensureListContains(t, dirs, "lib/foo")
- ensureListContains(t, dirs, "lib/foo/bar")
-
- ensureListContains(t, dirs, "bin")
- ensureListContains(t, dirs, "bin/foo")
- ensureListContains(t, dirs, "bin/foo/bar")
+ ensureContains(t, cmd, "/etc ")
+ ensureContains(t, cmd, "/etc/foo ")
+ ensureContains(t, cmd, "/etc/foo/bar ")
+ ensureContains(t, cmd, "/lib64 ")
+ ensureContains(t, cmd, "/lib64/foo ")
+ ensureContains(t, cmd, "/lib64/foo/bar ")
+ ensureContains(t, cmd, "/lib ")
+ ensureContains(t, cmd, "/lib/foo ")
+ ensureContains(t, cmd, "/lib/foo/bar ")
+ ensureContains(t, cmd, "/bin ")
+ ensureContains(t, cmd, "/bin/foo ")
+ ensureContains(t, cmd, "/bin/foo/bar ")
}
func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) {
@@ -4248,7 +4249,7 @@
apex {
name: "myapex",
key: "myapex.key",
- binaries: ["myscript"],
+ sh_binaries: ["myscript"],
updatable: false,
}
@@ -6204,7 +6205,7 @@
})
// Permission XML should point to the activated path of impl jar of java_sdk_library
sdkLibrary := ctx.ModuleForTests("foo.xml", "android_common_myapex").Rule("java_sdk_xml")
- ensureContains(t, sdkLibrary.RuleParams.Command, `<library name=\"foo\" file=\"/apex/myapex/javalib/foo.jar\"`)
+ ensureMatches(t, sdkLibrary.RuleParams.Command, `<library\\n\s+name=\\\"foo\\\"\\n\s+file=\\\"/apex/myapex/javalib/foo.jar\\\"`)
}
func TestJavaSDKLibrary_WithinApex(t *testing.T) {
@@ -7035,6 +7036,7 @@
`, insert))
}
}),
+ dexpreopt.FixtureSetBootImageProfiles("art/build/boot/boot-image-profile.txt"),
).
ExtendWithErrorHandler(errorHandler).
RunTestWithBp(t, bp)
@@ -7042,6 +7044,75 @@
return result.TestContext
}
+func TestDuplicateDeapexeresFromPrebuiltApexes(t *testing.T) {
+ preparers := android.GroupFixturePreparers(
+ java.PrepareForTestWithJavaDefaultModules,
+ PrepareForTestWithApexBuildComponents,
+ ).
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ "Multiple installable prebuilt APEXes provide ambiguous deapexers: com.android.myapex and com.mycompany.android.myapex"))
+
+ bpBase := `
+ apex_set {
+ name: "com.android.myapex",
+ installable: true,
+ exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ set: "myapex.apks",
+ }
+
+ apex_set {
+ name: "com.mycompany.android.myapex",
+ apex_name: "com.android.myapex",
+ installable: true,
+ exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ set: "company-myapex.apks",
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "my-bootclasspath-fragment",
+ apex_available: ["com.android.myapex"],
+ %s
+ }
+ `
+
+ t.Run("java_import", func(t *testing.T) {
+ _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+`
+ java_import {
+ name: "libfoo",
+ jars: ["libfoo.jar"],
+ apex_available: ["com.android.myapex"],
+ }
+ `)
+ })
+
+ t.Run("java_sdk_library_import", func(t *testing.T) {
+ _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+`
+ java_sdk_library_import {
+ name: "libfoo",
+ public: {
+ jars: ["libbar.jar"],
+ },
+ apex_available: ["com.android.myapex"],
+ }
+ `)
+ })
+
+ t.Run("prebuilt_bootclasspath_fragment", func(t *testing.T) {
+ _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `
+ image_name: "art",
+ contents: ["libfoo"],
+ `)+`
+ java_sdk_library_import {
+ name: "libfoo",
+ public: {
+ jars: ["libbar.jar"],
+ },
+ apex_available: ["com.android.myapex"],
+ }
+ `)
+ })
+}
+
func TestUpdatable_should_set_min_sdk_version(t *testing.T) {
testApexError(t, `"myapex" .*: updatable: updatable APEXes should set min_sdk_version`, `
apex {
@@ -7073,6 +7144,23 @@
`)
}
+func TestUpdatable_cannot_be_vendor_apex(t *testing.T) {
+ testApexError(t, `"myapex" .*: updatable: vendor APEXes are not updatable`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: true,
+ soc_specific: true,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `)
+}
+
func TestUpdatable_should_not_set_generate_classpaths_proto(t *testing.T) {
testApexError(t, `"mysystemserverclasspathfragment" .* it must not set generate_classpaths_proto to false`, `
apex {
@@ -7339,6 +7427,7 @@
apex_available: ["myapex"],
sdk_version: "none",
system_modules: "none",
+ min_sdk_version: "30",
}
java_library {
name: "nonbcp_lib2",
@@ -7347,9 +7436,11 @@
permitted_packages: ["a.b"],
sdk_version: "none",
system_modules: "none",
+ min_sdk_version: "30",
}
apex {
name: "myapex",
+ min_sdk_version: "30",
key: "myapex.key",
java_libs: ["bcp_lib1", "nonbcp_lib2"],
updatable: false,
@@ -7362,8 +7453,8 @@
},
},
{
- name: "Bootclasspath apex jar not satisfying allowed module packages.",
- expectedError: `module "bcp_lib2" .* which is restricted because jars that are part of the myapex module may only allow these packages: foo.bar. Please jarjar or move code around.`,
+ name: "Bootclasspath apex jar not satisfying allowed module packages on Q.",
+ expectedError: `module "bcp_lib2" .* which is restricted because jars that are part of the myapex module may only allow these packages: foo.bar with min_sdk < T. Please jarjar or move code around.`,
bp: `
java_library {
name: "bcp_lib1",
@@ -7372,6 +7463,7 @@
permitted_packages: ["foo.bar"],
sdk_version: "none",
system_modules: "none",
+ min_sdk_version: "29",
}
java_library {
name: "bcp_lib2",
@@ -7380,9 +7472,85 @@
permitted_packages: ["foo.bar", "bar.baz"],
sdk_version: "none",
system_modules: "none",
+ min_sdk_version: "29",
}
apex {
name: "myapex",
+ min_sdk_version: "29",
+ key: "myapex.key",
+ java_libs: ["bcp_lib1", "bcp_lib2"],
+ updatable: false,
+ }
+ `,
+ bootJars: []string{"bcp_lib1", "bcp_lib2"},
+ modulesPackages: map[string][]string{
+ "myapex": []string{
+ "foo.bar",
+ },
+ },
+ },
+ {
+ name: "Bootclasspath apex jar not satisfying allowed module packages on R.",
+ expectedError: `module "bcp_lib2" .* which is restricted because jars that are part of the myapex module may only allow these packages: foo.bar with min_sdk < T. Please jarjar or move code around.`,
+ bp: `
+ java_library {
+ name: "bcp_lib1",
+ srcs: ["lib1/src/*.java"],
+ apex_available: ["myapex"],
+ permitted_packages: ["foo.bar"],
+ sdk_version: "none",
+ system_modules: "none",
+ min_sdk_version: "30",
+ }
+ java_library {
+ name: "bcp_lib2",
+ srcs: ["lib2/src/*.java"],
+ apex_available: ["myapex"],
+ permitted_packages: ["foo.bar", "bar.baz"],
+ sdk_version: "none",
+ system_modules: "none",
+ min_sdk_version: "30",
+ }
+ apex {
+ name: "myapex",
+ min_sdk_version: "30",
+ key: "myapex.key",
+ java_libs: ["bcp_lib1", "bcp_lib2"],
+ updatable: false,
+ }
+ `,
+ bootJars: []string{"bcp_lib1", "bcp_lib2"},
+ modulesPackages: map[string][]string{
+ "myapex": []string{
+ "foo.bar",
+ },
+ },
+ },
+ {
+ name: "Bootclasspath apex jar >= T not satisfying Q/R/S allowed module packages.",
+ expectedError: "",
+ bp: `
+ java_library {
+ name: "bcp_lib1",
+ srcs: ["lib1/src/*.java"],
+ apex_available: ["myapex"],
+ permitted_packages: ["foo.bar"],
+ sdk_version: "none",
+ system_modules: "none",
+ min_sdk_version: "current",
+ }
+ java_library {
+ name: "bcp_lib2",
+ srcs: ["lib2/src/*.java"],
+ apex_available: ["myapex"],
+ permitted_packages: ["foo.bar", "bar.baz"],
+ sdk_version: "none",
+ system_modules: "none",
+ min_sdk_version: "current",
+ }
+ apex {
+ name: "myapex",
+ min_sdk_version: "current",
key: "myapex.key",
java_libs: ["bcp_lib1", "bcp_lib2"],
updatable: false,
@@ -8390,6 +8558,184 @@
ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += otherapex")
}
+func TestSdkLibraryCanHaveHigherMinSdkVersion(t *testing.T) {
+ preparer := android.GroupFixturePreparers(
+ PrepareForTestWithApexBuildComponents,
+ prepareForTestWithMyapex,
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestWithAndroidBuildComponents,
+ dexpreopt.FixtureSetApexBootJars("myapex:mybootclasspathlib"),
+ dexpreopt.FixtureSetApexSystemServerJars("myapex:mysystemserverclasspathlib"),
+ )
+
+ // Test java_sdk_library in bootclasspath_fragment may define higher min_sdk_version than the apex
+ t.Run("bootclasspath_fragment jar has higher min_sdk_version than apex", func(t *testing.T) {
+ preparer.RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: ["mybootclasspathfragment"],
+ min_sdk_version: "30",
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ contents: ["mybootclasspathlib"],
+ apex_available: ["myapex"],
+ }
+
+ java_sdk_library {
+ name: "mybootclasspathlib",
+ srcs: ["mybootclasspathlib.java"],
+ apex_available: ["myapex"],
+ compile_dex: true,
+ unsafe_ignore_missing_latest_api: true,
+ min_sdk_version: "31",
+ static_libs: ["util"],
+ }
+
+ java_library {
+ name: "util",
+ srcs: ["a.java"],
+ apex_available: ["myapex"],
+ min_sdk_version: "31",
+ static_libs: ["another_util"],
+ }
+
+ java_library {
+ name: "another_util",
+ srcs: ["a.java"],
+ min_sdk_version: "31",
+ apex_available: ["myapex"],
+ }
+ `)
+ })
+
+ // Test java_sdk_library in systemserverclasspath_fragment may define higher min_sdk_version than the apex
+ t.Run("systemserverclasspath_fragment jar has higher min_sdk_version than apex", func(t *testing.T) {
+ preparer.RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
+ min_sdk_version: "30",
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ systemserverclasspath_fragment {
+ name: "mysystemserverclasspathfragment",
+ contents: ["mysystemserverclasspathlib"],
+ apex_available: ["myapex"],
+ }
+
+ java_sdk_library {
+ name: "mysystemserverclasspathlib",
+ srcs: ["mysystemserverclasspathlib.java"],
+ apex_available: ["myapex"],
+ compile_dex: true,
+ min_sdk_version: "32",
+ unsafe_ignore_missing_latest_api: true,
+ static_libs: ["util"],
+ }
+
+ java_library {
+ name: "util",
+ srcs: ["a.java"],
+ apex_available: ["myapex"],
+ min_sdk_version: "31",
+ static_libs: ["another_util"],
+ }
+
+ java_library {
+ name: "another_util",
+ srcs: ["a.java"],
+ min_sdk_version: "31",
+ apex_available: ["myapex"],
+ }
+ `)
+ })
+
+ t.Run("bootclasspath_fragment jar must set min_sdk_version", func(t *testing.T) {
+ preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "mybootclasspathlib".*must set min_sdk_version`)).
+ RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: ["mybootclasspathfragment"],
+ min_sdk_version: "30",
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ contents: ["mybootclasspathlib"],
+ apex_available: ["myapex"],
+ }
+
+ java_sdk_library {
+ name: "mybootclasspathlib",
+ srcs: ["mybootclasspathlib.java"],
+ apex_available: ["myapex"],
+ compile_dex: true,
+ unsafe_ignore_missing_latest_api: true,
+ }
+ `)
+ })
+
+ t.Run("systemserverclasspath_fragment jar must set min_sdk_version", func(t *testing.T) {
+ preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "mysystemserverclasspathlib".*must set min_sdk_version`)).
+ RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
+ min_sdk_version: "30",
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ systemserverclasspath_fragment {
+ name: "mysystemserverclasspathfragment",
+ contents: ["mysystemserverclasspathlib"],
+ apex_available: ["myapex"],
+ }
+
+ java_sdk_library {
+ name: "mysystemserverclasspathlib",
+ srcs: ["mysystemserverclasspathlib.java"],
+ apex_available: ["myapex"],
+ compile_dex: true,
+ unsafe_ignore_missing_latest_api: true,
+ }
+ `)
+ })
+}
+
func TestMain(m *testing.M) {
os.Exit(m.Run())
}
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index cb7d3d1..7ecf9b2 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -21,6 +21,7 @@
"testing"
"android/soong/android"
+ "android/soong/dexpreopt"
"android/soong/java"
"github.com/google/blueprint/proptools"
@@ -35,11 +36,14 @@
)
// 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,
-})
+var prepareForTestWithArtApex = android.GroupFixturePreparers(
+ android.FixtureMergeMockFs(android.MockFS{
+ "com.android.art.avbpubkey": nil,
+ "com.android.art.pem": nil,
+ "system/sepolicy/apex/com.android.art-file_contexts": nil,
+ }),
+ dexpreopt.FixtureSetBootImageProfiles("art/build/boot/boot-image-profile.txt"),
+)
func TestBootclasspathFragments(t *testing.T) {
result := android.GroupFixturePreparers(
@@ -408,6 +412,7 @@
).RunTest(t)
ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+ "etc/boot-image.prof",
"etc/classpaths/bootclasspath.pb",
"javalib/arm/boot.art",
"javalib/arm/boot.oat",
@@ -451,6 +456,7 @@
).RunTest(t)
ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+ "etc/boot-image.prof",
"etc/classpaths/bootclasspath.pb",
"javalib/arm/boot.art",
"javalib/arm/boot.oat",
@@ -542,7 +548,7 @@
}
func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) {
- result := android.GroupFixturePreparers(
+ preparers := android.GroupFixturePreparers(
prepareForTestWithBootclasspathFragment,
prepareForTestWithArtApex,
@@ -553,7 +559,9 @@
// Configure some libraries in the art bootclasspath_fragment.
java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
- ).RunTestWithBp(t, `
+ )
+
+ bp := `
prebuilt_apex {
name: "com.android.art",
arch: {
@@ -599,22 +607,45 @@
all_flags: "mybootclasspathfragment/all-flags.csv",
},
}
- `)
- java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{
- `com.android.art.apex.selector`,
- `prebuilt_mybootclasspathfragment`,
+ // A prebuilt apex with the same apex_name that shouldn't interfere when it isn't enabled.
+ prebuilt_apex {
+ name: "com.mycompany.android.art",
+ apex_name: "com.android.art",
+ %s
+ src: "com.mycompany.android.art.apex",
+ exported_bootclasspath_fragments: ["mybootclasspathfragment"],
+ }
+ `
+
+ t.Run("disabled alternative APEX", func(t *testing.T) {
+ result := preparers.RunTestWithBp(t, fmt.Sprintf(bp, "enabled: false,"))
+
+ java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{
+ `com.android.art.apex.selector`,
+ `prebuilt_mybootclasspathfragment`,
+ })
+
+ java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_com.android.art", []string{
+ `com.android.art.deapexer`,
+ `dex2oatd`,
+ `prebuilt_bar`,
+ `prebuilt_foo`,
+ })
+
+ module := result.ModuleForTests("mybootclasspathfragment", "android_common_com.android.art")
+ checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
+
+ // Check that the right deapexer module was chosen for a boot image.
+ param := module.Output("out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art")
+ android.AssertStringDoesContain(t, "didn't find the expected deapexer in the input path", param.Input.String(), "/com.android.art.deapexer")
})
- java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_com.android.art", []string{
- `com.android.art.deapexer`,
- `dex2oatd`,
- `prebuilt_bar`,
- `prebuilt_foo`,
+ t.Run("enabled alternative APEX", func(t *testing.T) {
+ preparers.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ "Multiple installable prebuilt APEXes provide ambiguous deapexers: com.android.art and com.mycompany.android.art")).
+ RunTestWithBp(t, fmt.Sprintf(bp, ""))
})
-
- module := result.ModuleForTests("mybootclasspathfragment", "android_common_com.android.art")
- checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
}
// checkCopiesToPredefinedLocationForArt checks that the supplied modules are copied to the
diff --git a/apex/builder.go b/apex/builder.go
index 0880e2b..ea25537 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -72,19 +72,6 @@
}
var (
- // Create a canned fs config file where all files and directories are
- // by default set to (uid/gid/mode) = (1000/1000/0644)
- // TODO(b/113082813) make this configurable using config.fs syntax
- generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{
- Command: `( set -e; echo '/ 1000 1000 0755' ` +
- `&& for i in ${ro_paths}; do echo "/$$i 1000 1000 0644"; done ` +
- `&& for i in ${exec_paths}; do echo "/$$i 0 2000 0755"; done ` +
- `&& ( tr ' ' '\n' <${out}.apklist | for i in ${apk_paths}; do read apk; echo "/$$i 0 2000 0755"; zipinfo -1 $$apk | sed "s:\(.*\):/$$i/\1 1000 1000 0644:"; done ) ) > ${out}`,
- Description: "fs_config ${out}",
- Rspfile: "$out.apklist",
- RspfileContent: "$in",
- }, "ro_paths", "exec_paths", "apk_paths")
-
apexManifestRule = pctx.StaticRule("apexManifestRule", blueprint.RuleParams{
Command: `rm -f $out && ${jsonmodify} $in ` +
`-a provideNativeLibs ${provideNativeLibs} ` +
@@ -434,7 +421,10 @@
// Avoid creating duplicate build rules for multi-installed APEXes.
if proptools.BoolDefault(a.properties.Multi_install_skip_symbol_files, false) {
installSymbolFiles = false
+
}
+ // set of dependency module:location mappings
+ installMapSet := make(map[string]bool)
// TODO(jiyong): use the RuleBuilder
var copyCommands []string
@@ -442,7 +432,6 @@
pathWhenActivated := android.PathForModuleInPartitionInstall(ctx, "apex", apexName)
for _, fi := range a.filesInfo {
destPath := imageDir.Join(ctx, fi.path()).String()
- var installedPath android.InstallPath
// Prepare the destination path
destPathDir := filepath.Dir(destPath)
if fi.class == appSet {
@@ -450,6 +439,8 @@
}
copyCommands = append(copyCommands, "mkdir -p "+destPathDir)
+ installMapPath := fi.builtFile
+
// Copy the built file to the directory. But if the symlink optimization is turned
// on, place a symlink to the corresponding file in /system partition instead.
if a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform() {
@@ -457,6 +448,7 @@
pathOnDevice := filepath.Join("/system", fi.path())
copyCommands = append(copyCommands, "ln -sfn "+pathOnDevice+" "+destPath)
} else {
+ var installedPath android.InstallPath
if fi.class == appSet {
copyCommands = append(copyCommands,
fmt.Sprintf("unzip -qDD -d %s %s", destPathDir,
@@ -475,17 +467,19 @@
if installSymbolFiles {
implicitInputs = append(implicitInputs, installedPath)
}
- }
- // Create additional symlinks pointing the file inside the APEX (if any). Note that
- // this is independent from the symlink optimization.
- for _, symlinkPath := range fi.symlinkPaths() {
- symlinkDest := imageDir.Join(ctx, symlinkPath).String()
- copyCommands = append(copyCommands, "ln -sfn "+filepath.Base(destPath)+" "+symlinkDest)
- if installSymbolFiles {
- installedSymlink := ctx.InstallSymlink(pathWhenActivated.Join(ctx, filepath.Dir(symlinkPath)), filepath.Base(symlinkPath), installedPath)
- implicitInputs = append(implicitInputs, installedSymlink)
+ // Create additional symlinks pointing the file inside the APEX (if any). Note that
+ // this is independent from the symlink optimization.
+ for _, symlinkPath := range fi.symlinkPaths() {
+ symlinkDest := imageDir.Join(ctx, symlinkPath).String()
+ copyCommands = append(copyCommands, "ln -sfn "+filepath.Base(destPath)+" "+symlinkDest)
+ if installSymbolFiles {
+ installedSymlink := ctx.InstallSymlink(pathWhenActivated.Join(ctx, filepath.Dir(symlinkPath)), filepath.Base(symlinkPath), installedPath)
+ implicitInputs = append(implicitInputs, installedSymlink)
+ }
}
+
+ installMapPath = installedPath
}
// Copy the test files (if any)
@@ -502,6 +496,8 @@
copyCommands = append(copyCommands, "cp -f "+d.SrcPath.String()+" "+dataDest)
implicitInputs = append(implicitInputs, d.SrcPath)
}
+
+ installMapSet[installMapPath.String()+":"+fi.installDir+"/"+fi.builtFile.Base()] = true
}
implicitInputs = append(implicitInputs, a.manifestPbOut)
if installSymbolFiles {
@@ -510,6 +506,12 @@
implicitInputs = append(implicitInputs, installedManifest, installedKey)
}
+ if len(installMapSet) > 0 {
+ var installs []string
+ installs = append(installs, android.SortedStringKeys(installMapSet)...)
+ a.SetLicenseInstallMap(installs)
+ }
+
////////////////////////////////////////////////////////////////////////////////////////////
// Step 1.a: Write the list of files in this APEX to a txt file and compare it against
// the allowed list given via the allowed_files property. Build fails when the two lists
@@ -568,55 +570,11 @@
// Figure out if need to compress apex.
compressionEnabled := ctx.Config().CompressedApex() && proptools.BoolDefault(a.properties.Compressible, false) && !a.testApex && !ctx.Config().UnbundledBuildApps()
if apexType == imageApex {
+
////////////////////////////////////////////////////////////////////////////////////
// Step 2: create canned_fs_config which encodes filemode,uid,gid of each files
// in this APEX. The file will be used by apexer in later steps.
- // TODO(jiyong): make this as a function
- // TODO(jiyong): use the RuleBuilder
- var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"}
- var executablePaths []string // this also includes dirs
- var extractedAppSetPaths android.Paths
- var extractedAppSetDirs []string
- for _, f := range a.filesInfo {
- pathInApex := f.path()
- if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") {
- executablePaths = append(executablePaths, pathInApex)
- for _, d := range f.dataPaths {
- readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, d.RelativeInstallPath, d.SrcPath.Rel()))
- }
- for _, s := range f.symlinks {
- executablePaths = append(executablePaths, filepath.Join(f.installDir, s))
- }
- } else if f.class == appSet {
- extractedAppSetPaths = append(extractedAppSetPaths, f.builtFile)
- extractedAppSetDirs = append(extractedAppSetDirs, f.installDir)
- } else {
- readOnlyPaths = append(readOnlyPaths, pathInApex)
- }
- dir := f.installDir
- for !android.InList(dir, executablePaths) && dir != "" {
- executablePaths = append(executablePaths, dir)
- dir, _ = filepath.Split(dir) // move up to the parent
- if len(dir) > 0 {
- // remove trailing slash
- dir = dir[:len(dir)-1]
- }
- }
- }
- sort.Strings(readOnlyPaths)
- sort.Strings(executablePaths)
- cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config")
- ctx.Build(pctx, android.BuildParams{
- Rule: generateFsConfig,
- Output: cannedFsConfig,
- Description: "generate fs config",
- Inputs: extractedAppSetPaths,
- Args: map[string]string{
- "ro_paths": strings.Join(readOnlyPaths, " "),
- "exec_paths": strings.Join(executablePaths, " "),
- "apk_paths": strings.Join(extractedAppSetDirs, " "),
- },
- })
+ cannedFsConfig := a.buildCannedFsConfig(ctx)
implicitInputs = append(implicitInputs, cannedFsConfig)
////////////////////////////////////////////////////////////////////////////////////
@@ -1057,3 +1015,65 @@
a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build())
}
+
+func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.OutputPath {
+ var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"}
+ var executablePaths []string // this also includes dirs
+ var appSetDirs []string
+ appSetFiles := make(map[string]android.Path)
+ for _, f := range a.filesInfo {
+ pathInApex := f.path()
+ if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") {
+ executablePaths = append(executablePaths, pathInApex)
+ for _, d := range f.dataPaths {
+ readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, d.RelativeInstallPath, d.SrcPath.Rel()))
+ }
+ for _, s := range f.symlinks {
+ executablePaths = append(executablePaths, filepath.Join(f.installDir, s))
+ }
+ } else if f.class == appSet {
+ appSetDirs = append(appSetDirs, f.installDir)
+ appSetFiles[f.installDir] = f.builtFile
+ } else {
+ readOnlyPaths = append(readOnlyPaths, pathInApex)
+ }
+ dir := f.installDir
+ for !android.InList(dir, executablePaths) && dir != "" {
+ executablePaths = append(executablePaths, dir)
+ dir, _ = filepath.Split(dir) // move up to the parent
+ if len(dir) > 0 {
+ // remove trailing slash
+ dir = dir[:len(dir)-1]
+ }
+ }
+ }
+ sort.Strings(readOnlyPaths)
+ sort.Strings(executablePaths)
+ sort.Strings(appSetDirs)
+
+ cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config")
+ builder := android.NewRuleBuilder(pctx, ctx)
+ cmd := builder.Command()
+ cmd.Text("(")
+ cmd.Text("echo '/ 1000 1000 0755';")
+ for _, p := range readOnlyPaths {
+ cmd.Textf("echo '/%s 1000 1000 0644';", p)
+ }
+ for _, p := range executablePaths {
+ cmd.Textf("echo '/%s 0 2000 0755';", p)
+ }
+ for _, dir := range appSetDirs {
+ cmd.Textf("echo '/%s 0 2000 0755';", dir)
+ file := appSetFiles[dir]
+ cmd.Text("zipinfo -1").Input(file).Textf(`| sed "s:\(.*\):/%s/\1 1000 1000 0644:";`, dir)
+ }
+ // Custom fs_config is "appended" to the last so that entries from the file are preferred
+ // over default ones set above.
+ if a.properties.Canned_fs_config != nil {
+ cmd.Text("cat").Input(android.PathForModuleSrc(ctx, *a.properties.Canned_fs_config))
+ }
+ cmd.Text(")").FlagWithOutput("> ", cannedFsConfig)
+ builder.Build("generateFsConfig", fmt.Sprintf("Generating canned fs config for %s", a.BaseModuleName()))
+
+ return cannedFsConfig.OutputPath
+}
diff --git a/apex/key.go b/apex/key.go
index 259060f..829410e 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -34,8 +34,6 @@
func registerApexKeyBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("apex_key", ApexKeyFactory)
ctx.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
-
- android.RegisterBp2BuildMutator("apex_key", ApexKeyBp2Build)
}
type apexKey struct {
@@ -209,20 +207,9 @@
Private_key bazel.LabelAttribute
}
-func ApexKeyBp2Build(ctx android.TopDownMutatorContext) {
- module, ok := ctx.Module().(*apexKey)
- if !ok {
- // Not an APEX key
- return
- }
- if !module.ConvertWithBp2build(ctx) {
- return
- }
- if ctx.ModuleType() != "apex_key" {
- return
- }
-
- apexKeyBp2BuildInternal(ctx, module)
+// ConvertWithBp2build performs conversion apexKey for bp2build
+func (m *apexKey) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ apexKeyBp2BuildInternal(ctx, m)
}
func apexKeyBp2BuildInternal(ctx android.TopDownMutatorContext, module *apexKey) {
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 84bdcdd..254c90e 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -965,7 +965,7 @@
a.installDir = android.PathForModuleInstall(ctx, "apex")
if a.installable() {
- ctx.InstallFile(a.installDir, a.installFilename, a.outputApex)
+ a.installedFile = ctx.InstallFile(a.installDir, a.installFilename, a.outputApex)
}
// in case that apex_set replaces source apex (using prefer: prop)
diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go
index 412fa0e..d037664 100644
--- a/apex/systemserver_classpath_fragment_test.go
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -231,3 +231,95 @@
`prebuilt_foo`,
})
}
+
+func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithSystemserverclasspathFragment,
+ prepareForTestWithMyapex,
+ dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo"),
+ ).RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ systemserverclasspath_fragments: [
+ "mysystemserverclasspathfragment",
+ ],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "foo",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ systemserverclasspath_fragment {
+ name: "mysystemserverclasspathfragment",
+ standalone_contents: [
+ "foo",
+ ],
+ apex_available: [
+ "myapex",
+ ],
+ }
+ `)
+
+ ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
+ "etc/classpaths/systemserverclasspath.pb",
+ "javalib/foo.jar",
+ })
+}
+
+func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithSystemserverclasspathFragment,
+ prepareForTestWithMyapex,
+ dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo"),
+ ).RunTestWithBp(t, `
+ prebuilt_apex {
+ name: "myapex",
+ arch: {
+ arm64: {
+ src: "myapex-arm64.apex",
+ },
+ arm: {
+ src: "myapex-arm.apex",
+ },
+ },
+ exported_systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
+ }
+
+ java_import {
+ name: "foo",
+ jars: ["foo.jar"],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ prebuilt_systemserverclasspath_fragment {
+ name: "mysystemserverclasspathfragment",
+ prefer: true,
+ standalone_contents: [
+ "foo",
+ ],
+ apex_available: [
+ "myapex",
+ ],
+ }
+ `)
+
+ java.CheckModuleDependencies(t, result.TestContext, "mysystemserverclasspathfragment", "android_common_myapex", []string{
+ `myapex.deapexer`,
+ `prebuilt_foo`,
+ })
+}
diff --git a/apex/vndk.go b/apex/vndk.go
index cf525a8..ef3e5e1 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -140,21 +140,5 @@
addSymlink("/apex/com.android.i18n/etc/icu", dir, "icu")
}
- // TODO(b/124106384): Clean up compat symlinks for ART binaries.
- if name == "com.android.art" {
- dir := android.PathForModuleInPartitionInstall(ctx, "system", "bin")
- addSymlink("/apex/com.android.art/bin/dalvikvm", dir, "dalvikvm")
- dex2oat := "dex2oat32"
- if ctx.Config().Android64() {
- dex2oat = "dex2oat64"
- }
- addSymlink("/apex/com.android.art/bin/"+dex2oat, dir, "dex2oat")
- } else if name == "com.android.art" || strings.HasPrefix(name, "com.android.art.") {
- dir := android.PathForModuleInPartitionInstall(ctx, "system", "bin")
- symlinks = append(symlinks,
- dir.Join(ctx, "dalvikvm"),
- dir.Join(ctx, "dex2oat"))
- }
-
return symlinks
}
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index 0bd71c6..41f9886 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -17,6 +17,7 @@
CcStaticLibraryFiles []string
Includes []string
SystemIncludes []string
+ Headers []string
// Archives owned by the current target (not by its dependencies). These will
// be a subset of OutputFiles. (or static libraries, this will be equal to OutputFiles,
// but general cc_library will also have dynamic libraries in output files).
@@ -105,6 +106,7 @@
includes = cc_info.compilation_context.includes.to_list()
system_includes = cc_info.compilation_context.system_includes.to_list()
+headers = [f.path for f in cc_info.compilation_context.headers.to_list()]
ccObjectFiles = []
staticLibraries = []
@@ -145,6 +147,7 @@
ccObjectFiles,
includes,
system_includes,
+ headers,
rootStaticArchives,
rootDynamicLibraries,
[toc_file]
@@ -161,7 +164,7 @@
var ccObjects []string
splitString := strings.Split(rawString, "|")
- if expectedLen := 8; len(splitString) != expectedLen {
+ if expectedLen := 9; len(splitString) != expectedLen {
return CcInfo{}, fmt.Errorf("Expected %d items, got %q", expectedLen, splitString)
}
outputFilesString := splitString[0]
@@ -172,15 +175,17 @@
ccObjects = splitOrEmpty(ccObjectsString, ", ")
includes := splitOrEmpty(splitString[3], ", ")
systemIncludes := splitOrEmpty(splitString[4], ", ")
- rootStaticArchives := splitOrEmpty(splitString[5], ", ")
- rootDynamicLibraries := splitOrEmpty(splitString[6], ", ")
- tocFile := splitString[7] // NOTE: Will be the empty string if there wasn't
+ headers := splitOrEmpty(splitString[5], ", ")
+ rootStaticArchives := splitOrEmpty(splitString[6], ", ")
+ rootDynamicLibraries := splitOrEmpty(splitString[7], ", ")
+ tocFile := splitString[8] // NOTE: Will be the empty string if there wasn't
return CcInfo{
OutputFiles: outputFiles,
CcObjectFiles: ccObjects,
CcStaticLibraryFiles: ccStaticLibraries,
Includes: includes,
SystemIncludes: systemIncludes,
+ Headers: headers,
RootStaticArchives: rootStaticArchives,
RootDynamicLibraries: rootDynamicLibraries,
TocFile: tocFile,
diff --git a/bazel/cquery/request_type_test.go b/bazel/cquery/request_type_test.go
index 34d0832..d3bcb45 100644
--- a/bazel/cquery/request_type_test.go
+++ b/bazel/cquery/request_type_test.go
@@ -71,13 +71,14 @@
}{
{
description: "no result",
- input: "|||||||",
+ input: "||||||||",
expectedOutput: CcInfo{
OutputFiles: []string{},
CcObjectFiles: []string{},
CcStaticLibraryFiles: []string{},
Includes: []string{},
SystemIncludes: []string{},
+ Headers: []string{},
RootStaticArchives: []string{},
RootDynamicLibraries: []string{},
TocFile: "",
@@ -85,13 +86,14 @@
},
{
description: "only output",
- input: "test|||||||",
+ input: "test||||||||",
expectedOutput: CcInfo{
OutputFiles: []string{"test"},
CcObjectFiles: []string{},
CcStaticLibraryFiles: []string{},
Includes: []string{},
SystemIncludes: []string{},
+ Headers: []string{},
RootStaticArchives: []string{},
RootDynamicLibraries: []string{},
TocFile: "",
@@ -99,13 +101,14 @@
},
{
description: "all items set",
- input: "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir|rootstaticarchive1|rootdynamiclibrary1|lib.so.toc",
+ input: "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir|dir/subdir/hdr.h|rootstaticarchive1|rootdynamiclibrary1|lib.so.toc",
expectedOutput: CcInfo{
OutputFiles: []string{"out1", "out2"},
CcObjectFiles: []string{"object1", "object2"},
CcStaticLibraryFiles: []string{"static_lib1", "static_lib2"},
Includes: []string{".", "dir/subdir"},
SystemIncludes: []string{"system/dir", "system/other/dir"},
+ Headers: []string{"dir/subdir/hdr.h"},
RootStaticArchives: []string{"rootstaticarchive1"},
RootDynamicLibraries: []string{"rootdynamiclibrary1"},
TocFile: "lib.so.toc",
@@ -115,13 +118,13 @@
description: "too few result splits",
input: "|",
expectedOutput: CcInfo{},
- expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 8, []string{"", ""}),
+ expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 9, []string{"", ""}),
},
{
description: "too many result splits",
- input: strings.Repeat("|", 8),
+ input: strings.Repeat("|", 50),
expectedOutput: CcInfo{},
- expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 8, make([]string, 9)),
+ expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 9, make([]string, 51)),
},
}
for _, tc := range testCases {
diff --git a/bazel/properties.go b/bazel/properties.go
index b370bbf..76be058 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -107,6 +107,14 @@
return dirs
}
+// Add inserts the label Label at the end of the LabelList.
+func (ll *LabelList) Add(label *Label) {
+ if label == nil {
+ return
+ }
+ ll.Includes = append(ll.Includes, *label)
+}
+
// Append appends the fields of other labelList to the corresponding fields of ll.
func (ll *LabelList) Append(other LabelList) {
if len(ll.Includes) > 0 || len(other.Includes) > 0 {
@@ -366,9 +374,23 @@
// labelListSelectValues supports config-specific label_list typed Bazel attribute values.
type labelListSelectValues map[string]LabelList
-func (ll labelListSelectValues) appendSelects(other labelListSelectValues) {
+func (ll labelListSelectValues) addSelects(label labelSelectValues) {
+ for k, v := range label {
+ if label == nil {
+ continue
+ }
+ l := ll[k]
+ (&l).Add(v)
+ ll[k] = l
+ }
+}
+
+func (ll labelListSelectValues) appendSelects(other labelListSelectValues, forceSpecifyEmptyList bool) {
for k, v := range other {
l := ll[k]
+ if forceSpecifyEmptyList && l.IsNil() && !v.IsNil() {
+ l.Includes = []Label{}
+ }
(&l).Append(v)
ll[k] = l
}
@@ -424,17 +446,22 @@
cll[axis][config] = list
}
-func (cll configurableLabelLists) Append(other configurableLabelLists) {
+func (cll configurableLabelLists) Append(other configurableLabelLists, forceSpecifyEmptyList bool) {
for axis, otherSelects := range other {
selects := cll[axis]
if selects == nil {
selects = make(labelListSelectValues, len(otherSelects))
}
- selects.appendSelects(otherSelects)
+ selects.appendSelects(otherSelects, forceSpecifyEmptyList)
cll[axis] = selects
}
}
+func (lla *LabelListAttribute) Clone() *LabelListAttribute {
+ result := &LabelListAttribute{ForceSpecifyEmptyList: lla.ForceSpecifyEmptyList}
+ return result.Append(*lla)
+}
+
// MakeLabelListAttribute initializes a LabelListAttribute with the non-arch specific value.
func MakeLabelListAttribute(value LabelList) LabelListAttribute {
return LabelListAttribute{
@@ -488,16 +515,37 @@
}
// Append all values, including os and arch specific ones, from another
-// LabelListAttribute to this LabelListAttribute.
-func (lla *LabelListAttribute) Append(other LabelListAttribute) {
- if lla.ForceSpecifyEmptyList && !other.Value.IsNil() {
+// LabelListAttribute to this LabelListAttribute. Returns this LabelListAttribute.
+func (lla *LabelListAttribute) Append(other LabelListAttribute) *LabelListAttribute {
+ forceSpecifyEmptyList := lla.ForceSpecifyEmptyList || other.ForceSpecifyEmptyList
+ if forceSpecifyEmptyList && lla.Value.IsNil() && !other.Value.IsNil() {
lla.Value.Includes = []Label{}
}
lla.Value.Append(other.Value)
if lla.ConfigurableValues == nil {
lla.ConfigurableValues = make(configurableLabelLists)
}
- lla.ConfigurableValues.Append(other.ConfigurableValues)
+ lla.ConfigurableValues.Append(other.ConfigurableValues, forceSpecifyEmptyList)
+ return lla
+}
+
+// Add inserts the labels for each axis of LabelAttribute at the end of corresponding axis's
+// LabelList within the LabelListAttribute
+func (lla *LabelListAttribute) Add(label *LabelAttribute) {
+ if label == nil {
+ return
+ }
+
+ lla.Value.Add(label.Value)
+ if lla.ConfigurableValues == nil && label.ConfigurableValues != nil {
+ lla.ConfigurableValues = make(configurableLabelLists)
+ }
+ for axis, _ := range label.ConfigurableValues {
+ if _, exists := lla.ConfigurableValues[axis]; !exists {
+ lla.ConfigurableValues[axis] = make(labelListSelectValues)
+ }
+ lla.ConfigurableValues[axis].addSelects(label.ConfigurableValues[axis])
+ }
}
// HasConfigurableValues returns true if the attribute contains axis-specific label list values.
@@ -566,7 +614,7 @@
// LabelMapper is a function that takes a OtherModuleContext and returns a (potentially changed)
// label and whether it was changed.
-type LabelMapper func(OtherModuleContext, string) (string, bool)
+type LabelMapper func(OtherModuleContext, Label) (string, bool)
// LabelPartition contains descriptions of a partition for labels
type LabelPartition struct {
@@ -588,7 +636,7 @@
// not.
func (lf LabelPartition) filter(ctx OtherModuleContext, label Label) *Label {
if lf.LabelMapper != nil {
- if newLabel, changed := lf.LabelMapper(ctx, label.Label); changed {
+ if newLabel, changed := lf.LabelMapper(ctx, label); changed {
return &Label{newLabel, label.OriginalModuleName}
}
}
@@ -757,12 +805,18 @@
// Append appends all values, including os and arch specific ones, from another
// StringListAttribute to this StringListAttribute
-func (sla *StringListAttribute) Append(other StringListAttribute) {
+func (sla *StringListAttribute) Append(other StringListAttribute) *StringListAttribute {
sla.Value = append(sla.Value, other.Value...)
if sla.ConfigurableValues == nil {
sla.ConfigurableValues = make(configurableStringLists)
}
sla.ConfigurableValues.Append(other.ConfigurableValues)
+ return sla
+}
+
+func (sla *StringListAttribute) Clone() *StringListAttribute {
+ result := &StringListAttribute{}
+ return result.Append(*sla)
}
// SetSelectValue set a value for a bazel select for the given axis, config and value.
diff --git a/bazel/properties_test.go b/bazel/properties_test.go
index 7a7d6f3..c7f9776 100644
--- a/bazel/properties_test.go
+++ b/bazel/properties_test.go
@@ -313,16 +313,16 @@
// labelAddSuffixForTypeMapper returns a LabelMapper that adds suffix to label name for modules of
// typ
func labelAddSuffixForTypeMapper(suffix, typ string) LabelMapper {
- return func(omc OtherModuleContext, label string) (string, bool) {
- m, ok := omc.ModuleFromName(label)
+ return func(omc OtherModuleContext, label Label) (string, bool) {
+ m, ok := omc.ModuleFromName(label.Label)
if !ok {
- return label, false
+ return label.Label, false
}
mTyp := omc.OtherModuleType(m)
if typ == mTyp {
- return label + suffix, true
+ return label.Label + suffix, true
}
- return label, false
+ return label.Label, false
}
}
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 9b66354..ae0fb11 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -19,6 +19,7 @@
deps: [
"soong-android",
"soong-android-soongconfig",
+ "soong-shared",
"soong-apex",
"soong-bazel",
"soong-cc",
@@ -27,18 +28,21 @@
"soong-genrule",
"soong-python",
"soong-sh",
+ "soong-ui-metrics",
],
testSrcs: [
"android_app_certificate_conversion_test.go",
+ "android_app_conversion_test.go",
"apex_conversion_test.go",
"apex_key_conversion_test.go",
"build_conversion_test.go",
"bzl_conversion_test.go",
+ "cc_binary_conversion_test.go",
"cc_genrule_conversion_test.go",
"cc_library_conversion_test.go",
"cc_library_headers_conversion_test.go",
- "cc_library_static_conversion_test.go",
"cc_library_shared_conversion_test.go",
+ "cc_library_static_conversion_test.go",
"cc_object_conversion_test.go",
"conversion_test.go",
"filegroup_conversion_test.go",
@@ -48,6 +52,7 @@
"python_binary_conversion_test.go",
"python_library_conversion_test.go",
"sh_conversion_test.go",
+ "soong_config_module_type_conversion_test.go",
"testing.go",
],
pluginFor: [
diff --git a/bp2build/android_app_certificate_conversion_test.go b/bp2build/android_app_certificate_conversion_test.go
index 6a53b00..035a352 100644
--- a/bp2build/android_app_certificate_conversion_test.go
+++ b/bp2build/android_app_certificate_conversion_test.go
@@ -31,11 +31,10 @@
func TestAndroidAppCertificateSimple(t *testing.T) {
runAndroidAppCertificateTestCase(t, bp2buildTestCase{
- description: "Android app certificate - simple example",
- moduleTypeUnderTest: "android_app_certificate",
- moduleTypeUnderTestFactory: java.AndroidAppCertificateFactory,
- moduleTypeUnderTestBp2BuildMutator: java.AndroidAppCertificateBp2Build,
- filesystem: map[string]string{},
+ description: "Android app certificate - simple example",
+ moduleTypeUnderTest: "android_app_certificate",
+ moduleTypeUnderTestFactory: java.AndroidAppCertificateFactory,
+ filesystem: map[string]string{},
blueprint: `
android_app_certificate {
name: "com.android.apogee.cert",
diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go
new file mode 100644
index 0000000..153817b
--- /dev/null
+++ b/bp2build/android_app_conversion_test.go
@@ -0,0 +1,90 @@
+// 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/java"
+
+ "testing"
+)
+
+func runAndroidAppTestCase(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
+ runBp2BuildTestCase(t, registerAndroidAppModuleTypes, tc)
+}
+
+func registerAndroidAppModuleTypes(ctx android.RegistrationContext) {
+}
+
+func TestMinimalAndroidApp(t *testing.T) {
+ runAndroidAppTestCase(t, bp2buildTestCase{
+ description: "Android app - simple example",
+ moduleTypeUnderTest: "android_app",
+ moduleTypeUnderTestFactory: java.AndroidAppFactory,
+ filesystem: map[string]string{
+ "app.java": "",
+ "res/res.png": "",
+ "AndroidManifest.xml": "",
+ },
+ blueprint: `
+android_app {
+ name: "TestApp",
+ srcs: ["app.java"],
+ sdk_version: "current",
+}
+`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("android_binary", "TestApp", attrNameToString{
+ "srcs": `["app.java"]`,
+ "manifest": `"AndroidManifest.xml"`,
+ "resource_files": `["res/res.png"]`,
+ }),
+ }})
+}
+
+func TestAndroidAppAllSupportedFields(t *testing.T) {
+ runAndroidAppTestCase(t, bp2buildTestCase{
+ description: "Android app - all supported fields",
+ moduleTypeUnderTest: "android_app",
+ moduleTypeUnderTestFactory: java.AndroidAppFactory,
+ filesystem: map[string]string{
+ "app.java": "",
+ "resa/res.png": "",
+ "resb/res.png": "",
+ "manifest/AndroidManifest.xml": "",
+ },
+ blueprint: `
+android_app {
+ name: "TestApp",
+ srcs: ["app.java"],
+ sdk_version: "current",
+ package_name: "com.google",
+ resource_dirs: ["resa", "resb"],
+ manifest: "manifest/AndroidManifest.xml",
+}
+`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("android_binary", "TestApp", attrNameToString{
+ "srcs": `["app.java"]`,
+ "manifest": `"manifest/AndroidManifest.xml"`,
+ "resource_files": `[
+ "resa/res.png",
+ "resb/res.png",
+ ]`,
+ "custom_package": `"com.google"`,
+ }),
+ }})
+}
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
index 1a23db7..a3825e6 100644
--- a/bp2build/apex_conversion_test.go
+++ b/bp2build/apex_conversion_test.go
@@ -19,6 +19,7 @@
"android/soong/apex"
"android/soong/cc"
"android/soong/java"
+ "android/soong/sh"
"testing"
)
@@ -32,6 +33,8 @@
// CC module types needed as they can be APEX dependencies
cc.RegisterCCBuildComponents(ctx)
+ ctx.RegisterModuleType("sh_binary", sh.ShBinaryFactory)
+ ctx.RegisterModuleType("cc_binary", cc.BinaryFactory)
ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
ctx.RegisterModuleType("apex_key", apex.ApexKeyFactory)
ctx.RegisterModuleType("android_app_certificate", java.AndroidAppCertificateFactory)
@@ -40,60 +43,62 @@
func TestApexBundleSimple(t *testing.T) {
runApexTestCase(t, bp2buildTestCase{
- description: "apex - simple example",
- moduleTypeUnderTest: "apex",
- moduleTypeUnderTestFactory: apex.BundleFactory,
- moduleTypeUnderTestBp2BuildMutator: apex.ApexBundleBp2Build,
- filesystem: map[string]string{},
+ description: "apex - example with all props",
+ moduleTypeUnderTest: "apex",
+ moduleTypeUnderTestFactory: apex.BundleFactory,
+ filesystem: map[string]string{},
blueprint: `
apex_key {
- name: "com.android.apogee.key",
- public_key: "com.android.apogee.avbpubkey",
- private_key: "com.android.apogee.pem",
+ name: "com.android.apogee.key",
+ public_key: "com.android.apogee.avbpubkey",
+ private_key: "com.android.apogee.pem",
bazel_module: { bp2build_available: false },
}
android_app_certificate {
- name: "com.android.apogee.certificate",
- certificate: "com.android.apogee",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "native_shared_lib_1",
+ name: "com.android.apogee.certificate",
+ certificate: "com.android.apogee",
bazel_module: { bp2build_available: false },
}
cc_library {
- name: "native_shared_lib_2",
+ name: "native_shared_lib_1",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "native_shared_lib_2",
bazel_module: { bp2build_available: false },
}
// TODO(b/194878861): Add bp2build support for prebuilt_etc
cc_library {
- name: "pretend_prebuilt_1",
- bazel_module: { bp2build_available: false },
+ name: "pretend_prebuilt_1",
+ bazel_module: { bp2build_available: false },
}
// TODO(b/194878861): Add bp2build support for prebuilt_etc
cc_library {
- name: "pretend_prebuilt_2",
- bazel_module: { bp2build_available: false },
+ name: "pretend_prebuilt_2",
+ bazel_module: { bp2build_available: false },
}
filegroup {
name: "com.android.apogee-file_contexts",
- srcs: [
- "com.android.apogee-file_contexts",
- ],
- bazel_module: { bp2build_available: false },
+ srcs: [
+ "com.android.apogee-file_contexts",
+ ],
+ bazel_module: { bp2build_available: false },
}
+cc_binary { name: "cc_binary_1", bazel_module: { bp2build_available: false } }
+sh_binary { name: "sh_binary_2", bazel_module: { bp2build_available: false } }
+
apex {
name: "com.android.apogee",
manifest: "apogee_manifest.json",
androidManifest: "ApogeeAndroidManifest.xml",
- file_contexts: "com.android.apogee-file_contexts",
+ file_contexts: "com.android.apogee-file_contexts",
min_sdk_version: "29",
key: "com.android.apogee.key",
certificate: "com.android.apogee.certificate",
@@ -104,8 +109,8 @@
"native_shared_lib_2",
],
binaries: [
- "binary_1",
- "binary_2",
+ "cc_binary_1",
+ "sh_binary_2",
],
prebuilts: [
"pretend_prebuilt_1",
@@ -117,8 +122,8 @@
makeBazelTarget("apex", "com.android.apogee", attrNameToString{
"android_manifest": `"ApogeeAndroidManifest.xml"`,
"binaries": `[
- "binary_1",
- "binary_2",
+ ":cc_binary_1",
+ ":sh_binary_2",
]`,
"certificate": `":com.android.apogee.certificate"`,
"file_contexts": `":com.android.apogee-file_contexts"`,
@@ -141,11 +146,10 @@
func TestApexBundleDefaultPropertyValues(t *testing.T) {
runApexTestCase(t, bp2buildTestCase{
- description: "apex - default property values",
- moduleTypeUnderTest: "apex",
- moduleTypeUnderTestFactory: apex.BundleFactory,
- moduleTypeUnderTestBp2BuildMutator: apex.ApexBundleBp2Build,
- filesystem: map[string]string{},
+ description: "apex - default property values",
+ moduleTypeUnderTest: "apex",
+ moduleTypeUnderTestFactory: apex.BundleFactory,
+ filesystem: map[string]string{},
blueprint: `
apex {
name: "com.android.apogee",
@@ -160,11 +164,10 @@
func TestApexBundleHasBazelModuleProps(t *testing.T) {
runApexTestCase(t, bp2buildTestCase{
- description: "apex - has bazel module props",
- moduleTypeUnderTest: "apex",
- moduleTypeUnderTestFactory: apex.BundleFactory,
- moduleTypeUnderTestBp2BuildMutator: apex.ApexBundleBp2Build,
- filesystem: map[string]string{},
+ description: "apex - has bazel module props",
+ moduleTypeUnderTest: "apex",
+ moduleTypeUnderTestFactory: apex.BundleFactory,
+ filesystem: map[string]string{},
blueprint: `
apex {
name: "apogee",
diff --git a/bp2build/apex_key_conversion_test.go b/bp2build/apex_key_conversion_test.go
index 17f79a6..1d949901 100644
--- a/bp2build/apex_key_conversion_test.go
+++ b/bp2build/apex_key_conversion_test.go
@@ -31,11 +31,10 @@
func TestApexKeySimple(t *testing.T) {
runApexKeyTestCase(t, bp2buildTestCase{
- description: "apex key - simple example",
- moduleTypeUnderTest: "apex_key",
- moduleTypeUnderTestFactory: apex.ApexKeyFactory,
- moduleTypeUnderTestBp2BuildMutator: apex.ApexKeyBp2Build,
- filesystem: map[string]string{},
+ description: "apex key - simple example",
+ moduleTypeUnderTest: "apex_key",
+ moduleTypeUnderTestFactory: apex.ApexKeyFactory,
+ filesystem: map[string]string{},
blueprint: `
apex_key {
name: "com.android.apogee.key",
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 10ee582..54b59af 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -259,7 +259,7 @@
// Simple metrics tracking for bp2build
metrics := CodegenMetrics{
- ruleClassCount: make(map[string]int),
+ ruleClassCount: make(map[string]uint64),
}
dirs := make(map[string]bool)
@@ -698,9 +698,9 @@
} else {
return true
}
- // Always print bools, if you want a bool attribute to be able to take the default value, use a
- // bool pointer instead
- case reflect.Bool:
+ // Always print bool/strings, if you want a bool/string attribute to be able to take the default value, use a
+ // pointer instead
+ case reflect.Bool, reflect.String:
return false
default:
if !value.IsValid() {
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 983604b..1440b6f 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -41,6 +41,7 @@
soong_module_deps = [
],
bool_prop = False,
+ string_prop = "",
)`,
},
{
@@ -58,6 +59,7 @@
soong_module_deps = [
],
bool_prop = True,
+ string_prop = "",
)`,
},
{
@@ -76,6 +78,7 @@
],
bool_prop = False,
owner = "a_string_with\"quotes\"_and_\\backslashes\\\\",
+ string_prop = "",
)`,
},
{
@@ -94,6 +97,7 @@
],
bool_prop = False,
required = ["bar"],
+ string_prop = "",
)`,
},
{
@@ -111,6 +115,7 @@
soong_module_deps = [
],
bool_prop = False,
+ string_prop = "",
target_required = [
"qux",
"bazqux",
@@ -147,6 +152,7 @@
"tag": ".bar",
"targets": ["goal_bar"],
}],
+ string_prop = "",
)`,
},
{
@@ -179,6 +185,7 @@
}],
owner = "custom_owner",
required = ["bar"],
+ string_prop = "",
target_required = [
"qux",
"bazqux",
@@ -223,11 +230,24 @@
func TestGenerateBazelTargetModules(t *testing.T) {
testCases := []bp2buildTestCase{
{
- description: "string props",
+ description: "string ptr props",
blueprint: `custom {
name: "foo",
+ string_ptr_prop: "",
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("custom", "foo", attrNameToString{
+ "string_ptr_prop": `""`,
+ }),
+ },
+ },
+ {
+ description: "string props",
+ blueprint: `custom {
+ name: "foo",
string_list_prop: ["a", "b"],
- string_prop: "a",
+ string_ptr_prop: "a",
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []string{
@@ -236,7 +256,7 @@
"a",
"b",
]`,
- "string_prop": `"a"`,
+ "string_ptr_prop": `"a"`,
}),
},
},
@@ -245,7 +265,7 @@
blueprint: `custom {
name: "foo",
string_list_prop: ["\t", "\n"],
- string_prop: "a\t\n\r",
+ string_ptr_prop: "a\t\n\r",
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []string{
@@ -254,7 +274,7 @@
"\t",
"\n",
]`,
- "string_prop": `"a\t\n\r"`,
+ "string_ptr_prop": `"a\t\n\r"`,
}),
},
},
@@ -450,7 +470,7 @@
android.FailIfErrored(t, err)
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
- t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount)
+ t.Errorf("Expected %d bazel target (%s),\ngot %d (%s)", expectedCount, testCase.expectedBazelTargets, actualCount, bazelTargets)
} else {
for i, expectedBazelTarget := range testCase.expectedBazelTargets {
actualBazelTarget := bazelTargets[i]
@@ -576,6 +596,7 @@
{
bp: `custom {
name: "bar",
+ one_to_many_prop: true,
bazel_module: { bp2build_available: true },
}`,
expectedBazelTarget: `my_library(
@@ -600,7 +621,6 @@
config := android.TestConfig(buildDir, nil, testCase.bp, nil)
ctx := android.NewTestContext(config)
ctx.RegisterModuleType("custom", customModuleFactory)
- ctx.RegisterBp2BuildMutator("custom", customBp2BuildMutatorFromStarlark)
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
@@ -638,10 +658,9 @@
func TestModuleTypeBp2Build(t *testing.T) {
testCases := []bp2buildTestCase{
{
- description: "filegroup with does not specify srcs",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "filegroup with does not specify srcs",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
blueprint: `filegroup {
name: "fg_foo",
bazel_module: { bp2build_available: true },
@@ -651,10 +670,9 @@
},
},
{
- description: "filegroup with no srcs",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "filegroup with no srcs",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
blueprint: `filegroup {
name: "fg_foo",
srcs: [],
@@ -665,10 +683,9 @@
},
},
{
- description: "filegroup with srcs",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "filegroup with srcs",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
blueprint: `filegroup {
name: "fg_foo",
srcs: ["a", "b"],
@@ -684,10 +701,9 @@
},
},
{
- description: "filegroup with excludes srcs",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "filegroup with excludes srcs",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
blueprint: `filegroup {
name: "fg_foo",
srcs: ["a", "b"],
@@ -701,10 +717,9 @@
},
},
{
- description: "filegroup with glob",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "filegroup with glob",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
blueprint: `filegroup {
name: "fg_foo",
srcs: ["**/*.txt"],
@@ -727,12 +742,10 @@
},
},
{
- description: "filegroup with glob in subdir",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
- blueprint: ``,
- dir: "other",
+ description: "filegroup with glob in subdir",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
+ dir: "other",
filesystem: map[string]string{
"other/Android.bp": `filegroup {
name: "fg_foo",
@@ -755,10 +768,9 @@
},
},
{
- description: "depends_on_other_dir_module",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "depends_on_other_dir_module",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
blueprint: `filegroup {
name: "fg_foo",
srcs: [
@@ -784,26 +796,25 @@
},
},
{
- description: "depends_on_other_unconverted_module_error",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
- unconvertedDepsMode: errorModulesUnconvertedDeps,
- filesystem: map[string]string{
- "other/Android.bp": `filegroup {
- name: "foo",
- srcs: ["a", "b"],
-}`,
- },
+ description: "depends_on_other_unconverted_module_error",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
+ unconvertedDepsMode: errorModulesUnconvertedDeps,
blueprint: `filegroup {
- name: "fg_foo",
+ name: "foobar",
srcs: [
":foo",
"c",
],
bazel_module: { bp2build_available: true },
}`,
- expectedErr: fmt.Errorf(`"fg_foo" depends on unconverted modules: foo`),
+ expectedErr: fmt.Errorf(`"foobar" depends on unconverted modules: foo`),
+ filesystem: map[string]string{
+ "other/Android.bp": `filegroup {
+ name: "foo",
+ srcs: ["a", "b"],
+}`,
+ },
},
}
@@ -818,18 +829,16 @@
func TestAllowlistingBp2buildTargetsExplicitly(t *testing.T) {
testCases := []struct {
- moduleTypeUnderTest string
- moduleTypeUnderTestFactory android.ModuleFactory
- moduleTypeUnderTestBp2BuildMutator bp2buildMutator
- bp string
- expectedCount int
- description string
+ moduleTypeUnderTest string
+ moduleTypeUnderTestFactory android.ModuleFactory
+ bp string
+ expectedCount int
+ description string
}{
{
- description: "explicitly unavailable",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "explicitly unavailable",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
bp: `filegroup {
name: "foo",
srcs: ["a", "b"],
@@ -838,10 +847,9 @@
expectedCount: 0,
},
{
- description: "implicitly unavailable",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "implicitly unavailable",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
bp: `filegroup {
name: "foo",
srcs: ["a", "b"],
@@ -849,10 +857,9 @@
expectedCount: 0,
},
{
- description: "explicitly available",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "explicitly available",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
bp: `filegroup {
name: "foo",
srcs: ["a", "b"],
@@ -861,12 +868,12 @@
expectedCount: 1,
},
{
- description: "generates more than 1 target if needed",
- moduleTypeUnderTest: "custom",
- moduleTypeUnderTestFactory: customModuleFactory,
- moduleTypeUnderTestBp2BuildMutator: customBp2BuildMutatorFromStarlark,
+ description: "generates more than 1 target if needed",
+ moduleTypeUnderTest: "custom",
+ moduleTypeUnderTestFactory: customModuleFactory,
bp: `custom {
name: "foo",
+ one_to_many_prop: true,
bazel_module: { bp2build_available: true },
}`,
expectedCount: 3,
@@ -879,7 +886,6 @@
config := android.TestConfig(buildDir, nil, testCase.bp, nil)
ctx := android.NewTestContext(config)
ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
- ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
@@ -899,20 +905,18 @@
func TestAllowlistingBp2buildTargetsWithConfig(t *testing.T) {
testCases := []struct {
- moduleTypeUnderTest string
- moduleTypeUnderTestFactory android.ModuleFactory
- moduleTypeUnderTestBp2BuildMutator bp2buildMutator
- expectedCount map[string]int
- description string
- bp2buildConfig android.Bp2BuildConfig
- checkDir string
- fs map[string]string
+ moduleTypeUnderTest string
+ moduleTypeUnderTestFactory android.ModuleFactory
+ expectedCount map[string]int
+ description string
+ bp2buildConfig android.Bp2BuildConfig
+ checkDir string
+ fs map[string]string
}{
{
- description: "test bp2build config package and subpackages config",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "test bp2build config package and subpackages config",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
expectedCount: map[string]int{
"migrated": 1,
"migrated/but_not_really": 0,
@@ -934,10 +938,9 @@
},
},
{
- description: "test bp2build config opt-in and opt-out",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "test bp2build config opt-in and opt-out",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
expectedCount: map[string]int{
"package-opt-in": 2,
"package-opt-in/subpackage": 0,
@@ -988,7 +991,6 @@
config := android.TestConfig(buildDir, nil, "", fs)
ctx := android.NewTestContext(config)
ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
- ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
ctx.RegisterBp2BuildConfig(testCase.bp2buildConfig)
ctx.RegisterForBazelConversion()
@@ -1019,10 +1021,9 @@
func TestCombineBuildFilesBp2buildTargets(t *testing.T) {
testCases := []bp2buildTestCase{
{
- description: "filegroup bazel_module.label",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "filegroup bazel_module.label",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
blueprint: `filegroup {
name: "fg_foo",
bazel_module: { label: "//other:fg_foo" },
@@ -1035,19 +1036,18 @@
},
},
{
- description: "multiple bazel_module.label same BUILD",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "multiple bazel_module.label same BUILD",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
blueprint: `filegroup {
- name: "fg_foo",
- bazel_module: { label: "//other:fg_foo" },
- }
+ name: "fg_foo",
+ bazel_module: { label: "//other:fg_foo" },
+ }
- filegroup {
- name: "foo",
- bazel_module: { label: "//other:foo" },
- }`,
+ filegroup {
+ name: "foo",
+ bazel_module: { label: "//other:foo" },
+ }`,
expectedBazelTargets: []string{
`// BUILD file`,
},
@@ -1056,25 +1056,24 @@
},
},
{
- description: "filegroup bazel_module.label and bp2build in subdir",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
- dir: "other",
- blueprint: ``,
+ description: "filegroup bazel_module.label and bp2build in subdir",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
+ dir: "other",
+ blueprint: ``,
filesystem: map[string]string{
"other/Android.bp": `filegroup {
- name: "fg_foo",
- bazel_module: {
- bp2build_available: true,
- },
- }
- filegroup {
- name: "fg_bar",
- bazel_module: {
- label: "//other:fg_bar"
- },
- }`,
+ name: "fg_foo",
+ bazel_module: {
+ bp2build_available: true,
+ },
+ }
+ filegroup {
+ name: "fg_bar",
+ bazel_module: {
+ label: "//other:fg_bar"
+ },
+ }`,
"other/BUILD.bazel": `// definition for fg_bar`,
},
expectedBazelTargets: []string{
@@ -1083,26 +1082,26 @@
},
},
{
- description: "filegroup bazel_module.label and filegroup bp2build",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "filegroup bazel_module.label and filegroup bp2build",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
+
filesystem: map[string]string{
"other/BUILD.bazel": `// BUILD file`,
},
blueprint: `filegroup {
- name: "fg_foo",
- bazel_module: {
- label: "//other:fg_foo",
- },
- }
+ name: "fg_foo",
+ bazel_module: {
+ label: "//other:fg_foo",
+ },
+ }
- filegroup {
- name: "fg_bar",
- bazel_module: {
- bp2build_available: true,
- },
- }`,
+ filegroup {
+ name: "fg_bar",
+ bazel_module: {
+ bp2build_available: true,
+ },
+ }`,
expectedBazelTargets: []string{
makeBazelTarget("filegroup", "fg_bar", map[string]string{}),
`// BUILD file`,
@@ -1126,7 +1125,6 @@
config := android.TestConfig(buildDir, nil, testCase.blueprint, fs)
ctx := android.NewTestContext(config)
ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
- ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, toParse)
@@ -1172,10 +1170,9 @@
func TestGlobExcludeSrcs(t *testing.T) {
testCases := []bp2buildTestCase{
{
- description: "filegroup top level exclude_srcs",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "filegroup top level exclude_srcs",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
blueprint: `filegroup {
name: "fg_foo",
srcs: ["**/*.txt"],
@@ -1202,12 +1199,11 @@
},
},
{
- description: "filegroup in subdir exclude_srcs",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
- blueprint: "",
- dir: "dir",
+ description: "filegroup in subdir exclude_srcs",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
+ blueprint: "",
+ dir: "dir",
filesystem: map[string]string{
"dir/Android.bp": `filegroup {
name: "fg_foo",
@@ -1244,10 +1240,9 @@
func TestCommonBp2BuildModuleAttrs(t *testing.T) {
testCases := []bp2buildTestCase{
{
- description: "Required into data test",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "Required into data test",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + `
filegroup {
name: "fg_foo",
@@ -1261,21 +1256,20 @@
},
},
{
- description: "Required via arch into data test",
- moduleTypeUnderTest: "python_library",
- moduleTypeUnderTestFactory: python.PythonLibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: python.PythonLibraryBp2Build,
+ description: "Required via arch into data test",
+ moduleTypeUnderTest: "python_library",
+ moduleTypeUnderTestFactory: python.PythonLibraryFactory,
blueprint: simpleModuleDoNotConvertBp2build("python_library", "reqdx86") +
simpleModuleDoNotConvertBp2build("python_library", "reqdarm") + `
python_library {
name: "fg_foo",
arch: {
- arm: {
- required: ["reqdarm"],
- },
- x86: {
- required: ["reqdx86"],
- },
+ arm: {
+ required: ["reqdarm"],
+ },
+ x86: {
+ required: ["reqdx86"],
+ },
},
bazel_module: { bp2build_available: true },
}`,
@@ -1291,10 +1285,9 @@
},
},
{
- description: "Required appended to data test",
- moduleTypeUnderTest: "python_library",
- moduleTypeUnderTestFactory: python.PythonLibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: python.PythonLibraryBp2Build,
+ description: "Required appended to data test",
+ moduleTypeUnderTest: "python_library",
+ moduleTypeUnderTestFactory: python.PythonLibraryFactory,
filesystem: map[string]string{
"data.bin": "",
"src.py": "",
@@ -1317,10 +1310,9 @@
},
},
{
- description: "All props-to-attrs at once together test",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+ description: "All props-to-attrs at once together test",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + `
filegroup {
name: "fg_foo",
diff --git a/bp2build/bzl_conversion_test.go b/bp2build/bzl_conversion_test.go
index 1e78c0e..f3345a6 100644
--- a/bp2build/bzl_conversion_test.go
+++ b/bp2build/bzl_conversion_test.go
@@ -100,6 +100,7 @@
# nested_props_ptr start
# "nested_prop": attr.string(),
# nested_props_ptr end
+ "one_to_many_prop": attr.bool(),
"other_embedded_prop": attr.string(),
"string_list_prop": attr.string_list(),
"string_prop": attr.string(),
@@ -128,6 +129,7 @@
# nested_props_ptr start
# "nested_prop": attr.string(),
# nested_props_ptr end
+ "one_to_many_prop": attr.bool(),
"other_embedded_prop": attr.string(),
"string_list_prop": attr.string_list(),
"string_prop": attr.string(),
@@ -156,6 +158,7 @@
# nested_props_ptr start
# "nested_prop": attr.string(),
# nested_props_ptr end
+ "one_to_many_prop": attr.bool(),
"other_embedded_prop": attr.string(),
"string_list_prop": attr.string_list(),
"string_prop": attr.string(),
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index f9abcba..a156480 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -24,8 +24,7 @@
)
const (
- ccBinaryTypePlaceHolder = "{rule_name}"
- compatibleWithPlaceHolder = "{target_compatible_with}"
+ ccBinaryTypePlaceHolder = "{rule_name}"
)
type testBazelTarget struct {
@@ -69,14 +68,14 @@
t.Helper()
moduleTypeUnderTest := "cc_binary"
testCase := bp2buildTestCase{
- expectedBazelTargets: generateBazelTargetsForTest(tc.targets),
- moduleTypeUnderTest: moduleTypeUnderTest,
- moduleTypeUnderTestFactory: cc.BinaryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.BinaryBp2build,
- description: fmt.Sprintf("%s %s", moduleTypeUnderTest, tc.description),
- blueprint: binaryReplacer.Replace(tc.blueprint),
+ expectedBazelTargets: generateBazelTargetsForTest(tc.targets),
+ moduleTypeUnderTest: moduleTypeUnderTest,
+ moduleTypeUnderTestFactory: cc.BinaryFactory,
+ description: fmt.Sprintf("%s %s", moduleTypeUnderTest, tc.description),
+ blueprint: binaryReplacer.Replace(tc.blueprint),
}
t.Run(testCase.description, func(t *testing.T) {
+ t.Helper()
runBp2BuildTestCase(t, registerCcBinaryModuleTypes, testCase)
})
}
@@ -84,22 +83,24 @@
func runCcHostBinaryTestCase(t *testing.T, tc ccBinaryBp2buildTestCase) {
t.Helper()
testCase := tc
- for i, t := range testCase.targets {
- t.attrs["target_compatible_with"] = `select({
+ for i, tar := range testCase.targets {
+ if tar.typ != "cc_binary" {
+ continue
+ }
+ tar.attrs["target_compatible_with"] = `select({
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
"//conditions:default": [],
})`
- testCase.targets[i] = t
+ testCase.targets[i] = tar
}
moduleTypeUnderTest := "cc_binary_host"
t.Run(testCase.description, func(t *testing.T) {
runBp2BuildTestCase(t, registerCcBinaryModuleTypes, bp2buildTestCase{
- expectedBazelTargets: generateBazelTargetsForTest(testCase.targets),
- moduleTypeUnderTest: moduleTypeUnderTest,
- moduleTypeUnderTestFactory: cc.BinaryHostFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.BinaryHostBp2build,
- description: fmt.Sprintf("%s %s", moduleTypeUnderTest, tc.description),
- blueprint: hostBinaryReplacer.Replace(testCase.blueprint),
+ expectedBazelTargets: generateBazelTargetsForTest(testCase.targets),
+ moduleTypeUnderTest: moduleTypeUnderTest,
+ moduleTypeUnderTestFactory: cc.BinaryHostFactory,
+ description: fmt.Sprintf("%s %s", moduleTypeUnderTest, tc.description),
+ blueprint: hostBinaryReplacer.Replace(testCase.blueprint),
})
})
}
@@ -256,11 +257,13 @@
genrule {
name: "generated_hdr",
cmd: "nothing to see here",
+ bazel_module: { bp2build_available: false },
}
genrule {
name: "export_generated_hdr",
cmd: "nothing to see here",
+ bazel_module: { bp2build_available: false },
}
{rule_name} {
@@ -301,6 +304,7 @@
":not_explicitly_exported_whole_static_dep",
":whole_static_dep",
]`,
+ "local_includes": `["."]`,
},
},
},
@@ -448,3 +452,51 @@
})
}
}
+
+func TestCcBinarySharedProto(t *testing.T) {
+ runCcBinaryTests(t, ccBinaryBp2buildTestCase{
+ blueprint: soongCcProtoLibraries + `{rule_name} {
+ name: "foo",
+ srcs: ["foo.proto"],
+ proto: {
+ canonical_path_from_root: false,
+ },
+ include_build_directory: false,
+}`,
+ targets: []testBazelTarget{
+ {"proto_library", "foo_proto", attrNameToString{
+ "srcs": `["foo.proto"]`,
+ }}, {"cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
+ "deps": `[":foo_proto"]`,
+ }}, {"cc_binary", "foo", attrNameToString{
+ "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ "whole_archive_deps": `[":foo_cc_proto_lite"]`,
+ }},
+ },
+ })
+}
+
+func TestCcBinaryStaticProto(t *testing.T) {
+ runCcBinaryTests(t, ccBinaryBp2buildTestCase{
+ blueprint: soongCcProtoLibraries + `{rule_name} {
+ name: "foo",
+ srcs: ["foo.proto"],
+ static_executable: true,
+ proto: {
+ canonical_path_from_root: false,
+ },
+ include_build_directory: false,
+}`,
+ targets: []testBazelTarget{
+ {"proto_library", "foo_proto", attrNameToString{
+ "srcs": `["foo.proto"]`,
+ }}, {"cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
+ "deps": `[":foo_proto"]`,
+ }}, {"cc_binary", "foo", attrNameToString{
+ "deps": `[":libprotobuf-cpp-lite"]`,
+ "whole_archive_deps": `[":foo_cc_proto_lite"]`,
+ "linkshared": `False`,
+ }},
+ },
+ })
+}
diff --git a/bp2build/cc_genrule_conversion_test.go b/bp2build/cc_genrule_conversion_test.go
index b3624dd..440b462 100644
--- a/bp2build/cc_genrule_conversion_test.go
+++ b/bp2build/cc_genrule_conversion_test.go
@@ -19,7 +19,6 @@
"android/soong/android"
"android/soong/cc"
- "android/soong/genrule"
)
var otherCcGenruleBp = map[string]string{
@@ -41,7 +40,6 @@
t.Helper()
(&tc).moduleTypeUnderTest = "cc_genrule"
(&tc).moduleTypeUnderTestFactory = cc.GenRuleFactory
- (&tc).moduleTypeUnderTestBp2BuildMutator = genrule.CcGenruleBp2Build
runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index a3d902a..b4eb28f 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -39,6 +39,19 @@
native_bridge_supported: true,
src: "",
}`
+
+ soongCcProtoLibraries = `
+cc_library {
+ name: "libprotobuf-cpp-lite",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "libprotobuf-cpp-full",
+ bazel_module: { bp2build_available: false },
+}`
+
+ soongCcProtoPreamble = soongCcLibraryPreamble + soongCcProtoLibraries
)
func runCcLibraryTestCase(t *testing.T, tc bp2buildTestCase) {
@@ -57,10 +70,9 @@
func TestCcLibrarySimple(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library - simple example",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library - simple example",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
filesystem: map[string]string{
"android.cpp": "",
"bionic.cpp": "",
@@ -117,17 +129,16 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "foo-lib", attrNameToString{
- "copts": `["-Wall"]`,
- "export_includes": `["foo-dir"]`,
- "implementation_deps": `[":some-headers"]`,
- "linkopts": `["-Wl,--exclude-libs=bar.a"] + select({
+ expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
+ "copts": `["-Wall"]`,
+ "export_includes": `["foo-dir"]`,
+ "implementation_deps": `[":some-headers"]`,
+ "linkopts": `["-Wl,--exclude-libs=bar.a"] + select({
"//build/bazel/platforms/arch:x86": ["-Wl,--exclude-libs=baz.a"],
"//build/bazel/platforms/arch:x86_64": ["-Wl,--exclude-libs=qux.a"],
"//conditions:default": [],
})`,
- "srcs": `["impl.cpp"] + select({
+ "srcs": `["impl.cpp"] + select({
"//build/bazel/platforms/arch:x86": ["x86.cpp"],
"//build/bazel/platforms/arch:x86_64": ["x86_64.cpp"],
"//conditions:default": [],
@@ -141,17 +152,15 @@
"//build/bazel/platforms/os:linux_bionic": ["bionic.cpp"],
"//conditions:default": [],
})`,
- }),
- },
+ }),
})
}
func TestCcLibraryTrimmedLdAndroid(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library - trimmed example of //bionic/linker:ld-android",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library - trimmed example of //bionic/linker:ld-android",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
filesystem: map[string]string{
"ld-android.cpp": "",
"linked_list.h": "",
@@ -159,8 +168,8 @@
"linker_block_allocator.h": "",
"linker_cfi.h": "",
},
- blueprint: soongCcLibraryPreamble + `
-cc_library_headers { name: "libc_headers" }
+ blueprint: soongCcLibraryPreamble +
+ simpleModuleDoNotConvertBp2build("cc_library_headers", "libc_headers") + `
cc_library {
name: "fake-ld-android",
srcs: ["ld_android.cpp"],
@@ -190,17 +199,16 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "fake-ld-android", attrNameToString{
- "srcs": `["ld_android.cpp"]`,
- "copts": `[
+ expectedBazelTargets: makeCcLibraryTargets("fake-ld-android", attrNameToString{
+ "srcs": `["ld_android.cpp"]`,
+ "copts": `[
"-Wall",
"-Wextra",
"-Wunused",
"-Werror",
]`,
- "implementation_deps": `[":libc_headers"]`,
- "linkopts": `[
+ "implementation_deps": `[":libc_headers"]`,
+ "linkopts": `[
"-Wl,--exclude-libs=libgcc.a",
"-Wl,--exclude-libs=libgcc_stripped.a",
"-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
@@ -212,18 +220,16 @@
"//build/bazel/platforms/arch:x86_64": ["-Wl,--exclude-libs=libgcc_eh.a"],
"//conditions:default": [],
})`,
- }),
- },
+ }),
})
}
func TestCcLibraryExcludeSrcs(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library exclude_srcs - trimmed example of //external/arm-optimized-routines:libarm-optimized-routines-math",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
- dir: "external",
+ description: "cc_library exclude_srcs - trimmed example of //external/arm-optimized-routines:libarm-optimized-routines-math",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ dir: "external",
filesystem: map[string]string{
"external/math/cosf.c": "",
"external/math/erf.c": "",
@@ -258,25 +264,22 @@
`,
},
blueprint: soongCcLibraryPreamble,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "fake-libarm-optimized-routines-math", attrNameToString{
- "copts": `select({
+ expectedBazelTargets: makeCcLibraryTargets("fake-libarm-optimized-routines-math", attrNameToString{
+ "copts": `select({
"//build/bazel/platforms/arch:arm64": ["-DHAVE_FAST_FMA=1"],
"//conditions:default": [],
})`,
- "local_includes": `["."]`,
- "srcs_c": `["math/cosf.c"]`,
- }),
- },
+ "local_includes": `["."]`,
+ "srcs_c": `["math/cosf.c"]`,
+ }),
})
}
func TestCcLibrarySharedStaticProps(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library shared/static props",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library shared/static props",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
filesystem: map[string]string{
"both.cpp": "",
"sharedonly.cpp": "",
@@ -353,26 +356,48 @@
}
`,
expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "a", attrNameToString{
- "copts": `["bothflag"]`,
- "implementation_deps": `[":static_dep_for_both"]`,
- "implementation_dynamic_deps": `[":shared_dep_for_both"]`,
- "shared": `{
- "copts": ["sharedflag"],
- "implementation_deps": [":static_dep_for_shared"],
- "implementation_dynamic_deps": [":shared_dep_for_shared"],
- "srcs": ["sharedonly.cpp"],
- "whole_archive_deps": [":whole_static_lib_for_shared"],
- }`,
- "srcs": `["both.cpp"]`,
- "static": `{
- "copts": ["staticflag"],
- "implementation_deps": [":static_dep_for_static"],
- "implementation_dynamic_deps": [":shared_dep_for_static"],
- "srcs": ["staticonly.cpp"],
- "whole_archive_deps": [":whole_static_lib_for_static"],
- }`,
- "whole_archive_deps": `[":whole_static_lib_for_both"]`,
+ makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{
+ "copts": `[
+ "bothflag",
+ "staticflag",
+ ]`,
+ "implementation_deps": `[
+ ":static_dep_for_both",
+ ":static_dep_for_static",
+ ]`,
+ "implementation_dynamic_deps": `[
+ ":shared_dep_for_both",
+ ":shared_dep_for_static",
+ ]`,
+ "srcs": `[
+ "both.cpp",
+ "staticonly.cpp",
+ ]`,
+ "whole_archive_deps": `[
+ ":whole_static_lib_for_both",
+ ":whole_static_lib_for_static",
+ ]`}),
+ makeBazelTarget("cc_library_shared", "a", attrNameToString{
+ "copts": `[
+ "bothflag",
+ "sharedflag",
+ ]`,
+ "implementation_deps": `[
+ ":static_dep_for_both",
+ ":static_dep_for_shared",
+ ]`,
+ "implementation_dynamic_deps": `[
+ ":shared_dep_for_both",
+ ":shared_dep_for_shared",
+ ]`,
+ "srcs": `[
+ "both.cpp",
+ "sharedonly.cpp",
+ ]`,
+ "whole_archive_deps": `[
+ ":whole_static_lib_for_both",
+ ":whole_static_lib_for_shared",
+ ]`,
}),
},
})
@@ -380,10 +405,9 @@
func TestCcLibraryDeps(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library shared/static props",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library shared/static props",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
filesystem: map[string]string{
"both.cpp": "",
"sharedonly.cpp": "",
@@ -438,52 +462,79 @@
simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_both") +
simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_both"),
expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "a", attrNameToString{
- "copts": `["bothflag"]`,
- "deps": `[":static_dep_for_both"]`,
- "dynamic_deps": `[":shared_dep_for_both"]`,
- "implementation_deps": `[":implementation_static_dep_for_both"]`,
- "implementation_dynamic_deps": `[":implementation_shared_dep_for_both"]`,
- "shared": `{
- "copts": ["sharedflag"],
- "deps": [":static_dep_for_shared"],
- "dynamic_deps": [":shared_dep_for_shared"],
- "implementation_deps": [":implementation_static_dep_for_shared"],
- "implementation_dynamic_deps": [":implementation_shared_dep_for_shared"],
- "srcs": ["sharedonly.cpp"],
- "whole_archive_deps": [
- ":not_explicitly_exported_whole_static_dep_for_shared",
- ":whole_static_dep_for_shared",
- ],
- }`,
- "srcs": `["both.cpp"]`,
- "static": `{
- "copts": ["staticflag"],
- "deps": [":static_dep_for_static"],
- "dynamic_deps": [":shared_dep_for_static"],
- "implementation_deps": [":implementation_static_dep_for_static"],
- "implementation_dynamic_deps": [":implementation_shared_dep_for_static"],
- "srcs": ["staticonly.cpp"],
- "whole_archive_deps": [
- ":not_explicitly_exported_whole_static_dep_for_static",
- ":whole_static_dep_for_static",
- ],
- }`,
+ makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{
+ "copts": `[
+ "bothflag",
+ "staticflag",
+ ]`,
+ "deps": `[
+ ":static_dep_for_both",
+ ":static_dep_for_static",
+ ]`,
+ "dynamic_deps": `[
+ ":shared_dep_for_both",
+ ":shared_dep_for_static",
+ ]`,
+ "implementation_deps": `[
+ ":implementation_static_dep_for_both",
+ ":implementation_static_dep_for_static",
+ ]`,
+ "implementation_dynamic_deps": `[
+ ":implementation_shared_dep_for_both",
+ ":implementation_shared_dep_for_static",
+ ]`,
+ "srcs": `[
+ "both.cpp",
+ "staticonly.cpp",
+ ]`,
"whole_archive_deps": `[
":not_explicitly_exported_whole_static_dep_for_both",
":whole_static_dep_for_both",
+ ":not_explicitly_exported_whole_static_dep_for_static",
+ ":whole_static_dep_for_static",
]`,
}),
- },
- })
+ makeBazelTarget("cc_library_shared", "a", attrNameToString{
+ "copts": `[
+ "bothflag",
+ "sharedflag",
+ ]`,
+ "deps": `[
+ ":static_dep_for_both",
+ ":static_dep_for_shared",
+ ]`,
+ "dynamic_deps": `[
+ ":shared_dep_for_both",
+ ":shared_dep_for_shared",
+ ]`,
+ "implementation_deps": `[
+ ":implementation_static_dep_for_both",
+ ":implementation_static_dep_for_shared",
+ ]`,
+ "implementation_dynamic_deps": `[
+ ":implementation_shared_dep_for_both",
+ ":implementation_shared_dep_for_shared",
+ ]`,
+ "srcs": `[
+ "both.cpp",
+ "sharedonly.cpp",
+ ]`,
+ "whole_archive_deps": `[
+ ":not_explicitly_exported_whole_static_dep_for_both",
+ ":whole_static_dep_for_both",
+ ":not_explicitly_exported_whole_static_dep_for_shared",
+ ":whole_static_dep_for_shared",
+ ]`,
+ })},
+ },
+ )
}
func TestCcLibraryWholeStaticLibsAlwaysLink(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
- dir: "foo/bar",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ dir: "foo/bar",
filesystem: map[string]string{
"foo/bar/Android.bp": `
cc_library {
@@ -508,26 +559,29 @@
},
blueprint: soongCcLibraryPreamble,
expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "a", attrNameToString{
- "shared": `{
- "whole_archive_deps": [":whole_static_lib_for_shared_alwayslink"],
- }`,
- "static": `{
- "whole_archive_deps": [":whole_static_lib_for_static_alwayslink"],
- }`,
- "whole_archive_deps": `[":whole_static_lib_for_both_alwayslink"]`,
+ makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{
+ "whole_archive_deps": `[
+ ":whole_static_lib_for_both_alwayslink",
+ ":whole_static_lib_for_static_alwayslink",
+ ]`,
+ }),
+ makeBazelTarget("cc_library_shared", "a", attrNameToString{
+ "whole_archive_deps": `[
+ ":whole_static_lib_for_both_alwayslink",
+ ":whole_static_lib_for_shared_alwayslink",
+ ]`,
}),
},
- })
+ },
+ )
}
func TestCcLibrarySharedStaticPropsInArch(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library shared/static props in arch",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
- dir: "foo/bar",
+ description: "cc_library shared/static props in arch",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ dir: "foo/bar",
filesystem: map[string]string{
"foo/bar/arm.cpp": "",
"foo/bar/x86.cpp": "",
@@ -599,71 +653,85 @@
},
blueprint: soongCcLibraryPreamble,
expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "a", attrNameToString{
- "copts": `["bothflag"]`,
- "implementation_deps": `[":static_dep_for_both"]`,
- "local_includes": `["."]`,
- "shared": `{
- "copts": ["sharedflag"] + select({
- "//build/bazel/platforms/arch:arm": ["-DARM_SHARED"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os:android": ["-DANDROID_SHARED"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os_arch:android_arm": ["-DANDROID_ARM_SHARED"],
- "//conditions:default": [],
- }),
- "implementation_deps": [":static_dep_for_shared"] + select({
- "//build/bazel/platforms/arch:arm": [":arm_static_dep_for_shared"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os:android": [":android_dep_for_shared"],
- "//conditions:default": [],
- }),
- "implementation_dynamic_deps": select({
- "//build/bazel/platforms/arch:arm": [":arm_shared_dep_for_shared"],
- "//conditions:default": [],
- }),
- "srcs": ["sharedonly.cpp"] + select({
- "//build/bazel/platforms/arch:arm": ["arm_shared.cpp"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os:android": ["android_shared.cpp"],
- "//conditions:default": [],
- }),
- "whole_archive_deps": select({
- "//build/bazel/platforms/arch:arm": [":arm_whole_static_dep_for_shared"],
- "//conditions:default": [],
- }),
- }`,
- "srcs": `["both.cpp"]`,
- "static": `{
- "copts": ["staticflag"] + select({
- "//build/bazel/platforms/arch:x86": ["-DX86_STATIC"],
- "//conditions:default": [],
- }),
- "implementation_deps": [":static_dep_for_static"] + select({
- "//build/bazel/platforms/arch:x86": [":x86_dep_for_static"],
- "//conditions:default": [],
- }),
- "srcs": ["staticonly.cpp"] + select({
- "//build/bazel/platforms/arch:x86": ["x86_static.cpp"],
- "//conditions:default": [],
- }),
- }`,
+ makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{
+ "copts": `[
+ "bothflag",
+ "staticflag",
+ ] + select({
+ "//build/bazel/platforms/arch:x86": ["-DX86_STATIC"],
+ "//conditions:default": [],
+ })`,
+ "implementation_deps": `[
+ ":static_dep_for_both",
+ ":static_dep_for_static",
+ ] + select({
+ "//build/bazel/platforms/arch:x86": [":x86_dep_for_static"],
+ "//conditions:default": [],
+ })`,
+ "local_includes": `["."]`,
+ "srcs": `[
+ "both.cpp",
+ "staticonly.cpp",
+ ] + select({
+ "//build/bazel/platforms/arch:x86": ["x86_static.cpp"],
+ "//conditions:default": [],
+ })`,
+ }),
+ makeBazelTarget("cc_library_shared", "a", attrNameToString{
+ "copts": `[
+ "bothflag",
+ "sharedflag",
+ ] + select({
+ "//build/bazel/platforms/arch:arm": ["-DARM_SHARED"],
+ "//conditions:default": [],
+ }) + select({
+ "//build/bazel/platforms/os:android": ["-DANDROID_SHARED"],
+ "//conditions:default": [],
+ }) + select({
+ "//build/bazel/platforms/os_arch:android_arm": ["-DANDROID_ARM_SHARED"],
+ "//conditions:default": [],
+ })`,
+ "implementation_deps": `[
+ ":static_dep_for_both",
+ ":static_dep_for_shared",
+ ] + select({
+ "//build/bazel/platforms/arch:arm": [":arm_static_dep_for_shared"],
+ "//conditions:default": [],
+ }) + select({
+ "//build/bazel/platforms/os:android": [":android_dep_for_shared"],
+ "//conditions:default": [],
+ })`,
+ "implementation_dynamic_deps": `select({
+ "//build/bazel/platforms/arch:arm": [":arm_shared_dep_for_shared"],
+ "//conditions:default": [],
+ })`,
+ "local_includes": `["."]`,
+ "srcs": `[
+ "both.cpp",
+ "sharedonly.cpp",
+ ] + select({
+ "//build/bazel/platforms/arch:arm": ["arm_shared.cpp"],
+ "//conditions:default": [],
+ }) + select({
+ "//build/bazel/platforms/os:android": ["android_shared.cpp"],
+ "//conditions:default": [],
+ })`,
+ "whole_archive_deps": `select({
+ "//build/bazel/platforms/arch:arm": [":arm_whole_static_dep_for_shared"],
+ "//conditions:default": [],
+ })`,
}),
},
- })
+ },
+ )
}
func TestCcLibrarySharedStaticPropsWithMixedSources(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library shared/static props with c/cpp/s mixed sources",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
- dir: "foo/bar",
+ description: "cc_library shared/static props with c/cpp/s mixed sources",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ dir: "foo/bar",
filesystem: map[string]string{
"foo/bar/both_source.cpp": "",
"foo/bar/both_source.cc": "",
@@ -738,66 +806,64 @@
},
blueprint: soongCcLibraryPreamble,
expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "a", attrNameToString{
+ makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", attrNameToString{
"local_includes": `["."]`,
- "shared": `{
- "srcs": [
- "shared_source.cpp",
- "shared_source.cc",
- ":shared_filegroup_cpp_srcs",
- ],
- "srcs_as": [
- "shared_source.s",
- "shared_source.S",
- ":shared_filegroup_as_srcs",
- ],
- "srcs_c": [
- "shared_source.c",
- ":shared_filegroup_c_srcs",
- ],
- }`,
"srcs": `[
"both_source.cpp",
"both_source.cc",
":both_filegroup_cpp_srcs",
+ "static_source.cpp",
+ "static_source.cc",
+ ":static_filegroup_cpp_srcs",
]`,
"srcs_as": `[
"both_source.s",
"both_source.S",
":both_filegroup_as_srcs",
+ "static_source.s",
+ "static_source.S",
+ ":static_filegroup_as_srcs",
]`,
"srcs_c": `[
"both_source.c",
":both_filegroup_c_srcs",
+ "static_source.c",
+ ":static_filegroup_c_srcs",
]`,
- "static": `{
- "srcs": [
- "static_source.cpp",
- "static_source.cc",
- ":static_filegroup_cpp_srcs",
- ],
- "srcs_as": [
- "static_source.s",
- "static_source.S",
- ":static_filegroup_as_srcs",
- ],
- "srcs_c": [
- "static_source.c",
- ":static_filegroup_c_srcs",
- ],
- }`,
}),
- },
- })
+ makeBazelTarget("cc_library_shared", "a", attrNameToString{
+ "local_includes": `["."]`,
+ "srcs": `[
+ "both_source.cpp",
+ "both_source.cc",
+ ":both_filegroup_cpp_srcs",
+ "shared_source.cpp",
+ "shared_source.cc",
+ ":shared_filegroup_cpp_srcs",
+ ]`,
+ "srcs_as": `[
+ "both_source.s",
+ "both_source.S",
+ ":both_filegroup_as_srcs",
+ "shared_source.s",
+ "shared_source.S",
+ ":shared_filegroup_as_srcs",
+ ]`,
+ "srcs_c": `[
+ "both_source.c",
+ ":both_filegroup_c_srcs",
+ "shared_source.c",
+ ":shared_filegroup_c_srcs",
+ ]`,
+ })}})
}
func TestCcLibraryNonConfiguredVersionScript(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library non-configured version script",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
- dir: "foo/bar",
+ description: "cc_library non-configured version script",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ dir: "foo/bar",
filesystem: map[string]string{
"foo/bar/Android.bp": `
cc_library {
@@ -810,23 +876,21 @@
`,
},
blueprint: soongCcLibraryPreamble,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "a", attrNameToString{
- "additional_linker_inputs": `["v.map"]`,
- "linkopts": `["-Wl,--version-script,$(location v.map)"]`,
- "srcs": `["a.cpp"]`,
- }),
- },
- })
+ expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{
+ "additional_linker_inputs": `["v.map"]`,
+ "linkopts": `["-Wl,--version-script,$(location v.map)"]`,
+ "srcs": `["a.cpp"]`,
+ }),
+ },
+ )
}
func TestCcLibraryConfiguredVersionScript(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library configured version script",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
- dir: "foo/bar",
+ description: "cc_library configured version script",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ dir: "foo/bar",
filesystem: map[string]string{
"foo/bar/Android.bp": `
cc_library {
@@ -847,30 +911,28 @@
`,
},
blueprint: soongCcLibraryPreamble,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "a", attrNameToString{
- "additional_linker_inputs": `select({
+ expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{
+ "additional_linker_inputs": `select({
"//build/bazel/platforms/arch:arm": ["arm.map"],
"//build/bazel/platforms/arch:arm64": ["arm64.map"],
"//conditions:default": [],
})`,
- "linkopts": `select({
+ "linkopts": `select({
"//build/bazel/platforms/arch:arm": ["-Wl,--version-script,$(location arm.map)"],
"//build/bazel/platforms/arch:arm64": ["-Wl,--version-script,$(location arm64.map)"],
"//conditions:default": [],
})`,
- "srcs": `["a.cpp"]`,
- }),
- },
- })
+ "srcs": `["a.cpp"]`,
+ }),
+ },
+ )
}
func TestCcLibrarySharedLibs(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library shared_libs",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library shared_libs",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcLibraryPreamble + `
cc_library {
name: "mylib",
@@ -883,20 +945,47 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "a", attrNameToString{
- "implementation_dynamic_deps": `[":mylib"]`,
- }),
- },
- })
+ expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{
+ "implementation_dynamic_deps": `[":mylib"]`,
+ }),
+ },
+ )
}
func TestCcLibraryFeatures(t *testing.T) {
+ expected_targets := []string{}
+ expected_targets = append(expected_targets, makeCcLibraryTargets("a", attrNameToString{
+ "features": `[
+ "disable_pack_relocations",
+ "-no_undefined_symbols",
+ ]`,
+ "srcs": `["a.cpp"]`,
+ })...)
+ expected_targets = append(expected_targets, makeCcLibraryTargets("b", attrNameToString{
+ "features": `select({
+ "//build/bazel/platforms/arch:x86_64": [
+ "disable_pack_relocations",
+ "-no_undefined_symbols",
+ ],
+ "//conditions:default": [],
+ })`,
+ "srcs": `["b.cpp"]`,
+ })...)
+ expected_targets = append(expected_targets, makeCcLibraryTargets("c", attrNameToString{
+ "features": `select({
+ "//build/bazel/platforms/os:darwin": [
+ "disable_pack_relocations",
+ "-no_undefined_symbols",
+ ],
+ "//conditions:default": [],
+ })`,
+ "srcs": `["c.cpp"]`,
+ })...)
+
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library pack_relocations test",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library pack_relocations test",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcLibraryPreamble + `
cc_library {
name: "a",
@@ -929,42 +1018,15 @@
},
include_build_directory: false,
}`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "a", attrNameToString{
- "features": `[
- "disable_pack_relocations",
- "-no_undefined_symbols",
- ]`,
- "srcs": `["a.cpp"]`,
- }), makeBazelTarget("cc_library", "b", attrNameToString{
- "features": `select({
- "//build/bazel/platforms/arch:x86_64": [
- "disable_pack_relocations",
- "-no_undefined_symbols",
- ],
- "//conditions:default": [],
- })`,
- "srcs": `["b.cpp"]`,
- }), makeBazelTarget("cc_library", "c", attrNameToString{
- "features": `select({
- "//build/bazel/platforms/os:darwin": [
- "disable_pack_relocations",
- "-no_undefined_symbols",
- ],
- "//conditions:default": [],
- })`,
- "srcs": `["c.cpp"]`,
- }),
- },
+ expectedBazelTargets: expected_targets,
})
}
func TestCcLibrarySpacesInCopts(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library spaces in copts",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library spaces in copts",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcLibraryPreamble + `
cc_library {
name: "a",
@@ -972,23 +1034,21 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "a", attrNameToString{
- "copts": `[
+ expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{
+ "copts": `[
"-include",
"header.h",
]`,
- }),
- },
- })
+ }),
+ },
+ )
}
func TestCcLibraryCppFlagsGoesIntoCopts(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library cppflags usage",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library cppflags usage",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcLibraryPreamble + `cc_library {
name: "a",
srcs: ["a.cpp"],
@@ -1010,10 +1070,9 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "a", attrNameToString{
- "copts": `["-Wall"]`,
- "cppflags": `[
+ expectedBazelTargets: makeCcLibraryTargets("a", attrNameToString{
+ "copts": `["-Wall"]`,
+ "cppflags": `[
"-fsigned-char",
"-pedantic",
] + select({
@@ -1023,18 +1082,17 @@
"//build/bazel/platforms/os:android": ["-DANDROID=1"],
"//conditions:default": [],
})`,
- "srcs": `["a.cpp"]`,
- }),
- },
- })
+ "srcs": `["a.cpp"]`,
+ }),
+ },
+ )
}
func TestCcLibraryExcludeLibs(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
- filesystem: map[string]string{},
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ filesystem: map[string]string{},
blueprint: soongCcLibraryStaticPreamble + `
cc_library {
name: "foo_static",
@@ -1109,41 +1167,39 @@
bazel_module: { bp2build_available: false },
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "foo_static", attrNameToString{
- "implementation_deps": `select({
+ expectedBazelTargets: makeCcLibraryTargets("foo_static", attrNameToString{
+ "implementation_deps": `select({
"//build/bazel/platforms/arch:arm": [],
"//conditions:default": [":arm_static_lib_excludes_bp2build_cc_library_static"],
}) + select({
"//build/bazel/product_variables:malloc_not_svelte": [],
"//conditions:default": [":malloc_not_svelte_static_lib_excludes_bp2build_cc_library_static"],
})`,
- "implementation_dynamic_deps": `select({
+ "implementation_dynamic_deps": `select({
"//build/bazel/platforms/arch:arm": [],
"//conditions:default": [":arm_shared_lib_excludes"],
}) + select({
"//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_shared_lib"],
"//conditions:default": [],
})`,
- "srcs_c": `["common.c"]`,
- "whole_archive_deps": `select({
+ "srcs_c": `["common.c"]`,
+ "whole_archive_deps": `select({
"//build/bazel/platforms/arch:arm": [],
"//conditions:default": [":arm_whole_static_lib_excludes_bp2build_cc_library_static"],
}) + select({
"//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_whole_static_lib_bp2build_cc_library_static"],
"//conditions:default": [":malloc_not_svelte_whole_static_lib_excludes_bp2build_cc_library_static"],
})`,
- }),
- },
- })
+ }),
+ },
+ )
}
func TestCCLibraryNoCrtTrue(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library - nocrt: true emits attribute",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library - nocrt: true emits attribute",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
filesystem: map[string]string{
"impl.cpp": "",
},
@@ -1155,21 +1211,19 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "foo-lib", attrNameToString{
- "link_crt": `False`,
- "srcs": `["impl.cpp"]`,
- }),
- },
- })
+ expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
+ "link_crt": `False`,
+ "srcs": `["impl.cpp"]`,
+ }),
+ },
+ )
}
func TestCCLibraryNoCrtFalse(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library - nocrt: false - does not emit attribute",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library - nocrt: false - does not emit attribute",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
filesystem: map[string]string{
"impl.cpp": "",
},
@@ -1181,20 +1235,17 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "foo-lib", attrNameToString{
- "srcs": `["impl.cpp"]`,
- }),
- },
+ expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
+ "srcs": `["impl.cpp"]`,
+ }),
})
}
func TestCCLibraryNoCrtArchVariant(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library - nocrt in select",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library - nocrt in select",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
filesystem: map[string]string{
"impl.cpp": "",
},
@@ -1219,15 +1270,12 @@
func TestCCLibraryNoLibCrtTrue(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library - simple example",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
filesystem: map[string]string{
"impl.cpp": "",
},
blueprint: soongCcLibraryPreamble + `
-cc_library_headers { name: "some-headers" }
cc_library {
name: "foo-lib",
srcs: ["impl.cpp"],
@@ -1235,24 +1283,45 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "foo-lib", attrNameToString{
- "srcs": `["impl.cpp"]`,
- "use_libcrt": `False`,
- }),
- }})
+ expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
+ "srcs": `["impl.cpp"]`,
+ "use_libcrt": `False`,
+ }),
+ })
+}
+
+func makeCcLibraryTargets(name string, attrs attrNameToString) []string {
+ STATIC_ONLY_ATTRS := map[string]bool{}
+ SHARED_ONLY_ATTRS := map[string]bool{
+ "link_crt": true,
+ "additional_linker_inputs": true,
+ "linkopts": true,
+ "strip": true,
+ }
+ sharedAttrs := attrNameToString{}
+ staticAttrs := attrNameToString{}
+ for key, val := range attrs {
+ if _, staticOnly := STATIC_ONLY_ATTRS[key]; !staticOnly {
+ sharedAttrs[key] = val
+ }
+ if _, sharedOnly := SHARED_ONLY_ATTRS[key]; !sharedOnly {
+ staticAttrs[key] = val
+ }
+ }
+ sharedTarget := makeBazelTarget("cc_library_shared", name, sharedAttrs)
+ staticTarget := makeBazelTarget("cc_library_static", name+"_bp2build_cc_library_static", staticAttrs)
+
+ return []string{staticTarget, sharedTarget}
}
func TestCCLibraryNoLibCrtFalse(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
filesystem: map[string]string{
"impl.cpp": "",
},
blueprint: soongCcLibraryPreamble + `
-cc_library_headers { name: "some-headers" }
cc_library {
name: "foo-lib",
srcs: ["impl.cpp"],
@@ -1260,19 +1329,17 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "foo-lib", attrNameToString{
- "srcs": `["impl.cpp"]`,
- "use_libcrt": `True`,
- }),
- }})
+ expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
+ "srcs": `["impl.cpp"]`,
+ "use_libcrt": `True`,
+ }),
+ })
}
func TestCCLibraryNoLibCrtArchVariant(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
filesystem: map[string]string{
"impl.cpp": "",
},
@@ -1291,24 +1358,50 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "foo-lib", attrNameToString{
- "srcs": `["impl.cpp"]`,
- "use_libcrt": `select({
+ expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
+ "srcs": `["impl.cpp"]`,
+ "use_libcrt": `select({
"//build/bazel/platforms/arch:arm": False,
"//build/bazel/platforms/arch:x86": False,
"//conditions:default": None,
})`,
- }),
- }})
+ }),
+ })
}
func TestCcLibraryStrip(t *testing.T) {
+ expectedTargets := []string{}
+ expectedTargets = append(expectedTargets, makeCcLibraryTargets("all", attrNameToString{
+ "strip": `{
+ "all": True,
+ }`,
+ })...)
+ expectedTargets = append(expectedTargets, makeCcLibraryTargets("keep_symbols", attrNameToString{
+ "strip": `{
+ "keep_symbols": True,
+ }`,
+ })...)
+ expectedTargets = append(expectedTargets, makeCcLibraryTargets("keep_symbols_and_debug_frame", attrNameToString{
+ "strip": `{
+ "keep_symbols_and_debug_frame": True,
+ }`,
+ })...)
+ expectedTargets = append(expectedTargets, makeCcLibraryTargets("keep_symbols_list", attrNameToString{
+ "strip": `{
+ "keep_symbols_list": ["symbol"],
+ }`,
+ })...)
+ expectedTargets = append(expectedTargets, makeCcLibraryTargets("none", attrNameToString{
+ "strip": `{
+ "none": True,
+ }`,
+ })...)
+ expectedTargets = append(expectedTargets, makeCcLibraryTargets("nothing", attrNameToString{})...)
+
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library strip args",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library strip args",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcLibraryPreamble + `
cc_library {
name: "nothing",
@@ -1350,38 +1443,15 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "all", attrNameToString{
- "strip": `{
- "all": True,
- }`,
- }), makeBazelTarget("cc_library", "keep_symbols", attrNameToString{
- "strip": `{
- "keep_symbols": True,
- }`,
- }), makeBazelTarget("cc_library", "keep_symbols_and_debug_frame", attrNameToString{
- "strip": `{
- "keep_symbols_and_debug_frame": True,
- }`,
- }), makeBazelTarget("cc_library", "keep_symbols_list", attrNameToString{
- "strip": `{
- "keep_symbols_list": ["symbol"],
- }`,
- }), makeBazelTarget("cc_library", "none", attrNameToString{
- "strip": `{
- "none": True,
- }`,
- }), makeBazelTarget("cc_library", "nothing", attrNameToString{}),
- },
+ expectedBazelTargets: expectedTargets,
})
}
func TestCcLibraryStripWithArch(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library strip args",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library strip args",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcLibraryPreamble + `
cc_library {
name: "multi-arch",
@@ -1407,9 +1477,8 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "multi-arch", attrNameToString{
- "strip": `{
+ expectedBazelTargets: makeCcLibraryTargets("multi-arch", attrNameToString{
+ "strip": `{
"keep_symbols": select({
"//build/bazel/platforms/arch:arm64": True,
"//conditions:default": None,
@@ -1426,17 +1495,16 @@
"//conditions:default": [],
}),
}`,
- }),
- },
- })
+ }),
+ },
+ )
}
func TestCcLibrary_SystemSharedLibsRootEmpty(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library system_shared_libs empty at root",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library system_shared_libs empty at root",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcLibraryPreamble + `
cc_library {
name: "root_empty",
@@ -1444,20 +1512,18 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "root_empty", attrNameToString{
- "system_dynamic_deps": `[]`,
- }),
- },
- })
+ expectedBazelTargets: makeCcLibraryTargets("root_empty", attrNameToString{
+ "system_dynamic_deps": `[]`,
+ }),
+ },
+ )
}
func TestCcLibrary_SystemSharedLibsStaticEmpty(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library system_shared_libs empty for static variant",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library system_shared_libs empty for static variant",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcLibraryPreamble + `
cc_library {
name: "static_empty",
@@ -1468,21 +1534,19 @@
}
`,
expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "static_empty", attrNameToString{
- "static": `{
- "system_dynamic_deps": [],
- }`,
+ makeBazelTarget("cc_library_static", "static_empty_bp2build_cc_library_static", attrNameToString{
+ "system_dynamic_deps": "[]",
}),
+ makeBazelTarget("cc_library_shared", "static_empty", attrNameToString{}),
},
})
}
func TestCcLibrary_SystemSharedLibsSharedEmpty(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library system_shared_libs empty for shared variant",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library system_shared_libs empty for shared variant",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcLibraryPreamble + `
cc_library {
name: "shared_empty",
@@ -1493,10 +1557,9 @@
}
`,
expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "shared_empty", attrNameToString{
- "shared": `{
- "system_dynamic_deps": [],
- }`,
+ makeBazelTarget("cc_library_static", "shared_empty_bp2build_cc_library_static", attrNameToString{}),
+ makeBazelTarget("cc_library_shared", "shared_empty", attrNameToString{
+ "system_dynamic_deps": "[]",
}),
},
})
@@ -1504,10 +1567,9 @@
func TestCcLibrary_SystemSharedLibsSharedBionicEmpty(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library system_shared_libs empty for shared, bionic variant",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library system_shared_libs empty for shared, bionic variant",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcLibraryPreamble + `
cc_library {
name: "shared_empty",
@@ -1522,10 +1584,9 @@
}
`,
expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "shared_empty", attrNameToString{
- "shared": `{
- "system_dynamic_deps": [],
- }`,
+ makeBazelTarget("cc_library_static", "shared_empty_bp2build_cc_library_static", attrNameToString{}),
+ makeBazelTarget("cc_library_shared", "shared_empty", attrNameToString{
+ "system_dynamic_deps": "[]",
}),
},
})
@@ -1537,10 +1598,9 @@
// only for linux_bionic, but `android` had `["libc", "libdl", "libm"].
// b/195791252 tracks the fix.
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library system_shared_libs empty for linux_bionic variant",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library system_shared_libs empty for linux_bionic variant",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcLibraryPreamble + `
cc_library {
name: "target_linux_bionic_empty",
@@ -1552,20 +1612,18 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "target_linux_bionic_empty", attrNameToString{
- "system_dynamic_deps": `[]`,
- }),
- },
- })
+ expectedBazelTargets: makeCcLibraryTargets("target_linux_bionic_empty", attrNameToString{
+ "system_dynamic_deps": `[]`,
+ }),
+ },
+ )
}
func TestCcLibrary_SystemSharedLibsBionicEmpty(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library system_shared_libs empty for bionic variant",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library system_shared_libs empty for bionic variant",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcLibraryPreamble + `
cc_library {
name: "target_bionic_empty",
@@ -1577,20 +1635,18 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "target_bionic_empty", attrNameToString{
- "system_dynamic_deps": `[]`,
- }),
- },
- })
+ expectedBazelTargets: makeCcLibraryTargets("target_bionic_empty", attrNameToString{
+ "system_dynamic_deps": `[]`,
+ }),
+ },
+ )
}
func TestCcLibrary_SystemSharedLibsSharedAndRoot(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library system_shared_libs set for shared and root",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ description: "cc_library system_shared_libs set for shared and root",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcLibraryPreamble + `
cc_library {
name: "libc",
@@ -1611,25 +1667,26 @@
}
`,
expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "foo", attrNameToString{
- "shared": `{
- "system_dynamic_deps": [":libm"],
- }`,
+ makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
"system_dynamic_deps": `[":libc"]`,
}),
+ makeBazelTarget("cc_library_shared", "foo", attrNameToString{
+ "system_dynamic_deps": `[
+ ":libc",
+ ":libm",
+ ]`,
+ }),
},
})
}
func TestCcLibraryOsSelects(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
- description: "cc_library - selects for all os targets",
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
- filesystem: map[string]string{},
+ description: "cc_library - selects for all os targets",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ filesystem: map[string]string{},
blueprint: soongCcLibraryPreamble + `
-cc_library_headers { name: "some-headers" }
cc_library {
name: "foo-lib",
srcs: ["base.cpp"],
@@ -1659,9 +1716,8 @@
include_build_directory: false,
}
`,
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "foo-lib", attrNameToString{
- "srcs": `["base.cpp"] + select({
+ expectedBazelTargets: makeCcLibraryTargets("foo-lib", attrNameToString{
+ "srcs": `["base.cpp"] + select({
"//build/bazel/platforms/os:android": [
"linux.cpp",
"bionic.cpp",
@@ -1683,16 +1739,18 @@
"//build/bazel/platforms/os:windows": ["windows.cpp"],
"//conditions:default": [],
})`,
- }),
- },
- })
+ }),
+ },
+ )
}
func TestCcLibraryCppStdWithGnuExtensions_ConvertsToFeatureAttr(t *testing.T) {
type testCase struct {
cpp_std string
+ c_std string
gnu_extensions string
bazel_cpp_std string
+ bazel_c_std string
}
testCases := []testCase{
@@ -1702,45 +1760,58 @@
// not set, only emit if gnu_extensions is disabled. the default (gnu+17
// is set in the toolchain.)
{cpp_std: "", gnu_extensions: "", bazel_cpp_std: ""},
- {cpp_std: "", gnu_extensions: "false", bazel_cpp_std: "c++17"},
+ {cpp_std: "", gnu_extensions: "false", bazel_cpp_std: "c++17", bazel_c_std: "c99"},
{cpp_std: "", gnu_extensions: "true", bazel_cpp_std: ""},
// experimental defaults to gnu++2a
{cpp_std: "experimental", gnu_extensions: "", bazel_cpp_std: "gnu++2a"},
- {cpp_std: "experimental", gnu_extensions: "false", bazel_cpp_std: "c++2a"},
+ {cpp_std: "experimental", gnu_extensions: "false", bazel_cpp_std: "c++2a", bazel_c_std: "c99"},
{cpp_std: "experimental", gnu_extensions: "true", bazel_cpp_std: "gnu++2a"},
// Explicitly setting a c++ std does not use replace gnu++ std even if
// gnu_extensions is true.
// "c++11",
{cpp_std: "c++11", gnu_extensions: "", bazel_cpp_std: "c++11"},
- {cpp_std: "c++11", gnu_extensions: "false", bazel_cpp_std: "c++11"},
+ {cpp_std: "c++11", gnu_extensions: "false", bazel_cpp_std: "c++11", bazel_c_std: "c99"},
{cpp_std: "c++11", gnu_extensions: "true", bazel_cpp_std: "c++11"},
// "c++17",
{cpp_std: "c++17", gnu_extensions: "", bazel_cpp_std: "c++17"},
- {cpp_std: "c++17", gnu_extensions: "false", bazel_cpp_std: "c++17"},
+ {cpp_std: "c++17", gnu_extensions: "false", bazel_cpp_std: "c++17", bazel_c_std: "c99"},
{cpp_std: "c++17", gnu_extensions: "true", bazel_cpp_std: "c++17"},
// "c++2a",
{cpp_std: "c++2a", gnu_extensions: "", bazel_cpp_std: "c++2a"},
- {cpp_std: "c++2a", gnu_extensions: "false", bazel_cpp_std: "c++2a"},
+ {cpp_std: "c++2a", gnu_extensions: "false", bazel_cpp_std: "c++2a", bazel_c_std: "c99"},
{cpp_std: "c++2a", gnu_extensions: "true", bazel_cpp_std: "c++2a"},
// "c++98",
{cpp_std: "c++98", gnu_extensions: "", bazel_cpp_std: "c++98"},
- {cpp_std: "c++98", gnu_extensions: "false", bazel_cpp_std: "c++98"},
+ {cpp_std: "c++98", gnu_extensions: "false", bazel_cpp_std: "c++98", bazel_c_std: "c99"},
{cpp_std: "c++98", gnu_extensions: "true", bazel_cpp_std: "c++98"},
// gnu++ is replaced with c++ if gnu_extensions is explicitly false.
// "gnu++11",
{cpp_std: "gnu++11", gnu_extensions: "", bazel_cpp_std: "gnu++11"},
- {cpp_std: "gnu++11", gnu_extensions: "false", bazel_cpp_std: "c++11"},
+ {cpp_std: "gnu++11", gnu_extensions: "false", bazel_cpp_std: "c++11", bazel_c_std: "c99"},
{cpp_std: "gnu++11", gnu_extensions: "true", bazel_cpp_std: "gnu++11"},
// "gnu++17",
{cpp_std: "gnu++17", gnu_extensions: "", bazel_cpp_std: "gnu++17"},
- {cpp_std: "gnu++17", gnu_extensions: "false", bazel_cpp_std: "c++17"},
+ {cpp_std: "gnu++17", gnu_extensions: "false", bazel_cpp_std: "c++17", bazel_c_std: "c99"},
{cpp_std: "gnu++17", gnu_extensions: "true", bazel_cpp_std: "gnu++17"},
+
+ // some c_std test cases
+ {c_std: "experimental", gnu_extensions: "", bazel_c_std: "gnu11"},
+ {c_std: "experimental", gnu_extensions: "false", bazel_cpp_std: "c++17", bazel_c_std: "c11"},
+ {c_std: "experimental", gnu_extensions: "true", bazel_c_std: "gnu11"},
+ {c_std: "gnu11", cpp_std: "gnu++17", gnu_extensions: "", bazel_cpp_std: "gnu++17", bazel_c_std: "gnu11"},
+ {c_std: "gnu11", cpp_std: "gnu++17", gnu_extensions: "false", bazel_cpp_std: "c++17", bazel_c_std: "c11"},
+ {c_std: "gnu11", cpp_std: "gnu++17", gnu_extensions: "true", bazel_cpp_std: "gnu++17", bazel_c_std: "gnu11"},
}
- for _, tc := range testCases {
+ for i, tc := range testCases {
+ name_prefix := fmt.Sprintf("a_%v", i)
cppStdProp := ""
if tc.cpp_std != "" {
cppStdProp = fmt.Sprintf(" cpp_std: \"%s\",", tc.cpp_std)
}
+ cStdProp := ""
+ if tc.c_std != "" {
+ cStdProp = fmt.Sprintf(" c_std: \"%s\",", tc.c_std)
+ }
gnuExtensionsProp := ""
if tc.gnu_extensions != "" {
gnuExtensionsProp = fmt.Sprintf(" gnu_extensions: %s,", tc.gnu_extensions)
@@ -1749,62 +1820,224 @@
if tc.bazel_cpp_std != "" {
attrs["cpp_std"] = fmt.Sprintf(`"%s"`, tc.bazel_cpp_std)
}
+ if tc.bazel_c_std != "" {
+ attrs["c_std"] = fmt.Sprintf(`"%s"`, tc.bazel_c_std)
+ }
runCcLibraryTestCase(t, bp2buildTestCase{
description: fmt.Sprintf(
"cc_library with cpp_std: %s and gnu_extensions: %s", tc.cpp_std, tc.gnu_extensions),
- moduleTypeUnderTest: "cc_library",
- moduleTypeUnderTestFactory: cc.LibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
blueprint: soongCcLibraryPreamble + fmt.Sprintf(`
cc_library {
- name: "a",
+ name: "%s_full",
%s // cpp_std: *string
+%s // c_std: *string
%s // gnu_extensions: *bool
include_build_directory: false,
}
-`, cppStdProp, gnuExtensionsProp),
- expectedBazelTargets: []string{
- makeBazelTarget("cc_library", "a", attrs),
- },
+`, name_prefix, cppStdProp, cStdProp, gnuExtensionsProp),
+ expectedBazelTargets: makeCcLibraryTargets(name_prefix+"_full", attrs),
})
runCcLibraryStaticTestCase(t, bp2buildTestCase{
description: fmt.Sprintf(
"cc_library_static with cpp_std: %s and gnu_extensions: %s", tc.cpp_std, tc.gnu_extensions),
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
blueprint: soongCcLibraryPreamble + fmt.Sprintf(`
cc_library_static {
- name: "a",
+ name: "%s_static",
%s // cpp_std: *string
+%s // c_std: *string
%s // gnu_extensions: *bool
include_build_directory: false,
}
-`, cppStdProp, gnuExtensionsProp),
+`, name_prefix, cppStdProp, cStdProp, gnuExtensionsProp),
expectedBazelTargets: []string{
- makeBazelTarget("cc_library_static", "a", attrs),
+ makeBazelTarget("cc_library_static", name_prefix+"_static", attrs),
},
})
runCcLibrarySharedTestCase(t, bp2buildTestCase{
description: fmt.Sprintf(
"cc_library_shared with cpp_std: %s and gnu_extensions: %s", tc.cpp_std, tc.gnu_extensions),
- moduleTypeUnderTest: "cc_library_shared",
- moduleTypeUnderTestFactory: cc.LibrarySharedFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibrarySharedBp2Build,
+ moduleTypeUnderTest: "cc_library_shared",
+ moduleTypeUnderTestFactory: cc.LibrarySharedFactory,
blueprint: soongCcLibraryPreamble + fmt.Sprintf(`
cc_library_shared {
- name: "a",
+ name: "%s_shared",
%s // cpp_std: *string
+%s // c_std: *string
%s // gnu_extensions: *bool
include_build_directory: false,
}
-`, cppStdProp, gnuExtensionsProp),
+`, name_prefix, cppStdProp, cStdProp, gnuExtensionsProp),
expectedBazelTargets: []string{
- makeBazelTarget("cc_library_shared", "a", attrs),
+ makeBazelTarget("cc_library_shared", name_prefix+"_shared", attrs),
},
})
}
}
+
+func TestCcLibraryProtoSimple(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ blueprint: soongCcProtoPreamble + `cc_library {
+ name: "foo",
+ srcs: ["foo.proto"],
+ include_build_directory: false,
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("proto_library", "foo_proto", attrNameToString{
+ "srcs": `["foo.proto"]`,
+ "strip_import_prefix": `""`,
+ }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
+ "deps": `[":foo_proto"]`,
+ }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
+ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
+ "deps": `[":libprotobuf-cpp-lite"]`,
+ }), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
+ "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryProtoNoCanonicalPathFromRoot(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ blueprint: soongCcProtoPreamble + `cc_library {
+ name: "foo",
+ srcs: ["foo.proto"],
+ proto: { canonical_path_from_root: false},
+ include_build_directory: false,
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("proto_library", "foo_proto", attrNameToString{
+ "srcs": `["foo.proto"]`,
+ }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
+ "deps": `[":foo_proto"]`,
+ }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
+ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
+ "deps": `[":libprotobuf-cpp-lite"]`,
+ }), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
+ "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryProtoExplicitCanonicalPathFromRoot(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ blueprint: soongCcProtoPreamble + `cc_library {
+ name: "foo",
+ srcs: ["foo.proto"],
+ proto: { canonical_path_from_root: true},
+ include_build_directory: false,
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("proto_library", "foo_proto", attrNameToString{
+ "srcs": `["foo.proto"]`,
+ "strip_import_prefix": `""`,
+ }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
+ "deps": `[":foo_proto"]`,
+ }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
+ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
+ "deps": `[":libprotobuf-cpp-lite"]`,
+ }), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
+ "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryProtoFull(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ blueprint: soongCcProtoPreamble + `cc_library {
+ name: "foo",
+ srcs: ["foo.proto"],
+ proto: {
+ canonical_path_from_root: false,
+ type: "full",
+ },
+ include_build_directory: false,
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("proto_library", "foo_proto", attrNameToString{
+ "srcs": `["foo.proto"]`,
+ }), makeBazelTarget("cc_proto_library", "foo_cc_proto", attrNameToString{
+ "deps": `[":foo_proto"]`,
+ }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
+ "implementation_whole_archive_deps": `[":foo_cc_proto"]`,
+ "deps": `[":libprotobuf-cpp-full"]`,
+ }), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
+ "dynamic_deps": `[":libprotobuf-cpp-full"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryProtoLite(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ blueprint: soongCcProtoPreamble + `cc_library {
+ name: "foo",
+ srcs: ["foo.proto"],
+ proto: {
+ canonical_path_from_root: false,
+ type: "lite",
+ },
+ include_build_directory: false,
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("proto_library", "foo_proto", attrNameToString{
+ "srcs": `["foo.proto"]`,
+ }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
+ "deps": `[":foo_proto"]`,
+ }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
+ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
+ "deps": `[":libprotobuf-cpp-lite"]`,
+ }), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
+ "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryProtoExportHeaders(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ blueprint: soongCcProtoPreamble + `cc_library {
+ name: "foo",
+ srcs: ["foo.proto"],
+ proto: {
+ canonical_path_from_root: false,
+ export_proto_headers: true,
+ },
+ include_build_directory: false,
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("proto_library", "foo_proto", attrNameToString{
+ "srcs": `["foo.proto"]`,
+ }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
+ "deps": `[":foo_proto"]`,
+ }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", attrNameToString{
+ "deps": `[":libprotobuf-cpp-lite"]`,
+ "whole_archive_deps": `[":foo_cc_proto_lite"]`,
+ }), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
+ "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ "whole_archive_deps": `[":foo_cc_proto_lite"]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 76fdab2..594c050 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -78,10 +78,9 @@
func TestCcLibraryHeadersSimple(t *testing.T) {
runCcLibraryHeadersTestCase(t, bp2buildTestCase{
- description: "cc_library_headers test",
- moduleTypeUnderTest: "cc_library_headers",
- moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryHeadersBp2Build,
+ description: "cc_library_headers test",
+ moduleTypeUnderTest: "cc_library_headers",
+ moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
filesystem: map[string]string{
"lib-1/lib1a.h": "",
"lib-1/lib1b.h": "",
@@ -150,11 +149,10 @@
func TestCcLibraryHeadersOsSpecificHeader(t *testing.T) {
runCcLibraryHeadersTestCase(t, bp2buildTestCase{
- description: "cc_library_headers test with os-specific header_libs props",
- moduleTypeUnderTest: "cc_library_headers",
- moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryHeadersBp2Build,
- filesystem: map[string]string{},
+ description: "cc_library_headers test with os-specific header_libs props",
+ moduleTypeUnderTest: "cc_library_headers",
+ moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
+ filesystem: map[string]string{},
blueprint: soongCcLibraryPreamble + `
cc_library_headers {
name: "android-lib",
@@ -209,11 +207,10 @@
func TestCcLibraryHeadersOsSpecficHeaderLibsExportHeaderLibHeaders(t *testing.T) {
runCcLibraryHeadersTestCase(t, bp2buildTestCase{
- 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,
- filesystem: map[string]string{},
+ description: "cc_library_headers test with os-specific header_libs and export_header_lib_headers props",
+ moduleTypeUnderTest: "cc_library_headers",
+ moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
+ filesystem: map[string]string{},
blueprint: soongCcLibraryPreamble + `
cc_library_headers {
name: "android-lib",
@@ -250,11 +247,10 @@
func TestCcLibraryHeadersArchAndTargetExportSystemIncludes(t *testing.T) {
runCcLibraryHeadersTestCase(t, bp2buildTestCase{
- description: "cc_library_headers test with arch-specific and target-specific export_system_include_dirs props",
- moduleTypeUnderTest: "cc_library_headers",
- moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryHeadersBp2Build,
- filesystem: map[string]string{},
+ description: "cc_library_headers test with arch-specific and target-specific export_system_include_dirs props",
+ moduleTypeUnderTest: "cc_library_headers",
+ moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
+ filesystem: map[string]string{},
blueprint: soongCcLibraryPreamble + `cc_library_headers {
name: "foo_headers",
export_system_include_dirs: [
@@ -310,10 +306,9 @@
func TestCcLibraryHeadersNoCrtIgnored(t *testing.T) {
runCcLibraryHeadersTestCase(t, bp2buildTestCase{
- description: "cc_library_headers test",
- moduleTypeUnderTest: "cc_library_headers",
- moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryHeadersBp2Build,
+ description: "cc_library_headers test",
+ moduleTypeUnderTest: "cc_library_headers",
+ moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
filesystem: map[string]string{
"lib-1/lib1a.h": "",
"lib-1/lib1b.h": "",
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 4ec95c3..97a600a 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -33,13 +33,13 @@
ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory)
ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
+ ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
}
func runCcLibrarySharedTestCase(t *testing.T, tc bp2buildTestCase) {
t.Helper()
(&tc).moduleTypeUnderTest = "cc_library_shared"
(&tc).moduleTypeUnderTestFactory = cc.LibrarySharedFactory
- (&tc).moduleTypeUnderTestBp2BuildMutator = cc.CcLibrarySharedBp2Build
runBp2BuildTestCase(t, registerCcLibrarySharedModuleTypes, tc)
}
@@ -425,3 +425,42 @@
expectedErr: fmt.Errorf("Android.bp:16:1: module \"foo_shared\": nocrt is not supported for arch variants"),
})
}
+
+func TestCcLibrarySharedProto(t *testing.T) {
+ runCcLibrarySharedTestCase(t, bp2buildTestCase{
+ blueprint: soongCcProtoPreamble + `cc_library_shared {
+ name: "foo",
+ srcs: ["foo.proto"],
+ proto: {
+ canonical_path_from_root: false,
+ export_proto_headers: true,
+ },
+ include_build_directory: false,
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("proto_library", "foo_proto", attrNameToString{
+ "srcs": `["foo.proto"]`,
+ }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
+ "deps": `[":foo_proto"]`,
+ }), makeBazelTarget("cc_library_shared", "foo", attrNameToString{
+ "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ "whole_archive_deps": `[":foo_cc_proto_lite"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibrarySharedUseVersionLib(t *testing.T) {
+ runCcLibrarySharedTestCase(t, bp2buildTestCase{
+ blueprint: soongCcProtoPreamble + `cc_library_shared {
+ name: "foo",
+ use_version_lib: true,
+ include_build_directory: false,
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_shared", "foo", attrNameToString{
+ "use_version_lib": "True",
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 2f760d2..e2e55dd 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -82,7 +82,6 @@
(&tc).moduleTypeUnderTest = "cc_library_static"
(&tc).moduleTypeUnderTestFactory = cc.LibraryStaticFactory
- (&tc).moduleTypeUnderTestBp2BuildMutator = cc.CcLibraryStaticBp2Build
runBp2BuildTestCase(t, registerCcLibraryStaticModuleTypes, tc)
}
@@ -954,11 +953,13 @@
genrule {
name: "generated_hdr",
cmd: "nothing to see here",
+ bazel_module: { bp2build_available: false },
}
genrule {
name: "export_generated_hdr",
cmd: "nothing to see here",
+ bazel_module: { bp2build_available: false },
}
cc_library_static {
@@ -970,7 +971,9 @@
}`,
expectedBazelTargets: []string{
makeBazelTarget("cc_library_static", "foo_static", attrNameToString{
- "hdrs": `[":export_generated_hdr"]`,
+ "export_includes": `["."]`,
+ "local_includes": `["."]`,
+ "hdrs": `[":export_generated_hdr"]`,
"srcs": `[
"cpp_src.cpp",
":generated_hdr",
@@ -996,66 +999,38 @@
"for-x86.cpp": "",
"not-for-x86.cpp": "",
"not-for-everything.cpp": "",
- "dep/Android.bp": `
-genrule {
- name: "generated_src_other_pkg",
- cmd: "nothing to see here",
-}
-
-genrule {
- name: "generated_hdr_other_pkg",
- cmd: "nothing to see here",
-}
-
-genrule {
- name: "generated_hdr_other_pkg_x86",
- cmd: "nothing to see here",
-}
-
-genrule {
- name: "generated_hdr_other_pkg_android",
- cmd: "nothing to see here",
-}`,
+ "dep/Android.bp": simpleModuleDoNotConvertBp2build("genrule", "generated_src_other_pkg") +
+ simpleModuleDoNotConvertBp2build("genrule", "generated_hdr_other_pkg") +
+ simpleModuleDoNotConvertBp2build("genrule", "generated_src_other_pkg_x86") +
+ simpleModuleDoNotConvertBp2build("genrule", "generated_hdr_other_pkg_x86") +
+ simpleModuleDoNotConvertBp2build("genrule", "generated_hdr_other_pkg_android"),
},
- blueprint: soongCcLibraryStaticPreamble + `
-genrule {
- name: "generated_src",
- cmd: "nothing to see here",
-}
-
-genrule {
- name: "generated_src_not_x86",
- cmd: "nothing to see here",
-}
-
-genrule {
- name: "generated_src_android",
- cmd: "nothing to see here",
-}
-
-genrule {
- name: "generated_hdr",
- cmd: "nothing to see here",
-}
-
+ blueprint: soongCcLibraryStaticPreamble +
+ simpleModuleDoNotConvertBp2build("genrule", "generated_src") +
+ simpleModuleDoNotConvertBp2build("genrule", "generated_src_not_x86") +
+ simpleModuleDoNotConvertBp2build("genrule", "generated_src_android") +
+ simpleModuleDoNotConvertBp2build("genrule", "generated_hdr") + `
cc_library_static {
name: "foo_static",
srcs: ["common.cpp", "not-for-*.cpp"],
exclude_srcs: ["not-for-everything.cpp"],
generated_sources: ["generated_src", "generated_src_other_pkg", "generated_src_not_x86"],
generated_headers: ["generated_hdr", "generated_hdr_other_pkg"],
+ export_generated_headers: ["generated_hdr_other_pkg"],
arch: {
x86: {
srcs: ["for-x86.cpp"],
exclude_srcs: ["not-for-x86.cpp"],
generated_headers: ["generated_hdr_other_pkg_x86"],
exclude_generated_sources: ["generated_src_not_x86"],
+ export_generated_headers: ["generated_hdr_other_pkg_x86"],
},
},
target: {
android: {
generated_sources: ["generated_src_android"],
generated_headers: ["generated_hdr_other_pkg_android"],
+ export_generated_headers: ["generated_hdr_other_pkg_android"],
},
},
@@ -1069,23 +1044,25 @@
":generated_src",
"//dep:generated_src_other_pkg",
":generated_hdr",
- "//dep:generated_hdr_other_pkg",
] + select({
- "//build/bazel/platforms/arch:x86": [
- "for-x86.cpp",
- "//dep:generated_hdr_other_pkg_x86",
- ],
+ "//build/bazel/platforms/arch:x86": ["for-x86.cpp"],
"//conditions:default": [
"not-for-x86.cpp",
":generated_src_not_x86",
],
}) + select({
- "//build/bazel/platforms/os:android": [
- ":generated_src_android",
- "//dep:generated_hdr_other_pkg_android",
- ],
+ "//build/bazel/platforms/os:android": [":generated_src_android"],
"//conditions:default": [],
})`,
+ "hdrs": `["//dep:generated_hdr_other_pkg"] + select({
+ "//build/bazel/platforms/arch:x86": ["//dep:generated_hdr_other_pkg_x86"],
+ "//conditions:default": [],
+ }) + select({
+ "//build/bazel/platforms/os:android": ["//dep:generated_hdr_other_pkg_android"],
+ "//conditions:default": [],
+ })`,
+ "local_includes": `["."]`,
+ "export_absolute_includes": `["dep"]`,
}),
},
})
@@ -1366,9 +1343,8 @@
func TestStaticLibrary_SystemSharedLibsBionic(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
description: "cc_library_static system_shared_libs set for bionic variant",
- blueprint: soongCcLibraryStaticPreamble + `
-cc_library{name: "libc"}
-
+ blueprint: soongCcLibraryStaticPreamble +
+ simpleModuleDoNotConvertBp2build("cc_library", "libc") + `
cc_library_static {
name: "target_bionic",
target: {
@@ -1394,10 +1370,9 @@
func TestStaticLibrary_SystemSharedLibsLinuxRootAndLinuxBionic(t *testing.T) {
runCcLibraryStaticTestCase(t, bp2buildTestCase{
description: "cc_library_static system_shared_libs set for root and linux_bionic variant",
- blueprint: soongCcLibraryStaticPreamble + `
-cc_library{name: "libc"}
-cc_library{name: "libm"}
-
+ blueprint: soongCcLibraryStaticPreamble +
+ simpleModuleDoNotConvertBp2build("cc_library", "libc") +
+ simpleModuleDoNotConvertBp2build("cc_library", "libm") + `
cc_library_static {
name: "target_linux_bionic",
system_shared_libs: ["libc"],
@@ -1419,3 +1394,42 @@
},
})
}
+
+func TestCcLibraryStaticProto(t *testing.T) {
+ runCcLibraryStaticTestCase(t, bp2buildTestCase{
+ blueprint: soongCcProtoPreamble + `cc_library_static {
+ name: "foo",
+ srcs: ["foo.proto"],
+ proto: {
+ canonical_path_from_root: false,
+ export_proto_headers: true,
+ },
+ include_build_directory: false,
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("proto_library", "foo_proto", attrNameToString{
+ "srcs": `["foo.proto"]`,
+ }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", attrNameToString{
+ "deps": `[":foo_proto"]`,
+ }), makeBazelTarget("cc_library_static", "foo", attrNameToString{
+ "deps": `[":libprotobuf-cpp-lite"]`,
+ "whole_archive_deps": `[":foo_cc_proto_lite"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryStaticUseVersionLib(t *testing.T) {
+ runCcLibraryStaticTestCase(t, bp2buildTestCase{
+ blueprint: soongCcProtoPreamble + `cc_library_static {
+ name: "foo",
+ use_version_lib: true,
+ include_build_directory: false,
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo", attrNameToString{
+ "use_version_lib": "True",
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index 5ab9129..0a6c317 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -30,7 +30,6 @@
t.Helper()
(&tc).moduleTypeUnderTest = "cc_object"
(&tc).moduleTypeUnderTestFactory = cc.ObjectFactory
- (&tc).moduleTypeUnderTestBp2BuildMutator = cc.ObjectBp2Build
runBp2BuildTestCase(t, registerCcObjectModuleTypes, tc)
}
diff --git a/bp2build/cc_prebuilt_library_shared_test.go b/bp2build/cc_prebuilt_library_shared_test.go
index bac3908..ef2fddc 100644
--- a/bp2build/cc_prebuilt_library_shared_test.go
+++ b/bp2build/cc_prebuilt_library_shared_test.go
@@ -9,10 +9,9 @@
func TestSharedPrebuiltLibrary(t *testing.T) {
runBp2BuildTestCaseSimple(t,
bp2buildTestCase{
- description: "prebuilt library shared simple",
- moduleTypeUnderTest: "cc_prebuilt_library_shared",
- moduleTypeUnderTestFactory: cc.PrebuiltSharedLibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.PrebuiltLibrarySharedBp2Build,
+ description: "prebuilt library shared simple",
+ moduleTypeUnderTest: "cc_prebuilt_library_shared",
+ moduleTypeUnderTestFactory: cc.PrebuiltSharedLibraryFactory,
filesystem: map[string]string{
"libf.so": "",
},
@@ -33,10 +32,9 @@
func TestSharedPrebuiltLibraryWithArchVariance(t *testing.T) {
runBp2BuildTestCaseSimple(t,
bp2buildTestCase{
- description: "prebuilt library shared with arch variance",
- moduleTypeUnderTest: "cc_prebuilt_library_shared",
- moduleTypeUnderTestFactory: cc.PrebuiltSharedLibraryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.PrebuiltLibrarySharedBp2Build,
+ description: "prebuilt library shared with arch variance",
+ moduleTypeUnderTest: "cc_prebuilt_library_shared",
+ moduleTypeUnderTestFactory: cc.PrebuiltSharedLibraryFactory,
filesystem: map[string]string{
"libf.so": "",
"libg.so": "",
diff --git a/bp2build/filegroup_conversion_test.go b/bp2build/filegroup_conversion_test.go
index 9f4add2..b43cf53 100644
--- a/bp2build/filegroup_conversion_test.go
+++ b/bp2build/filegroup_conversion_test.go
@@ -25,7 +25,6 @@
t.Helper()
(&tc).moduleTypeUnderTest = "filegroup"
(&tc).moduleTypeUnderTestFactory = android.FileGroupFactory
- (&tc).moduleTypeUnderTestBp2BuildMutator = android.FilegroupBp2Build
runBp2BuildTestCase(t, registerFilegroupModuleTypes, tc)
}
diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go
index 5976666..fd631a5 100644
--- a/bp2build/genrule_conversion_test.go
+++ b/bp2build/genrule_conversion_test.go
@@ -28,7 +28,6 @@
t.Helper()
(&tc).moduleTypeUnderTest = "genrule"
(&tc).moduleTypeUnderTestFactory = genrule.GenRuleFactory
- (&tc).moduleTypeUnderTestBp2BuildMutator = genrule.GenruleBp2Build
runBp2BuildTestCase(t, registerGenruleModuleTypes, tc)
}
diff --git a/bp2build/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go
new file mode 100644
index 0000000..96b8958
--- /dev/null
+++ b/bp2build/java_binary_host_conversion_test.go
@@ -0,0 +1,63 @@
+// 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 (
+ "testing"
+
+ "android/soong/android"
+ "android/soong/cc"
+ "android/soong/java"
+)
+
+func runJavaBinaryHostTestCase(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
+ (&tc).moduleTypeUnderTest = "java_binary_host"
+ (&tc).moduleTypeUnderTestFactory = java.BinaryHostFactory
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("cc_library_host_shared", cc.LibraryHostSharedFactory)
+ }, tc)
+}
+
+var fs = map[string]string{
+ "test.mf": "Main-Class: com.android.test.MainClass",
+ "other/Android.bp": `cc_library_host_shared {
+ name: "jni-lib-1",
+ stl: "none",
+}`,
+}
+
+func TestJavaBinaryHost(t *testing.T) {
+ runJavaBinaryHostTestCase(t, bp2buildTestCase{
+ description: "java_binary_host with srcs, exclude_srcs, jni_libs and manifest.",
+ filesystem: fs,
+ blueprint: `java_binary_host {
+ name: "java-binary-host-1",
+ srcs: ["a.java", "b.java"],
+ exclude_srcs: ["b.java"],
+ manifest: "test.mf",
+ jni_libs: ["jni-lib-1"],
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("java_binary", "java-binary-host-1", attrNameToString{
+ "srcs": `["a.java"]`,
+ "main_class": `"com.android.test.MainClass"`,
+ "deps": `["//other:jni-lib-1"]`,
+ "jvm_flags": `["-Djava.library.path=$${RUNPATH}other"]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
new file mode 100644
index 0000000..5c65ec2
--- /dev/null
+++ b/bp2build/java_library_conversion_test.go
@@ -0,0 +1,57 @@
+// 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 (
+ "testing"
+
+ "android/soong/android"
+ "android/soong/java"
+)
+
+func runJavaLibraryTestCase(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
+ (&tc).moduleTypeUnderTest = "java_library"
+ (&tc).moduleTypeUnderTestFactory = java.LibraryFactory
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
+}
+
+func TestJavaLibrary(t *testing.T) {
+ runJavaLibraryTestCase(t, bp2buildTestCase{
+ description: "java_library with srcs, exclude_srcs and libs",
+ blueprint: `java_library {
+ name: "java-lib-1",
+ srcs: ["a.java", "b.java"],
+ exclude_srcs: ["b.java"],
+ libs: ["java-lib-2"],
+ bazel_module: { bp2build_available: true },
+}
+
+java_library {
+ name: "java-lib-2",
+ srcs: ["b.java"],
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("java_library", "java-lib-1", attrNameToString{
+ "srcs": `["a.java"]`,
+ "deps": `[":java-lib-2"]`,
+ }),
+ makeBazelTarget("java_library", "java-lib-2", attrNameToString{
+ "srcs": `["b.java"]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/java_library_host_conversion_test.go b/bp2build/java_library_host_conversion_test.go
new file mode 100644
index 0000000..6ac82db
--- /dev/null
+++ b/bp2build/java_library_host_conversion_test.go
@@ -0,0 +1,57 @@
+// 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 (
+ "testing"
+
+ "android/soong/android"
+ "android/soong/java"
+)
+
+func runJavaLibraryHostTestCase(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
+ (&tc).moduleTypeUnderTest = "java_library_host"
+ (&tc).moduleTypeUnderTestFactory = java.LibraryHostFactory
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
+}
+
+func TestJavaLibraryHost(t *testing.T) {
+ runJavaLibraryHostTestCase(t, bp2buildTestCase{
+ description: "java_library_host with srcs, exclude_srcs and libs",
+ blueprint: `java_library_host {
+ name: "java-lib-host-1",
+ srcs: ["a.java", "b.java"],
+ exclude_srcs: ["b.java"],
+ libs: ["java-lib-host-2"],
+ bazel_module: { bp2build_available: true },
+}
+
+java_library_host {
+ name: "java-lib-host-2",
+ srcs: ["c.java"],
+ bazel_module: { bp2build_available: true },
+}`,
+ expectedBazelTargets: []string{
+ makeBazelTarget("java_library", "java-lib-host-1", attrNameToString{
+ "srcs": `["a.java"]`,
+ "deps": `[":java-lib-host-2"]`,
+ }),
+ makeBazelTarget("java_library", "java-lib-host-2", attrNameToString{
+ "srcs": `["c.java"]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/metrics.go b/bp2build/metrics.go
index 1cc4143..68ac544 100644
--- a/bp2build/metrics.go
+++ b/bp2build/metrics.go
@@ -1,41 +1,61 @@
package bp2build
import (
- "android/soong/android"
"fmt"
+ "os"
+ "path/filepath"
"strings"
+
+ "android/soong/android"
+ "android/soong/shared"
+ "android/soong/ui/metrics/bp2build_metrics_proto"
)
// Simple metrics struct to collect information about a Blueprint to BUILD
// conversion process.
type CodegenMetrics struct {
// Total number of Soong modules converted to generated targets
- generatedModuleCount int
+ generatedModuleCount uint64
// Total number of Soong modules converted to handcrafted targets
- handCraftedModuleCount int
+ handCraftedModuleCount uint64
// Total number of unconverted Soong modules
- unconvertedModuleCount int
+ unconvertedModuleCount uint64
// Counts of generated Bazel targets per Bazel rule class
- ruleClassCount map[string]int
+ ruleClassCount map[string]uint64
+ // List of modules with unconverted deps
+ // NOTE: NOT in the .proto
moduleWithUnconvertedDepsMsgs []string
+ // List of converted modules
convertedModules []string
}
+// Serialize returns the protoized version of CodegenMetrics: bp2build_metrics_proto.Bp2BuildMetrics
+func (metrics *CodegenMetrics) Serialize() bp2build_metrics_proto.Bp2BuildMetrics {
+ return bp2build_metrics_proto.Bp2BuildMetrics{
+ GeneratedModuleCount: metrics.generatedModuleCount,
+ HandCraftedModuleCount: metrics.handCraftedModuleCount,
+ UnconvertedModuleCount: metrics.unconvertedModuleCount,
+ RuleClassCount: metrics.ruleClassCount,
+ ConvertedModules: metrics.convertedModules,
+ }
+}
+
// Print the codegen metrics to stdout.
func (metrics *CodegenMetrics) Print() {
- generatedTargetCount := 0
+ generatedTargetCount := uint64(0)
for _, ruleClass := range android.SortedStringKeys(metrics.ruleClassCount) {
count := metrics.ruleClassCount[ruleClass]
fmt.Printf("[bp2build] %s: %d targets\n", ruleClass, count)
generatedTargetCount += count
}
fmt.Printf(
- "[bp2build] Generated %d total BUILD targets and included %d handcrafted BUILD targets from %d Android.bp modules.\n With %d modules with unconverted deps \n\t%s",
+ "[bp2build] Converted %d Android.bp modules to %d total generated BUILD targets. Included %d handcrafted BUILD targets. There are %d total Android.bp modules.\n%d converted modules have unconverted deps: \n\t%s",
+ metrics.generatedModuleCount,
generatedTargetCount,
metrics.handCraftedModuleCount,
metrics.TotalModuleCount(),
@@ -43,6 +63,40 @@
strings.Join(metrics.moduleWithUnconvertedDepsMsgs, "\n\t"))
}
+const bp2buildMetricsFilename = "bp2build_metrics.pb"
+
+// fail prints $PWD to stderr, followed by the given printf string and args (vals),
+// then the given alert, and then exits with 1 for failure
+func fail(err error, alertFmt string, vals ...interface{}) {
+ cwd, wderr := os.Getwd()
+ if wderr != nil {
+ cwd = "FAILED TO GET $PWD: " + wderr.Error()
+ }
+ fmt.Fprintf(os.Stderr, "\nIn "+cwd+":\n"+alertFmt+"\n"+err.Error()+"\n", vals...)
+ os.Exit(1)
+}
+
+// Write the bp2build-protoized codegen metrics into the given directory
+func (metrics *CodegenMetrics) Write(dir string) {
+ if _, err := os.Stat(dir); os.IsNotExist(err) {
+ // The metrics dir doesn't already exist, so create it (and parents)
+ if err := os.MkdirAll(dir, 0755); err != nil { // rx for all; w for user
+ fail(err, "Failed to `mkdir -p` %s", dir)
+ }
+ } else if err != nil {
+ fail(err, "Failed to `stat` %s", dir)
+ }
+ metricsFile := filepath.Join(dir, bp2buildMetricsFilename)
+ if err := metrics.dump(metricsFile); err != nil {
+ fail(err, "Error outputting %s", metricsFile)
+ }
+ if _, err := os.Stat(metricsFile); err != nil {
+ fail(err, "MISSING BP2BUILD METRICS OUTPUT: Failed to `stat` %s", metricsFile)
+ } else {
+ fmt.Printf("\nWrote bp2build metrics to: %s\n", metricsFile)
+ }
+}
+
func (metrics *CodegenMetrics) IncrementRuleClassCount(ruleClass string) {
metrics.ruleClassCount[ruleClass] += 1
}
@@ -51,12 +105,18 @@
metrics.unconvertedModuleCount += 1
}
-func (metrics *CodegenMetrics) TotalModuleCount() int {
+func (metrics *CodegenMetrics) TotalModuleCount() uint64 {
return metrics.handCraftedModuleCount +
metrics.generatedModuleCount +
metrics.unconvertedModuleCount
}
+// Dump serializes the metrics to the given filename
+func (metrics *CodegenMetrics) dump(filename string) (err error) {
+ ser := metrics.Serialize()
+ return shared.Save(&ser, filename)
+}
+
type ConversionType int
const (
diff --git a/bp2build/performance_test.go b/bp2build/performance_test.go
index 3283952..c4bbae2 100644
--- a/bp2build/performance_test.go
+++ b/bp2build/performance_test.go
@@ -29,6 +29,10 @@
"testing"
)
+const (
+ performance_test_dir = "."
+)
+
func genCustomModule(i int, convert bool) string {
var conversionString string
if convert {
@@ -76,34 +80,83 @@
return strings.Join(bp, "\n\n")
}
+type testConfig struct {
+ config android.Config
+ ctx *android.TestContext
+ codegenCtx *CodegenContext
+}
+
+func (tc testConfig) parse() []error {
+ _, errs := tc.ctx.ParseFileList(performance_test_dir, []string{"Android.bp"})
+ return errs
+}
+
+func (tc testConfig) resolveDependencies() []error {
+ _, errs := tc.ctx.ResolveDependencies(tc.config)
+ return errs
+}
+
+func (tc testConfig) convert() {
+ generateBazelTargetsForDir(tc.codegenCtx, performance_test_dir)
+}
+
+func setup(builddir string, tcSize float64) testConfig {
+ config := android.TestConfig(buildDir, nil, genCustomModuleBp(tcSize), nil)
+ ctx := android.NewTestContext(config)
+
+ registerCustomModuleForBp2buildConversion(ctx)
+ codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ return testConfig{
+ config,
+ ctx,
+ codegenCtx,
+ }
+}
+
var pctToConvert = []float64{0.0, 0.01, 0.05, 0.10, 0.25, 0.5, 0.75, 1.0}
+// This is not intended to test performance, but to verify performance infra continues to work
+func TestConvertManyModulesFull(t *testing.T) {
+ for _, tcSize := range pctToConvert {
+
+ t.Run(fmt.Sprintf("pctConverted %f", tcSize), func(t *testing.T) {
+ testConfig := setup(buildDir, tcSize)
+
+ errs := testConfig.parse()
+ if len(errs) > 0 {
+ t.Fatalf("Unexpected errors: %s", errs)
+ }
+
+ errs = testConfig.resolveDependencies()
+ if len(errs) > 0 {
+ t.Fatalf("Unexpected errors: %s", errs)
+ }
+
+ testConfig.convert()
+ })
+ }
+}
+
func BenchmarkManyModulesFull(b *testing.B) {
- dir := "."
for _, tcSize := range pctToConvert {
b.Run(fmt.Sprintf("pctConverted %f", tcSize), func(b *testing.B) {
for n := 0; n < b.N; n++ {
b.StopTimer()
- // setup we don't want to measure
- config := android.TestConfig(buildDir, nil, genCustomModuleBp(tcSize), nil)
- ctx := android.NewTestContext(config)
-
- registerCustomModuleForBp2buildConversion(ctx)
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ testConfig := setup(buildDir, tcSize)
b.StartTimer()
- _, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
+ errs := testConfig.parse()
if len(errs) > 0 {
b.Fatalf("Unexpected errors: %s", errs)
}
- _, errs = ctx.ResolveDependencies(config)
+ errs = testConfig.resolveDependencies()
if len(errs) > 0 {
b.Fatalf("Unexpected errors: %s", errs)
}
- generateBazelTargetsForDir(codegenCtx, dir)
+ testConfig.convert()
b.StopTimer()
}
})
@@ -111,63 +164,53 @@
}
func BenchmarkManyModulesResolveDependencies(b *testing.B) {
- dir := "."
for _, tcSize := range pctToConvert {
b.Run(fmt.Sprintf("pctConverted %f", tcSize), func(b *testing.B) {
for n := 0; n < b.N; n++ {
b.StopTimer()
// setup we don't want to measure
- config := android.TestConfig(buildDir, nil, genCustomModuleBp(tcSize), nil)
- ctx := android.NewTestContext(config)
+ testConfig := setup(buildDir, tcSize)
- registerCustomModuleForBp2buildConversion(ctx)
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
-
- _, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
+ errs := testConfig.parse()
if len(errs) > 0 {
b.Fatalf("Unexpected errors: %s", errs)
}
b.StartTimer()
- _, errs = ctx.ResolveDependencies(config)
+ errs = testConfig.resolveDependencies()
b.StopTimer()
if len(errs) > 0 {
b.Fatalf("Unexpected errors: %s", errs)
}
- generateBazelTargetsForDir(codegenCtx, dir)
+ testConfig.convert()
}
})
}
}
func BenchmarkManyModulesGenerateBazelTargetsForDir(b *testing.B) {
- dir := "."
for _, tcSize := range pctToConvert {
b.Run(fmt.Sprintf("pctConverted %f", tcSize), func(b *testing.B) {
for n := 0; n < b.N; n++ {
b.StopTimer()
// setup we don't want to measure
- config := android.TestConfig(buildDir, nil, genCustomModuleBp(tcSize), nil)
- ctx := android.NewTestContext(config)
+ testConfig := setup(buildDir, tcSize)
- registerCustomModuleForBp2buildConversion(ctx)
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
-
- _, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
+ errs := testConfig.parse()
if len(errs) > 0 {
b.Fatalf("Unexpected errors: %s", errs)
}
- _, errs = ctx.ResolveDependencies(config)
+ errs = testConfig.resolveDependencies()
if len(errs) > 0 {
b.Fatalf("Unexpected errors: %s", errs)
}
b.StartTimer()
- generateBazelTargetsForDir(codegenCtx, dir)
+ testConfig.convert()
b.StopTimer()
}
})
diff --git a/bp2build/prebuilt_etc_conversion_test.go b/bp2build/prebuilt_etc_conversion_test.go
index 1189309..5065893 100644
--- a/bp2build/prebuilt_etc_conversion_test.go
+++ b/bp2build/prebuilt_etc_conversion_test.go
@@ -25,7 +25,6 @@
t.Helper()
(&tc).moduleTypeUnderTest = "prebuilt_etc"
(&tc).moduleTypeUnderTestFactory = etc.PrebuiltEtcFactory
- (&tc).moduleTypeUnderTestBp2BuildMutator = etc.PrebuiltEtcBp2Build
runBp2BuildTestCase(t, registerPrebuiltEtcModuleTypes, tc)
}
diff --git a/bp2build/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go
index 01b6aa2..40c8ba1 100644
--- a/bp2build/python_binary_conversion_test.go
+++ b/bp2build/python_binary_conversion_test.go
@@ -17,10 +17,9 @@
func TestPythonBinaryHostSimple(t *testing.T) {
runBp2BuildTestCaseWithPythonLibraries(t, bp2buildTestCase{
- description: "simple python_binary_host converts to a native py_binary",
- moduleTypeUnderTest: "python_binary_host",
- moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
- moduleTypeUnderTestBp2BuildMutator: python.PythonBinaryBp2Build,
+ description: "simple python_binary_host converts to a native py_binary",
+ moduleTypeUnderTest: "python_binary_host",
+ moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
filesystem: map[string]string{
"a.py": "",
"b/c.py": "",
@@ -40,7 +39,7 @@
python_library_host {
name: "bar",
srcs: ["b/e.py"],
- bazel_module: { bp2build_available: true },
+ bazel_module: { bp2build_available: false },
}`,
expectedBazelTargets: []string{
makeBazelTarget("py_binary", "foo", attrNameToString{
@@ -59,10 +58,9 @@
func TestPythonBinaryHostPy2(t *testing.T) {
runBp2BuildTestCaseSimple(t, bp2buildTestCase{
- description: "py2 python_binary_host",
- moduleTypeUnderTest: "python_binary_host",
- moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
- moduleTypeUnderTestBp2BuildMutator: python.PythonBinaryBp2Build,
+ description: "py2 python_binary_host",
+ moduleTypeUnderTest: "python_binary_host",
+ moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
blueprint: `python_binary_host {
name: "foo",
srcs: ["a.py"],
@@ -89,10 +87,9 @@
func TestPythonBinaryHostPy3(t *testing.T) {
runBp2BuildTestCaseSimple(t, bp2buildTestCase{
- description: "py3 python_binary_host",
- moduleTypeUnderTest: "python_binary_host",
- moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
- moduleTypeUnderTestBp2BuildMutator: python.PythonBinaryBp2Build,
+ description: "py3 python_binary_host",
+ moduleTypeUnderTest: "python_binary_host",
+ moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
blueprint: `python_binary_host {
name: "foo",
srcs: ["a.py"],
@@ -119,10 +116,9 @@
func TestPythonBinaryHostArchVariance(t *testing.T) {
runBp2BuildTestCaseSimple(t, bp2buildTestCase{
- description: "test arch variants",
- moduleTypeUnderTest: "python_binary_host",
- moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
- moduleTypeUnderTestBp2BuildMutator: python.PythonBinaryBp2Build,
+ description: "test arch variants",
+ moduleTypeUnderTest: "python_binary_host",
+ moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
filesystem: map[string]string{
"dir/arm.py": "",
"dir/x86.py": "",
diff --git a/bp2build/python_library_conversion_test.go b/bp2build/python_library_conversion_test.go
index e334592..6b26105 100644
--- a/bp2build/python_library_conversion_test.go
+++ b/bp2build/python_library_conversion_test.go
@@ -18,7 +18,6 @@
testCase.blueprint = fmt.Sprintf(testCase.blueprint, "python_library")
testCase.moduleTypeUnderTest = "python_library"
testCase.moduleTypeUnderTestFactory = python.PythonLibraryFactory
- testCase.moduleTypeUnderTestBp2BuildMutator = python.PythonLibraryBp2Build
runBp2BuildTestCaseSimple(t, testCase)
}
@@ -29,7 +28,6 @@
testCase.blueprint = fmt.Sprintf(testCase.blueprint, "python_library_host")
testCase.moduleTypeUnderTest = "python_library_host"
testCase.moduleTypeUnderTestFactory = python.PythonLibraryHostFactory
- testCase.moduleTypeUnderTestBp2BuildMutator = python.PythonLibraryHostBp2Build
runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("python_library", python.PythonLibraryFactory)
},
diff --git a/bp2build/sh_conversion_test.go b/bp2build/sh_conversion_test.go
index 1ca4a0e..f6d2a20 100644
--- a/bp2build/sh_conversion_test.go
+++ b/bp2build/sh_conversion_test.go
@@ -55,18 +55,21 @@
func TestShBinarySimple(t *testing.T) {
runShBinaryTestCase(t, bp2buildTestCase{
- description: "sh_binary test",
- moduleTypeUnderTest: "sh_binary",
- moduleTypeUnderTestFactory: sh.ShBinaryFactory,
- moduleTypeUnderTestBp2BuildMutator: sh.ShBinaryBp2Build,
+ description: "sh_binary test",
+ moduleTypeUnderTest: "sh_binary",
+ moduleTypeUnderTestFactory: sh.ShBinaryFactory,
blueprint: `sh_binary {
name: "foo",
src: "foo.sh",
+ filename: "foo.exe",
+ sub_dir: "sub",
bazel_module: { bp2build_available: true },
}`,
expectedBazelTargets: []string{
makeBazelTarget("sh_binary", "foo", attrNameToString{
- "srcs": `["foo.sh"]`,
+ "srcs": `["foo.sh"]`,
+ "filename": `"foo.exe"`,
+ "sub_dir": `"sub"`,
})},
})
}
diff --git a/bp2build/soong_config_module_type_conversion_test.go b/bp2build/soong_config_module_type_conversion_test.go
index d21db04..f1489aa 100644
--- a/bp2build/soong_config_module_type_conversion_test.go
+++ b/bp2build/soong_config_module_type_conversion_test.go
@@ -61,11 +61,10 @@
`
runSoongConfigModuleTypeTest(t, bp2buildTestCase{
- description: "soong config variables - soong_config_module_type is supported in bp2build",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
- blueprint: bp,
+ description: "soong config variables - soong_config_module_type is supported in bp2build",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ blueprint: bp,
expectedBazelTargets: []string{`cc_library_static(
name = "foo",
copts = select({
@@ -107,10 +106,9 @@
`
runSoongConfigModuleTypeTest(t, bp2buildTestCase{
- description: "soong config variables - soong_config_module_type_import is supported in bp2build",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ description: "soong config variables - soong_config_module_type_import is supported in bp2build",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
filesystem: map[string]string{
"foo/bar/SoongConfig.bp": configBp,
},
@@ -161,11 +159,10 @@
`
runSoongConfigModuleTypeTest(t, bp2buildTestCase{
- description: "soong config variables - generates selects for string vars",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
- blueprint: bp,
+ description: "soong config variables - generates selects for string vars",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ blueprint: bp,
expectedBazelTargets: []string{`cc_library_static(
name = "foo",
copts = select({
@@ -232,11 +229,10 @@
}`
runSoongConfigModuleTypeTest(t, bp2buildTestCase{
- description: "soong config variables - generates selects for multiple variable types",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
- blueprint: bp,
+ description: "soong config variables - generates selects for multiple variable types",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ blueprint: bp,
expectedBazelTargets: []string{`cc_library_static(
name = "foo",
copts = select({
@@ -298,11 +294,10 @@
`
runSoongConfigModuleTypeTest(t, bp2buildTestCase{
- description: "soong config variables - generates selects for label list attributes",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
- blueprint: bp,
+ description: "soong config variables - generates selects for label list attributes",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ blueprint: bp,
filesystem: map[string]string{
"foo/bar/Android.bp": otherDeps,
},
@@ -365,11 +360,10 @@
`
runSoongConfigModuleTypeTest(t, bp2buildTestCase{
- description: "soong config variables - defaults with a single namespace",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
- blueprint: bp,
+ description: "soong config variables - defaults with a single namespace",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ blueprint: bp,
expectedBazelTargets: []string{`cc_library_static(
name = "lib",
copts = select({
@@ -445,11 +439,10 @@
`
runSoongConfigModuleTypeTest(t, bp2buildTestCase{
- description: "soong config variables - multiple defaults with a single namespace",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
- blueprint: bp,
+ description: "soong config variables - multiple defaults with a single namespace",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ blueprint: bp,
expectedBazelTargets: []string{`cc_library_static(
name = "lib",
asflags = select({
@@ -561,11 +554,10 @@
`
runSoongConfigModuleTypeTest(t, bp2buildTestCase{
- description: "soong config variables - defaults with multiple namespaces",
- moduleTypeUnderTest: "cc_library_static",
- moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
- blueprint: bp,
+ description: "soong config variables - defaults with multiple namespaces",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ blueprint: bp,
expectedBazelTargets: []string{`cc_library_static(
name = "lib",
copts = select({
@@ -652,11 +644,10 @@
`
runSoongConfigModuleTypeTest(t, bp2buildTestCase{
- description: "soong config variables - generates selects for library_linking_strategy",
- moduleTypeUnderTest: "cc_binary",
- moduleTypeUnderTestFactory: cc.BinaryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.BinaryBp2build,
- blueprint: bp,
+ description: "soong config variables - generates selects for library_linking_strategy",
+ moduleTypeUnderTest: "cc_binary",
+ moduleTypeUnderTestFactory: cc.BinaryFactory,
+ blueprint: bp,
filesystem: map[string]string{
"foo/bar/Android.bp": otherDeps,
},
@@ -733,11 +724,10 @@
`
runSoongConfigModuleTypeTest(t, bp2buildTestCase{
- description: "soong config variables - generates selects for library_linking_strategy",
- moduleTypeUnderTest: "cc_binary",
- moduleTypeUnderTestFactory: cc.BinaryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.BinaryBp2build,
- blueprint: bp,
+ description: "soong config variables - generates selects for library_linking_strategy",
+ moduleTypeUnderTest: "cc_binary",
+ moduleTypeUnderTestFactory: cc.BinaryFactory,
+ blueprint: bp,
filesystem: map[string]string{
"foo/bar/Android.bp": otherDeps,
},
@@ -821,11 +811,10 @@
`
runSoongConfigModuleTypeTest(t, bp2buildTestCase{
- description: "soong config variables - generates selects for library_linking_strategy",
- moduleTypeUnderTest: "cc_binary",
- moduleTypeUnderTestFactory: cc.BinaryFactory,
- moduleTypeUnderTestBp2BuildMutator: cc.BinaryBp2build,
- blueprint: bp,
+ description: "soong config variables - generates selects for library_linking_strategy",
+ moduleTypeUnderTest: "cc_binary",
+ moduleTypeUnderTestFactory: cc.BinaryFactory,
+ blueprint: bp,
filesystem: map[string]string{
"foo/bar/Android.bp": otherDeps,
},
diff --git a/bp2build/testing.go b/bp2build/testing.go
index daa9c22..15cf486 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -74,16 +74,15 @@
}
type bp2buildTestCase struct {
- description string
- moduleTypeUnderTest string
- moduleTypeUnderTestFactory android.ModuleFactory
- moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
- blueprint string
- expectedBazelTargets []string
- filesystem map[string]string
- dir string
- expectedErr error
- unconvertedDepsMode unconvertedDepsMode
+ description string
+ moduleTypeUnderTest string
+ moduleTypeUnderTestFactory android.ModuleFactory
+ blueprint string
+ expectedBazelTargets []string
+ filesystem map[string]string
+ dir string
+ expectedErr error
+ unconvertedDepsMode unconvertedDepsMode
}
func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc bp2buildTestCase) {
@@ -105,7 +104,6 @@
registerModuleTypes(ctx)
ctx.RegisterModuleType(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestFactory)
ctx.RegisterBp2BuildConfig(bp2buildConfig)
- ctx.RegisterBp2BuildMutator(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestBp2BuildMutator)
ctx.RegisterForBazelConversion()
_, parseErrs := ctx.ParseFileList(dir, toParse)
@@ -149,15 +147,15 @@
}
type nestedProps struct {
- Nested_prop string
+ Nested_prop *string
}
type EmbeddedProps struct {
- Embedded_prop string
+ Embedded_prop *string
}
type OtherEmbeddedProps struct {
- Other_embedded_prop string
+ Other_embedded_prop *string
}
type customProps struct {
@@ -178,6 +176,9 @@
Arch_paths []string `android:"path,arch_variant"`
Arch_paths_exclude []string `android:"path,arch_variant"`
+
+ // Prop used to indicate this conversion should be 1 module -> multiple targets
+ One_to_many_prop *bool
}
type customModule struct {
@@ -262,86 +263,80 @@
}
type EmbeddedAttr struct {
- Embedded_attr string
+ Embedded_attr *string
}
type OtherEmbeddedAttr struct {
- Other_embedded_attr string
+ Other_embedded_attr *string
}
type customBazelModuleAttributes struct {
EmbeddedAttr
*OtherEmbeddedAttr
- String_prop string
+ String_ptr_prop *string
String_list_prop []string
Arch_paths bazel.LabelListAttribute
}
-func customBp2BuildMutator(ctx android.TopDownMutatorContext) {
- if m, ok := ctx.Module().(*customModule); ok {
- if !m.ConvertWithBp2build(ctx) {
- return
- }
+func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ paths := bazel.LabelListAttribute{}
- paths := bazel.LabelListAttribute{}
+ if p := m.props.One_to_many_prop; p != nil && *p {
+ customBp2buildOneToMany(ctx, m)
+ return
+ }
- for axis, configToProps := range m.GetArchVariantProperties(ctx, &customProps{}) {
- for config, props := range configToProps {
- if archProps, ok := props.(*customProps); ok && archProps.Arch_paths != nil {
- paths.SetSelectValue(axis, config, android.BazelLabelForModuleSrcExcludes(ctx, archProps.Arch_paths, archProps.Arch_paths_exclude))
- }
+ for axis, configToProps := range m.GetArchVariantProperties(ctx, &customProps{}) {
+ for config, props := range configToProps {
+ if archProps, ok := props.(*customProps); ok && archProps.Arch_paths != nil {
+ paths.SetSelectValue(axis, config, android.BazelLabelForModuleSrcExcludes(ctx, archProps.Arch_paths, archProps.Arch_paths_exclude))
}
}
-
- paths.ResolveExcludes()
-
- attrs := &customBazelModuleAttributes{
- String_prop: m.props.String_prop,
- String_list_prop: m.props.String_list_prop,
- Arch_paths: paths,
- }
- attrs.Embedded_attr = m.props.Embedded_prop
- if m.props.OtherEmbeddedProps != nil {
- attrs.OtherEmbeddedAttr = &OtherEmbeddedAttr{Other_embedded_attr: m.props.OtherEmbeddedProps.Other_embedded_prop}
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "custom",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
}
+
+ paths.ResolveExcludes()
+
+ attrs := &customBazelModuleAttributes{
+ String_ptr_prop: m.props.String_ptr_prop,
+ String_list_prop: m.props.String_list_prop,
+ Arch_paths: paths,
+ }
+ attrs.Embedded_attr = m.props.Embedded_prop
+ if m.props.OtherEmbeddedProps != nil {
+ attrs.OtherEmbeddedAttr = &OtherEmbeddedAttr{Other_embedded_attr: m.props.OtherEmbeddedProps.Other_embedded_prop}
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "custom",
+ }
+
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
}
// A bp2build mutator that uses load statements and creates a 1:M mapping from
// module to target.
-func customBp2BuildMutatorFromStarlark(ctx android.TopDownMutatorContext) {
- if m, ok := ctx.Module().(*customModule); ok {
- if !m.ConvertWithBp2build(ctx) {
- return
- }
+func customBp2buildOneToMany(ctx android.TopDownMutatorContext, m *customModule) {
- baseName := m.Name()
- attrs := &customBazelModuleAttributes{}
+ baseName := m.Name()
+ attrs := &customBazelModuleAttributes{}
- myLibraryProps := bazel.BazelTargetModuleProperties{
- Rule_class: "my_library",
- Bzl_load_location: "//build/bazel/rules:rules.bzl",
- }
- ctx.CreateBazelTargetModule(myLibraryProps, android.CommonAttributes{Name: baseName}, attrs)
-
- protoLibraryProps := bazel.BazelTargetModuleProperties{
- Rule_class: "proto_library",
- Bzl_load_location: "//build/bazel/rules:proto.bzl",
- }
- ctx.CreateBazelTargetModule(protoLibraryProps, android.CommonAttributes{Name: baseName + "_proto_library_deps"}, attrs)
-
- myProtoLibraryProps := bazel.BazelTargetModuleProperties{
- Rule_class: "my_proto_library",
- Bzl_load_location: "//build/bazel/rules:proto.bzl",
- }
- ctx.CreateBazelTargetModule(myProtoLibraryProps, android.CommonAttributes{Name: baseName + "_my_proto_library_deps"}, attrs)
+ myLibraryProps := bazel.BazelTargetModuleProperties{
+ Rule_class: "my_library",
+ Bzl_load_location: "//build/bazel/rules:rules.bzl",
}
+ ctx.CreateBazelTargetModule(myLibraryProps, android.CommonAttributes{Name: baseName}, attrs)
+
+ protoLibraryProps := bazel.BazelTargetModuleProperties{
+ Rule_class: "proto_library",
+ Bzl_load_location: "//build/bazel/rules:proto.bzl",
+ }
+ ctx.CreateBazelTargetModule(protoLibraryProps, android.CommonAttributes{Name: baseName + "_proto_library_deps"}, attrs)
+
+ myProtoLibraryProps := bazel.BazelTargetModuleProperties{
+ Rule_class: "my_proto_library",
+ Bzl_load_location: "//build/bazel/rules:proto.bzl",
+ }
+ ctx.CreateBazelTargetModule(myProtoLibraryProps, android.CommonAttributes{Name: baseName + "_my_proto_library_deps"}, attrs)
}
// Helper method for tests to easily access the targets in a dir.
@@ -353,7 +348,6 @@
func registerCustomModuleForBp2buildConversion(ctx *android.TestContext) {
ctx.RegisterModuleType("custom", customModuleFactory)
- ctx.RegisterBp2BuildMutator("custom", customBp2BuildMutator)
ctx.RegisterForBazelConversion()
}
diff --git a/bpfix/Android.bp b/bpfix/Android.bp
index 345dbd0..a72d9b4 100644
--- a/bpfix/Android.bp
+++ b/bpfix/Android.bp
@@ -52,5 +52,6 @@
],
deps: [
"blueprint-parser",
+ "blueprint-pathtools",
],
}
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index e1140b8..c0925fe 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -22,6 +22,7 @@
"flag"
"fmt"
"io"
+ "io/ioutil"
"os"
"path/filepath"
"reflect"
@@ -29,6 +30,7 @@
"strings"
"github.com/google/blueprint/parser"
+ "github.com/google/blueprint/pathtools"
)
// Reformat takes a blueprint file as a string and returns a formatted version
@@ -166,7 +168,7 @@
},
{
Name: "rewriteLicenseProperties",
- Fix: runPatchListMod(rewriteLicenseProperties),
+ Fix: runPatchListMod(rewriteLicenseProperty(nil, "")),
},
}
@@ -1452,9 +1454,16 @@
return nil
}
+func rewriteLicenseProperty(fs pathtools.FileSystem, relativePath string) patchListModFunction {
+ return func(mod *parser.Module, buf []byte, patchList *parser.PatchList) error {
+ return rewriteLicenseProperties(mod, patchList, fs, relativePath)
+ }
+}
+
// rewrite the "android_license_kinds" and "android_license_files" properties to a package module
// (and a license module when needed).
-func rewriteLicenseProperties(mod *parser.Module, buf []byte, patchList *parser.PatchList) error {
+func rewriteLicenseProperties(mod *parser.Module, patchList *parser.PatchList, fs pathtools.FileSystem,
+ relativePath string) error {
// if a package module has been added, no more action is needed.
for _, patch := range *patchList {
if strings.Contains(patch.Replacement, "package {") {
@@ -1462,15 +1471,33 @@
}
}
+ // initial the fs
+ if fs == nil {
+ fs = pathtools.NewOsFs(os.Getenv("ANDROID_BUILD_TOP"))
+ }
+
+ // initial the relativePath
+ if len(relativePath) == 0 {
+ relativePath = getModuleRelativePath()
+ }
+ // validate the relativePath
+ ok := hasFile(relativePath+"/Android.mk", fs)
+ // some modules in the existing test cases in the androidmk_test.go do not have a valid path
+ if !ok && len(relativePath) > 0 {
+ return fmt.Errorf("Cannot find an Android.mk file at path %s", relativePath)
+ }
+
licenseKindsPropertyName := "android_license_kinds"
licenseFilesPropertyName := "android_license_files"
- androidBpFileErr := "// Error: No Android.bp file is found at\n" +
+ androidBpFileErr := "// Error: No Android.bp file is found at path\n" +
"// %s\n" +
- "// Please add one there with the needed license module first.\n"
+ "// Please add one there with the needed license module first.\n" +
+ "// Then reset the default_applicable_licenses property below with the license module name.\n"
licenseModuleErr := "// Error: Cannot get the name of the license module in the\n" +
"// %s file.\n" +
- "// If no such license module exists, please add one there first.\n"
+ "// If no such license module exists, please add one there first.\n" +
+ "// Then reset the default_applicable_licenses property below with the license module name.\n"
defaultApplicableLicense := "Android-Apache-2.0"
var licenseModuleName, licensePatch string
@@ -1482,15 +1509,16 @@
// if have LOCAL_NOTICE_FILE outside the current directory, need to find and refer to the license
// module in the LOCAL_NOTICE_FILE location directly and no new license module needs to be created
if hasFileInParentDir {
- bpPath, ok := getPathFromProperty(mod, licenseFilesPropertyName)
+ bpPath, ok := getPathFromProperty(mod, licenseFilesPropertyName, fs, relativePath)
if !ok {
- bpDir, err := getDirFromProperty(mod, licenseFilesPropertyName)
+ bpDir, err := getDirFromProperty(mod, licenseFilesPropertyName, fs, relativePath)
if err != nil {
return err
}
licensePatch += fmt.Sprintf(androidBpFileErr, bpDir)
+ defaultApplicableLicense = ""
} else {
- licenseModuleName, _ = getModuleName(bpPath, "license")
+ licenseModuleName, _ = getModuleName(bpPath, "license", fs)
if len(licenseModuleName) == 0 {
licensePatch += fmt.Sprintf(licenseModuleErr, bpPath)
}
@@ -1498,7 +1526,6 @@
}
} else {
// if have LOCAL_NOTICE_FILE in the current directory, need to create a new license module
- relativePath := getModuleRelativePath()
if len(relativePath) == 0 {
return fmt.Errorf("Cannot obtain the relative path of the Android.mk file")
}
@@ -1617,17 +1644,14 @@
return absPath
}
-// check whether a file exists in a directory
-func hasFile(dir string, fileName string) error {
- _, err := os.Stat(dir + fileName)
- if err != nil {
- return err
- }
- return nil
+// check whether a file exists in a filesystem
+func hasFile(path string, fs pathtools.FileSystem) bool {
+ ok, _, _ := fs.Exists(path)
+ return ok
}
// get the directory where an `Android.bp` file and the property files are expected to locate
-func getDirFromProperty(mod *parser.Module, property string) (string, error) {
+func getDirFromProperty(mod *parser.Module, property string, fs pathtools.FileSystem, relativePath string) (string, error) {
listValue, ok := getLiteralListPropertyValue(mod, property)
if !ok {
// if do not find
@@ -1637,7 +1661,11 @@
// if empty
return "", fmt.Errorf("Cannot find the value of the %s.%s property", mod.Type, property)
}
- path := getModuleAbsolutePath()
+ _, isDir, _ := fs.Exists(relativePath)
+ if !isDir {
+ return "", fmt.Errorf("Cannot find the path %s", relativePath)
+ }
+ path := relativePath
for {
if !strings.HasPrefix(listValue[0], "../") {
break
@@ -1645,25 +1673,29 @@
path = filepath.Dir(path)
listValue[0] = strings.TrimPrefix(listValue[0], "../")
}
+ _, isDir, _ = fs.Exists(path)
+ if !isDir {
+ return "", fmt.Errorf("Cannot find the path %s", path)
+ }
return path, nil
}
// get the path of the `Android.bp` file at the expected location where the property files locate
-func getPathFromProperty(mod *parser.Module, property string) (string, bool) {
- dir, err := getDirFromProperty(mod, property)
+func getPathFromProperty(mod *parser.Module, property string, fs pathtools.FileSystem, relativePath string) (string, bool) {
+ dir, err := getDirFromProperty(mod, property, fs, relativePath)
if err != nil {
return "", false
}
- err = hasFile(dir, "/Android.bp")
- if err != nil {
+ ok := hasFile(dir+"/Android.bp", fs)
+ if !ok {
return "", false
}
return dir + "/Android.bp", true
}
// parse an Android.bp file to get the name of the first module with type of moduleType
-func getModuleName(path string, moduleType string) (string, error) {
- tree, err := parserPath(path)
+func getModuleName(path string, moduleType string, fs pathtools.FileSystem) (string, error) {
+ tree, err := parserPath(path, fs)
if err != nil {
return "", err
}
@@ -1685,8 +1717,13 @@
}
// parse an Android.bp file with the specific path
-func parserPath(path string) (tree *parser.File, err error) {
- fileContent, _ := os.ReadFile(path)
+func parserPath(path string, fs pathtools.FileSystem) (tree *parser.File, err error) {
+ f, err := fs.Open(path)
+ if err != nil {
+ return tree, err
+ }
+ defer f.Close()
+ fileContent, _ := ioutil.ReadAll(f)
tree, err = parse(path, bytes.NewBufferString(string(fileContent)))
if err != nil {
return tree, err
diff --git a/bpfix/bpfix/bpfix_test.go b/bpfix/bpfix/bpfix_test.go
index e6b6af5..221df45 100644
--- a/bpfix/bpfix/bpfix_test.go
+++ b/bpfix/bpfix/bpfix_test.go
@@ -25,6 +25,7 @@
"reflect"
"github.com/google/blueprint/parser"
+ "github.com/google/blueprint/pathtools"
)
// TODO(jeffrygaston) remove this when position is removed from ParseNode (in b/38325146) and we can directly do reflect.DeepEqual
@@ -1678,10 +1679,20 @@
}
}
-func TestRewriteLicenseProperties(t *testing.T) {
+func TestRewriteLicenseProperty(t *testing.T) {
+ mockFs := pathtools.MockFs(map[string][]byte{
+ "a/b/c/d/Android.mk": []byte("this is not important."),
+ "a/b/LicenseFile1": []byte("LicenseFile1"),
+ "a/b/LicenseFile2": []byte("LicenseFile2"),
+ "a/b/Android.bp": []byte("license {\n\tname: \"reuse_a_b_license\",\n}\n"),
+ })
+ relativePath := "a/b/c/d"
+ relativePathErr := "a/b/c"
tests := []struct {
name string
in string
+ fs pathtools.FileSystem
+ path string
out string
}{
{
@@ -1744,13 +1755,194 @@
}
`,
},
- // TODO(b/205615944): When valid "android_license_files" exists, the test requires an Android.mk
- // file (and an Android.bp file is required as well if the license files locates outside the current
- // directory). So plan to use a mock file system to mock the Android.mk and Android.bp files.
+ {
+ name: "license rewriting with license files in the current directory",
+ in: `
+ android_test {
+ name: "foo",
+ android_license_kinds: ["license_kind"],
+ android_license_conditions: ["license_notice"],
+ android_license_files: ["LicenseFile1", "LicenseFile2",],
+ }
+ `,
+ fs: mockFs,
+ path: relativePath,
+ out: `
+ package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "a_b_c_d_license",
+ ],
+ }
+
+ license {
+ name: "a_b_c_d_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "license_kind",
+ ],
+ license_text: [
+ "LicenseFile1",
+ "LicenseFile2",
+ ],
+ }
+
+ android_test {
+ name: "foo",
+ android_license_kinds: ["license_kind"],
+ android_license_conditions: ["license_notice"],
+ android_license_files: [
+ "LicenseFile1",
+ "LicenseFile2",
+ ],
+ }
+ `,
+ },
+ {
+ name: "license rewriting with license files outside the current directory",
+ in: `
+ android_test {
+ name: "foo",
+ android_license_kinds: ["license_kind"],
+ android_license_conditions: ["license_notice"],
+ android_license_files: ["../../LicenseFile1", "../../LicenseFile2",],
+ }
+ `,
+ fs: mockFs,
+ path: relativePath,
+ out: `
+ package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "reuse_a_b_license",
+ ],
+ }
+
+ android_test {
+ name: "foo",
+ android_license_kinds: ["license_kind"],
+ android_license_conditions: ["license_notice"],
+ android_license_files: [
+ "../../LicenseFile1",
+ "../../LicenseFile2",
+ ],
+ }
+ `,
+ },
+ {
+ name: "license rewriting with no Android.bp file in the expected location",
+ in: `
+ android_test {
+ name: "foo",
+ android_license_kinds: ["license_kind"],
+ android_license_conditions: ["license_notice"],
+ android_license_files: ["../../LicenseFile1", "../../LicenseFile2",],
+ }
+ `,
+ fs: pathtools.MockFs(map[string][]byte{
+ "a/b/c/d/Android.mk": []byte("this is not important."),
+ "a/b/LicenseFile1": []byte("LicenseFile1"),
+ "a/b/LicenseFile2": []byte("LicenseFile2"),
+ "a/Android.bp": []byte("license {\n\tname: \"reuse_a_b_license\",\n}\n"),
+ }),
+ path: relativePath,
+ out: `
+ // Error: No Android.bp file is found at path
+ // a/b
+ // Please add one there with the needed license module first.
+ // Then reset the default_applicable_licenses property below with the license module name.
+ package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "",
+ ],
+ }
+
+ android_test {
+ name: "foo",
+ android_license_kinds: ["license_kind"],
+ android_license_conditions: ["license_notice"],
+ android_license_files: [
+ "../../LicenseFile1",
+ "../../LicenseFile2",
+ ],
+ }
+ `,
+ },
+ {
+ name: "license rewriting with an Android.bp file without a license module",
+ in: `
+ android_test {
+ name: "foo",
+ android_license_kinds: ["license_kind"],
+ android_license_conditions: ["license_notice"],
+ android_license_files: ["../../LicenseFile1", "../../LicenseFile2",],
+ }
+ `,
+ fs: pathtools.MockFs(map[string][]byte{
+ "a/b/c/d/Android.mk": []byte("this is not important."),
+ "a/b/LicenseFile1": []byte("LicenseFile1"),
+ "a/b/LicenseFile2": []byte("LicenseFile2"),
+ "a/b/Android.bp": []byte("non_license {\n\tname: \"reuse_a_b_license\",\n}\n"),
+ }),
+ path: relativePath,
+ out: `
+ // Error: Cannot get the name of the license module in the
+ // a/b/Android.bp file.
+ // If no such license module exists, please add one there first.
+ // Then reset the default_applicable_licenses property below with the license module name.
+ package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "",
+ ],
+ }
+
+ android_test {
+ name: "foo",
+ android_license_kinds: ["license_kind"],
+ android_license_conditions: ["license_notice"],
+ android_license_files: [
+ "../../LicenseFile1",
+ "../../LicenseFile2",
+ ],
+ }
+ `,
+ },
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
- runPassOnce(t, test.in, test.out, runPatchListMod(rewriteLicenseProperties))
+ runPassOnce(t, test.in, test.out, runPatchListMod(rewriteLicenseProperty(test.fs, test.path)))
+ })
+ }
+
+ testErrs := []struct {
+ name string
+ in string
+ fs pathtools.FileSystem
+ path string
+ expectedErr string
+ }{
+ {
+ name: "license rewriting with a wrong path",
+ in: `
+ android_test {
+ name: "foo",
+ android_license_kinds: ["license_kind"],
+ android_license_conditions: ["license_notice"],
+ android_license_files: ["../../LicenseFile1", "../../LicenseFile2",],
+ }
+ `,
+ fs: mockFs,
+ path: relativePathErr,
+ expectedErr: `
+ Cannot find an Android.mk file at path a/b/c
+ `,
+ },
+ }
+ for _, test := range testErrs {
+ t.Run(test.name, func(t *testing.T) {
+ checkError(t, test.in, test.expectedErr, runPatchListMod(rewriteLicenseProperty(test.fs, test.path)))
})
}
}
diff --git a/build_test.bash b/build_test.bash
index b039285..b6d00e2 100755
--- a/build_test.bash
+++ b/build_test.bash
@@ -50,7 +50,9 @@
echo
echo "Free disk space:"
-df -h
+# Ignore df errors because it errors out on gvfsd file systems
+# but still displays most of the useful info we need
+df -h || true
echo
echo "Running Bazel smoke test..."
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 45bb1ca..636bab8 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -263,9 +263,10 @@
library.androidMkWriteExportedFlags(entries)
library.androidMkEntriesWriteAdditionalDependenciesForSourceAbiDiff(entries)
- _, _, ext := android.SplitFileExt(entries.OutputFile.Path().Base())
-
- entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
+ if entries.OutputFile.Valid() {
+ _, _, ext := android.SplitFileExt(entries.OutputFile.Path().Base())
+ entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
+ }
if library.coverageOutputFile.Valid() {
entries.SetString("LOCAL_PREBUILT_COVERAGE_ARCHIVE", library.coverageOutputFile.String())
diff --git a/cc/binary.go b/cc/binary.go
index a5afb07..50175d9 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -18,6 +18,7 @@
"path/filepath"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
"android/soong/android"
"android/soong/bazel"
@@ -68,13 +69,14 @@
// cc_binary produces a binary that is runnable on a device.
func BinaryFactory() android.Module {
- module, _ := NewBinary(android.HostAndDeviceSupported)
+ module, _ := newBinary(android.HostAndDeviceSupported, true)
return module.Init()
}
// cc_binary_host produces a binary that is runnable on a host.
func BinaryHostFactory() android.Module {
- module, _ := NewBinary(android.HostSupported)
+ module, _ := newBinary(android.HostSupported, true)
+ module.bazelable = true
return module.Init()
}
@@ -192,6 +194,10 @@
// Individual module implementations which comprise a C++ binary should call this function,
// set some fields on the result, and then call the Init function.
func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
+ return newBinary(hod, true)
+}
+
+func newBinary(hod android.HostOrDeviceSupported, bazelable bool) (*Module, *binaryDecorator) {
module := newModule(hod, android.MultilibFirst)
binary := &binaryDecorator{
baseLinker: NewBaseLinker(module.sanitize),
@@ -200,6 +206,7 @@
module.compiler = NewBaseCompiler()
module.linker = binary
module.installer = binary
+ module.bazelable = bazelable
// Allow module to be added as member of an sdk/module_exports.
module.sdkMemberTypes = []android.SdkMemberType{
@@ -344,6 +351,12 @@
flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--no-dynamic-linker")
}
+ if ctx.Darwin() && deps.DarwinSecondArchOutput.Valid() {
+ fatOutputFile := outputFile
+ outputFile = android.PathForModuleOut(ctx, "pre-fat", fileName)
+ transformDarwinUniversalBinary(ctx, fatOutputFile, outputFile, deps.DarwinSecondArchOutput.Path())
+ }
+
builderFlags := flagsToBuilderFlags(flags)
stripFlags := flagsToStripFlags(flags)
if binary.stripper.NeedsStrip(ctx) {
@@ -388,7 +401,7 @@
}
}
- var validations android.WritablePaths
+ var validations android.Paths
// Handle host bionic linker symbols.
if ctx.Os() == android.LinuxBionic && !binary.static() {
@@ -411,6 +424,7 @@
linkerDeps = append(linkerDeps, deps.EarlySharedLibsDeps...)
linkerDeps = append(linkerDeps, deps.SharedLibsDeps...)
linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...)
+ linkerDeps = append(linkerDeps, ndkSharedLibDeps(ctx)...)
}
validations = append(validations, objs.tidyFiles...)
@@ -543,33 +557,7 @@
})
}
-func init() {
- android.RegisterBp2BuildMutator("cc_binary", BinaryBp2build)
- android.RegisterBp2BuildMutator("cc_binary_host", BinaryHostBp2build)
-}
-
-func BinaryBp2build(ctx android.TopDownMutatorContext) {
- binaryBp2build(ctx, "cc_binary")
-}
-
-func BinaryHostBp2build(ctx android.TopDownMutatorContext) {
- binaryBp2build(ctx, "cc_binary_host")
-}
-
-func binaryBp2build(ctx android.TopDownMutatorContext, typ string) {
- m, ok := ctx.Module().(*Module)
- if !ok {
- // Not a cc module
- return
- }
- if !m.ConvertWithBp2build(ctx) {
- return
- }
-
- if ctx.ModuleType() != typ {
- return
- }
-
+func binaryBp2build(ctx android.TopDownMutatorContext, m *Module, typ string) {
var compatibleWith bazel.StringListAttribute
if typ == "cc_binary_host" {
//incompatible with android OS
@@ -578,9 +566,16 @@
}
baseAttrs := bp2BuildParseBaseProps(ctx, m)
+ binaryLinkerAttrs := bp2buildBinaryLinkerProps(ctx, m)
+
+ if proptools.BoolDefault(binaryLinkerAttrs.Linkshared, true) {
+ baseAttrs.implementationDynamicDeps.Add(baseAttrs.protoDependency)
+ } else {
+ baseAttrs.implementationDeps.Add(baseAttrs.protoDependency)
+ }
attrs := &binaryAttributes{
- binaryLinkerAttrs: bp2buildBinaryLinkerProps(ctx, m),
+ binaryLinkerAttrs: binaryLinkerAttrs,
Srcs: baseAttrs.srcs,
Srcs_c: baseAttrs.cSrcs,
diff --git a/cc/bp2build.go b/cc/bp2build.go
index d949436..6c1646c 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -27,9 +27,10 @@
)
const (
- cSrcPartition = "c"
- asSrcPartition = "as"
- cppSrcPartition = "cpp"
+ cSrcPartition = "c"
+ asSrcPartition = "as"
+ cppSrcPartition = "cpp"
+ protoSrcPartition = "proto"
)
// staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties --
@@ -41,52 +42,53 @@
Hdrs bazel.LabelListAttribute
Copts bazel.StringListAttribute
- Deps bazel.LabelListAttribute
- Implementation_deps bazel.LabelListAttribute
- Dynamic_deps bazel.LabelListAttribute
- Implementation_dynamic_deps bazel.LabelListAttribute
- Whole_archive_deps bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Implementation_deps bazel.LabelListAttribute
+ Dynamic_deps bazel.LabelListAttribute
+ Implementation_dynamic_deps bazel.LabelListAttribute
+ Whole_archive_deps bazel.LabelListAttribute
+ Implementation_whole_archive_deps bazel.LabelListAttribute
System_dynamic_deps bazel.LabelListAttribute
}
func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute {
- // Check that a module is a filegroup type named <label>.
- isFilegroupNamed := func(m android.Module, fullLabel string) bool {
- if ctx.OtherModuleType(m) != "filegroup" {
- return false
- }
- labelParts := strings.Split(fullLabel, ":")
- if len(labelParts) > 2 {
- // There should not be more than one colon in a label.
- ctx.ModuleErrorf("%s is not a valid Bazel label for a filegroup", fullLabel)
- }
- return m.Name() == labelParts[len(labelParts)-1]
+ // Check that a module is a filegroup type
+ isFilegroup := func(m blueprint.Module) bool {
+ return ctx.OtherModuleType(m) == "filegroup"
}
// Convert filegroup dependencies into extension-specific filegroups filtered in the filegroup.bzl
// macro.
addSuffixForFilegroup := func(suffix string) bazel.LabelMapper {
- return func(ctx bazel.OtherModuleContext, label string) (string, bool) {
- m, exists := ctx.ModuleFromName(label)
- if !exists {
- return label, false
+ return func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
+ m, exists := ctx.ModuleFromName(label.OriginalModuleName)
+ labelStr := label.Label
+ if !exists || !isFilegroup(m) {
+ return labelStr, false
}
- aModule, _ := m.(android.Module)
- if !isFilegroupNamed(aModule, label) {
- return label, false
- }
- return label + suffix, true
+ return labelStr + suffix, true
}
}
+ isProtoFilegroup := func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
+ m, exists := ctx.ModuleFromName(label.OriginalModuleName)
+ labelStr := label.Label
+ if !exists || !isFilegroup(m) {
+ return labelStr, false
+ }
+ likelyProtos := strings.HasSuffix(labelStr, "proto") || strings.HasSuffix(labelStr, "protos")
+ return labelStr, likelyProtos
+ }
+
// TODO(b/190006308): Handle language detection of sources in a Bazel rule.
partitioned := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{
cSrcPartition: bazel.LabelPartition{Extensions: []string{".c"}, LabelMapper: addSuffixForFilegroup("_c_srcs")},
asSrcPartition: bazel.LabelPartition{Extensions: []string{".s", ".S"}, LabelMapper: addSuffixForFilegroup("_as_srcs")},
// C++ is the "catch-all" group, and comprises generated sources because we don't
// know the language of these sources until the genrule is executed.
- cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true},
+ cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true},
+ protoSrcPartition: bazel.LabelPartition{Extensions: []string{".proto"}, LabelMapper: isProtoFilegroup},
})
return partitioned
@@ -195,6 +197,11 @@
attrs.Srcs_c = partitionedSrcs[cSrcPartition]
attrs.Srcs_as = partitionedSrcs[asSrcPartition]
+ if !partitionedSrcs[protoSrcPartition].IsEmpty() {
+ // TODO(b/208815215): determine whether this is used and add support if necessary
+ ctx.ModuleErrorf("Migrating static/shared only proto srcs is not currently supported")
+ }
+
return attrs
}
@@ -230,6 +237,8 @@
type baseAttributes struct {
compilerAttributes
linkerAttributes
+
+ protoDependency *bazel.LabelAttribute
}
// Convenience struct to hold all attributes parsed from compiler properties.
@@ -252,10 +261,15 @@
// Not affected by arch variants
stl *string
+ cStd *string
cppStd *string
localIncludes bazel.StringListAttribute
absoluteIncludes bazel.StringListAttribute
+
+ includes BazelIncludes
+
+ protoSrcs bazel.LabelListAttribute
}
func parseCommandLineFlags(soongFlags []string) []string {
@@ -278,8 +292,7 @@
localIncludeDirs := props.Local_include_dirs
if axis == bazel.NoConfigAxis {
- ca.cppStd = bp2buildResolveCppStdValue(props.Cpp_std, props.Gnu_extensions)
-
+ ca.cStd, ca.cppStd = bp2buildResolveCppStdValue(props.C_std, props.Cpp_std, props.Gnu_extensions)
if includeBuildDirectory(props.Include_build_directory) {
localIncludeDirs = append(localIncludeDirs, ".")
}
@@ -337,6 +350,8 @@
ca.srcs.ResolveExcludes()
partitionedSrcs := groupSrcsByExtension(ctx, ca.srcs)
+ ca.protoSrcs = partitionedSrcs[protoSrcPartition]
+
for p, lla := range partitionedSrcs {
// if there are no sources, there is no need for headers
if lla.IsEmpty() {
@@ -371,28 +386,63 @@
return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedSrcsLabelList), anySrcs
}
-func bp2buildResolveCppStdValue(cpp_std *string, gnu_extensions *bool) *string {
- var cppStd *string
- // If cpp_std is not specified, don't generate it in the
- // BUILD file. For readability purposes, cpp_std and gnu_extensions are
- // combined into a single -std=<version> copt, except in the
- // default case where cpp_std is nil and gnu_extensions is true or unspecified,
- // then the toolchain's default "gnu++17" will be used.
+func bp2buildResolveCppStdValue(c_std *string, cpp_std *string, gnu_extensions *bool) (*string, *string) {
+ var cStdVal, cppStdVal string
+ // If c{,pp}std properties are not specified, don't generate them in the BUILD file.
+ // Defaults are handled by the toolchain definition.
+ // However, if gnu_extensions is false, then the default gnu-to-c version must be specified.
if cpp_std != nil {
- // TODO(b/202491296): Handle C_std.
- // These transformations are shared with compiler.go.
- cppStdVal := parseCppStd(cpp_std)
- _, cppStdVal = maybeReplaceGnuToC(gnu_extensions, "", cppStdVal)
- cppStd = &cppStdVal
+ cppStdVal = parseCppStd(cpp_std)
} else if gnu_extensions != nil && !*gnu_extensions {
- cppStdVal := "c++17"
- cppStd = &cppStdVal
+ cppStdVal = "c++17"
}
- return cppStd
+ if c_std != nil {
+ cStdVal = parseCStd(c_std)
+ } else if gnu_extensions != nil && !*gnu_extensions {
+ cStdVal = "c99"
+ }
+
+ cStdVal, cppStdVal = maybeReplaceGnuToC(gnu_extensions, cStdVal, cppStdVal)
+ var c_std_prop, cpp_std_prop *string
+ if cStdVal != "" {
+ c_std_prop = &cStdVal
+ }
+ if cppStdVal != "" {
+ cpp_std_prop = &cppStdVal
+ }
+
+ return c_std_prop, cpp_std_prop
+}
+
+// packageFromLabel extracts package from a fully-qualified or relative Label and whether the label
+// is fully-qualified.
+// e.g. fully-qualified "//a/b:foo" -> "a/b", true, relative: ":bar" -> ".", false
+func packageFromLabel(label string) (string, bool) {
+ split := strings.Split(label, ":")
+ if len(split) != 2 {
+ return "", false
+ }
+ if split[0] == "" {
+ return ".", false
+ }
+ // remove leading "//"
+ return split[0][2:], true
+}
+
+// includesFromLabelList extracts relative/absolute includes from a bazel.LabelList>
+func includesFromLabelList(labelList bazel.LabelList) (relative, absolute []string) {
+ for _, hdr := range labelList.Includes {
+ if pkg, hasPkg := packageFromLabel(hdr.Label); hasPkg {
+ absolute = append(absolute, pkg)
+ } else if pkg != "" {
+ relative = append(relative, pkg)
+ }
+ }
+ return relative, absolute
}
// bp2BuildParseCompilerProps returns copts, srcs and hdrs and other attributes.
-func bp2BuildParseBaseProps(ctx android.BazelConversionPathContext, module *Module) baseAttributes {
+func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) baseAttributes {
archVariantCompilerProps := module.GetArchVariantProperties(ctx, &BaseCompilerProperties{})
archVariantLinkerProps := module.GetArchVariantProperties(ctx, &BaseLinkerProperties{})
@@ -434,6 +484,18 @@
headers := maybePartitionExportedAndImplementationsDeps(ctx, !module.Binary(), allHdrs, exportHdrs, android.BazelLabelForModuleDeps)
implementationHdrs.SetSelectValue(axis, config, headers.implementation)
compilerAttrs.hdrs.SetSelectValue(axis, config, headers.export)
+
+ exportIncludes, exportAbsoluteIncludes := includesFromLabelList(headers.export)
+ compilerAttrs.includes.Includes.SetSelectValue(axis, config, exportIncludes)
+ compilerAttrs.includes.AbsoluteIncludes.SetSelectValue(axis, config, exportAbsoluteIncludes)
+
+ includes, absoluteIncludes := includesFromLabelList(headers.implementation)
+ currAbsoluteIncludes := compilerAttrs.absoluteIncludes.SelectValue(axis, config)
+ currAbsoluteIncludes = android.FirstUniqueStrings(append(currAbsoluteIncludes, absoluteIncludes...))
+ compilerAttrs.absoluteIncludes.SetSelectValue(axis, config, currAbsoluteIncludes)
+ currIncludes := compilerAttrs.localIncludes.SelectValue(axis, config)
+ currIncludes = android.FirstUniqueStrings(append(currIncludes, includes...))
+ compilerAttrs.localIncludes.SetSelectValue(axis, config, currIncludes)
}
}
@@ -448,23 +510,34 @@
(&compilerAttrs).finalize(ctx, implementationHdrs)
(&linkerAttrs).finalize()
+ protoDep := bp2buildProto(ctx, module, compilerAttrs.protoSrcs)
+
+ // bp2buildProto will only set wholeStaticLib or implementationWholeStaticLib, but we don't know
+ // which. This will add the newly generated proto library to the appropriate attribute and nothing
+ // to the other
+ (&linkerAttrs).wholeArchiveDeps.Add(protoDep.wholeStaticLib)
+ (&linkerAttrs).implementationWholeArchiveDeps.Add(protoDep.implementationWholeStaticLib)
+
return baseAttributes{
compilerAttrs,
linkerAttrs,
+ protoDep.protoDep,
}
}
// Convenience struct to hold all attributes parsed from linker properties.
type linkerAttributes struct {
- deps bazel.LabelListAttribute
- implementationDeps bazel.LabelListAttribute
- dynamicDeps bazel.LabelListAttribute
- implementationDynamicDeps bazel.LabelListAttribute
- wholeArchiveDeps bazel.LabelListAttribute
- systemDynamicDeps bazel.LabelListAttribute
+ deps bazel.LabelListAttribute
+ implementationDeps bazel.LabelListAttribute
+ dynamicDeps bazel.LabelListAttribute
+ implementationDynamicDeps bazel.LabelListAttribute
+ wholeArchiveDeps bazel.LabelListAttribute
+ implementationWholeArchiveDeps bazel.LabelListAttribute
+ systemDynamicDeps bazel.LabelListAttribute
linkCrt bazel.BoolAttribute
useLibcrt bazel.BoolAttribute
+ useVersionLib bazel.BoolAttribute
linkopts bazel.StringListAttribute
additionalLinkerInputs bazel.LabelListAttribute
stripKeepSymbols bazel.BoolAttribute
@@ -534,6 +607,10 @@
la.linkopts.SetSelectValue(axis, config, linkerFlags)
la.useLibcrt.SetSelectValue(axis, config, props.libCrt())
+ if axis == bazel.NoConfigAxis {
+ la.useVersionLib.SetSelectValue(axis, config, props.Use_version_lib)
+ }
+
// it's very unlikely for nocrt to be arch variant, so bp2build doesn't support it.
if props.crt() != nil {
if axis == bazel.NoConfigAxis {
@@ -656,13 +733,14 @@
// BazelIncludes contains information about -I and -isystem paths from a module converted to Bazel
// attributes.
type BazelIncludes struct {
- Includes bazel.StringListAttribute
- SystemIncludes bazel.StringListAttribute
+ AbsoluteIncludes bazel.StringListAttribute
+ Includes bazel.StringListAttribute
+ SystemIncludes bazel.StringListAttribute
}
-func bp2BuildParseExportedIncludes(ctx android.BazelConversionPathContext, module *Module) BazelIncludes {
+func bp2BuildParseExportedIncludes(ctx android.BazelConversionPathContext, module *Module, existingIncludes BazelIncludes) BazelIncludes {
libraryDecorator := module.linker.(*libraryDecorator)
- return bp2BuildParseExportedIncludesHelper(ctx, module, libraryDecorator)
+ return bp2BuildParseExportedIncludesHelper(ctx, module, libraryDecorator, &existingIncludes)
}
// Bp2buildParseExportedIncludesForPrebuiltLibrary returns a BazelIncludes with Bazel-ified values
@@ -670,25 +748,31 @@
func Bp2BuildParseExportedIncludesForPrebuiltLibrary(ctx android.BazelConversionPathContext, module *Module) BazelIncludes {
prebuiltLibraryLinker := module.linker.(*prebuiltLibraryLinker)
libraryDecorator := prebuiltLibraryLinker.libraryDecorator
- return bp2BuildParseExportedIncludesHelper(ctx, module, libraryDecorator)
+ return bp2BuildParseExportedIncludesHelper(ctx, module, libraryDecorator, nil)
}
// bp2BuildParseExportedIncludes creates a string list attribute contains the
// exported included directories of a module.
-func bp2BuildParseExportedIncludesHelper(ctx android.BazelConversionPathContext, module *Module, libraryDecorator *libraryDecorator) BazelIncludes {
- exported := BazelIncludes{}
+func bp2BuildParseExportedIncludesHelper(ctx android.BazelConversionPathContext, module *Module, libraryDecorator *libraryDecorator, includes *BazelIncludes) BazelIncludes {
+ var exported BazelIncludes
+ if includes != nil {
+ exported = *includes
+ } else {
+ exported = BazelIncludes{}
+ }
for axis, configToProps := range module.GetArchVariantProperties(ctx, &FlagExporterProperties{}) {
for config, props := range configToProps {
if flagExporterProperties, ok := props.(*FlagExporterProperties); ok {
if len(flagExporterProperties.Export_include_dirs) > 0 {
- exported.Includes.SetSelectValue(axis, config, flagExporterProperties.Export_include_dirs)
+ exported.Includes.SetSelectValue(axis, config, android.FirstUniqueStrings(append(exported.Includes.SelectValue(axis, config), flagExporterProperties.Export_include_dirs...)))
}
if len(flagExporterProperties.Export_system_include_dirs) > 0 {
- exported.SystemIncludes.SetSelectValue(axis, config, flagExporterProperties.Export_system_include_dirs)
+ exported.SystemIncludes.SetSelectValue(axis, config, android.FirstUniqueStrings(append(exported.SystemIncludes.SelectValue(axis, config), flagExporterProperties.Export_system_include_dirs...)))
}
}
}
}
+ exported.AbsoluteIncludes.DeduplicateAxesFromBase()
exported.Includes.DeduplicateAxesFromBase()
exported.SystemIncludes.DeduplicateAxesFromBase()
diff --git a/cc/builder.go b/cc/builder.go
index 72c2fa5..8af2255 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -165,6 +165,12 @@
}
}()
+ darwinLipo = pctx.AndroidStaticRule("darwinLipo",
+ blueprint.RuleParams{
+ Command: "${config.MacLipoPath} -create -output $out $in",
+ CommandDeps: []string{"${config.MacLipoPath}"},
+ })
+
_ = pctx.SourcePathVariable("archiveRepackPath", "build/soong/scripts/archive_repack.sh")
// Rule to repack an archive (.a) file with a subset of object files.
@@ -413,7 +419,7 @@
// Objects is a collection of file paths corresponding to outputs for C++ related build statements.
type Objects struct {
objFiles android.Paths
- tidyFiles android.WritablePaths
+ tidyFiles android.Paths
coverageFiles android.Paths
sAbiDumpFiles android.Paths
kytheFiles android.Paths
@@ -422,7 +428,7 @@
func (a Objects) Copy() Objects {
return Objects{
objFiles: append(android.Paths{}, a.objFiles...),
- tidyFiles: append(android.WritablePaths{}, a.tidyFiles...),
+ tidyFiles: append(android.Paths{}, a.tidyFiles...),
coverageFiles: append(android.Paths{}, a.coverageFiles...),
sAbiDumpFiles: append(android.Paths{}, a.sAbiDumpFiles...),
kytheFiles: append(android.Paths{}, a.kytheFiles...),
@@ -451,11 +457,11 @@
// Source files are one-to-one with tidy, coverage, or kythe files, if enabled.
objFiles := make(android.Paths, len(srcFiles))
- var tidyFiles android.WritablePaths
+ var tidyFiles android.Paths
noTidySrcsMap := make(map[android.Path]bool)
var tidyVars string
if flags.tidy {
- tidyFiles = make(android.WritablePaths, 0, len(srcFiles))
+ tidyFiles = make(android.Paths, 0, len(srcFiles))
for _, path := range noTidySrcs {
noTidySrcsMap[path] = true
}
@@ -665,7 +671,6 @@
rule = clangTidyRE
}
- ctx.TidyFile(tidyFile)
ctx.Build(pctx, android.BuildParams{
Rule: rule,
Description: "clang-tidy " + srcFile.Rel(),
@@ -719,7 +724,7 @@
// Generate a rule for compiling multiple .o files to a static library (.a)
func transformObjToStaticLib(ctx android.ModuleContext,
objFiles android.Paths, wholeStaticLibs android.Paths,
- flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths, validations android.WritablePaths) {
+ flags builderFlags, outputFile android.ModuleOutPath, deps android.Paths, validations android.Paths) {
arCmd := "${config.ClangBin}/llvm-ar"
arFlags := ""
@@ -734,7 +739,7 @@
Output: outputFile,
Inputs: objFiles,
Implicits: deps,
- Validations: validations.Paths(),
+ Validations: validations,
Args: map[string]string{
"arFlags": "crsPD" + arFlags,
"arCmd": arCmd,
@@ -764,7 +769,7 @@
func transformObjToDynamicBinary(ctx android.ModuleContext,
objFiles, sharedLibs, staticLibs, lateStaticLibs, wholeStaticLibs, deps, crtBegin, crtEnd android.Paths,
groupLate bool, flags builderFlags, outputFile android.WritablePath,
- implicitOutputs android.WritablePaths, validations android.WritablePaths) {
+ implicitOutputs android.WritablePaths, validations android.Paths) {
ldCmd := "${config.ClangBin}/clang++"
@@ -831,7 +836,7 @@
Inputs: objFiles,
Implicits: deps,
OrderOnly: sharedLibs,
- Validations: validations.Paths(),
+ Validations: validations,
Args: args,
})
}
@@ -1060,6 +1065,15 @@
})
}
+func transformDarwinUniversalBinary(ctx android.ModuleContext, outputFile android.WritablePath, inputFiles ...android.Path) {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: darwinLipo,
+ Description: "lipo " + outputFile.Base(),
+ Output: outputFile,
+ Inputs: inputFiles,
+ })
+}
+
// Registers build statement to zip one or more coverage files.
func transformCoverageFilesToZip(ctx android.ModuleContext,
inputs Objects, baseName string) android.OptionalPath {
diff --git a/cc/cc.go b/cc/cc.go
index 113620c..5c4edb9 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -167,6 +167,10 @@
// Path to the dynamic linker binary
DynamicLinker android.OptionalPath
+
+ // For Darwin builds, the path to the second architecture's output that should
+ // be combined with this architectures's output into a FAT MachO file.
+ DarwinSecondArchOutput android.OptionalPath
}
// LocalOrGlobalFlags contains flags that need to have values set globally by the build system or locally by the module
@@ -682,6 +686,15 @@
return d.Kind == staticLibraryDependency
}
+func (d libraryDependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
+ if d.shared() {
+ return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency}
+ }
+ return nil
+}
+
+var _ android.LicenseAnnotationsDependencyTag = libraryDependencyTag{}
+
// InstallDepNeeded returns true for shared libraries so that shared library dependencies of
// binaries or other shared libraries are installed as dependencies.
func (d libraryDependencyTag) InstallDepNeeded() bool {
@@ -773,8 +786,9 @@
Properties BaseProperties
// initialize before calling Init
- hod android.HostOrDeviceSupported
- multilib android.Multilib
+ hod android.HostOrDeviceSupported
+ multilib android.Multilib
+ bazelable bool
// Allowable SdkMemberTypes of this module type.
sdkMemberTypes []android.SdkMemberType
@@ -815,6 +829,10 @@
makeLinkType string
// Kythe (source file indexer) paths for this compilation module
kytheFiles android.Paths
+ // Object .o file output paths for this compilation module
+ objFiles android.Paths
+ // Tidy .tidy file output paths for this compilation module
+ tidyFiles android.Paths
// For apex variants, this is set as apex.min_sdk_version
apexSdkVersion android.ApiLevel
@@ -1133,7 +1151,9 @@
}
android.InitAndroidArchModule(c, c.hod, c.multilib)
- android.InitBazelModule(c)
+ if c.bazelable {
+ android.InitBazelModule(c)
+ }
android.InitApexModule(c)
android.InitSdkAwareModule(c)
android.InitDefaultableModule(c)
@@ -1713,7 +1733,15 @@
// Returns true if Bazel was successfully used for the analysis of this module.
func (c *Module) maybeGenerateBazelActions(actx android.ModuleContext) bool {
- bazelModuleLabel := c.GetBazelLabel(actx, c)
+ var bazelModuleLabel string
+ if actx.ModuleType() == "cc_library" && c.static() {
+ // cc_library is a special case in bp2build; two targets are generated -- one for each
+ // of the shared and static variants. The shared variant keeps the module name, but the
+ // static variant uses a different suffixed name.
+ bazelModuleLabel = bazelLabelForStaticModule(actx, c)
+ } else {
+ bazelModuleLabel = c.GetBazelLabel(actx, c)
+ }
bazelActionsUsed := false
// Mixed builds mode is disabled for modules outside of device OS.
// TODO(b/200841190): Support non-device OS in mixed builds.
@@ -1827,6 +1855,8 @@
return
}
c.kytheFiles = objs.kytheFiles
+ c.objFiles = objs.objFiles
+ c.tidyFiles = objs.tidyFiles
}
if c.linker != nil {
@@ -2570,6 +2600,11 @@
depName := ctx.OtherModuleName(dep)
depTag := ctx.OtherModuleDependencyTag(dep)
+ if depTag == android.DarwinUniversalVariantTag {
+ depPaths.DarwinSecondArchOutput = dep.(*Module).OutputFile()
+ return
+ }
+
ccDep, ok := dep.(LinkableInterface)
if !ok {
@@ -3153,6 +3188,24 @@
return false
}
+func (c *Module) benchmarkBinary() bool {
+ if b, ok := c.linker.(interface {
+ benchmarkBinary() bool
+ }); ok {
+ return b.benchmarkBinary()
+ }
+ return false
+}
+
+func (c *Module) fuzzBinary() bool {
+ if f, ok := c.linker.(interface {
+ fuzzBinary() bool
+ }); ok {
+ return f.fuzzBinary()
+ }
+ return false
+}
+
// Header returns true if the module is a header-only variant. (See cc/library.go header()).
func (c *Module) Header() bool {
if h, ok := c.linker.(interface {
@@ -3398,6 +3451,45 @@
var _ snapshot.RelativeInstallPath = (*Module)(nil)
+// ConvertWithBp2build converts Module to Bazel for bp2build.
+func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ prebuilt := c.IsPrebuilt()
+ if c.Binary() {
+ if !prebuilt {
+ binaryBp2build(ctx, c, ctx.ModuleType())
+ }
+ } else if c.Object() {
+ if !prebuilt {
+ objectBp2Build(ctx, c)
+ }
+ } else if c.CcLibrary() {
+ static := c.BuildStaticVariant()
+ shared := c.BuildSharedVariant()
+
+ if static && shared {
+ if !prebuilt {
+ libraryBp2Build(ctx, c)
+ }
+ } else if !static && !shared {
+ if !prebuilt {
+ libraryHeadersBp2Build(ctx, c)
+ }
+ } else if static {
+ if prebuilt {
+ prebuiltLibraryStaticBp2Build(ctx, c)
+ } else {
+ sharedOrStaticLibraryBp2Build(ctx, c, true)
+ }
+ } else if shared {
+ if prebuilt {
+ prebuiltLibrarySharedBp2Build(ctx, c)
+ } else {
+ sharedOrStaticLibraryBp2Build(ctx, c, false)
+ }
+ }
+ }
+}
+
//
// Defaults
//
diff --git a/cc/compiler.go b/cc/compiler.go
index ffe8b2e..8adc3ab 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -304,11 +304,24 @@
cppStd := String(cppStdPtr)
switch cppStd {
case "":
- cppStd = config.CppStdVersion
+ return config.CppStdVersion
case "experimental":
- cppStd = config.ExperimentalCppStdVersion
+ return config.ExperimentalCppStdVersion
+ default:
+ return cppStd
}
- return cppStd
+}
+
+func parseCStd(cStdPtr *string) string {
+ cStd := String(cStdPtr)
+ switch cStd {
+ case "":
+ return config.CStdVersion
+ case "experimental":
+ return config.ExperimentalCStdVersion
+ default:
+ return cStd
+ }
}
// Create a Flags struct that collects the compile flags from global values,
@@ -479,13 +492,7 @@
flags.Global.CommonFlags = append(flags.Global.CommonFlags, tc.ToolchainCflags())
- cStd := config.CStdVersion
- if String(compiler.Properties.C_std) == "experimental" {
- cStd = config.ExperimentalCStdVersion
- } else if String(compiler.Properties.C_std) != "" {
- cStd = String(compiler.Properties.C_std)
- }
-
+ cStd := parseCStd(compiler.Properties.C_std)
cppStd := parseCppStd(compiler.Properties.Cpp_std)
cStd, cppStd = maybeReplaceGnuToC(compiler.Properties.Gnu_extensions, cStd, cppStd)
@@ -630,9 +637,9 @@
func ndkPathDeps(ctx ModuleContext) android.Paths {
if ctx.Module().(*Module).IsSdkVariant() {
- // The NDK sysroot timestamp file depends on all the NDK sysroot files
- // (headers and libraries).
- return android.Paths{getNdkBaseTimestampFile(ctx)}
+ // The NDK sysroot timestamp file depends on all the NDK sysroot header files
+ // for compiling src to obj files.
+ return android.Paths{getNdkHeadersTimestampFile(ctx)}
}
return nil
}
diff --git a/cc/config/darwin_host.go b/cc/config/darwin_host.go
index 318acb4..206bec1 100644
--- a/cc/config/darwin_host.go
+++ b/cc/config/darwin_host.go
@@ -54,6 +54,7 @@
darwinSupportedSdkVersions = []string{
"11",
+ "12",
}
darwinAvailableLibraries = append(
@@ -87,6 +88,10 @@
return getMacTools(ctx).arPath
})
+ pctx.VariableFunc("MacLipoPath", func(ctx android.PackageVarContext) string {
+ return getMacTools(ctx).lipoPath
+ })
+
pctx.VariableFunc("MacStripPath", func(ctx android.PackageVarContext) string {
return getMacTools(ctx).stripPath
})
@@ -118,6 +123,7 @@
sdkRoot string
arPath string
+ lipoPath string
stripPath string
toolPath string
}
@@ -157,6 +163,7 @@
macTools.sdkRoot = xcrun("--show-sdk-path")
macTools.arPath = xcrun("--find", "ar")
+ macTools.lipoPath = xcrun("--find", "lipo")
macTools.stripPath = xcrun("--find", "strip")
macTools.toolPath = filepath.Dir(xcrun("--find", "ld"))
})
diff --git a/cc/config/global.go b/cc/config/global.go
index 0b229be..a340e46 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -46,7 +46,6 @@
"-O2",
"-g",
- "-fdebug-info-for-profiling",
"-fno-strict-aliasing",
@@ -125,6 +124,9 @@
"-Werror=sequence-point",
"-Werror=format-security",
"-nostdlibinc",
+
+ // Emit additional debug info for AutoFDO
+ "-fdebug-info-for-profiling",
}
deviceGlobalCppflags = []string{
diff --git a/cc/fuzz.go b/cc/fuzz.go
index e987fe4..23d81d6 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -52,6 +52,10 @@
installedSharedDeps []string
}
+func (fuzz *fuzzBinary) fuzzBinary() bool {
+ return true
+}
+
func (fuzz *fuzzBinary) linkerProps() []interface{} {
props := fuzz.binaryDecorator.linkerProps()
props = append(props, &fuzz.fuzzPackagedModule.FuzzProperties)
@@ -234,7 +238,7 @@
}
func NewFuzz(hod android.HostOrDeviceSupported) *Module {
- module, binary := NewBinary(hod)
+ module, binary := newBinary(hod, false)
binary.baseInstaller = NewFuzzInstaller()
module.sanitize.SetSanitizer(Fuzzer, true)
diff --git a/cc/libbuildversion/Android.bp b/cc/libbuildversion/Android.bp
index 4debb1c..b105a30 100644
--- a/cc/libbuildversion/Android.bp
+++ b/cc/libbuildversion/Android.bp
@@ -14,8 +14,10 @@
enabled: true,
},
},
+ min_sdk_version: "26",
apex_available: [
"//apex_available:platform",
"//apex_available:anyapex",
],
+ vendor_available: true,
}
diff --git a/cc/libbuildversion/libbuildversion.cpp b/cc/libbuildversion/libbuildversion.cpp
index 5242025..1e01c11 100644
--- a/cc/libbuildversion/libbuildversion.cpp
+++ b/cc/libbuildversion/libbuildversion.cpp
@@ -36,7 +36,11 @@
return soong_build_number;
}
+#ifdef __ANDROID_VENDOR__
+ const prop_info* pi = __system_property_find("ro.vendor.build.version.incremental");
+#else
const prop_info* pi = __system_property_find("ro.build.version.incremental");
+#endif
if (pi == nullptr) return "";
std::string property_value;
diff --git a/cc/library.go b/cc/library.go
index dbf927d..216c124 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -207,10 +207,6 @@
func init() {
RegisterLibraryBuildComponents(android.InitRegistrationContext)
-
- android.RegisterBp2BuildMutator("cc_library_static", CcLibraryStaticBp2Build)
- android.RegisterBp2BuildMutator("cc_library_shared", CcLibrarySharedBp2Build)
- android.RegisterBp2BuildMutator("cc_library", CcLibraryBp2Build)
}
func RegisterLibraryBuildComponents(ctx android.RegistrationContext) {
@@ -236,12 +232,13 @@
Hdrs bazel.LabelListAttribute
- Deps bazel.LabelListAttribute
- Implementation_deps bazel.LabelListAttribute
- Dynamic_deps bazel.LabelListAttribute
- Implementation_dynamic_deps bazel.LabelListAttribute
- Whole_archive_deps bazel.LabelListAttribute
- System_dynamic_deps bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Implementation_deps bazel.LabelListAttribute
+ Dynamic_deps bazel.LabelListAttribute
+ Implementation_dynamic_deps bazel.LabelListAttribute
+ Whole_archive_deps bazel.LabelListAttribute
+ Implementation_whole_archive_deps bazel.LabelListAttribute
+ System_dynamic_deps bazel.LabelListAttribute
Export_includes bazel.StringListAttribute
Export_system_includes bazel.StringListAttribute
@@ -253,6 +250,7 @@
Stl *string
Cpp_std *string
+ C_std *string
// This is shared only.
Link_crt bazel.BoolAttribute
@@ -275,21 +273,12 @@
None bazel.BoolAttribute
}
-func CcLibraryBp2Build(ctx android.TopDownMutatorContext) {
- m, ok := ctx.Module().(*Module)
- if !ok || !m.ConvertWithBp2build(ctx) {
- return
- }
-
- if ctx.ModuleType() != "cc_library" {
- return
- }
-
+func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
// For some cc_library modules, their static variants are ready to be
// converted, but not their shared variants. For these modules, delegate to
// the cc_library_static bp2build converter temporarily instead.
if android.GenerateCcLibraryStaticOnly(ctx.Module().Name()) {
- ccSharedOrStaticBp2BuildMutatorInternal(ctx, m, "cc_library_static")
+ sharedOrStaticLibraryBp2Build(ctx, m, true)
return
}
@@ -298,43 +287,89 @@
baseAttributes := bp2BuildParseBaseProps(ctx, m)
compilerAttrs := baseAttributes.compilerAttributes
linkerAttrs := baseAttributes.linkerAttributes
- exportedIncludes := bp2BuildParseExportedIncludes(ctx, m)
+ exportedIncludes := bp2BuildParseExportedIncludes(ctx, m, compilerAttrs.includes)
srcs := compilerAttrs.srcs
+ sharedAttrs.Dynamic_deps.Add(baseAttributes.protoDependency)
+ staticAttrs.Deps.Add(baseAttributes.protoDependency)
+
asFlags := compilerAttrs.asFlags
if compilerAttrs.asSrcs.IsEmpty() && sharedAttrs.Srcs_as.IsEmpty() && staticAttrs.Srcs_as.IsEmpty() {
// Skip asflags for BUILD file simplicity if there are no assembly sources.
asFlags = bazel.MakeStringListAttribute(nil)
}
- attrs := &bazelCcLibraryAttributes{
- Srcs: srcs,
- Srcs_c: compilerAttrs.cSrcs,
- Srcs_as: compilerAttrs.asSrcs,
- Hdrs: compilerAttrs.hdrs,
+ staticCommonAttrs := staticOrSharedAttributes{
+ Srcs: *srcs.Clone().Append(staticAttrs.Srcs),
+ Srcs_c: *compilerAttrs.cSrcs.Clone().Append(staticAttrs.Srcs_c),
+ Srcs_as: *compilerAttrs.asSrcs.Clone().Append(staticAttrs.Srcs_as),
+ Copts: *compilerAttrs.copts.Clone().Append(staticAttrs.Copts),
+ Hdrs: *compilerAttrs.hdrs.Clone().Append(staticAttrs.Hdrs),
- Copts: compilerAttrs.copts,
+ Deps: *linkerAttrs.deps.Clone().Append(staticAttrs.Deps),
+ Implementation_deps: *linkerAttrs.implementationDeps.Clone().Append(staticAttrs.Implementation_deps),
+ Dynamic_deps: *linkerAttrs.dynamicDeps.Clone().Append(staticAttrs.Dynamic_deps),
+ Implementation_dynamic_deps: *linkerAttrs.implementationDynamicDeps.Clone().Append(staticAttrs.Implementation_dynamic_deps),
+ Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps,
+ Whole_archive_deps: *linkerAttrs.wholeArchiveDeps.Clone().Append(staticAttrs.Whole_archive_deps),
+ System_dynamic_deps: *linkerAttrs.systemDynamicDeps.Clone().Append(staticAttrs.System_dynamic_deps),
+ }
+
+ sharedCommonAttrs := staticOrSharedAttributes{
+ Srcs: *srcs.Clone().Append(sharedAttrs.Srcs),
+ Srcs_c: *compilerAttrs.cSrcs.Clone().Append(sharedAttrs.Srcs_c),
+ Srcs_as: *compilerAttrs.asSrcs.Clone().Append(sharedAttrs.Srcs_as),
+ Copts: *compilerAttrs.copts.Clone().Append(sharedAttrs.Copts),
+ Hdrs: *compilerAttrs.hdrs.Clone().Append(sharedAttrs.Hdrs),
+
+ Deps: *linkerAttrs.deps.Clone().Append(sharedAttrs.Deps),
+ Implementation_deps: *linkerAttrs.implementationDeps.Clone().Append(sharedAttrs.Implementation_deps),
+ Dynamic_deps: *linkerAttrs.dynamicDeps.Clone().Append(sharedAttrs.Dynamic_deps),
+ Implementation_dynamic_deps: *linkerAttrs.implementationDynamicDeps.Clone().Append(sharedAttrs.Implementation_dynamic_deps),
+ Whole_archive_deps: *linkerAttrs.wholeArchiveDeps.Clone().Append(sharedAttrs.Whole_archive_deps),
+ System_dynamic_deps: *linkerAttrs.systemDynamicDeps.Clone().Append(sharedAttrs.System_dynamic_deps),
+ }
+
+ staticTargetAttrs := &bazelCcLibraryStaticAttributes{
+ staticOrSharedAttributes: staticCommonAttrs,
+
Cppflags: compilerAttrs.cppFlags,
Conlyflags: compilerAttrs.conlyFlags,
Asflags: asFlags,
- Implementation_deps: linkerAttrs.implementationDeps,
- Deps: linkerAttrs.deps,
- Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps,
- Dynamic_deps: linkerAttrs.dynamicDeps,
- Whole_archive_deps: linkerAttrs.wholeArchiveDeps,
- System_dynamic_deps: linkerAttrs.systemDynamicDeps,
- Export_includes: exportedIncludes.Includes,
- Export_system_includes: exportedIncludes.SystemIncludes,
- Local_includes: compilerAttrs.localIncludes,
- Absolute_includes: compilerAttrs.absoluteIncludes,
- Linkopts: linkerAttrs.linkopts,
- Link_crt: linkerAttrs.linkCrt,
- Use_libcrt: linkerAttrs.useLibcrt,
- Rtti: compilerAttrs.rtti,
- Stl: compilerAttrs.stl,
- Cpp_std: compilerAttrs.cppStd,
+ Export_includes: exportedIncludes.Includes,
+ Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
+ Export_system_includes: exportedIncludes.SystemIncludes,
+ Local_includes: compilerAttrs.localIncludes,
+ Absolute_includes: compilerAttrs.absoluteIncludes,
+ Use_libcrt: linkerAttrs.useLibcrt,
+ Rtti: compilerAttrs.rtti,
+ Stl: compilerAttrs.stl,
+ Cpp_std: compilerAttrs.cppStd,
+ C_std: compilerAttrs.cStd,
+
+ Features: linkerAttrs.features,
+ }
+
+ sharedTargetAttrs := &bazelCcLibrarySharedAttributes{
+ staticOrSharedAttributes: sharedCommonAttrs,
+ Cppflags: compilerAttrs.cppFlags,
+ Conlyflags: compilerAttrs.conlyFlags,
+ Asflags: asFlags,
+
+ Export_includes: exportedIncludes.Includes,
+ Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
+ Export_system_includes: exportedIncludes.SystemIncludes,
+ Local_includes: compilerAttrs.localIncludes,
+ Absolute_includes: compilerAttrs.absoluteIncludes,
+ Linkopts: linkerAttrs.linkopts,
+ Link_crt: linkerAttrs.linkCrt,
+ Use_libcrt: linkerAttrs.useLibcrt,
+ Rtti: compilerAttrs.rtti,
+ Stl: compilerAttrs.stl,
+ Cpp_std: compilerAttrs.cppStd,
+ C_std: compilerAttrs.cStd,
Additional_linker_inputs: linkerAttrs.additionalLinkerInputs,
@@ -345,20 +380,20 @@
All: linkerAttrs.stripAll,
None: linkerAttrs.stripNone,
},
-
- Shared: sharedAttrs,
-
- Static: staticAttrs,
-
Features: linkerAttrs.features,
}
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "cc_library",
- Bzl_load_location: "//build/bazel/rules:full_cc_library.bzl",
+ staticProps := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_library_static",
+ Bzl_load_location: "//build/bazel/rules:cc_library_static.bzl",
+ }
+ sharedProps := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_library_shared",
+ Bzl_load_location: "//build/bazel/rules:cc_library_shared.bzl",
}
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
+ ctx.CreateBazelTargetModule(staticProps, android.CommonAttributes{Name: m.Name() + "_bp2build_cc_library_static"}, staticTargetAttrs)
+ ctx.CreateBazelTargetModule(sharedProps, android.CommonAttributes{Name: m.Name()}, sharedTargetAttrs)
}
// cc_library creates both static and/or shared libraries for a device and/or
@@ -373,6 +408,7 @@
staticLibrarySdkMemberType,
staticAndSharedLibrarySdkMemberType,
}
+ module.bazelable = true
module.bazelHandler = &ccLibraryBazelHandler{module: module}
return module.Init()
}
@@ -382,6 +418,7 @@
module, library := NewLibrary(android.HostAndDeviceSupported)
library.BuildOnlyStatic()
module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
+ module.bazelable = true
module.bazelHandler = &ccLibraryBazelHandler{module: module}
return module.Init()
}
@@ -391,6 +428,7 @@
module, library := NewLibrary(android.HostAndDeviceSupported)
library.BuildOnlyShared()
module.sdkMemberTypes = []android.SdkMemberType{sharedLibrarySdkMemberType}
+ module.bazelable = true
module.bazelHandler = &ccLibraryBazelHandler{module: module}
return module.Init()
}
@@ -409,6 +447,8 @@
module, library := NewLibrary(android.HostSupported)
library.BuildOnlyShared()
module.sdkMemberTypes = []android.SdkMemberType{sharedLibrarySdkMemberType}
+ module.bazelable = true
+ module.bazelHandler = &ccLibraryBazelHandler{module: module}
return module.Init()
}
@@ -1320,11 +1360,21 @@
return outputFile
}
+func ndkSharedLibDeps(ctx ModuleContext) android.Paths {
+ if ctx.Module().(*Module).IsSdkVariant() {
+ // The NDK sysroot timestamp file depends on all the NDK
+ // sysroot header and shared library files.
+ return android.Paths{getNdkBaseTimestampFile(ctx)}
+ }
+ return nil
+}
+
func (library *libraryDecorator) linkShared(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
var linkerDeps android.Paths
linkerDeps = append(linkerDeps, flags.LdFlagsDeps...)
+ linkerDeps = append(linkerDeps, ndkSharedLibDeps(ctx)...)
unexportedSymbols := ctx.ExpandOptionalSource(library.Properties.Unexported_symbols_list, "unexported_symbols_list")
forceNotWeakSymbols := ctx.ExpandOptionalSource(library.Properties.Force_symbols_not_weak_list, "force_symbols_not_weak_list")
@@ -1373,6 +1423,12 @@
builderFlags := flagsToBuilderFlags(flags)
+ if ctx.Darwin() && deps.DarwinSecondArchOutput.Valid() {
+ fatOutputFile := outputFile
+ outputFile = android.PathForModuleOut(ctx, "pre-fat", fileName)
+ transformDarwinUniversalBinary(ctx, fatOutputFile, outputFile, deps.DarwinSecondArchOutput.Path())
+ }
+
// Optimize out relinking against shared libraries whose interface hasn't changed by
// depending on a table of contents file instead of the library itself.
tocFile := outputFile.ReplaceExtension(ctx, flags.Toolchain.ShlibSuffix()[1:]+".toc")
@@ -2349,30 +2405,12 @@
return outputFile
}
-func ccSharedOrStaticBp2BuildMutator(ctx android.TopDownMutatorContext, modType string) {
- module, ok := ctx.Module().(*Module)
- if !ok {
- // Not a cc module
- return
- }
- if !module.ConvertWithBp2build(ctx) {
- return
- }
-
- ccSharedOrStaticBp2BuildMutatorInternal(ctx, module, modType)
-}
-
-func ccSharedOrStaticBp2BuildMutatorInternal(ctx android.TopDownMutatorContext, module *Module, modType string) {
- if modType != "cc_library_static" && modType != "cc_library_shared" {
- panic("ccSharedOrStaticBp2BuildMutatorInternal only supports cc_library_{static,shared}")
- }
- isStatic := modType == "cc_library_static"
-
+func sharedOrStaticLibraryBp2Build(ctx android.TopDownMutatorContext, module *Module, isStatic bool) {
baseAttributes := bp2BuildParseBaseProps(ctx, module)
compilerAttrs := baseAttributes.compilerAttributes
linkerAttrs := baseAttributes.linkerAttributes
- exportedIncludes := bp2BuildParseExportedIncludes(ctx, module)
+ exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, compilerAttrs.includes)
// Append shared/static{} stanza properties. These won't be specified on
// cc_library_* itself, but may be specified in cc_defaults that this module
@@ -2403,27 +2441,34 @@
Copts: compilerAttrs.copts,
Hdrs: compilerAttrs.hdrs,
- Deps: linkerAttrs.deps,
- Implementation_deps: linkerAttrs.implementationDeps,
- Dynamic_deps: linkerAttrs.dynamicDeps,
- Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps,
- Whole_archive_deps: linkerAttrs.wholeArchiveDeps,
- System_dynamic_deps: linkerAttrs.systemDynamicDeps,
+ Deps: linkerAttrs.deps,
+ Implementation_deps: linkerAttrs.implementationDeps,
+ Dynamic_deps: linkerAttrs.dynamicDeps,
+ Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps,
+ Whole_archive_deps: linkerAttrs.wholeArchiveDeps,
+ Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps,
+ System_dynamic_deps: linkerAttrs.systemDynamicDeps,
}
var attrs interface{}
if isStatic {
+ commonAttrs.Deps.Add(baseAttributes.protoDependency)
attrs = &bazelCcLibraryStaticAttributes{
staticOrSharedAttributes: commonAttrs,
- Use_libcrt: linkerAttrs.useLibcrt,
- Rtti: compilerAttrs.rtti,
- Stl: compilerAttrs.stl,
- Cpp_std: compilerAttrs.cppStd,
- Export_includes: exportedIncludes.Includes,
- Export_system_includes: exportedIncludes.SystemIncludes,
- Local_includes: compilerAttrs.localIncludes,
- Absolute_includes: compilerAttrs.absoluteIncludes,
+ Use_libcrt: linkerAttrs.useLibcrt,
+ Use_version_lib: linkerAttrs.useVersionLib,
+
+ Rtti: compilerAttrs.rtti,
+ Stl: compilerAttrs.stl,
+ Cpp_std: compilerAttrs.cppStd,
+ C_std: compilerAttrs.cStd,
+
+ Export_includes: exportedIncludes.Includes,
+ Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
+ Export_system_includes: exportedIncludes.SystemIncludes,
+ Local_includes: compilerAttrs.localIncludes,
+ Absolute_includes: compilerAttrs.absoluteIncludes,
Cppflags: compilerAttrs.cppFlags,
Conlyflags: compilerAttrs.conlyFlags,
@@ -2432,21 +2477,27 @@
Features: linkerAttrs.features,
}
} else {
+ commonAttrs.Dynamic_deps.Add(baseAttributes.protoDependency)
+
attrs = &bazelCcLibrarySharedAttributes{
staticOrSharedAttributes: commonAttrs,
Cppflags: compilerAttrs.cppFlags,
Conlyflags: compilerAttrs.conlyFlags,
Asflags: asFlags,
- Linkopts: linkerAttrs.linkopts,
- Link_crt: linkerAttrs.linkCrt,
- Use_libcrt: linkerAttrs.useLibcrt,
- Rtti: compilerAttrs.rtti,
- Stl: compilerAttrs.stl,
- Cpp_std: compilerAttrs.cppStd,
+ Linkopts: linkerAttrs.linkopts,
+ Link_crt: linkerAttrs.linkCrt,
+ Use_libcrt: linkerAttrs.useLibcrt,
+ Use_version_lib: linkerAttrs.useVersionLib,
+
+ Rtti: compilerAttrs.rtti,
+ Stl: compilerAttrs.stl,
+ Cpp_std: compilerAttrs.cppStd,
+ C_std: compilerAttrs.cStd,
Export_includes: exportedIncludes.Includes,
+ Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
Export_system_includes: exportedIncludes.SystemIncludes,
Local_includes: compilerAttrs.localIncludes,
Absolute_includes: compilerAttrs.absoluteIncludes,
@@ -2464,6 +2515,12 @@
}
}
+ var modType string
+ if isStatic {
+ modType = "cc_library_static"
+ } else {
+ modType = "cc_library_shared"
+ }
props := bazel.BazelTargetModuleProperties{
Rule_class: modType,
Bzl_load_location: fmt.Sprintf("//build/bazel/rules:%s.bzl", modType),
@@ -2476,16 +2533,20 @@
type bazelCcLibraryStaticAttributes struct {
staticOrSharedAttributes
- Use_libcrt bazel.BoolAttribute
- Rtti bazel.BoolAttribute
- Stl *string
- Cpp_std *string
+ Use_libcrt bazel.BoolAttribute
+ Use_version_lib bazel.BoolAttribute
- Export_includes bazel.StringListAttribute
- Export_system_includes bazel.StringListAttribute
- Local_includes bazel.StringListAttribute
- Absolute_includes bazel.StringListAttribute
- Hdrs bazel.LabelListAttribute
+ Rtti bazel.BoolAttribute
+ Stl *string
+ Cpp_std *string
+ C_std *string
+
+ Export_includes bazel.StringListAttribute
+ Export_absolute_includes bazel.StringListAttribute
+ Export_system_includes bazel.StringListAttribute
+ Local_includes bazel.StringListAttribute
+ Absolute_includes bazel.StringListAttribute
+ Hdrs bazel.LabelListAttribute
Cppflags bazel.StringListAttribute
Conlyflags bazel.StringListAttribute
@@ -2494,34 +2555,27 @@
Features bazel.StringListAttribute
}
-func CcLibraryStaticBp2Build(ctx android.TopDownMutatorContext) {
- isLibraryStatic := ctx.ModuleType() == "cc_library_static"
- if b, ok := ctx.Module().(android.Bazelable); ok {
- // This is created by a custom soong config module type, so its ctx.ModuleType() is not
- // cc_library_static. Check its BaseModuleType.
- isLibraryStatic = isLibraryStatic || b.BaseModuleType() == "cc_library_static"
- }
- if isLibraryStatic {
- ccSharedOrStaticBp2BuildMutator(ctx, "cc_library_static")
- }
-}
-
// TODO(b/199902614): Can this be factored to share with the other Attributes?
type bazelCcLibrarySharedAttributes struct {
staticOrSharedAttributes
- Linkopts bazel.StringListAttribute
- Link_crt bazel.BoolAttribute // Only for linking shared library (and cc_binary)
- Use_libcrt bazel.BoolAttribute
- Rtti bazel.BoolAttribute
- Stl *string
- Cpp_std *string
+ Linkopts bazel.StringListAttribute
+ Link_crt bazel.BoolAttribute // Only for linking shared library (and cc_binary)
- Export_includes bazel.StringListAttribute
- Export_system_includes bazel.StringListAttribute
- Local_includes bazel.StringListAttribute
- Absolute_includes bazel.StringListAttribute
- Hdrs bazel.LabelListAttribute
+ Use_libcrt bazel.BoolAttribute
+ Use_version_lib bazel.BoolAttribute
+
+ Rtti bazel.BoolAttribute
+ Stl *string
+ Cpp_std *string
+ C_std *string
+
+ Export_includes bazel.StringListAttribute
+ Export_absolute_includes bazel.StringListAttribute
+ Export_system_includes bazel.StringListAttribute
+ Local_includes bazel.StringListAttribute
+ Absolute_includes bazel.StringListAttribute
+ Hdrs bazel.LabelListAttribute
Strip stripAttributes
Additional_linker_inputs bazel.LabelListAttribute
@@ -2532,15 +2586,3 @@
Features bazel.StringListAttribute
}
-
-func CcLibrarySharedBp2Build(ctx android.TopDownMutatorContext) {
- isLibraryShared := ctx.ModuleType() == "cc_library_shared"
- if b, ok := ctx.Module().(android.Bazelable); ok {
- // This is created by a custom soong config module type, so its ctx.ModuleType() is not
- // cc_library_shared. Check its BaseModuleType.
- isLibraryShared = isLibraryShared || b.BaseModuleType() == "cc_library_shared"
- }
- if isLibraryShared {
- ccSharedOrStaticBp2BuildMutator(ctx, "cc_library_shared")
- }
-}
diff --git a/cc/library_headers.go b/cc/library_headers.go
index ede6ab3..70e4715 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -25,7 +25,6 @@
// Register sdk member types.
android.RegisterSdkMemberType(headersLibrarySdkMemberType)
- android.RegisterBp2BuildMutator("cc_library_headers", CcLibraryHeadersBp2Build)
}
var headersLibrarySdkMemberType = &librarySdkMemberType{
@@ -96,52 +95,41 @@
module, library := NewLibrary(android.HostAndDeviceSupported)
library.HeaderOnly()
module.sdkMemberTypes = []android.SdkMemberType{headersLibrarySdkMemberType}
+ module.bazelable = true
module.bazelHandler = &libraryHeaderBazelHander{module: module, library: library}
return module.Init()
}
// cc_prebuilt_library_headers is a prebuilt version of cc_library_headers
func prebuiltLibraryHeaderFactory() android.Module {
- module, library := NewPrebuiltLibrary(android.HostAndDeviceSupported)
+ module, library := NewPrebuiltLibrary(android.HostAndDeviceSupported, "")
library.HeaderOnly()
return module.Init()
}
type bazelCcLibraryHeadersAttributes struct {
- Hdrs bazel.LabelListAttribute
- Export_includes bazel.StringListAttribute
- Export_system_includes bazel.StringListAttribute
- Deps bazel.LabelListAttribute
- Implementation_deps bazel.LabelListAttribute
- System_dynamic_deps bazel.LabelListAttribute
+ Hdrs bazel.LabelListAttribute
+ Export_includes bazel.StringListAttribute
+ Export_absolute_includes bazel.StringListAttribute
+ Export_system_includes bazel.StringListAttribute
+ Deps bazel.LabelListAttribute
+ Implementation_deps bazel.LabelListAttribute
+ System_dynamic_deps bazel.LabelListAttribute
}
-func CcLibraryHeadersBp2Build(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_headers" {
- return
- }
-
- exportedIncludes := bp2BuildParseExportedIncludes(ctx, module)
+func libraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) {
baseAttributes := bp2BuildParseBaseProps(ctx, module)
+ exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, baseAttributes.includes)
linkerAttrs := baseAttributes.linkerAttributes
attrs := &bazelCcLibraryHeadersAttributes{
- Export_includes: exportedIncludes.Includes,
- Export_system_includes: exportedIncludes.SystemIncludes,
- Implementation_deps: linkerAttrs.implementationDeps,
- Deps: linkerAttrs.deps,
- System_dynamic_deps: linkerAttrs.systemDynamicDeps,
- Hdrs: baseAttributes.hdrs,
+ Export_includes: exportedIncludes.Includes,
+ Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
+ Export_system_includes: exportedIncludes.SystemIncludes,
+ Implementation_deps: linkerAttrs.implementationDeps,
+ Deps: linkerAttrs.deps,
+ System_dynamic_deps: linkerAttrs.systemDynamicDeps,
+ Hdrs: baseAttributes.hdrs,
}
props := bazel.BazelTargetModuleProperties{
diff --git a/cc/library_headers_test.go b/cc/library_headers_test.go
index 564ef61..3e448ba 100644
--- a/cc/library_headers_test.go
+++ b/cc/library_headers_test.go
@@ -15,48 +15,85 @@
package cc
import (
- "strings"
+ "fmt"
"testing"
+
+ "android/soong/android"
+
+ "github.com/google/blueprint"
)
func TestLibraryHeaders(t *testing.T) {
- ctx := testCc(t, `
- cc_library_headers {
- name: "headers",
- export_include_dirs: ["my_include"],
- }
- cc_library_static {
- name: "lib",
- srcs: ["foo.c"],
- header_libs: ["headers"],
- }
- `)
+ bp := `
+ %s {
+ name: "headers",
+ export_include_dirs: ["my_include"],
+ }
+ cc_library_static {
+ name: "lib",
+ srcs: ["foo.c"],
+ header_libs: ["headers"],
+ }
+ `
- // test if header search paths are correctly added
- cc := ctx.ModuleForTests("lib", "android_arm64_armv8-a_static").Rule("cc")
- cflags := cc.Args["cFlags"]
- if !strings.Contains(cflags, " -Imy_include ") {
- t.Errorf("cflags for libsystem must contain -Imy_include, but was %#v.", cflags)
+ for _, headerModule := range []string{"cc_library_headers", "cc_prebuilt_library_headers"} {
+ t.Run(headerModule, func(t *testing.T) {
+ ctx := testCc(t, fmt.Sprintf(bp, headerModule))
+
+ // test if header search paths are correctly added
+ cc := ctx.ModuleForTests("lib", "android_arm64_armv8-a_static").Rule("cc")
+ android.AssertStringDoesContain(t, "cFlags for lib module", cc.Args["cFlags"], " -Imy_include ")
+
+ // Test that there's a valid AndroidMk entry.
+ headers := ctx.ModuleForTests("headers", "android_arm64_armv8-a").Module()
+ e := android.AndroidMkEntriesForTest(t, ctx, headers)[0]
+
+ // This duplicates the tests done in AndroidMkEntries.write. It would be
+ // better to test its output, but there are no test functions that capture that.
+ android.AssertBoolEquals(t, "AndroidMkEntries.Disabled", false, e.Disabled)
+ android.AssertBoolEquals(t, "AndroidMkEntries.OutputFile.Valid()", true, e.OutputFile.Valid())
+
+ android.AssertStringListContains(t, "LOCAL_EXPORT_CFLAGS for headers module", e.EntryMap["LOCAL_EXPORT_CFLAGS"], "-Imy_include")
+ })
}
}
-func TestPrebuiltLibraryHeaders(t *testing.T) {
- ctx := testCc(t, `
- cc_prebuilt_library_headers {
- name: "headers",
- export_include_dirs: ["my_include"],
- }
- cc_library_static {
- name: "lib",
- srcs: ["foo.c"],
- header_libs: ["headers"],
- }
- `)
+func TestPrebuiltLibraryHeadersPreferred(t *testing.T) {
+ bp := `
+ cc_library_headers {
+ name: "headers",
+ export_include_dirs: ["my_include"],
+ }
+ cc_prebuilt_library_headers {
+ name: "headers",
+ prefer: %t,
+ export_include_dirs: ["my_include"],
+ }
+ cc_library_static {
+ name: "lib",
+ srcs: ["foo.c"],
+ header_libs: ["headers"],
+ }
+ `
- // test if header search paths are correctly added
- cc := ctx.ModuleForTests("lib", "android_arm64_armv8-a_static").Rule("cc")
- cflags := cc.Args["cFlags"]
- if !strings.Contains(cflags, " -Imy_include ") {
- t.Errorf("cflags for libsystem must contain -Imy_include, but was %#v.", cflags)
+ for _, prebuiltPreferred := range []bool{false, true} {
+ t.Run(fmt.Sprintf("prebuilt prefer %t", prebuiltPreferred), func(t *testing.T) {
+ ctx := testCc(t, fmt.Sprintf(bp, prebuiltPreferred))
+ lib := ctx.ModuleForTests("lib", "android_arm64_armv8-a_static")
+ sourceDep := ctx.ModuleForTests("headers", "android_arm64_armv8-a")
+ prebuiltDep := ctx.ModuleForTests("prebuilt_headers", "android_arm64_armv8-a")
+ hasSourceDep := false
+ hasPrebuiltDep := false
+ ctx.VisitDirectDeps(lib.Module(), func(dep blueprint.Module) {
+ if dep == sourceDep.Module() {
+ hasSourceDep = true
+ }
+ if dep == prebuiltDep.Module() {
+ hasPrebuiltDep = true
+ }
+ })
+ android.AssertBoolEquals(t, "depends on source headers", !prebuiltPreferred, hasSourceDep)
+ android.AssertBoolEquals(t, "depends on prebuilt headers", prebuiltPreferred, hasPrebuiltDep)
+ })
}
}
diff --git a/cc/library_test.go b/cc/library_test.go
index 7ddfaa7..d220e19 100644
--- a/cc/library_test.go
+++ b/cc/library_test.go
@@ -257,9 +257,16 @@
CcObjectFiles: []string{"foo.o"},
Includes: []string{"include"},
SystemIncludes: []string{"system_include"},
- RootStaticArchives: []string{"foo.a"},
+ Headers: []string{"foo.h"},
RootDynamicLibraries: []string{"foo.so"},
},
+ "//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{
+ CcObjectFiles: []string{"foo.o"},
+ Includes: []string{"include"},
+ SystemIncludes: []string{"system_include"},
+ Headers: []string{"foo.h"},
+ RootStaticArchives: []string{"foo.a"},
+ },
},
}
ctx := testCcWithConfig(t, config)
@@ -273,18 +280,25 @@
expectedOutputFiles := []string{"outputbase/execroot/__main__/foo.a"}
android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
+ flagExporter := ctx.ModuleProvider(staticFoo, FlagExporterInfoProvider).(FlagExporterInfo)
+ android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs)
+ android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs)
+ android.AssertPathsRelativeToTopEquals(t, "exported headers", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.GeneratedHeaders)
+ android.AssertPathsRelativeToTopEquals(t, "deps", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.Deps)
+
sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
outputFiles, err = sharedFoo.(android.OutputFileProducer).OutputFiles("")
if err != nil {
- t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
+ t.Errorf("Unexpected error getting cc_library outputfiles %s", err)
}
expectedOutputFiles = []string{"outputbase/execroot/__main__/foo.so"}
android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
- entries := android.AndroidMkEntriesForTest(t, ctx, sharedFoo)[0]
- expectedFlags := []string{"-Ioutputbase/execroot/__main__/include", "-isystem outputbase/execroot/__main__/system_include"}
- gotFlags := entries.EntryMap["LOCAL_EXPORT_CFLAGS"]
- android.AssertDeepEquals(t, "androidmk exported cflags", expectedFlags, gotFlags)
+ flagExporter = ctx.ModuleProvider(sharedFoo, FlagExporterInfoProvider).(FlagExporterInfo)
+ android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs)
+ android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs)
+ android.AssertPathsRelativeToTopEquals(t, "exported headers", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.GeneratedHeaders)
+ android.AssertPathsRelativeToTopEquals(t, "deps", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.Deps)
}
func TestLibraryVersionScript(t *testing.T) {
diff --git a/cc/linkable.go b/cc/linkable.go
index 560c9de..02d7047 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -384,9 +384,13 @@
includes := android.PathsForBazelOut(ctx, ccInfo.Includes)
systemIncludes := android.PathsForBazelOut(ctx, ccInfo.SystemIncludes)
+ headers := android.PathsForBazelOut(ctx, ccInfo.Headers)
return FlagExporterInfo{
IncludeDirs: android.FirstUniquePaths(includes),
SystemIncludeDirs: android.FirstUniquePaths(systemIncludes),
+ GeneratedHeaders: headers,
+ // necessary to ensure generated headers are considered implicit deps of dependent actions
+ Deps: headers,
}
}
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index fd458d9..6c200f5 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -82,6 +82,12 @@
return android.PathForOutput(ctx, "ndk_base.timestamp")
}
+// The headers timestamp file depends only on the NDK headers.
+// This is used mainly for .tidy files that do not need any stub libraries.
+func getNdkHeadersTimestampFile(ctx android.PathContext) android.WritablePath {
+ return android.PathForOutput(ctx, "ndk_headers.timestamp")
+}
+
// The full timestamp file depends on the base timestamp *and* the static
// libraries.
func getNdkFullTimestampFile(ctx android.PathContext) android.WritablePath {
@@ -96,6 +102,7 @@
func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var staticLibInstallPaths android.Paths
+ var headerPaths android.Paths
var installPaths android.Paths
var licensePaths android.Paths
ctx.VisitAllModules(func(module android.Module) {
@@ -104,16 +111,19 @@
}
if m, ok := module.(*headerModule); ok {
+ headerPaths = append(headerPaths, m.installPaths...)
installPaths = append(installPaths, m.installPaths...)
licensePaths = append(licensePaths, m.licensePath)
}
if m, ok := module.(*versionedHeaderModule); ok {
+ headerPaths = append(headerPaths, m.installPaths...)
installPaths = append(installPaths, m.installPaths...)
licensePaths = append(licensePaths, m.licensePath)
}
if m, ok := module.(*preprocessedHeadersModule); ok {
+ headerPaths = append(headerPaths, m.installPaths...)
installPaths = append(installPaths, m.installPaths...)
licensePaths = append(licensePaths, m.licensePath)
}
@@ -153,6 +163,12 @@
Validation: getNdkAbiDiffTimestampFile(ctx),
})
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Touch,
+ Output: getNdkHeadersTimestampFile(ctx),
+ Implicits: headerPaths,
+ })
+
fullDepPaths := append(staticLibInstallPaths, getNdkBaseTimestampFile(ctx))
// There's a phony "ndk" rule defined in core/main.mk that depends on this.
diff --git a/cc/object.go b/cc/object.go
index 0327a45..bd43e36 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -29,7 +29,6 @@
android.RegisterModuleType("cc_object", ObjectFactory)
android.RegisterSdkMemberType(ccObjectSdkMemberType)
- android.RegisterBp2BuildMutator("cc_object", ObjectBp2Build)
}
var ccObjectSdkMemberType = &librarySdkMemberType{
@@ -117,6 +116,7 @@
module.sdkMemberTypes = []android.SdkMemberType{ccObjectSdkMemberType}
+ module.bazelable = true
return module.Init()
}
@@ -135,19 +135,9 @@
Linker_script bazel.LabelAttribute
}
-// ObjectBp2Build is the bp2build converter from cc_object modules to the
+// objectBp2Build is the bp2build converter from cc_object modules to the
// Bazel equivalent target, plus any necessary include deps for the cc_object.
-func ObjectBp2Build(ctx android.TopDownMutatorContext) {
- m, ok := ctx.Module().(*Module)
- if !ok || !m.ConvertWithBp2build(ctx) {
- return
- }
-
- // a Module can be something other than a cc_object.
- if ctx.ModuleType() != "cc_object" {
- return
- }
-
+func objectBp2Build(ctx android.TopDownMutatorContext, m *Module) {
if m.compiler == nil {
// a cc_object must have access to the compiler decorator for its props.
ctx.ModuleErrorf("compiler must not be nil for a cc_object module")
diff --git a/cc/pgo.go b/cc/pgo.go
index e78549e..cd017c4 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -96,10 +96,6 @@
flags.Local.LdFlags = append(flags.Local.LdFlags, profileInstrumentFlag)
return flags
}
-func (props *PgoProperties) addSamplingProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
- flags.Local.CFlags = append(flags.Local.CFlags, props.Pgo.Cflags...)
- return flags
-}
func (props *PgoProperties) getPgoProfileFile(ctx BaseModuleContext) android.OptionalPath {
profileFile := *props.Pgo.Profile_file
@@ -313,10 +309,6 @@
if (props.ShouldProfileModule && props.isInstrumentation()) || props.PgoInstrLink {
// Instrumentation PGO use and gather flags cannot coexist.
return props.addInstrumentationProfileGatherFlags(ctx, flags)
- } else if props.ShouldProfileModule && props.isSampling() {
- flags = props.addSamplingProfileGatherFlags(ctx, flags)
- } else if ctx.DeviceConfig().SamplingPGO() {
- flags = props.addSamplingProfileGatherFlags(ctx, flags)
}
if !ctx.Config().IsEnvTrue("ANDROID_PGO_NO_PROFILE_USE") {
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 16945ac..feae812 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -32,8 +32,6 @@
ctx.RegisterModuleType("cc_prebuilt_test_library_shared", PrebuiltSharedTestLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_object", prebuiltObjectFactory)
ctx.RegisterModuleType("cc_prebuilt_binary", prebuiltBinaryFactory)
-
- android.RegisterBp2BuildMutator("cc_prebuilt_library_shared", PrebuiltLibrarySharedBp2Build)
}
type prebuiltLinkerInterface interface {
@@ -197,7 +195,13 @@
if p.header() {
ctx.SetProvider(HeaderLibraryInfoProvider, HeaderLibraryInfo{})
- return nil
+ // Need to return an output path so that the AndroidMk logic doesn't skip
+ // the prebuilt header. For compatibility, in case Android.mk files use a
+ // header lib in LOCAL_STATIC_LIBRARIES, create an empty ar file as
+ // placeholder, just like non-prebuilt header modules do in linkStatic().
+ ph := android.PathForModuleOut(ctx, ctx.ModuleName()+staticLibraryExtension)
+ transformObjToStaticLib(ctx, nil, nil, builderFlags{}, ph, nil, nil)
+ return ph
}
return nil
@@ -235,7 +239,7 @@
return android.RemoveOptionalPrebuiltPrefix(name)
}
-func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
+func NewPrebuiltLibrary(hod android.HostOrDeviceSupported, srcsProperty string) (*Module, *libraryDecorator) {
module, library := NewLibrary(hod)
module.compiler = nil
@@ -247,11 +251,15 @@
module.AddProperties(&prebuilt.properties)
- srcsSupplier := func(ctx android.BaseModuleContext, _ android.Module) []string {
- return prebuilt.prebuiltSrcs(ctx)
- }
+ if srcsProperty == "" {
+ android.InitPrebuiltModuleWithoutSrcs(module)
+ } else {
+ srcsSupplier := func(ctx android.BaseModuleContext, _ android.Module) []string {
+ return prebuilt.prebuiltSrcs(ctx)
+ }
- android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
+ android.InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, srcsProperty)
+ }
// Prebuilt libraries can be used in SDKs.
android.InitSdkAwareModule(module)
@@ -261,7 +269,7 @@
// cc_prebuilt_library installs a precompiled shared library that are
// listed in the srcs property in the device's directory.
func PrebuiltLibraryFactory() android.Module {
- module, _ := NewPrebuiltLibrary(android.HostAndDeviceSupported)
+ module, _ := NewPrebuiltLibrary(android.HostAndDeviceSupported, "srcs")
// Prebuilt shared libraries can be included in APEXes
android.InitApexModule(module)
@@ -280,15 +288,16 @@
// to be used as a data dependency of a test-related module (such as cc_test, or
// cc_test_library).
func PrebuiltSharedTestLibraryFactory() android.Module {
- module, library := NewPrebuiltLibrary(android.HostAndDeviceSupported)
+ module, library := NewPrebuiltLibrary(android.HostAndDeviceSupported, "srcs")
library.BuildOnlyShared()
library.baseInstaller = NewTestInstaller()
return module.Init()
}
func NewPrebuiltSharedLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
- module, library := NewPrebuiltLibrary(hod)
+ module, library := NewPrebuiltLibrary(hod, "srcs")
library.BuildOnlyShared()
+ module.bazelable = true
// Prebuilt shared libraries can be included in APEXes
android.InitApexModule(module)
@@ -304,33 +313,43 @@
}
func NewPrebuiltStaticLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
- module, library := NewPrebuiltLibrary(hod)
+ module, library := NewPrebuiltLibrary(hod, "srcs")
library.BuildOnlyStatic()
+ module.bazelable = true
module.bazelHandler = &prebuiltStaticLibraryBazelHandler{module: module, library: library}
return module, library
}
+type bazelPrebuiltLibraryStaticAttributes struct {
+ Static_library bazel.LabelAttribute
+ Export_includes bazel.StringListAttribute
+ Export_system_includes bazel.StringListAttribute
+}
+
+func prebuiltLibraryStaticBp2Build(ctx android.TopDownMutatorContext, module *Module) {
+ prebuiltAttrs := Bp2BuildParsePrebuiltLibraryProps(ctx, module)
+ exportedIncludes := Bp2BuildParseExportedIncludesForPrebuiltLibrary(ctx, module)
+
+ attrs := &bazelPrebuiltLibraryStaticAttributes{
+ Static_library: prebuiltAttrs.Src,
+ Export_includes: exportedIncludes.Includes,
+ Export_system_includes: exportedIncludes.SystemIncludes,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "prebuilt_library_static",
+ Bzl_load_location: "//build/bazel/rules:prebuilt_library_static.bzl",
+ }
+
+ name := android.RemoveOptionalPrebuiltPrefix(module.Name())
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
+}
+
type bazelPrebuiltLibrarySharedAttributes struct {
Shared_library bazel.LabelAttribute
}
-func PrebuiltLibrarySharedBp2Build(ctx android.TopDownMutatorContext) {
- module, ok := ctx.Module().(*Module)
- if !ok {
- // Not a cc module
- return
- }
- if !module.ConvertWithBp2build(ctx) {
- return
- }
- if ctx.ModuleType() != "cc_prebuilt_library_shared" {
- return
- }
-
- prebuiltLibrarySharedBp2BuildInternal(ctx, module)
-}
-
-func prebuiltLibrarySharedBp2BuildInternal(ctx android.TopDownMutatorContext, module *Module) {
+func prebuiltLibrarySharedBp2Build(ctx android.TopDownMutatorContext, module *Module) {
prebuiltAttrs := Bp2BuildParsePrebuiltLibraryProps(ctx, module)
attrs := &bazelPrebuiltLibrarySharedAttributes{
@@ -533,7 +552,7 @@
}
func NewPrebuiltBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
- module, binary := NewBinary(hod)
+ module, binary := newBinary(hod, false)
module.compiler = nil
prebuilt := &prebuiltBinaryLinker{
diff --git a/cc/proto.go b/cc/proto.go
index 4466144..f3410bc 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -16,8 +16,14 @@
import (
"github.com/google/blueprint/pathtools"
+ "github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/bazel"
+)
+
+const (
+ protoTypeDefault = "lite"
)
// genProto creates a rule to convert a .proto file to generated .pb.cc and .pb.h files and returns
@@ -63,7 +69,7 @@
var lib string
if String(p.Proto.Plugin) == "" {
- switch String(p.Proto.Type) {
+ switch proptools.StringDefault(p.Proto.Type, protoTypeDefault) {
case "full":
if ctx.useSdk() {
lib = "libprotobuf-cpp-full-ndk"
@@ -71,7 +77,7 @@
} else {
lib = "libprotobuf-cpp-full"
}
- case "lite", "":
+ case "lite":
if ctx.useSdk() {
lib = "libprotobuf-cpp-lite-ndk"
static = true
@@ -157,3 +163,69 @@
return flags
}
+
+type protoAttributes struct {
+ Deps bazel.LabelListAttribute
+}
+
+type bp2buildProtoDeps struct {
+ wholeStaticLib *bazel.LabelAttribute
+ implementationWholeStaticLib *bazel.LabelAttribute
+ protoDep *bazel.LabelAttribute
+}
+
+func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute) bp2buildProtoDeps {
+ var ret bp2buildProtoDeps
+
+ protoInfo, ok := android.Bp2buildProtoProperties(ctx, m, protoSrcs)
+ if !ok {
+ return ret
+ }
+
+ var depName string
+ typ := proptools.StringDefault(protoInfo.Type, protoTypeDefault)
+ var rule_class string
+ suffix := "_cc_proto"
+ switch typ {
+ case "lite":
+ suffix += "_lite"
+ rule_class = "cc_lite_proto_library"
+ depName = "libprotobuf-cpp-lite"
+ case "full":
+ rule_class = "cc_proto_library"
+ depName = "libprotobuf-cpp-full"
+ default:
+ ctx.PropertyErrorf("proto.type", "cannot handle conversion at this time: %q", typ)
+ }
+
+ dep := android.BazelLabelForModuleDepSingle(ctx, depName)
+ ret.protoDep = &bazel.LabelAttribute{Value: &dep}
+
+ protoLabel := bazel.Label{Label: ":" + protoInfo.Name}
+ var protoAttrs protoAttributes
+ protoAttrs.Deps.SetValue(bazel.LabelList{Includes: []bazel.Label{protoLabel}})
+
+ name := m.Name() + suffix
+
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: rule_class,
+ Bzl_load_location: "//build/bazel/rules:cc_proto.bzl",
+ },
+ android.CommonAttributes{Name: name},
+ &protoAttrs)
+
+ var privateHdrs bool
+ if lib, ok := m.linker.(*libraryDecorator); ok {
+ privateHdrs = !proptools.Bool(lib.Properties.Proto.Export_proto_headers)
+ }
+
+ labelAttr := &bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + name}}
+ if privateHdrs {
+ ret.implementationWholeStaticLib = labelAttr
+ } else {
+ ret.wholeStaticLib = labelAttr
+ }
+
+ return ret
+}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 93d4b4c..d7b1ade 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -35,7 +35,6 @@
asanCflags = []string{
"-fno-omit-frame-pointer",
- "-fno-experimental-new-pass-manager",
}
asanLdflags = []string{"-Wl,-u,__asan_preinit"}
@@ -666,9 +665,6 @@
flags.Local.LdFlags = append(flags.Local.LdFlags, "-fno-sanitize-coverage=stack-depth")
flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-coverage=stack-depth")
- // TODO(b/133876586): Experimental PM breaks sanitizer coverage.
- flags.Local.CFlags = append(flags.Local.CFlags, "-fno-experimental-new-pass-manager")
-
// Disable fortify for fuzzing builds. Generally, we'll be building with
// UBSan or ASan here and the fortify checks pollute the stack traces.
flags.Local.CFlags = append(flags.Local.CFlags, "-U_FORTIFY_SOURCE")
diff --git a/cc/test.go b/cc/test.go
index f37fdae..d8b7833 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -105,11 +105,6 @@
// Add RunCommandTargetPreparer to stop framework before the test and start it after the test.
Disable_framework *bool
- // Add ShippingApiLevelModuleController to auto generated test config. If the device properties
- // for the shipping api level is less than the test_min_api_level, skip this module.
- // Deprecated (b/187258404). Use test_options.min_shipping_api_level instead.
- Test_min_api_level *int64
-
// Flag to indicate whether or not to create test config automatically. If AndroidTest.xml
// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
// explicitly.
@@ -432,14 +427,6 @@
var options []tradefed.Option
options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Min_shipping_api_level), 10)})
configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
- } else if test.Properties.Test_min_api_level != nil {
- // TODO: (b/187258404) Remove test.Properties.Test_min_api_level
- if test.Properties.Test_options.Vsr_min_shipping_api_level != nil {
- ctx.PropertyErrorf("test_min_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.")
- }
- var options []tradefed.Option
- options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_min_api_level), 10)})
- configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options})
}
if test.Properties.Test_options.Vsr_min_shipping_api_level != nil {
var options []tradefed.Option
@@ -474,7 +461,7 @@
}
func NewTest(hod android.HostOrDeviceSupported) *Module {
- module, binary := NewBinary(hod)
+ module, binary := newBinary(hod, false)
module.multilib = android.MultilibBoth
binary.baseInstaller = NewTestInstaller()
@@ -564,6 +551,10 @@
testConfig android.Path
}
+func (benchmark *benchmarkDecorator) benchmarkBinary() bool {
+ return true
+}
+
func (benchmark *benchmarkDecorator) linkerInit(ctx BaseModuleContext) {
runpath := "../../lib"
if ctx.toolchain().Is64Bit() {
@@ -601,7 +592,7 @@
}
func NewBenchmark(hod android.HostOrDeviceSupported) *Module {
- module, binary := NewBinary(hod)
+ module, binary := newBinary(hod, false)
module.multilib = android.MultilibBoth
binary.baseInstaller = NewBaseInstaller("benchmarktest", "benchmarktest64", InstallInData)
diff --git a/cc/tidy.go b/cc/tidy.go
index 53ff156..78a791f 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -15,6 +15,7 @@
package cc
import (
+ "path/filepath"
"regexp"
"strings"
@@ -183,3 +184,154 @@
}
return flags
}
+
+func init() {
+ android.RegisterSingletonType("tidy_phony_targets", TidyPhonySingleton)
+}
+
+// This TidyPhonySingleton generates both tidy-* and obj-* phony targets for C/C++ files.
+func TidyPhonySingleton() android.Singleton {
+ return &tidyPhonySingleton{}
+}
+
+type tidyPhonySingleton struct{}
+
+// Given a final module, add its tidy/obj phony targets to tidy/objModulesInDirGroup.
+func collectTidyObjModuleTargets(ctx android.SingletonContext, module android.Module,
+ tidyModulesInDirGroup, objModulesInDirGroup map[string]map[string]android.Paths) {
+ allObjFileGroups := make(map[string]android.Paths) // variant group name => obj file Paths
+ allTidyFileGroups := make(map[string]android.Paths) // variant group name => tidy file Paths
+ subsetObjFileGroups := make(map[string]android.Paths) // subset group name => obj file Paths
+ subsetTidyFileGroups := make(map[string]android.Paths) // subset group name => tidy file Paths
+
+ // (1) Collect all obj/tidy files into OS-specific groups.
+ ctx.VisitAllModuleVariants(module, func(variant android.Module) {
+ if ctx.Config().KatiEnabled() && android.ShouldSkipAndroidMkProcessing(variant) {
+ return
+ }
+ if m, ok := variant.(*Module); ok {
+ osName := variant.Target().Os.Name
+ addToOSGroup(osName, m.objFiles, allObjFileGroups, subsetObjFileGroups)
+ addToOSGroup(osName, m.tidyFiles, allTidyFileGroups, subsetTidyFileGroups)
+ }
+ })
+
+ // (2) Add an all-OS group, with "" or "subset" name, to include all os-specific phony targets.
+ addAllOSGroup(ctx, module, allObjFileGroups, "", "obj")
+ addAllOSGroup(ctx, module, allTidyFileGroups, "", "tidy")
+ addAllOSGroup(ctx, module, subsetObjFileGroups, "subset", "obj")
+ addAllOSGroup(ctx, module, subsetTidyFileGroups, "subset", "tidy")
+
+ tidyTargetGroups := make(map[string]android.Path)
+ objTargetGroups := make(map[string]android.Path)
+ genObjTidyPhonyTargets(ctx, module, "obj", allObjFileGroups, objTargetGroups)
+ genObjTidyPhonyTargets(ctx, module, "obj", subsetObjFileGroups, objTargetGroups)
+ genObjTidyPhonyTargets(ctx, module, "tidy", allTidyFileGroups, tidyTargetGroups)
+ genObjTidyPhonyTargets(ctx, module, "tidy", subsetTidyFileGroups, tidyTargetGroups)
+
+ moduleDir := ctx.ModuleDir(module)
+ appendToModulesInDirGroup(tidyTargetGroups, moduleDir, tidyModulesInDirGroup)
+ appendToModulesInDirGroup(objTargetGroups, moduleDir, objModulesInDirGroup)
+}
+
+func (m *tidyPhonySingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ // For tidy-* directory phony targets, there are different variant groups.
+ // tidyModulesInDirGroup[G][D] is for group G, directory D, with Paths
+ // of all phony targets to be included into direct dependents of tidy-D_G.
+ tidyModulesInDirGroup := make(map[string]map[string]android.Paths)
+ // Also for obj-* directory phony targets.
+ objModulesInDirGroup := make(map[string]map[string]android.Paths)
+
+ // Collect tidy/obj targets from the 'final' modules.
+ ctx.VisitAllModules(func(module android.Module) {
+ if module == ctx.FinalModule(module) {
+ collectTidyObjModuleTargets(ctx, module, tidyModulesInDirGroup, objModulesInDirGroup)
+ }
+ })
+
+ suffix := ""
+ if ctx.Config().KatiEnabled() {
+ suffix = "-soong"
+ }
+ generateObjTidyPhonyTargets(ctx, suffix, "obj", objModulesInDirGroup)
+ generateObjTidyPhonyTargets(ctx, suffix, "tidy", tidyModulesInDirGroup)
+}
+
+// The name for an obj/tidy module variant group phony target is Name_group-obj/tidy,
+func objTidyModuleGroupName(module android.Module, group string, suffix string) string {
+ if group == "" {
+ return module.Name() + "-" + suffix
+ }
+ return module.Name() + "_" + group + "-" + suffix
+}
+
+// Generate obj-* or tidy-* phony targets.
+func generateObjTidyPhonyTargets(ctx android.SingletonContext, suffix string, prefix string, objTidyModulesInDirGroup map[string]map[string]android.Paths) {
+ // For each variant group, create a <prefix>-<directory>_group target that
+ // depends on all subdirectories and modules in the directory.
+ for group, modulesInDir := range objTidyModulesInDirGroup {
+ groupSuffix := ""
+ if group != "" {
+ groupSuffix = "_" + group
+ }
+ mmTarget := func(dir string) string {
+ return prefix + "-" + strings.Replace(filepath.Clean(dir), "/", "-", -1) + groupSuffix
+ }
+ dirs, topDirs := android.AddAncestors(ctx, modulesInDir, mmTarget)
+ // Create a <prefix>-soong_group target that depends on all <prefix>-dir_group of top level dirs.
+ var topDirPaths android.Paths
+ for _, dir := range topDirs {
+ topDirPaths = append(topDirPaths, android.PathForPhony(ctx, mmTarget(dir)))
+ }
+ ctx.Phony(prefix+suffix+groupSuffix, topDirPaths...)
+ // Create a <prefix>-dir_group target that depends on all targets in modulesInDir[dir]
+ for _, dir := range dirs {
+ if dir != "." && dir != "" {
+ ctx.Phony(mmTarget(dir), modulesInDir[dir]...)
+ }
+ }
+ }
+}
+
+// Append (obj|tidy)TargetGroups[group] into (obj|tidy)ModulesInDirGroups[group][moduleDir].
+func appendToModulesInDirGroup(targetGroups map[string]android.Path, moduleDir string, modulesInDirGroup map[string]map[string]android.Paths) {
+ for group, phonyPath := range targetGroups {
+ if _, found := modulesInDirGroup[group]; !found {
+ modulesInDirGroup[group] = make(map[string]android.Paths)
+ }
+ modulesInDirGroup[group][moduleDir] = append(modulesInDirGroup[group][moduleDir], phonyPath)
+ }
+}
+
+// Add given files to the OS group and subset group.
+func addToOSGroup(osName string, files android.Paths, allGroups, subsetGroups map[string]android.Paths) {
+ if len(files) > 0 {
+ subsetName := osName + "_subset"
+ allGroups[osName] = append(allGroups[osName], files...)
+ // Now include only the first variant in the subsetGroups.
+ // If clang and clang-tidy get faster, we might include more variants.
+ if _, found := subsetGroups[subsetName]; !found {
+ subsetGroups[subsetName] = files
+ }
+ }
+}
+
+// Add an all-OS group, with groupName, to include all os-specific phony targets.
+func addAllOSGroup(ctx android.SingletonContext, module android.Module, phonyTargetGroups map[string]android.Paths, groupName string, objTidyName string) {
+ if len(phonyTargetGroups) > 0 {
+ var targets android.Paths
+ for group, _ := range phonyTargetGroups {
+ targets = append(targets, android.PathForPhony(ctx, objTidyModuleGroupName(module, group, objTidyName)))
+ }
+ phonyTargetGroups[groupName] = targets
+ }
+}
+
+// Create one phony targets for each group and add them to the targetGroups.
+func genObjTidyPhonyTargets(ctx android.SingletonContext, module android.Module, objTidyName string, fileGroups map[string]android.Paths, targetGroups map[string]android.Path) {
+ for group, files := range fileGroups {
+ groupName := objTidyModuleGroupName(module, group, objTidyName)
+ ctx.Phony(groupName, files...)
+ targetGroups[group] = android.PathForPhony(ctx, groupName)
+ }
+}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index dfc4eae..f07eafa 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -386,7 +386,7 @@
// - won't be overwritten by corresponding bp2build generated files
//
// And return their paths so they can be left out of the Bazel workspace dir (i.e. ignored)
-func getPathsToIgnoredBuildFiles(topDir string, generatedRoot string, srcDirBazelFiles []string) []string {
+func getPathsToIgnoredBuildFiles(topDir string, generatedRoot string, srcDirBazelFiles []string, verbose bool) []string {
paths := make([]string, 0)
for _, srcDirBazelFileRelativePath := range srcDirBazelFiles {
@@ -416,7 +416,9 @@
// BUILD file clash resolution happens later in the symlink forest creation
continue
}
- fmt.Fprintf(os.Stderr, "Ignoring existing BUILD file: %s\n", srcDirBazelFileRelativePath)
+ if verbose {
+ fmt.Fprintf(os.Stderr, "Ignoring existing BUILD file: %s\n", srcDirBazelFileRelativePath)
+ }
paths = append(paths, srcDirBazelFileRelativePath)
}
@@ -523,7 +525,7 @@
os.Exit(1)
}
- pathsToIgnoredBuildFiles := getPathsToIgnoredBuildFiles(topDir, generatedRoot, existingBazelRelatedFiles)
+ pathsToIgnoredBuildFiles := getPathsToIgnoredBuildFiles(topDir, generatedRoot, existingBazelRelatedFiles, configuration.IsEnvTrue("BP2BUILD_VERBOSE"))
excludes = append(excludes, pathsToIgnoredBuildFiles...)
excludes = append(excludes, getTemporaryExcludes()...)
@@ -535,6 +537,7 @@
// for queryview, since that's a total repo-wide conversion and there's a
// 1:1 mapping for each module.
metrics.Print()
+ writeBp2BuildMetrics(&metrics, configuration)
ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
ninjaDeps = append(ninjaDeps, symlinkForestDeps...)
@@ -544,3 +547,13 @@
// Create an empty bp2build marker file.
touch(shared.JoinPath(topDir, bp2buildMarker))
}
+
+// Write Bp2Build metrics into $LOG_DIR
+func writeBp2BuildMetrics(metrics *bp2build.CodegenMetrics, configuration android.Config) {
+ metricsDir := configuration.Getenv("LOG_DIR")
+ if len(metricsDir) < 1 {
+ fmt.Fprintf(os.Stderr, "\nMissing required env var for generating bp2build metrics: LOG_DIR\n")
+ os.Exit(1)
+ }
+ metrics.Write(metricsDir)
+}
diff --git a/compliance/build_license_metadata/Android.bp b/compliance/build_license_metadata/Android.bp
index 5000346..4826526 100644
--- a/compliance/build_license_metadata/Android.bp
+++ b/compliance/build_license_metadata/Android.bp
@@ -25,5 +25,6 @@
"license_metadata_proto",
"golang-protobuf-proto",
"golang-protobuf-encoding-prototext",
+ "soong-response",
],
}
diff --git a/compliance/build_license_metadata/build_license_metadata.go b/compliance/build_license_metadata/build_license_metadata.go
index 8b1fe58..53d2407 100644
--- a/compliance/build_license_metadata/build_license_metadata.go
+++ b/compliance/build_license_metadata/build_license_metadata.go
@@ -26,28 +26,12 @@
"google.golang.org/protobuf/proto"
"android/soong/compliance/license_metadata_proto"
+ "android/soong/response"
)
-var (
- packageName = flag.String("p", "", "license package name")
- moduleType = newMultiString("mt", "module type")
- moduleClass = newMultiString("mc", "module class")
- kinds = newMultiString("k", "license kinds")
- conditions = newMultiString("c", "license conditions")
- notices = newMultiString("n", "license notice file")
- deps = newMultiString("d", "license metadata file dependency")
- sources = newMultiString("s", "source (input) dependency")
- built = newMultiString("t", "built targets")
- installed = newMultiString("i", "installed targets")
- roots = newMultiString("r", "root directory of project")
- installedMap = newMultiString("m", "map dependent targets to their installed names")
- isContainer = flag.Bool("is_container", false, "preserved dependent target name when given")
- outFile = flag.String("o", "", "output file")
-)
-
-func newMultiString(name, usage string) *multiString {
+func newMultiString(flags *flag.FlagSet, name, usage string) *multiString {
var f multiString
- flag.Var(&f, name, usage)
+ flags.Var(&f, name, usage)
return &f
}
@@ -57,7 +41,45 @@
func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil }
func main() {
- flag.Parse()
+ var expandedArgs []string
+ for _, arg := range os.Args[1:] {
+ if strings.HasPrefix(arg, "@") {
+ f, err := os.Open(strings.TrimPrefix(arg, "@"))
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+
+ respArgs, err := response.ReadRspFile(f)
+ f.Close()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err.Error())
+ os.Exit(1)
+ }
+ expandedArgs = append(expandedArgs, respArgs...)
+ } else {
+ expandedArgs = append(expandedArgs, arg)
+ }
+ }
+
+ flags := flag.NewFlagSet("flags", flag.ExitOnError)
+
+ packageName := flags.String("p", "", "license package name")
+ moduleType := newMultiString(flags, "mt", "module type")
+ kinds := newMultiString(flags, "k", "license kinds")
+ moduleClass := newMultiString(flags, "mc", "module class")
+ conditions := newMultiString(flags, "c", "license conditions")
+ notices := newMultiString(flags, "n", "license notice file")
+ deps := newMultiString(flags, "d", "license metadata file dependency")
+ sources := newMultiString(flags, "s", "source (input) dependency")
+ built := newMultiString(flags, "t", "built targets")
+ installed := newMultiString(flags, "i", "installed targets")
+ roots := newMultiString(flags, "r", "root directory of project")
+ installedMap := newMultiString(flags, "m", "map dependent targets to their installed names")
+ isContainer := flags.Bool("is_container", false, "preserved dependent target name when given")
+ outFile := flags.String("o", "", "output file")
+
+ flags.Parse(expandedArgs)
metadata := license_metadata_proto.LicenseMetadata{}
metadata.PackageName = proto.String(*packageName)
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index de3666a..6d6b41d 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -49,10 +49,12 @@
ArtApexJars android.ConfiguredJarList // modules for jars that are in the ART APEX
- SystemServerJars android.ConfiguredJarList // jars that form the system server
- SystemServerApps []string // apps that are loaded into system server
- ApexSystemServerJars android.ConfiguredJarList // jars within apex that are loaded into system server
- SpeedApps []string // apps that should be speed optimized
+ SystemServerJars android.ConfiguredJarList // system_server classpath jars on the platform
+ SystemServerApps []string // apps that are loaded into system server
+ ApexSystemServerJars android.ConfiguredJarList // system_server classpath jars delivered via apex
+ StandaloneSystemServerJars android.ConfiguredJarList // jars on the platform that system_server loads dynamically using separate classloaders
+ ApexStandaloneSystemServerJars android.ConfiguredJarList // jars delivered via apex that system_server loads dynamically using separate classloaders
+ SpeedApps []string // apps that should be speed optimized
BrokenSuboptimalOrderOfSystemServerJars bool // if true, sub-optimal order does not cause a build error
@@ -619,6 +621,8 @@
SystemServerJars: android.EmptyConfiguredJarList(),
SystemServerApps: nil,
ApexSystemServerJars: android.EmptyConfiguredJarList(),
+ StandaloneSystemServerJars: android.EmptyConfiguredJarList(),
+ ApexStandaloneSystemServerJars: android.EmptyConfiguredJarList(),
SpeedApps: nil,
PreoptFlags: nil,
DefaultCompilerFilter: "",
diff --git a/dexpreopt/testing.go b/dexpreopt/testing.go
index 8f5c315..5131cd3 100644
--- a/dexpreopt/testing.go
+++ b/dexpreopt/testing.go
@@ -85,12 +85,12 @@
// Prepares a test fixture by enabling dexpreopt, registering the fake_tool_binary module type and
// using that to define the `dex2oatd` module.
var PrepareForTestByEnablingDexpreopt = android.GroupFixturePreparers(
- FixtureModifyGlobalConfig(func(*GlobalConfig) {}),
+ FixtureModifyGlobalConfig(func(android.PathContext, *GlobalConfig) {}),
)
// FixtureModifyGlobalConfig enables dexpreopt (unless modified by the mutator) and modifies the
// configuration.
-func FixtureModifyGlobalConfig(configModifier func(dexpreoptConfig *GlobalConfig)) android.FixturePreparer {
+func FixtureModifyGlobalConfig(configModifier func(ctx android.PathContext, dexpreoptConfig *GlobalConfig)) android.FixturePreparer {
return android.FixtureModifyConfig(func(config android.Config) {
// Initialize the dexpreopt GlobalConfig to an empty structure. This has no effect if it has
// already been set.
@@ -100,48 +100,70 @@
// Retrieve the existing configuration and modify it.
dexpreoptConfig = GetGlobalConfig(pathCtx)
- configModifier(dexpreoptConfig)
+ configModifier(pathCtx, dexpreoptConfig)
})
}
// FixtureSetArtBootJars enables dexpreopt and sets the ArtApexJars property.
func FixtureSetArtBootJars(bootJars ...string) android.FixturePreparer {
- return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
+ return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) {
dexpreoptConfig.ArtApexJars = android.CreateTestConfiguredJarList(bootJars)
})
}
// FixtureSetBootJars enables dexpreopt and sets the BootJars property.
func FixtureSetBootJars(bootJars ...string) android.FixturePreparer {
- return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
+ return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) {
dexpreoptConfig.BootJars = android.CreateTestConfiguredJarList(bootJars)
})
}
// FixtureSetApexBootJars sets the ApexBootJars property in the global config.
func FixtureSetApexBootJars(bootJars ...string) android.FixturePreparer {
- return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
+ return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) {
dexpreoptConfig.ApexBootJars = android.CreateTestConfiguredJarList(bootJars)
})
}
+// FixtureSetStandaloneSystemServerJars sets the StandaloneSystemServerJars property.
+func FixtureSetStandaloneSystemServerJars(jars ...string) android.FixturePreparer {
+ return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) {
+ dexpreoptConfig.StandaloneSystemServerJars = android.CreateTestConfiguredJarList(jars)
+ })
+}
+
// FixtureSetSystemServerJars sets the SystemServerJars property.
func FixtureSetSystemServerJars(jars ...string) android.FixturePreparer {
- return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
+ return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) {
dexpreoptConfig.SystemServerJars = android.CreateTestConfiguredJarList(jars)
})
}
// FixtureSetApexSystemServerJars sets the ApexSystemServerJars property in the global config.
func FixtureSetApexSystemServerJars(jars ...string) android.FixturePreparer {
- return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
+ return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) {
dexpreoptConfig.ApexSystemServerJars = android.CreateTestConfiguredJarList(jars)
})
}
+// FixtureSetApexStandaloneSystemServerJars sets the ApexStandaloneSystemServerJars property in the
+// global config.
+func FixtureSetApexStandaloneSystemServerJars(jars ...string) android.FixturePreparer {
+ return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) {
+ dexpreoptConfig.ApexStandaloneSystemServerJars = android.CreateTestConfiguredJarList(jars)
+ })
+}
+
// FixtureSetPreoptWithUpdatableBcp sets the PreoptWithUpdatableBcp property in the global config.
func FixtureSetPreoptWithUpdatableBcp(value bool) android.FixturePreparer {
- return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
+ return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) {
dexpreoptConfig.PreoptWithUpdatableBcp = value
})
}
+
+// FixtureSetBootImageProfiles sets the BootImageProfiles property in the global config.
+func FixtureSetBootImageProfiles(profiles ...string) android.FixturePreparer {
+ return FixtureModifyGlobalConfig(func(ctx android.PathContext, dexpreoptConfig *GlobalConfig) {
+ dexpreoptConfig.BootImageProfiles = android.PathsForSource(ctx, profiles)
+ })
+}
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 2865ffa..80ab41b 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -63,7 +63,6 @@
ctx.RegisterModuleType("prebuilt_defaults", defaultsFactory)
- android.RegisterBp2BuildMutator("prebuilt_etc", PrebuiltEtcBp2Build)
}
var PrepareForTestWithPrebuiltEtc = android.FixtureRegisterWithContext(RegisterPrebuiltEtcBuildComponents)
@@ -663,20 +662,14 @@
Installable bazel.BoolAttribute
}
-func PrebuiltEtcBp2Build(ctx android.TopDownMutatorContext) {
- module, ok := ctx.Module().(*PrebuiltEtc)
- if !ok {
- // Not an prebuilt_etc
- return
- }
- if !module.ConvertWithBp2build(ctx) {
- return
- }
+// ConvertWithBp2build performs bp2build conversion of PrebuiltEtc
+func (p *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ // All prebuilt_* modules are PrebuiltEtc, but at this time, we only convert prebuilt_etc modules.
if ctx.ModuleType() != "prebuilt_etc" {
return
}
- prebuiltEtcBp2BuildInternal(ctx, module)
+ prebuiltEtcBp2BuildInternal(ctx, p)
}
func prebuiltEtcBp2BuildInternal(ctx android.TopDownMutatorContext, module *PrebuiltEtc) {
diff --git a/genrule/genrule.go b/genrule/genrule.go
index c9bf958..6a91e01 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -67,13 +67,6 @@
ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("genrule_tool_deps", toolDepsMutator).Parallel()
})
-
- android.RegisterBp2BuildMutator("genrule", GenruleBp2Build)
- android.RegisterBp2BuildMutator("cc_genrule", CcGenruleBp2Build)
-}
-
-func RegisterGenruleBp2BuildDeps(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("genrule_tool_deps", toolDepsMutator)
}
var (
@@ -110,6 +103,7 @@
type hostToolDependencyTag struct {
blueprint.BaseDependencyTag
+ android.LicenseAnnotationToolchainDependencyTag
label string
}
type generatorProperties struct {
@@ -832,38 +826,8 @@
Cmd string
}
-// CcGenruleBp2Build is for cc_genrule.
-func CcGenruleBp2Build(ctx android.TopDownMutatorContext) {
- m, ok := ctx.Module().(*Module)
- if !ok || !m.ConvertWithBp2build(ctx) {
- return
- }
-
- if ctx.ModuleType() != "cc_genrule" {
- // Not a cc_genrule.
- return
- }
-
- genruleBp2Build(ctx)
-}
-
-// GenruleBp2Build is used for genrule.
-func GenruleBp2Build(ctx android.TopDownMutatorContext) {
- m, ok := ctx.Module().(*Module)
- if !ok || !m.ConvertWithBp2build(ctx) {
- return
- }
-
- if ctx.ModuleType() != "genrule" {
- // Not a regular genrule.
- return
- }
-
- genruleBp2Build(ctx)
-}
-
-func genruleBp2Build(ctx android.TopDownMutatorContext) {
- m, _ := ctx.Module().(*Module)
+// ConvertWithBp2build converts a Soong module -> Bazel target.
+func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
// Bazel only has the "tools" attribute.
tools_prop := android.BazelLabelForModuleDeps(ctx, m.properties.Tools)
tool_files_prop := android.BazelLabelForModuleSrc(ctx, m.properties.Tool_files)
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 38065f1..f29d8ad 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "strconv"
"strings"
"github.com/google/blueprint"
@@ -42,6 +43,21 @@
},
"args", "libs")
+// targetSdkVersion for manifest_fixer
+// When TARGET_BUILD_APPS is not empty, this method returns 10000 for modules targeting an unreleased SDK
+// This enables release builds (that run with TARGET_BUILD_APPS=[val...]) to target APIs that have not yet been finalized as part of an SDK
+func targetSdkVersionForManifestFixer(ctx android.ModuleContext, sdkContext android.SdkContext) string {
+ targetSdkVersionSpec := sdkContext.TargetSdkVersion(ctx)
+ if ctx.Config().UnbundledBuildApps() && targetSdkVersionSpec.ApiLevel.IsPreview() {
+ return strconv.Itoa(android.FutureApiLevel.FinalOrFutureInt())
+ }
+ targetSdkVersion, err := targetSdkVersionSpec.EffectiveVersionString(ctx)
+ if err != nil {
+ ctx.ModuleErrorf("invalid targetSdkVersion: %s", err)
+ }
+ return targetSdkVersion
+}
+
// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext android.SdkContext,
classLoaderContexts dexpreopt.ClassLoaderContextMap, isLibrary, useEmbeddedNativeLibs, usesNonSdkApis,
@@ -89,10 +105,8 @@
args = append(args, "--logging-parent", loggingParent)
}
var deps android.Paths
- targetSdkVersion, err := sdkContext.TargetSdkVersion(ctx).EffectiveVersionString(ctx)
- if err != nil {
- ctx.ModuleErrorf("invalid targetSdkVersion: %s", err)
- }
+ targetSdkVersion := targetSdkVersionForManifestFixer(ctx, sdkContext)
+
if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
deps = append(deps, ApiFingerprintPath(ctx))
diff --git a/java/android_resources.go b/java/android_resources.go
index 6864ebb..8c5908f 100644
--- a/java/android_resources.go
+++ b/java/android_resources.go
@@ -43,7 +43,7 @@
// androidResourceGlob returns the list of files in the given directory, using the standard
// exclusion patterns for Android resources.
-func androidResourceGlob(ctx android.ModuleContext, dir android.Path) android.Paths {
+func androidResourceGlob(ctx android.EarlyModuleContext, dir android.Path) android.Paths {
return ctx.GlobFiles(filepath.Join(dir.String(), "**/*"), androidResourceIgnoreFilenames)
}
diff --git a/java/app.go b/java/app.go
index c08ec06..b753c0c 100755
--- a/java/app.go
+++ b/java/app.go
@@ -43,8 +43,6 @@
ctx.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory)
ctx.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory)
ctx.RegisterModuleType("override_android_test", OverrideAndroidTestModuleFactory)
-
- android.RegisterBp2BuildMutator("android_app_certificate", AndroidAppCertificateBp2Build)
}
// AndroidManifest.xml merging
@@ -139,6 +137,7 @@
}
type AndroidApp struct {
+ android.BazelModuleBase
Library
aapt
android.OverridableModuleBase
@@ -291,7 +290,7 @@
if minSdkVersion, err := a.MinSdkVersion(ctx).EffectiveVersion(ctx); err == nil {
a.checkJniLibsSdkVersion(ctx, minSdkVersion)
- android.CheckMinSdkVersion(a, ctx, minSdkVersion)
+ android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps)
} else {
ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
}
@@ -943,6 +942,7 @@
android.InitDefaultableModule(module)
android.InitOverridableModule(module, &module.appProperties.Overrides)
android.InitApexModule(module)
+ android.InitBazelModule(module)
return module
}
@@ -1405,23 +1405,11 @@
Certificate string
}
-func AndroidAppCertificateBp2Build(ctx android.TopDownMutatorContext) {
- module, ok := ctx.Module().(*AndroidAppCertificate)
- if !ok {
- // Not an Android app certificate
- return
- }
- if !module.ConvertWithBp2build(ctx) {
- return
- }
- if ctx.ModuleType() != "android_app_certificate" {
- return
- }
-
- androidAppCertificateBp2BuildInternal(ctx, module)
+func (m *AndroidAppCertificate) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ androidAppCertificateBp2Build(ctx, m)
}
-func androidAppCertificateBp2BuildInternal(ctx android.TopDownMutatorContext, module *AndroidAppCertificate) {
+func androidAppCertificateBp2Build(ctx android.TopDownMutatorContext, module *AndroidAppCertificate) {
var certificate string
if module.properties.Certificate != nil {
certificate = *module.properties.Certificate
@@ -1438,3 +1426,39 @@
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
}
+
+type bazelAndroidAppAttributes struct {
+ Srcs bazel.LabelListAttribute
+ Manifest bazel.Label
+ Custom_package *string
+ Resource_files bazel.LabelListAttribute
+}
+
+// ConvertWithBp2build is used to convert android_app to Bazel.
+func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ //TODO(b/209577426): Support multiple arch variants
+ srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, a.properties.Srcs, a.properties.Exclude_srcs))
+
+ manifest := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
+
+ resourceFiles := bazel.LabelList{
+ Includes: []bazel.Label{},
+ }
+ for _, dir := range android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res") {
+ files := android.RootToModuleRelativePaths(ctx, androidResourceGlob(ctx, dir))
+ resourceFiles.Includes = append(resourceFiles.Includes, files...)
+ }
+
+ attrs := &bazelAndroidAppAttributes{
+ Srcs: srcs,
+ Manifest: android.BazelLabelForModuleSrcSingle(ctx, manifest),
+ // TODO(b/209576404): handle package name override by product variable PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES
+ Custom_package: a.overridableAppProperties.Package_name,
+ Resource_files: bazel.MakeLabelListAttribute(resourceFiles),
+ }
+ props := bazel.BazelTargetModuleProperties{Rule_class: "android_binary",
+ Bzl_load_location: "@rules_android//rules:rules.bzl"}
+
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: a.Name()}, attrs)
+
+}
diff --git a/java/app_test.go b/java/app_test.go
index 0aae928..4da7c3d 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2873,3 +2873,76 @@
t.Errorf("App does not use library proguard config")
}
}
+
+func TestTargetSdkVersionManifestFixer(t *testing.T) {
+ platform_sdk_codename := "Tiramisu"
+ testCases := []struct {
+ name string
+ targetSdkVersionInBp string
+ targetSdkVersionExpected string
+ unbundledBuild bool
+ }{
+ {
+ name: "Non-Unbundled build: Android.bp has targetSdkVersion",
+ targetSdkVersionInBp: "30",
+ targetSdkVersionExpected: "30",
+ unbundledBuild: false,
+ },
+ {
+ name: "Unbundled build: Android.bp has targetSdkVersion",
+ targetSdkVersionInBp: "30",
+ targetSdkVersionExpected: "30",
+ unbundledBuild: true,
+ },
+ {
+ name: "Non-Unbundled build: Android.bp has targetSdkVersion equal to platform_sdk_codename",
+ targetSdkVersionInBp: platform_sdk_codename,
+ targetSdkVersionExpected: platform_sdk_codename,
+ unbundledBuild: false,
+ },
+ {
+ name: "Unbundled build: Android.bp has targetSdkVersion equal to platform_sdk_codename",
+ targetSdkVersionInBp: platform_sdk_codename,
+ targetSdkVersionExpected: "10000",
+ unbundledBuild: true,
+ },
+
+ {
+ name: "Non-Unbundled build: Android.bp has no targetSdkVersion",
+ targetSdkVersionExpected: platform_sdk_codename,
+ unbundledBuild: false,
+ },
+ {
+ name: "Unbundled build: Android.bp has no targetSdkVersion",
+ targetSdkVersionExpected: "10000",
+ unbundledBuild: true,
+ },
+ }
+ for _, testCase := range testCases {
+ bp := fmt.Sprintf(`
+ android_app {
+ name: "foo",
+ sdk_version: "current",
+ target_sdk_version: "%v",
+ }
+ `, testCase.targetSdkVersionInBp)
+ fixture := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ // explicitly set platform_sdk_codename to make the test deterministic
+ variables.Platform_sdk_codename = &platform_sdk_codename
+ variables.Platform_version_active_codenames = []string{platform_sdk_codename}
+ // create a non-empty list if unbundledBuild==true
+ if testCase.unbundledBuild {
+ variables.Unbundled_build_apps = []string{"apex_a", "apex_b"}
+ }
+ }),
+ )
+
+ result := fixture.RunTestWithBp(t, bp)
+ foo := result.ModuleForTests("foo", "android_common")
+
+ manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args
+ android.AssertStringEquals(t, testCase.name, testCase.targetSdkVersionExpected, manifestFixerArgs["targetSdkVersion"])
+ }
+}
diff --git a/java/base.go b/java/base.go
index d9b1260..c45ef64 100644
--- a/java/base.go
+++ b/java/base.go
@@ -197,6 +197,10 @@
// Defaults to sdk_version if not set. See sdk_version for possible values.
Min_sdk_version *string
+ // if not blank, set the maximum version of the sdk that the compiled artifacts will run against.
+ // Defaults to empty string "". See sdk_version for possible values.
+ Max_sdk_version *string
+
// if not blank, set the targetSdkVersion in the AndroidManifest.xml.
// Defaults to sdk_version if not set. See sdk_version for possible values.
Target_sdk_version *string
@@ -368,6 +372,7 @@
android.DefaultableModuleBase
android.ApexModuleBase
android.SdkBase
+ android.BazelModuleBase
// Functionality common to Module and Import.
embeddableInModuleAndImport
@@ -460,6 +465,7 @@
sdkVersion android.SdkSpec
minSdkVersion android.SdkSpec
+ maxSdkVersion android.SdkSpec
}
func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error {
@@ -617,6 +623,13 @@
return j.SdkVersion(ctx)
}
+func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+ maxSdkVersion := proptools.StringDefault(j.deviceProperties.Max_sdk_version, "")
+ // SdkSpecFrom returns SdkSpecPrivate for this, which may be confusing.
+ // TODO(b/208456999): ideally MaxSdkVersion should be an ApiLevel and not SdkSpec.
+ return android.SdkSpecFrom(ctx, maxSdkVersion)
+}
+
func (j *Module) MinSdkVersionString() string {
return j.minSdkVersion.Raw
}
@@ -1631,8 +1644,7 @@
}
// Implements android.ApexModule
-func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
- sdkVersion android.ApiLevel) error {
+func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
sdkSpec := j.MinSdkVersion(ctx)
if !sdkSpec.Specified() {
return fmt.Errorf("min_sdk_version is not specified")
@@ -1941,3 +1953,17 @@
}
var _ ModuleWithStem = (*Module)(nil)
+
+func (j *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ switch ctx.ModuleType() {
+ case "java_library", "java_library_host":
+ if lib, ok := ctx.Module().(*Library); ok {
+ javaLibraryBp2Build(ctx, lib)
+ }
+ case "java_binary_host":
+ if binary, ok := ctx.Module().(*Binary); ok {
+ javaBinaryHostBp2Build(ctx, binary)
+ }
+ }
+
+}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index bfa6838..bfe895c 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -390,6 +390,13 @@
// Map from the base module name (without prebuilt_ prefix) of a fragment's contents module to the
// hidden API encoded dex jar path.
contentModuleDexJarPaths bootDexJarByModule
+
+ // Path to the image profile file on host (or empty, if profile is not generated).
+ profilePathOnHost android.Path
+
+ // Install path of the boot image profile if it needs to be installed in the APEX, or empty if not
+ // needed.
+ profileInstallPathInApex string
}
func (i BootclasspathFragmentApexContentInfo) Modules() android.ConfiguredJarList {
@@ -418,6 +425,14 @@
}
}
+func (i BootclasspathFragmentApexContentInfo) ProfilePathOnHost() android.Path {
+ return i.profilePathOnHost
+}
+
+func (i BootclasspathFragmentApexContentInfo) ProfileInstallPathInApex() string {
+ return i.profileInstallPathInApex
+}
+
func (b *BootclasspathFragmentModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
tag := ctx.OtherModuleDependencyTag(dep)
if IsBootclasspathFragmentContentDepTag(tag) {
@@ -579,6 +594,11 @@
if imageConfig != nil {
info.modules = imageConfig.modules
+ global := dexpreopt.GetGlobalConfig(ctx)
+ if !global.DisableGenerateProfile {
+ info.profilePathOnHost = imageConfig.profilePathOnHost
+ info.profileInstallPathInApex = imageConfig.profileInstallPathInApex
+ }
}
info.bootImageFilesByArch = bootImageFilesByArch
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index f63d81d..e77971b 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -25,7 +25,7 @@
"android/soong/android"
)
-// Build rules and utilities to generate individual packages/modules/SdkExtensions/proto/classpaths.proto
+// Build rules and utilities to generate individual packages/modules/common/proto/classpaths.proto
// config files based on build configuration to embed into /system and /apex on a device.
//
// See `derive_classpath` service that reads the configs at runtime and defines *CLASSPATH variables
@@ -34,14 +34,15 @@
type classpathType int
const (
- // Matches definition in packages/modules/SdkExtensions/proto/classpaths.proto
+ // Matches definition in packages/modules/common/proto/classpaths.proto
BOOTCLASSPATH classpathType = iota
DEX2OATBOOTCLASSPATH
SYSTEMSERVERCLASSPATH
+ STANDALONE_SYSTEMSERVER_JARS
)
func (c classpathType) String() string {
- return [...]string{"BOOTCLASSPATH", "DEX2OATBOOTCLASSPATH", "SYSTEMSERVERCLASSPATH"}[c]
+ return [...]string{"BOOTCLASSPATH", "DEX2OATBOOTCLASSPATH", "SYSTEMSERVERCLASSPATH", "STANDALONE_SYSTEMSERVER_JARS"}[c]
}
type classpathFragmentProperties struct {
@@ -84,11 +85,10 @@
// Matches definition of Jar in packages/modules/SdkExtensions/proto/classpaths.proto
type classpathJar struct {
- path string
- classpath classpathType
- // TODO(satayev): propagate min/max sdk versions for the jars
- minSdkVersion int32
- maxSdkVersion int32
+ path string
+ classpath classpathType
+ minSdkVersion string
+ maxSdkVersion string
}
// gatherPossibleApexModuleNamesAndStems returns a set of module and stem names from the
@@ -120,10 +120,32 @@
jars := make([]classpathJar, 0, len(paths)*len(classpaths))
for i := 0; i < len(paths); i++ {
for _, classpathType := range classpaths {
- jars = append(jars, classpathJar{
+ jar := classpathJar{
classpath: classpathType,
path: paths[i],
+ }
+ ctx.VisitDirectDepsIf(func(m android.Module) bool {
+ return m.Name() == configuredJars.Jar(i)
+ }, func(m android.Module) {
+ if s, ok := m.(*SdkLibrary); ok {
+ // TODO(208456999): instead of mapping "current" to latest, min_sdk_version should never be set to "current"
+ if s.minSdkVersion.Specified() {
+ if s.minSdkVersion.ApiLevel.IsCurrent() {
+ jar.minSdkVersion = ctx.Config().LatestPreviewApiLevel().String()
+ } else {
+ jar.minSdkVersion = s.minSdkVersion.ApiLevel.String()
+ }
+ }
+ if s.maxSdkVersion.Specified() {
+ if s.maxSdkVersion.ApiLevel.IsCurrent() {
+ jar.maxSdkVersion = ctx.Config().LatestPreviewApiLevel().String()
+ } else {
+ jar.maxSdkVersion = s.maxSdkVersion.ApiLevel.String()
+ }
+ }
+ }
})
+ jars = append(jars, jar)
}
}
return jars
@@ -136,15 +158,15 @@
c.outputFilepath = android.PathForModuleOut(ctx, outputFilename).OutputPath
c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths")
- generatedJson := android.PathForModuleOut(ctx, outputFilename+".json")
- writeClasspathsJson(ctx, generatedJson, jars)
+ generatedTextproto := android.PathForModuleOut(ctx, outputFilename+".textproto")
+ writeClasspathsTextproto(ctx, generatedTextproto, jars)
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
BuiltTool("conv_classpaths_proto").
Flag("encode").
- Flag("--format=json").
- FlagWithInput("--input=", generatedJson).
+ Flag("--format=textproto").
+ FlagWithInput("--input=", generatedTextproto).
FlagWithOutput("--output=", c.outputFilepath)
rule.Build("classpath_fragment", "Compiling "+c.outputFilepath.String())
@@ -159,24 +181,18 @@
ctx.SetProvider(ClasspathFragmentProtoContentInfoProvider, classpathProtoInfo)
}
-func writeClasspathsJson(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) {
+func writeClasspathsTextproto(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) {
var content strings.Builder
- fmt.Fprintf(&content, "{\n")
- fmt.Fprintf(&content, "\"jars\": [\n")
- for idx, jar := range jars {
- fmt.Fprintf(&content, "{\n")
- fmt.Fprintf(&content, "\"path\": \"%s\",\n", jar.path)
- fmt.Fprintf(&content, "\"classpath\": \"%s\"\n", jar.classpath)
-
- if idx < len(jars)-1 {
- fmt.Fprintf(&content, "},\n")
- } else {
- fmt.Fprintf(&content, "}\n")
- }
+ for _, jar := range jars {
+ fmt.Fprintf(&content, "jars {\n")
+ fmt.Fprintf(&content, "path: \"%s\"\n", jar.path)
+ fmt.Fprintf(&content, "classpath: %s\n", jar.classpath)
+ fmt.Fprintf(&content, "min_sdk_version: \"%s\"\n", jar.minSdkVersion)
+ fmt.Fprintf(&content, "max_sdk_version: \"%s\"\n", jar.maxSdkVersion)
+ fmt.Fprintf(&content, "}\n")
}
- fmt.Fprintf(&content, "]\n")
- fmt.Fprintf(&content, "}\n")
+
android.WriteFileRule(ctx, output, content.String())
}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 7c081b6..f3a53ee 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -122,13 +122,7 @@
}
func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
- global := dexpreopt.GetGlobalConfig(ctx)
-
- if global.DisablePreopt {
- return true
- }
-
- if inList(moduleName(ctx), global.DisablePreoptModules) {
+ if !ctx.Device() {
return true
}
@@ -144,7 +138,17 @@
return true
}
- if ctx.Host() {
+ if !android.IsModulePreferred(ctx.Module()) {
+ return true
+ }
+
+ global := dexpreopt.GetGlobalConfig(ctx)
+
+ if global.DisablePreopt {
+ return true
+ }
+
+ if inList(moduleName(ctx), global.DisablePreoptModules) {
return true
}
@@ -161,10 +165,6 @@
}
}
- if !android.IsModulePreferred(ctx.Module()) {
- return true
- }
-
// TODO: contains no java code
return false
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 284a19a..75083e8 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -256,6 +256,10 @@
// Subdirectory where the image files on device are installed.
installDirOnDevice string
+ // Install path of the boot image profile if it needs to be installed in the APEX, or empty if not
+ // needed.
+ profileInstallPathInApex string
+
// A list of (location, jar) pairs for the Java modules in this image.
modules android.ConfiguredJarList
@@ -272,6 +276,9 @@
// Rules which should be used in make to install the outputs.
profileInstalls android.RuleBuilderInstalls
+ // Path to the image profile file on host (or empty, if profile is not generated).
+ profilePathOnHost android.Path
+
// Target-dependent fields.
variants []*bootImageVariant
}
@@ -625,7 +632,6 @@
Flag("--runtime-arg").FlagWithArg("-Xmx", global.Dex2oatImageXmx)
if profile != nil {
- cmd.FlagWithArg("--compiler-filter=", "speed-profile")
cmd.FlagWithInput("--profile-file=", profile)
}
@@ -770,11 +776,14 @@
FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps).
FlagWithOutput("--reference-profile-file=", profile)
- rule.Install(profile, "/system/etc/boot-image.prof")
+ if image == defaultBootImageConfig(ctx) {
+ rule.Install(profile, "/system/etc/boot-image.prof")
+ image.profileInstalls = append(image.profileInstalls, rule.Installs()...)
+ }
rule.Build("bootJarsProfile", "profile boot jars")
- image.profileInstalls = append(image.profileInstalls, rule.Installs()...)
+ image.profilePathOnHost = profile
return profile
}
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 415a1d4..26c1105 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -56,22 +56,20 @@
artModules := global.ArtApexJars
frameworkModules := global.BootJars.RemoveList(artModules)
- artDirOnHost := "apex/art_boot_images/javalib"
- artDirOnDevice := "apex/com.android.art/javalib"
- frameworkSubdir := "system/framework"
-
// ART config for the primary boot image in the ART apex.
// It includes the Core Libraries.
artCfg := bootImageConfig{
- name: artBootImageName,
- stem: "boot",
- installDirOnHost: artDirOnHost,
- installDirOnDevice: artDirOnDevice,
- modules: artModules,
+ name: artBootImageName,
+ stem: "boot",
+ installDirOnHost: "apex/art_boot_images/javalib",
+ installDirOnDevice: "apex/com.android.art/javalib",
+ profileInstallPathInApex: "etc/boot-image.prof",
+ modules: artModules,
}
// Framework config for the boot image extension.
// It includes framework libraries and depends on the ART config.
+ frameworkSubdir := "system/framework"
frameworkCfg := bootImageConfig{
extends: &artCfg,
name: frameworkBootImageName,
diff --git a/java/java.go b/java/java.go
index 2f9e03a..f77c694 100644
--- a/java/java.go
+++ b/java/java.go
@@ -21,7 +21,9 @@
import (
"fmt"
"path/filepath"
+ "strings"
+ "android/soong/bazel"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -270,6 +272,9 @@
type dependencyTag struct {
blueprint.BaseDependencyTag
name string
+
+ // True if the dependency is relinked at runtime.
+ runtimeLinked bool
}
// installDependencyTag is a dependency tag that is annotated to cause the installed files of the
@@ -280,6 +285,15 @@
name string
}
+func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
+ if d.runtimeLinked {
+ return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency}
+ }
+ return nil
+}
+
+var _ android.LicenseAnnotationsDependencyTag = dependencyTag{}
+
type usesLibraryDependencyTag struct {
dependencyTag
@@ -296,10 +310,13 @@
func makeUsesLibraryDependencyTag(sdkVersion int, optional bool, implicit bool) usesLibraryDependencyTag {
return usesLibraryDependencyTag{
- dependencyTag: dependencyTag{name: fmt.Sprintf("uses-library-%d", sdkVersion)},
- sdkVersion: sdkVersion,
- optional: optional,
- implicit: implicit,
+ dependencyTag: dependencyTag{
+ name: fmt.Sprintf("uses-library-%d", sdkVersion),
+ runtimeLinked: true,
+ },
+ sdkVersion: sdkVersion,
+ optional: optional,
+ implicit: implicit,
}
}
@@ -310,22 +327,22 @@
var (
dataNativeBinsTag = dependencyTag{name: "dataNativeBins"}
staticLibTag = dependencyTag{name: "staticlib"}
- libTag = dependencyTag{name: "javalib"}
- java9LibTag = dependencyTag{name: "java9lib"}
+ libTag = dependencyTag{name: "javalib", runtimeLinked: true}
+ java9LibTag = dependencyTag{name: "java9lib", runtimeLinked: true}
pluginTag = dependencyTag{name: "plugin"}
errorpronePluginTag = dependencyTag{name: "errorprone-plugin"}
exportedPluginTag = dependencyTag{name: "exported-plugin"}
- bootClasspathTag = dependencyTag{name: "bootclasspath"}
- systemModulesTag = dependencyTag{name: "system modules"}
+ bootClasspathTag = dependencyTag{name: "bootclasspath", runtimeLinked: true}
+ systemModulesTag = dependencyTag{name: "system modules", runtimeLinked: true}
frameworkResTag = dependencyTag{name: "framework-res"}
- kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"}
- kotlinAnnotationsTag = dependencyTag{name: "kotlin-annotations"}
+ kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib", runtimeLinked: true}
+ kotlinAnnotationsTag = dependencyTag{name: "kotlin-annotations", runtimeLinked: true}
kotlinPluginTag = dependencyTag{name: "kotlin-plugin"}
proguardRaiseTag = dependencyTag{name: "proguard-raise"}
certificateTag = dependencyTag{name: "certificate"}
instrumentationForTag = dependencyTag{name: "instrumentation_for"}
extraLintCheckTag = dependencyTag{name: "extra-lint-check"}
- jniLibTag = dependencyTag{name: "jnilib"}
+ jniLibTag = dependencyTag{name: "jnilib", runtimeLinked: true}
syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
jniInstallTag = installDependencyTag{name: "jni install"}
binaryInstallTag = installDependencyTag{name: "binary install"}
@@ -434,6 +451,12 @@
return normalizeJavaVersion(ctx, javaVersion)
} else if ctx.Device() {
return defaultJavaLanguageVersion(ctx, sdkContext.SdkVersion(ctx))
+ } else if ctx.Config().IsEnvTrue("EXPERIMENTAL_TARGET_JAVA_VERSION_11") {
+ // Temporary experimental flag to be able to try and build with
+ // java version 11 options. The flag, if used, just sets Java
+ // 11 as the default version, leaving any components that
+ // target an older version intact.
+ return JAVA_VERSION_11
} else {
return JAVA_VERSION_9
}
@@ -447,6 +470,7 @@
JAVA_VERSION_7 = 7
JAVA_VERSION_8 = 8
JAVA_VERSION_9 = 9
+ JAVA_VERSION_11 = 11
)
func (v javaVersion) String() string {
@@ -459,6 +483,8 @@
return "1.8"
case JAVA_VERSION_9:
return "1.9"
+ case JAVA_VERSION_11:
+ return "11"
default:
return "unsupported"
}
@@ -479,8 +505,10 @@
return JAVA_VERSION_8
case "1.9", "9":
return JAVA_VERSION_9
- case "10", "11":
- ctx.PropertyErrorf("java_version", "Java language levels above 9 are not supported")
+ case "11":
+ return JAVA_VERSION_11
+ case "10":
+ ctx.PropertyErrorf("java_version", "Java language levels 10 is not supported")
return JAVA_VERSION_UNSUPPORTED
default:
ctx.PropertyErrorf("java_version", "Unrecognized Java language level")
@@ -545,6 +573,7 @@
func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.sdkVersion = j.SdkVersion(ctx)
j.minSdkVersion = j.MinSdkVersion(ctx)
+ j.maxSdkVersion = j.MaxSdkVersion(ctx)
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
if !apexInfo.IsForPlatform() {
@@ -729,6 +758,7 @@
android.InitApexModule(module)
android.InitSdkAwareModule(module)
+ android.InitBazelModule(module)
InitJavaModule(module, android.HostAndDeviceSupported)
return module
}
@@ -751,6 +781,7 @@
android.InitApexModule(module)
android.InitSdkAwareModule(module)
+ android.InitBazelModule(module)
InitJavaModule(module, android.HostSupported)
return module
}
@@ -1201,6 +1232,8 @@
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommonFirst)
android.InitDefaultableModule(module)
+ android.InitBazelModule(module)
+
return module
}
@@ -1218,6 +1251,7 @@
android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommonFirst)
android.InitDefaultableModule(module)
+ android.InitBazelModule(module)
return module
}
@@ -1934,3 +1968,103 @@
clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
}
}
+
+type javaLibraryAttributes struct {
+ Srcs bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Javacopts bazel.StringListAttribute
+}
+
+func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
+ srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs))
+ attrs := &javaLibraryAttributes{
+ Srcs: srcs,
+ }
+
+ if m.properties.Javacflags != nil {
+ attrs.Javacopts = bazel.MakeStringListAttribute(m.properties.Javacflags)
+ }
+
+ if m.properties.Libs != nil {
+ attrs.Deps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, m.properties.Libs))
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "java_library",
+ Bzl_load_location: "//build/bazel/rules/java:library.bzl",
+ }
+
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
+}
+
+type javaBinaryHostAttributes struct {
+ Srcs bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Main_class string
+ Jvm_flags bazel.StringListAttribute
+}
+
+// JavaBinaryHostBp2Build is for java_binary_host bp2build.
+func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) {
+ mainClass := ""
+ if m.binaryProperties.Main_class != nil {
+ mainClass = *m.binaryProperties.Main_class
+ }
+ if m.properties.Manifest != nil {
+ mainClassInManifest, err := android.GetMainClassInManifest(ctx.Config(), android.PathForModuleSrc(ctx, *m.properties.Manifest).String())
+ if err != nil {
+ return
+ }
+ mainClass = mainClassInManifest
+ }
+ srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs))
+ attrs := &javaBinaryHostAttributes{
+ Srcs: srcs,
+ Main_class: mainClass,
+ }
+
+ // Attribute deps
+ deps := []string{}
+ if m.properties.Static_libs != nil {
+ deps = append(deps, m.properties.Static_libs...)
+ }
+ if m.binaryProperties.Jni_libs != nil {
+ deps = append(deps, m.binaryProperties.Jni_libs...)
+ }
+ if len(deps) > 0 {
+ attrs.Deps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, deps))
+ }
+
+ // Attribute jvm_flags
+ if m.binaryProperties.Jni_libs != nil {
+ jniLibPackages := map[string]bool{}
+ for _, jniLibLabel := range android.BazelLabelForModuleDeps(ctx, m.binaryProperties.Jni_libs).Includes {
+ jniLibPackage := jniLibLabel.Label
+ indexOfColon := strings.Index(jniLibLabel.Label, ":")
+ if indexOfColon > 0 {
+ // JNI lib from other package
+ jniLibPackage = jniLibLabel.Label[2:indexOfColon]
+ } else if indexOfColon == 0 {
+ // JNI lib in the same package of java_binary
+ packageOfCurrentModule := m.GetBazelLabel(ctx, m)
+ jniLibPackage = packageOfCurrentModule[2:strings.Index(packageOfCurrentModule, ":")]
+ }
+ if _, inMap := jniLibPackages[jniLibPackage]; !inMap {
+ jniLibPackages[jniLibPackage] = true
+ }
+ }
+ jniLibPaths := []string{}
+ for jniLibPackage, _ := range jniLibPackages {
+ // See cs/f:.*/third_party/bazel/.*java_stub_template.txt for the use of RUNPATH
+ jniLibPaths = append(jniLibPaths, "$${RUNPATH}"+jniLibPackage)
+ }
+ attrs.Jvm_flags = bazel.MakeStringListAttribute([]string{"-Djava.library.path=" + strings.Join(jniLibPaths, ":")})
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "java_binary",
+ }
+
+ // Create the BazelTargetModule.
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
+}
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 9fec08a..1e27238 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -68,7 +68,6 @@
func platformBootclasspathFactory() android.SingletonModule {
m := &platformBootclasspathModule{}
m.AddProperties(&m.properties)
- // TODO(satayev): split apex jars into separate configs.
initClasspathFragment(m, BOOTCLASSPATH)
android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
return m
diff --git a/java/sdk.go b/java/sdk.go
index e6bf220..de7070e 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -55,6 +55,12 @@
return JAVA_VERSION_7
} else if sdk.FinalOrFutureInt() <= 29 {
return JAVA_VERSION_8
+ } else if ctx.Config().IsEnvTrue("EXPERIMENTAL_TARGET_JAVA_VERSION_11") {
+ // Temporary experimental flag to be able to try and build with
+ // java version 11 options. The flag, if used, just sets Java
+ // 11 as the default version, leaving any components that
+ // target an older version intact.
+ return JAVA_VERSION_11
} else {
return JAVA_VERSION_9
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index d7f14d6..de0d796 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -21,6 +21,7 @@
"reflect"
"regexp"
"sort"
+ "strconv"
"strings"
"sync"
@@ -32,25 +33,7 @@
)
const (
- sdkXmlFileSuffix = ".xml"
- permissionsTemplate = `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n` +
- `<!-- Copyright (C) 2018 The Android Open Source Project\n` +
- `\n` +
- ` Licensed under the Apache License, Version 2.0 (the \"License\");\n` +
- ` you may not use this file except in compliance with the License.\n` +
- ` You may obtain a copy of the License at\n` +
- `\n` +
- ` http://www.apache.org/licenses/LICENSE-2.0\n` +
- `\n` +
- ` Unless required by applicable law or agreed to in writing, software\n` +
- ` distributed under the License is distributed on an \"AS IS\" BASIS,\n` +
- ` WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n` +
- ` See the License for the specific language governing permissions and\n` +
- ` limitations under the License.\n` +
- `-->\n` +
- `<permissions>\n` +
- ` <library name=\"%s\" file=\"%s\"/>\n` +
- `</permissions>\n`
+ sdkXmlFileSuffix = ".xml"
)
// A tag to associated a dependency with a specific api scope.
@@ -637,6 +620,33 @@
// Files containing information about supported java doc tags.
Doctag_files []string `android:"path"`
+
+ // Signals that this shared library is part of the bootclasspath starting
+ // on the version indicated in this attribute.
+ //
+ // This will make platforms at this level and above to ignore
+ // <uses-library> tags with this library name because the library is already
+ // available
+ On_bootclasspath_since *string
+
+ // Signals that this shared library was part of the bootclasspath before
+ // (but not including) the version indicated in this attribute.
+ //
+ // The system will automatically add a <uses-library> tag with this library to
+ // apps that target any SDK less than the version indicated in this attribute.
+ On_bootclasspath_before *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is below the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Min_device_sdk *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is above the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Max_device_sdk *string
}
// commonSdkLibraryAndImportModule defines the interface that must be provided by a module that
@@ -1119,6 +1129,22 @@
return generatedScopes
}
+var _ android.ModuleWithMinSdkVersionCheck = (*SdkLibrary)(nil)
+
+func (module *SdkLibrary) CheckMinSdkVersion(ctx android.ModuleContext) {
+ android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx).ApiLevel, func(c android.ModuleContext, do android.PayloadDepsCallback) {
+ ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
+ isExternal := !module.depIsInSameApex(ctx, child)
+ if am, ok := child.(android.ApexModule); ok {
+ if !do(ctx, parent, am, isExternal) {
+ return false
+ }
+ }
+ return !isExternal
+ })
+ })
+}
+
type sdkLibraryComponentTag struct {
blueprint.BaseDependencyTag
name string
@@ -1196,14 +1222,23 @@
func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) {
paths, err := module.commonOutputFiles(tag)
- if paths == nil && err == nil {
- return module.Library.OutputFiles(tag)
- } else {
+ if paths != nil || err != nil {
return paths, err
}
+ if module.requiresRuntimeImplementationLibrary() {
+ return module.Library.OutputFiles(tag)
+ }
+ if tag == "" {
+ return nil, nil
+ }
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if proptools.String(module.deviceProperties.Min_sdk_version) != "" {
+ module.CheckMinSdkVersion(ctx)
+ }
+
module.generateCommonBuildActions(ctx)
// Only build an implementation library if required.
@@ -1580,14 +1615,29 @@
// Creates the xml file that publicizes the runtime library
func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
+ moduleMinApiLevel := module.Library.MinSdkVersion(mctx).ApiLevel
+ var moduleMinApiLevelStr = moduleMinApiLevel.String()
+ if moduleMinApiLevel == android.NoneApiLevel {
+ moduleMinApiLevelStr = "current"
+ }
props := struct {
- Name *string
- Lib_name *string
- Apex_available []string
+ Name *string
+ Lib_name *string
+ Apex_available []string
+ On_bootclasspath_since *string
+ On_bootclasspath_before *string
+ Min_device_sdk *string
+ Max_device_sdk *string
+ Sdk_library_min_api_level *string
}{
- Name: proptools.StringPtr(module.xmlPermissionsModuleName()),
- Lib_name: proptools.StringPtr(module.BaseModuleName()),
- Apex_available: module.ApexProperties.Apex_available,
+ Name: proptools.StringPtr(module.xmlPermissionsModuleName()),
+ Lib_name: proptools.StringPtr(module.BaseModuleName()),
+ Apex_available: module.ApexProperties.Apex_available,
+ On_bootclasspath_since: module.commonSdkLibraryProperties.On_bootclasspath_since,
+ On_bootclasspath_before: module.commonSdkLibraryProperties.On_bootclasspath_before,
+ Min_device_sdk: module.commonSdkLibraryProperties.Min_device_sdk,
+ Max_device_sdk: module.commonSdkLibraryProperties.Max_device_sdk,
+ Sdk_library_min_api_level: &moduleMinApiLevelStr,
}
mctx.CreateModule(sdkLibraryXmlFactory, &props)
@@ -2383,6 +2433,38 @@
type sdkLibraryXmlProperties struct {
// canonical name of the lib
Lib_name *string
+
+ // Signals that this shared library is part of the bootclasspath starting
+ // on the version indicated in this attribute.
+ //
+ // This will make platforms at this level and above to ignore
+ // <uses-library> tags with this library name because the library is already
+ // available
+ On_bootclasspath_since *string
+
+ // Signals that this shared library was part of the bootclasspath before
+ // (but not including) the version indicated in this attribute.
+ //
+ // The system will automatically add a <uses-library> tag with this library to
+ // apps that target any SDK less than the version indicated in this attribute.
+ On_bootclasspath_before *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is below the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Min_device_sdk *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is above the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Max_device_sdk *string
+
+ // The SdkLibrary's min api level as a string
+ //
+ // This value comes from the ApiLevel of the MinSdkVersion property.
+ Sdk_library_min_api_level *string
}
// java_sdk_library_xml builds the permission xml file for a java_sdk_library.
@@ -2459,11 +2541,81 @@
return "/" + partition + "/framework/" + implName + ".jar"
}
+func formattedOptionalSdkLevelAttribute(ctx android.ModuleContext, attrName string, value *string) string {
+ if value == nil {
+ return ""
+ }
+ apiLevel, err := android.ApiLevelFromUser(ctx, *value)
+ if err != nil {
+ // attributes in bp files have underscores but in the xml have dashes.
+ ctx.PropertyErrorf(strings.ReplaceAll(attrName, "-", "_"), err.Error())
+ return ""
+ }
+ intStr := strconv.Itoa(apiLevel.FinalOrPreviewInt())
+ return formattedOptionalAttribute(attrName, &intStr)
+}
+
+// formats an attribute for the xml permissions file if the value is not null
+// returns empty string otherwise
+func formattedOptionalAttribute(attrName string, value *string) string {
+ if value == nil {
+ return ""
+ }
+ return fmt.Sprintf(` %s=\"%s\"\n`, attrName, *value)
+}
+
+func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) string {
+ libName := proptools.String(module.properties.Lib_name)
+ libNameAttr := formattedOptionalAttribute("name", &libName)
+ filePath := module.implPath(ctx)
+ filePathAttr := formattedOptionalAttribute("file", &filePath)
+ implicitFromAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-since", module.properties.On_bootclasspath_since)
+ implicitUntilAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-before", module.properties.On_bootclasspath_before)
+ minSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "min-device-sdk", module.properties.Min_device_sdk)
+ maxSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "max-device-sdk", module.properties.Max_device_sdk)
+ // <library> is understood in all android versions whereas <updatable-library> is only understood from API T (and ignored before that).
+ // similarly, min_device_sdk is only understood from T. So if a library is using that, we need to use the updatable-library to make sure this library is not loaded before T
+ var libraryTag string
+ if module.properties.Min_device_sdk != nil {
+ libraryTag = ` <updatable-library\n`
+ } else {
+ libraryTag = ` <library\n`
+ }
+
+ return strings.Join([]string{
+ `<?xml version=\"1.0\" encoding=\"utf-8\"?>\n`,
+ `<!-- Copyright (C) 2018 The Android Open Source Project\n`,
+ `\n`,
+ ` Licensed under the Apache License, Version 2.0 (the \"License\");\n`,
+ ` you may not use this file except in compliance with the License.\n`,
+ ` You may obtain a copy of the License at\n`,
+ `\n`,
+ ` http://www.apache.org/licenses/LICENSE-2.0\n`,
+ `\n`,
+ ` Unless required by applicable law or agreed to in writing, software\n`,
+ ` distributed under the License is distributed on an \"AS IS\" BASIS,\n`,
+ ` WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n`,
+ ` See the License for the specific language governing permissions and\n`,
+ ` limitations under the License.\n`,
+ `-->\n`,
+ `<permissions>\n`,
+ libraryTag,
+ libNameAttr,
+ filePathAttr,
+ implicitFromAttr,
+ implicitUntilAttr,
+ minSdkAttr,
+ maxSdkAttr,
+ ` />\n`,
+ `</permissions>\n`}, "")
+}
+
func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {
module.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
libName := proptools.String(module.properties.Lib_name)
- xmlContent := fmt.Sprintf(permissionsTemplate, libName, module.implPath(ctx))
+ module.selfValidate(ctx)
+ xmlContent := module.permissionsContents(ctx)
module.outputFilePath = android.PathForModuleOut(ctx, libName+".xml").OutputPath
rule := android.NewRuleBuilder(pctx, ctx)
@@ -2478,12 +2630,12 @@
func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
if module.hideApexVariantFromMake {
- return []android.AndroidMkEntries{android.AndroidMkEntries{
+ return []android.AndroidMkEntries{{
Disabled: true,
}}
}
- return []android.AndroidMkEntries{android.AndroidMkEntries{
+ return []android.AndroidMkEntries{{
Class: "ETC",
OutputFile: android.OptionalPathForPath(module.outputFilePath),
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
@@ -2496,6 +2648,81 @@
}}
}
+func (module *sdkLibraryXml) selfValidate(ctx android.ModuleContext) {
+ module.validateAtLeastTAttributes(ctx)
+ module.validateMinAndMaxDeviceSdk(ctx)
+ module.validateMinMaxDeviceSdkAndModuleMinSdk(ctx)
+ module.validateOnBootclasspathBeforeRequirements(ctx)
+}
+
+func (module *sdkLibraryXml) validateAtLeastTAttributes(ctx android.ModuleContext) {
+ t := android.ApiLevelOrPanic(ctx, "Tiramisu")
+ module.attrAtLeastT(ctx, t, module.properties.Min_device_sdk, "min_device_sdk")
+ module.attrAtLeastT(ctx, t, module.properties.Max_device_sdk, "max_device_sdk")
+ module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_before, "on_bootclasspath_before")
+ module.attrAtLeastT(ctx, t, module.properties.On_bootclasspath_since, "on_bootclasspath_since")
+}
+
+func (module *sdkLibraryXml) attrAtLeastT(ctx android.ModuleContext, t android.ApiLevel, attr *string, attrName string) {
+ if attr != nil {
+ if level, err := android.ApiLevelFromUser(ctx, *attr); err == nil {
+ // we will inform the user of invalid inputs when we try to write the
+ // permissions xml file so we don't need to do it here
+ if t.GreaterThan(level) {
+ ctx.PropertyErrorf(attrName, "Attribute value needs to be at least T")
+ }
+ }
+ }
+}
+
+func (module *sdkLibraryXml) validateMinAndMaxDeviceSdk(ctx android.ModuleContext) {
+ if module.properties.Min_device_sdk != nil && module.properties.Max_device_sdk != nil {
+ min, minErr := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
+ max, maxErr := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
+ if minErr == nil && maxErr == nil {
+ // we will inform the user of invalid inputs when we try to write the
+ // permissions xml file so we don't need to do it here
+ if min.GreaterThan(max) {
+ ctx.ModuleErrorf("min_device_sdk can't be greater than max_device_sdk")
+ }
+ }
+ }
+}
+
+func (module *sdkLibraryXml) validateMinMaxDeviceSdkAndModuleMinSdk(ctx android.ModuleContext) {
+ moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
+ if module.properties.Min_device_sdk != nil {
+ api, err := android.ApiLevelFromUser(ctx, *module.properties.Min_device_sdk)
+ if err == nil {
+ if moduleMinApi.GreaterThan(api) {
+ ctx.PropertyErrorf("min_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
+ }
+ }
+ }
+ if module.properties.Max_device_sdk != nil {
+ api, err := android.ApiLevelFromUser(ctx, *module.properties.Max_device_sdk)
+ if err == nil {
+ if moduleMinApi.GreaterThan(api) {
+ ctx.PropertyErrorf("max_device_sdk", "Can't be less than module's min sdk (%s)", moduleMinApi)
+ }
+ }
+ }
+}
+
+func (module *sdkLibraryXml) validateOnBootclasspathBeforeRequirements(ctx android.ModuleContext) {
+ moduleMinApi := android.ApiLevelOrPanic(ctx, *module.properties.Sdk_library_min_api_level)
+ if module.properties.On_bootclasspath_before != nil {
+ t := android.ApiLevelOrPanic(ctx, "Tiramisu")
+ // if we use the attribute, then we need to do this validation
+ if moduleMinApi.LessThan(t) {
+ // if minAPi is < T, then we need to have min_device_sdk (which only accepts T+)
+ if module.properties.Min_device_sdk == nil {
+ ctx.PropertyErrorf("on_bootclasspath_before", "Using this property requires that the module's min_sdk_version or the shared library's min_device_sdk is at least T")
+ }
+ }
+ }
+}
+
type sdkLibrarySdkMemberType struct {
android.SdkMemberTypeBase
}
@@ -2547,6 +2774,33 @@
Doctag_paths android.Paths
Permitted_packages []string
+
+ // Signals that this shared library is part of the bootclasspath starting
+ // on the version indicated in this attribute.
+ //
+ // This will make platforms at this level and above to ignore
+ // <uses-library> tags with this library name because the library is already
+ // available
+ On_bootclasspath_since *string
+
+ // Signals that this shared library was part of the bootclasspath before
+ // (but not including) the version indicated in this attribute.
+ //
+ // The system will automatically add a <uses-library> tag with this library to
+ // apps that target any SDK less than the version indicated in this attribute.
+ On_bootclasspath_before *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is below the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Min_device_sdk *string
+
+ // Indicates that PackageManager should ignore this shared library if the
+ // platform is above the version indicated in this attribute.
+ //
+ // This means that the device won't recognise this library as installed.
+ Max_device_sdk *string
}
type scopeProperties struct {
@@ -2593,6 +2847,10 @@
s.Compile_dex = sdk.dexProperties.Compile_dex
s.Doctag_paths = sdk.doctagPaths
s.Permitted_packages = sdk.PermittedPackagesForUpdatableBootJars()
+ s.On_bootclasspath_since = sdk.commonSdkLibraryProperties.On_bootclasspath_since
+ s.On_bootclasspath_before = sdk.commonSdkLibraryProperties.On_bootclasspath_before
+ s.Min_device_sdk = sdk.commonSdkLibraryProperties.Min_device_sdk
+ s.Max_device_sdk = sdk.commonSdkLibraryProperties.Max_device_sdk
}
func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index be23536..f3a19e9 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -15,12 +15,13 @@
package java
import (
- "android/soong/android"
"fmt"
"path/filepath"
"regexp"
"testing"
+ "android/soong/android"
+
"github.com/google/blueprint/proptools"
)
@@ -107,7 +108,7 @@
libs: ["foo"],
sdk_version: "module_30",
}
- `)
+ `)
// check the existence of the internal modules
foo := result.ModuleForTests("foo", "android_common")
@@ -162,6 +163,185 @@
}
}
+func TestJavaSdkLibrary_UpdatableLibrary(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "28": {"foo"},
+ "29": {"foo"},
+ "30": {"foo", "fooUpdatable", "fooUpdatableErr"},
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_version_active_codenames = []string{"Tiramisu", "U", "V", "W"}
+ }),
+ ).RunTestWithBp(t,
+ `
+ java_sdk_library {
+ name: "fooUpdatable",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ on_bootclasspath_since: "U",
+ on_bootclasspath_before: "V",
+ min_device_sdk: "W",
+ max_device_sdk: "current",
+ min_sdk_version: "S",
+ }
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ }
+`)
+ // test that updatability attributes are passed on correctly
+ fooUpdatable := result.ModuleForTests("fooUpdatable.xml", "android_common").Rule("java_sdk_xml")
+ android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `on-bootclasspath-since=\"9001\"`)
+ android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `on-bootclasspath-before=\"9002\"`)
+ android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `min-device-sdk=\"9003\"`)
+ android.AssertStringDoesContain(t, "fooUpdatable.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `max-device-sdk=\"10000\"`)
+
+ // double check that updatability attributes are not written if they don't exist in the bp file
+ // the permissions file for the foo library defined above
+ fooPermissions := result.ModuleForTests("foo.xml", "android_common").Rule("java_sdk_xml")
+ android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooPermissions.RuleParams.Command, `on-bootclasspath-since`)
+ android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooPermissions.RuleParams.Command, `on-bootclasspath-before`)
+ android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooPermissions.RuleParams.Command, `min-device-sdk`)
+ android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooPermissions.RuleParams.Command, `max-device-sdk`)
+}
+
+func TestJavaSdkLibrary_UpdatableLibrary_Validation_ValidVersion(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "30": {"fooUpdatable", "fooUpdatableErr"},
+ }),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(
+ []string{
+ `on_bootclasspath_since: "aaa" could not be parsed as an integer and is not a recognized codename`,
+ `on_bootclasspath_before: "bbc" could not be parsed as an integer and is not a recognized codename`,
+ `min_device_sdk: "ccc" could not be parsed as an integer and is not a recognized codename`,
+ `max_device_sdk: "ddd" could not be parsed as an integer and is not a recognized codename`,
+ })).RunTestWithBp(t,
+ `
+ java_sdk_library {
+ name: "fooUpdatableErr",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ on_bootclasspath_since: "aaa",
+ on_bootclasspath_before: "bbc",
+ min_device_sdk: "ccc",
+ max_device_sdk: "ddd",
+ }
+`)
+}
+
+func TestJavaSdkLibrary_UpdatableLibrary_Validation_AtLeastTAttributes(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "28": {"foo"},
+ }),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(
+ []string{
+ "on_bootclasspath_since: Attribute value needs to be at least T",
+ "on_bootclasspath_before: Attribute value needs to be at least T",
+ "min_device_sdk: Attribute value needs to be at least T",
+ "max_device_sdk: Attribute value needs to be at least T",
+ },
+ )).RunTestWithBp(t,
+ `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ on_bootclasspath_since: "S",
+ on_bootclasspath_before: "S",
+ min_device_sdk: "S",
+ max_device_sdk: "S",
+ min_sdk_version: "S",
+ }
+`)
+}
+
+func TestJavaSdkLibrary_UpdatableLibrary_Validation_MinAndMaxDeviceSdk(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "28": {"foo"},
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_version_active_codenames = []string{"Tiramisu", "U", "V"}
+ }),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(
+ []string{
+ "min_device_sdk can't be greater than max_device_sdk",
+ },
+ )).RunTestWithBp(t,
+ `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ min_device_sdk: "V",
+ max_device_sdk: "U",
+ min_sdk_version: "S",
+ }
+`)
+}
+
+func TestJavaSdkLibrary_UpdatableLibrary_Validation_MinAndMaxDeviceSdkAndModuleMinSdk(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "28": {"foo"},
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_version_active_codenames = []string{"Tiramisu", "U", "V"}
+ }),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(
+ []string{
+ regexp.QuoteMeta("min_device_sdk: Can't be less than module's min sdk (V)"),
+ regexp.QuoteMeta("max_device_sdk: Can't be less than module's min sdk (V)"),
+ },
+ )).RunTestWithBp(t,
+ `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ min_device_sdk: "U",
+ max_device_sdk: "U",
+ min_sdk_version: "V",
+ }
+`)
+}
+
+func TestJavaSdkLibrary_UpdatableLibrary_usesNewTag(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "30": {"foo"},
+ }),
+ ).RunTestWithBp(t,
+ `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ min_device_sdk: "Tiramisu",
+ min_sdk_version: "S",
+ }
+`)
+ // test that updatability attributes are passed on correctly
+ fooUpdatable := result.ModuleForTests("foo.xml", "android_common").Rule("java_sdk_xml")
+ android.AssertStringDoesContain(t, "foo.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `<updatable-library`)
+ android.AssertStringDoesNotContain(t, "foo.xml java_sdk_xml command", fooUpdatable.RuleParams.Command, `<library`)
+}
+
func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForJavaTest,
@@ -960,3 +1140,87 @@
})
}
}
+
+func TestSdkLibrary_CheckMinSdkVersion(t *testing.T) {
+ preparer := android.GroupFixturePreparers(
+ PrepareForTestWithJavaBuildComponents,
+ PrepareForTestWithJavaDefaultModules,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ )
+
+ preparer.RunTestWithBp(t, `
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ static_libs: ["util"],
+ min_sdk_version: "30",
+ unsafe_ignore_missing_latest_api: true,
+ }
+
+ java_library {
+ name: "util",
+ srcs: ["a.java"],
+ min_sdk_version: "30",
+ }
+ `)
+
+ preparer.
+ RunTestWithBp(t, `
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ libs: ["util"],
+ impl_only_libs: ["util"],
+ stub_only_libs: ["util"],
+ stub_only_static_libs: ["util"],
+ min_sdk_version: "30",
+ unsafe_ignore_missing_latest_api: true,
+ }
+
+ java_library {
+ name: "util",
+ srcs: ["a.java"],
+ }
+ `)
+
+ preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "util".*should support min_sdk_version\(30\)`)).
+ RunTestWithBp(t, `
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ static_libs: ["util"],
+ min_sdk_version: "30",
+ unsafe_ignore_missing_latest_api: true,
+ }
+
+ java_library {
+ name: "util",
+ srcs: ["a.java"],
+ min_sdk_version: "31",
+ }
+ `)
+
+ preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "another_util".*should support min_sdk_version\(30\)`)).
+ RunTestWithBp(t, `
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ static_libs: ["util"],
+ min_sdk_version: "30",
+ unsafe_ignore_missing_latest_api: true,
+ }
+
+ java_library {
+ name: "util",
+ srcs: ["a.java"],
+ static_libs: ["another_util"],
+ min_sdk_version: "30",
+ }
+
+ java_library {
+ name: "another_util",
+ srcs: ["a.java"],
+ min_sdk_version: "31",
+ }
+ `)
+}
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index e263cc4..2ec33a4 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -58,6 +58,10 @@
func (p *platformSystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
configuredJars := p.configuredJars(ctx)
classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, p.classpathType)
+ standaloneConfiguredJars := p.standaloneConfiguredJars(ctx)
+ standaloneClasspathJars := configuredJarListToClasspathJars(ctx, standaloneConfiguredJars, STANDALONE_SYSTEMSERVER_JARS)
+ configuredJars = configuredJars.AppendList(standaloneConfiguredJars)
+ classpathJars = append(classpathJars, standaloneClasspathJars...)
p.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars)
}
@@ -66,6 +70,10 @@
return dexpreopt.GetGlobalConfig(ctx).SystemServerJars
}
+func (p *platformSystemServerClasspathModule) standaloneConfiguredJars(ctx android.ModuleContext) android.ConfiguredJarList {
+ return dexpreopt.GetGlobalConfig(ctx).StandaloneSystemServerJars
+}
+
type SystemServerClasspathModule struct {
android.ModuleBase
android.ApexModuleBase
@@ -84,10 +92,15 @@
}
type systemServerClasspathFragmentProperties struct {
- // The contents of this systemserverclasspath_fragment, could be either java_library, or java_sdk_library.
+ // List of system_server classpath jars, could be either java_library, or java_sdk_library.
//
// The order of this list matters as it is the order that is used in the SYSTEMSERVERCLASSPATH.
Contents []string
+
+ // List of jars that system_server loads dynamically using separate classloaders.
+ //
+ // The order does not matter.
+ Standalone_contents []string
}
func systemServerClasspathFactory() android.Module {
@@ -101,12 +114,16 @@
}
func (s *SystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- if len(s.properties.Contents) == 0 {
- ctx.PropertyErrorf("contents", "empty contents are not allowed")
+ if len(s.properties.Contents) == 0 && len(s.properties.Standalone_contents) == 0 {
+ ctx.PropertyErrorf("contents", "Either contents or standalone_contents needs to be non-empty")
}
configuredJars := s.configuredJars(ctx)
classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, s.classpathType)
+ standaloneConfiguredJars := s.standaloneConfiguredJars(ctx)
+ standaloneClasspathJars := configuredJarListToClasspathJars(ctx, standaloneConfiguredJars, STANDALONE_SYSTEMSERVER_JARS)
+ configuredJars = configuredJars.AppendList(standaloneConfiguredJars)
+ classpathJars = append(classpathJars, standaloneClasspathJars...)
s.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars)
// Collect the module directory for IDE info in java/jdeps.go.
@@ -145,6 +162,17 @@
return jars
}
+func (s *SystemServerClasspathModule) standaloneConfiguredJars(ctx android.ModuleContext) android.ConfiguredJarList {
+ global := dexpreopt.GetGlobalConfig(ctx)
+
+ possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, s.properties.Standalone_contents, systemServerClasspathFragmentContentDepTag)
+ jars, _ := global.ApexStandaloneSystemServerJars.Filter(possibleUpdatableModules)
+
+ // TODO(jiakaiz): add a check to ensure that the contents are declared in make.
+
+ return jars
+}
+
type systemServerClasspathFragmentContentDependencyTag struct {
blueprint.BaseDependencyTag
}
@@ -192,8 +220,11 @@
func (s *SystemServerClasspathModule) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
module := ctx.Module()
_, isSourceModule := module.(*SystemServerClasspathModule)
+ var deps []string
+ deps = append(deps, s.properties.Contents...)
+ deps = append(deps, s.properties.Standalone_contents...)
- for _, name := range s.properties.Contents {
+ for _, name := range deps {
// A systemserverclasspath_fragment must depend only on other source modules, while the
// prebuilt_systemserverclasspath_fragment_fragment must only depend on other prebuilt modules.
if !isSourceModule {
@@ -206,6 +237,7 @@
// Collect information for opening IDE project files in java/jdeps.go.
func (s *SystemServerClasspathModule) IDEInfo(dpInfo *android.IdeInfo) {
dpInfo.Deps = append(dpInfo.Deps, s.properties.Contents...)
+ dpInfo.Deps = append(dpInfo.Deps, s.properties.Standalone_contents...)
dpInfo.Paths = append(dpInfo.Paths, s.modulePaths...)
}
@@ -233,14 +265,22 @@
type systemServerClasspathFragmentSdkMemberProperties struct {
android.SdkMemberPropertiesBase
- // Contents of the systemserverclasspath fragment
+ // List of system_server classpath jars, could be either java_library, or java_sdk_library.
+ //
+ // The order of this list matters as it is the order that is used in the SYSTEMSERVERCLASSPATH.
Contents []string
+
+ // List of jars that system_server loads dynamically using separate classloaders.
+ //
+ // The order does not matter.
+ Standalone_contents []string
}
func (s *systemServerClasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
module := variant.(*SystemServerClasspathModule)
s.Contents = module.properties.Contents
+ s.Standalone_contents = module.properties.Standalone_contents
}
func (s *systemServerClasspathFragmentSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
@@ -250,6 +290,10 @@
if len(s.Contents) > 0 {
propertySet.AddPropertyWithTag("contents", s.Contents, requiredMemberDependency)
}
+
+ if len(s.Standalone_contents) > 0 {
+ propertySet.AddPropertyWithTag("standalone_contents", s.Standalone_contents, requiredMemberDependency)
+ }
}
var _ android.SdkMemberType = (*systemServerClasspathFragmentMemberType)(nil)
diff --git a/java/systemserver_classpath_fragment_test.go b/java/systemserver_classpath_fragment_test.go
index 9ad50dd..ba328e7 100644
--- a/java/systemserver_classpath_fragment_test.go
+++ b/java/systemserver_classpath_fragment_test.go
@@ -99,7 +99,7 @@
func TestSystemServerClasspathFragmentWithoutContents(t *testing.T) {
prepareForTestWithSystemServerClasspath.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
- `\Qempty contents are not allowed\E`)).
+ `\QEither contents or standalone_contents needs to be non-empty\E`)).
RunTestWithBp(t, `
systemserverclasspath_fragment {
name: "systemserverclasspath-fragment",
diff --git a/mk2rbc/Android.bp b/mk2rbc/Android.bp
index b18bfc7..4fa3eb6 100644
--- a/mk2rbc/Android.bp
+++ b/mk2rbc/Android.bp
@@ -38,7 +38,6 @@
"soong_variables.go",
"types.go",
"variable.go",
- "version_defaults.go",
],
deps: ["androidmk-parser"],
}
diff --git a/mk2rbc/cmd/mk2rbc.go b/mk2rbc/cmd/mk2rbc.go
index bb5a680..d9b4e86 100644
--- a/mk2rbc/cmd/mk2rbc.go
+++ b/mk2rbc/cmd/mk2rbc.go
@@ -80,7 +80,6 @@
var tracedVariables []string
var errorLogger = errorSink{data: make(map[string]datum)}
var makefileFinder = &LinuxMakefileFinder{}
-var versionDefaultsMk = filepath.Join("build", "make", "core", "version_defaults.mk")
func main() {
flag.Usage = func() {
@@ -168,18 +167,14 @@
if len(files) != 1 {
quit(fmt.Errorf("a launcher can be generated only for a single product"))
}
- versionDefaults, err := generateVersionDefaults()
- if err != nil {
- quit(err)
+ if *inputVariables == "" {
+ quit(fmt.Errorf("the product launcher requires an input variables file"))
}
- versionDefaultsPath := outputFilePath(versionDefaultsMk)
- err = writeGenerated(versionDefaultsPath, versionDefaults)
- if err != nil {
- fmt.Fprintf(os.Stderr, "%s: %s", files[0], err)
- ok = false
+ if !convertOne(*inputVariables) {
+ quit(fmt.Errorf("the product launcher input variables file failed to convert"))
}
- err = writeGenerated(*launcher, mk2rbc.Launcher(outputFilePath(files[0]), versionDefaultsPath,
+ err := writeGenerated(*launcher, mk2rbc.Launcher(outputFilePath(files[0]), outputFilePath(*inputVariables),
mk2rbc.MakePath2ModuleName(files[0])))
if err != nil {
fmt.Fprintf(os.Stderr, "%s: %s", files[0], err)
@@ -213,15 +208,6 @@
}
}
-func generateVersionDefaults() (string, error) {
- versionSettings, err := mk2rbc.ParseVersionDefaults(filepath.Join(*rootDir, versionDefaultsMk))
- if err != nil {
- return "", err
- }
- return mk2rbc.VersionDefaults(versionSettings), nil
-
-}
-
func quit(s interface{}) {
fmt.Fprintln(os.Stderr, s)
os.Exit(2)
diff --git a/mk2rbc/expr.go b/mk2rbc/expr.go
index ec0b279..81b31c7 100644
--- a/mk2rbc/expr.go
+++ b/mk2rbc/expr.go
@@ -85,6 +85,31 @@
s.emit(gctx)
}
+// Boolean literal
+type boolLiteralExpr struct {
+ literal bool
+}
+
+func (b *boolLiteralExpr) eval(_ map[string]starlarkExpr) (res starlarkExpr, same bool) {
+ return b, true
+}
+
+func (b *boolLiteralExpr) emit(gctx *generationContext) {
+ if b.literal {
+ gctx.write("True")
+ } else {
+ gctx.write("False")
+ }
+}
+
+func (_ *boolLiteralExpr) typ() starlarkType {
+ return starlarkTypeBool
+}
+
+func (b *boolLiteralExpr) emitListVarCopy(gctx *generationContext) {
+ b.emit(gctx)
+}
+
// interpolateExpr represents Starlark's interpolation operator <string> % list
// we break <string> into a list of chunks, i.e., "first%second%third" % (X, Y)
// will have chunks = ["first", "second", "third"] and args = [X, Y]
@@ -617,6 +642,55 @@
cx.emit(gctx)
}
+type ifExpr struct {
+ condition starlarkExpr
+ ifTrue starlarkExpr
+ ifFalse starlarkExpr
+}
+
+func (i *ifExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same bool) {
+ cond, condSame := i.condition.eval(valueMap)
+ t, tSame := i.ifTrue.eval(valueMap)
+ f, fSame := i.ifFalse.eval(valueMap)
+ same = condSame && tSame && fSame
+ if same {
+ return i, same
+ } else {
+ return &ifExpr{
+ condition: cond,
+ ifTrue: t,
+ ifFalse: f,
+ }, same
+ }
+}
+
+func (i *ifExpr) emit(gctx *generationContext) {
+ gctx.write("(")
+ i.ifTrue.emit(gctx)
+ gctx.write(" if ")
+ i.condition.emit(gctx)
+ gctx.write(" else ")
+ i.ifFalse.emit(gctx)
+ gctx.write(")")
+}
+
+func (i *ifExpr) typ() starlarkType {
+ tType := i.ifTrue.typ()
+ fType := i.ifFalse.typ()
+ if tType != fType && tType != starlarkTypeUnknown && fType != starlarkTypeUnknown {
+ panic("Conflicting types in if expression")
+ }
+ if tType != starlarkTypeUnknown {
+ return tType
+ } else {
+ return fType
+ }
+}
+
+func (i *ifExpr) emitListVarCopy(gctx *generationContext) {
+ i.emit(gctx)
+}
+
type badExpr struct {
errorLocation ErrorLocation
message string
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 4b9779c..d5ff181 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -112,6 +112,7 @@
"filter-out": {baseName + ".filter_out", starlarkTypeList, hiddenArgNone},
"firstword": {"!firstword", starlarkTypeString, hiddenArgNone},
"get-vendor-board-platforms": {"!get-vendor-board-platforms", starlarkTypeList, hiddenArgNone}, // internal macro, used by is-board-platform, etc.
+ "if": {"!if", starlarkTypeUnknown, hiddenArgNone},
"info": {baseName + ".mkinfo", starlarkTypeVoid, hiddenArgNone},
"is-android-codename": {"!is-android-codename", starlarkTypeBool, hiddenArgNone}, // unused by product config
"is-android-codename-in-list": {"!is-android-codename-in-list", starlarkTypeBool, hiddenArgNone}, // unused by product config
@@ -1111,10 +1112,8 @@
}
switch call.name {
- case "filter":
+ case "filter", "filter-out":
return ctx.parseCompareFilterFuncResult(directive, call, value, isEq), true
- case "filter-out":
- return ctx.parseCompareFilterFuncResult(directive, call, value, !isEq), true
case "wildcard":
return ctx.parseCompareWildcardFuncResult(directive, call, value, !isEq), true
case "findstring":
@@ -1333,6 +1332,34 @@
// TODO (asmundak): if we find many, maybe handle them.
return ctx.newBadExpr(node, "SOONG_CONFIG_ variables cannot be referenced, use soong_config_get instead: %s", refDump)
}
+ // Handle substitution references: https://www.gnu.org/software/make/manual/html_node/Substitution-Refs.html
+ if strings.Contains(refDump, ":") {
+ parts := strings.SplitN(refDump, ":", 2)
+ substParts := strings.SplitN(parts[1], "=", 2)
+ if len(substParts) < 2 || strings.Count(substParts[0], "%") > 1 {
+ return ctx.newBadExpr(node, "Invalid substitution reference")
+ }
+ if !strings.Contains(substParts[0], "%") {
+ if strings.Contains(substParts[1], "%") {
+ return ctx.newBadExpr(node, "A substitution reference must have a %% in the \"before\" part of the substitution if it has one in the \"after\" part.")
+ }
+ substParts[0] = "%" + substParts[0]
+ substParts[1] = "%" + substParts[1]
+ }
+ v := ctx.addVariable(parts[0])
+ if v == nil {
+ return ctx.newBadExpr(node, "unknown variable %s", refDump)
+ }
+ return &callExpr{
+ name: "patsubst",
+ returnType: knownFunctions["patsubst"].returnType,
+ args: []starlarkExpr{
+ &stringLiteralExpr{literal: substParts[0]},
+ &stringLiteralExpr{literal: substParts[1]},
+ &variableRefExpr{v, ctx.lastAssignment(v.name()) != nil},
+ },
+ }
+ }
if v := ctx.addVariable(refDump); v != nil {
return &variableRefExpr{v, ctx.lastAssignment(v.name()) != nil}
}
@@ -1370,6 +1397,8 @@
return ctx.newBadExpr(node, "cannot handle invoking %s", expr.name)
}
switch expr.name {
+ case "if":
+ return ctx.parseIfFunc(node, args)
case "word":
return ctx.parseWordFunc(node, args)
case "firstword", "lastword":
@@ -1425,6 +1454,35 @@
}
}
+func (ctx *parseContext) parseIfFunc(node mkparser.Node, args *mkparser.MakeString) starlarkExpr {
+ words := args.Split(",")
+ if len(words) != 2 && len(words) != 3 {
+ return ctx.newBadExpr(node, "if function should have 2 or 3 arguments, found "+strconv.Itoa(len(words)))
+ }
+ condition := ctx.parseMakeString(node, words[0])
+ ifTrue := ctx.parseMakeString(node, words[1])
+ var ifFalse starlarkExpr
+ if len(words) == 3 {
+ ifFalse = ctx.parseMakeString(node, words[2])
+ } else {
+ switch ifTrue.typ() {
+ case starlarkTypeList:
+ ifFalse = &listExpr{items: []starlarkExpr{}}
+ case starlarkTypeInt:
+ ifFalse = &intLiteralExpr{literal: 0}
+ case starlarkTypeBool:
+ ifFalse = &boolLiteralExpr{literal: false}
+ default:
+ ifFalse = &stringLiteralExpr{literal: ""}
+ }
+ }
+ return &ifExpr{
+ condition,
+ ifTrue,
+ ifFalse,
+ }
+}
+
func (ctx *parseContext) parseWordFunc(node mkparser.Node, args *mkparser.MakeString) starlarkExpr {
words := args.Split(",")
if len(words) != 2 {
@@ -1695,12 +1753,12 @@
return starScript, nil
}
-func Launcher(mainModuleUri, versionDefaultsUri, mainModuleName string) string {
+func Launcher(mainModuleUri, inputVariablesUri, mainModuleName string) string {
var buf bytes.Buffer
fmt.Fprintf(&buf, "load(%q, %q)\n", baseUri, baseName)
- fmt.Fprintf(&buf, "load(%q, \"version_defaults\")\n", versionDefaultsUri)
+ fmt.Fprintf(&buf, "load(%q, input_variables_init = \"init\")\n", inputVariablesUri)
fmt.Fprintf(&buf, "load(%q, \"init\")\n", mainModuleUri)
- fmt.Fprintf(&buf, "%s(%s(%q, init, version_defaults))\n", cfnPrintVars, cfnMain, mainModuleName)
+ fmt.Fprintf(&buf, "%s(%s(%q, init, input_variables_init))\n", cfnPrintVars, cfnMain, mainModuleName)
return buf.String()
}
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index dfdf274..78444c9 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -390,6 +390,8 @@
ifeq (,$(filter barbet coral%,$(TARGET_PRODUCT)))
else ifneq (,$(filter barbet%,$(TARGET_PRODUCT)))
endif
+ifeq (,$(filter-out sunfish_kasan, $(TARGET_PRODUCT)))
+endif
`,
expected: `load("//build/make/core:product_config.rbc", "rblf")
@@ -409,6 +411,8 @@
pass
elif rblf.filter("barbet%", g["TARGET_PRODUCT"]):
pass
+ if not rblf.filter_out("sunfish_kasan", g["TARGET_PRODUCT"]):
+ pass
`,
},
{
@@ -1087,6 +1091,46 @@
pass
`,
},
+ {
+ desc: "if expression",
+ mkname: "product.mk",
+ in: `
+TEST_VAR := foo
+TEST_VAR_LIST := foo
+TEST_VAR_LIST += bar
+TEST_VAR_2 := $(if $(TEST_VAR),bar)
+TEST_VAR_3 := $(if $(TEST_VAR),bar,baz)
+TEST_VAR_3 := $(if $(TEST_VAR),$(TEST_VAR_LIST))
+`,
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ g["TEST_VAR"] = "foo"
+ g["TEST_VAR_LIST"] = ["foo"]
+ g["TEST_VAR_LIST"] += ["bar"]
+ g["TEST_VAR_2"] = ("bar" if g["TEST_VAR"] else "")
+ g["TEST_VAR_3"] = ("bar" if g["TEST_VAR"] else "baz")
+ g["TEST_VAR_3"] = (g["TEST_VAR_LIST"] if g["TEST_VAR"] else [])
+`,
+ },
+ {
+ desc: "substitution references",
+ mkname: "product.mk",
+ in: `
+SOURCES := foo.c bar.c
+OBJECTS := $(SOURCES:.c=.o)
+OBJECTS2 := $(SOURCES:%.c=%.o)
+`,
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ g["SOURCES"] = "foo.c bar.c"
+ g["OBJECTS"] = rblf.mkpatsubst("%.c", "%.o", g["SOURCES"])
+ g["OBJECTS2"] = rblf.mkpatsubst("%.c", "%.o", g["SOURCES"])
+`,
+ },
}
var known_variables = []struct {
diff --git a/mk2rbc/version_defaults.go b/mk2rbc/version_defaults.go
deleted file mode 100644
index 64645d7..0000000
--- a/mk2rbc/version_defaults.go
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2021 Google LLC
-//
-// 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 mk2rbc
-
-import (
- "bytes"
- "fmt"
- "io/ioutil"
- "os"
- "sort"
- "strconv"
- "strings"
-
- mkparser "android/soong/androidmk/parser"
-)
-
-const codenamePrefix = "PLATFORM_VERSION_CODENAME."
-
-// ParseVersionDefaults extracts version settings from the given file
-// and returns the map.
-func ParseVersionDefaults(path string) (map[string]string, error) {
- contents, err := ioutil.ReadFile(path)
- if err != nil {
- return nil, err
- }
- parser := mkparser.NewParser(path, bytes.NewBuffer(contents))
- nodes, errs := parser.Parse()
- if len(errs) > 0 {
- for _, e := range errs {
- fmt.Fprintln(os.Stderr, "ERROR:", e)
- }
- return nil, fmt.Errorf("cannot parse %s", path)
- }
-
- result := map[string]string{
- "DEFAULT_PLATFORM_VERSION": "",
- "MAX_PLATFORM_VERSION": "",
- "MIN_PLATFORM_VERSION": "A",
- "PLATFORM_BASE_SDK_EXTENSION_VERSION": "",
- "PLATFORM_SDK_EXTENSION_VERSION": "",
- "PLATFORM_SDK_VERSION": "",
- "PLATFORM_SECURITY_PATCH": "",
- "PLATFORM_VERSION_LAST_STABLE": "",
- }
- for _, node := range nodes {
- asgn, ok := node.(*mkparser.Assignment)
- if !(ok && asgn.Name.Const()) {
- continue
- }
- s := asgn.Name.Strings[0]
- _, ok = result[s]
- if !ok {
- ok = strings.HasPrefix(s, codenamePrefix)
- }
- if !ok {
- continue
- }
- v := asgn.Value
- if !v.Const() {
- return nil, fmt.Errorf("the value of %s should be constant", s)
- }
- result[s] = strings.TrimSpace(v.Strings[0])
- }
- return result, nil
-}
-
-func genericValue(s string) interface{} {
- if ival, err := strconv.ParseInt(s, 0, 0); err == nil {
- return ival
- }
- return s
-}
-
-// VersionDefaults generates the contents of the version_defaults.rbc file
-func VersionDefaults(values map[string]string) string {
- var sink bytes.Buffer
- var lines []string
- var codenames []string
- for name, value := range values {
- if strings.HasPrefix(name, codenamePrefix) {
- codenames = append(codenames,
- fmt.Sprintf("%q: %q", strings.TrimPrefix(name, codenamePrefix), value))
- } else {
- // Print numbers as such
- lines = append(lines, fmt.Sprintf(" %s = %#v,\n",
- strings.ToLower(name), genericValue(value)))
- }
- }
-
- sort.Strings(lines)
- sort.Strings(codenames)
-
- sink.WriteString("version_defaults = struct(\n")
- for _, l := range lines {
- sink.WriteString(l)
- }
- sink.WriteString(" codenames = { ")
- sink.WriteString(strings.Join(codenames, ", "))
- sink.WriteString(" }\n)\n")
- return sink.String()
-}
diff --git a/mk2rbc/version_defaults_test.go b/mk2rbc/version_defaults_test.go
deleted file mode 100644
index c78fa32..0000000
--- a/mk2rbc/version_defaults_test.go
+++ /dev/null
@@ -1,60 +0,0 @@
-package mk2rbc
-
-import (
- "path/filepath"
- "reflect"
- "strings"
- "testing"
-)
-
-func TestParseVersionDefaults(t *testing.T) {
- testDir := getTestDirectory()
- abspath := func(relPath string) string { return filepath.Join(testDir, relPath) }
- actualProducts, err := ParseVersionDefaults(abspath("version_defaults.mk.test"))
- if err != nil {
- t.Fatal(err)
- }
- expectedProducts := map[string]string{
- "DEFAULT_PLATFORM_VERSION": "TP1A",
- "MAX_PLATFORM_VERSION": "TP1A",
- "MIN_PLATFORM_VERSION": "TP1A",
- "PLATFORM_BASE_SDK_EXTENSION_VERSION": "0",
- "PLATFORM_SDK_EXTENSION_VERSION": "1",
- "PLATFORM_SDK_VERSION": "31",
- "PLATFORM_SECURITY_PATCH": "2021-10-05",
- "PLATFORM_VERSION_LAST_STABLE": "12",
- "PLATFORM_VERSION_CODENAME.SP2A": "Sv2",
- "PLATFORM_VERSION_CODENAME.TP1A": "Tiramisu",
- }
- if !reflect.DeepEqual(actualProducts, expectedProducts) {
- t.Errorf("\nExpected: %v\n Actual: %v", expectedProducts, actualProducts)
- }
-}
-
-func TestVersionDefaults(t *testing.T) {
- testDir := getTestDirectory()
- abspath := func(relPath string) string { return filepath.Join(testDir, relPath) }
- actualProducts, err := ParseVersionDefaults(abspath("version_defaults.mk.test"))
- if err != nil {
- t.Fatal(err)
- }
- expectedString := `version_defaults = struct(
- default_platform_version = "TP1A",
- max_platform_version = "TP1A",
- min_platform_version = "TP1A",
- platform_base_sdk_extension_version = 0,
- platform_sdk_extension_version = 1,
- platform_sdk_version = 31,
- platform_security_patch = "2021-10-05",
- platform_version_last_stable = 12,
- codenames = { "SP2A": "Sv2", "TP1A": "Tiramisu" }
-)
-`
- actualString := VersionDefaults(actualProducts)
- if !reflect.DeepEqual(actualString, expectedString) {
- t.Errorf("\nExpected: %v\nActual:\n%v",
- strings.ReplaceAll(expectedString, "\n", "\n"),
- strings.ReplaceAll(actualString, "\n", "\n"))
- }
-
-}
diff --git a/python/androidmk.go b/python/androidmk.go
index 13b4172..ccc85ec 100644
--- a/python/androidmk.go
+++ b/python/androidmk.go
@@ -75,12 +75,6 @@
}
func (installer *pythonInstaller) AndroidMk(base *Module, entries *android.AndroidMkEntries) {
- // Soong installation is only supported for host modules. Have Make
- // installation trigger Soong installation.
- if base.Target().Os.Class == android.Host {
- entries.OutputFile = android.OptionalPathForPath(installer.path)
- }
-
entries.Required = append(entries.Required, "libc++")
entries.ExtraEntries = append(entries.ExtraEntries,
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
diff --git a/python/binary.go b/python/binary.go
index bf6167c..99c6259 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -27,7 +27,6 @@
func init() {
registerPythonBinaryComponents(android.InitRegistrationContext)
- android.RegisterBp2BuildMutator("python_binary_host", PythonBinaryBp2Build)
}
func registerPythonBinaryComponents(ctx android.RegistrationContext) {
@@ -35,29 +34,19 @@
}
type bazelPythonBinaryAttributes struct {
- Main string
+ Main *string
Srcs bazel.LabelListAttribute
Deps bazel.LabelListAttribute
- Python_version string
+ Python_version *string
}
-func PythonBinaryBp2Build(ctx android.TopDownMutatorContext) {
- m, ok := ctx.Module().(*Module)
- if !ok || !m.ConvertWithBp2build(ctx) {
- return
- }
-
- // a Module can be something other than a python_binary_host
- if ctx.ModuleType() != "python_binary_host" {
- return
- }
-
- var main string
+func pythonBinaryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
+ var main *string
for _, propIntf := range m.GetProperties() {
if props, ok := propIntf.(*BinaryProperties); ok {
// main is optional.
if props.Main != nil {
- main = *props.Main
+ main = props.Main
break
}
}
@@ -69,13 +58,13 @@
// under Bionic.
py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, false)
py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
- var python_version string
+ var python_version *string
if py3Enabled && py2Enabled {
panic(fmt.Errorf(
"error for '%s' module: bp2build's python_binary_host converter does not support "+
"converting a module that is enabled for both Python 2 and 3 at the same time.", m.Name()))
} else if py2Enabled {
- python_version = "PY2"
+ python_version = &pyVersion2
} else {
// do nothing, since python_version defaults to PY3.
}
diff --git a/python/library.go b/python/library.go
index d136a4e..d026c13 100644
--- a/python/library.go
+++ b/python/library.go
@@ -17,17 +17,14 @@
// This file contains the module types for building Python library.
import (
- "fmt"
-
"android/soong/android"
"android/soong/bazel"
+
"github.com/google/blueprint/proptools"
)
func init() {
registerPythonLibraryComponents(android.InitRegistrationContext)
- android.RegisterBp2BuildMutator("python_library_host", PythonLibraryHostBp2Build)
- android.RegisterBp2BuildMutator("python_library", PythonLibraryBp2Build)
}
func registerPythonLibraryComponents(ctx android.RegistrationContext) {
@@ -46,43 +43,23 @@
type bazelPythonLibraryAttributes struct {
Srcs bazel.LabelListAttribute
Deps bazel.LabelListAttribute
- Srcs_version string
+ Srcs_version *string
}
-func PythonLibraryHostBp2Build(ctx android.TopDownMutatorContext) {
- pythonLibBp2Build(ctx, "python_library_host")
-}
-
-func PythonLibraryBp2Build(ctx android.TopDownMutatorContext) {
- pythonLibBp2Build(ctx, "python_library")
-}
-
-func pythonLibBp2Build(ctx android.TopDownMutatorContext, modType string) {
- m, ok := ctx.Module().(*Module)
- if !ok || !m.ConvertWithBp2build(ctx) {
- return
- }
-
- // a Module can be something other than a `modType`
- if ctx.ModuleType() != modType {
- return
- }
-
+func pythonLibBp2Build(ctx android.TopDownMutatorContext, m *Module) {
// TODO(b/182306917): this doesn't fully handle all nested props versioned
// by the python version, which would have been handled by the version split
// mutator. This is sufficient for very simple python_library modules under
// Bionic.
py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, true)
py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
- var python_version string
+ var python_version *string
if py2Enabled && !py3Enabled {
- python_version = "PY2"
+ python_version = &pyVersion2
} else if !py2Enabled && py3Enabled {
- python_version = "PY3"
+ python_version = &pyVersion3
} else if !py2Enabled && !py3Enabled {
- panic(fmt.Errorf(
- "error for '%s' module: bp2build's %s converter doesn't understand having "+
- "neither py2 nor py3 enabled", m.Name(), modType))
+ ctx.ModuleErrorf("bp2build converter doesn't understand having neither py2 nor py3 enabled")
} else {
// do nothing, since python_version defaults to PY2ANDPY3
}
@@ -95,8 +72,8 @@
}
props := bazel.BazelTargetModuleProperties{
- // Use the native py_library rule.
- Rule_class: "py_library",
+ Rule_class: "py_library",
+ Bzl_load_location: "//build/bazel/rules/python:library.bzl",
}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{
diff --git a/python/python.go b/python/python.go
index 401d91f..734ac57 100644
--- a/python/python.go
+++ b/python/python.go
@@ -23,6 +23,7 @@
"strings"
"android/soong/bazel"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -667,18 +668,25 @@
}
// isPythonLibModule returns whether the given module is a Python library Module or not
-// This is distinguished by the fact that Python libraries are not installable, while other Python
-// modules are.
func isPythonLibModule(module blueprint.Module) bool {
if m, ok := module.(*Module); ok {
- // Python library has no bootstrapper or installer
- if m.bootstrapper == nil && m.installer == nil {
- return true
- }
+ return m.isLibrary()
}
return false
}
+// This is distinguished by the fact that Python libraries are not installable, while other Python
+// modules are.
+func (p *Module) isLibrary() bool {
+ // Python library has no bootstrapper or installer
+ return p.bootstrapper == nil && p.installer == nil
+}
+
+func (p *Module) isBinary() bool {
+ _, ok := p.bootstrapper.(*binaryDecorator)
+ return ok
+}
+
// collectPathsFromTransitiveDeps checks for source/data files for duplicate paths
// for module and its transitive dependencies and collects list of data/source file
// zips for transitive dependencies.
@@ -752,6 +760,14 @@
return true
}
+func (p *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ if p.isLibrary() {
+ pythonLibBp2Build(ctx, p)
+ } else if p.isBinary() {
+ pythonBinaryBp2Build(ctx, p)
+ }
+}
+
var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault
var String = proptools.String
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 32d02e4..5e1b4b7 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -30,7 +30,7 @@
defaultBindgenFlags = []string{""}
// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
- bindgenClangVersion = "clang-r433403"
+ bindgenClangVersion = "clang-r437112"
_ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
diff --git a/rust/builder.go b/rust/builder.go
index 60b5926..a7efc28 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -216,6 +216,13 @@
// Suppress an implicit sysroot
rustcFlags = append(rustcFlags, "--sysroot=/dev/null")
+ // Enable incremental compilation if requested by user
+ if ctx.Config().IsEnvTrue("SOONG_RUSTC_INCREMENTAL") {
+ incrementalPath := android.PathForOutput(ctx, "rustc").String()
+
+ rustcFlags = append(rustcFlags, "-C incremental="+incrementalPath)
+ }
+
// Collect linker flags
linkFlags = append(linkFlags, flags.GlobalLinkFlags...)
linkFlags = append(linkFlags, flags.LinkFlags...)
diff --git a/rust/config/global.go b/rust/config/global.go
index d3826ac..bfb2d1f 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,9 +24,9 @@
var pctx = android.NewPackageContext("android/soong/rust/config")
var (
- RustDefaultVersion = "1.56.1p1"
+ RustDefaultVersion = "1.57.0"
RustDefaultBase = "prebuilts/rust/"
- DefaultEdition = "2018"
+ DefaultEdition = "2021"
Stdlibs = []string{
"libstd",
}
@@ -41,12 +41,13 @@
}
GlobalRustFlags = []string{
- "--remap-path-prefix $$(pwd)=",
+ "-Z remap-cwd-prefix=.",
"-C codegen-units=1",
"-C debuginfo=2",
"-C opt-level=3",
"-C relocation-model=pic",
"-C overflow-checks=on",
+ "-C force-unwind-tables=yes",
// Use v0 mangling to distinguish from C++ symbols
"-Z symbol-mangling-version=v0",
}
@@ -54,6 +55,8 @@
deviceGlobalRustFlags = []string{
"-C panic=abort",
"-Z link-native-libraries=no",
+ // Generate additional debug info for AutoFDO
+ "-Z debug-info-for-profiling",
}
deviceGlobalLinkFlags = []string{
diff --git a/rust/project_json.go b/rust/project_json.go
index ae48312..fe259d6 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -211,6 +211,8 @@
comp = c.binaryDecorator.baseCompiler
case *procMacroDecorator:
comp = c.baseCompiler
+ case *toolchainLibraryDecorator:
+ comp = c.baseCompiler
default:
return nil, nil, false
}
diff --git a/rust/rust.go b/rust/rust.go
index b575c7a..300c0f5 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -969,6 +969,7 @@
name string
library bool
procMacro bool
+ dynamic bool
}
// InstallDepNeeded returns true for rlibs, dylibs, and proc macros so that they or their transitive
@@ -979,10 +980,19 @@
var _ android.InstallNeededDependencyTag = dependencyTag{}
+func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
+ if d.library && d.dynamic {
+ return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency}
+ }
+ return nil
+}
+
+var _ android.LicenseAnnotationsDependencyTag = dependencyTag{}
+
var (
customBindgenDepTag = dependencyTag{name: "customBindgenTag"}
rlibDepTag = dependencyTag{name: "rlibTag", library: true}
- dylibDepTag = dependencyTag{name: "dylib", library: true}
+ dylibDepTag = dependencyTag{name: "dylib", library: true, dynamic: true}
procMacroDepTag = dependencyTag{name: "procMacro", procMacro: true}
testPerSrcDepTag = dependencyTag{name: "rust_unit_tests"}
sourceDepTag = dependencyTag{name: "source"}
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 730d756..4c847a1 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -47,15 +47,6 @@
srcs: [
"manifest.py",
],
- version: {
- py2: {
- // TODO(b/203436762) Remove when system/apex/apexer/apexer.py is converted
- enabled: true,
- },
- py3: {
- enabled: true,
- },
- },
visibility: ["//system/apex/apexer:__pkg__"],
}
diff --git a/scripts/check_boot_jars/package_allowed_list.txt b/scripts/check_boot_jars/package_allowed_list.txt
index ed63651..a02c195 100644
--- a/scripts/check_boot_jars/package_allowed_list.txt
+++ b/scripts/check_boot_jars/package_allowed_list.txt
@@ -72,6 +72,7 @@
jdk\.internal
jdk\.internal\.math
jdk\.internal\.misc
+jdk\.internal\.ref
jdk\.internal\.reflect
jdk\.internal\.util
jdk\.internal\.vm\.annotation
diff --git a/scripts/gen_java_usedby_apex.sh b/scripts/gen_java_usedby_apex.sh
index 251d7aa..e398541 100755
--- a/scripts/gen_java_usedby_apex.sh
+++ b/scripts/gen_java_usedby_apex.sh
@@ -30,9 +30,11 @@
shift
rm -f "$out"
touch "$out"
+ echo "<externals>" >> "$out"
for x in "$@"; do
- "$dexdeps" "$x" >> "$out" || true
+ "$dexdeps" "$x" >> "$out" || echo "</external>" >> "$out"
done
+ echo "</externals>" >> "$out"
}
if [[ "$1" == "help" ]]
diff --git a/scripts/rbc-run b/scripts/rbc-run
index 235da75..7243421 100755
--- a/scripts/rbc-run
+++ b/scripts/rbc-run
@@ -2,7 +2,7 @@
# Convert and run one configuration
# Args: a product/board makefile optionally followed by additional arguments
# that will be passed to rbcrun.
-[[ $# -gt 0 && -f "$1" ]] || { echo "Usage: ${0##*/} product.mk [Additional rbcrun arguments]" >&2; exit 1; }
+[[ $# -gt 1 && -f "$1" && -f "$2" ]] || { echo "Usage: ${0##*/} product.mk input_variables.mk [Additional rbcrun arguments]" >&2; exit 1; }
set -eu
declare -r output_root="${OUT_DIR:-out}"
@@ -10,7 +10,8 @@
declare -r converter="${output_root}/soong/mk2rbc"
declare -r launcher="${output_root}/rbc/launcher.rbc"
declare -r makefile="$1"
-shift
-"${converter}" -mode=write -r --outdir "${output_root}/rbc" --launcher="${launcher}" "${makefile}"
+declare -r input_variables="$2"
+shift 2
+"${converter}" -mode=write -r --outdir "${output_root}/rbc" --input_variables "${input_variables}" --launcher="${launcher}" "${makefile}"
"${runner}" RBC_OUT="make,global" RBC_DEBUG="${RBC_DEBUG:-}" $@ "${launcher}"
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index ff2af43..2dacdb5 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -40,6 +40,7 @@
}
`, apex, fragment)),
android.FixtureAddFile("frameworks/base/config/boot-profile.txt", nil),
+ android.FixtureAddFile("frameworks/base/config/boot-image-profile.txt", nil),
android.FixtureAddFile("build/soong/scripts/check_boot_jars/package_allowed_list.txt", nil),
)
}
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index c32cde0..2d98e8b 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -42,8 +42,6 @@
pctx.Import("android/soong/android")
registerShBuildComponents(android.InitRegistrationContext)
-
- android.RegisterBp2BuildMutator("sh_binary", ShBinaryBp2Build)
}
func registerShBuildComponents(ctx android.RegistrationContext) {
@@ -516,7 +514,9 @@
}
type bazelShBinaryAttributes struct {
- Srcs bazel.LabelListAttribute
+ Srcs bazel.LabelListAttribute
+ Filename string
+ Sub_dir string
// Bazel also supports the attributes below, but (so far) these are not required for Bionic
// deps
// data
@@ -538,21 +538,29 @@
// visibility
}
-func ShBinaryBp2Build(ctx android.TopDownMutatorContext) {
- m, ok := ctx.Module().(*ShBinary)
- if !ok || !m.ConvertWithBp2build(ctx) {
- return
- }
-
+func (m *ShBinary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
srcs := bazel.MakeLabelListAttribute(
android.BazelLabelForModuleSrc(ctx, []string{*m.properties.Src}))
+ var filename string
+ if m.properties.Filename != nil {
+ filename = *m.properties.Filename
+ }
+
+ var subDir string
+ if m.properties.Sub_dir != nil {
+ subDir = *m.properties.Sub_dir
+ }
+
attrs := &bazelShBinaryAttributes{
- Srcs: srcs,
+ Srcs: srcs,
+ Filename: filename,
+ Sub_dir: subDir,
}
props := bazel.BazelTargetModuleProperties{
- Rule_class: "sh_binary",
+ Rule_class: "sh_binary",
+ Bzl_load_location: "//build/bazel/rules:sh_binary.bzl",
}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
diff --git a/shared/Android.bp b/shared/Android.bp
index deb17f8..3c84f55 100644
--- a/shared/Android.bp
+++ b/shared/Android.bp
@@ -9,11 +9,13 @@
"env.go",
"paths.go",
"debug.go",
+ "proto.go",
],
testSrcs: [
"paths_test.go",
],
deps: [
"soong-bazel",
+ "golang-protobuf-proto",
],
}
diff --git a/shared/proto.go b/shared/proto.go
new file mode 100644
index 0000000..232656b
--- /dev/null
+++ b/shared/proto.go
@@ -0,0 +1,41 @@
+// 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 shared
+
+import (
+ "io/ioutil"
+ "os"
+
+ "google.golang.org/protobuf/proto"
+)
+
+// Save takes a protobuf message, marshals to an array of bytes
+// and is then saved to a file.
+func Save(pb proto.Message, filepath string) (err error) {
+ data, err := proto.Marshal(pb)
+ if err != nil {
+ return err
+ }
+ tempFilepath := filepath + ".tmp"
+ if err := ioutil.WriteFile(tempFilepath, []byte(data), 0644 /* rw-r--r-- */); err != nil {
+ return err
+ }
+
+ if err := os.Rename(tempFilepath, filepath); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/tests/androidmk_test.sh b/tests/androidmk_test.sh
new file mode 100755
index 0000000..331dc77
--- /dev/null
+++ b/tests/androidmk_test.sh
@@ -0,0 +1,135 @@
+#!/bin/bash -eu
+
+set -o pipefail
+
+# How to run: bash path-to-script/androidmk_test.sh
+# Tests of converting license functionality of the androidmk tool
+REAL_TOP="$(readlink -f "$(dirname "$0")"/../../..)"
+$REAL_TOP/build/soong/soong_ui.bash --make-mode androidmk
+
+source "$(dirname "$0")/lib.sh"
+
+# Expect to create a new license module
+function test_rewrite_license_property_inside_current_directory {
+ setup
+
+ # Create an Android.mk file
+ mkdir -p a/b
+ cat > a/b/Android.mk <<'EOF'
+include $(CLEAR_VARS)
+LOCAL_MODULE := foo
+LOCAL_LICENSE_KINDS := license_kind1 license_kind2
+LOCAL_LICENSE_CONDITIONS := license_condition
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/license_notice1 $(LOCAL_PATH)/license_notice2
+include $(BUILD_PACKAGE)
+EOF
+
+ # Create an expected Android.bp file for the module "foo"
+ cat > a/b/Android.bp <<'EOF'
+package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "a_b_license",
+ ],
+}
+
+license {
+ name: "a_b_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "license_kind1",
+ "license_kind2",
+ ],
+ license_text: [
+ "license_notice1",
+ "license_notice2",
+ ],
+}
+
+android_app {
+ name: "foo",
+}
+EOF
+
+ run_androidmk_test "a/b/Android.mk" "a/b/Android.bp"
+}
+
+# Expect to reference to an existing license module
+function test_rewrite_license_property_outside_current_directory {
+ setup
+
+ # Create an Android.mk file
+ mkdir -p a/b/c/d
+ cat > a/b/c/d/Android.mk <<'EOF'
+include $(CLEAR_VARS)
+LOCAL_MODULE := foo
+LOCAL_LICENSE_KINDS := license_kind1 license_kind2
+LOCAL_LICENSE_CONDITIONS := license_condition
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../license_notice1 $(LOCAL_PATH)/../../license_notice2
+include $(BUILD_PACKAGE)
+EOF
+
+ # Create an expected (input) Android.bp file at a/b/
+ cat > a/b/Android.bp <<'EOF'
+package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "a_b_license",
+ ],
+}
+
+license {
+ name: "a_b_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "license_kind1",
+ "license_kind2",
+ ],
+ license_text: [
+ "license_notice1",
+ "license_notice2",
+ ],
+}
+
+android_app {
+ name: "bar",
+}
+EOF
+
+ # Create an expected (output) Android.bp file for the module "foo"
+ cat > a/b/c/d/Android.bp <<'EOF'
+package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "a_b_license",
+ ],
+}
+
+android_app {
+ name: "foo",
+}
+EOF
+
+ run_androidmk_test "a/b/c/d/Android.mk" "a/b/c/d/Android.bp"
+}
+
+run_androidmk_test () {
+ export ANDROID_BUILD_TOP="$MOCK_TOP"
+
+ local out=$($REAL_TOP/*/host/*/bin/androidmk "$1")
+ local expected=$(<"$2")
+
+ if [[ "$out" != "$expected" ]]; then
+ ANDROID_BUILD_TOP="$REAL_TOP"
+ cleanup_mock_top
+ fail "The output is not the same as the expected"
+ fi
+
+ ANDROID_BUILD_TOP="$REAL_TOP"
+ cleanup_mock_top
+ echo "Succeeded"
+}
+
+test_rewrite_license_property_inside_current_directory
+
+test_rewrite_license_property_outside_current_directory
diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh
index a376e06..76a918b 100755
--- a/tests/run_integration_tests.sh
+++ b/tests/run_integration_tests.sh
@@ -3,8 +3,9 @@
set -o pipefail
TOP="$(readlink -f "$(dirname "$0")"/../../..)"
+"$TOP/build/soong/tests/androidmk_test.sh"
"$TOP/build/soong/tests/bootstrap_test.sh"
"$TOP/build/soong/tests/mixed_mode_test.sh"
"$TOP/build/soong/tests/bp2build_bazel_test.sh"
"$TOP/build/soong/tests/soong_test.sh"
-"$TOP/build/bazel/ci/rbc_product_config.sh" aosp_arm64-userdebug
+"$TOP/build/bazel/ci/rbc_regression_test.sh" aosp_arm64-userdebug
diff --git a/ui/build/config.go b/ui/build/config.go
index c306633..4c26d3e 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -1255,16 +1255,22 @@
return c.metricsUploader
}
-// LogsDir returns the logs directory where build log and metrics
-// files are located. By default, the logs directory is the out
+// LogsDir returns the absolute path to the logs directory where build log and
+// metrics files are located. By default, the logs directory is the out
// directory. If the argument dist is specified, the logs directory
// is <dist_dir>/logs.
func (c *configImpl) LogsDir() string {
+ dir := c.OutDir()
if c.Dist() {
// Always write logs to the real dist dir, even if Bazel is using a rigged dist dir for other files
- return filepath.Join(c.RealDistDir(), "logs")
+ dir = filepath.Join(c.RealDistDir(), "logs")
}
- return c.OutDir()
+ absDir, err := filepath.Abs(dir)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "\nError making log dir '%s' absolute: %s\n", dir, err.Error())
+ os.Exit(1)
+ }
+ return absDir
}
// BazelMetricsDir returns the <logs dir>/bazel_metrics directory
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 4ced722..5360342 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -153,7 +153,12 @@
return true, nil
}
-func primaryBuilderInvocation(config Config, name string, output string, specificArgs []string) bootstrap.PrimaryBuilderInvocation {
+func primaryBuilderInvocation(
+ config Config,
+ name string,
+ output string,
+ specificArgs []string,
+ description string) bootstrap.PrimaryBuilderInvocation {
commonArgs := make([]string, 0, 0)
if !config.skipSoongTests {
@@ -178,9 +183,10 @@
allArgs = append(allArgs, "Android.bp")
return bootstrap.PrimaryBuilderInvocation{
- Inputs: []string{"Android.bp"},
- Outputs: []string{output},
- Args: allArgs,
+ Inputs: []string{"Android.bp"},
+ Outputs: []string{output},
+ Args: allArgs,
+ Description: description,
}
}
@@ -232,7 +238,9 @@
config,
soongBuildTag,
config.SoongNinjaFile(),
- mainSoongBuildExtraArgs)
+ mainSoongBuildExtraArgs,
+ fmt.Sprintf("analyzing Android.bp files and generating ninja file at %s", config.SoongNinjaFile()),
+ )
if config.bazelBuildMode() == mixedBuild {
// Mixed builds call Bazel from soong_build and they therefore need the
@@ -248,7 +256,9 @@
config.Bp2BuildMarkerFile(),
[]string{
"--bp2build_marker", config.Bp2BuildMarkerFile(),
- })
+ },
+ fmt.Sprintf("converting Android.bp files to BUILD files at %s/bp2build", config.SoongOutDir()),
+ )
jsonModuleGraphInvocation := primaryBuilderInvocation(
config,
@@ -256,15 +266,20 @@
config.ModuleGraphFile(),
[]string{
"--module_graph_file", config.ModuleGraphFile(),
- })
+ },
+ fmt.Sprintf("generating the Soong module graph at %s", config.ModuleGraphFile()),
+ )
+ queryviewDir := filepath.Join(config.SoongOutDir(), "queryview")
queryviewInvocation := primaryBuilderInvocation(
config,
queryviewTag,
config.QueryviewMarkerFile(),
[]string{
- "--bazel_queryview_dir", filepath.Join(config.SoongOutDir(), "queryview"),
- })
+ "--bazel_queryview_dir", queryviewDir,
+ },
+ fmt.Sprintf("generating the Soong module graph as a Bazel workspace at %s", queryviewDir),
+ )
soongDocsInvocation := primaryBuilderInvocation(
config,
@@ -272,7 +287,9 @@
config.SoongDocsHtml(),
[]string{
"--soong_docs", config.SoongDocsHtml(),
- })
+ },
+ fmt.Sprintf("generating Soong docs at %s", config.SoongDocsHtml()),
+ )
globFiles := []string{
config.NamedGlobFile(soongBuildTag),
@@ -356,6 +373,7 @@
soongBuildEnv.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output"))
soongBuildEnv.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
soongBuildEnv.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
+ soongBuildEnv.Set("LOG_DIR", config.LogsDir())
// For Soong bootstrapping tests
if os.Getenv("ALLOW_MISSING_DEPENDENCIES") == "true" {
diff --git a/ui/metrics/Android.bp b/ui/metrics/Android.bp
index 96f6389..3ba3907 100644
--- a/ui/metrics/Android.bp
+++ b/ui/metrics/Android.bp
@@ -25,6 +25,7 @@
"soong-ui-metrics_proto",
"soong-ui-bp2build_metrics_proto",
"soong-ui-tracer",
+ "soong-shared",
],
srcs: [
"metrics.go",
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index f1bb862..80f8c1a 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -32,12 +32,12 @@
// of what an event is and how the metrics system is a stack based system.
import (
- "io/ioutil"
"os"
"runtime"
"strings"
"time"
+ "android/soong/shared"
"google.golang.org/protobuf/proto"
soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
@@ -196,7 +196,7 @@
}
m.metrics.HostOs = proto.String(runtime.GOOS)
- return save(&m.metrics, out)
+ return shared.Save(&m.metrics, out)
}
// SetSoongBuildMetrics sets the metrics collected from the soong_build
@@ -228,25 +228,5 @@
// Dump saves the collected CUJs metrics to the raw protobuf file.
func (c *CriticalUserJourneysMetrics) Dump(filename string) (err error) {
- return save(&c.cujs, filename)
-}
-
-// save takes a protobuf message, marshals to an array of bytes
-// and is then saved to a file.
-func save(pb proto.Message, filename string) (err error) {
- data, err := proto.Marshal(pb)
- if err != nil {
- return err
- }
-
- tempFilename := filename + ".tmp"
- if err := ioutil.WriteFile(tempFilename, []byte(data), 0644 /* rw-r--r-- */); err != nil {
- return err
- }
-
- if err := os.Rename(tempFilename, filename); err != nil {
- return err
- }
-
- return nil
+ return shared.Save(&c.cujs, filename)
}
diff --git a/ui/terminal/simple_status.go b/ui/terminal/simple_status.go
index 936b275..3157813 100644
--- a/ui/terminal/simple_status.go
+++ b/ui/terminal/simple_status.go
@@ -22,32 +22,41 @@
)
type simpleStatusOutput struct {
- writer io.Writer
- formatter formatter
- keepANSI bool
+ writer io.Writer
+ formatter formatter
+ keepANSI bool
+ outputLevel status.MsgLevel
}
// NewSimpleStatusOutput returns a StatusOutput that represents the
// current build status similarly to Ninja's built-in terminal
// output.
-func NewSimpleStatusOutput(w io.Writer, formatter formatter, keepANSI bool) status.StatusOutput {
+func NewSimpleStatusOutput(w io.Writer, formatter formatter, keepANSI bool, quietBuild bool) status.StatusOutput {
+ level := status.StatusLvl
+ if quietBuild {
+ level = status.PrintLvl
+ }
return &simpleStatusOutput{
- writer: w,
- formatter: formatter,
- keepANSI: keepANSI,
+ writer: w,
+ formatter: formatter,
+ keepANSI: keepANSI,
+ outputLevel: level,
}
}
func (s *simpleStatusOutput) Message(level status.MsgLevel, message string) {
- if level >= status.StatusLvl {
+ if level >= s.outputLevel {
fmt.Fprintln(s.writer, s.formatter.message(level, message))
}
}
-func (s *simpleStatusOutput) StartAction(action *status.Action, counts status.Counts) {
+func (s *simpleStatusOutput) StartAction(_ *status.Action, _ status.Counts) {
}
func (s *simpleStatusOutput) FinishAction(result status.ActionResult, counts status.Counts) {
+ if s.outputLevel > status.StatusLvl {
+ return
+ }
str := result.Description
if str == "" {
str = result.Command
diff --git a/ui/terminal/status.go b/ui/terminal/status.go
index 2ad174f..ff0af47 100644
--- a/ui/terminal/status.go
+++ b/ui/terminal/status.go
@@ -29,9 +29,9 @@
func NewStatusOutput(w io.Writer, statusFormat string, forceSimpleOutput, quietBuild, forceKeepANSI bool) status.StatusOutput {
formatter := newFormatter(statusFormat, quietBuild)
- if !forceSimpleOutput && isSmartTerminal(w) {
- return NewSmartStatusOutput(w, formatter)
+ if forceSimpleOutput || quietBuild || !isSmartTerminal(w) {
+ return NewSimpleStatusOutput(w, formatter, forceKeepANSI, quietBuild)
} else {
- return NewSimpleStatusOutput(w, formatter, forceKeepANSI)
+ return NewSmartStatusOutput(w, formatter)
}
}