Merge "Revert "Respect Clang version override env vars.""
diff --git a/OWNERS b/OWNERS
index 964e27a..0234f27 100644
--- a/OWNERS
+++ b/OWNERS
@@ -3,7 +3,6 @@
# AMER
agespino@google.com
-alexmarquez@google.com
ccross@android.com
colefaust@google.com
cparsons@google.com
diff --git a/README.md b/README.md
index 7f18463..70311cb 100644
--- a/README.md
+++ b/README.md
@@ -105,31 +105,35 @@
### Types
-Variables and properties are strongly typed, variables dynamically based on the
-first assignment, and properties statically by the module type. The supported
-types are:
+Variables and properties are strongly typed. Variables are dynamically typed
+based on the first assignment, and properties are statically typed by the
+module type. The supported types are:
* Bool (`true` or `false`)
* Integers (`int`)
* Strings (`"string"`)
* Lists of strings (`["string1", "string2"]`)
* Maps (`{key1: "value1", key2: ["value2"]}`)
-Maps may values of any type, including nested maps. Lists and maps may have
-trailing commas after the last value.
+Maps may contain values of any type, including nested maps. Lists and maps may
+have trailing commas after the last value.
Strings can contain double quotes using `\"`, for example `"cat \"a b\""`.
### Operators
-Strings, lists of strings, and maps can be appended using the `+` operator.
-Integers can be summed up using the `+` operator. Appending a map produces the
-union of keys in both maps, appending the values of any keys that are present
-in both maps.
+The `+` operator:
+* Sums integers.
+* Concatenates strings and lists.
+* Produces the union of maps.
+
+Concatenating maps produces a map whose keys are the union of the given maps'
+keys, and whose mapped values are the union of the given maps' corresponding
+mapped values.
### Defaults modules
-A defaults module can be used to repeat the same properties in multiple modules.
-For example:
+A `defaults` module can be used to repeat the same properties in multiple
+modules. For example:
```
cc_defaults {
@@ -184,7 +188,7 @@
```
package {
- default_visibility: [":__subpackages"]
+ default_visibility: [":__subpackages__"]
}
```
diff --git a/android/Android.bp b/android/Android.bp
index 29a88f2..118087d 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -17,6 +17,7 @@
"soong-remoteexec",
"soong-response",
"soong-shared",
+ "soong-starlark",
"soong-starlark-format",
"soong-ui-metrics_proto",
"soong-android-allowlists",
@@ -60,7 +61,6 @@
"license_metadata.go",
"license_sdk_member.go",
"licenses.go",
- "makefile_goal.go",
"makevars.go",
"metrics.go",
"module.go",
@@ -111,6 +111,7 @@
"depset_test.go",
"deptag_test.go",
"expand_test.go",
+ "filegroup_test.go",
"fixture_test.go",
"gen_notice_test.go",
"license_kind_test.go",
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 63495bc..6bd4e26 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -37,6 +37,8 @@
// all modules in this package and subpackages default to bp2build_available: false.
// allows modules to opt-in.
Bp2BuildDefaultFalseRecursively
+
+ DEFAULT_NINJA_WEIGHT = 1000
)
var (
@@ -125,10 +127,12 @@
"external/eigen": Bp2BuildDefaultTrueRecursively,
"external/erofs-utils": Bp2BuildDefaultTrueRecursively,
"external/error_prone": Bp2BuildDefaultTrueRecursively,
+ "external/escapevelocity": Bp2BuildDefaultTrueRecursively,
"external/expat": Bp2BuildDefaultTrueRecursively,
"external/f2fs-tools": Bp2BuildDefaultTrue,
"external/flac": Bp2BuildDefaultTrueRecursively,
"external/fmtlib": Bp2BuildDefaultTrueRecursively,
+ "external/guava": Bp2BuildDefaultTrueRecursively,
"external/google-benchmark": Bp2BuildDefaultTrueRecursively,
"external/googletest": Bp2BuildDefaultTrueRecursively,
"external/gwp_asan": Bp2BuildDefaultTrueRecursively,
@@ -179,22 +183,27 @@
"external/selinux/libselinux": Bp2BuildDefaultTrueRecursively,
"external/selinux/libsepol": Bp2BuildDefaultTrueRecursively,
"external/speex": Bp2BuildDefaultTrueRecursively,
+ "external/sqlite": Bp2BuildDefaultTrueRecursively,
+ "external/tinyalsa": Bp2BuildDefaultTrueRecursively,
+ "external/tinyalsa_new": Bp2BuildDefaultTrueRecursively,
"external/toybox": Bp2BuildDefaultTrueRecursively,
"external/zlib": Bp2BuildDefaultTrueRecursively,
"external/zopfli": Bp2BuildDefaultTrueRecursively,
"external/zstd": Bp2BuildDefaultTrueRecursively,
"frameworks/av": Bp2BuildDefaultTrue,
+ "frameworks/av/media/audioaidlconversion": Bp2BuildDefaultTrueRecursively,
"frameworks/av/media/codec2/components/aom": Bp2BuildDefaultTrueRecursively,
"frameworks/av/media/codecs": Bp2BuildDefaultTrueRecursively,
"frameworks/av/media/liberror": Bp2BuildDefaultTrueRecursively,
+ "frameworks/av/media/libmediahelper": Bp2BuildDefaultTrue,
"frameworks/av/media/libshmem": Bp2BuildDefaultTrueRecursively,
- "frameworks/av/media/audioaidlconversion": Bp2BuildDefaultTrueRecursively,
"frameworks/av/media/module/minijail": Bp2BuildDefaultTrueRecursively,
"frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively,
"frameworks/base/libs/androidfw": Bp2BuildDefaultTrue,
"frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue,
"frameworks/base/services/tests/servicestests/aidl": Bp2BuildDefaultTrue,
+ "frameworks/base/proto": Bp2BuildDefaultTrue,
"frameworks/base/startop/apps/test": Bp2BuildDefaultTrue,
"frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively,
"frameworks/base/tools/aapt2": Bp2BuildDefaultTrue,
@@ -206,56 +215,63 @@
"frameworks/native/libs/gui": Bp2BuildDefaultTrue,
"frameworks/native/libs/math": Bp2BuildDefaultTrueRecursively,
"frameworks/native/libs/nativebase": Bp2BuildDefaultTrueRecursively,
+ "frameworks/native/libs/permission": Bp2BuildDefaultTrueRecursively,
"frameworks/native/libs/vr": 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/native/libs/permission": Bp2BuildDefaultTrue,
"frameworks/native/services/batteryservice": Bp2BuildDefaultTrue,
"frameworks/proto_logging/stats": Bp2BuildDefaultTrueRecursively,
- "hardware/interfaces": Bp2BuildDefaultTrue,
- "hardware/interfaces/audio/aidl": Bp2BuildDefaultTrue,
- "hardware/interfaces/common/aidl": Bp2BuildDefaultTrue,
- "hardware/interfaces/common/fmq/aidl": Bp2BuildDefaultTrue,
- "hardware/interfaces/configstore/1.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/configstore/1.1": Bp2BuildDefaultTrue,
- "hardware/interfaces/configstore/utils": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/allocator/2.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/allocator/3.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/allocator/4.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/allocator/aidl": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/bufferqueue/1.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/bufferqueue/2.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/common/1.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/common/1.1": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/common/1.2": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/common/aidl": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/mapper/2.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/mapper/2.1": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/mapper/3.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/mapper/4.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/health/1.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/health/1.0/default": Bp2BuildDefaultTrue,
- "hardware/interfaces/health/2.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/health/2.0/default": Bp2BuildDefaultTrue,
- "hardware/interfaces/health/2.0/utils": Bp2BuildDefaultTrueRecursively,
- "hardware/interfaces/health/2.1": Bp2BuildDefaultTrue,
- "hardware/interfaces/health/aidl": Bp2BuildDefaultTrue,
- "hardware/interfaces/health/utils": Bp2BuildDefaultTrueRecursively,
- "hardware/interfaces/media/1.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/media/bufferpool/2.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/media/c2/1.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/media/c2/1.1": Bp2BuildDefaultTrue,
- "hardware/interfaces/media/c2/1.2": Bp2BuildDefaultTrue,
- "hardware/interfaces/media/omx/1.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/neuralnetworks/1.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/neuralnetworks/1.1": Bp2BuildDefaultTrue,
- "hardware/interfaces/neuralnetworks/1.2": Bp2BuildDefaultTrue,
- "hardware/interfaces/neuralnetworks/1.3": Bp2BuildDefaultTrue,
- "hardware/interfaces/neuralnetworks/aidl": Bp2BuildDefaultTrue,
+ "hardware/interfaces": Bp2BuildDefaultTrue,
+ "hardware/interfaces/audio/aidl": Bp2BuildDefaultTrue,
+ "hardware/interfaces/audio/aidl/common": Bp2BuildDefaultTrue,
+ "hardware/interfaces/audio/aidl/default": Bp2BuildDefaultTrue,
+ "hardware/interfaces/audio/aidl/sounddose": Bp2BuildDefaultTrue,
+ "hardware/interfaces/common/aidl": Bp2BuildDefaultTrue,
+ "hardware/interfaces/common/fmq/aidl": Bp2BuildDefaultTrue,
+ "hardware/interfaces/common/support": Bp2BuildDefaultTrue,
+ "hardware/interfaces/configstore/1.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/configstore/1.1": Bp2BuildDefaultTrue,
+ "hardware/interfaces/configstore/utils": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/allocator/2.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/allocator/3.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/allocator/4.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/allocator/aidl": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/bufferqueue/1.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/bufferqueue/2.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/common/1.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/common/1.1": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/common/1.2": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/common/aidl": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/mapper/2.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/mapper/2.1": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/mapper/3.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/mapper/4.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/health/1.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/health/1.0/default": Bp2BuildDefaultTrue,
+ "hardware/interfaces/health/2.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/health/2.0/default": Bp2BuildDefaultTrue,
+ "hardware/interfaces/health/2.0/utils": Bp2BuildDefaultTrueRecursively,
+ "hardware/interfaces/health/2.1": Bp2BuildDefaultTrue,
+ "hardware/interfaces/health/aidl": Bp2BuildDefaultTrue,
+ "hardware/interfaces/health/utils": Bp2BuildDefaultTrueRecursively,
+ "hardware/interfaces/media/1.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/media/bufferpool": Bp2BuildDefaultTrueRecursively,
+ "hardware/interfaces/media/bufferpool/aidl/default/tests": Bp2BuildDefaultFalseRecursively,
+ "hardware/interfaces/media/c2/1.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/media/c2/1.1": Bp2BuildDefaultTrue,
+ "hardware/interfaces/media/c2/1.2": Bp2BuildDefaultTrue,
+ "hardware/interfaces/media/omx/1.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/neuralnetworks": Bp2BuildDefaultTrueRecursively,
+ "hardware/interfaces/neuralnetworks/aidl/vts": Bp2BuildDefaultFalseRecursively,
+ "hardware/interfaces/neuralnetworks/1.0/vts": Bp2BuildDefaultFalseRecursively,
+ "hardware/interfaces/neuralnetworks/1.1/vts": Bp2BuildDefaultFalseRecursively,
+ "hardware/interfaces/neuralnetworks/1.2/vts": Bp2BuildDefaultFalseRecursively,
+ "hardware/interfaces/neuralnetworks/1.3/vts": Bp2BuildDefaultFalseRecursively,
+ "hardware/interfaces/neuralnetworks/1.4/vts": Bp2BuildDefaultFalseRecursively,
"libnativehelper": Bp2BuildDefaultTrueRecursively,
@@ -274,21 +290,27 @@
"packages/modules/adb/pairing_connection": Bp2BuildDefaultTrueRecursively,
"packages/modules/adb/proto": Bp2BuildDefaultTrueRecursively,
"packages/modules/adb/tls": Bp2BuildDefaultTrueRecursively,
+ "packages/modules/Gki/libkver": Bp2BuildDefaultTrue,
"packages/modules/NetworkStack/common/captiveportal": Bp2BuildDefaultTrue,
+ "packages/modules/NeuralNetworks/apex": Bp2BuildDefaultTrue,
+ "packages/modules/NeuralNetworks/apex/testing": Bp2BuildDefaultTrue,
"packages/providers/MediaProvider/tools/dialogs": Bp2BuildDefaultFalse, // TODO(b/242834374)
"packages/screensavers/Basic": Bp2BuildDefaultTrue,
"packages/services/Car/tests/SampleRearViewCamera": Bp2BuildDefaultFalse, // TODO(b/242834321)
"platform_testing/tests/example": Bp2BuildDefaultTrueRecursively,
- "prebuilts/clang/host/linux-x86": Bp2BuildDefaultTrueRecursively,
- "prebuilts/gradle-plugin": Bp2BuildDefaultTrueRecursively,
- "prebuilts/runtime/mainline/platform/sdk": Bp2BuildDefaultTrueRecursively,
- "prebuilts/sdk/current/androidx": Bp2BuildDefaultTrue,
- "prebuilts/sdk/current/extras/app-toolkit": Bp2BuildDefaultTrue,
- "prebuilts/sdk/current/support": Bp2BuildDefaultTrue,
- "prebuilts/tools": Bp2BuildDefaultTrue,
- "prebuilts/tools/common/m2": Bp2BuildDefaultTrue,
+ "prebuilts/clang/host/linux-x86": Bp2BuildDefaultTrueRecursively,
+ "prebuilts/gradle-plugin": Bp2BuildDefaultTrueRecursively,
+ "prebuilts/runtime/mainline/platform/sdk": Bp2BuildDefaultTrueRecursively,
+ "prebuilts/sdk/current/androidx": Bp2BuildDefaultTrue,
+ "prebuilts/sdk/current/androidx-legacy": Bp2BuildDefaultTrue,
+ "prebuilts/sdk/current/extras/constraint-layout-x": Bp2BuildDefaultTrue,
+ "prebuilts/sdk/current/extras/material-design-x": Bp2BuildDefaultTrue,
+ "prebuilts/sdk/current/extras/app-toolkit": Bp2BuildDefaultTrue,
+ "prebuilts/sdk/current/support": Bp2BuildDefaultTrue,
+ "prebuilts/tools": Bp2BuildDefaultTrue,
+ "prebuilts/tools/common/m2": Bp2BuildDefaultTrue,
"sdk/dumpeventlog": Bp2BuildDefaultTrue,
"sdk/eventanalyzer": Bp2BuildDefaultTrue,
@@ -337,10 +359,12 @@
"system/libhidl/transport/token/1.0/utils": Bp2BuildDefaultTrue,
"system/libhwbinder": Bp2BuildDefaultTrueRecursively,
"system/libprocinfo": Bp2BuildDefaultTrue,
+ "system/libvintf": Bp2BuildDefaultTrue,
"system/libziparchive": Bp2BuildDefaultTrueRecursively,
"system/logging": Bp2BuildDefaultTrueRecursively,
"system/media": Bp2BuildDefaultTrue,
"system/media/audio": Bp2BuildDefaultTrueRecursively,
+ "system/media/alsa_utils": Bp2BuildDefaultTrueRecursively,
"system/media/audio_utils": Bp2BuildDefaultTrueRecursively,
"system/memory/libion": Bp2BuildDefaultTrueRecursively,
"system/memory/libmemunreachable": Bp2BuildDefaultTrueRecursively,
@@ -348,13 +372,20 @@
"system/testing/gtest_extras": Bp2BuildDefaultTrueRecursively,
"system/timezone/apex": Bp2BuildDefaultTrueRecursively,
"system/timezone/output_data": Bp2BuildDefaultTrueRecursively,
+ "system/timezone/testdata": Bp2BuildDefaultTrueRecursively,
+ "system/timezone/testing": Bp2BuildDefaultTrueRecursively,
"system/tools/aidl/build/tests_bp2build": Bp2BuildDefaultTrue,
+ "system/tools/aidl/metadata": Bp2BuildDefaultTrue,
+ "system/tools/hidl/metadata": Bp2BuildDefaultTrue,
"system/tools/mkbootimg": Bp2BuildDefaultTrueRecursively,
"system/tools/sysprop": Bp2BuildDefaultTrue,
+ "system/tools/xsdc/utils": Bp2BuildDefaultTrueRecursively,
"system/unwinding/libunwindstack": Bp2BuildDefaultTrueRecursively,
- "tools/apksig": Bp2BuildDefaultTrue,
- "tools/metalava": Bp2BuildDefaultTrue,
+ "tools/apifinder": Bp2BuildDefaultTrue,
+ "tools/apksig": Bp2BuildDefaultTrue,
+ "tools/external_updater": Bp2BuildDefaultTrueRecursively,
+ "tools/metalava": Bp2BuildDefaultTrue,
"tools/platform-compat/java/android/compat": Bp2BuildDefaultTrueRecursively,
"tools/tradefederation/prebuilts/filegroups": Bp2BuildDefaultTrueRecursively,
}
@@ -366,6 +397,7 @@
"build/bazel":/* recursive = */ true,
"build/make/core":/* recursive = */ false,
"build/bazel_common_rules":/* recursive = */ true,
+ "build/make/target/product/security":/* recursive = */ false,
// build/make/tools/signapk BUILD file is generated, so build/make/tools is not recursive.
"build/make/tools":/* recursive = */ false,
"build/pesto":/* recursive = */ true,
@@ -377,15 +409,14 @@
"external/bazelbuild-rules_license":/* recursive = */ true,
"external/bazelbuild-kotlin-rules":/* recursive = */ true,
"external/bazel-skylib":/* recursive = */ true,
- "external/guava":/* recursive = */ true,
"external/protobuf":/* recursive = */ false,
"external/python/absl-py":/* recursive = */ true,
+ "external/compiler-rt/lib/cfi":/* recursive = */ false,
+
// this BUILD file is globbed by //external/icu/icu4c/source:icu4c_test_data's "data/**/*".
"external/icu/icu4c/source/data/unidata/norm2":/* recursive = */ false,
- "frameworks/ex/common":/* recursive = */ true,
-
// Building manually due to b/179889880: resource files cross package boundary
"packages/apps/Music":/* recursive = */ true,
@@ -397,7 +428,7 @@
"prebuilts/clang-tools":/* recursive = */ true,
"prebuilts/gcc":/* recursive = */ true,
"prebuilts/build-tools":/* recursive = */ true,
- "prebuilts/jdk/jdk11":/* recursive = */ false,
+ "prebuilts/jdk/jdk17":/* recursive = */ true,
"prebuilts/misc":/* recursive = */ false, // not recursive because we need bp2build converted build files in prebuilts/misc/common/asm
"prebuilts/sdk":/* recursive = */ false,
"prebuilts/sdk/tools":/* recursive = */ false,
@@ -427,16 +458,10 @@
"com.android.media.swcodec-mediaswcodec.rc",
"com.android.media.swcodec.certificate",
"com.android.media.swcodec.key",
- "com.android.neuralnetworks",
- "com.android.neuralnetworks-androidManifest",
- "com.android.neuralnetworks.certificate",
- "com.android.neuralnetworks.key",
"flatbuffer_headers",
"framework-connectivity-protos",
"gemmlowp_headers",
"gl_headers",
- "ipconnectivity-proto-src",
- "libaidlcommonsupport",
"libandroid_runtime_lazy",
"libandroid_runtime_vm_headers",
"libaudioclient_aidl_conversion_util",
@@ -456,6 +481,7 @@
"libgralloctypes",
"libnativewindow",
"libneuralnetworks",
+ "libneuralnetworks_static",
"libgraphicsenv",
"libhardware",
"libhardware_headers",
@@ -498,13 +524,6 @@
"mediaswcodec.policy",
"mediaswcodec.xml",
"neuralnetworks_types",
- "neuralnetworks_utils_hal_aidl",
- "neuralnetworks_utils_hal_common",
- "neuralnetworks_utils_hal_service",
- "neuralnetworks_utils_hal_1_0",
- "neuralnetworks_utils_hal_1_1",
- "neuralnetworks_utils_hal_1_2",
- "neuralnetworks_utils_hal_1_3",
"libneuralnetworks_common",
// packagemanager_aidl_interface is created implicitly in packagemanager_aidl module
"packagemanager_aidl_interface",
@@ -529,6 +548,14 @@
"liblp",
"libstorage_literals_headers",
+ "PluginCoreLib",
+ "dagger2",
+ "dagger2-android-annotation-stubs",
+ "dagger2-bootstrap-compiler",
+ "dagger2-producers",
+ "okio-lib",
+ "setupdesign-strings",
+
//external/avb
"avbtool",
"libavb",
@@ -567,8 +594,8 @@
"car-ui-androidx-constraintlayout-solver-nodeps",
//system/libhidl
- // needed by cc_hidl_library
- "libhidlbase",
+ "libhidlbase", // needed by cc_hidl_library
+ "libhidl_gtest_helper",
//frameworks/native
"framework_native_aidl_binder",
@@ -677,7 +704,6 @@
"libcodec2_soft_common",
// kotlin srcs in java libs
- "CtsPkgInstallerConstants",
"kotlinx_atomicfu",
// kotlin srcs in java binary
@@ -690,6 +716,9 @@
//kotlin srcs in android_binary
"MusicKotlin",
+ // java_library with prebuilt sdk_version
+ "android-common",
+
// checked in current.txt for merged_txts
"non-updatable-current.txt",
"non-updatable-system-current.txt",
@@ -698,6 +727,26 @@
// for api_fingerprint.txt generation
"api_fingerprint",
+
+ // allowlisting for kotlinx_coroutines
+ "annotations",
+ "kotlinx-coroutines-android-annotation-stubs",
+ "kotlinx-coroutines-core",
+ "kotlinx_coroutines",
+ "kotlinx_coroutines-device",
+ "kotlinx_coroutines-host",
+
+ // for building com.android.neuralnetworks
+ "libimapper_stablec",
+ "libimapper_providerutils",
+
+ // min_sdk_version in android_app
+ "CtsShimUpgrade",
+
+ "art_cmdlineparser_headers",
+
+ // Mainline Module Apps
+ "CaptivePortalLogin",
}
Bp2buildModuleTypeAlwaysConvertList = []string{
@@ -720,15 +769,6 @@
// the "prebuilt_" prefix to the name, so that it's differentiable from
// the source versions within Soong's module graph.
Bp2buildModuleDoNotConvertList = []string{
- // TODO(b/250876486): Created cc_aidl_library doesn't have static libs from parent cc module
- "libgui_window_info_static",
- "libgui", // Depends on unconverted libgui_window_info_static
- "libdisplay", // Depends on uncovnerted libgui
- // Depends on unconverted libdisplay
- "libdvr_static.google",
- "libdvr.google",
- "libvrsensor",
- "dvr_api-test",
// Depends on unconverted libandroid, libgui
"dvr_buffer_queue-test",
"dvr_display-test",
@@ -738,7 +778,6 @@
"buffer_hub_queue_producer-test",
// cc bugs
- "libactivitymanager_aidl", // TODO(b/207426160): Unsupported use of aidl sources (via Dactivity_manager_procstate_aidl) in a cc_library
// TODO(b/198619163) module has same name as source
"logtagd.rc",
@@ -751,16 +790,16 @@
"libcutils_test_static",
"KernelLibcutilsTest",
- "linker", // TODO(b/228316882): cc_binary uses link_crt
- "versioner", // TODO(b/228313961): depends on prebuilt shared library libclang-cpp_host as a shared library, which does not supply expected providers for a shared library
- "art_libartbase_headers", // TODO(b/236268577): Header libraries do not support export_shared_libs_headers
- "apexer_test", // Requires aapt2
- "apexer_test_host_tools",
- "host_apex_verifier",
- "tjbench", // TODO(b/240563612): Stem property
+ "linker", // TODO(b/228316882): cc_binary uses link_crt
+ "versioner", // TODO(b/228313961): depends on prebuilt shared library libclang-cpp_host as a shared library, which does not supply expected providers for a shared library
+ "tjbench", // TODO(b/240563612): Stem property
+
+ // requires host tools for apexer
+ "apexer_test", "apexer_test_host_tools", "host_apex_verifier",
// java bugs
- "libbase_ndk", // TODO(b/186826477): fails to link libctscamera2_jni for device (required for CtsCameraTestCases)
+ "libbase_ndk", // TODO(b/186826477): fails to link libctscamera2_jni for device (required for CtsCameraTestCases)
+ "bouncycastle", // TODO(b/274474005): Need support for custom system_modules.
// python protos
"libprotobuf-python", // Has a handcrafted alternative
@@ -786,6 +825,7 @@
// go deps:
"analyze_bcpf", // depends on bpmodify a blueprint_go_binary.
+ "analyze_bcpf_test", // depends on bpmodify a blueprint_go_binary.
"host_bionic_linker_asm", // depends on extract_linker, a go binary.
"host_bionic_linker_script", // depends on extract_linker, a go binary.
@@ -796,13 +836,15 @@
"libtombstoned_client_rust_bridge_code", "libtombstoned_client_wrapper", // rust conversions are not supported
// unconverted deps
- "CarHTMLViewer", // depends on unconverted modules android.car-stubs, car-ui-lib
+ "apexer_with_DCLA_preprocessing_test", // depends on unconverted modules: apexer_test_host_tools, com.android.example.apex
"adb", // depends on unconverted modules: AdbWinApi, libandroidfw, libopenscreen-discovery, libopenscreen-platform-impl, libusb, bin2c_fastdeployagent, AdbWinUsbApi
"android_icu4j_srcgen", // depends on unconverted modules: currysrc
"android_icu4j_srcgen_binary", // depends on unconverted modules: android_icu4j_srcgen, currysrc
+ "apex_compression_test", // depends on unconverted modules: soong_zip, com.android.example.apex
"apex_manifest_proto_java", // b/210751803, depends on libprotobuf-java-full
"art-script", // depends on unconverted modules: dalvikvm, dex2oat
"bin2c_fastdeployagent", // depends on unconverted modules: deployagent
+ "CarHTMLViewer", // depends on unconverted modules android.car-stubs, car-ui-lib
"com.android.runtime", // depends on unconverted modules: bionic-linker-config, linkerconfig
"currysrc", // depends on unconverted modules: currysrc_org.eclipse, guavalib, jopt-simple-4.9
"dex2oat-script", // depends on unconverted modules: dex2oat
@@ -827,12 +869,12 @@
"libgmock_ndk", // depends on unconverted modules: libgtest_ndk_c++
"libnativehelper_lazy_mts_jni", "libnativehelper_mts_jni", // depends on unconverted modules: libnativetesthelper_jni, libgmock_ndk
"libnativetesthelper_jni", // depends on unconverted modules: libgtest_ndk_c++
- "libprotobuf-java-nano", // b/220869005, depends on non-public_current SDK
"libstatslog", // depends on unconverted modules: libstatspull, statsd-aidl-ndk
"libstatslog_art", // depends on unconverted modules: statslog_art.cpp, statslog_art.h
"linker_reloc_bench_main", // depends on unconverted modules: liblinker_reloc_bench_*
"malloc-rss-benchmark", // depends on unconverted modules: libmeminfo
"pbtombstone", "crash_dump", // depends on libdebuggerd, libunwindstack
+ "releasetools_test", // depends on unconverted modules: com.android.apex.compressed.v1
"robolectric-sqlite4java-0.282", // depends on unconverted modules: robolectric-sqlite4java-import, robolectric-sqlite4java-native
"static_crasher", // depends on unconverted modules: libdebuggerd_handler
"test_fips", // depends on unconverted modules: adb
@@ -856,7 +898,34 @@
// depends on android.hardware.health-V2.0-java
"android.hardware.health-translate-java",
+ //system/libvintf
+ // depends on apex-info-list-tinyxml, unconverted xsd_config Soong module type.
+ "libvintf",
+ "vintf",
+ "libassemblevintf",
+ "assemble_vintf",
+ "libvintffm",
+ "vintffm",
+ "checkvintf",
+
+ // depends on audio_policy_configuration_aidl_default, xsd_config module.
+ "libaudioserviceexampleimpl",
+ "android.hardware.audio.service-aidl.example",
+
+ // depends on //system/tools/aidl/build:aidl_metadata_json, which is an aidl_interfaces_metadata custom Soong type.
+ "aidl_metadata_in_cpp",
+ "libaidlmetadata",
+ "libaidlmetadata_test",
+
+ // depends on //system/tools/hidl/build:hidl_metadata_json, which is an hidl_interfaces_metadata custom Soong type.
+ "hidl_metadata_in_cpp",
+ "libhidlmetadata",
+ "hidl_metadata_test",
+
// cc_test related.
+ // b/274164834 "Could not open Configuration file test.cfg"
+ "svcenc", "svcdec",
+
// Failing host cc_tests
"memunreachable_unit_test",
"libprocinfo_test",
@@ -882,6 +951,11 @@
"libandroidfw_tests", "aapt2_tests", // failing due to data path issues
+ // error: overriding commands for target
+ // `out/host/linux-x86/nativetest64/gmock_tests/gmock_tests__cc_runner_test',
+ // previously defined at out/soong/installs-aosp_arm.mk:64919`
+ "gmock_tests",
+
// cc_test with unconverted deps, or are device-only (and not verified to pass yet)
"AMRWBEncTest",
"AmrnbDecoderTest", // depends on unconverted modules: libaudioutils, libsndfile
@@ -1008,7 +1082,7 @@
"libcfi-test",
"libcfi-test-bad",
"libcrash_test",
- // "libcrypto_fuzz_unsafe",
+ "libcrypto_fuzz_unsafe",
"libdl_preempt_test_1",
"libdl_preempt_test_2",
"libdl_test_df_1_global",
@@ -1219,7 +1293,7 @@
"librelocations-fat",
"libsegment_gap_inner",
"libsegment_gap_outer",
- // "libssl_fuzz_unsafe",
+ "libssl_fuzz_unsafe",
"libstatssocket_private",
"libsysv-hash-table-library",
"libtest_atexit",
@@ -1350,6 +1424,26 @@
// TODO(b/266459895): depends on libunwindstack
"libutils_test",
+
+ // Has dependencies on other tools like ziptool, bp2build'd data properties don't work with these tests atm
+ "ziparchive_tests_large",
+ "mkbootimg_test",
+ "certify_bootimg_test",
+
+ // Despite being _host module types, these require devices to run
+ "logd_integration_test",
+ "mobly-hello-world-test",
+ "mobly-multidevice-test",
+
+ // TODO(b/274805756): Support core_platform and current java APIs
+ "fake-framework",
+
+ // TODO(b/277616982): These modules depend on private java APIs, but maybe they don't need to.
+ "StreamingProtoTest",
+ "textclassifierprotoslite",
+ "styleprotoslite",
+ "CtsPkgInstallerConstants",
+ "guava-android-testlib",
}
MixedBuildsDisabledList = []string{
@@ -1406,25 +1500,30 @@
"unwind",
"unwind_info",
"unwind_symbols",
- "libc_malloc_debug",
- "libfdtrack",
- "mediaswcodec",
- "libcodec2_hidl@1.0",
"libEGL",
- "libstagefright_bufferqueue_helper_novndk",
"libGLESv2",
+ "libc_malloc_debug",
+ "libcodec2_hidl@1.0",
"libcodec2_hidl@1.1",
- "libmedia_codecserviceregistrant",
"libcodec2_hidl@1.2",
+ "libfdtrack",
+ "libgui",
+ "libgui_bufferqueue_static",
+ "libmedia_codecserviceregistrant",
+ "libstagefright_bufferqueue_helper_novndk",
"libutils_test",
"libutilscallstack",
+ "mediaswcodec",
}
// Bazel prod-mode allowlist. Modules in this list are built by Bazel
// in either prod mode or staging mode.
ProdMixedBuildsEnabledList = []string{
+ // M5: tzdata launch
"com.android.tzdata",
"test1_com.android.tzdata",
+ "test3_com.android.tzdata",
+ // M7: adbd launch
"com.android.adbd",
"test_com.android.adbd",
"adbd_test",
@@ -1432,6 +1531,13 @@
"adb_pairing_auth_test",
"adb_pairing_connection_test",
"adb_tls_connection_test",
+ // M9: mixed builds for mainline trains launch
+ "api_fingerprint",
+ // M11: neuralnetworks launch
+ "com.android.neuralnetworks",
+ "test_com.android.neuralnetworks",
+ "libneuralnetworks",
+ "libneuralnetworks_static",
}
// Staging-mode allowlist. Modules in this list are only built
@@ -1439,23 +1545,285 @@
// which will soon be added to the prod allowlist.
// It is implicit that all modules in ProdMixedBuildsEnabledList will
// also be built - do not add them to this list.
- StagingMixedBuildsEnabledList = []string{
- "api_fingerprint",
- }
+ StagingMixedBuildsEnabledList = []string{}
// These should be the libs that are included by the apexes in the ProdMixedBuildsEnabledList
- ProdDclaMixedBuildsEnabledList = []string{}
-
- // These should be the libs that are included by the apexes in the StagingMixedBuildsEnabledList
- StagingDclaMixedBuildsEnabledList = []string{
+ ProdDclaMixedBuildsEnabledList = []string{
"libbase",
"libc++",
"libcrypto",
"libcutils",
}
+ // These should be the libs that are included by the apexes in the StagingMixedBuildsEnabledList
+ StagingDclaMixedBuildsEnabledList = []string{}
+
// TODO(b/269342245): Enable the rest of the DCLA libs
// "libssl",
// "libstagefright_flacdec",
// "libutils",
+
+ // TODO(b/273282046): Make this list customizable to support various targets.
+ // The list of modules which are expected to spend lots of build time.
+ // With `--ninja_weight_source=soong`, ninja builds these modules and deps first.
+ HugeModulesMap = map[string]int{
+ "AccountManagementApp": DEFAULT_NINJA_WEIGHT,
+ "ActivityManagerPerfTestsStubApp1": DEFAULT_NINJA_WEIGHT,
+ "ActivityManagerPerfTestsStubApp2": DEFAULT_NINJA_WEIGHT,
+ "ActivityManagerPerfTestsStubApp3": DEFAULT_NINJA_WEIGHT,
+ "api-stubs-docs-non-updatable": DEFAULT_NINJA_WEIGHT,
+ "AppCompatibilityTest": DEFAULT_NINJA_WEIGHT,
+ "AppTransitionTests": DEFAULT_NINJA_WEIGHT,
+ "art_compiler_tests": DEFAULT_NINJA_WEIGHT,
+ "art.module.intra.core.api.stubs.source": DEFAULT_NINJA_WEIGHT,
+ "art.module.public.api.stubs.source": DEFAULT_NINJA_WEIGHT,
+ "AttestationVerificationTest": DEFAULT_NINJA_WEIGHT,
+ "BatteryUsageStatsProtoTests": DEFAULT_NINJA_WEIGHT,
+ "bluetooth_test_gd_unit": DEFAULT_NINJA_WEIGHT,
+ "Bluetooth": DEFAULT_NINJA_WEIGHT,
+ "BluetoothInstrumentationTests": DEFAULT_NINJA_WEIGHT,
+ "Calendar": DEFAULT_NINJA_WEIGHT,
+ "CalendarProvider": DEFAULT_NINJA_WEIGHT,
+ "Camera2": DEFAULT_NINJA_WEIGHT,
+ "CarRotaryControllerUnitTests": DEFAULT_NINJA_WEIGHT,
+ "CarSettingsForUnitTesting": DEFAULT_NINJA_WEIGHT,
+ "CarSettingsUnitTests": DEFAULT_NINJA_WEIGHT,
+ "CarSystemUI-tests": DEFAULT_NINJA_WEIGHT,
+ "CellBroadcastApp": DEFAULT_NINJA_WEIGHT,
+ "CellBroadcastLegacyApp": DEFAULT_NINJA_WEIGHT,
+ "CellBroadcastReceiverOemUnitTests": DEFAULT_NINJA_WEIGHT,
+ "CellBroadcastServiceModule": DEFAULT_NINJA_WEIGHT,
+ "CompanionDeviceManager": DEFAULT_NINJA_WEIGHT,
+ "ConnectivityChecker": DEFAULT_NINJA_WEIGHT,
+ "Contacts": DEFAULT_NINJA_WEIGHT,
+ "ContactsProvider": DEFAULT_NINJA_WEIGHT,
+ "ContentCapturePerfTests": DEFAULT_NINJA_WEIGHT,
+ "CorePerfTests": DEFAULT_NINJA_WEIGHT,
+ "crosvm": DEFAULT_NINJA_WEIGHT,
+ "CtsDomainVerificationDeviceMultiUserTestCases": DEFAULT_NINJA_WEIGHT,
+ "CtsLogdTestCases": DEFAULT_NINJA_WEIGHT,
+ "CtsMediaProviderTranscodeTests": DEFAULT_NINJA_WEIGHT,
+ "CtsRollbackManagerHostTestHelperApp": DEFAULT_NINJA_WEIGHT,
+ "CtsRollbackManagerHostTestHelperApp2": DEFAULT_NINJA_WEIGHT,
+ "CtsRootPackageInstallerTestCases": DEFAULT_NINJA_WEIGHT,
+ "CtsRootRollbackManagerHostTestHelperApp": DEFAULT_NINJA_WEIGHT,
+ "CtsTranscodeTestAppSupportsHevc": DEFAULT_NINJA_WEIGHT,
+ "CtsTranscodeTestAppSupportsSlowMotion": DEFAULT_NINJA_WEIGHT,
+ "CuttlefishDisplayHotplugHelperApp": DEFAULT_NINJA_WEIGHT,
+ "cvd-host_package": DEFAULT_NINJA_WEIGHT,
+ "DelegateTestApp": DEFAULT_NINJA_WEIGHT,
+ "DeskClock": DEFAULT_NINJA_WEIGHT,
+ "Development": DEFAULT_NINJA_WEIGHT,
+ "DeviceAdminTestApp": DEFAULT_NINJA_WEIGHT,
+ "DevicePolicyManagementRoleHolderTestApp": DEFAULT_NINJA_WEIGHT,
+ "dex2oatd": DEFAULT_NINJA_WEIGHT,
+ "DocumentsUI": DEFAULT_NINJA_WEIGHT,
+ "EasterEgg": DEFAULT_NINJA_WEIGHT,
+ "EffectProxyTest": DEFAULT_NINJA_WEIGHT,
+ "EmergencyInfo": DEFAULT_NINJA_WEIGHT,
+ "EmptyTestApp": DEFAULT_NINJA_WEIGHT,
+ "ExtServices": DEFAULT_NINJA_WEIGHT,
+ "FacebookAppsScenarioTests": DEFAULT_NINJA_WEIGHT,
+ "flickerlib-core": DEFAULT_NINJA_WEIGHT,
+ "flickerlib": DEFAULT_NINJA_WEIGHT,
+ "FlickerLibTest": DEFAULT_NINJA_WEIGHT,
+ "FlickerTests": DEFAULT_NINJA_WEIGHT,
+ "framework-minus-apex": DEFAULT_NINJA_WEIGHT,
+ "framework-res": DEFAULT_NINJA_WEIGHT,
+ "FrameworksCoreTests": DEFAULT_NINJA_WEIGHT,
+ "FrameworksMockingCoreTests": DEFAULT_NINJA_WEIGHT,
+ "FrameworksMockingServicesTests": DEFAULT_NINJA_WEIGHT,
+ "FrameworksNetSmokeTests": DEFAULT_NINJA_WEIGHT,
+ "FrameworksNetTests": DEFAULT_NINJA_WEIGHT,
+ "FrameworksServicesTests": DEFAULT_NINJA_WEIGHT,
+ "FrameworksTelephonyTests": DEFAULT_NINJA_WEIGHT,
+ "FrameworksUiServicesTests": DEFAULT_NINJA_WEIGHT,
+ "FrameworksVcnTests": DEFAULT_NINJA_WEIGHT,
+ "Gallery2": DEFAULT_NINJA_WEIGHT,
+ "GameCoreDevice": DEFAULT_NINJA_WEIGHT,
+ "GoogleBluetoothInstrumentationTests": DEFAULT_NINJA_WEIGHT,
+ "guice_munged_srcs": DEFAULT_NINJA_WEIGHT,
+ "HalfSheetUX": DEFAULT_NINJA_WEIGHT,
+ "ImePerfTests": DEFAULT_NINJA_WEIGHT,
+ "imgdiag": DEFAULT_NINJA_WEIGHT,
+ "ImsServiceEntitlement": DEFAULT_NINJA_WEIGHT,
+ "ImsServiceEntitlementUnitTests": DEFAULT_NINJA_WEIGHT,
+ "InputTests": DEFAULT_NINJA_WEIGHT,
+ "InstallTest": DEFAULT_NINJA_WEIGHT,
+ "IntentResolver": DEFAULT_NINJA_WEIGHT,
+ "JankBench": DEFAULT_NINJA_WEIGHT,
+ "jsilver": DEFAULT_NINJA_WEIGHT,
+ "KeyChain": DEFAULT_NINJA_WEIGHT,
+ "KeyChainTests": DEFAULT_NINJA_WEIGHT,
+ "keystore2": DEFAULT_NINJA_WEIGHT,
+ "LargeResourcesCompressed": DEFAULT_NINJA_WEIGHT,
+ "LatinIME": DEFAULT_NINJA_WEIGHT,
+ "Launcher3QuickStepLib": DEFAULT_NINJA_WEIGHT,
+ "libaom": DEFAULT_NINJA_WEIGHT,
+ "libart-broken": DEFAULT_NINJA_WEIGHT,
+ "libart-compiler": DEFAULT_NINJA_WEIGHT,
+ "libart-disassembler": DEFAULT_NINJA_WEIGHT,
+ "libart": DEFAULT_NINJA_WEIGHT,
+ "libartd": DEFAULT_NINJA_WEIGHT,
+ "libaudiohal@7.1": DEFAULT_NINJA_WEIGHT,
+ "libbluetooth_core_rs": DEFAULT_NINJA_WEIGHT,
+ "libbluetooth_gd_unit_tests": DEFAULT_NINJA_WEIGHT,
+ "libbluetooth_gd": DEFAULT_NINJA_WEIGHT,
+ "libbluetooth_rs": DEFAULT_NINJA_WEIGHT,
+ "libbluetooth-for-tests": DEFAULT_NINJA_WEIGHT,
+ "libbt_common": DEFAULT_NINJA_WEIGHT,
+ "libbt_packets_nonapex": DEFAULT_NINJA_WEIGHT,
+ "libbt_packets": DEFAULT_NINJA_WEIGHT,
+ "libbt_shim_ffi": DEFAULT_NINJA_WEIGHT,
+ "libbt_shim": DEFAULT_NINJA_WEIGHT,
+ "libbt-audio-hal-interface": DEFAULT_NINJA_WEIGHT,
+ "libbt-bta-core": DEFAULT_NINJA_WEIGHT,
+ "libbt-bta": DEFAULT_NINJA_WEIGHT,
+ "libbt-common": DEFAULT_NINJA_WEIGHT,
+ "libbt-hci": DEFAULT_NINJA_WEIGHT,
+ "libbt-platform-protos-lite": DEFAULT_NINJA_WEIGHT,
+ "libbt-protos-lite": DEFAULT_NINJA_WEIGHT,
+ "libbt-sbc-decoder": DEFAULT_NINJA_WEIGHT,
+ "libc": DEFAULT_NINJA_WEIGHT,
+ "libclap": DEFAULT_NINJA_WEIGHT,
+ "libcodec2_soft_av1dec_gav1": DEFAULT_NINJA_WEIGHT,
+ "libcompositionengine_test": DEFAULT_NINJA_WEIGHT,
+ "libdevices": DEFAULT_NINJA_WEIGHT,
+ "libfrontend_proto": DEFAULT_NINJA_WEIGHT,
+ "libhwtrust": DEFAULT_NINJA_WEIGHT,
+ "libjni": DEFAULT_NINJA_WEIGHT,
+ "libkeystore2": DEFAULT_NINJA_WEIGHT,
+ "libkmr_ta": DEFAULT_NINJA_WEIGHT,
+ "liblmp": DEFAULT_NINJA_WEIGHT,
+ "libopenjdkjvmtid": DEFAULT_NINJA_WEIGHT,
+ "libprotobuf_deprecated": DEFAULT_NINJA_WEIGHT,
+ "libprotobuf": DEFAULT_NINJA_WEIGHT,
+ "libregex": DEFAULT_NINJA_WEIGHT,
+ "LibStatsPullTests": DEFAULT_NINJA_WEIGHT,
+ "libstd": DEFAULT_NINJA_WEIGHT,
+ "libsurfaceflinger_unittest": DEFAULT_NINJA_WEIGHT,
+ "libsyn": DEFAULT_NINJA_WEIGHT,
+ "libtokio": DEFAULT_NINJA_WEIGHT,
+ "libuwb_core": DEFAULT_NINJA_WEIGHT,
+ "libuwb_uci_jni_rust": DEFAULT_NINJA_WEIGHT,
+ "libuwb_uci_packets": DEFAULT_NINJA_WEIGHT,
+ "libvpx": DEFAULT_NINJA_WEIGHT,
+ "libvulkan_enc": DEFAULT_NINJA_WEIGHT,
+ "libwebrtc": DEFAULT_NINJA_WEIGHT,
+ "LiveWallpapersPicker": DEFAULT_NINJA_WEIGHT,
+ "LockTaskApp": DEFAULT_NINJA_WEIGHT,
+ "LongevityPlatformLibTests": DEFAULT_NINJA_WEIGHT,
+ "ManagedProvisioning": DEFAULT_NINJA_WEIGHT,
+ "ManagedProvisioningTests": DEFAULT_NINJA_WEIGHT,
+ "MediaProvider": DEFAULT_NINJA_WEIGHT,
+ "MediaProviderClientTests": DEFAULT_NINJA_WEIGHT,
+ "MediaProviderLegacy": DEFAULT_NINJA_WEIGHT,
+ "messaging": DEFAULT_NINJA_WEIGHT,
+ "metalava": DEFAULT_NINJA_WEIGHT,
+ "MicrobenchmarkRunnerTests": DEFAULT_NINJA_WEIGHT,
+ "microdroid_manager": DEFAULT_NINJA_WEIGHT,
+ "minikin_tests": DEFAULT_NINJA_WEIGHT,
+ "MLCTestApp": DEFAULT_NINJA_WEIGHT,
+ "MmsService": DEFAULT_NINJA_WEIGHT,
+ "MmsServiceTests": DEFAULT_NINJA_WEIGHT,
+ "module-lib-api-stubs-docs-non-updatable": DEFAULT_NINJA_WEIGHT,
+ "motion_tool_lib_tests": DEFAULT_NINJA_WEIGHT,
+ "MtpService": DEFAULT_NINJA_WEIGHT,
+ "MultiUserTests": DEFAULT_NINJA_WEIGHT,
+ "NearbyIntegrationUiTests": DEFAULT_NINJA_WEIGHT,
+ "net_test_bluetooth": DEFAULT_NINJA_WEIGHT,
+ "net_test_btif": DEFAULT_NINJA_WEIGHT,
+ "net_test_main_shim": DEFAULT_NINJA_WEIGHT,
+ "net_test_stack": DEFAULT_NINJA_WEIGHT,
+ "net-tests-utils": DEFAULT_NINJA_WEIGHT,
+ "NetworkStackCoverageTests": DEFAULT_NINJA_WEIGHT,
+ "NetworkStackIntegrationTests": DEFAULT_NINJA_WEIGHT,
+ "NetworkStackNext": DEFAULT_NINJA_WEIGHT,
+ "NfcNci": DEFAULT_NINJA_WEIGHT,
+ "NfcNciUnitTests": DEFAULT_NINJA_WEIGHT,
+ "NotEmptyTestApp": DEFAULT_NINJA_WEIGHT,
+ "NotificationFunctionalTests": DEFAULT_NINJA_WEIGHT,
+ "oatdumpd": DEFAULT_NINJA_WEIGHT,
+ "OsuLogin": DEFAULT_NINJA_WEIGHT,
+ "PackageInstaller": DEFAULT_NINJA_WEIGHT,
+ "PackageManagerComponentOverrideTests": DEFAULT_NINJA_WEIGHT,
+ "PackageManagerPerfTests": DEFAULT_NINJA_WEIGHT,
+ "PackageManagerServiceServerTests": DEFAULT_NINJA_WEIGHT,
+ "PackageManagerServiceUnitTests": DEFAULT_NINJA_WEIGHT,
+ "PackageWatchdogTest": DEFAULT_NINJA_WEIGHT,
+ "PandoraServerLib": DEFAULT_NINJA_WEIGHT,
+ "pdl": DEFAULT_NINJA_WEIGHT,
+ "perfetto_trace_java_protos": DEFAULT_NINJA_WEIGHT,
+ "perfetto_trace-full": DEFAULT_NINJA_WEIGHT,
+ "PermissionController": DEFAULT_NINJA_WEIGHT,
+ "PermissionControllerMockingTests": DEFAULT_NINJA_WEIGHT,
+ "PixelAppCompTests": DEFAULT_NINJA_WEIGHT,
+ "platform-bootclasspath": DEFAULT_NINJA_WEIGHT,
+ "PlatformCommonScenarioTests": DEFAULT_NINJA_WEIGHT,
+ "PlatformComposeCoreTests": DEFAULT_NINJA_WEIGHT,
+ "platformprotoslite": DEFAULT_NINJA_WEIGHT,
+ "PlatformRuleTests": DEFAULT_NINJA_WEIGHT,
+ "precompiled_sepolicy-without_apex": DEFAULT_NINJA_WEIGHT,
+ "PresencePolling": DEFAULT_NINJA_WEIGHT,
+ "PrintSpooler": DEFAULT_NINJA_WEIGHT,
+ "QuickSearchBox": DEFAULT_NINJA_WEIGHT,
+ "RemoteDPCTestApp": DEFAULT_NINJA_WEIGHT,
+ "RemoteProvisioningServiceTests": DEFAULT_NINJA_WEIGHT,
+ "RkpdAppUnitTests": DEFAULT_NINJA_WEIGHT,
+ "Robolectric_shadows_framework": DEFAULT_NINJA_WEIGHT,
+ "RoleHolderApp": DEFAULT_NINJA_WEIGHT,
+ "SdkSandbox": DEFAULT_NINJA_WEIGHT,
+ "service-appsearch": DEFAULT_NINJA_WEIGHT,
+ "service-connectivity": DEFAULT_NINJA_WEIGHT,
+ "service-uwb": DEFAULT_NINJA_WEIGHT,
+ "service-wifi": DEFAULT_NINJA_WEIGHT,
+ "services-non-updatable-stubs": DEFAULT_NINJA_WEIGHT,
+ "services": DEFAULT_NINJA_WEIGHT,
+ "Settings-core": DEFAULT_NINJA_WEIGHT,
+ "Settings": DEFAULT_NINJA_WEIGHT,
+ "SettingsIntelligence": DEFAULT_NINJA_WEIGHT,
+ "SettingsLibTests": DEFAULT_NINJA_WEIGHT,
+ "SettingsProvider": DEFAULT_NINJA_WEIGHT,
+ "Shell": DEFAULT_NINJA_WEIGHT,
+ "SimAppDialog": DEFAULT_NINJA_WEIGHT,
+ "sl4a": DEFAULT_NINJA_WEIGHT,
+ "SmsApp": DEFAULT_NINJA_WEIGHT,
+ "SoundPicker": DEFAULT_NINJA_WEIGHT,
+ "StagedInstallTest": DEFAULT_NINJA_WEIGHT,
+ "StatementService": DEFAULT_NINJA_WEIGHT,
+ "StatsdFrameworkTestApp": DEFAULT_NINJA_WEIGHT,
+ "StatsdFrameworkTestAppNoPermission": DEFAULT_NINJA_WEIGHT,
+ "statsdprotolite": DEFAULT_NINJA_WEIGHT,
+ "Stk": DEFAULT_NINJA_WEIGHT,
+ "StorageManager": DEFAULT_NINJA_WEIGHT,
+ "system-api-stubs-docs-non-updatable": DEFAULT_NINJA_WEIGHT,
+ "SystemUI-core": DEFAULT_NINJA_WEIGHT,
+ "SystemUI-tests-base": DEFAULT_NINJA_WEIGHT,
+ "SystemUI-tests": DEFAULT_NINJA_WEIGHT,
+ "SystemUI": DEFAULT_NINJA_WEIGHT,
+ "SystemUIComposeFeatures": DEFAULT_NINJA_WEIGHT,
+ "SystemUIComposeFeaturesTests": DEFAULT_NINJA_WEIGHT,
+ "SystemUITests": DEFAULT_NINJA_WEIGHT,
+ "Tag": DEFAULT_NINJA_WEIGHT,
+ "Telecom": DEFAULT_NINJA_WEIGHT,
+ "TelecomUnitTests": DEFAULT_NINJA_WEIGHT,
+ "telephony-common": DEFAULT_NINJA_WEIGHT,
+ "TelephonyProvider": DEFAULT_NINJA_WEIGHT,
+ "TeleService": DEFAULT_NINJA_WEIGHT,
+ "test-api-stubs-docs-non-updatable": DEFAULT_NINJA_WEIGHT,
+ "TetheringIntegrationTests": DEFAULT_NINJA_WEIGHT,
+ "TetheringNext": DEFAULT_NINJA_WEIGHT,
+ "ThemePickerTests": DEFAULT_NINJA_WEIGHT,
+ "Traceur": DEFAULT_NINJA_WEIGHT,
+ "UsbManagerTests": DEFAULT_NINJA_WEIGHT,
+ "UsbTests": DEFAULT_NINJA_WEIGHT,
+ "virtmgr": DEFAULT_NINJA_WEIGHT,
+ "WallpaperPicker2TestLib": DEFAULT_NINJA_WEIGHT,
+ "WallpaperPicker2Tests": DEFAULT_NINJA_WEIGHT,
+ "WifiDialog": DEFAULT_NINJA_WEIGHT,
+ "wm-proto-parsers": DEFAULT_NINJA_WEIGHT,
+ "WMShellFlickerTests": DEFAULT_NINJA_WEIGHT,
+ "WmTests": DEFAULT_NINJA_WEIGHT,
+ "wpa_supplicant": DEFAULT_NINJA_WEIGHT,
+ }
)
diff --git a/android/apex.go b/android/apex.go
index 358818f..6119b08 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -84,6 +84,9 @@
//
// See Prebuilt.ApexInfoMutator for more information.
ForPrebuiltApex bool
+
+ // Returns the name of the test apexes that this module is included in.
+ TestApexes []string
}
var ApexInfoProvider = blueprint.NewMutatorProvider(ApexInfo{}, "apex")
@@ -287,6 +290,9 @@
// See ApexModule.UniqueApexVariants()
UniqueApexVariationsForDeps bool `blueprint:"mutated"`
+
+ // The test apexes that includes this apex variant
+ TestApexes []string `blueprint:"mutated"`
}
// Marker interface that identifies dependencies that are excluded from APEX contents.
@@ -356,9 +362,18 @@
return m
}
+var (
+ availableToPlatformList = []string{AvailableToPlatform}
+)
+
// Implements ApexModule
func (m *ApexModuleBase) ApexAvailable() []string {
- return m.ApexProperties.Apex_available
+ aa := m.ApexProperties.Apex_available
+ if len(aa) > 0 {
+ return aa
+ }
+ // Default is availability to platform
+ return CopyOf(availableToPlatformList)
}
// Implements ApexModule
@@ -420,6 +435,11 @@
return nil
}
+// Returns the test apexes that this module is included in.
+func (m *ApexModuleBase) TestApexes() []string {
+ return m.ApexProperties.TestApexes
+}
+
// Implements ApexModule
func (m *ApexModuleBase) UniqueApexVariations() bool {
// If needed, this will bel overridden by concrete types inheriting
@@ -442,6 +462,14 @@
AvailableToGkiApex = "com.android.gki.*"
)
+var (
+ AvailableToRecognziedWildcards = []string{
+ AvailableToPlatform,
+ AvailableToAnyApex,
+ AvailableToGkiApex,
+ }
+)
+
// CheckAvailableForApex provides the default algorithm for checking the apex availability. When the
// availability is empty, it defaults to ["//apex_available:platform"] which means "available to the
// platform but not available to any APEX". When the list is not empty, `what` is matched against
@@ -540,12 +568,14 @@
// Platform APIs is allowed for this module only when all APEXes containing
// the module are with `use_platform_apis: true`.
merged[index].UsePlatformApis = merged[index].UsePlatformApis && apexInfo.UsePlatformApis
+ merged[index].TestApexes = append(merged[index].TestApexes, apexInfo.TestApexes...)
} else {
seen[mergedName] = len(merged)
apexInfo.ApexVariationName = mergedName
apexInfo.InApexVariants = CopyOf(apexInfo.InApexVariants)
apexInfo.InApexModules = CopyOf(apexInfo.InApexModules)
apexInfo.ApexContents = append([]*ApexContents(nil), apexInfo.ApexContents...)
+ apexInfo.TestApexes = CopyOf(apexInfo.TestApexes)
merged = append(merged, apexInfo)
}
aliases = append(aliases, [2]string{variantName, mergedName})
@@ -593,8 +623,10 @@
mctx.SetDefaultDependencyVariation(&defaultVariation)
variations := []string{defaultVariation}
+ testApexes := []string{}
for _, a := range apexInfos {
variations = append(variations, a.ApexVariationName)
+ testApexes = append(testApexes, a.TestApexes...)
}
modules := mctx.CreateVariations(variations...)
for i, mod := range modules {
@@ -608,6 +640,9 @@
if !platformVariation {
mctx.SetVariationProvider(mod, ApexInfoProvider, apexInfos[i-1])
}
+ // Set the value of TestApexes in every single apex variant.
+ // This allows each apex variant to be aware of the test apexes in the user provided apex_available.
+ mod.(ApexModule).apexModuleBase().ApexProperties.TestApexes = testApexes
}
for _, alias := range aliases {
@@ -845,7 +880,7 @@
// ModuleWithMinSdkVersionCheck represents a module that implements min_sdk_version checks
type ModuleWithMinSdkVersionCheck interface {
Module
- MinSdkVersion(ctx EarlyModuleContext) SdkSpec
+ MinSdkVersion(ctx EarlyModuleContext) ApiLevel
CheckMinSdkVersion(ctx ModuleContext)
}
@@ -898,3 +933,9 @@
return true
})
}
+
+// Implemented by apexBundle.
+type ApexTestInterface interface {
+ // Return true if the apex bundle is an apex_test
+ IsTestApex() bool
+}
diff --git a/android/apex_test.go b/android/apex_test.go
index 0bf4c9c..ddc730d 100644
--- a/android/apex_test.go
+++ b/android/apex_test.go
@@ -33,10 +33,10 @@
{
name: "single",
in: []ApexInfo{
- {"foo", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
+ {"foo", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex, nil},
},
wantMerged: []ApexInfo{
- {"apex10000", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
+ {"apex10000", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex, nil},
},
wantAliases: [][2]string{
{"foo", "apex10000"},
@@ -45,11 +45,11 @@
{
name: "merge",
in: []ApexInfo{
- {"foo", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
- {"bar", FutureApiLevel, false, false, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
+ {"foo", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex, nil},
+ {"bar", FutureApiLevel, false, false, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex, nil},
},
wantMerged: []ApexInfo{
- {"apex10000", FutureApiLevel, false, false, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, false}},
+ {"apex10000", FutureApiLevel, false, false, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, false, nil}},
wantAliases: [][2]string{
{"bar", "apex10000"},
{"foo", "apex10000"},
@@ -58,12 +58,12 @@
{
name: "don't merge version",
in: []ApexInfo{
- {"foo", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
- {"bar", uncheckedFinalApiLevel(30), false, false, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
+ {"foo", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex, nil},
+ {"bar", uncheckedFinalApiLevel(30), false, false, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex, nil},
},
wantMerged: []ApexInfo{
- {"apex30", uncheckedFinalApiLevel(30), false, false, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
- {"apex10000", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
+ {"apex30", uncheckedFinalApiLevel(30), false, false, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex, nil},
+ {"apex10000", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex, nil},
},
wantAliases: [][2]string{
{"bar", "apex30"},
@@ -73,11 +73,11 @@
{
name: "merge updatable",
in: []ApexInfo{
- {"foo", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
- {"bar", FutureApiLevel, true, false, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
+ {"foo", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex, nil},
+ {"bar", FutureApiLevel, true, false, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex, nil},
},
wantMerged: []ApexInfo{
- {"apex10000", FutureApiLevel, true, false, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex},
+ {"apex10000", FutureApiLevel, true, false, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex, nil},
},
wantAliases: [][2]string{
{"bar", "apex10000"},
@@ -87,15 +87,15 @@
{
name: "don't merge when for prebuilt_apex",
in: []ApexInfo{
- {"foo", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
- {"bar", FutureApiLevel, true, false, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
+ {"foo", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex, nil},
+ {"bar", FutureApiLevel, true, false, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex, nil},
// This one should not be merged in with the others because it is for
// a prebuilt_apex.
- {"baz", FutureApiLevel, true, false, []string{"baz"}, []string{"baz"}, nil, ForPrebuiltApex},
+ {"baz", FutureApiLevel, true, false, []string{"baz"}, []string{"baz"}, nil, ForPrebuiltApex, nil},
},
wantMerged: []ApexInfo{
- {"apex10000", FutureApiLevel, true, false, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex},
- {"baz", FutureApiLevel, true, false, []string{"baz"}, []string{"baz"}, nil, ForPrebuiltApex},
+ {"apex10000", FutureApiLevel, true, false, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex, nil},
+ {"baz", FutureApiLevel, true, false, []string{"baz"}, []string{"baz"}, nil, ForPrebuiltApex, nil},
},
wantAliases: [][2]string{
{"bar", "apex10000"},
@@ -105,11 +105,11 @@
{
name: "merge different UsePlatformApis but don't allow using platform api",
in: []ApexInfo{
- {"foo", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
- {"bar", FutureApiLevel, false, true, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
+ {"foo", FutureApiLevel, false, false, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex, nil},
+ {"bar", FutureApiLevel, false, true, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex, nil},
},
wantMerged: []ApexInfo{
- {"apex10000", FutureApiLevel, false, false, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex},
+ {"apex10000", FutureApiLevel, false, false, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex, nil},
},
wantAliases: [][2]string{
{"bar", "apex10000"},
@@ -119,11 +119,11 @@
{
name: "merge same UsePlatformApis and allow using platform api",
in: []ApexInfo{
- {"foo", FutureApiLevel, false, true, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
- {"bar", FutureApiLevel, false, true, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
+ {"foo", FutureApiLevel, false, true, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex, nil},
+ {"bar", FutureApiLevel, false, true, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex, nil},
},
wantMerged: []ApexInfo{
- {"apex10000", FutureApiLevel, false, true, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex},
+ {"apex10000", FutureApiLevel, false, true, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex, nil},
},
wantAliases: [][2]string{
{"bar", "apex10000"},
diff --git a/android/api_levels.go b/android/api_levels.go
index 9440ee9..7214ccb 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -55,6 +55,9 @@
}
func (this ApiLevel) FinalInt() int {
+ if this.IsInvalid() {
+ panic(fmt.Errorf("%v is not a recognized api_level\n", this))
+ }
if this.IsPreview() {
panic("Requested a final int from a non-final ApiLevel")
} else {
@@ -63,6 +66,9 @@
}
func (this ApiLevel) FinalOrFutureInt() int {
+ if this.IsInvalid() {
+ panic(fmt.Errorf("%v is not a recognized api_level\n", this))
+ }
if this.IsPreview() {
return FutureApiLevelInt
} else {
@@ -76,6 +82,9 @@
// - preview codenames -> preview base (9000) + index
// - otherwise -> cast to int
func (this ApiLevel) FinalOrPreviewInt() int {
+ if this.IsInvalid() {
+ panic(fmt.Errorf("%v is not a recognized api_level\n", this))
+ }
if this.IsCurrent() {
return this.number
}
@@ -97,6 +106,11 @@
return this.isPreview
}
+// Returns true if the raw api level string is invalid
+func (this ApiLevel) IsInvalid() bool {
+ return this.EqualTo(InvalidApiLevel)
+}
+
// Returns true if this is the unfinalized "current" API level. This means
// different things across Java and native. Java APIs do not use explicit
// codenames, so all non-final codenames are grouped into "current". For native
@@ -113,6 +127,72 @@
return this.number == -1
}
+// Returns true if an app is compiling against private apis.
+// e.g. if sdk_version = "" in Android.bp, then the ApiLevel of that "sdk" is at PrivateApiLevel.
+func (this ApiLevel) IsPrivate() bool {
+ return this.number == PrivateApiLevel.number
+}
+
+// EffectiveVersion converts an ApiLevel into the concrete ApiLevel that the module should use. For
+// modules targeting an unreleased SDK (meaning it does not yet have a number) it returns
+// FutureApiLevel(10000).
+func (l ApiLevel) EffectiveVersion(ctx EarlyModuleContext) (ApiLevel, error) {
+ if l.EqualTo(InvalidApiLevel) {
+ return l, fmt.Errorf("invalid version in sdk_version %q", l.value)
+ }
+ if !l.IsPreview() {
+ return l, nil
+ }
+ ret := ctx.Config().DefaultAppTargetSdk(ctx)
+ if ret.IsPreview() {
+ return FutureApiLevel, nil
+ }
+ return ret, nil
+}
+
+// EffectiveVersionString converts an SdkSpec into the concrete version string that the module
+// should use. For modules targeting an unreleased SDK (meaning it does not yet have a number)
+// it returns the codename (P, Q, R, etc.)
+func (l ApiLevel) EffectiveVersionString(ctx EarlyModuleContext) (string, error) {
+ if l.EqualTo(InvalidApiLevel) {
+ return l.value, fmt.Errorf("invalid version in sdk_version %q", l.value)
+ }
+ if !l.IsPreview() {
+ return l.String(), nil
+ }
+ // Determine the default sdk
+ ret := ctx.Config().DefaultAppTargetSdk(ctx)
+ if !ret.IsPreview() {
+ // If the default sdk has been finalized, return that
+ return ret.String(), nil
+ }
+ // There can be more than one active in-development sdks
+ // If an app is targeting an active sdk, but not the default one, return the requested active sdk.
+ // e.g.
+ // SETUP
+ // In-development: UpsideDownCake, VanillaIceCream
+ // Default: VanillaIceCream
+ // Android.bp
+ // min_sdk_version: `UpsideDownCake`
+ // RETURN
+ // UpsideDownCake and not VanillaIceCream
+ for _, preview := range ctx.Config().PreviewApiLevels() {
+ if l.String() == preview.String() {
+ return preview.String(), nil
+ }
+ }
+ // Otherwise return the default one
+ return ret.String(), nil
+}
+
+// Specified returns true if the module is targeting a recognzized api_level.
+// It returns false if either
+// 1. min_sdk_version is not an int or a recognized codename
+// 2. both min_sdk_version and sdk_version are empty. In this case, MinSdkVersion() defaults to SdkSpecPrivate.ApiLevel
+func (this ApiLevel) Specified() bool {
+ return !this.IsInvalid() && !this.IsPrivate()
+}
+
// Returns -1 if the current API level is less than the argument, 0 if they
// are equal, and 1 if it is greater than the argument.
func (this ApiLevel) CompareTo(other ApiLevel) int {
@@ -166,6 +246,19 @@
isPreview: true,
}
+// Sentinel ApiLevel to validate that an apiLevel is either an int or a recognized codename.
+var InvalidApiLevel = NewInvalidApiLevel("invalid")
+
+// Returns an apiLevel object at the same level as InvalidApiLevel.
+// The object contains the raw string provied in bp file, and can be used for error handling.
+func NewInvalidApiLevel(raw string) ApiLevel {
+ return ApiLevel{
+ value: raw,
+ number: -2, // One less than NoneApiLevel
+ isPreview: true,
+ }
+}
+
// The first version that introduced 64-bit ABIs.
var FirstLp64Version = uncheckedFinalApiLevel(21)
@@ -204,6 +297,16 @@
return strconv.Itoa(num)
}
+// ApiLevelFrom converts the given string `raw` to an ApiLevel.
+// If `raw` is invalid (empty string, unrecognized codename etc.) it returns an invalid ApiLevel
+func ApiLevelFrom(ctx PathContext, raw string) ApiLevel {
+ ret, err := ApiLevelFromUser(ctx, raw)
+ if err != nil {
+ return NewInvalidApiLevel(raw)
+ }
+ return ret
+}
+
// 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.
@@ -241,14 +344,17 @@
}
}
- 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)
+ canonical, ok := getApiLevelsMapReleasedVersions()[raw]
+ if !ok {
+ asInt, err := strconv.Atoi(raw)
+ if err != nil {
+ return NoneApiLevel, fmt.Errorf("%q could not be parsed as an integer and is not a recognized codename", raw)
+ }
+ return uncheckedFinalApiLevel(asInt), nil
}
- apiLevel := uncheckedFinalApiLevel(asInt)
- return apiLevel, nil
+ return uncheckedFinalApiLevel(canonical), nil
+
}
// ApiLevelForTest returns an ApiLevel constructed from the supplied raw string.
@@ -363,7 +469,7 @@
// https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/common/api.bzl;l=23;drc=231c7e8c8038fd478a79eb68aa5b9f5c64e0e061
return config.Once(apiLevelsMapKey, func() interface{} {
apiLevelsMap := getApiLevelsMapReleasedVersions()
- for i, codename := range config.PlatformVersionActiveCodenames() {
+ for i, codename := range config.PlatformVersionAllPreviewCodenames() {
apiLevelsMap[codename] = previewAPILevelBase + i
}
diff --git a/android/arch.go b/android/arch.go
index 6acf9cf..4b4691b 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -1694,6 +1694,7 @@
return []archConfig{
{"arm64", "armv8-a-branchprot", "", []string{"arm64-v8a"}},
{"arm", "armv7-a-neon", "", []string{"armeabi-v7a"}},
+ {"riscv64", "", "", []string{"riscv64"}},
{"x86_64", "", "", []string{"x86_64"}},
{"x86", "", "", []string{"x86"}},
}
diff --git a/android/arch_test.go b/android/arch_test.go
index e445ec6..5021a67 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -401,7 +401,7 @@
{
name: "same arch host and host cross",
preparer: FixtureModifyConfig(func(config Config) {
- modifyTestConfigForMusl(config)
+ ModifyTestConfigForMusl(config)
modifyTestConfigForMuslArm64HostCross(config)
}),
fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"},
@@ -705,7 +705,7 @@
{
name: "linux_musl",
goOS: "linux",
- preparer: FixtureModifyConfig(modifyTestConfigForMusl),
+ preparer: FixtureModifyConfig(ModifyTestConfigForMusl),
results: []result{
{
module: "foo",
diff --git a/android/bazel.go b/android/bazel.go
index b600758..58d9d87 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -32,6 +32,22 @@
Bp2BuildTopLevel = "."
)
+type MixedBuildEnabledStatus int
+
+const (
+ // This module can be mixed_built.
+ MixedBuildEnabled = iota
+
+ // There is a technical incompatibility preventing this module from being
+ // bazel-analyzed. Note: the module might also be incompatible.
+ TechnicalIncompatibility
+
+ // This module cannot be mixed_built due to some incompatibility with it
+ // that is not a platform incompatibility. Example: the module-type is not
+ // enabled, or is not bp2build-converted.
+ ModuleIncompatibility
+)
+
// FileGroupAsLibrary describes a filegroup module that is converted to some library
// such as aidl_library or proto_library.
type FileGroupAsLibrary interface {
@@ -346,21 +362,31 @@
}).(Bp2BuildConversionAllowlist)
}
-// MixedBuildsEnabled returns true if a module is ready to be replaced by a
-// converted or handcrafted Bazel target. As a side effect, calling this
-// method will also log whether this module is mixed build enabled for
-// metrics reporting.
-func MixedBuildsEnabled(ctx BaseModuleContext) bool {
+// MixedBuildsEnabled returns a MixedBuildEnabledStatus regarding whether
+// a module is ready to be replaced by a converted or handcrafted Bazel target.
+// As a side effect, calling this method will also log whether this module is
+// mixed build enabled for metrics reporting.
+func MixedBuildsEnabled(ctx BaseModuleContext) MixedBuildEnabledStatus {
module := ctx.Module()
apexInfo := ctx.Provider(ApexInfoProvider).(ApexInfo)
withinApex := !apexInfo.IsForPlatform()
+
+ platformIncompatible := isPlatformIncompatible(ctx.Os(), ctx.Arch().ArchType)
+ if platformIncompatible {
+ ctx.Config().LogMixedBuild(ctx, false)
+ return TechnicalIncompatibility
+ }
+
mixedBuildEnabled := ctx.Config().IsMixedBuildsEnabled() &&
- ctx.Os() != Windows && // Windows toolchains are not currently supported.
module.Enabled() &&
convertedToBazel(ctx, module) &&
ctx.Config().BazelContext.IsModuleNameAllowed(module.Name(), withinApex)
ctx.Config().LogMixedBuild(ctx, mixedBuildEnabled)
- return mixedBuildEnabled
+
+ if mixedBuildEnabled {
+ return MixedBuildEnabled
+ }
+ return ModuleIncompatibility
}
// ConvertedToBazel returns whether this module has been converted (with bp2build or manually) to Bazel.
@@ -385,6 +411,13 @@
OtherModuleDir(m blueprint.Module) string
}
+func isPlatformIncompatible(osType OsType, arch ArchType) bool {
+ return osType == Windows || // Windows toolchains are not currently supported.
+ osType == LinuxBionic || // Linux Bionic toolchains are not currently supported.
+ osType == LinuxMusl || // Linux musl toolchains are not currently supported (b/259266326).
+ arch == Riscv64 // TODO(b/262192655) Riscv64 toolchains are not currently supported.
+}
+
func (b *BazelModuleBase) shouldConvertWithBp2build(ctx bazelOtherModuleContext, module blueprint.Module) bool {
if !b.bazelProps().Bazel_module.CanConvertToBazel {
return false
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index e7b84e3..dafb610 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -18,7 +18,6 @@
"bytes"
"fmt"
"os"
- "os/exec"
"path"
"path/filepath"
"runtime"
@@ -30,7 +29,6 @@
"android/soong/bazel/cquery"
"android/soong/shared"
"android/soong/starlark_fmt"
-
"github.com/google/blueprint"
"github.com/google/blueprint/metrics"
@@ -63,6 +61,8 @@
"LLVM_NEXT",
"ALLOW_UNKNOWN_WARNING_OPTION",
+ "UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT",
+
// Overrides the version in the apex_manifest.json. The version is unique for
// each branch (internal, aosp, mainline releases, dessert releases). This
// enables modules built on an older branch to be installed against a newer
@@ -84,7 +84,9 @@
func mixedBuildsPrepareMutator(ctx BottomUpMutatorContext) {
if m := ctx.Module(); m.Enabled() {
if mixedBuildMod, ok := m.(MixedBuildBuildable); ok {
- if mixedBuildMod.IsMixedBuildSupported(ctx) && MixedBuildsEnabled(ctx) {
+ mixedBuildEnabled := MixedBuildsEnabled(ctx)
+ queueMixedBuild := mixedBuildMod.IsMixedBuildSupported(ctx) && mixedBuildEnabled == MixedBuildEnabled
+ if queueMixedBuild {
mixedBuildMod.QueueBazelCall(ctx)
}
}
@@ -214,8 +216,7 @@
}
type bazelRunner interface {
- createBazelCommand(config Config, paths *bazelPaths, runName bazel.RunName, command bazelCommand, extraFlags ...string) *exec.Cmd
- issueBazelCommand(bazelCmd *exec.Cmd, eventHandler *metrics.EventHandler) (output string, errorMessage string, error error)
+ issueBazelCommand(cmdRequest bazel.CmdRequest, paths *bazelPaths, eventHandler *metrics.EventHandler) (output string, errorMessage string, error error)
}
type bazelPaths struct {
@@ -654,36 +655,6 @@
expression string
}
-type mockBazelRunner struct {
- bazelCommandResults map[bazelCommand]string
- // use *exec.Cmd as a key to get the bazelCommand, the map will be used in issueBazelCommand()
- // Register createBazelCommand() invocations. Later, an
- // issueBazelCommand() invocation can be mapped to the *exec.Cmd instance
- // and then to the expected result via bazelCommandResults
- tokens map[*exec.Cmd]bazelCommand
- commands []bazelCommand
- extraFlags []string
-}
-
-func (r *mockBazelRunner) createBazelCommand(_ Config, _ *bazelPaths, _ bazel.RunName,
- command bazelCommand, extraFlags ...string) *exec.Cmd {
- r.commands = append(r.commands, command)
- r.extraFlags = append(r.extraFlags, strings.Join(extraFlags, " "))
- cmd := &exec.Cmd{}
- if r.tokens == nil {
- r.tokens = make(map[*exec.Cmd]bazelCommand)
- }
- r.tokens[cmd] = command
- return cmd
-}
-
-func (r *mockBazelRunner) issueBazelCommand(bazelCmd *exec.Cmd, _ *metrics.EventHandler) (string, string, error) {
- if command, ok := r.tokens[bazelCmd]; ok {
- return r.bazelCommandResults[command], "", nil
- }
- return "", "", nil
-}
-
type builtinBazelRunner struct {
useBazelProxy bool
outDir string
@@ -693,17 +664,12 @@
// Returns (stdout, stderr, error). The first and second return values are strings
// containing the stdout and stderr of the run command, and an error is returned if
// the invocation returned an error code.
-func (r *builtinBazelRunner) issueBazelCommand(bazelCmd *exec.Cmd, eventHandler *metrics.EventHandler) (string, string, error) {
+func (r *builtinBazelRunner) issueBazelCommand(cmdRequest bazel.CmdRequest, paths *bazelPaths, eventHandler *metrics.EventHandler) (string, string, error) {
if r.useBazelProxy {
eventHandler.Begin("client_proxy")
defer eventHandler.End("client_proxy")
proxyClient := bazel.NewProxyClient(r.outDir)
- // Omit the arg containing the Bazel binary, as that is handled by the proxy
- // server.
- bazelFlags := bazelCmd.Args[1:]
- // TODO(b/270989498): Refactor these functions to not take exec.Cmd, as its
- // not actually executed for client proxying.
- resp, err := proxyClient.IssueCommand(bazel.CmdRequest{bazelFlags, bazelCmd.Env})
+ resp, err := proxyClient.IssueCommand(cmdRequest)
if err != nil {
return "", "", err
@@ -715,35 +681,19 @@
} else {
eventHandler.Begin("bazel command")
defer eventHandler.End("bazel command")
- stderr := &bytes.Buffer{}
- bazelCmd.Stderr = stderr
- if output, err := bazelCmd.Output(); err != nil {
- return "", string(stderr.Bytes()),
- fmt.Errorf("bazel command failed: %s\n---command---\n%s\n---env---\n%s\n---stderr---\n%s---",
- err, bazelCmd, strings.Join(bazelCmd.Env, "\n"), stderr)
- } else {
- return string(output), string(stderr.Bytes()), nil
- }
+
+ stdout, stderr, err := bazel.ExecBazel(paths.bazelPath, absolutePath(paths.syntheticWorkspaceDir()), cmdRequest)
+ return string(stdout), string(stderr), err
}
}
-func (r *builtinBazelRunner) createBazelCommand(config Config, paths *bazelPaths, runName bazel.RunName, command bazelCommand,
- extraFlags ...string) *exec.Cmd {
+func (context *mixedBuildBazelContext) createBazelCommand(config Config, runName bazel.RunName, command bazelCommand,
+ extraFlags ...string) bazel.CmdRequest {
cmdFlags := []string{
- "--output_base=" + absolutePath(paths.outputBase),
+ "--output_base=" + absolutePath(context.paths.outputBase),
command.command,
command.expression,
- // TODO(asmundak): is it needed in every build?
- "--profile=" + shared.BazelMetricsFilename(paths, runName),
-
- // Set default platforms to canonicalized values for mixed builds requests.
- // If these are set in the bazelrc, they will have values that are
- // non-canonicalized to @sourceroot labels, and thus be invalid when
- // referenced from the buildroot.
- //
- // The actual platform values here may be overridden by configuration
- // transitions from the buildroot.
- fmt.Sprintf("--extra_toolchains=%s", "//prebuilts/clang/host/linux-x86:all"),
+ "--profile=" + shared.BazelMetricsFilename(context.paths, runName),
// We don't need to set --host_platforms because it's set in bazelrc files
// that the bazel shell script wrapper passes
@@ -758,15 +708,13 @@
}
cmdFlags = append(cmdFlags, extraFlags...)
- bazelCmd := exec.Command(paths.bazelPath, cmdFlags...)
- bazelCmd.Dir = absolutePath(paths.syntheticWorkspaceDir())
extraEnv := []string{
- "HOME=" + paths.homeDir,
+ "HOME=" + context.paths.homeDir,
pwdPrefix(),
- "BUILD_DIR=" + absolutePath(paths.soongOutDir),
+ "BUILD_DIR=" + absolutePath(context.paths.soongOutDir),
// Make OUT_DIR absolute here so build/bazel/bin/bazel uses the correct
// OUT_DIR at <root>/out, instead of <root>/out/soong/workspace/out.
- "OUT_DIR=" + absolutePath(paths.outDir()),
+ "OUT_DIR=" + absolutePath(context.paths.outDir()),
// Disables local host detection of gcc; toolchain information is defined
// explicitly in BUILD files.
"BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1",
@@ -778,15 +726,15 @@
}
extraEnv = append(extraEnv, fmt.Sprintf("%s=%s", envvar, val))
}
- bazelCmd.Env = append(os.Environ(), extraEnv...)
+ envVars := append(os.Environ(), extraEnv...)
- return bazelCmd
+ return bazel.CmdRequest{cmdFlags, envVars}
}
-func printableCqueryCommand(bazelCmd *exec.Cmd) string {
- outputString := strings.Join(bazelCmd.Env, " ") + " \"" + strings.Join(bazelCmd.Args, "\" \"") + "\""
+func (context *mixedBuildBazelContext) printableCqueryCommand(bazelCmd bazel.CmdRequest) string {
+ args := append([]string{context.paths.bazelPath}, bazelCmd.Argv...)
+ outputString := strings.Join(bazelCmd.Env, " ") + " \"" + strings.Join(args, "\" \"") + "\""
return outputString
-
}
func (context *mixedBuildBazelContext) mainBzlFileContents() []byte {
@@ -969,9 +917,13 @@
// request type.
func (context *mixedBuildBazelContext) cqueryStarlarkFileContents() []byte {
requestTypeToCqueryIdEntries := map[cqueryRequest][]string{}
+ requestTypes := []cqueryRequest{}
for _, val := range context.requests {
cqueryId := getCqueryId(val)
mapEntryString := fmt.Sprintf("%q : True", cqueryId)
+ if _, seenKey := requestTypeToCqueryIdEntries[val.requestType]; !seenKey {
+ requestTypes = append(requestTypes, val.requestType)
+ }
requestTypeToCqueryIdEntries[val.requestType] =
append(requestTypeToCqueryIdEntries[val.requestType], mapEntryString)
}
@@ -993,7 +945,7 @@
return id_string + ">>" + %s(target, id_string)
`
- for requestType := range requestTypeToCqueryIdEntries {
+ for _, requestType := range requestTypes {
labelMapName := requestType.Name() + "_Labels"
functionName := requestType.Name() + "_Fn"
labelRegistrationMapSection += fmt.Sprintf(mapDeclarationFormatString,
@@ -1009,31 +961,6 @@
formatString := `
# This file is generated by soong_build. Do not edit.
-# a drop-in replacement for json.encode(), not available in cquery environment
-# TODO(cparsons): bring json module in and remove this function
-def json_encode(input):
- # Avoiding recursion by limiting
- # - a dict to contain anything except a dict
- # - a list to contain only primitives
- def encode_primitive(p):
- t = type(p)
- if t == "string" or t == "int":
- return repr(p)
- fail("unsupported value '%s' of type '%s'" % (p, type(p)))
-
- def encode_list(list):
- return "[%s]" % ", ".join([encode_primitive(item) for item in list])
-
- def encode_list_or_primitive(v):
- return encode_list(v) if type(v) == "list" else encode_primitive(v)
-
- if type(input) == "dict":
- # TODO(juu): the result is read line by line so can't use '\n' yet
- kv_pairs = [("%s: %s" % (encode_primitive(k), encode_list_or_primitive(v))) for (k, v) in input.items()]
- return "{ %s }" % ", ".join(kv_pairs)
- else:
- return encode_list_or_primitive(input)
-
{LABEL_REGISTRATION_MAP_SECTION}
{FUNCTION_DEF_SECTION}
@@ -1130,9 +1057,10 @@
const buildrootLabel = "@soong_injection//mixed_builds:buildroot"
var (
- cqueryCmd = bazelCommand{"cquery", fmt.Sprintf("deps(%s, 2)", buildrootLabel)}
- aqueryCmd = bazelCommand{"aquery", fmt.Sprintf("deps(%s)", buildrootLabel)}
- buildCmd = bazelCommand{"build", "@soong_injection//mixed_builds:phonyroot"}
+ cqueryCmd = bazelCommand{"cquery", fmt.Sprintf("deps(%s, 2)", buildrootLabel)}
+ aqueryCmd = bazelCommand{"aquery", fmt.Sprintf("deps(%s)", buildrootLabel)}
+ buildCmd = bazelCommand{"build", "@soong_injection//mixed_builds:phonyroot"}
+ allBazelCommands = []bazelCommand{aqueryCmd, cqueryCmd, buildCmd}
)
// Issues commands to Bazel to receive results for all cquery requests
@@ -1194,12 +1122,12 @@
extraFlags = append(extraFlags, "--collect_code_coverage")
}
- cqueryCommandWithFlag := context.createBazelCommand(config, context.paths, bazel.CqueryBuildRootRunName, cqueryCmd, extraFlags...)
- cqueryOutput, cqueryErrorMessage, cqueryErr := context.issueBazelCommand(cqueryCommandWithFlag, eventHandler)
+ cqueryCmdRequest := context.createBazelCommand(config, bazel.CqueryBuildRootRunName, cqueryCmd, extraFlags...)
+ cqueryOutput, cqueryErrorMessage, cqueryErr := context.issueBazelCommand(cqueryCmdRequest, context.paths, eventHandler)
if cqueryErr != nil {
return cqueryErr
}
- cqueryCommandPrint := fmt.Sprintf("cquery command line:\n %s \n\n\n", printableCqueryCommand(cqueryCommandWithFlag))
+ cqueryCommandPrint := fmt.Sprintf("cquery command line:\n %s \n\n\n", context.printableCqueryCommand(cqueryCmdRequest))
if err := os.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"), []byte(cqueryCommandPrint+cqueryOutput), 0666); err != nil {
return err
}
@@ -1257,8 +1185,8 @@
extraFlags = append(extraFlags, "--instrumentation_filter="+strings.Join(paths, ","))
}
}
- aqueryOutput, _, err := context.issueBazelCommand(context.createBazelCommand(config, context.paths, bazel.AqueryBuildRootRunName, aqueryCmd,
- extraFlags...), eventHandler)
+ aqueryOutput, _, err := context.issueBazelCommand(context.createBazelCommand(config, bazel.AqueryBuildRootRunName, aqueryCmd,
+ extraFlags...), context.paths, eventHandler)
if err != nil {
return err
}
@@ -1273,7 +1201,7 @@
// Issue a build command of the phony root to generate symlink forests for dependencies of the
// Bazel build. This is necessary because aquery invocations do not generate this symlink forest,
// but some of symlinks may be required to resolve source dependencies of the build.
- _, _, err := context.issueBazelCommand(context.createBazelCommand(config, context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd), eventHandler)
+ _, _, err := context.issueBazelCommand(context.createBazelCommand(config, bazel.BazelBuildPhonyRootRunName, buildCmd), context.paths, eventHandler)
return err
}
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index c67d7fb..b17b765 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -8,6 +8,7 @@
"strings"
"testing"
+ "android/soong/bazel"
"android/soong/bazel/cquery"
analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
@@ -19,6 +20,34 @@
type testInvokeBazelContext struct{}
+type mockBazelRunner struct {
+ testHelper *testing.T
+ // Stores mock behavior. If an issueBazelCommand request is made for command
+ // k, and {k:v} is present in this map, then the mock will return v.
+ bazelCommandResults map[bazelCommand]string
+ // Requests actually made of the mockBazelRunner with issueBazelCommand,
+ // keyed by the command they represent.
+ bazelCommandRequests map[bazelCommand]bazel.CmdRequest
+}
+
+func (r *mockBazelRunner) bazelCommandForRequest(cmdRequest bazel.CmdRequest) bazelCommand {
+ for _, arg := range cmdRequest.Argv {
+ for _, cmdType := range allBazelCommands {
+ if arg == cmdType.command {
+ return cmdType
+ }
+ }
+ }
+ r.testHelper.Fatalf("Unrecognized bazel request: %s", cmdRequest)
+ return cqueryCmd
+}
+
+func (r *mockBazelRunner) issueBazelCommand(cmdRequest bazel.CmdRequest, paths *bazelPaths, eventHandler *metrics.EventHandler) (string, string, error) {
+ command := r.bazelCommandForRequest(cmdRequest)
+ r.bazelCommandRequests[command] = cmdRequest
+ return r.bazelCommandResults[command], "", nil
+}
+
func (t *testInvokeBazelContext) GetEventHandler() *metrics.EventHandler {
return &metrics.EventHandler{}
}
@@ -36,9 +65,7 @@
`@//foo:foo|arm64_armv8-a|android|within_apex|29>>out/foo/foo.txt`,
`@//foo:bar|arm64_armv8-a|android>>out/foo/bar.txt`,
}
- bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
- bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: strings.Join(cmd_results, "\n"),
- })
+ bazelContext, _ := testBazelContext(t, map[bazelCommand]string{cqueryCmd: strings.Join(cmd_results, "\n")})
bazelContext.QueueBazelRequest(label_foo, cquery.GetOutputFiles, cfg_foo)
bazelContext.QueueBazelRequest(label_bar, cquery.GetOutputFiles, cfg_bar)
@@ -139,8 +166,7 @@
if err != nil {
t.Error(err)
}
- bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
- bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: string(data)})
+ bazelContext, _ := testBazelContext(t, map[bazelCommand]string{aqueryCmd: string(data)})
err = bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
if err != nil {
@@ -166,30 +192,26 @@
testConfig.productVariables.NativeCoveragePaths = []string{"foo1", "foo2"}
testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1", "bar2"}
- verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+foo1,+foo2,-bar1,-bar2`)
+ verifyAqueryContainsFlags(t, testConfig, "--collect_code_coverage", "--instrumentation_filter=+foo1,+foo2,-bar1,-bar2")
testConfig.productVariables.NativeCoveragePaths = []string{"foo1"}
testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
- verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+foo1,-bar1`)
+ verifyAqueryContainsFlags(t, testConfig, "--collect_code_coverage", "--instrumentation_filter=+foo1,-bar1")
testConfig.productVariables.NativeCoveragePaths = []string{"foo1"}
testConfig.productVariables.NativeCoverageExcludePaths = nil
- verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+foo1`)
+ verifyAqueryContainsFlags(t, testConfig, "--collect_code_coverage", "--instrumentation_filter=+foo1")
testConfig.productVariables.NativeCoveragePaths = nil
testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
- verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=-bar1`)
+ verifyAqueryContainsFlags(t, testConfig, "--collect_code_coverage", "--instrumentation_filter=-bar1")
testConfig.productVariables.NativeCoveragePaths = []string{"*"}
testConfig.productVariables.NativeCoverageExcludePaths = nil
- verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+.*`)
+ verifyAqueryContainsFlags(t, testConfig, "--collect_code_coverage", "--instrumentation_filter=+.*")
testConfig.productVariables.ClangCoverage = boolPtr(false)
- actual := verifyExtraFlags(t, testConfig, ``)
- if strings.Contains(actual, "--collect_code_coverage") ||
- strings.Contains(actual, "--instrumentation_filter=") {
- t.Errorf("Expected code coverage disabled, but got %#v", actual)
- }
+ verifyAqueryDoesNotContainSubstrings(t, testConfig, "collect_code_coverage", "instrumentation_filter")
}
func TestBazelRequestsSorted(t *testing.T) {
@@ -268,7 +290,8 @@
}
}
-func verifyExtraFlags(t *testing.T, config Config, expected string) string {
+func verifyAqueryContainsFlags(t *testing.T, config Config, expected ...string) {
+ t.Helper()
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
err := bazelContext.InvokeBazel(config, &testInvokeBazelContext{})
@@ -276,17 +299,49 @@
t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
}
- flags := bazelContext.bazelRunner.(*mockBazelRunner).extraFlags
- if expected := 3; len(flags) != expected {
- t.Errorf("Expected %d extra flags got %#v", expected, flags)
+ sliceContains := func(slice []string, x string) bool {
+ for _, s := range slice {
+ if s == x {
+ return true
+ }
+ }
+ return false
}
- actual := flags[1]
- if !strings.Contains(actual, expected) {
- t.Errorf("Expected %#v got %#v", expected, actual)
+ aqueryArgv := bazelContext.bazelRunner.(*mockBazelRunner).bazelCommandRequests[aqueryCmd].Argv
+
+ for _, expectedFlag := range expected {
+ if !sliceContains(aqueryArgv, expectedFlag) {
+ t.Errorf("aquery does not contain expected flag %#v. Argv was: %#v", expectedFlag, aqueryArgv)
+ }
+ }
+}
+
+func verifyAqueryDoesNotContainSubstrings(t *testing.T, config Config, substrings ...string) {
+ t.Helper()
+ bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
+
+ err := bazelContext.InvokeBazel(config, &testInvokeBazelContext{})
+ if err != nil {
+ t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
}
- return actual
+ sliceContainsSubstring := func(slice []string, substring string) bool {
+ for _, s := range slice {
+ if strings.Contains(s, substring) {
+ return true
+ }
+ }
+ return false
+ }
+
+ aqueryArgv := bazelContext.bazelRunner.(*mockBazelRunner).bazelCommandRequests[aqueryCmd].Argv
+
+ for _, substring := range substrings {
+ if sliceContainsSubstring(aqueryArgv, substring) {
+ t.Errorf("aquery contains unexpected substring %#v. Argv was: %#v", substring, aqueryArgv)
+ }
+ }
}
func testBazelContext(t *testing.T, bazelCommandResults map[bazelCommand]string) (*mixedBuildBazelContext, string) {
@@ -296,11 +351,14 @@
outputBase: "outputbase",
workspaceDir: "workspace_dir",
}
- aqueryCommand := bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}
- if _, exists := bazelCommandResults[aqueryCommand]; !exists {
- bazelCommandResults[aqueryCommand] = ""
+ if _, exists := bazelCommandResults[aqueryCmd]; !exists {
+ bazelCommandResults[aqueryCmd] = ""
}
- runner := &mockBazelRunner{bazelCommandResults: bazelCommandResults}
+ runner := &mockBazelRunner{
+ testHelper: t,
+ bazelCommandResults: bazelCommandResults,
+ bazelCommandRequests: map[bazelCommand]bazel.CmdRequest{},
+ }
return &mixedBuildBazelContext{
bazelRunner: runner,
paths: &p,
diff --git a/android/config.go b/android/config.go
index b37d5c8..0b54ed9 100644
--- a/android/config.go
+++ b/android/config.go
@@ -52,6 +52,15 @@
// FutureApiLevelInt is a placeholder constant for unreleased API levels.
const FutureApiLevelInt = 10000
+// PrivateApiLevel represents the api level of SdkSpecPrivate (sdk_version: "")
+// This api_level exists to differentiate user-provided "" from "current" sdk_version
+// The differentiation is necessary to enable different validation rules for these two possible values.
+var PrivateApiLevel = ApiLevel{
+ value: "current", // The value is current since aidl expects `current` as the default (TestAidlFlagsWithMinSdkVersion)
+ number: FutureApiLevelInt + 1, // This is used to differentiate it from FutureApiLevel
+ isPreview: true,
+}
+
// FutureApiLevel represents unreleased API levels.
var FutureApiLevel = ApiLevel{
value: "current",
@@ -83,12 +92,18 @@
ModuleActionsFile string
DocFile string
+ MultitreeBuild bool
+
BazelMode bool
BazelModeDev bool
BazelModeStaging bool
BazelForceEnabledModules string
UseBazelProxy bool
+
+ BuildFromTextStub bool
+
+ EnsureAllowlistIntegrity bool
}
// Build modes that soong_build can run as.
@@ -161,6 +176,13 @@
return c.config.TestProductVariables != nil
}
+// MaxPageSizeSupported returns the max page size supported by the device. This
+// value will define the ELF segment alignment for binaries (executables and
+// shared libraries).
+func (c Config) MaxPageSizeSupported() string {
+ return String(c.config.productVariables.DeviceMaxPageSizeSupported)
+}
+
// A DeviceConfig object represents the configuration for a particular device
// being built. For now there will only be one of these, but in the future there
// may be multiple devices being built.
@@ -229,6 +251,10 @@
Bp2buildPackageConfig Bp2BuildConversionAllowlist
Bp2buildSoongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions
+ // If MultitreeBuild is true then this is one inner tree of a multitree
+ // build directed by the multitree orchestrator.
+ MultitreeBuild bool
+
// If testAllowNonExistentPaths is true then PathForSource and PathForModuleSrc won't error
// in tests when a path doesn't exist.
TestAllowNonExistentPaths bool
@@ -257,6 +283,15 @@
// If true, for any requests to Bazel, communicate with a Bazel proxy using
// unix sockets, instead of spawning Bazel as a subprocess.
UseBazelProxy bool
+
+ // If buildFromTextStub is true then the Java API stubs are
+ // built from the signature text files, not the source Java files.
+ buildFromTextStub bool
+
+ // If ensureAllowlistIntegrity is true, then the presence of any allowlisted
+ // modules that aren't mixed-built for at least one variant will cause a build
+ // failure
+ ensureAllowlistIntegrity bool
}
type deviceConfig struct {
@@ -399,6 +434,8 @@
fmt.Sprintf(`_arch_variant_product_var_constraints = %s`, archVariantProductVariablesJson),
"\n", `
product_vars = _product_vars
+
+# TODO(b/269577299) Remove these when everything switches over to loading them from product_variable_constants.bzl
product_var_constraints = _product_var_constraints
arch_variant_product_var_constraints = _arch_variant_product_var_constraints
`,
@@ -408,6 +445,13 @@
if err != nil {
return fmt.Errorf("Could not write .bzl config file %s", err)
}
+ err = pathtools.WriteFileIfChanged(filepath.Join(dir, "product_variable_constants.bzl"), []byte(fmt.Sprintf(`
+product_var_constraints = %s
+arch_variant_product_var_constraints = %s
+`, nonArchVariantProductVariablesJson, archVariantProductVariablesJson)), 0644)
+ if err != nil {
+ return fmt.Errorf("Could not write .bzl config file %s", err)
+ }
err = pathtools.WriteFileIfChanged(filepath.Join(dir, "BUILD"),
[]byte(bazel.GeneratedBazelFileWarning), 0644)
if err != nil {
@@ -449,7 +493,10 @@
mixedBuildEnabledModules: make(map[string]struct{}),
bazelForceEnabledModules: make(map[string]struct{}),
- UseBazelProxy: cmdArgs.UseBazelProxy,
+ MultitreeBuild: cmdArgs.MultitreeBuild,
+ UseBazelProxy: cmdArgs.UseBazelProxy,
+
+ buildFromTextStub: cmdArgs.BuildFromTextStub,
}
config.deviceConfig = &deviceConfig{
@@ -559,12 +606,11 @@
setBazelMode(cmdArgs.BazelMode, "--bazel-mode", BazelProdMode)
setBazelMode(cmdArgs.BazelModeStaging, "--bazel-mode-staging", BazelStagingMode)
- config.BazelContext, err = NewBazelContext(config)
- config.Bp2buildPackageConfig = GetBp2BuildAllowList()
-
for _, module := range strings.Split(cmdArgs.BazelForceEnabledModules, ",") {
config.bazelForceEnabledModules[module] = struct{}{}
}
+ config.BazelContext, err = NewBazelContext(config)
+ config.Bp2buildPackageConfig = GetBp2BuildAllowList()
return Config{config}, err
}
@@ -800,6 +846,10 @@
return uncheckedFinalApiLevel(*c.productVariables.Platform_sdk_version)
}
+func (c *config) RawPlatformSdkVersion() *int {
+ return c.productVariables.Platform_sdk_version
+}
+
func (c *config) PlatformSdkFinal() bool {
return Bool(c.productVariables.Platform_sdk_final)
}
@@ -889,8 +939,16 @@
return c.PlatformSdkVersion()
}
codename := c.PlatformSdkCodename()
+ hostOnlyBuild := c.productVariables.DeviceArch == nil
if codename == "" {
- return NoneApiLevel
+ // There are some host-only builds (those are invoked by build-prebuilts.sh) which
+ // don't set platform sdk codename. Platform sdk codename makes sense only when we
+ // are building the platform. So we don't enforce the below panic for the host-only
+ // builds.
+ if hostOnlyBuild {
+ return NoneApiLevel
+ }
+ panic("Platform_sdk_codename must be set")
}
if codename == "REL" {
panic("Platform_sdk_codename should not be REL when Platform_sdk_final is true")
@@ -907,6 +965,11 @@
return c.productVariables.Platform_version_active_codenames
}
+// All unreleased codenames.
+func (c *config) PlatformVersionAllPreviewCodenames() []string {
+ return c.productVariables.Platform_version_all_preview_codenames
+}
+
func (c *config) ProductAAPTConfig() []string {
return c.productVariables.AAPTConfig
}
@@ -1163,6 +1226,10 @@
return append([]string(nil), c.productVariables.NamespacesToExport...)
}
+func (c *config) SourceRootDirs() []string {
+ return c.productVariables.SourceRootDirs
+}
+
func (c *config) IncludeTags() []string {
return c.productVariables.IncludeTags
}
@@ -1369,6 +1436,11 @@
}
}
if coverage && len(c.config.productVariables.NativeCoverageExcludePaths) > 0 {
+ // Workaround coverage boot failure.
+ // http://b/269981180
+ if strings.HasPrefix(path, "external/protobuf") {
+ coverage = false
+ }
if HasAnyPrefix(path, c.config.productVariables.NativeCoverageExcludePaths) {
coverage = false
}
@@ -1380,6 +1452,21 @@
return c.config.productVariables.PgoAdditionalProfileDirs
}
+// AfdoProfile returns fully qualified path associated to the given module name
+func (c *deviceConfig) AfdoProfile(name string) (*string, error) {
+ for _, afdoProfile := range c.config.productVariables.AfdoProfiles {
+ split := strings.Split(afdoProfile, ":")
+ if len(split) != 3 {
+ return nil, fmt.Errorf("AFDO_PROFILES has invalid value: %s. "+
+ "The expected format is <module>:<fully-qualified-path-to-fdo_profile>", afdoProfile)
+ }
+ if split[0] == name {
+ return proptools.StringPtr(strings.Join([]string{split[1], split[2]}, ":")), nil
+ }
+ }
+ return nil, nil
+}
+
func (c *deviceConfig) VendorSepolicyDirs() []string {
return c.config.productVariables.BoardVendorSepolicyDirs
}
@@ -1484,6 +1571,13 @@
return HasAnyPrefix(path, c.productVariables.MemtagHeapSyncIncludePaths) && !c.MemtagHeapDisabledForPath(path)
}
+func (c *config) HWASanEnabledForPath(path string) bool {
+ if len(c.productVariables.HWASanIncludePaths) == 0 {
+ return false
+ }
+ return HasAnyPrefix(path, c.productVariables.HWASanIncludePaths)
+}
+
func (c *config) VendorConfig(name string) VendorConfig {
return soongconfig.Config(c.productVariables.VendorVars[name])
}
@@ -1759,6 +1853,10 @@
return c.config.productVariables.BuildBrokenTrebleSyspropNeverallow
}
+func (c *deviceConfig) BuildBrokenUsesSoongPython2Modules() bool {
+ return c.config.productVariables.BuildBrokenUsesSoongPython2Modules
+}
+
func (c *deviceConfig) BuildDebugfsRestrictionsEnabled() bool {
return c.config.productVariables.BuildDebugfsRestrictionsEnabled
}
@@ -1827,6 +1925,10 @@
return Bool(c.productVariables.HostMusl)
}
+func (c *config) GetMixedBuildsEnabledModules() map[string]struct{} {
+ return c.mixedBuildEnabledModules
+}
+
func (c *config) LogMixedBuild(ctx BaseModuleContext, useBazel bool) {
moduleName := ctx.Module().Name()
c.mixedBuildsLock.Lock()
@@ -1837,3 +1939,27 @@
c.mixedBuildDisabledModules[moduleName] = struct{}{}
}
}
+
+// ApiSurfaces directory returns the source path inside the api_surfaces repo
+// (relative to workspace root).
+func (c *config) ApiSurfacesDir(s ApiSurface, version string) string {
+ return filepath.Join(
+ "build",
+ "bazel",
+ "api_surfaces",
+ s.String(),
+ version)
+}
+
+func (c *config) BuildFromTextStub() bool {
+ return c.buildFromTextStub
+}
+
+func (c *config) SetBuildFromTextStub(b bool) {
+ c.buildFromTextStub = b
+}
+func (c *config) AddForceEnabledModules(forceEnabled []string) {
+ for _, forceEnabledModule := range forceEnabled {
+ c.bazelForceEnabledModules[forceEnabledModule] = struct{}{}
+ }
+}
diff --git a/android/defaults.go b/android/defaults.go
index a821b28..31d6014 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -15,8 +15,6 @@
package android
import (
- "bytes"
- "fmt"
"reflect"
"github.com/google/blueprint"
@@ -69,11 +67,9 @@
// Set the property structures into which defaults will be added.
setProperties(props []interface{}, variableProperties interface{})
- // Apply defaults from the supplied DefaultsModule to the property structures supplied to
+ // Apply defaults from the supplied Defaults to the property structures supplied to
// setProperties(...).
- applyDefaults(TopDownMutatorContext, []DefaultsModule)
-
- applySingleDefaultsWithTracker(EarlyModuleContext, DefaultsModule, defaultsTrackerFunc)
+ applyDefaults(TopDownMutatorContext, []Defaults)
// Set the hook to be called after any defaults have been applied.
//
@@ -119,23 +115,9 @@
Defaults_visibility []string
}
-// AdditionalDefaultsProperties contains properties of defaults modules which
-// can have other defaults applied.
-type AdditionalDefaultsProperties struct {
-
- // The list of properties set by the default whose values must not be changed by any module that
- // applies these defaults. It is an error if a property is not supported by the defaults module or
- // has not been set to a non-zero value. If this contains "*" then that must be the only entry in
- // which case all properties that are set on this defaults will be protected (except the
- // protected_properties and visibility.
- Protected_properties []string
-}
-
type DefaultsModuleBase struct {
DefaultableModuleBase
- defaultsProperties AdditionalDefaultsProperties
-
// Included to support setting bazel_module.label for multiple Soong modules to the same Bazel
// target. This is primarily useful for modules that were architecture specific and instead are
// handled in Bazel as a select().
@@ -169,18 +151,6 @@
// DefaultsModuleBase will type-assert to the Defaults interface.
isDefaults() bool
- // additionalDefaultableProperties returns additional properties provided by the defaults which
- // can themselves have defaults applied.
- additionalDefaultableProperties() []interface{}
-
- // protectedProperties returns the names of the properties whose values cannot be changed by a
- // module that applies these defaults.
- protectedProperties() []string
-
- // setProtectedProperties sets the names of the properties whose values cannot be changed by a
- // module that applies these defaults.
- setProtectedProperties(protectedProperties []string)
-
// Get the structures containing the properties for which defaults can be provided.
properties() []interface{}
@@ -197,18 +167,6 @@
Bazelable
}
-func (d *DefaultsModuleBase) additionalDefaultableProperties() []interface{} {
- return []interface{}{&d.defaultsProperties}
-}
-
-func (d *DefaultsModuleBase) protectedProperties() []string {
- return d.defaultsProperties.Protected_properties
-}
-
-func (d *DefaultsModuleBase) setProtectedProperties(protectedProperties []string) {
- d.defaultsProperties.Protected_properties = protectedProperties
-}
-
func (d *DefaultsModuleBase) properties() []interface{} {
return d.defaultableProperties
}
@@ -232,10 +190,6 @@
&ApexProperties{},
&distProperties{})
- // Additional properties of defaults modules that can themselves have
- // defaults applied.
- module.AddProperties(module.additionalDefaultableProperties()...)
-
// Bazel module must be initialized _before_ Defaults to be included in cc_defaults module.
InitBazelModule(module)
initAndroidModuleBase(module)
@@ -263,58 +217,6 @@
// The applicable licenses property for defaults is 'licenses'.
setPrimaryLicensesProperty(module, "licenses", &commonProperties.Licenses)
-
- AddLoadHook(module, func(ctx LoadHookContext) {
-
- protectedProperties := module.protectedProperties()
- if len(protectedProperties) == 0 {
- return
- }
-
- propertiesAvailable := map[string]struct{}{}
- propertiesSet := map[string]struct{}{}
-
- // A defaults tracker which will keep track of which properties have been set on this module.
- collector := func(defaults DefaultsModule, property string, dstValue interface{}, srcValue interface{}) bool {
- value := reflect.ValueOf(dstValue)
- propertiesAvailable[property] = struct{}{}
- if !value.IsZero() {
- propertiesSet[property] = struct{}{}
- }
- // Skip all the properties so that there are no changes to the defaults.
- return false
- }
-
- // Try and apply this module's defaults to itself, so that the properties can be collected but
- // skip all the properties so it doesn't actually do anything.
- module.applySingleDefaultsWithTracker(ctx, module, collector)
-
- if InList("*", protectedProperties) {
- if len(protectedProperties) != 1 {
- ctx.PropertyErrorf("protected_properties", `if specified then "*" must be the only property listed`)
- return
- }
-
- // Do not automatically protect the protected_properties property.
- delete(propertiesSet, "protected_properties")
-
- // Or the visibility property.
- delete(propertiesSet, "visibility")
-
- // Replace the "*" with the names of all the properties that have been set.
- protectedProperties = SortedKeys(propertiesSet)
- module.setProtectedProperties(protectedProperties)
- } else {
- for _, property := range protectedProperties {
- if _, ok := propertiesAvailable[property]; !ok {
- ctx.PropertyErrorf(property, "property is not supported by this module type %q",
- ctx.ModuleType())
- } else if _, ok := propertiesSet[property]; !ok {
- ctx.PropertyErrorf(property, "is not set; protected properties must be explicitly set")
- }
- }
- }
- })
}
var _ Defaults = (*DefaultsModuleBase)(nil)
@@ -366,204 +268,35 @@
b.setNamespacedVariableProps(dst)
}
-// defaultValueInfo contains information about each default value that applies to a protected
-// property.
-type defaultValueInfo struct {
- // The DefaultsModule providing the value, which may be defined on that module or applied as a
- // default from other modules.
- module Module
-
- // The default value, as returned by getComparableValue
- defaultValue reflect.Value
-}
-
-// protectedPropertyInfo contains information about each property that has to be protected when
-// applying defaults.
-type protectedPropertyInfo struct {
- // True if the property was set on the module to which defaults are applied, this is an error.
- propertySet bool
-
- // The original value of the property on the module, as returned by getComparableValue.
- originalValue reflect.Value
-
- // A list of defaults for the property that are being applied.
- defaultValues []defaultValueInfo
-}
-
-// getComparableValue takes a reflect.Value that may be a pointer to another value and returns a
-// reflect.Value to the underlying data or the original if was not a pointer or was nil. The
-// returned values can then be compared for equality.
-func getComparableValue(value reflect.Value) reflect.Value {
- if value.IsZero() {
- return value
- }
- for value.Kind() == reflect.Ptr {
- value = value.Elem()
- }
- return value
-}
-
func (defaultable *DefaultableModuleBase) applyDefaults(ctx TopDownMutatorContext,
- defaultsList []DefaultsModule) {
-
- // Collate information on all the properties protected by each of the default modules applied
- // to this module.
- allProtectedProperties := map[string]*protectedPropertyInfo{}
- for _, defaults := range defaultsList {
- for _, property := range defaults.protectedProperties() {
- info := allProtectedProperties[property]
- if info == nil {
- info = &protectedPropertyInfo{}
- allProtectedProperties[property] = info
- }
- }
- }
-
- // If there are any protected properties then collate information about attempts to change them.
- var protectedPropertyInfoCollector defaultsTrackerFunc
- if len(allProtectedProperties) > 0 {
- protectedPropertyInfoCollector = func(defaults DefaultsModule, property string,
- dstValue interface{}, srcValue interface{}) bool {
-
- // If the property is not protected then return immediately.
- info := allProtectedProperties[property]
- if info == nil {
- return true
- }
-
- currentValue := reflect.ValueOf(dstValue)
- if info.defaultValues == nil {
- info.propertySet = !currentValue.IsZero()
- info.originalValue = getComparableValue(currentValue)
- }
-
- defaultValue := reflect.ValueOf(srcValue)
- if !defaultValue.IsZero() {
- info.defaultValues = append(info.defaultValues,
- defaultValueInfo{defaults, getComparableValue(defaultValue)})
- }
-
- return true
- }
- }
+ defaultsList []Defaults) {
for _, defaults := range defaultsList {
if ctx.Config().BuildMode == Bp2build {
applyNamespacedVariableDefaults(defaults, ctx)
}
-
- defaultable.applySingleDefaultsWithTracker(ctx, defaults, protectedPropertyInfoCollector)
- }
-
- // Check the status of any protected properties.
- for property, info := range allProtectedProperties {
- if len(info.defaultValues) == 0 {
- // No defaults were applied to the protected properties. Possibly because this module type
- // does not support any of them.
- continue
- }
-
- // Check to make sure that there are no conflicts between the defaults.
- conflictingDefaults := false
- previousDefaultValue := reflect.ValueOf(false)
- for _, defaultInfo := range info.defaultValues {
- defaultValue := defaultInfo.defaultValue
- if previousDefaultValue.IsZero() {
- previousDefaultValue = defaultValue
- } else if !reflect.DeepEqual(previousDefaultValue.Interface(), defaultValue.Interface()) {
- conflictingDefaults = true
- break
- }
- }
-
- if conflictingDefaults {
- var buf bytes.Buffer
- for _, defaultInfo := range info.defaultValues {
- buf.WriteString(fmt.Sprintf("\n defaults module %q provides value %#v",
- ctx.OtherModuleName(defaultInfo.module), defaultInfo.defaultValue))
- }
- result := buf.String()
- ctx.ModuleErrorf("has conflicting default values for protected property %q:%s", property, result)
- continue
- }
-
- // Now check to see whether there the current module tried to override/append to the defaults.
- if info.propertySet {
- originalValue := info.originalValue
- // Just compare against the first defaults.
- defaultValue := info.defaultValues[0].defaultValue
- defaults := info.defaultValues[0].module
-
- if originalValue.Kind() == reflect.Slice {
- ctx.ModuleErrorf("attempts to append %q to protected property %q's value of %q defined in module %q",
- originalValue,
- property,
- defaultValue,
- ctx.OtherModuleName(defaults))
+ for _, prop := range defaultable.defaultableProperties {
+ if prop == defaultable.defaultableVariableProperties {
+ defaultable.applyDefaultVariableProperties(ctx, defaults, prop)
} else {
- same := reflect.DeepEqual(originalValue.Interface(), defaultValue.Interface())
- message := ""
- if same {
- message = fmt.Sprintf(" with a matching value (%#v) so this property can simply be removed.", originalValue)
- } else {
- message = fmt.Sprintf(" with a different value (override %#v with %#v) so removing the property may necessitate other changes.", defaultValue, originalValue)
- }
- ctx.ModuleErrorf("attempts to override protected property %q defined in module %q%s",
- property,
- ctx.OtherModuleName(defaults), message)
+ defaultable.applyDefaultProperties(ctx, defaults, prop)
}
}
}
}
-func (defaultable *DefaultableModuleBase) applySingleDefaultsWithTracker(ctx EarlyModuleContext, defaults DefaultsModule, tracker defaultsTrackerFunc) {
- for _, prop := range defaultable.defaultableProperties {
- var err error
- if prop == defaultable.defaultableVariableProperties {
- err = defaultable.applyDefaultVariableProperties(defaults, prop, tracker)
- } else {
- err = defaultable.applyDefaultProperties(defaults, prop, tracker)
- }
- if err != nil {
- if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
- ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
- } else {
- panic(err)
- }
- }
- }
-}
-
-// defaultsTrackerFunc is the type of a function that can be used to track how defaults are applied.
-type defaultsTrackerFunc func(defaults DefaultsModule, property string,
- dstValue interface{}, srcValue interface{}) bool
-
-// filterForTracker wraps a defaultsTrackerFunc in a proptools.ExtendPropertyFilterFunc
-func filterForTracker(defaults DefaultsModule, tracker defaultsTrackerFunc) proptools.ExtendPropertyFilterFunc {
- if tracker == nil {
- return nil
- }
- return func(property string,
- dstField, srcField reflect.StructField,
- dstValue, srcValue interface{}) (bool, error) {
-
- apply := tracker(defaults, property, dstValue, srcValue)
- return apply, nil
- }
-}
-
// Product variable properties need special handling, the type of the filtered product variable
// property struct may not be identical between the defaults module and the defaultable module.
// Use PrependMatchingProperties to apply whichever properties match.
-func (defaultable *DefaultableModuleBase) applyDefaultVariableProperties(defaults DefaultsModule,
- defaultableProp interface{}, tracker defaultsTrackerFunc) error {
+func (defaultable *DefaultableModuleBase) applyDefaultVariableProperties(ctx TopDownMutatorContext,
+ defaults Defaults, defaultableProp interface{}) {
if defaultableProp == nil {
- return nil
+ return
}
defaultsProp := defaults.productVariableProperties()
if defaultsProp == nil {
- return nil
+ return
}
dst := []interface{}{
@@ -573,26 +306,31 @@
proptools.CloneEmptyProperties(reflect.ValueOf(defaultsProp)).Interface(),
}
- filter := filterForTracker(defaults, tracker)
-
- return proptools.PrependMatchingProperties(dst, defaultsProp, filter)
+ err := proptools.PrependMatchingProperties(dst, defaultsProp, nil)
+ if err != nil {
+ if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
+ ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+ } else {
+ panic(err)
+ }
+ }
}
-func (defaultable *DefaultableModuleBase) applyDefaultProperties(defaults DefaultsModule,
- defaultableProp interface{}, checker defaultsTrackerFunc) error {
-
- filter := filterForTracker(defaults, checker)
+func (defaultable *DefaultableModuleBase) applyDefaultProperties(ctx TopDownMutatorContext,
+ defaults Defaults, defaultableProp interface{}) {
for _, def := range defaults.properties() {
if proptools.TypeEqual(defaultableProp, def) {
- err := proptools.PrependProperties(defaultableProp, def, filter)
+ err := proptools.PrependProperties(defaultableProp, def, nil)
if err != nil {
- return err
+ if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
+ ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+ } else {
+ panic(err)
+ }
}
}
}
-
- return nil
}
func RegisterDefaultsPreArchMutators(ctx RegisterMutatorsContext) {
@@ -609,12 +347,12 @@
func defaultsMutator(ctx TopDownMutatorContext) {
if defaultable, ok := ctx.Module().(Defaultable); ok {
if len(defaultable.defaults().Defaults) > 0 {
- var defaultsList []DefaultsModule
+ var defaultsList []Defaults
seen := make(map[Defaults]bool)
ctx.WalkDeps(func(module, parent Module) bool {
if ctx.OtherModuleDependencyTag(module) == DefaultsDepTag {
- if defaults, ok := module.(DefaultsModule); ok {
+ if defaults, ok := module.(Defaults); ok {
if !seen[defaults] {
seen[defaults] = true
defaultsList = append(defaultsList, defaults)
diff --git a/android/defaults_test.go b/android/defaults_test.go
index d80f40c..a7542ab 100644
--- a/android/defaults_test.go
+++ b/android/defaults_test.go
@@ -19,14 +19,7 @@
)
type defaultsTestProperties struct {
- Foo []string
- Bar []string
- Nested struct {
- Fizz *bool
- }
- Other struct {
- Buzz *string
- }
+ Foo []string
}
type defaultsTestModule struct {
@@ -137,167 +130,3 @@
// TODO: missing transitive defaults is currently not handled
_ = missingTransitiveDefaults
}
-
-func TestProtectedProperties_ProtectedPropertyNotSet(t *testing.T) {
- bp := `
- defaults {
- name: "transitive",
- protected_properties: ["foo"],
- }
- `
-
- GroupFixturePreparers(
- prepareForDefaultsTest,
- FixtureWithRootAndroidBp(bp),
- ).ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(
- "module \"transitive\": foo: is not set; protected properties must be explicitly set")).
- RunTest(t)
-}
-
-func TestProtectedProperties_ProtectedPropertyNotLeaf(t *testing.T) {
- bp := `
- defaults {
- name: "transitive",
- protected_properties: ["nested"],
- nested: {
- fizz: true,
- },
- }
- `
-
- GroupFixturePreparers(
- prepareForDefaultsTest,
- FixtureWithRootAndroidBp(bp),
- ).ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(
- `\Qmodule "transitive": nested: property is not supported by this module type "defaults"\E`)).
- RunTest(t)
-}
-
-// TestProtectedProperties_ApplyDefaults makes sure that the protected_properties property has
-// defaults applied.
-func TestProtectedProperties_HasDefaultsApplied(t *testing.T) {
-
- bp := `
- defaults {
- name: "transitive",
- protected_properties: ["foo"],
- foo: ["transitive"],
- }
-
- defaults {
- name: "defaults",
- defaults: ["transitive"],
- protected_properties: ["bar"],
- bar: ["defaults"],
- }
- `
-
- result := GroupFixturePreparers(
- prepareForDefaultsTest,
- FixtureWithRootAndroidBp(bp),
- ).RunTest(t)
-
- defaults := result.Module("defaults", "").(DefaultsModule)
- AssertDeepEquals(t, "defaults protected properties", []string{"foo", "bar"}, defaults.protectedProperties())
-}
-
-// TestProtectedProperties_ProtectAllProperties makes sure that protected_properties: ["*"] protects
-// all properties.
-func TestProtectedProperties_ProtectAllProperties(t *testing.T) {
-
- bp := `
- defaults {
- name: "transitive",
- protected_properties: ["other.buzz"],
- other: {
- buzz: "transitive",
- },
- }
-
- defaults {
- name: "defaults",
- defaults: ["transitive"],
- visibility: ["//visibility:private"],
- protected_properties: ["*"],
- foo: ["other"],
- bar: ["defaults"],
- nested: {
- fizz: true,
- }
- }
- `
-
- result := GroupFixturePreparers(
- prepareForDefaultsTest,
- FixtureWithRootAndroidBp(bp),
- ).RunTest(t)
-
- defaults := result.Module("defaults", "").(DefaultsModule)
- AssertDeepEquals(t, "defaults protected properties", []string{"other.buzz", "bar", "foo", "nested.fizz"},
- defaults.protectedProperties())
-}
-
-func TestProtectedProperties_DetectedOverride(t *testing.T) {
- bp := `
- defaults {
- name: "defaults",
- protected_properties: ["foo", "nested.fizz"],
- foo: ["defaults"],
- nested: {
- fizz: true,
- },
- }
-
- test {
- name: "foo",
- defaults: ["defaults"],
- foo: ["module"],
- nested: {
- fizz: false,
- },
- }
- `
-
- GroupFixturePreparers(
- prepareForDefaultsTest,
- FixtureWithRootAndroidBp(bp),
- ).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(
- []string{
- `\Qmodule "foo": attempts to append ["module"] to protected property "foo"'s value of ["defaults"] defined in module "defaults"\E`,
- `\Qmodule "foo": attempts to override protected property "nested.fizz" defined in module "defaults" with a different value (override true with false) so removing the property may necessitate other changes.\E`,
- })).RunTest(t)
-}
-
-func TestProtectedProperties_DefaultsConflict(t *testing.T) {
- bp := `
- defaults {
- name: "defaults1",
- protected_properties: ["other.buzz"],
- other: {
- buzz: "value",
- },
- }
-
- defaults {
- name: "defaults2",
- protected_properties: ["other.buzz"],
- other: {
- buzz: "another",
- },
- }
-
- test {
- name: "foo",
- defaults: ["defaults1", "defaults2"],
- }
- `
-
- GroupFixturePreparers(
- prepareForDefaultsTest,
- FixtureWithRootAndroidBp(bp),
- ).ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(
- `\Qmodule "foo": has conflicting default values for protected property "other.buzz":
- defaults module "defaults1" provides value "value"
- defaults module "defaults2" provides value "another"\E`,
- )).RunTest(t)
-}
diff --git a/android/filegroup.go b/android/filegroup.go
index 7d929bc..0ca5dc5 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -26,13 +26,18 @@
)
func init() {
- RegisterModuleType("filegroup", FileGroupFactory)
+ RegisterFilegroupBuildComponents(InitRegistrationContext)
}
var PrepareForTestWithFilegroup = FixtureRegisterWithContext(func(ctx RegistrationContext) {
- ctx.RegisterModuleType("filegroup", FileGroupFactory)
+ RegisterFilegroupBuildComponents(ctx)
})
+func RegisterFilegroupBuildComponents(ctx RegistrationContext) {
+ ctx.RegisterModuleType("filegroup", FileGroupFactory)
+ ctx.RegisterModuleType("filegroup_defaults", FileGroupDefaultsFactory)
+}
+
var convertedProtoLibrarySuffix = "_bp2build_converted"
// IsFilegroup checks that a module is a filegroup type
@@ -76,6 +81,13 @@
type bazelAidlLibraryAttributes struct {
Srcs bazel.LabelListAttribute
Strip_import_prefix *string
+ Deps bazel.LabelListAttribute
+}
+
+// api srcs can be contained in filegroups.
+// this should be generated in api_bp2build workspace as well.
+func (fg *fileGroup) ConvertWithApiBp2build(ctx TopDownMutatorContext) {
+ fg.ConvertWithBp2build(ctx)
}
// ConvertWithBp2build performs bp2build conversion of filegroup
@@ -107,27 +119,39 @@
// If the module has a mixed bag of AIDL and non-AIDL files, split the filegroup manually
// and then convert
if fg.ShouldConvertToAidlLibrary(ctx) {
+ tags := []string{"apex_available=//apex_available:anyapex"}
+ deps := bazel.MakeLabelListAttribute(BazelLabelForModuleDeps(ctx, fg.properties.Aidl.Deps))
+
attrs := &bazelAidlLibraryAttributes{
Srcs: srcs,
Strip_import_prefix: fg.properties.Path,
+ Deps: deps,
}
props := bazel.BazelTargetModuleProperties{
Rule_class: "aidl_library",
- Bzl_load_location: "//build/bazel/rules/aidl:library.bzl",
+ Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
}
- ctx.CreateBazelTargetModule(props, CommonAttributes{Name: fg.Name()}, attrs)
+ ctx.CreateBazelTargetModule(
+ props,
+ CommonAttributes{
+ Name: fg.Name(),
+ Tags: bazel.MakeStringListAttribute(tags),
+ },
+ attrs)
} else {
if fg.ShouldConvertToProtoLibrary(ctx) {
- // TODO(b/246997908): we can remove this tag if we could figure out a
- // solution for this bug.
attrs := &ProtoAttrs{
Srcs: srcs,
Strip_import_prefix: fg.properties.Path,
}
- tags := []string{"manual"}
+ tags := []string{
+ "apex_available=//apex_available:anyapex",
+ // TODO(b/246997908): we can remove this tag if we could figure out a solution for this bug.
+ "manual",
+ }
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
CommonAttributes{
@@ -167,11 +191,20 @@
// Create a make variable with the specified name that contains the list of files in the
// filegroup, relative to the root of the source tree.
Export_to_make_var *string
+
+ // aidl is explicitly provided for implicit aidl dependencies
+ // TODO(b/278298615): aidl prop is a no-op in Soong and is an escape hatch
+ // to include implicit aidl dependencies for bazel migration compatibility
+ Aidl struct {
+ // List of aidl files or filegroup depended on by srcs
+ Deps []string `android:"path"`
+ }
}
type fileGroup struct {
ModuleBase
BazelModuleBase
+ DefaultableModuleBase
FileGroupAsLibrary
properties fileGroupProperties
srcs Paths
@@ -189,6 +222,7 @@
module.AddProperties(&module.properties)
InitAndroidModule(module)
InitBazelModule(module)
+ InitDefaultableModule(module)
return module
}
@@ -320,3 +354,17 @@
}
return nil, false
}
+
+// Defaults
+type FileGroupDefaults struct {
+ ModuleBase
+ DefaultsModuleBase
+}
+
+func FileGroupDefaultsFactory() Module {
+ module := &FileGroupDefaults{}
+ module.AddProperties(&fileGroupProperties{})
+ InitDefaultsModule(module)
+
+ return module
+}
diff --git a/android/filegroup_test.go b/android/filegroup_test.go
index 8292d5e..893da57 100644
--- a/android/filegroup_test.go
+++ b/android/filegroup_test.go
@@ -58,3 +58,24 @@
AssertStringEquals(t, "src full path", expectedOutputfile, fg.srcs[0].String())
}
}
+
+func TestFilegroupDefaults(t *testing.T) {
+ bp := FixtureAddTextFile("p/Android.bp", `
+ filegroup_defaults {
+ name: "defaults",
+ visibility: ["//x"],
+ }
+ filegroup {
+ name: "foo",
+ defaults: ["defaults"],
+ visibility: ["//y"],
+ }
+ `)
+ result := GroupFixturePreparers(
+ PrepareForTestWithFilegroup,
+ PrepareForTestWithDefaults,
+ PrepareForTestWithVisibility,
+ bp).RunTest(t)
+ rules := effectiveVisibilityRules(result.Config, qualifiedModuleName{pkg: "p", name: "foo"})
+ AssertDeepEquals(t, "visibility", []string{"//x", "//y"}, rules.Strings())
+}
diff --git a/android/fixture.go b/android/fixture.go
index c2b16f6..dbc3bc5 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "runtime"
"strings"
"testing"
)
@@ -379,6 +380,12 @@
})
}
+var PrepareForSkipTestOnMac = newSimpleFixturePreparer(func(fixture *fixture) {
+ if runtime.GOOS != "linux" {
+ fixture.t.Skip("Test is only supported on linux.")
+ }
+})
+
// PrepareForDebug_DO_NOT_SUBMIT puts the fixture into debug which will cause it to output its
// state before running the test.
//
diff --git a/android/makefile_goal.go b/android/makefile_goal.go
deleted file mode 100644
index 07354a6..0000000
--- a/android/makefile_goal.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2020 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"
- "io"
- "path/filepath"
-
- "github.com/google/blueprint/proptools"
-)
-
-func init() {
- RegisterModuleType("makefile_goal", MakefileGoalFactory)
-}
-
-type makefileGoalProperties struct {
- // Sources.
-
- // Makefile goal output file path, relative to PRODUCT_OUT.
- Product_out_path *string
-}
-
-type makefileGoal struct {
- ModuleBase
-
- properties makefileGoalProperties
-
- // Destination. Output file path of this module.
- outputFilePath OutputPath
-}
-
-var _ AndroidMkEntriesProvider = (*makefileGoal)(nil)
-var _ OutputFileProducer = (*makefileGoal)(nil)
-
-// Input file of this makefile_goal module. Nil if none specified. May use variable names in makefiles.
-func (p *makefileGoal) inputPath() *string {
- if p.properties.Product_out_path != nil {
- return proptools.StringPtr(filepath.Join("$(PRODUCT_OUT)", proptools.String(p.properties.Product_out_path)))
- }
- return nil
-}
-
-// OutputFileProducer
-func (p *makefileGoal) OutputFiles(tag string) (Paths, error) {
- if tag != "" {
- return nil, fmt.Errorf("unsupported tag %q", tag)
- }
- return Paths{p.outputFilePath}, nil
-}
-
-// AndroidMkEntriesProvider
-func (p *makefileGoal) DepsMutator(ctx BottomUpMutatorContext) {
- if p.inputPath() == nil {
- ctx.PropertyErrorf("product_out_path", "Path relative to PRODUCT_OUT required")
- }
-}
-
-func (p *makefileGoal) GenerateAndroidBuildActions(ctx ModuleContext) {
- filename := filepath.Base(proptools.String(p.inputPath()))
- p.outputFilePath = PathForModuleOut(ctx, filename).OutputPath
-
- ctx.InstallFile(PathForModuleInstall(ctx, "etc"), ctx.ModuleName(), p.outputFilePath)
-}
-
-func (p *makefileGoal) AndroidMkEntries() []AndroidMkEntries {
- return []AndroidMkEntries{AndroidMkEntries{
- Class: "ETC",
- OutputFile: OptionalPathForPath(p.outputFilePath),
- ExtraFooters: []AndroidMkExtraFootersFunc{
- func(w io.Writer, name, prefix, moduleDir string) {
- // Can't use Cp because inputPath() is not a valid Path.
- fmt.Fprintf(w, "$(eval $(call copy-one-file,%s,%s))\n", proptools.String(p.inputPath()), p.outputFilePath)
- },
- },
- }}
-}
-
-// Import a Makefile goal to Soong by copying the file built by
-// the goal to a path visible to Soong. This rule only works on boot images.
-func MakefileGoalFactory() Module {
- module := &makefileGoal{}
- module.AddProperties(&module.properties)
- InitAndroidModule(module)
- return module
-}
diff --git a/android/module.go b/android/module.go
index 773d77b..c8670c3 100644
--- a/android/module.go
+++ b/android/module.go
@@ -37,26 +37,64 @@
DeviceStaticLibrary = "static_library"
)
+// BuildParameters describes the set of potential parameters to build a Ninja rule.
+// In general, these correspond to a Ninja concept.
type BuildParams struct {
- Rule blueprint.Rule
- Deps blueprint.Deps
- Depfile WritablePath
- Description string
- Output WritablePath
- Outputs WritablePaths
- SymlinkOutput WritablePath
- SymlinkOutputs WritablePaths
- ImplicitOutput WritablePath
+ // A Ninja Rule that will be written to the Ninja file. This allows factoring out common code
+ // among multiple modules to reduce repetition in the Ninja file of action requirements. A rule
+ // can contain variables that should be provided in Args.
+ Rule blueprint.Rule
+ // Deps represents the depfile format. When using RuleBuilder, this defaults to GCC when depfiles
+ // are used.
+ Deps blueprint.Deps
+ // Depfile is a writeable path that allows correct incremental builds when the inputs have not
+ // been fully specified by the Ninja rule. Ninja supports a subset of the Makefile depfile syntax.
+ Depfile WritablePath
+ // A description of the build action.
+ Description string
+ // Output is an output file of the action. When using this field, references to $out in the Ninja
+ // command will refer to this file.
+ Output WritablePath
+ // Outputs is a slice of output file of the action. When using this field, references to $out in
+ // the Ninja command will refer to these files.
+ Outputs WritablePaths
+ // SymlinkOutput is an output file specifically that is a symlink.
+ SymlinkOutput WritablePath
+ // SymlinkOutputs is a slice of output files specifically that is a symlink.
+ SymlinkOutputs WritablePaths
+ // ImplicitOutput is an output file generated by the action. Note: references to `$out` in the
+ // Ninja command will NOT include references to this file.
+ ImplicitOutput WritablePath
+ // ImplicitOutputs is a slice of output files generated by the action. Note: references to `$out`
+ // in the Ninja command will NOT include references to these files.
ImplicitOutputs WritablePaths
- Input Path
- Inputs Paths
- Implicit Path
- Implicits Paths
- OrderOnly Paths
- Validation Path
- Validations Paths
- Default bool
- Args map[string]string
+ // Input is an input file to the Ninja action. When using this field, references to $in in the
+ // Ninja command will refer to this file.
+ Input Path
+ // Inputs is a slice of input files to the Ninja action. When using this field, references to $in
+ // in the Ninja command will refer to these files.
+ Inputs Paths
+ // Implicit is an input file to the Ninja action. Note: references to `$in` in the Ninja command
+ // will NOT include references to this file.
+ Implicit Path
+ // Implicits is a slice of input files to the Ninja action. Note: references to `$in` in the Ninja
+ // command will NOT include references to these files.
+ Implicits Paths
+ // OrderOnly are Ninja order-only inputs to the action. When these are out of date, the output is
+ // not rebuilt until they are built, but changes in order-only dependencies alone do not cause the
+ // output to be rebuilt.
+ OrderOnly Paths
+ // Validation is an output path for a validation action. Validation outputs imply lower
+ // non-blocking priority to building non-validation outputs.
+ Validation Path
+ // Validations is a slice of output path for a validation action. Validation outputs imply lower
+ // non-blocking priority to building non-validation outputs.
+ Validations Paths
+ // Whether to skip outputting a default target statement which will be built by Ninja when no
+ // targets are specified on Ninja's command line.
+ Default bool
+ // Args is a key value mapping for replacements of variables within the Rule
+ Args map[string]string
}
type ModuleBuildParams BuildParams
@@ -512,6 +550,7 @@
ExportedToMake() bool
InitRc() Paths
VintfFragments() Paths
+ EffectiveLicenseKinds() []string
EffectiveLicenseFiles() Paths
AddProperties(props ...interface{})
@@ -1986,6 +2025,10 @@
return m.commonProperties.NamespaceExportedToMake
}
+func (m *ModuleBase) EffectiveLicenseKinds() []string {
+ return m.commonProperties.Effective_license_kinds
+}
+
func (m *ModuleBase) EffectiveLicenseFiles() Paths {
result := make(Paths, 0, len(m.commonProperties.Effective_license_text))
for _, p := range m.commonProperties.Effective_license_text {
@@ -2395,7 +2438,7 @@
func (m *ModuleBase) isHandledByBazel(ctx ModuleContext) (MixedBuildBuildable, bool) {
if mixedBuildMod, ok := m.module.(MixedBuildBuildable); ok {
- if mixedBuildMod.IsMixedBuildSupported(ctx) && MixedBuildsEnabled(ctx) {
+ if mixedBuildMod.IsMixedBuildSupported(ctx) && (MixedBuildsEnabled(ctx) == MixedBuildEnabled) {
return mixedBuildMod, true
}
}
diff --git a/android/mutator.go b/android/mutator.go
index 4dacb8d..0a091eb 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -268,6 +268,17 @@
// platforms, as dictated by a given bool attribute: the target will not be buildable in
// any platform for which this bool attribute is false.
CreateBazelTargetModuleWithRestrictions(bazel.BazelTargetModuleProperties, CommonAttributes, interface{}, bazel.BoolAttribute)
+
+ // CreateBazelTargetAliasInDir creates an alias definition in `dir` directory.
+ // This function can be used to create alias definitions in a directory that is different
+ // from the directory of the visited Soong module.
+ CreateBazelTargetAliasInDir(dir string, name string, actual bazel.Label)
+
+ // CreateBazelConfigSetting creates a config_setting in <dir>/BUILD.bazel
+ // build/bazel has several static config_setting(s) that are used in Bazel builds.
+ // This function can be used to createa additional config_setting(s) based on the build graph
+ // (e.g. a config_setting specific to an apex variant)
+ CreateBazelConfigSetting(csa bazel.ConfigSettingAttributes, ca CommonAttributes, dir string)
}
type topDownMutatorContext struct {
@@ -705,6 +716,51 @@
t.createBazelTargetModule(bazelProps, commonAttrs, attrs, enabledProperty)
}
+var (
+ bazelAliasModuleProperties = bazel.BazelTargetModuleProperties{
+ Rule_class: "alias",
+ }
+)
+
+type bazelAliasAttributes struct {
+ Actual *bazel.LabelAttribute
+}
+
+func (t *topDownMutatorContext) CreateBazelTargetAliasInDir(
+ dir string,
+ name string,
+ actual bazel.Label) {
+ mod := t.Module()
+ attrs := &bazelAliasAttributes{
+ Actual: bazel.MakeLabelAttribute(actual.Label),
+ }
+ info := bp2buildInfo{
+ Dir: dir,
+ BazelProps: bazelAliasModuleProperties,
+ CommonAttrs: CommonAttributes{Name: name},
+ ConstraintAttrs: constraintAttributes{},
+ Attrs: attrs,
+ }
+ mod.base().addBp2buildInfo(info)
+}
+
+func (t *topDownMutatorContext) CreateBazelConfigSetting(
+ csa bazel.ConfigSettingAttributes,
+ ca CommonAttributes,
+ dir string) {
+ mod := t.Module()
+ info := bp2buildInfo{
+ Dir: dir,
+ BazelProps: bazel.BazelTargetModuleProperties{
+ Rule_class: "config_setting",
+ },
+ CommonAttrs: ca,
+ ConstraintAttrs: constraintAttributes{},
+ Attrs: &csa,
+ }
+ mod.base().addBp2buildInfo(info)
+}
+
// ApexAvailableTags converts the apex_available property value of an ApexModule
// module and returns it as a list of keyed tags.
func ApexAvailableTags(mod Module) bazel.StringListAttribute {
@@ -714,11 +770,46 @@
// TODO(b/218841706): hidl_interface has the apex_available prop, but it's
// defined directly as a prop and not via ApexModule, so this doesn't
// pick those props up.
- attr.Value = ConvertApexAvailableToTags(am.apexModuleBase().ApexAvailable())
+ apexAvailable := am.apexModuleBase().ApexAvailable()
+ // If a user does not specify apex_available in Android.bp, then soong provides a default.
+ // To avoid verbosity of BUILD files, remove this default from user-facing BUILD files.
+ if len(am.apexModuleBase().ApexProperties.Apex_available) == 0 {
+ apexAvailable = []string{}
+ }
+ attr.Value = ConvertApexAvailableToTags(apexAvailable)
}
return attr
}
+func ApexAvailableTagsWithoutTestApexes(ctx BaseModuleContext, mod Module) bazel.StringListAttribute {
+ attr := bazel.StringListAttribute{}
+ if am, ok := mod.(ApexModule); ok {
+ apexAvailableWithoutTestApexes := removeTestApexes(ctx, am.apexModuleBase().ApexAvailable())
+ // If a user does not specify apex_available in Android.bp, then soong provides a default.
+ // To avoid verbosity of BUILD files, remove this default from user-facing BUILD files.
+ if len(am.apexModuleBase().ApexProperties.Apex_available) == 0 {
+ apexAvailableWithoutTestApexes = []string{}
+ }
+ attr.Value = ConvertApexAvailableToTags(apexAvailableWithoutTestApexes)
+ }
+ return attr
+}
+
+func removeTestApexes(ctx BaseModuleContext, apex_available []string) []string {
+ testApexes := []string{}
+ for _, aa := range apex_available {
+ // ignore the wildcards
+ if InList(aa, AvailableToRecognziedWildcards) {
+ continue
+ }
+ mod, _ := ctx.ModuleFromName(aa)
+ if apex, ok := mod.(ApexTestInterface); ok && apex.IsTestApex() {
+ testApexes = append(testApexes, aa)
+ }
+ }
+ return RemoveListFromList(CopyOf(apex_available), testApexes)
+}
+
func ConvertApexAvailableToTags(apexAvailable []string) []string {
if len(apexAvailable) == 0 {
// We need nil specifically to make bp2build not add the tags property at all,
@@ -732,6 +823,13 @@
return result
}
+// ConvertApexAvailableToTagsWithoutTestApexes converts a list of apex names to a list of bazel tags
+// This function drops any test apexes from the input.
+func ConvertApexAvailableToTagsWithoutTestApexes(ctx BaseModuleContext, apexAvailable []string) []string {
+ noTestApexes := removeTestApexes(ctx, apexAvailable)
+ return ConvertApexAvailableToTags(noTestApexes)
+}
+
func (t *topDownMutatorContext) createBazelTargetModule(
bazelProps bazel.BazelTargetModuleProperties,
commonAttrs CommonAttributes,
diff --git a/android/namespace.go b/android/namespace.go
index b43ffdf..ebf85a1 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -225,6 +225,10 @@
return ns, nil
}
+func (r *NameResolver) NewSkippedModule(ctx blueprint.NamespaceContext, name string, skipInfo blueprint.SkippedModuleInfo) {
+ r.rootNamespace.moduleContainer.NewSkippedModule(ctx, name, skipInfo)
+}
+
func (r *NameResolver) AllModules() []blueprint.ModuleGroup {
childLists := [][]blueprint.ModuleGroup{}
totalCount := 0
@@ -241,6 +245,10 @@
return allModules
}
+func (r *NameResolver) SkippedModuleFromName(moduleName string, namespace blueprint.Namespace) (skipInfos []blueprint.SkippedModuleInfo, skipped bool) {
+ return r.rootNamespace.moduleContainer.SkippedModuleFromName(moduleName, namespace)
+}
+
// parses a fully-qualified path (like "//namespace_path:module_name") into a namespace name and a
// module name
func (r *NameResolver) parseFullyQualifiedName(name string) (namespaceName string, moduleName string, ok bool) {
@@ -300,7 +308,7 @@
for _, name := range namespace.importedNamespaceNames {
imp, ok := r.namespaceAt(name)
if !ok {
- return fmt.Errorf("namespace %v does not exist", name)
+ return fmt.Errorf("namespace %v does not exist; Some necessary modules may have been skipped by Soong. Check if PRODUCT_SOURCE_ROOT_DIRS is pruning necessary Android.bp files.", name)
}
namespace.visibleNamespaces = append(namespace.visibleNamespaces, imp)
}
@@ -317,8 +325,8 @@
namespace.id = strconv.Itoa(id)
}
-func (r *NameResolver) MissingDependencyError(depender string, dependerNamespace blueprint.Namespace, depName string) (err error) {
- text := fmt.Sprintf("%q depends on undefined module %q", depender, depName)
+func (r *NameResolver) MissingDependencyError(depender string, dependerNamespace blueprint.Namespace, depName string, guess []string) (err error) {
+ text := fmt.Sprintf("%q depends on undefined module %q.", depender, depName)
_, _, isAbs := r.parseFullyQualifiedName(depName)
if isAbs {
@@ -329,12 +337,18 @@
// determine which namespaces the module can be found in
foundInNamespaces := []string{}
+ skippedDepErrors := []error{}
for _, namespace := range r.sortedNamespaces.sortedItems() {
_, found := namespace.moduleContainer.ModuleFromName(depName, nil)
if found {
foundInNamespaces = append(foundInNamespaces, namespace.Path)
}
+ _, skipped := namespace.moduleContainer.SkippedModuleFromName(depName, nil)
+ if skipped {
+ skippedDepErrors = append(skippedDepErrors, namespace.moduleContainer.MissingDependencyError(depender, dependerNamespace, depName, nil))
+ }
}
+
if len(foundInNamespaces) > 0 {
// determine which namespaces are visible to dependerNamespace
dependerNs := dependerNamespace.(*Namespace)
@@ -346,6 +360,13 @@
text += fmt.Sprintf("\nModule %q is defined in namespace %q which can read these %v namespaces: %q", depender, dependerNs.Path, len(importedNames), importedNames)
text += fmt.Sprintf("\nModule %q can be found in these namespaces: %q", depName, foundInNamespaces)
}
+ for _, err := range skippedDepErrors {
+ text += fmt.Sprintf("\n%s", err.Error())
+ }
+
+ if len(guess) > 0 {
+ text += fmt.Sprintf("\nOr did you mean %q?", guess)
+ }
return fmt.Errorf(text)
}
diff --git a/android/namespace_test.go b/android/namespace_test.go
index 7a387a0..ea51c6e 100644
--- a/android/namespace_test.go
+++ b/android/namespace_test.go
@@ -174,9 +174,10 @@
`,
}),
).
- ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir3/Android.bp:4:5: "b" depends on undefined module "a"
+ ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir3/Android.bp:4:5: "b" depends on undefined module "a".
Module "b" is defined in namespace "dir3" which can read these 2 namespaces: ["dir3" "."]
-Module "a" can be found in these namespaces: ["dir1" "dir2"]\E`)).
+Module "a" can be found in these namespaces: ["dir1" "dir2"]\E
+Or did you mean ["soong_namespace"]?`)).
RunTest(t)
}
@@ -421,9 +422,10 @@
`,
}),
).
- ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir1/subdir1/Android.bp:4:5: "b" depends on undefined module "a"
+ ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir1/subdir1/Android.bp:4:5: "b" depends on undefined module "a".
Module "b" is defined in namespace "dir1/subdir1" which can read these 2 namespaces: ["dir1/subdir1" "."]
-Module "a" can be found in these namespaces: ["dir1"]\E`)).
+Module "a" can be found in these namespaces: ["dir1"]\E
+Or did you mean ["soong_namespace"]?`)).
RunTest(t)
}
@@ -481,9 +483,10 @@
`,
}),
).
- ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir3/Android.bp:5:5: "c" depends on undefined module "a"
+ ExtendWithErrorHandler(FixtureExpectsOneErrorPattern(`\Qdir3/Android.bp:5:5: "c" depends on undefined module "a".
Module "c" is defined in namespace "dir3" which can read these 3 namespaces: ["dir3" "dir2" "."]
-Module "a" can be found in these namespaces: ["dir1"]\E`)).
+Module "a" can be found in these namespaces: ["dir1"]\E
+Or did you mean ["b"]?`)).
RunTest(t)
}
diff --git a/android/neverallow.go b/android/neverallow.go
index ba5385c..5b5e613 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -55,7 +55,6 @@
AddNeverAllowRules(createJavaDeviceForHostRules()...)
AddNeverAllowRules(createCcSdkVariantRules()...)
AddNeverAllowRules(createUncompressDexRules()...)
- AddNeverAllowRules(createMakefileGoalRules()...)
AddNeverAllowRules(createInitFirstStageRules()...)
AddNeverAllowRules(createProhibitFrameworkAccessRules()...)
AddNeverAllowRules(createBp2BuildRule())
@@ -165,6 +164,7 @@
javaDeviceForHostProjectsAllowedList := []string{
"development/build",
"external/guava",
+ "external/kotlinx.coroutines",
"external/robolectric-shadows",
"external/robolectric",
"frameworks/layoutlib",
@@ -235,20 +235,6 @@
}
}
-func createMakefileGoalRules() []Rule {
- allowlist := []string{
- // libwifi_hal uses makefile_goal for its dependencies
- "frameworks/opt/net/wifi/libwifi_hal",
- }
- return []Rule{
- NeverAllow().
- ModuleType("makefile_goal").
- WithoutMatcher("product_out_path", Regexp("^boot[0-9a-zA-Z.-]*[.]img$")).
- NotIn(allowlist...).
- Because("Only boot images may be imported as a makefile goal if not in allowed projects"),
- }
-}
-
func createInitFirstStageRules() []Rule {
return []Rule{
NeverAllow().
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 5f5f9a1..ddd982d 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -313,45 +313,6 @@
"module \"outside_art_libraries\": violates neverallow",
},
},
- {
- name: "disallowed makefile_goal",
- fs: map[string][]byte{
- "Android.bp": []byte(`
- makefile_goal {
- name: "foo",
- product_out_path: "boot/trap.img"
- }
- `),
- },
- expectedErrors: []string{
- "Only boot images.* may be imported as a makefile goal",
- },
- },
- {
- name: "disallowed makefile_goal outside external",
- fs: map[string][]byte{
- "project/Android.bp": []byte(`
- makefile_goal {
- name: "foo",
- product_out_path: "obj/EXE/foo",
- }
- `),
- },
- expectedErrors: []string{
- "not in allowed projects",
- },
- },
- {
- name: "allow makefile_goal within external",
- fs: map[string][]byte{
- "frameworks/opt/net/wifi/libwifi_hal/Android.bp": []byte(`
- makefile_goal {
- name: "foo",
- product_out_path: "obj/EXE/foo",
- }
- `),
- },
- },
// Tests for the rule prohibiting the use of framework
{
name: "prohibit framework",
@@ -391,7 +352,6 @@
ctx.RegisterModuleType("java_library", newMockJavaLibraryModule)
ctx.RegisterModuleType("java_library_host", newMockJavaLibraryModule)
ctx.RegisterModuleType("java_device_for_host", newMockJavaLibraryModule)
- ctx.RegisterModuleType("makefile_goal", newMockMakefileGoalModule)
}),
)
@@ -489,22 +449,3 @@
func (p *mockJavaLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
}
-
-type mockMakefileGoalProperties struct {
- Product_out_path *string
-}
-
-type mockMakefileGoalModule struct {
- ModuleBase
- properties mockMakefileGoalProperties
-}
-
-func newMockMakefileGoalModule() Module {
- m := &mockMakefileGoalModule{}
- m.AddProperties(&m.properties)
- InitAndroidModule(m)
- return m
-}
-
-func (p *mockMakefileGoalModule) GenerateAndroidBuildActions(ModuleContext) {
-}
diff --git a/android/ninja_deps.go b/android/ninja_deps.go
index 2f442d5..1d50a47 100644
--- a/android/ninja_deps.go
+++ b/android/ninja_deps.go
@@ -14,7 +14,10 @@
package android
-import "sort"
+import (
+ "android/soong/starlark_import"
+ "sort"
+)
func (c *config) addNinjaFileDeps(deps ...string) {
for _, dep := range deps {
@@ -40,4 +43,11 @@
func (ninjaDepsSingleton) GenerateBuildActions(ctx SingletonContext) {
ctx.AddNinjaFileDeps(ctx.Config().ninjaFileDeps()...)
+
+ deps, err := starlark_import.GetNinjaDeps()
+ if err != nil {
+ ctx.Errorf("Error running starlark code: %s", err)
+ } else {
+ ctx.AddNinjaFileDeps(deps...)
+ }
}
diff --git a/android/override_module.go b/android/override_module.go
index 2d30a85..86f582b 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -304,8 +304,9 @@
for i, o := range overrides {
mods[i+1].(OverridableModule).override(ctx, o)
if o.getOverriddenByPrebuilt() {
- // The overriding module itself, too, is overridden by a prebuilt. Skip its installation.
- mods[i+1].HideFromMake()
+ // The overriding module itself, too, is overridden by a prebuilt.
+ // Copy the flag and hide it in make
+ mods[i+1].ReplacedByPrebuilt()
}
}
} else if o, ok := ctx.Module().(OverrideModule); ok {
diff --git a/android/packaging.go b/android/packaging.go
index 4a9b591..c764a6d 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -238,11 +238,11 @@
// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
// entries into the specified directory.
-func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir ModuleOutPath) (entries []string) {
+func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
seenDir := make(map[string]bool)
for _, k := range SortedKeys(specs) {
ps := specs[k]
- destPath := dir.Join(ctx, ps.relPathInPackage).String()
+ destPath := filepath.Join(dir.String(), ps.relPathInPackage)
destDir := filepath.Dir(destPath)
entries = append(entries, ps.relPathInPackage)
if _, ok := seenDir[destDir]; !ok {
diff --git a/android/proto.go b/android/proto.go
index 09e50c8..cebbd59 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -234,7 +234,7 @@
}
}
- tags := ApexAvailableTags(ctx.Module())
+ tags := ApexAvailableTagsWithoutTestApexes(ctx.(TopDownMutatorContext), ctx.Module())
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
diff --git a/android/register.go b/android/register.go
index 9a3d3aa..1a3db9d 100644
--- a/android/register.go
+++ b/android/register.go
@@ -162,6 +162,7 @@
ctx := &Context{blueprint.NewContext(), config}
ctx.SetSrcDir(absSrcDir)
ctx.AddIncludeTags(config.IncludeTags()...)
+ ctx.AddSourceRootDirs(config.SourceRootDirs()...)
return ctx
}
diff --git a/android/sdk.go b/android/sdk.go
index 8b23d63..63e0bbe 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -25,7 +25,7 @@
// minApiLevelForSdkSnapshot provides access to the min_sdk_version for MinApiLevelForSdkSnapshot
type minApiLevelForSdkSnapshot interface {
- MinSdkVersion(ctx EarlyModuleContext) SdkSpec
+ MinSdkVersion(ctx EarlyModuleContext) ApiLevel
}
// MinApiLevelForSdkSnapshot returns the ApiLevel of the min_sdk_version of the supplied module.
@@ -34,7 +34,7 @@
func MinApiLevelForSdkSnapshot(ctx EarlyModuleContext, module Module) ApiLevel {
minApiLevel := NoneApiLevel
if m, ok := module.(minApiLevelForSdkSnapshot); ok {
- minApiLevel = m.MinSdkVersion(ctx).ApiLevel
+ minApiLevel = m.MinSdkVersion(ctx)
}
if minApiLevel == NoneApiLevel {
// The default min API level is 1.
diff --git a/android/sdk_version.go b/android/sdk_version.go
index a7e03dc..08762ef 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -25,15 +25,15 @@
SdkVersion(ctx EarlyModuleContext) SdkSpec
// SystemModules returns the system_modules property of the current module, or an empty string if it is not set.
SystemModules() string
- // MinSdkVersion returns SdkSpec that corresponds to the min_sdk_version property of the current module,
+ // MinSdkVersion returns ApiLevel that corresponds to the min_sdk_version property of the current module,
// or from sdk_version if it is not set.
- MinSdkVersion(ctx EarlyModuleContext) SdkSpec
- // ReplaceMaxSdkVersionPlaceholder returns SdkSpec to replace the maxSdkVersion property of permission and
+ MinSdkVersion(ctx EarlyModuleContext) ApiLevel
+ // ReplaceMaxSdkVersionPlaceholder returns Apilevel to replace the maxSdkVersion property of permission and
// uses-permission tags if it is set.
- ReplaceMaxSdkVersionPlaceholder(ctx EarlyModuleContext) SdkSpec
- // TargetSdkVersion returns the SdkSpec that corresponds to the target_sdk_version property of the current module,
+ ReplaceMaxSdkVersionPlaceholder(ctx EarlyModuleContext) ApiLevel
+ // TargetSdkVersion returns the ApiLevel that corresponds to the target_sdk_version property of the current module,
// or from sdk_version if it is not set.
- TargetSdkVersion(ctx EarlyModuleContext) SdkSpec
+ TargetSdkVersion(ctx EarlyModuleContext) ApiLevel
}
// SdkKind represents a particular category of an SDK spec like public, system, test, etc.
@@ -84,6 +84,50 @@
}
}
+// JavaLibraryName returns the soong module containing the Java APIs of that API surface.
+func (k SdkKind) JavaLibraryName(c Config) string {
+ name := k.DefaultJavaLibraryName()
+ return JavaApiLibraryName(c, name)
+}
+
+// JavaApiLibraryName returns the name of .txt equivalent of a java_library, but does
+// not check if either module exists.
+// TODO: Return .txt (single-tree or multi-tree equivalents) based on config
+func JavaApiLibraryName(c Config, name string) string {
+ if c.BuildFromTextStub() {
+ return name + ".from-text"
+ }
+ return name
+}
+
+// JavaApiLibraryNames applies JavaApiLibraryName to the list of java_library names.
+func JavaApiLibraryNames(c Config, names []string) []string {
+ apiLibs := make([]string, len(names))
+ for i, name := range names {
+ apiLibs[i] = JavaApiLibraryName(c, name)
+ }
+ return apiLibs
+}
+
+func (k SdkKind) DefaultJavaLibraryName() string {
+ switch k {
+ case SdkPublic:
+ return "android_stubs_current"
+ case SdkSystem:
+ return "android_system_stubs_current"
+ case SdkTest:
+ return "android_test_stubs_current"
+ case SdkCore:
+ return "core.current.stubs"
+ case SdkModule:
+ return "android_module_lib_stubs_current"
+ case SdkSystemServer:
+ return "android_system_server_stubs_current"
+ default:
+ panic(fmt.Errorf("APIs of API surface %v cannot be provided by a single Soong module\n", k))
+ }
+}
+
// SdkSpec represents the kind and the version of an SDK for a module to build against
type SdkSpec struct {
Kind SdkKind
@@ -187,14 +231,7 @@
if ctx.DeviceSpecific() || ctx.SocSpecific() {
s = s.ForVendorPartition(ctx)
}
- if !s.ApiLevel.IsPreview() {
- return s.ApiLevel, nil
- }
- ret := ctx.Config().DefaultAppTargetSdk(ctx)
- if ret.IsPreview() {
- return FutureApiLevel, nil
- }
- return ret, nil
+ return s.ApiLevel.EffectiveVersion(ctx)
}
// EffectiveVersionString converts an SdkSpec into the concrete version string that the module
@@ -208,37 +245,12 @@
if ctx.DeviceSpecific() || ctx.SocSpecific() {
s = s.ForVendorPartition(ctx)
}
- if !s.ApiLevel.IsPreview() {
- return s.ApiLevel.String(), nil
- }
- // Determine the default sdk
- ret := ctx.Config().DefaultAppTargetSdk(ctx)
- if !ret.IsPreview() {
- // If the default sdk has been finalized, return that
- return ret.String(), nil
- }
- // There can be more than one active in-development sdks
- // If an app is targeting an active sdk, but not the default one, return the requested active sdk.
- // e.g.
- // SETUP
- // In-development: UpsideDownCake, VanillaIceCream
- // Default: VanillaIceCream
- // Android.bp
- // min_sdk_version: `UpsideDownCake`
- // RETURN
- // UpsideDownCake and not VanillaIceCream
- for _, preview := range ctx.Config().PreviewApiLevels() {
- if s.ApiLevel.String() == preview.String() {
- return preview.String(), nil
- }
- }
- // Otherwise return the default one
- return ret.String(), nil
+ return s.ApiLevel.EffectiveVersionString(ctx)
}
var (
SdkSpecNone = SdkSpec{SdkNone, NoneApiLevel, "(no version)"}
- SdkSpecPrivate = SdkSpec{SdkPrivate, FutureApiLevel, ""}
+ SdkSpecPrivate = SdkSpec{SdkPrivate, PrivateApiLevel, ""}
SdkSpecCorePlatform = SdkSpec{SdkCorePlatform, FutureApiLevel, "core_platform"}
)
@@ -261,7 +273,7 @@
var kindString string
if sep == 0 {
- return SdkSpec{SdkInvalid, NoneApiLevel, str}
+ return SdkSpec{SdkInvalid, NewInvalidApiLevel(str), str}
} else if sep == -1 {
kindString = ""
} else {
@@ -289,7 +301,7 @@
apiLevel, err := ApiLevelFromUserWithConfig(config, versionString)
if err != nil {
- return SdkSpec{SdkInvalid, apiLevel, str}
+ return SdkSpec{SdkInvalid, NewInvalidApiLevel(versionString), str}
}
return SdkSpec{kind, apiLevel, str}
}
@@ -316,3 +328,18 @@
}
return true
}
+
+func init() {
+ RegisterMakeVarsProvider(pctx, javaSdkMakeVars)
+}
+
+// Export the name of the soong modules representing the various Java API surfaces.
+func javaSdkMakeVars(ctx MakeVarsContext) {
+ ctx.Strict("ANDROID_PUBLIC_STUBS", SdkPublic.JavaLibraryName(ctx.Config()))
+ ctx.Strict("ANDROID_SYSTEM_STUBS", SdkSystem.JavaLibraryName(ctx.Config()))
+ ctx.Strict("ANDROID_TEST_STUBS", SdkTest.JavaLibraryName(ctx.Config()))
+ ctx.Strict("ANDROID_MODULE_LIB_STUBS", SdkModule.JavaLibraryName(ctx.Config()))
+ ctx.Strict("ANDROID_SYSTEM_SERVER_STUBS", SdkSystemServer.JavaLibraryName(ctx.Config()))
+ // TODO (jihoonkang): Create a .txt equivalent for core.current.stubs
+ ctx.Strict("ANDROID_CORE_STUBS", SdkCore.JavaLibraryName(ctx.Config()))
+}
diff --git a/android/sdk_version_test.go b/android/sdk_version_test.go
index ec81782..ea99c4d 100644
--- a/android/sdk_version_test.go
+++ b/android/sdk_version_test.go
@@ -37,11 +37,11 @@
},
{
input: "_",
- expected: "invalid_(no version)",
+ expected: "invalid__",
},
{
input: "_31",
- expected: "invalid_(no version)",
+ expected: "invalid__31",
},
{
input: "system_R",
diff --git a/android/test_asserts.go b/android/test_asserts.go
index 064f656..4143f15 100644
--- a/android/test_asserts.go
+++ b/android/test_asserts.go
@@ -160,6 +160,7 @@
// the value of the expected bool. If the expectation does not hold it reports an error prefixed with
// the supplied message and including a reason for why it failed.
func AssertStringListContainsEquals(t *testing.T, message string, list []string, s string, expected bool) {
+ t.Helper()
if expected {
AssertStringListContains(t, message, list, s)
} else {
diff --git a/android/test_config.go b/android/test_config.go
index 70c319a..28d9ec4 100644
--- a/android/test_config.go
+++ b/android/test_config.go
@@ -65,6 +65,7 @@
BuildMode: BazelProdMode,
mixedBuildDisabledModules: make(map[string]struct{}),
mixedBuildEnabledModules: make(map[string]struct{}),
+ bazelForceEnabledModules: make(map[string]struct{}),
}
config.deviceConfig = &deviceConfig{
config: config,
@@ -109,7 +110,8 @@
config.TestProductVariables.DeviceSecondaryArchVariant = proptools.StringPtr("armv7-a-neon")
}
-func modifyTestConfigForMusl(config Config) {
+// ModifyTestConfigForMusl takes a Config returned by TestConfig and changes the host targets from glibc to musl.
+func ModifyTestConfigForMusl(config Config) {
delete(config.Targets, config.BuildOS)
config.productVariables.HostMusl = boolPtr(true)
determineBuildOS(config.config)
diff --git a/android/util.go b/android/util.go
index 38e0a4d..08a3521 100644
--- a/android/util.go
+++ b/android/util.go
@@ -26,7 +26,11 @@
// CopyOf returns a new slice that has the same contents as s.
func CopyOf(s []string) []string {
- return append([]string(nil), s...)
+ // If the input is nil, return nil and not an empty list
+ if s == nil {
+ return s
+ }
+ return append([]string{}, s...)
}
// Concat returns a new slice concatenated from the two input slices. It does not change the input
@@ -276,6 +280,8 @@
// FirstUniqueStrings returns all unique elements of a slice of strings, keeping the first copy of
// each. It modifies the slice contents in place, and returns a subslice of the original slice.
func FirstUniqueStrings(list []string) []string {
+ // Do not moodify the input in-place, operate on a copy instead.
+ list = CopyOf(list)
// 128 was chosen based on BenchmarkFirstUniqueStrings results.
if len(list) > 128 {
return firstUniqueStringsMap(list)
@@ -332,6 +338,7 @@
// SortedUniqueStrings returns what the name says
func SortedUniqueStrings(list []string) []string {
+ // FirstUniqueStrings creates a copy of `list`, so the input remains untouched.
unique := FirstUniqueStrings(list)
sort.Strings(unique)
return unique
diff --git a/android/util_test.go b/android/util_test.go
index 5584b38..a2ef589 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -381,6 +381,14 @@
}
}
+func TestCopyOfEmptyAndNil(t *testing.T) {
+ emptyList := []string{}
+ copyOfEmptyList := CopyOf(emptyList)
+ AssertBoolEquals(t, "Copy of an empty list should be an empty list and not nil", true, copyOfEmptyList != nil)
+ copyOfNilList := CopyOf(nil)
+ AssertBoolEquals(t, "Copy of a nil list should be a nil list and not an empty list", true, copyOfNilList == nil)
+}
+
func ExampleCopyOf() {
a := []string{"1", "2", "3"}
b := CopyOf(a)
diff --git a/android/variable.go b/android/variable.go
index 1b5d558..496f523 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -199,6 +199,7 @@
Platform_sdk_extension_version *int `json:",omitempty"`
Platform_base_sdk_extension_version *int `json:",omitempty"`
Platform_version_active_codenames []string `json:",omitempty"`
+ Platform_version_all_preview_codenames []string `json:",omitempty"`
Platform_vndk_version *string `json:",omitempty"`
Platform_systemsdk_versions []string `json:",omitempty"`
Platform_security_patch *string `json:",omitempty"`
@@ -217,6 +218,7 @@
DeviceVndkVersion *string `json:",omitempty"`
DeviceCurrentApiLevelForVendorModules *string `json:",omitempty"`
DeviceSystemSdkVersions []string `json:",omitempty"`
+ DeviceMaxPageSizeSupported *string `json:",omitempty"`
RecoverySnapshotVersion *string `json:",omitempty"`
@@ -305,6 +307,8 @@
MemtagHeapAsyncIncludePaths []string `json:",omitempty"`
MemtagHeapSyncIncludePaths []string `json:",omitempty"`
+ HWASanIncludePaths []string `json:",omitempty"`
+
VendorPath *string `json:",omitempty"`
OdmPath *string `json:",omitempty"`
ProductPath *string `json:",omitempty"`
@@ -442,6 +446,7 @@
BuildBrokenDepfile *bool `json:",omitempty"`
BuildBrokenEnforceSyspropOwner bool `json:",omitempty"`
BuildBrokenTrebleSyspropNeverallow bool `json:",omitempty"`
+ BuildBrokenUsesSoongPython2Modules bool `json:",omitempty"`
BuildBrokenVendorPropertyNamespace bool `json:",omitempty"`
BuildBrokenInputDirModules []string `json:",omitempty"`
@@ -460,7 +465,10 @@
IgnorePrefer32OnDevice bool `json:",omitempty"`
- IncludeTags []string `json:",omitempty"`
+ IncludeTags []string `json:",omitempty"`
+ SourceRootDirs []string `json:",omitempty"`
+
+ AfdoProfiles []string `json:",omitempty"`
}
func boolPtr(v bool) *bool {
@@ -479,13 +487,14 @@
*v = productVariables{
BuildNumberFile: stringPtr("build_number.txt"),
- Platform_version_name: stringPtr("S"),
- Platform_base_sdk_extension_version: intPtr(30),
- Platform_sdk_version: intPtr(30),
- Platform_sdk_codename: stringPtr("S"),
- Platform_sdk_final: boolPtr(false),
- Platform_version_active_codenames: []string{"S"},
- Platform_vndk_version: stringPtr("S"),
+ Platform_version_name: stringPtr("S"),
+ Platform_base_sdk_extension_version: intPtr(30),
+ Platform_sdk_version: intPtr(30),
+ Platform_sdk_codename: stringPtr("S"),
+ Platform_sdk_final: boolPtr(false),
+ Platform_version_active_codenames: []string{"S"},
+ Platform_version_all_preview_codenames: []string{"S"},
+ Platform_vndk_version: stringPtr("S"),
HostArch: stringPtr("x86_64"),
HostSecondaryArch: stringPtr("x86"),
@@ -499,6 +508,7 @@
DeviceSecondaryArchVariant: stringPtr("armv8-a"),
DeviceSecondaryCpuVariant: stringPtr("generic"),
DeviceSecondaryAbi: []string{"armeabi-v7a", "armeabi"},
+ DeviceMaxPageSizeSupported: stringPtr("4096"),
AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
AAPTPreferredConfig: stringPtr("xhdpi"),
diff --git a/android/visibility.go b/android/visibility.go
index 5955133..3130135 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -47,7 +47,6 @@
// the dependency. If it cannot then an error is reported.
//
// TODO(b/130631145) - Make visibility work properly with prebuilts.
-// TODO(b/130796911) - Make visibility work properly with defaults.
// Patterns for the values that can be specified in visibility property.
const (
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 7f03621..684833d 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -63,15 +63,17 @@
}
// Return the full module name for a dependency module, which appends the apex module name unless re-using a system lib.
-func (a *apexBundle) fullModuleName(apexBundleName string, fi *apexFile) string {
- linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform()
-
+func (a *apexBundle) fullModuleName(apexBundleName string, linkToSystemLib bool, fi *apexFile) string {
if linkToSystemLib {
return fi.androidMkModuleName
}
return fi.androidMkModuleName + "." + apexBundleName + a.suffix
}
+// androidMkForFiles generates Make definitions for the contents of an
+// apexBundle (apexBundle#filesInfo). The filesInfo structure can either be
+// populated by Soong for unconverted APEXes, or Bazel in mixed mode. Use
+// apexFile#isBazelPrebuilt to differentiate.
func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, moduleDir string,
apexAndroidMkData android.AndroidMkData) []string {
@@ -95,8 +97,7 @@
for _, fi := range a.filesInfo {
linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform()
-
- moduleName := a.fullModuleName(apexBundleName, &fi)
+ moduleName := a.fullModuleName(apexBundleName, linkToSystemLib, &fi)
// This name will be added to LOCAL_REQUIRED_MODULES of the APEX. We need to be
// arch-specific otherwise we will end up installing both ABIs even when only
@@ -124,6 +125,7 @@
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
}
fmt.Fprintln(w, "LOCAL_MODULE :=", moduleName)
+
if fi.module != nil && fi.module.Owner() != "" {
fmt.Fprintln(w, "LOCAL_MODULE_OWNER :=", fi.module.Owner())
}
@@ -161,6 +163,7 @@
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", fi.builtFile.String())
fmt.Fprintln(w, "LOCAL_MODULE_CLASS :=", fi.class.nameInMake())
if fi.module != nil {
+ // This apexFile's module comes from Soong
archStr := fi.module.Target().Arch.ArchType.String()
host := false
switch fi.module.Target().Os.Class {
@@ -188,6 +191,9 @@
fmt.Fprintln(w, "LOCAL_MODULE_HOST_OS :=", makeOs)
fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
}
+ } else if fi.isBazelPrebuilt && fi.arch != "" {
+ // This apexFile comes from Bazel
+ fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", fi.arch)
}
if fi.jacocoReportClassesFile != nil {
fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", fi.jacocoReportClassesFile.String())
@@ -231,17 +237,21 @@
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_android_app_set.mk")
case nativeSharedLib, nativeExecutable, nativeTest:
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.stem())
- if ccMod, ok := fi.module.(*cc.Module); ok {
- if ccMod.UnstrippedOutputFile() != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", ccMod.UnstrippedOutputFile().String())
- }
- ccMod.AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
- if ccMod.CoverageOutputFile().Valid() {
- fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", ccMod.CoverageOutputFile().String())
- }
- } else if rustMod, ok := fi.module.(*rust.Module); ok {
- if rustMod.UnstrippedOutputFile() != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", rustMod.UnstrippedOutputFile().String())
+ if fi.isBazelPrebuilt {
+ fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", fi.unstrippedBuiltFile)
+ } else {
+ if ccMod, ok := fi.module.(*cc.Module); ok {
+ if ccMod.UnstrippedOutputFile() != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", ccMod.UnstrippedOutputFile().String())
+ }
+ ccMod.AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
+ if ccMod.CoverageOutputFile().Valid() {
+ fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", ccMod.CoverageOutputFile().String())
+ }
+ } else if rustMod, ok := fi.module.(*rust.Module); ok {
+ if rustMod.UnstrippedOutputFile() != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", rustMod.UnstrippedOutputFile().String())
+ }
}
}
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk")
diff --git a/apex/apex.go b/apex/apex.go
index f506876..69547c3 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -103,12 +103,13 @@
// to avoid mistakes. When set as true, no force-labelling.
Use_file_contexts_as_is *bool
- // 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.
+ // Path to the canned fs config file for customizing file's
+ // uid/gid/mod/capabilities. The content of this file is appended to the
+ // default config, so that the custom entries are preferred. 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.
Canned_fs_config *string `android:"path"`
ApexNativeDependencies
@@ -509,6 +510,21 @@
shBinary
)
+var (
+ classes = map[string]apexFileClass{
+ "app": app,
+ "appSet": appSet,
+ "etc": etc,
+ "goBinary": goBinary,
+ "javaSharedLib": javaSharedLib,
+ "nativeExecutable": nativeExecutable,
+ "nativeSharedLib": nativeSharedLib,
+ "nativeTest": nativeTest,
+ "pyBinary": pyBinary,
+ "shBinary": shBinary,
+ }
+)
+
// apexFile represents a file in an APEX bundle. This is created during the first half of
// GenerateAndroidBuildActions by traversing the dependencies of the APEX. Then in the second half
// of the function, this is used to create commands that copies the files into a staging directory,
@@ -543,6 +559,10 @@
multilib string
+ isBazelPrebuilt bool
+ unstrippedBuiltFile android.Path
+ arch string
+
// TODO(jiyong): remove this
module android.Module
}
@@ -974,6 +994,9 @@
if !useVndk {
mctx.PropertyErrorf("use_vndk_as_stable", "not supported for system/system_ext APEXes")
}
+ if a.minSdkVersionValue(mctx) != "" {
+ mctx.PropertyErrorf("use_vndk_as_stable", "not supported when min_sdk_version is set")
+ }
mctx.VisitDirectDepsWithTag(sharedLibTag, func(dep android.Module) {
if c, ok := dep.(*cc.Module); ok && c.IsVndk() {
mctx.PropertyErrorf("use_vndk_as_stable", "Trying to include a VNDK library(%s) while use_vndk_as_stable is true.", dep.Name())
@@ -1041,6 +1064,10 @@
apexVariationName := mctx.ModuleName() // could be com.android.foo
a.properties.ApexVariationName = apexVariationName
+ testApexes := []string{}
+ if a.testApex {
+ testApexes = []string{apexVariationName}
+ }
apexInfo := android.ApexInfo{
ApexVariationName: apexVariationName,
MinSdkVersion: minSdkVersion,
@@ -1049,6 +1076,7 @@
InApexVariants: []string{apexVariationName},
InApexModules: []string{a.Name()}, // could be com.mycompany.android.foo
ApexContents: []*android.ApexContents{apexContents},
+ TestApexes: testApexes,
}
mctx.WalkDeps(func(child, parent android.Module) bool {
if !continueApexDepsWalk(child, parent) {
@@ -1636,7 +1664,6 @@
if ccMod.Target().NativeBridge == android.NativeBridgeEnabled {
dirInApex = filepath.Join(dirInApex, ccMod.Target().NativeBridgeRelativePath)
}
- dirInApex = filepath.Join(dirInApex, ccMod.RelativeInstallPath())
if handleSpecialLibs && cc.InstallToBootstrap(ccMod.BaseModuleName(), ctx.Config()) {
// Special case for Bionic libs and other libs installed with them. This is to
// prevent those libs from being included in the search path
@@ -1649,6 +1676,10 @@
// loading of them, which isn't supported.
dirInApex = filepath.Join(dirInApex, "bionic")
}
+ // This needs to go after the runtime APEX handling because otherwise we would get
+ // weird paths like lib64/rel_install_path/bionic rather than
+ // lib64/bionic/rel_install_path.
+ dirInApex = filepath.Join(dirInApex, ccMod.RelativeInstallPath())
fileToCopy := android.OutputFileForModule(ctx, ccMod, "")
androidMkModuleName := ccMod.BaseModuleName() + ccMod.Properties.SubName
@@ -1710,6 +1741,7 @@
// NB: Since go binaries are static we don't need the module for anything here, which is
// good since the go tool is a blueprint.Module not an android.Module like we would
// normally use.
+ //
return newApexFile(ctx, fileToCopy, depName, dirInApex, goBinary, nil)
}
@@ -1919,7 +1951,7 @@
var _ android.MixedBuildBuildable = (*apexBundle)(nil)
func (a *apexBundle) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
- return ctx.ModuleType() == "apex" && a.properties.ApexType == imageApex
+ return a.properties.ApexType == imageApex
}
func (a *apexBundle) QueueBazelCall(ctx android.BaseModuleContext) {
@@ -1962,9 +1994,9 @@
// Set the output file to .apex or .capex depending on the compression configuration.
a.setCompression(ctx)
if a.isCompressed {
- a.outputApexFile = android.PathForBazelOut(ctx, outputs.SignedCompressedOutput)
+ a.outputApexFile = android.PathForBazelOutRelative(ctx, ctx.ModuleDir(), outputs.SignedCompressedOutput)
} else {
- a.outputApexFile = android.PathForBazelOut(ctx, outputs.SignedOutput)
+ a.outputApexFile = android.PathForBazelOutRelative(ctx, ctx.ModuleDir(), outputs.SignedOutput)
}
a.outputFile = a.outputApexFile
@@ -2003,13 +2035,41 @@
panic(fmt.Errorf("internal error: unexpected apex_type for the ProcessBazelQueryResponse: %v", a.properties.ApexType))
}
- // filesInfo is not set in mixed mode, because all information about the
- // apex's contents should completely come from the Starlark providers.
+ // filesInfo in mixed mode must retrieve all information about the apex's
+ // contents completely from the Starlark providers. It should never rely on
+ // Android.bp information, as they might not exist for fully migrated
+ // dependencies.
//
// Prevent accidental writes to filesInfo in the earlier parts Soong by
// asserting it to be nil.
if a.filesInfo != nil {
- panic(fmt.Errorf("internal error: filesInfo must be nil for an apex handled by Bazel."))
+ panic(
+ fmt.Errorf("internal error: filesInfo must be nil for an apex handled by Bazel. " +
+ "Did something else set filesInfo before this line of code?"))
+ }
+ for _, f := range outputs.PayloadFilesInfo {
+ fileInfo := apexFile{
+ isBazelPrebuilt: true,
+
+ builtFile: android.PathForBazelOut(ctx, f["built_file"]),
+ unstrippedBuiltFile: android.PathForBazelOut(ctx, f["unstripped_built_file"]),
+ androidMkModuleName: f["make_module_name"],
+ installDir: f["install_dir"],
+ class: classes[f["class"]],
+ customStem: f["basename"],
+ moduleDir: f["package"],
+ }
+
+ arch := f["arch"]
+ fileInfo.arch = arch
+ if len(arch) > 0 {
+ fileInfo.multilib = "lib32"
+ if strings.HasSuffix(arch, "64") {
+ fileInfo.multilib = "lib64"
+ }
+ }
+
+ a.filesInfo = append(a.filesInfo, fileInfo)
}
}
@@ -2780,7 +2840,7 @@
if !baseModuleIsApex {
panic(fmt.Errorf("Base module is not apex module: %s", baseApexModuleName))
}
- attrs, props := convertWithBp2build(a, ctx)
+ attrs, props, commonAttrs := convertWithBp2build(a, ctx)
// We just want the name, not module reference.
baseApexName := strings.TrimPrefix(baseApexModuleName, ":")
@@ -2854,7 +2914,9 @@
}
}
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: o.Name()}, &attrs)
+ commonAttrs.Name = o.Name()
+
+ ctx.CreateBazelTargetModule(props, commonAttrs, &attrs)
}
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -2898,12 +2960,8 @@
}
// Returns apex's min_sdk_version SdkSpec, honoring overrides
-func (a *apexBundle) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
- return android.SdkSpec{
- Kind: android.SdkNone,
- ApiLevel: a.minSdkVersion(ctx),
- Raw: a.minSdkVersionValue(ctx),
- }
+func (a *apexBundle) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+ return a.minSdkVersion(ctx)
}
// Returns apex's min_sdk_version ApiLevel, honoring overrides
@@ -2977,8 +3035,8 @@
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 proptools.Bool(a.properties.Use_vndk_as_stable) {
+ ctx.PropertyErrorf("use_vndk_as_stable", "updatable APEXes can't use external VNDK libs")
}
if a.FutureUpdatable() {
ctx.PropertyErrorf("future_updatable", "Already updatable. Remove `future_updatable: true:`")
@@ -3469,6 +3527,7 @@
Manifest bazel.LabelAttribute
Android_manifest bazel.LabelAttribute
File_contexts bazel.LabelAttribute
+ Canned_fs_config bazel.LabelAttribute
Key bazel.LabelAttribute
Certificate bazel.LabelAttribute // used when the certificate prop is a module
Certificate_name bazel.StringAttribute // used when the certificate prop is a string
@@ -3502,17 +3561,12 @@
return
}
- attrs, props := convertWithBp2build(a, ctx)
- commonAttrs := android.CommonAttributes{
- Name: a.Name(),
- }
- if a.testApex {
- commonAttrs.Testonly = proptools.BoolPtr(a.testApex)
- }
+ attrs, props, commonAttrs := convertWithBp2build(a, ctx)
+ commonAttrs.Name = a.Name()
ctx.CreateBazelTargetModule(props, commonAttrs, &attrs)
}
-func convertWithBp2build(a *apexBundle, ctx android.TopDownMutatorContext) (bazelApexBundleAttributes, bazel.BazelTargetModuleProperties) {
+func convertWithBp2build(a *apexBundle, ctx android.TopDownMutatorContext) (bazelApexBundleAttributes, bazel.BazelTargetModuleProperties, android.CommonAttributes) {
var manifestLabelAttribute bazel.LabelAttribute
manifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json")))
@@ -3533,6 +3587,11 @@
fileContextsLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.File_contexts))
}
+ var cannedFsConfigAttribute bazel.LabelAttribute
+ if a.properties.Canned_fs_config != nil {
+ cannedFsConfigAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.Canned_fs_config))
+ }
+
productVariableProps := android.ProductVariableProperties(ctx, a)
// TODO(b/219503907) this would need to be set to a.MinSdkVersionValue(ctx) but
// given it's coming via config, we probably don't want to put it in here.
@@ -3619,6 +3678,7 @@
Manifest: manifestLabelAttribute,
Android_manifest: androidManifestLabelAttribute,
File_contexts: fileContextsLabelAttribute,
+ Canned_fs_config: cannedFsConfigAttribute,
Min_sdk_version: minSdkVersion,
Key: keyLabelAttribute,
Certificate: certificate,
@@ -3640,7 +3700,12 @@
Bzl_load_location: "//build/bazel/rules/apex:apex.bzl",
}
- return attrs, props
+ commonAttrs := android.CommonAttributes{}
+ if a.testApex {
+ commonAttrs.Testonly = proptools.BoolPtr(true)
+ }
+
+ return attrs, props, commonAttrs
}
// The following conversions are based on this table where the rows are the compile_multilib
@@ -3746,3 +3811,7 @@
func invalidCompileMultilib(ctx android.TopDownMutatorContext, value string) {
ctx.PropertyErrorf("compile_multilib", "Invalid value: %s", value)
}
+
+func (a *apexBundle) IsTestApex() bool {
+ return a.testApex
+}
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index 1581949..ebc35cf 100644
--- a/apex/apex_singleton.go
+++ b/apex/apex_singleton.go
@@ -23,7 +23,11 @@
)
func init() {
- android.RegisterSingletonType("apex_depsinfo_singleton", apexDepsInfoSingletonFactory)
+ registerApexDepsInfoComponents(android.InitRegistrationContext)
+}
+
+func registerApexDepsInfoComponents(ctx android.RegistrationContext) {
+ ctx.RegisterSingletonType("apex_depsinfo_singleton", apexDepsInfoSingletonFactory)
}
type apexDepsInfoSingleton struct {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 1f33eca..31b7ef7 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -1001,7 +1001,7 @@
// Ensure that stub dependency from a rust module is not included
ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.shared_from_rust.so")
// The rust module is linked to the stub cc library
- rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").Args["linkFlags"]
+ rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustLink").Args["linkFlags"]
ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so")
ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so")
@@ -1077,7 +1077,7 @@
mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
- rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").Args["linkFlags"]
+ rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustLink").Args["linkFlags"]
ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so")
ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so")
}
@@ -1927,13 +1927,13 @@
expectNoLink("libx", "shared_apex10000", "libz", "shared")
}
-func TestApexMinSdkVersion_crtobjectInVendorApex(t *testing.T) {
+func TestApexMinSdkVersion_InVendorApex(t *testing.T) {
ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib"],
- updatable: false,
+ updatable: true,
vendor: true,
min_sdk_version: "29",
}
@@ -1946,26 +1946,127 @@
cc_library {
name: "mylib",
+ srcs: ["mylib.cpp"],
vendor_available: true,
- system_shared_libs: [],
- stl: "none",
- apex_available: [ "myapex" ],
min_sdk_version: "29",
+ shared_libs: ["libbar"],
+ }
+
+ cc_library {
+ name: "libbar",
+ stubs: { versions: ["29", "30"] },
+ llndk: { symbol_file: "libbar.map.txt" },
}
`)
vendorVariant := "android_vendor.29_arm64_armv8-a"
- // First check that the correct variant of crtbegin_so is used.
- ldRule := ctx.ModuleForTests("mylib", vendorVariant+"_shared_apex29").Rule("ld")
- crtBegin := names(ldRule.Args["crtBegin"])
- ensureListContains(t, crtBegin, "out/soong/.intermediates/"+cc.DefaultCcCommonTestModulesDir+"crtbegin_so/"+vendorVariant+"_apex29/crtbegin_so.o")
+ mylib := ctx.ModuleForTests("mylib", vendorVariant+"_shared_myapex")
+
+ // Ensure that mylib links with "current" LLNDK
+ libFlags := names(mylib.Rule("ld").Args["libFlags"])
+ ensureListContains(t, libFlags, "out/soong/.intermediates/libbar/"+vendorVariant+"_shared_current/libbar.so")
+
+ // Ensure that mylib is targeting 29
+ ccRule := ctx.ModuleForTests("mylib", vendorVariant+"_static_apex29").Output("obj/mylib.o")
+ ensureContains(t, ccRule.Args["cFlags"], "-target aarch64-linux-android29")
+
+ // Ensure that the correct variant of crtbegin_so is used.
+ crtBegin := mylib.Rule("ld").Args["crtBegin"]
+ ensureContains(t, crtBegin, "out/soong/.intermediates/"+cc.DefaultCcCommonTestModulesDir+"crtbegin_so/"+vendorVariant+"_apex29/crtbegin_so.o")
// Ensure that the crtbegin_so used by the APEX is targeting 29
cflags := ctx.ModuleForTests("crtbegin_so", vendorVariant+"_apex29").Rule("cc").Args["cFlags"]
android.AssertStringDoesContain(t, "cflags", cflags, "-target aarch64-linux-android29")
}
+func TestTrackAllowedDeps(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: true,
+ native_shared_libs: [
+ "mylib",
+ "yourlib",
+ ],
+ min_sdk_version: "29",
+ }
+
+ apex {
+ name: "myapex2",
+ key: "myapex.key",
+ updatable: false,
+ native_shared_libs: ["yourlib"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["libbar"],
+ min_sdk_version: "29",
+ apex_available: ["myapex"],
+ }
+
+ cc_library {
+ name: "libbar",
+ stubs: { versions: ["29", "30"] },
+ }
+
+ cc_library {
+ name: "yourlib",
+ srcs: ["mylib.cpp"],
+ min_sdk_version: "29",
+ apex_available: ["myapex", "myapex2", "//apex_available:platform"],
+ }
+ `, withFiles(android.MockFS{
+ "packages/modules/common/build/allowed_deps.txt": nil,
+ }))
+
+ depsinfo := ctx.SingletonForTests("apex_depsinfo_singleton")
+ inputs := depsinfo.Rule("generateApexDepsInfoFilesRule").BuildParams.Inputs.Strings()
+ android.AssertStringListContains(t, "updatable myapex should generate depsinfo file", inputs,
+ "out/soong/.intermediates/myapex/android_common_myapex_image/depsinfo/flatlist.txt")
+ android.AssertStringListDoesNotContain(t, "non-updatable myapex2 should not generate depsinfo file", inputs,
+ "out/soong/.intermediates/myapex2/android_common_myapex2_image/depsinfo/flatlist.txt")
+
+ myapex := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+ flatlist := strings.Split(myapex.Output("depsinfo/flatlist.txt").BuildParams.Args["content"], "\\n")
+ android.AssertStringListContains(t, "deps with stubs should be tracked in depsinfo as external dep",
+ flatlist, "libbar(minSdkVersion:(no version)) (external)")
+ android.AssertStringListDoesNotContain(t, "do not track if not available for platform",
+ flatlist, "mylib:(minSdkVersion:29)")
+ android.AssertStringListContains(t, "track platform-available lib",
+ flatlist, "yourlib(minSdkVersion:29)")
+}
+
+func TestTrackAllowedDeps_SkipWithoutAllowedDepsTxt(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: true,
+ min_sdk_version: "29",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `)
+ depsinfo := ctx.SingletonForTests("apex_depsinfo_singleton")
+ if nil != depsinfo.MaybeRule("generateApexDepsInfoFilesRule").Output {
+ t.Error("apex_depsinfo_singleton shouldn't run when allowed_deps.txt doesn't exist")
+ }
+}
+
func TestPlatformUsesLatestStubsFromApexes(t *testing.T) {
ctx := testApex(t, `
apex {
@@ -5267,7 +5368,16 @@
apex_set {
name: "myapex",
set: "myapex.apks",
+ exported_java_libs: ["myjavalib"],
exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ exported_systemserverclasspath_fragments: ["my-systemserverclasspath-fragment"],
+ }
+
+ java_import {
+ name: "myjavalib",
+ jars: ["myjavalib.jar"],
+ apex_available: ["myapex"],
+ permitted_packages: ["javalib"],
}
prebuilt_bootclasspath_fragment {
@@ -5284,6 +5394,12 @@
},
}
+ prebuilt_systemserverclasspath_fragment {
+ name: "my-systemserverclasspath-fragment",
+ contents: ["libbaz"],
+ apex_available: ["myapex"],
+ }
+
java_import {
name: "libfoo",
jars: ["libfoo.jar"],
@@ -5300,6 +5416,16 @@
shared_library: false,
permitted_packages: ["bar"],
}
+
+ java_sdk_library_import {
+ name: "libbaz",
+ public: {
+ jars: ["libbaz.jar"],
+ },
+ apex_available: ["myapex"],
+ shared_library: false,
+ permitted_packages: ["baz"],
+ }
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
@@ -5312,6 +5438,24 @@
my-bootclasspath-fragment/index.csv
out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
`)
+
+ myApex := ctx.ModuleForTests("myapex", "android_common_myapex").Module()
+
+ overrideNames := []string{
+ "",
+ "myjavalib.myapex",
+ "libfoo.myapex",
+ "libbar.myapex",
+ "libbaz.myapex",
+ }
+ mkEntries := android.AndroidMkEntriesForTest(t, ctx, myApex)
+ for i, e := range mkEntries {
+ g := e.OverrideName
+ if w := overrideNames[i]; w != g {
+ t.Errorf("Expected override name %q, got %q", w, g)
+ }
+ }
+
})
t.Run("prebuilt with source library preferred", func(t *testing.T) {
@@ -7087,7 +7231,7 @@
native_shared_libs: ["mylib"],
java_libs: ["myjar"],
updatable: true,
- min_sdk_version: "current",
+ min_sdk_version: "33",
}
apex_key {
@@ -7110,7 +7254,7 @@
"myapex.updatable",
"//apex_available:platform",
],
- min_sdk_version: "current",
+ min_sdk_version: "33",
}
cc_library {
@@ -7123,7 +7267,7 @@
"myapex.updatable",
"//apex_available:platform",
],
- min_sdk_version: "current",
+ min_sdk_version: "33",
}
cc_library {
@@ -7137,7 +7281,7 @@
"myapex.updatable",
"//apex_available:platform",
],
- min_sdk_version: "current",
+ min_sdk_version: "33",
}
java_library {
@@ -7151,7 +7295,7 @@
"myapex.updatable",
"//apex_available:platform",
],
- min_sdk_version: "current",
+ min_sdk_version: "33",
}
java_library {
@@ -7164,7 +7308,7 @@
"myapex.updatable",
"//apex_available:platform",
],
- min_sdk_version: "current",
+ min_sdk_version: "33",
}
`
@@ -7501,6 +7645,7 @@
"some-updatable-apex",
],
permitted_packages: ["some.updatable.apex.lib"],
+ min_sdk_version: "33",
}
java_library {
@@ -7540,6 +7685,7 @@
],
hostdex: true,
compile_dex: true,
+ min_sdk_version: "33",
}
apex {
@@ -7547,7 +7693,7 @@
key: "some-updatable-apex.key",
java_libs: ["some-updatable-apex-lib"],
updatable: true,
- min_sdk_version: "current",
+ min_sdk_version: "33",
}
apex {
@@ -7570,7 +7716,7 @@
key: "com.android.art.debug.key",
bootclasspath_fragments: ["art-bootclasspath-fragment"],
updatable: true,
- min_sdk_version: "current",
+ min_sdk_version: "33",
}
bootclasspath_fragment {
@@ -7860,12 +8006,13 @@
`)
}
-func TestUpdatable_cannot_be_vendor_apex(t *testing.T) {
- testApexError(t, `"myapex" .*: updatable: vendor APEXes are not updatable`, `
+func Test_use_vndk_as_stable_shouldnt_be_used_for_updatable_vendor_apexes(t *testing.T) {
+ testApexError(t, `"myapex" .*: use_vndk_as_stable: updatable APEXes can't use external VNDK libs`, `
apex {
name: "myapex",
key: "myapex.key",
updatable: true,
+ use_vndk_as_stable: true,
soc_specific: true,
}
@@ -7877,6 +8024,42 @@
`)
}
+func Test_use_vndk_as_stable_shouldnt_be_used_with_min_sdk_version(t *testing.T) {
+ testApexError(t, `"myapex" .*: use_vndk_as_stable: not supported when min_sdk_version is set`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: false,
+ min_sdk_version: "29",
+ use_vndk_as_stable: true,
+ vendor: true,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `)
+}
+
+func Test_use_vndk_as_stable_shouldnt_be_used_for_non_vendor_apexes(t *testing.T) {
+ testApexError(t, `"myapex" .*: use_vndk_as_stable: not supported for system/system_ext APEXes`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: false,
+ use_vndk_as_stable: 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 {
@@ -10054,3 +10237,45 @@
android.AssertStringDoesContain(t, "missing lib to trim", libs_to_trim, "libbar")
android.AssertStringDoesNotContain(t, "unexpected libs in the libs to trim", libs_to_trim, "libbaz")
}
+
+func TestCannedFsConfig(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }`)
+ mod := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+ generateFsRule := mod.Rule("generateFsConfig")
+ cmd := generateFsRule.RuleParams.Command
+
+ ensureContains(t, cmd, `( echo '/ 1000 1000 0755'; echo '/apex_manifest.json 1000 1000 0644'; echo '/apex_manifest.pb 1000 1000 0644'; ) >`)
+}
+
+func TestCannedFsConfig_HasCustomConfig(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ canned_fs_config: "my_config",
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }`)
+ mod := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+ generateFsRule := mod.Rule("generateFsConfig")
+ cmd := generateFsRule.RuleParams.Command
+
+ // Ensure that canned_fs_config has "cat my_config" at the end
+ ensureContains(t, cmd, `( echo '/ 1000 1000 0755'; echo '/apex_manifest.json 1000 1000 0644'; echo '/apex_manifest.pb 1000 1000 0644'; cat my_config ) >`)
+}
diff --git a/apex/bp2build_test.go b/apex/bp2build_test.go
index 2f2b61e..2a0f6e9 100644
--- a/apex/bp2build_test.go
+++ b/apex/bp2build_test.go
@@ -25,6 +25,7 @@
apex_key{
name: "foo_key",
}
+
apex {
name: "foo",
key: "foo_key",
@@ -59,6 +60,16 @@
ProvidesLibs: []string{"a", "b"},
// ApexMkInfo Starlark provider
+ PayloadFilesInfo: []map[string]string{
+ {
+ "built_file": "bazel-out/adbd",
+ "install_dir": "bin",
+ "class": "nativeExecutable",
+ "make_module_name": "adbd",
+ "basename": "adbd",
+ "package": "foo",
+ },
+ },
MakeModulesToInstall: []string{"c"}, // d deliberately omitted
},
},
@@ -68,10 +79,12 @@
m := result.ModuleForTests("foo", "android_common_foo_image").Module()
ab, ok := m.(*apexBundle)
+
if !ok {
t.Fatalf("Expected module to be an apexBundle, was not")
}
+ // TODO: refactor to android.AssertStringEquals
if w, g := "out/bazel/execroot/__main__/public_key", ab.publicKeyFile.String(); w != g {
t.Errorf("Expected public key %q, got %q", w, g)
}
@@ -120,11 +133,136 @@
if len(ab.makeModulesToInstall) != 1 && ab.makeModulesToInstall[0] != "c" {
t.Errorf("Expected makeModulesToInstall slice to only contain 'c', got %q", ab.makeModulesToInstall)
}
- if w := "LOCAL_REQUIRED_MODULES := c"; !strings.Contains(data, w) {
+ if w := "LOCAL_REQUIRED_MODULES := adbd.foo c"; !strings.Contains(data, w) {
t.Errorf("Expected %q in androidmk data, but did not find it in %q", w, data)
}
}
+func TestApexImageCreatesFilesInfoForMake(t *testing.T) {
+ bp := `
+apex_key{
+ name: "foo_key",
+}
+
+apex {
+ name: "foo",
+ key: "foo_key",
+ updatable: true,
+ min_sdk_version: "31",
+ file_contexts: ":myapex-file_contexts",
+ bazel_module: { label: "//:foo" },
+}`
+
+ outputBaseDir := "out/bazel"
+ result := android.GroupFixturePreparers(
+ prepareForApexTest,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: outputBaseDir,
+ LabelToApexInfo: map[string]cquery.ApexInfo{
+ "//:foo": {
+ // ApexInfo Starlark provider. Necessary for the test.
+ SignedOutput: "signed_out.apex",
+ BundleKeyInfo: []string{"public_key", "private_key"},
+ ContainerKeyInfo: []string{"container_cert", "container_private"},
+
+ // ApexMkInfo Starlark provider
+ PayloadFilesInfo: []map[string]string{
+ {
+ "arch": "arm64",
+ "basename": "libcrypto.so",
+ "built_file": "bazel-out/64/libcrypto.so",
+ "class": "nativeSharedLib",
+ "install_dir": "lib64",
+ "make_module_name": "libcrypto",
+ "package": "foo/bar",
+ "unstripped_built_file": "bazel-out/64/unstripped_libcrypto.so",
+ },
+ {
+ "arch": "arm",
+ "basename": "libcrypto.so",
+ "built_file": "bazel-out/32/libcrypto.so",
+ "class": "nativeSharedLib",
+ "install_dir": "lib",
+ "make_module_name": "libcrypto",
+ "package": "foo/bar",
+ },
+ {
+ "arch": "arm64",
+ "basename": "adbd",
+ "built_file": "bazel-out/adbd",
+ "class": "nativeExecutable",
+ "install_dir": "bin",
+ "make_module_name": "adbd",
+ "package": "foo",
+ },
+ },
+ },
+ },
+ }
+ }),
+ ).RunTestWithBp(t, bp)
+
+ m := result.ModuleForTests("foo", "android_common_foo_image").Module()
+ ab, ok := m.(*apexBundle)
+
+ if !ok {
+ t.Fatalf("Expected module to be an apexBundle, was not")
+ }
+
+ expectedFilesInfo := []apexFile{
+ {
+ androidMkModuleName: "libcrypto",
+ builtFile: android.PathForTesting("out/bazel/execroot/__main__/bazel-out/64/libcrypto.so"),
+ class: nativeSharedLib,
+ customStem: "libcrypto.so",
+ installDir: "lib64",
+ moduleDir: "foo/bar",
+ arch: "arm64",
+ unstrippedBuiltFile: android.PathForTesting("out/bazel/execroot/__main__/bazel-out/64/unstripped_libcrypto.so"),
+ },
+ {
+ androidMkModuleName: "libcrypto",
+ builtFile: android.PathForTesting("out/bazel/execroot/__main__/bazel-out/32/libcrypto.so"),
+ class: nativeSharedLib,
+ customStem: "libcrypto.so",
+ installDir: "lib",
+ moduleDir: "foo/bar",
+ arch: "arm",
+ },
+ {
+ androidMkModuleName: "adbd",
+ builtFile: android.PathForTesting("out/bazel/execroot/__main__/bazel-out/adbd"),
+ class: nativeExecutable,
+ customStem: "adbd",
+ installDir: "bin",
+ moduleDir: "foo",
+ arch: "arm64",
+ },
+ }
+
+ if len(ab.filesInfo) != len(expectedFilesInfo) {
+ t.Errorf("Expected %d entries in ab.filesInfo, but got %d", len(ab.filesInfo), len(expectedFilesInfo))
+ }
+
+ for idx, f := range ab.filesInfo {
+ expected := expectedFilesInfo[idx]
+ android.AssertSame(t, "different class", expected.class, f.class)
+ android.AssertStringEquals(t, "different built file", expected.builtFile.String(), f.builtFile.String())
+ android.AssertStringEquals(t, "different custom stem", expected.customStem, f.customStem)
+ android.AssertStringEquals(t, "different install dir", expected.installDir, f.installDir)
+ android.AssertStringEquals(t, "different make module name", expected.androidMkModuleName, f.androidMkModuleName)
+ android.AssertStringEquals(t, "different moduleDir", expected.moduleDir, f.moduleDir)
+ android.AssertStringEquals(t, "different arch", expected.arch, f.arch)
+ if expected.unstrippedBuiltFile != nil {
+ if f.unstrippedBuiltFile == nil {
+ t.Errorf("expected an unstripped built file path.")
+ }
+ android.AssertStringEquals(t, "different unstripped built file", expected.unstrippedBuiltFile.String(), f.unstrippedBuiltFile.String())
+ }
+ }
+}
+
func TestCompressedApexImageInMixedBuilds(t *testing.T) {
bp := `
apex_key{
diff --git a/apex/builder.go b/apex/builder.go
index ee6c473..7c6522d 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -71,6 +71,9 @@
pctx.HostBinToolVariable("make_erofs", "make_erofs")
pctx.HostBinToolVariable("apex_compression_tool", "apex_compression_tool")
pctx.HostBinToolVariable("dexdeps", "dexdeps")
+ pctx.HostBinToolVariable("apex_sepolicy_tests", "apex_sepolicy_tests")
+ pctx.HostBinToolVariable("deapexer", "deapexer")
+ pctx.HostBinToolVariable("debugfs_static", "debugfs_static")
pctx.SourcePathVariable("genNdkUsedbyApexPath", "build/soong/scripts/gen_ndk_usedby_apex.sh")
}
@@ -226,7 +229,12 @@
Description: "Generate symbol list used by Apex",
}, "image_dir", "readelf")
- // Don't add more rules here. Consider using android.NewRuleBuilder instead.
+ apexSepolicyTestsRule = pctx.StaticRule("apexSepolicyTestsRule", blueprint.RuleParams{
+ Command: `${deapexer} --debugfs_path ${debugfs_static} list -Z ${in} > ${out}.fc` +
+ ` && ${apex_sepolicy_tests} -f ${out}.fc && touch ${out}`,
+ CommandDeps: []string{"${apex_sepolicy_tests}", "${deapexer}", "${debugfs_static}"},
+ Description: "run apex_sepolicy_tests",
+ })
)
// buildManifest creates buile rules to modify the input apex_manifest.json to add information
@@ -505,9 +513,6 @@
}
}
implicitInputs = append(implicitInputs, fi.builtFile)
- 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.
@@ -515,8 +520,7 @@
symlinkDest := imageDir.Join(ctx, symlinkPath).String()
copyCommands = append(copyCommands, "ln -sfn "+filepath.Base(destPath)+" "+symlinkDest)
if installSymbolFiles {
- installedSymlink := ctx.InstallSymlink(apexDir.Join(ctx, filepath.Dir(symlinkPath)), filepath.Base(symlinkPath), installedPath)
- implicitInputs = append(implicitInputs, installedSymlink)
+ ctx.InstallSymlink(apexDir.Join(ctx, filepath.Dir(symlinkPath)), filepath.Base(symlinkPath), installedPath)
}
}
@@ -541,11 +545,6 @@
installMapSet[installMapPath.String()+":"+fi.installDir+"/"+fi.builtFile.Base()] = true
}
implicitInputs = append(implicitInputs, a.manifestPbOut)
- if installSymbolFiles {
- installedManifest := ctx.InstallFile(apexDir, "apex_manifest.pb", a.manifestPbOut)
- installedKey := ctx.InstallFile(apexDir, "apex_pubkey", a.publicKeyFile)
- implicitInputs = append(implicitInputs, installedManifest, installedKey)
- }
if len(installMapSet) > 0 {
var installs []string
@@ -872,6 +871,11 @@
args["implicits"] = strings.Join(implicits.Strings(), ",")
args["outCommaList"] = signedOutputFile.String()
}
+ var validations android.Paths
+ // TODO(b/279688635) deapexer supports [ext4]
+ if suffix == imageApexSuffix && ext4 == a.payloadFsType {
+ validations = append(validations, runApexSepolicyTests(ctx, unsignedOutputFile.OutputPath))
+ }
ctx.Build(pctx, android.BuildParams{
Rule: rule,
Description: "signapk",
@@ -879,6 +883,7 @@
Input: unsignedOutputFile,
Implicits: implicits,
Args: args,
+ Validations: validations,
})
if suffix == imageApexSuffix {
a.outputApexFile = signedOutputFile
@@ -1063,10 +1068,10 @@
} else {
toMinSdkVersion := "(no version)"
if m, ok := to.(interface {
- MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec
+ MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel
}); ok {
- if v := m.MinSdkVersion(ctx); !v.ApiLevel.IsNone() {
- toMinSdkVersion = v.ApiLevel.String()
+ if v := m.MinSdkVersion(ctx); !v.IsNone() {
+ toMinSdkVersion = v.String()
}
} else if m, ok := to.(interface{ MinSdkVersion() string }); ok {
// TODO(b/175678607) eliminate the use of MinSdkVersion returning
@@ -1087,7 +1092,7 @@
return !externalDep
})
- a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(ctx).Raw, depInfos)
+ a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(ctx).String(), depInfos)
ctx.Build(pctx, android.BuildParams{
Rule: android.Phony,
@@ -1167,8 +1172,22 @@
if a.properties.Canned_fs_config != nil {
cmd.Text("cat").Input(android.PathForModuleSrc(ctx, *a.properties.Canned_fs_config))
}
- cmd.Text(") | LC_ALL=C sort ").FlagWithOutput("> ", cannedFsConfig)
+ cmd.Text(")").FlagWithOutput("> ", cannedFsConfig)
builder.Build("generateFsConfig", fmt.Sprintf("Generating canned fs config for %s", a.BaseModuleName()))
return cannedFsConfig.OutputPath
}
+
+// Runs apex_sepolicy_tests
+//
+// $ deapexer list -Z {apex_file} > {file_contexts}
+// $ apex_sepolicy_tests -f {file_contexts}
+func runApexSepolicyTests(ctx android.ModuleContext, apexFile android.OutputPath) android.Path {
+ timestamp := android.PathForModuleOut(ctx, "sepolicy_tests.timestamp")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: apexSepolicyTestsRule,
+ Input: apexFile,
+ Output: timestamp,
+ })
+ return timestamp
+}
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 0997a68..31cecf1 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -35,11 +35,12 @@
blueprint.RuleParams{
Command: `rm -rf "$out" && ` +
`${extract_apks} -o "${out}" -allow-prereleased=${allow-prereleased} ` +
- `-sdk-version=${sdk-version} -abis=${abis} -screen-densities=all -extract-single ` +
+ `-sdk-version=${sdk-version} -skip-sdk-check=${skip-sdk-check} -abis=${abis} ` +
+ `-screen-densities=all -extract-single ` +
`${in}`,
CommandDeps: []string{"${extract_apks}"},
},
- "abis", "allow-prereleased", "sdk-version")
+ "abis", "allow-prereleased", "sdk-version", "skip-sdk-check")
)
type prebuilt interface {
@@ -315,31 +316,29 @@
}
}
-func (p *prebuiltCommon) getExportedDependencies() map[string]exportedDependencyTag {
- dependencies := make(map[string]exportedDependencyTag)
-
- for _, dep := range p.prebuiltCommonProperties.Exported_java_libs {
- dependencies[dep] = exportedJavaLibTag
- }
-
- for _, dep := range p.prebuiltCommonProperties.Exported_bootclasspath_fragments {
- dependencies[dep] = exportedBootclasspathFragmentTag
- }
-
- for _, dep := range p.prebuiltCommonProperties.Exported_systemserverclasspath_fragments {
- dependencies[dep] = exportedSystemserverclasspathFragmentTag
- }
-
- return dependencies
+func (p *prebuiltCommon) hasExportedDeps() bool {
+ return len(p.prebuiltCommonProperties.Exported_java_libs) > 0 ||
+ len(p.prebuiltCommonProperties.Exported_bootclasspath_fragments) > 0 ||
+ len(p.prebuiltCommonProperties.Exported_systemserverclasspath_fragments) > 0
}
// prebuiltApexContentsDeps adds dependencies onto the prebuilt apex module's contents.
func (p *prebuiltCommon) prebuiltApexContentsDeps(ctx android.BottomUpMutatorContext) {
module := ctx.Module()
- for dep, tag := range p.getExportedDependencies() {
+ for _, dep := range p.prebuiltCommonProperties.Exported_java_libs {
prebuiltDep := android.PrebuiltNameFromSource(dep)
- ctx.AddDependency(module, tag, prebuiltDep)
+ ctx.AddDependency(module, exportedJavaLibTag, prebuiltDep)
+ }
+
+ for _, dep := range p.prebuiltCommonProperties.Exported_bootclasspath_fragments {
+ prebuiltDep := android.PrebuiltNameFromSource(dep)
+ ctx.AddDependency(module, exportedBootclasspathFragmentTag, prebuiltDep)
+ }
+
+ for _, dep := range p.prebuiltCommonProperties.Exported_systemserverclasspath_fragments {
+ prebuiltDep := android.PrebuiltNameFromSource(dep)
+ ctx.AddDependency(module, exportedSystemserverclasspathFragmentTag, prebuiltDep)
}
}
@@ -607,7 +606,7 @@
// the listed modules need access to files from within the prebuilt .apex file.
func (p *prebuiltCommon) createDeapexerModuleIfNeeded(ctx android.TopDownMutatorContext, deapexerName string, apexFileSource string) {
// Only create the deapexer module if it is needed.
- if len(p.getExportedDependencies()) == 0 {
+ if !p.hasExportedDeps() {
return
}
@@ -845,6 +844,7 @@
"abis": strings.Join(abis, ","),
"allow-prereleased": strconv.FormatBool(proptools.BoolDefault(p.properties.Prerelease, defaultAllowPrerelease)),
"sdk-version": ctx.Config().PlatformSdkVersion().String(),
+ "skip-sdk-check": strconv.FormatBool(ctx.Config().IsEnvTrue("SOONG_SKIP_APPSET_SDK_CHECK")),
},
})
}
diff --git a/apex/testing.go b/apex/testing.go
index 69bd73e..3b200f0 100644
--- a/apex/testing.go
+++ b/apex/testing.go
@@ -19,6 +19,7 @@
var PrepareForTestWithApexBuildComponents = android.GroupFixturePreparers(
android.FixtureRegisterWithContext(registerApexBuildComponents),
android.FixtureRegisterWithContext(registerApexKeyBuildComponents),
+ android.FixtureRegisterWithContext(registerApexDepsInfoComponents),
// Additional files needed in tests that disallow non-existent source files.
// This includes files that are needed by all, or at least most, instances of an apex module type.
android.MockFS{
diff --git a/apex/vndk.go b/apex/vndk.go
index c0be753..095e89d 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -72,12 +72,14 @@
}
targets := mctx.MultiTargets()
- if len(targets) > 0 && apiLevel.LessThan(cc.MinApiForArch(mctx, targets[0].Arch.ArchType)) {
- // Disable VNDK apexes for VNDK versions less than the minimum supported API level for the primary
- // architecture.
+ if len(targets) > 0 && apiLevel.LessThan(cc.MinApiForArch(mctx, targets[0].Arch.ArchType)) &&
+ vndkVersion != mctx.DeviceConfig().PlatformVndkVersion() {
+ // Disable VNDK APEXes for VNDK versions less than the minimum supported API
+ // level for the primary architecture. This validation is skipped if the VNDK
+ // version matches the platform VNDK version, which can occur when the device
+ // config targets the 'current' VNDK (see `vndkVersion`).
ab.Disable()
}
-
}
}
diff --git a/bazel/bazel_proxy.go b/bazel/bazel_proxy.go
index d7f5e64..2940b99 100644
--- a/bazel/bazel_proxy.go
+++ b/bazel/bazel_proxy.go
@@ -128,6 +128,24 @@
}
}
+func ExecBazel(bazelPath string, workspaceDir string, request CmdRequest) (stdout []byte, stderr []byte, cmdErr error) {
+ bazelCmd := exec.Command(bazelPath, request.Argv...)
+ bazelCmd.Dir = workspaceDir
+ bazelCmd.Env = request.Env
+
+ stderrBuffer := &bytes.Buffer{}
+ bazelCmd.Stderr = stderrBuffer
+
+ if output, err := bazelCmd.Output(); err != nil {
+ cmdErr = fmt.Errorf("bazel command failed: %s\n---command---\n%s\n---env---\n%s\n---stderr---\n%s---",
+ err, bazelCmd, strings.Join(bazelCmd.Env, "\n"), stderrBuffer)
+ } else {
+ stdout = output
+ }
+ stderr = stderrBuffer.Bytes()
+ return
+}
+
func (b *ProxyServer) handleRequest(conn net.Conn) error {
defer conn.Close()
@@ -137,23 +155,13 @@
return fmt.Errorf("Error decoding request: %s", err)
}
- bazelCmd := exec.Command("./build/bazel/bin/bazel", req.Argv...)
- bazelCmd.Dir = b.workspaceDir
- bazelCmd.Env = req.Env
-
- stderr := &bytes.Buffer{}
- bazelCmd.Stderr = stderr
- var stdout string
- var bazelErrString string
-
- if output, err := bazelCmd.Output(); err != nil {
- bazelErrString = fmt.Sprintf("bazel command failed: %s\n---command---\n%s\n---env---\n%s\n---stderr---\n%s---",
- err, bazelCmd, strings.Join(bazelCmd.Env, "\n"), stderr)
- } else {
- stdout = string(output)
+ stdout, stderr, cmdErr := ExecBazel("./build/bazel/bin/bazel", b.workspaceDir, req)
+ errorString := ""
+ if cmdErr != nil {
+ errorString = cmdErr.Error()
}
- resp := CmdResponse{stdout, string(stderr.Bytes()), bazelErrString}
+ resp := CmdResponse{string(stdout), string(stderr), errorString}
enc := gob.NewEncoder(conn)
if err := enc.Encode(&resp); err != nil {
return fmt.Errorf("Error encoding response: %s", err)
diff --git a/bazel/configurability.go b/bazel/configurability.go
index 4680256..d01877d 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -268,9 +268,8 @@
case productVariables:
// do nothing
case osAndInApex:
- if _, ok := osAndInApexMap[config]; !ok {
- panic(fmt.Errorf("Unknown os+in_apex config: %s", config))
- }
+ // do nothing
+ // this axis can contain additional per-apex keys
case inApex:
if _, ok := inApexMap[config]; !ok {
panic(fmt.Errorf("Unknown in_apex config: %s", config))
@@ -299,7 +298,10 @@
}
return fmt.Sprintf("%s:%s", productVariableBazelPackage, config)
case osAndInApex:
- return osAndInApexMap[config]
+ if ret, exists := osAndInApexMap[config]; exists {
+ return ret
+ }
+ return config
case inApex:
return inApexMap[config]
default:
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index 0c8247a..6a3b3c8 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -149,6 +149,7 @@
rootSharedLibraries = []
shared_info_tag = "//build/bazel/rules/cc:cc_library_shared.bzl%CcSharedLibraryOutputInfo"
+stubs_tag = "//build/bazel/rules/cc:cc_stub_library.bzl%CcStubInfo"
unstripped_tag = "//build/bazel/rules/cc:stripped_cc_common.bzl%CcUnstrippedInfo"
unstripped = ""
@@ -160,6 +161,8 @@
unstripped = path
if unstripped_tag in p:
unstripped = p[unstripped_tag].unstripped.path
+elif stubs_tag in p:
+ rootSharedLibraries.extend([f.path for f in target.files.to_list()])
else:
for linker_input in linker_inputs:
for library in linker_input.libraries:
@@ -197,7 +200,7 @@
local_whole_static_libs = androidmk_info.local_whole_static_libs
local_shared_libs = androidmk_info.local_shared_libs
-return json_encode({
+return json.encode({
"OutputFiles": outputFiles,
"CcObjectFiles": ccObjectFiles,
"CcSharedLibraryFiles": sharedLibraries,
@@ -266,7 +269,7 @@
if clang_tidy_info:
tidy_files = [v.path for v in clang_tidy_info.transitive_tidy_files.to_list()]
-return json_encode({
+return json.encode({
"signed_output": info.signed_output.path,
"signed_compressed_output": signed_compressed_output,
"unsigned_output": info.unsigned_output.path,
@@ -281,6 +284,7 @@
"bundle_file": info.base_with_config_zip.path,
"installed_files": info.installed_files.path,
"make_modules_to_install": mk_info.make_modules_to_install,
+ "files_info": mk_info.files_info,
"tidy_files": [t for t in tidy_files],
})`
}
@@ -303,7 +307,8 @@
TidyFiles []string `json:"tidy_files"`
// From the ApexMkInfo provider
- MakeModulesToInstall []string `json:"make_modules_to_install"`
+ MakeModulesToInstall []string `json:"make_modules_to_install"`
+ PayloadFilesInfo []map[string]string `json:"files_info"`
}
// ParseResult returns a value obtained by parsing the result of the request's Starlark function.
@@ -333,7 +338,7 @@
unstripped_tag = "//build/bazel/rules/cc:stripped_cc_common.bzl%CcUnstrippedInfo"
if unstripped_tag in p:
unstripped_info = p[unstripped_tag]
- unstripped = unstripped_info.unstripped.files.to_list()[0].path
+ unstripped = unstripped_info.unstripped[0].files.to_list()[0].path
local_static_libs = []
local_whole_static_libs = []
@@ -350,7 +355,7 @@
if clang_tidy_info:
tidy_files = [v.path for v in clang_tidy_info.transitive_tidy_files.to_list()]
-return json_encode({
+return json.encode({
"OutputFile": output_path,
"UnstrippedOutput": unstripped,
"LocalStaticLibs": [l for l in local_static_libs],
diff --git a/bazel/properties.go b/bazel/properties.go
index 40d0ba3..1757bad 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -1424,3 +1424,14 @@
sub := productVariableSubstitutionPattern.ReplaceAllString(s, "$("+productVariable+")")
return sub, s != sub
}
+
+// StringMapAttribute is a map of strings.
+// The use case for this is storing the flag_values in a config_setting object.
+// Bazel rules do not support map attributes, and this should NOT be used in Bazel rules.
+type StringMapAttribute map[string]string
+
+// ConfigSettingAttributes stores the keys of a config_setting object.
+type ConfigSettingAttributes struct {
+ // Each key in Flag_values is a label to a custom string_setting
+ Flag_values StringMapAttribute
+}
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 6edd78a..b6635c4 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -61,6 +61,7 @@
"genrule_conversion_test.go",
"gensrcs_conversion_test.go",
"java_binary_host_conversion_test.go",
+ "java_host_for_device_conversion_test.go",
"java_import_conversion_test.go",
"java_library_conversion_test.go",
"java_library_host_conversion_test.go",
@@ -75,6 +76,7 @@
"prebuilt_etc_conversion_test.go",
"python_binary_conversion_test.go",
"python_library_conversion_test.go",
+ "python_test_conversion_test.go",
"sh_conversion_test.go",
"soong_config_module_type_conversion_test.go",
],
diff --git a/bp2build/aar_conversion_test.go b/bp2build/aar_conversion_test.go
index 0cda5dd..09d9dc1 100644
--- a/bp2build/aar_conversion_test.go
+++ b/bp2build/aar_conversion_test.go
@@ -66,9 +66,12 @@
"resource_files": `["res/res.png"]`,
"deps": `[":static_lib_dep"]`,
"exports": `[":static_lib_dep"]`,
- "javacopts": `["-source 1.7 -target 1.7"]`,
+ "java_version": `"7"`,
}),
- MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
+ MakeNeverlinkDuplicateTargetWithAttrs(
+ "android_library",
+ "TestLib",
+ AttrNameToString{"java_version": `"7"`}),
}})
}
@@ -171,3 +174,39 @@
MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
}})
}
+
+func TestConvertAndroidLibraryKotlinCflags(t *testing.T) {
+ t.Helper()
+ RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
+ Description: "Android Library with .kt srcs and kotlincflags ",
+ ModuleTypeUnderTest: "android_library",
+ ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
+ Filesystem: map[string]string{
+ "AndroidManifest.xml": "",
+ },
+ Blueprint: `
+android_library {
+ name: "TestLib",
+ srcs: ["a.java", "b.kt"],
+ kotlincflags: ["-flag1", "-flag2"],
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget(
+ "android_library",
+ "TestLib",
+ AttrNameToString{
+ "srcs": `[
+ "a.java",
+ "b.kt",
+ ]`,
+ "kotlincflags": `[
+ "-flag1",
+ "-flag2",
+ ]`,
+ "manifest": `"AndroidManifest.xml"`,
+ "resource_files": `[]`,
+ }),
+ MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
+ }})
+}
diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go
index 4d18f83..928a1f2 100644
--- a/bp2build/android_app_conversion_test.go
+++ b/bp2build/android_app_conversion_test.go
@@ -53,6 +53,7 @@
"srcs": `["app.java"]`,
"manifest": `"AndroidManifest.xml"`,
"resource_files": `["res/res.png"]`,
+ "sdk_version": `"current"`,
}),
}})
}
@@ -91,7 +92,8 @@
]`,
"custom_package": `"com.google"`,
"deps": `[":static_lib_dep"]`,
- "javacopts": `["-source 1.7 -target 1.7"]`,
+ "java_version": `"7"`,
+ "sdk_version": `"current"`,
"certificate_name": `"foocert"`,
}),
}})
@@ -131,6 +133,7 @@
})`,
"manifest": `"AndroidManifest.xml"`,
"resource_files": `["res/res.png"]`,
+ "sdk_version": `"current"`,
}),
}})
}
@@ -306,3 +309,90 @@
}),
}})
}
+
+func TestAndroidAppKotlinCflags(t *testing.T) {
+ runAndroidAppTestCase(t, Bp2buildTestCase{
+ Description: "Android app with kotlincflags",
+ ModuleTypeUnderTest: "android_app",
+ ModuleTypeUnderTestFactory: java.AndroidAppFactory,
+ Filesystem: map[string]string{
+ "res/res.png": "",
+ },
+ Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
+android_app {
+ name: "foo",
+ srcs: ["a.java", "b.kt"],
+ certificate: ":foocert",
+ manifest: "fooManifest.xml",
+ kotlincflags: ["-flag1", "-flag2"],
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("android_library", "foo_kt", AttrNameToString{
+ "srcs": `[
+ "a.java",
+ "b.kt",
+ ]`,
+ "manifest": `"fooManifest.xml"`,
+ "resource_files": `["res/res.png"]`,
+ "kotlincflags": `[
+ "-flag1",
+ "-flag2",
+ ]`,
+ }),
+ MakeBazelTarget("android_binary", "foo", AttrNameToString{
+ "deps": `[":foo_kt"]`,
+ "certificate": `":foocert"`,
+ "manifest": `"fooManifest.xml"`,
+ }),
+ }})
+}
+
+func TestAndroidAppMinSdkProvided(t *testing.T) {
+ runAndroidAppTestCase(t, Bp2buildTestCase{
+ Description: "Android app with value for min_sdk_version",
+ ModuleTypeUnderTest: "android_app",
+ ModuleTypeUnderTestFactory: java.AndroidAppFactory,
+ Filesystem: map[string]string{},
+ Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
+android_app {
+ name: "foo",
+ sdk_version: "current",
+ min_sdk_version: "24",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("android_binary", "foo", AttrNameToString{
+ "manifest": `"AndroidManifest.xml"`,
+ "resource_files": `[]`,
+ "manifest_values": `{
+ "minSdkVersion": "24",
+ }`,
+ "sdk_version": `"current"`,
+ }),
+ }})
+}
+
+func TestAndroidAppMinSdkDefaultToSdkVersion(t *testing.T) {
+ runAndroidAppTestCase(t, Bp2buildTestCase{
+ Description: "Android app with value for sdk_version",
+ ModuleTypeUnderTest: "android_app",
+ ModuleTypeUnderTestFactory: java.AndroidAppFactory,
+ Filesystem: map[string]string{},
+ Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
+android_app {
+ name: "foo",
+ sdk_version: "30",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("android_binary", "foo", AttrNameToString{
+ "manifest": `"AndroidManifest.xml"`,
+ "resource_files": `[]`,
+ "manifest_values": `{
+ "minSdkVersion": "30",
+ }`,
+ "sdk_version": `"30"`,
+ }),
+ }})
+}
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
index 73c889f..1cc3f22 100644
--- a/bp2build/apex_conversion_test.go
+++ b/bp2build/apex_conversion_test.go
@@ -58,6 +58,7 @@
ctx.RegisterModuleType("cc_binary", cc.BinaryFactory)
ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
ctx.RegisterModuleType("apex_key", apex.ApexKeyFactory)
+ ctx.RegisterModuleType("apex_test", apex.TestApexBundleFactory)
ctx.RegisterModuleType("android_app_certificate", java.AndroidAppCertificateFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("apex", apex.BundleFactory)
@@ -706,6 +707,125 @@
}})
}
+func TestOverrideApexTest(t *testing.T) {
+ runOverrideApexTestCase(t, Bp2buildTestCase{
+ Description: "override_apex",
+ ModuleTypeUnderTest: "override_apex",
+ ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+ Filesystem: map[string]string{},
+ Blueprint: `
+apex_key {
+ 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",
+ bazel_module: { bp2build_available: false },
+}
+
+prebuilt_etc {
+ name: "prebuilt_1",
+ bazel_module: { bp2build_available: false },
+}
+
+filegroup {
+ name: "com.android.apogee-file_contexts",
+ 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_test {
+ name: "com.android.apogee",
+ manifest: "apogee_manifest.json",
+ androidManifest: "ApogeeAndroidManifest.xml",
+ file_contexts: ":com.android.apogee-file_contexts",
+ min_sdk_version: "29",
+ key: "com.android.apogee.key",
+ certificate: ":com.android.apogee.certificate",
+ updatable: false,
+ installable: false,
+ compressible: false,
+ native_shared_libs: [
+ "native_shared_lib_1",
+ ],
+ binaries: [
+ "cc_binary_1",
+ "sh_binary_2",
+ ],
+ prebuilts: [
+ "prebuilt_1",
+ ],
+ bazel_module: { bp2build_available: false },
+}
+
+apex_key {
+ name: "com.google.android.apogee.key",
+ public_key: "com.google.android.apogee.avbpubkey",
+ private_key: "com.google.android.apogee.pem",
+ bazel_module: { bp2build_available: false },
+}
+
+android_app_certificate {
+ name: "com.google.android.apogee.certificate",
+ certificate: "com.google.android.apogee",
+ bazel_module: { bp2build_available: false },
+}
+
+override_apex {
+ name: "com.google.android.apogee",
+ base: ":com.android.apogee",
+ key: "com.google.android.apogee.key",
+ certificate: ":com.google.android.apogee.certificate",
+ prebuilts: [],
+ compressible: true,
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
+ "android_manifest": `"ApogeeAndroidManifest.xml"`,
+ "base_apex_name": `"com.android.apogee"`,
+ "binaries": `[
+ ":cc_binary_1",
+ ":sh_binary_2",
+ ]`,
+ "certificate": `":com.google.android.apogee.certificate"`,
+ "file_contexts": `":com.android.apogee-file_contexts"`,
+ "installable": "False",
+ "key": `":com.google.android.apogee.key"`,
+ "manifest": `"apogee_manifest.json"`,
+ "min_sdk_version": `"29"`,
+ "native_shared_libs_32": `select({
+ "//build/bazel/platforms/arch:arm": [":native_shared_lib_1"],
+ "//build/bazel/platforms/arch:x86": [":native_shared_lib_1"],
+ "//conditions:default": [],
+ })`,
+ "native_shared_libs_64": `select({
+ "//build/bazel/platforms/arch:arm64": [":native_shared_lib_1"],
+ "//build/bazel/platforms/arch:x86_64": [":native_shared_lib_1"],
+ "//conditions:default": [],
+ })`,
+ "testonly": "True",
+ "prebuilts": `[]`,
+ "updatable": "False",
+ "compressible": "True",
+ }),
+ }})
+}
+
func TestApexBundleSimple_manifestIsEmpty_baseApexOverrideApexInDifferentAndroidBp(t *testing.T) {
runOverrideApexTestCase(t, Bp2buildTestCase{
Description: "override_apex - manifest of base apex is empty, base apex and override_apex is in different Android.bp",
@@ -1191,9 +1311,9 @@
"tags": `["apex_available=myapex"]`,
}),
MakeBazelTarget("cc_stub_suite", "foo_stub_libs", AttrNameToString{
- "soname": `"foo.so"`,
- "source_library": `":foo"`,
- "symbol_file": `"foo.map.txt"`,
+ "soname": `"foo.so"`,
+ "source_library_label": `"//:foo"`,
+ "symbol_file": `"foo.map.txt"`,
"versions": `[
"28",
"29",
@@ -1446,3 +1566,25 @@
}),
}})
}
+
+func TestApexBundleSimple_customCannedFsConfig(t *testing.T) {
+ runApexTestCase(t, Bp2buildTestCase{
+ Description: "apex - custom canned_fs_config",
+ ModuleTypeUnderTest: "apex",
+ ModuleTypeUnderTestFactory: apex.BundleFactory,
+ Filesystem: map[string]string{},
+ Blueprint: `
+apex {
+ name: "com.android.apogee",
+ canned_fs_config: "custom.canned_fs_config",
+ file_contexts: "file_contexts_file",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
+ "canned_fs_config": `"custom.canned_fs_config"`,
+ "file_contexts": `"file_contexts_file"`,
+ "manifest": `"apex_manifest.json"`,
+ }),
+ }})
+}
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
index d1dfb9d..b22cb28 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -15,6 +15,7 @@
package bp2build
import (
+ "android/soong/starlark_import"
"fmt"
"os"
"path/filepath"
@@ -93,6 +94,12 @@
os.Exit(1)
}
writeFiles(ctx, android.PathForOutput(ctx, bazel.SoongInjectionDirName), injectionFiles)
+ starlarkDeps, err := starlark_import.GetNinjaDeps()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s\n", err)
+ os.Exit(1)
+ }
+ ctx.AddNinjaFileDeps(starlarkDeps...)
return &res.metrics
}
diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go
index 3eec439..3abef9d 100644
--- a/bp2build/bp2build_product_config.go
+++ b/bp2build/bp2build_product_config.go
@@ -53,7 +53,7 @@
"@//build/bazel/product_config:__subpackages__",
])
load(":soong.variables.bzl", _soong_variables = "variables")
-load("@//build/bazel/product_config:utils.bzl", "android_product")
+load("@//build/bazel/product_config:android_product.bzl", "android_product")
android_product(
name = "{PRODUCT}-{VARIANT}",
@@ -68,25 +68,18 @@
"@//build/bazel/product_config:__subpackages__",
"@soong_injection//product_config_platforms:__subpackages__",
])
-
-# TODO(b/249685973): Remove this. It was only added for a platform_mappings file,
-# which can possibly be replaced with autogenerating the platform_mappings file,
-# or removing that file entirely.
-alias(
- name = "current_android_platform",
- # TODO: When we start generating the platforms for more than just the
- # currently lunched, product, turn this into a select with an arm for each product.
- actual = "@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}",
-)
-
-alias(
- name = "product_vars",
- actual = select({
- # TODO: When we start generating the platforms for more than just the
- # currently lunched, product, this select should have an arm for each product.
- "@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_constraint_value": "@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_product_vars",
- }),
-)
+`)),
+ newFile(
+ "product_config_platforms",
+ "product_labels.bzl",
+ productReplacer.Replace(`
+# This file keeps a list of all the products in the android source tree, because they're
+# discovered as part of a preprocessing step before bazel runs.
+# TODO: When we start generating the platforms for more than just the
+# currently lunched product, they should all be listed here
+product_labels = [
+ "@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}"
+]
`)),
newFile(
"product_config_platforms",
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index ced779c..a860484 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -60,6 +60,15 @@
}
}
+// PackageName returns the package of the Bazel target.
+// Defaults to root of tree.
+func (t BazelTarget) PackageName() string {
+ if t.packageName == "" {
+ return "."
+ }
+ return t.packageName
+}
+
// BazelTargets is a typedef for a slice of BazelTarget objects.
type BazelTargets []BazelTarget
@@ -312,6 +321,9 @@
// target, each of a different rule class.
metrics.IncrementRuleClassCount(t.ruleClass)
}
+ } else if _, ok := ctx.Config().BazelModulesForceEnabledByFlag()[m.Name()]; ok && m.Name() != "" {
+ err := fmt.Errorf("Force Enabled Module %s not converted", m.Name())
+ errs = append(errs, err)
} else {
metrics.AddUnconvertedModule(moduleType)
return
@@ -337,7 +349,10 @@
return
}
- buildFileToTargets[dir] = append(buildFileToTargets[dir], targets...)
+ for _, target := range targets {
+ targetDir := target.PackageName()
+ buildFileToTargets[targetDir] = append(buildFileToTargets[targetDir], target)
+ }
})
if len(errs) > 0 {
@@ -454,7 +469,8 @@
targetName := targetNameWithVariant(ctx, m)
return BazelTarget{
- name: targetName,
+ name: targetName,
+ packageName: ctx.ModuleDir(m),
content: fmt.Sprintf(
soongModuleTargetTemplate,
targetName,
@@ -584,6 +600,11 @@
// TODO(b/164227191): implement pretty print for interfaces.
// Interfaces are used for for arch, multilib and target properties.
return "", nil
+ case reflect.Map:
+ if v, ok := propertyValue.Interface().(bazel.StringMapAttribute); ok {
+ return starlark_fmt.PrintStringStringDict(v, indent), nil
+ }
+ return "", fmt.Errorf("bp2build expects map of type map[string]string for field: %s", propertyValue)
default:
return "", fmt.Errorf(
"unexpected kind for property struct field: %s", propertyValue.Kind())
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index d312169..1b64055 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -1175,6 +1175,8 @@
bp2buildConfig allowlists.Bp2BuildConfig
checkDir string
fs map[string]string
+ forceEnabledModules []string
+ expectedErrorMessages []string
}{
{
description: "test bp2build config package and subpackages config",
@@ -1237,6 +1239,24 @@
`,
},
},
+ {
+ description: "test force-enabled errors out",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
+ expectedCount: map[string]int{
+ "migrated": 0,
+ "not_migrated": 0,
+ },
+ bp2buildConfig: allowlists.Bp2BuildConfig{
+ "migrated/but_not_really": allowlists.Bp2BuildDefaultFalse,
+ "not_migrated": allowlists.Bp2BuildDefaultFalse,
+ },
+ fs: map[string]string{
+ "migrated/Android.bp": `filegroup { name: "a" }`,
+ },
+ forceEnabledModules: []string{"a"},
+ expectedErrorMessages: []string{"Force Enabled Module a not converted"},
+ },
}
dir := "."
@@ -1252,6 +1272,7 @@
fs[f] = []byte(content)
}
config := android.TestConfig(buildDir, nil, "", fs)
+ config.AddForceEnabledModules(testCase.forceEnabledModules)
ctx := android.NewTestContext(config)
ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
allowlist := android.NewBp2BuildAllowlist().SetDefaultConfig(testCase.bp2buildConfig)
@@ -1268,7 +1289,7 @@
// For each directory, test that the expected number of generated targets is correct.
for dir, expectedCount := range testCase.expectedCount {
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
- android.FailIfErrored(t, err)
+ android.CheckErrorsAgainstExpectations(t, err, testCase.expectedErrorMessages)
if actualCount := len(bazelTargets); actualCount != expectedCount {
t.Fatalf(
"%s: Expected %d bazel target for %s package, got %d",
@@ -1877,3 +1898,36 @@
Description: "Generating API contribution Bazel targets for custom module",
})
}
+
+func TestGenerateConfigSetting(t *testing.T) {
+ bp := `
+ custom {
+ name: "foo",
+ test_config_setting: true,
+ }
+ `
+ expectedBazelTargets := []string{
+ MakeBazelTargetNoRestrictions(
+ "config_setting",
+ "foo_config_setting",
+ AttrNameToString{
+ "flag_values": `{
+ "//build/bazel/rules/my_string_setting": "foo",
+ }`,
+ },
+ ),
+ MakeBazelTarget(
+ "custom",
+ "foo",
+ AttrNameToString{},
+ ),
+ }
+ registerCustomModule := func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
+ }
+ RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
+ Blueprint: bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ Description: "Generating API contribution Bazel targets for custom module",
+ })
+}
diff --git a/bp2build/bzl_conversion_test.go b/bp2build/bzl_conversion_test.go
index a8e557d..fa1bf8a 100644
--- a/bp2build/bzl_conversion_test.go
+++ b/bp2build/bzl_conversion_test.go
@@ -108,6 +108,7 @@
"string_literal_prop": attr.string(),
"string_prop": attr.string(),
"string_ptr_prop": attr.string(),
+ "test_config_setting": attr.bool(),
},
)
@@ -139,6 +140,7 @@
"string_literal_prop": attr.string(),
"string_prop": attr.string(),
"string_ptr_prop": attr.string(),
+ "test_config_setting": attr.bool(),
},
)
@@ -170,6 +172,7 @@
"string_literal_prop": attr.string(),
"string_prop": attr.string(),
"string_ptr_prop": attr.string(),
+ "test_config_setting": attr.bool(),
# test_prop start
# "test_string_prop": attr.string(),
# test_prop end
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index 0315732..89eac8a 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -996,3 +996,44 @@
},
})
}
+
+func TestCcBinaryHiddenVisibilityConvertedToFeature(t *testing.T) {
+ runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
+ description: "cc_binary changes hidden visibility to feature",
+ blueprint: `
+{rule_name} {
+ name: "foo",
+ cflags: ["-fvisibility=hidden"],
+}`,
+ targets: []testBazelTarget{
+ {"cc_binary", "foo", AttrNameToString{
+ "local_includes": `["."]`,
+ "features": `["visibility_hidden"]`,
+ }},
+ },
+ })
+}
+
+func TestCcBinaryHiddenVisibilityConvertedToFeatureOsSpecific(t *testing.T) {
+ runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
+ description: "cc_binary changes hidden visibility to feature for specific os",
+ blueprint: `
+{rule_name} {
+ name: "foo",
+ target: {
+ android: {
+ cflags: ["-fvisibility=hidden"],
+ },
+ },
+}`,
+ targets: []testBazelTarget{
+ {"cc_binary", "foo", AttrNameToString{
+ "local_includes": `["."]`,
+ "features": `select({
+ "//build/bazel/platforms/os:android": ["visibility_hidden"],
+ "//conditions:default": [],
+ })`,
+ }},
+ },
+ })
+}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index e20cffd..9f78195 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -2425,7 +2425,10 @@
"whole_archive_deps": `[":a_cc_proto_lite"]`,
}), MakeBazelTargetNoRestrictions("proto_library", "a_fg_proto_bp2build_converted", AttrNameToString{
"srcs": `["a_fg.proto"]`,
- "tags": `["manual"]`,
+ "tags": `[
+ "apex_available=//apex_available:anyapex",
+ "manual",
+ ]`,
}), MakeBazelTargetNoRestrictions("filegroup", "a_fg_proto", AttrNameToString{
"srcs": `["a_fg.proto"]`,
}),
@@ -2464,7 +2467,10 @@
"whole_archive_deps": `[":a_cc_proto_lite"]`,
}), MakeBazelTargetNoRestrictions("proto_library", "a_fg_proto_bp2build_converted", AttrNameToString{
"srcs": `["a_fg.proto"]`,
- "tags": `["manual"]`,
+ "tags": `[
+ "apex_available=//apex_available:anyapex",
+ "manual",
+ ]`,
}), MakeBazelTargetNoRestrictions("filegroup", "a_fg_proto", AttrNameToString{
"srcs": `["a_fg.proto"]`,
}),
@@ -2780,9 +2786,9 @@
"stubs_symbol_file": `"a.map.txt"`,
})
expectedBazelTargets = append(expectedBazelTargets, makeCcStubSuiteTargets("a", AttrNameToString{
- "soname": `"a.so"`,
- "source_library": `":a"`,
- "stubs_symbol_file": `"a.map.txt"`,
+ "soname": `"a.so"`,
+ "source_library_label": `"//foo/bar:a"`,
+ "stubs_symbol_file": `"a.map.txt"`,
"stubs_versions": `[
"28",
"29",
@@ -3032,13 +3038,15 @@
},
},
bazel_module: { bp2build_available: true },
+ apex_available: ["foo"],
}`,
ExpectedBazelTargets: makeCcLibraryTargets("foolib", AttrNameToString{
"implementation_dynamic_deps": `select({
- "//build/bazel/rules/apex:android-in_apex": [":barlib_stub_libs_current"],
+ "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:barlib"],
"//conditions:default": [":barlib"],
})`,
"local_includes": `["."]`,
+ "tags": `["apex_available=foo"]`,
}),
})
}
@@ -3072,6 +3080,7 @@
},
include_build_directory: false,
bazel_module: { bp2build_available: true },
+ apex_available: ["foo"],
}`,
ExpectedBazelTargets: makeCcLibraryTargets("foolib", AttrNameToString{
"implementation_dynamic_deps": `select({
@@ -3088,14 +3097,15 @@
"//build/bazel/platforms/os:linux_musl": [":quxlib"],
"//build/bazel/platforms/os:windows": [":quxlib"],
"//build/bazel/rules/apex:android-in_apex": [
- ":barlib_stub_libs_current",
- ":quxlib_stub_libs_current",
+ "@api_surfaces//module-libapi/current:barlib",
+ "@api_surfaces//module-libapi/current:quxlib",
],
"//conditions:default": [
":barlib",
":quxlib",
],
})`,
+ "tags": `["apex_available=foo"]`,
}),
})
}
@@ -3322,6 +3332,7 @@
MakeBazelTargetNoRestrictions("aidl_library", "A_aidl", AttrNameToString{
"srcs": `["aidl/A.aidl"]`,
"strip_import_prefix": `"aidl"`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
}),
MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
"srcs": `["B.aidl"]`,
@@ -3591,42 +3602,57 @@
})
}
-func TestCcLibraryWithAidlAndSharedLibs(t *testing.T) {
+func TestCcLibraryWithAidlAndLibs(t *testing.T) {
runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_aidl_library depends on shared libs from parent cc_library_static",
+ Description: "cc_aidl_library depends on libs from parent cc_library_static",
ModuleTypeUnderTest: "cc_library",
ModuleTypeUnderTestFactory: cc.LibraryFactory,
Blueprint: `
cc_library_static {
- name: "foo",
- srcs: [
- "Foo.aidl",
- ],
+ name: "foo",
+ srcs: [
+ "Foo.aidl",
+ ],
+ static_libs: [
+ "bar-static",
+ "baz-static",
+ ],
shared_libs: [
- "bar",
- "baz",
+ "bar-shared",
+ "baz-shared",
+ ],
+ export_static_lib_headers: [
+ "baz-static",
],
export_shared_lib_headers: [
- "baz",
+ "baz-shared",
],
}` +
- simpleModuleDoNotConvertBp2build("cc_library", "bar") +
- simpleModuleDoNotConvertBp2build("cc_library", "baz"),
+ simpleModuleDoNotConvertBp2build("cc_library_static", "bar-static") +
+ simpleModuleDoNotConvertBp2build("cc_library_static", "baz-static") +
+ simpleModuleDoNotConvertBp2build("cc_library", "bar-shared") +
+ simpleModuleDoNotConvertBp2build("cc_library", "baz-shared"),
ExpectedBazelTargets: []string{
MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
"srcs": `["Foo.aidl"]`,
}),
MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
"deps": `[":foo_aidl_library"]`,
+ "implementation_deps": `[
+ ":baz-static",
+ ":bar-static",
+ ]`,
"implementation_dynamic_deps": `[
- ":baz",
- ":bar",
+ ":baz-shared",
+ ":bar-shared",
]`,
}),
MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
"implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
- "dynamic_deps": `[":baz"]`,
- "implementation_dynamic_deps": `[":bar"]`,
+ "deps": `[":baz-static"]`,
+ "implementation_deps": `[":bar-static"]`,
+ "dynamic_deps": `[":baz-shared"]`,
+ "implementation_dynamic_deps": `[":bar-shared"]`,
"local_includes": `["."]`,
}),
},
@@ -3640,8 +3666,17 @@
ModuleTypeUnderTestFactory: cc.LibraryFactory,
Blueprint: `
cc_library_static {
- name: "foo",
- srcs: ["foo.cpp"],
+ name: "foo",
+ srcs: ["foo.cpp"],
+}
+cc_library_static {
+ name: "foo-no-tidy",
+ srcs: ["foo.cpp"],
+ tidy: false,
+}
+cc_library_static {
+ name: "foo-tidy",
+ srcs: ["foo.cpp"],
tidy: true,
tidy_checks: ["check1", "check2"],
tidy_checks_as_errors: ["check1error", "check2error"],
@@ -3652,7 +3687,16 @@
MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
"local_includes": `["."]`,
"srcs": `["foo.cpp"]`,
- "tidy": `True`,
+ }),
+ MakeBazelTarget("cc_library_static", "foo-no-tidy", AttrNameToString{
+ "local_includes": `["."]`,
+ "srcs": `["foo.cpp"]`,
+ "tidy": `"never"`,
+ }),
+ MakeBazelTarget("cc_library_static", "foo-tidy", AttrNameToString{
+ "local_includes": `["."]`,
+ "srcs": `["foo.cpp"]`,
+ "tidy": `"local"`,
"tidy_checks": `[
"check1",
"check2",
@@ -4112,11 +4156,11 @@
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
"implementation_dynamic_deps": `select({
- "//build/bazel/rules/apex:android-in_apex": [":barlib_stub_libs_current"],
+ "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:barlib"],
"//conditions:default": [":barlib"],
})`,
"dynamic_deps": `select({
- "//build/bazel/rules/apex:android-in_apex": [":bazlib_stub_libs_current"],
+ "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:bazlib"],
"//conditions:default": [":bazlib"],
})`,
"local_includes": `["."]`,
@@ -4124,11 +4168,11 @@
}),
MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
"implementation_dynamic_deps": `select({
- "//build/bazel/rules/apex:android-in_apex": [":barlib_stub_libs_current"],
+ "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:barlib"],
"//conditions:default": [":barlib"],
})`,
"dynamic_deps": `select({
- "//build/bazel/rules/apex:android-in_apex": [":bazlib_stub_libs_current"],
+ "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:bazlib"],
"//conditions:default": [":bazlib"],
})`,
"local_includes": `["."]`,
@@ -4306,3 +4350,136 @@
},
})
}
+
+func TestCcLibraryHiddenVisibilityConvertedToFeature(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library changes hidden visibility flag to feature",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library {
+ name: "foo",
+ cflags: ["-fvisibility=hidden"],
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "features": `["visibility_hidden"]`,
+ "local_includes": `["."]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "features": `["visibility_hidden"]`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryHiddenVisibilityConvertedToFeatureSharedSpecific(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library changes hidden visibility flag to feature when specific to shared variant",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library {
+ name: "foo",
+ shared: {
+ cflags: ["-fvisibility=hidden"],
+ },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "local_includes": `["."]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "features": `["visibility_hidden"]`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryHiddenVisibilityConvertedToFeatureStaticSpecific(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library changes hidden visibility flag to feature when specific to static variant",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library {
+ name: "foo",
+ static: {
+ cflags: ["-fvisibility=hidden"],
+ },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "features": `["visibility_hidden"]`,
+ "local_includes": `["."]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryHiddenVisibilityConvertedToFeatureOsSpecific(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library changes hidden visibility flag to feature when specific to an os",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library {
+ name: "foo",
+ target: {
+ android: {
+ cflags: ["-fvisibility=hidden"],
+ },
+ },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "features": `select({
+ "//build/bazel/platforms/os:android": ["visibility_hidden"],
+ "//conditions:default": [],
+ })`,
+ "local_includes": `["."]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "features": `select({
+ "//build/bazel/platforms/os:android": ["visibility_hidden"],
+ "//conditions:default": [],
+ })`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
+// Test that a config_setting specific to an apex is created by cc_library.
+func TestCcLibraryCreatesInApexConfigSetting(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library creates a config_setting for each apex in apex_available",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Dir: "build/bazel/rules/apex",
+ Blueprint: `
+cc_library {
+ name: "foo",
+ apex_available: [
+ "//apex_available:platform", // This will be skipped, since it is equivalent to //build/bazel/rules/apex:android-non_apex
+ "myapex"
+ ],
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions(
+ "config_setting",
+ "android-in_myapex",
+ AttrNameToString{
+ "flag_values": `{
+ "//build/bazel/rules/apex:apex_name": "myapex",
+ }`,
+ },
+ ),
+ },
+ })
+}
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 838b297..f5d62c6 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -36,6 +36,7 @@
func runCcLibrarySharedTestCase(t *testing.T, tc Bp2buildTestCase) {
t.Helper()
+ t.Parallel()
(&tc).ModuleTypeUnderTest = "cc_library_shared"
(&tc).ModuleTypeUnderTestFactory = cc.LibrarySharedFactory
RunBp2BuildTestCase(t, registerCcLibrarySharedModuleTypes, tc)
@@ -540,9 +541,9 @@
},
Blueprint: soongCcLibraryPreamble,
ExpectedBazelTargets: []string{makeCcStubSuiteTargets("a", AttrNameToString{
- "soname": `"a.so"`,
- "source_library": `":a"`,
- "stubs_symbol_file": `"a.map.txt"`,
+ "soname": `"a.so"`,
+ "source_library_label": `"//foo/bar:a"`,
+ "stubs_symbol_file": `"a.map.txt"`,
"stubs_versions": `[
"28",
"29",
@@ -556,6 +557,151 @@
})
}
+func TestCcLibrarySharedStubs_UseImplementationInSameApex(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_shared stubs",
+ ModuleTypeUnderTest: "cc_library_shared",
+ ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
+ Blueprint: soongCcLibrarySharedPreamble + `
+cc_library_shared {
+ name: "a",
+ stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
+ bazel_module: { bp2build_available: false },
+ include_build_directory: false,
+ apex_available: ["made_up_apex"],
+}
+cc_library_shared {
+ name: "b",
+ shared_libs: [":a"],
+ include_build_directory: false,
+ apex_available: ["made_up_apex"],
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
+ "implementation_dynamic_deps": `[":a"]`,
+ "tags": `["apex_available=made_up_apex"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibrarySharedStubs_UseStubsInDifferentApex(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_shared stubs",
+ ModuleTypeUnderTest: "cc_library_shared",
+ ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
+ Blueprint: soongCcLibrarySharedPreamble + `
+cc_library_shared {
+ name: "a",
+ stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
+ bazel_module: { bp2build_available: false },
+ include_build_directory: false,
+ apex_available: ["apex_a"],
+}
+cc_library_shared {
+ name: "b",
+ shared_libs: [":a"],
+ include_build_directory: false,
+ apex_available: ["apex_b"],
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
+ "implementation_dynamic_deps": `select({
+ "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:a"],
+ "//conditions:default": [":a"],
+ })`,
+ "tags": `["apex_available=apex_b"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibrarySharedStubs_IgnorePlatformAvailable(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_shared stubs",
+ ModuleTypeUnderTest: "cc_library_shared",
+ ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
+ Blueprint: soongCcLibrarySharedPreamble + `
+cc_library_shared {
+ name: "a",
+ stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
+ bazel_module: { bp2build_available: false },
+ include_build_directory: false,
+ apex_available: ["//apex_available:platform", "apex_a"],
+}
+cc_library_shared {
+ name: "b",
+ shared_libs: [":a"],
+ include_build_directory: false,
+ apex_available: ["//apex_available:platform", "apex_b"],
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
+ "implementation_dynamic_deps": `select({
+ "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:a"],
+ "//conditions:default": [":a"],
+ })`,
+ "tags": `[
+ "apex_available=//apex_available:platform",
+ "apex_available=apex_b",
+ ]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibrarySharedStubs_MultipleApexAvailable(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ ModuleTypeUnderTest: "cc_library_shared",
+ ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
+ Blueprint: soongCcLibrarySharedPreamble + `
+cc_library_shared {
+ name: "a",
+ stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
+ bazel_module: { bp2build_available: false },
+ include_build_directory: false,
+ apex_available: ["//apex_available:platform", "apex_a", "apex_b"],
+}
+cc_library_shared {
+ name: "b",
+ shared_libs: [":a"],
+ include_build_directory: false,
+ apex_available: ["//apex_available:platform", "apex_b"],
+}
+
+cc_library_shared {
+ name: "c",
+ shared_libs: [":a"],
+ include_build_directory: false,
+ apex_available: ["//apex_available:platform", "apex_a", "apex_b"],
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
+ "implementation_dynamic_deps": `select({
+ "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:a"],
+ "//conditions:default": [":a"],
+ })`,
+ "tags": `[
+ "apex_available=//apex_available:platform",
+ "apex_available=apex_b",
+ ]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "c", AttrNameToString{
+ "implementation_dynamic_deps": `[":a"]`,
+ "tags": `[
+ "apex_available=//apex_available:platform",
+ "apex_available=apex_a",
+ "apex_available=apex_b",
+ ]`,
+ }),
+ },
+ })
+}
+
func TestCcLibrarySharedSystemSharedLibsSharedEmpty(t *testing.T) {
runCcLibrarySharedTestCase(t, Bp2buildTestCase{
Description: "cc_library_shared system_shared_libs empty shared default",
@@ -1104,3 +1250,107 @@
},
})
}
+
+func TestCcLibrarySharedHiddenVisibilityConvertedToFeature(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_shared changes hidden visibility flag to feature",
+ Blueprint: `
+cc_library_shared{
+ name: "foo",
+ cflags: ["-fvisibility=hidden"],
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "features": `["visibility_hidden"]`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibrarySharedHiddenVisibilityConvertedToFeatureOsSpecific(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_shared changes hidden visibility flag to feature for specific os",
+ Blueprint: `
+cc_library_shared{
+ name: "foo",
+ target: {
+ android: {
+ cflags: ["-fvisibility=hidden"],
+ },
+ },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "features": `select({
+ "//build/bazel/platforms/os:android": ["visibility_hidden"],
+ "//conditions:default": [],
+ })`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibrarySharedStubsDessertVersionConversion(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_shared converts dessert codename versions to numerical versions",
+ Blueprint: `
+cc_library_shared {
+ name: "a",
+ include_build_directory: false,
+ stubs: {
+ symbol_file: "a.map.txt",
+ versions: [
+ "Q",
+ "R",
+ "31",
+ ],
+ },
+}
+cc_library_shared {
+ name: "b",
+ include_build_directory: false,
+ stubs: {
+ symbol_file: "b.map.txt",
+ versions: [
+ "Q",
+ "R",
+ "31",
+ "current",
+ ],
+ },
+}
+`,
+ ExpectedBazelTargets: []string{
+ makeCcStubSuiteTargets("a", AttrNameToString{
+ "soname": `"a.so"`,
+ "source_library_label": `"//:a"`,
+ "stubs_symbol_file": `"a.map.txt"`,
+ "stubs_versions": `[
+ "29",
+ "30",
+ "31",
+ "current",
+ ]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
+ "stubs_symbol_file": `"a.map.txt"`,
+ }),
+ makeCcStubSuiteTargets("b", AttrNameToString{
+ "soname": `"b.so"`,
+ "source_library_label": `"//:b"`,
+ "stubs_symbol_file": `"b.map.txt"`,
+ "stubs_versions": `[
+ "29",
+ "30",
+ "31",
+ "current",
+ ]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
+ "stubs_symbol_file": `"b.map.txt"`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index d16c5cc..f89f2dd 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -1517,12 +1517,14 @@
},
},
include_build_directory: false,
+ apex_available: ["foo"],
}
cc_library_static {
name: "all",
shared_libs: ["libc"],
include_build_directory: false,
+ apex_available: ["foo"],
}
cc_library_static {
@@ -1530,12 +1532,14 @@
shared_libs: ["libc"],
system_shared_libs: [],
include_build_directory: false,
+ apex_available: ["foo"],
}
cc_library_static {
name: "used_with_stubs",
shared_libs: ["libm"],
include_build_directory: false,
+ apex_available: ["foo"],
}
cc_library_static {
@@ -1543,23 +1547,32 @@
shared_libs: ["libm"],
system_shared_libs: [],
include_build_directory: false,
+ apex_available: ["foo"],
}
`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "all", AttrNameToString{}),
+ MakeBazelTarget("cc_library_static", "all", AttrNameToString{
+ "tags": `["apex_available=foo"]`,
+ }),
MakeBazelTarget("cc_library_static", "keep_for_empty_system_shared_libs", AttrNameToString{
"implementation_dynamic_deps": `[":libc"]`,
"system_dynamic_deps": `[]`,
+ "tags": `["apex_available=foo"]`,
}),
MakeBazelTarget("cc_library_static", "keep_with_stubs", AttrNameToString{
"implementation_dynamic_deps": `select({
- "//build/bazel/rules/apex:android-in_apex": [":libm_stub_libs_current"],
+ "//build/bazel/rules/apex:android-in_apex": ["@api_surfaces//module-libapi/current:libm"],
"//conditions:default": [":libm"],
})`,
"system_dynamic_deps": `[]`,
+ "tags": `["apex_available=foo"]`,
}),
- MakeBazelTarget("cc_library_static", "used_in_bionic_oses", AttrNameToString{}),
- MakeBazelTarget("cc_library_static", "used_with_stubs", AttrNameToString{}),
+ MakeBazelTarget("cc_library_static", "used_in_bionic_oses", AttrNameToString{
+ "tags": `["apex_available=foo"]`,
+ }),
+ MakeBazelTarget("cc_library_static", "used_with_stubs", AttrNameToString{
+ "tags": `["apex_available=foo"]`,
+ }),
},
})
}
@@ -2019,3 +2032,44 @@
},
})
}
+
+func TestCcLibraryStaticHiddenVisibilityConvertedToFeature(t *testing.T) {
+ runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_static changes hidden visibility flag to feature",
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ cflags: ["-fvisibility=hidden"],
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "features": `["visibility_hidden"]`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryStaticHiddenVisibilityConvertedToFeatureOsSpecific(t *testing.T) {
+ runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_static changes hidden visibility flag to feature for specific os",
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ target: {
+ android: {
+ cflags: ["-fvisibility=hidden"],
+ },
+ },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "features": `select({
+ "//build/bazel/platforms/os:android": ["visibility_hidden"],
+ "//conditions:default": [],
+ })`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_prebuilt_library_conversion_test.go b/bp2build/cc_prebuilt_library_conversion_test.go
index 2fe158e..b88960e 100644
--- a/bp2build/cc_prebuilt_library_conversion_test.go
+++ b/bp2build/cc_prebuilt_library_conversion_test.go
@@ -20,12 +20,17 @@
"android/soong/cc"
)
+func runCcPrebuiltLibraryTestCase(t *testing.T, tc Bp2buildTestCase) {
+ t.Helper()
+ (&tc).ModuleTypeUnderTest = "cc_prebuilt_library"
+ (&tc).ModuleTypeUnderTestFactory = cc.PrebuiltLibraryFactory
+ RunBp2BuildTestCaseSimple(t, tc)
+}
+
func TestPrebuiltLibraryStaticAndSharedSimple(t *testing.T) {
- RunBp2BuildTestCaseSimple(t,
+ runCcPrebuiltLibraryTestCase(t,
Bp2buildTestCase{
- Description: "prebuilt library static and shared simple",
- ModuleTypeUnderTest: "cc_prebuilt_library",
- ModuleTypeUnderTestFactory: cc.PrebuiltLibraryFactory,
+ Description: "prebuilt library static and shared simple",
Filesystem: map[string]string{
"libf.so": "",
},
@@ -39,6 +44,10 @@
MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
"static_library": `"libf.so"`,
}),
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static_alwayslink", AttrNameToString{
+ "static_library": `"libf.so"`,
+ "alwayslink": "True",
+ }),
MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
"shared_library": `"libf.so"`,
}),
@@ -47,11 +56,9 @@
}
func TestPrebuiltLibraryWithArchVariance(t *testing.T) {
- RunBp2BuildTestCaseSimple(t,
+ runCcPrebuiltLibraryTestCase(t,
Bp2buildTestCase{
- Description: "prebuilt library with arch variance",
- ModuleTypeUnderTest: "cc_prebuilt_library",
- ModuleTypeUnderTestFactory: cc.PrebuiltLibraryFactory,
+ Description: "prebuilt library with arch variance",
Filesystem: map[string]string{
"libf.so": "",
"libg.so": "",
@@ -71,8 +78,14 @@
"//build/bazel/platforms/arch:arm": "libg.so",
"//build/bazel/platforms/arch:arm64": "libf.so",
"//conditions:default": None,
- })`,
- }),
+ })`}),
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static_alwayslink", AttrNameToString{
+ "alwayslink": "True",
+ "static_library": `select({
+ "//build/bazel/platforms/arch:arm": "libg.so",
+ "//build/bazel/platforms/arch:arm64": "libf.so",
+ "//conditions:default": None,
+ })`}),
MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
"shared_library": `select({
"//build/bazel/platforms/arch:arm": "libg.so",
@@ -85,11 +98,9 @@
}
func TestPrebuiltLibraryAdditionalAttrs(t *testing.T) {
- RunBp2BuildTestCaseSimple(t,
+ runCcPrebuiltLibraryTestCase(t,
Bp2buildTestCase{
- Description: "prebuilt library additional attributes",
- ModuleTypeUnderTest: "cc_prebuilt_library",
- ModuleTypeUnderTestFactory: cc.PrebuiltLibraryFactory,
+ Description: "prebuilt library additional attributes",
Filesystem: map[string]string{
"libf.so": "",
"testdir/1/include.h": "",
@@ -109,20 +120,25 @@
"export_includes": `["testdir/1/"]`,
"export_system_includes": `["testdir/2/"]`,
}),
- // TODO(b/229374533): When fixed, update this test
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static_alwayslink", AttrNameToString{
+ "static_library": `"libf.so"`,
+ "export_includes": `["testdir/1/"]`,
+ "export_system_includes": `["testdir/2/"]`,
+ "alwayslink": "True",
+ }),
MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
- "shared_library": `"libf.so"`,
+ "shared_library": `"libf.so"`,
+ "export_includes": `["testdir/1/"]`,
+ "export_system_includes": `["testdir/2/"]`,
}),
},
})
}
func TestPrebuiltLibrarySharedStanzaFails(t *testing.T) {
- RunBp2BuildTestCaseSimple(t,
+ runCcPrebuiltLibraryTestCase(t,
Bp2buildTestCase{
- Description: "prebuilt library with shared stanza fails because multiple sources",
- ModuleTypeUnderTest: "cc_prebuilt_library",
- ModuleTypeUnderTestFactory: cc.PrebuiltLibraryFactory,
+ Description: "prebuilt library with shared stanza fails because multiple sources",
Filesystem: map[string]string{
"libf.so": "",
"libg.so": "",
@@ -164,11 +180,9 @@
}
func TestPrebuiltLibrarySharedAndStaticStanzas(t *testing.T) {
- RunBp2BuildTestCaseSimple(t,
+ runCcPrebuiltLibraryTestCase(t,
Bp2buildTestCase{
- Description: "prebuilt library with both shared and static stanzas",
- ModuleTypeUnderTest: "cc_prebuilt_library",
- ModuleTypeUnderTestFactory: cc.PrebuiltLibraryFactory,
+ Description: "prebuilt library with both shared and static stanzas",
Filesystem: map[string]string{
"libf.so": "",
"libg.so": "",
@@ -188,6 +202,10 @@
MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
"static_library": `"libf.so"`,
}),
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static_alwayslink", AttrNameToString{
+ "static_library": `"libf.so"`,
+ "alwayslink": "True",
+ }),
MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
"shared_library": `"libg.so"`,
}),
@@ -197,11 +215,9 @@
// TODO(b/228623543): When this bug is fixed, enable this test
//func TestPrebuiltLibraryOnlyShared(t *testing.T) {
-// RunBp2BuildTestCaseSimple(t,
+// runCcPrebuiltLibraryTestCase(t,
// bp2buildTestCase{
// description: "prebuilt library shared only",
-// moduleTypeUnderTest: "cc_prebuilt_library",
-// moduleTypeUnderTestFactory: cc.PrebuiltLibraryFactory,
// filesystem: map[string]string{
// "libf.so": "",
// },
@@ -224,11 +240,9 @@
// TODO(b/228623543): When this bug is fixed, enable this test
//func TestPrebuiltLibraryOnlyStatic(t *testing.T) {
-// RunBp2BuildTestCaseSimple(t,
+// runCcPrebuiltLibraryTestCase(t,
// bp2buildTestCase{
// description: "prebuilt library static only",
-// moduleTypeUnderTest: "cc_prebuilt_library",
-// moduleTypeUnderTestFactory: cc.PrebuiltLibraryFactory,
// filesystem: map[string]string{
// "libf.so": "",
// },
@@ -245,6 +259,104 @@
// makeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", attrNameToString{
// "static_library": `"libf.so"`,
// }),
+// makeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static_always", attrNameToString{
+// "static_library": `"libf.so"`,
+// "alwayslink": "True",
+// }),
// },
// })
//}
+
+func TestPrebuiltLibraryWithExportIncludesArchVariant(t *testing.T) {
+ runCcPrebuiltLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_prebuilt_library correctly translates export_includes with arch variance",
+ Filesystem: map[string]string{
+ "libf.so": "",
+ "libg.so": "",
+ },
+ Blueprint: `
+cc_prebuilt_library {
+ name: "libtest",
+ srcs: ["libf.so"],
+ arch: {
+ arm: { export_include_dirs: ["testdir/1/"], },
+ arm64: { export_include_dirs: ["testdir/2/"], },
+ },
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
+ "shared_library": `"libf.so"`,
+ "export_includes": `select({
+ "//build/bazel/platforms/arch:arm": ["testdir/1/"],
+ "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
+ "static_library": `"libf.so"`,
+ "export_includes": `select({
+ "//build/bazel/platforms/arch:arm": ["testdir/1/"],
+ "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static_alwayslink", AttrNameToString{
+ "alwayslink": "True",
+ "static_library": `"libf.so"`,
+ "export_includes": `select({
+ "//build/bazel/platforms/arch:arm": ["testdir/1/"],
+ "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPrebuiltLibraryWithExportSystemIncludesArchVariant(t *testing.T) {
+ runCcPrebuiltLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_prebuilt_ibrary correctly translates export_system_includes with arch variance",
+ Filesystem: map[string]string{
+ "libf.so": "",
+ "libg.so": "",
+ },
+ Blueprint: `
+cc_prebuilt_library {
+ name: "libtest",
+ srcs: ["libf.so"],
+ arch: {
+ arm: { export_system_include_dirs: ["testdir/1/"], },
+ arm64: { export_system_include_dirs: ["testdir/2/"], },
+ },
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
+ "shared_library": `"libf.so"`,
+ "export_system_includes": `select({
+ "//build/bazel/platforms/arch:arm": ["testdir/1/"],
+ "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
+ "static_library": `"libf.so"`,
+ "export_system_includes": `select({
+ "//build/bazel/platforms/arch:arm": ["testdir/1/"],
+ "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static_alwayslink", AttrNameToString{
+ "alwayslink": "True",
+ "static_library": `"libf.so"`,
+ "export_system_includes": `select({
+ "//build/bazel/platforms/arch:arm": ["testdir/1/"],
+ "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_prebuilt_library_shared_conversion_test.go b/bp2build/cc_prebuilt_library_shared_conversion_test.go
new file mode 100644
index 0000000..9e975ae
--- /dev/null
+++ b/bp2build/cc_prebuilt_library_shared_conversion_test.go
@@ -0,0 +1,165 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package bp2build
+
+import (
+ "testing"
+
+ "android/soong/cc"
+)
+
+func runCcPrebuiltLibrarySharedTestCase(t *testing.T, tc Bp2buildTestCase) {
+ t.Parallel()
+ t.Helper()
+ (&tc).ModuleTypeUnderTest = "cc_prebuilt_library_shared"
+ (&tc).ModuleTypeUnderTestFactory = cc.PrebuiltSharedLibraryFactory
+ RunBp2BuildTestCaseSimple(t, tc)
+}
+
+func TestPrebuiltLibrarySharedSimple(t *testing.T) {
+ runCcPrebuiltLibrarySharedTestCase(t,
+ Bp2buildTestCase{
+ Description: "prebuilt library shared simple",
+ Filesystem: map[string]string{
+ "libf.so": "",
+ },
+ Blueprint: `
+cc_prebuilt_library_shared {
+ name: "libtest",
+ srcs: ["libf.so"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
+ "shared_library": `"libf.so"`,
+ }),
+ },
+ })
+}
+
+func TestPrebuiltLibrarySharedWithArchVariance(t *testing.T) {
+ runCcPrebuiltLibrarySharedTestCase(t,
+ Bp2buildTestCase{
+ Description: "prebuilt library shared with arch variance",
+ Filesystem: map[string]string{
+ "libf.so": "",
+ "libg.so": "",
+ },
+ Blueprint: `
+cc_prebuilt_library_shared {
+ name: "libtest",
+ arch: {
+ arm64: { srcs: ["libf.so"], },
+ arm: { srcs: ["libg.so"], },
+ },
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
+ "shared_library": `select({
+ "//build/bazel/platforms/arch:arm": "libg.so",
+ "//build/bazel/platforms/arch:arm64": "libf.so",
+ "//conditions:default": None,
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPrebuiltLibrarySharedAdditionalAttrs(t *testing.T) {
+ runCcPrebuiltLibrarySharedTestCase(t,
+ Bp2buildTestCase{
+ Description: "prebuilt library shared additional attributes",
+ Filesystem: map[string]string{
+ "libf.so": "",
+ "testdir/1/include.h": "",
+ "testdir/2/other.h": "",
+ },
+ Blueprint: `
+cc_prebuilt_library_shared {
+ name: "libtest",
+ srcs: ["libf.so"],
+ export_include_dirs: ["testdir/1/"],
+ export_system_include_dirs: ["testdir/2/"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
+ "shared_library": `"libf.so"`,
+ "export_includes": `["testdir/1/"]`,
+ "export_system_includes": `["testdir/2/"]`,
+ }),
+ },
+ })
+}
+
+func TestPrebuiltLibrarySharedWithExportIncludesArchVariant(t *testing.T) {
+ runCcPrebuiltLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_prebuilt_library_shared correctly translates export_includes with arch variance",
+ Filesystem: map[string]string{
+ "libf.so": "",
+ "libg.so": "",
+ },
+ Blueprint: `
+cc_prebuilt_library_shared {
+ name: "libtest",
+ srcs: ["libf.so"],
+ arch: {
+ arm: { export_include_dirs: ["testdir/1/"], },
+ arm64: { export_include_dirs: ["testdir/2/"], },
+ },
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
+ "shared_library": `"libf.so"`,
+ "export_includes": `select({
+ "//build/bazel/platforms/arch:arm": ["testdir/1/"],
+ "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPrebuiltLibrarySharedWithExportSystemIncludesArchVariant(t *testing.T) {
+ runCcPrebuiltLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_prebuilt_library_shared correctly translates export_system_includes with arch variance",
+ Filesystem: map[string]string{
+ "libf.so": "",
+ "libg.so": "",
+ },
+ Blueprint: `
+cc_prebuilt_library_shared {
+ name: "libtest",
+ srcs: ["libf.so"],
+ arch: {
+ arm: { export_system_include_dirs: ["testdir/1/"], },
+ arm64: { export_system_include_dirs: ["testdir/2/"], },
+ },
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
+ "shared_library": `"libf.so"`,
+ "export_system_includes": `select({
+ "//build/bazel/platforms/arch:arm": ["testdir/1/"],
+ "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_prebuilt_library_static_conversion_test.go b/bp2build/cc_prebuilt_library_static_conversion_test.go
new file mode 100644
index 0000000..77562e7
--- /dev/null
+++ b/bp2build/cc_prebuilt_library_static_conversion_test.go
@@ -0,0 +1,199 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package bp2build
+
+import (
+ "testing"
+
+ "android/soong/cc"
+)
+
+func runCcPrebuiltLibraryStaticTestCase(t *testing.T, tc Bp2buildTestCase) {
+ t.Parallel()
+ t.Helper()
+ (&tc).ModuleTypeUnderTest = "cc_prebuilt_library_static"
+ (&tc).ModuleTypeUnderTestFactory = cc.PrebuiltStaticLibraryFactory
+ RunBp2BuildTestCaseSimple(t, tc)
+}
+
+func TestPrebuiltLibraryStaticSimple(t *testing.T) {
+ runCcPrebuiltLibraryStaticTestCase(t,
+ Bp2buildTestCase{
+ Description: "prebuilt library static simple",
+ Filesystem: map[string]string{
+ "libf.so": "",
+ },
+ Blueprint: `
+cc_prebuilt_library_static {
+ name: "libtest",
+ srcs: ["libf.so"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
+ "static_library": `"libf.so"`,
+ }),
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_alwayslink", AttrNameToString{
+ "static_library": `"libf.so"`,
+ "alwayslink": "True",
+ }),
+ },
+ })
+}
+
+func TestPrebuiltLibraryStaticWithArchVariance(t *testing.T) {
+ runCcPrebuiltLibraryStaticTestCase(t,
+ Bp2buildTestCase{
+ Description: "prebuilt library with arch variance",
+ Filesystem: map[string]string{
+ "libf.so": "",
+ "libg.so": "",
+ },
+ Blueprint: `
+cc_prebuilt_library_static {
+ name: "libtest",
+ arch: {
+ arm64: { srcs: ["libf.so"], },
+ arm: { srcs: ["libg.so"], },
+ },
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
+ "static_library": `select({
+ "//build/bazel/platforms/arch:arm": "libg.so",
+ "//build/bazel/platforms/arch:arm64": "libf.so",
+ "//conditions:default": None,
+ })`}),
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_alwayslink", AttrNameToString{
+ "alwayslink": "True",
+ "static_library": `select({
+ "//build/bazel/platforms/arch:arm": "libg.so",
+ "//build/bazel/platforms/arch:arm64": "libf.so",
+ "//conditions:default": None,
+ })`}),
+ },
+ })
+}
+
+func TestPrebuiltLibraryStaticAdditionalAttrs(t *testing.T) {
+ runCcPrebuiltLibraryStaticTestCase(t,
+ Bp2buildTestCase{
+ Description: "prebuilt library additional attributes",
+ Filesystem: map[string]string{
+ "libf.so": "",
+ "testdir/1/include.h": "",
+ "testdir/2/other.h": "",
+ },
+ Blueprint: `
+cc_prebuilt_library_static {
+ name: "libtest",
+ srcs: ["libf.so"],
+ export_include_dirs: ["testdir/1/"],
+ export_system_include_dirs: ["testdir/2/"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
+ "static_library": `"libf.so"`,
+ "export_includes": `["testdir/1/"]`,
+ "export_system_includes": `["testdir/2/"]`,
+ }),
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_alwayslink", AttrNameToString{
+ "static_library": `"libf.so"`,
+ "export_includes": `["testdir/1/"]`,
+ "export_system_includes": `["testdir/2/"]`,
+ "alwayslink": "True",
+ }),
+ },
+ })
+}
+
+func TestPrebuiltLibraryStaticWithExportIncludesArchVariant(t *testing.T) {
+ runCcPrebuiltLibraryStaticTestCase(t, Bp2buildTestCase{
+ Description: "cc_prebuilt_library_static correctly translates export_includes with arch variance",
+ Filesystem: map[string]string{
+ "libf.so": "",
+ "libg.so": "",
+ },
+ Blueprint: `
+cc_prebuilt_library_static {
+ name: "libtest",
+ srcs: ["libf.so"],
+ arch: {
+ arm: { export_include_dirs: ["testdir/1/"], },
+ arm64: { export_include_dirs: ["testdir/2/"], },
+ },
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
+ "static_library": `"libf.so"`,
+ "export_includes": `select({
+ "//build/bazel/platforms/arch:arm": ["testdir/1/"],
+ "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_alwayslink", AttrNameToString{
+ "alwayslink": "True",
+ "static_library": `"libf.so"`,
+ "export_includes": `select({
+ "//build/bazel/platforms/arch:arm": ["testdir/1/"],
+ "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPrebuiltLibraryStaticWithExportSystemIncludesArchVariant(t *testing.T) {
+ runCcPrebuiltLibraryStaticTestCase(t, Bp2buildTestCase{
+ Description: "cc_prebuilt_library_static correctly translates export_system_includes with arch variance",
+ Filesystem: map[string]string{
+ "libf.so": "",
+ "libg.so": "",
+ },
+ Blueprint: `
+cc_prebuilt_library_static {
+ name: "libtest",
+ srcs: ["libf.so"],
+ arch: {
+ arm: { export_system_include_dirs: ["testdir/1/"], },
+ arm64: { export_system_include_dirs: ["testdir/2/"], },
+ },
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
+ "static_library": `"libf.so"`,
+ "export_system_includes": `select({
+ "//build/bazel/platforms/arch:arm": ["testdir/1/"],
+ "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_alwayslink", AttrNameToString{
+ "alwayslink": "True",
+ "static_library": `"libf.so"`,
+ "export_system_includes": `select({
+ "//build/bazel/platforms/arch:arm": ["testdir/1/"],
+ "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_prebuilt_library_static_test.go b/bp2build/cc_prebuilt_library_static_test.go
index 6116b00..17da813 100644
--- a/bp2build/cc_prebuilt_library_static_test.go
+++ b/bp2build/cc_prebuilt_library_static_test.go
@@ -39,6 +39,10 @@
MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
"static_library": `"libf.so"`,
}),
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_alwayslink", AttrNameToString{
+ "static_library": `"libf.so"`,
+ "alwayslink": "True",
+ }),
},
})
}
@@ -68,8 +72,14 @@
"//build/bazel/platforms/arch:arm": "libg.so",
"//build/bazel/platforms/arch:arm64": "libf.so",
"//conditions:default": None,
- })`,
- }),
+ })`}),
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_alwayslink", AttrNameToString{
+ "alwayslink": "True",
+ "static_library": `select({
+ "//build/bazel/platforms/arch:arm": "libg.so",
+ "//build/bazel/platforms/arch:arm64": "libf.so",
+ "//conditions:default": None,
+ })`}),
},
})
}
diff --git a/bp2build/cc_test_conversion_test.go b/bp2build/cc_test_conversion_test.go
index 20adddb..4df4d4d 100644
--- a/bp2build/cc_test_conversion_test.go
+++ b/bp2build/cc_test_conversion_test.go
@@ -76,17 +76,28 @@
static_libs: ["hostlib"],
},
},
+ static_libs: ["cc_test_lib1"],
+ shared_libs: ["cc_test_lib2"],
data: [":data_mod", "file.txt"],
data_bins: [":cc_bin"],
data_libs: [":cc_lib"],
cflags: ["-Wall"],
}
+
+cc_test_library {
+ name: "cc_test_lib1",
+ host_supported: true,
+ include_build_directory: false,
+}
` + simpleModuleDoNotConvertBp2build("cc_library", "foolib") +
simpleModuleDoNotConvertBp2build("cc_library_static", "hostlib") +
simpleModuleDoNotConvertBp2build("genrule", "data_mod") +
simpleModuleDoNotConvertBp2build("cc_binary", "cc_bin") +
- simpleModuleDoNotConvertBp2build("cc_test_library", "cc_lib"),
+ simpleModuleDoNotConvertBp2build("cc_library", "cc_lib") +
+ simpleModuleDoNotConvertBp2build("cc_test_library", "cc_test_lib2"),
targets: []testBazelTarget{
+ {"cc_library_shared", "cc_test_lib1", AttrNameToString{}},
+ {"cc_library_static", "cc_test_lib1_bp2build_cc_library_static", AttrNameToString{}},
{"cc_test", "mytest", AttrNameToString{
"copts": `["-Wall"]`,
"data": `[
@@ -95,7 +106,7 @@
":cc_bin",
":cc_lib",
]`,
- "deps": `select({
+ "deps": `[":cc_test_lib1_bp2build_cc_library_static"] + select({
"//build/bazel/platforms/os:darwin": [":hostlib"],
"//build/bazel/platforms/os:linux_bionic": [":hostlib"],
"//build/bazel/platforms/os:linux_glibc": [":hostlib"],
@@ -106,7 +117,7 @@
"gtest": "True",
"isolated": "True",
"local_includes": `["."]`,
- "dynamic_deps": `select({
+ "dynamic_deps": `[":cc_test_lib2"] + select({
"//build/bazel/platforms/os:android": [":foolib"],
"//conditions:default": [],
})`,
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 6a39e25..608fcd8 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -1,8 +1,11 @@
package bp2build
import (
+ "android/soong/starlark_fmt"
"encoding/json"
+ "fmt"
"reflect"
+ "strconv"
"strings"
"android/soong/android"
@@ -48,7 +51,9 @@
if err != nil {
panic(err)
}
+ files = append(files, newFile("metrics", GeneratedBuildFileName, "")) // Creates a //metrics package.
files = append(files, newFile("metrics", "converted_modules_path_map.json", string(convertedModulePathMap)))
+ files = append(files, newFile("metrics", "converted_modules_path_map.bzl", "modules = "+strings.ReplaceAll(string(convertedModulePathMap), "\\", "\\\\")))
files = append(files, newFile("product_config", "soong_config_variables.bzl", cfg.Bp2buildSoongConfigDefinitions.String()))
@@ -62,6 +67,7 @@
// TODO(b/269691302) value of apiLevelsContent is product variable dependent and should be avoided for soong injection
files = append(files, newFile("api_levels", "api_levels.json", string(apiLevelsContent)))
files = append(files, newFile("api_levels", "api_levels.bzl", android.StarlarkApiLevelConfigs(cfg)))
+ files = append(files, newFile("api_levels", "platform_versions.bzl", platformVersionContents(cfg)))
files = append(files, newFile("allowlists", GeneratedBuildFileName, ""))
files = append(files, newFile("allowlists", "env.bzl", android.EnvironmentVarsFile(cfg)))
@@ -72,6 +78,31 @@
return files, nil
}
+func platformVersionContents(cfg android.Config) string {
+ // Despite these coming from cfg.productVariables, they are actually hardcoded in global
+ // makefiles, not set in individual product config makesfiles, so they're safe to just export
+ // and load() directly.
+
+ platformVersionActiveCodenames := make([]string, 0, len(cfg.PlatformVersionActiveCodenames()))
+ for _, codename := range cfg.PlatformVersionActiveCodenames() {
+ platformVersionActiveCodenames = append(platformVersionActiveCodenames, fmt.Sprintf("%q", codename))
+ }
+
+ platformSdkVersion := "None"
+ if cfg.RawPlatformSdkVersion() != nil {
+ platformSdkVersion = strconv.Itoa(*cfg.RawPlatformSdkVersion())
+ }
+
+ return fmt.Sprintf(`
+platform_versions = struct(
+ platform_sdk_final = %s,
+ platform_sdk_version = %s,
+ platform_sdk_codename = %q,
+ platform_version_active_codenames = [%s],
+)
+`, starlark_fmt.PrintBool(cfg.PlatformSdkFinal()), platformSdkVersion, cfg.PlatformSdkCodename(), strings.Join(platformVersionActiveCodenames, ", "))
+}
+
func CreateBazelFiles(
cfg android.Config,
ruleShims map[string]RuleShim,
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index 8c1d2ae..2f5dc3c 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -131,9 +131,17 @@
},
{
dir: "metrics",
+ basename: "BUILD.bazel",
+ },
+ {
+ dir: "metrics",
basename: "converted_modules_path_map.json",
},
{
+ dir: "metrics",
+ basename: "converted_modules_path_map.bzl",
+ },
+ {
dir: "product_config",
basename: "soong_config_variables.bzl",
},
@@ -154,6 +162,10 @@
basename: "api_levels.bzl",
},
{
+ dir: "api_levels",
+ basename: "platform_versions.bzl",
+ },
+ {
dir: "allowlists",
basename: GeneratedBuildFileName,
},
diff --git a/bp2build/filegroup_conversion_test.go b/bp2build/filegroup_conversion_test.go
index e978fb3..273d556 100644
--- a/bp2build/filegroup_conversion_test.go
+++ b/bp2build/filegroup_conversion_test.go
@@ -74,6 +74,7 @@
expectedBazelAttrs: AttrNameToString{
"srcs": `["aidl/foo.aidl"]`,
"strip_import_prefix": `"aidl"`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
},
},
{
@@ -85,22 +86,61 @@
}`,
expectedBazelAttrs: AttrNameToString{
"srcs": `["aidl/foo.aidl"]`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
},
},
}
for _, test := range testcases {
- expectedBazelTargets := []string{
- MakeBazelTargetNoRestrictions("aidl_library", "foo", test.expectedBazelAttrs),
- }
- runFilegroupTestCase(t, Bp2buildTestCase{
- Description: test.name,
- Blueprint: test.bp,
- ExpectedBazelTargets: expectedBazelTargets,
+ t.Run(test.name, func(t *testing.T) {
+ expectedBazelTargets := []string{
+ MakeBazelTargetNoRestrictions("aidl_library", "foo", test.expectedBazelAttrs),
+ }
+ runFilegroupTestCase(t, Bp2buildTestCase{
+ Description: test.name,
+ Blueprint: test.bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
})
}
}
+func TestFilegroupWithAidlDeps(t *testing.T) {
+ bp := `
+ filegroup {
+ name: "bar",
+ srcs: ["bar.aidl"],
+ }
+ filegroup {
+ name: "foo",
+ srcs: ["aidl/foo.aidl"],
+ path: "aidl",
+ aidl: {
+ deps: [":bar"],
+ }
+ }`
+
+ t.Run("filegroup with aidl deps", func(t *testing.T) {
+ expectedBazelTargets := []string{
+ MakeBazelTargetNoRestrictions("aidl_library", "bar", AttrNameToString{
+ "srcs": `["bar.aidl"]`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
+ }),
+ MakeBazelTargetNoRestrictions("aidl_library", "foo", AttrNameToString{
+ "srcs": `["aidl/foo.aidl"]`,
+ "strip_import_prefix": `"aidl"`,
+ "deps": `[":bar"]`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
+ }),
+ }
+ runFilegroupTestCase(t, Bp2buildTestCase{
+ Description: "filegroup with aidl deps",
+ Blueprint: bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ })
+}
+
func TestFilegroupWithAidlAndNonAidlSrcs(t *testing.T) {
runFilegroupTestCase(t, Bp2buildTestCase{
Description: "filegroup with aidl and non-aidl srcs",
@@ -136,7 +176,11 @@
MakeBazelTargetNoRestrictions("proto_library", "foo_bp2build_converted", AttrNameToString{
"srcs": `["proto/foo.proto"]`,
"strip_import_prefix": `"proto"`,
- "tags": `["manual"]`}),
+ "tags": `[
+ "apex_available=//apex_available:anyapex",
+ "manual",
+ ]`,
+ }),
MakeBazelTargetNoRestrictions("filegroup", "foo", AttrNameToString{
"srcs": `["proto/foo.proto"]`}),
}})
diff --git a/bp2build/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go
index 6f17e34..c821f59 100644
--- a/bp2build/java_binary_host_conversion_test.go
+++ b/bp2build/java_binary_host_conversion_test.go
@@ -56,20 +56,25 @@
java_version: "8",
}`,
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"]`,
- "javacopts": `[
- "-Xdoclint:all/protected",
- "-source 1.8 -target 1.8",
- ]`,
+ MakeBazelTarget("java_library", "java-binary-host-1_lib", AttrNameToString{
+ "srcs": `["a.java"]`,
+ "deps": `["//other:jni-lib-1"]`,
+ "java_version": `"8"`,
+ "javacopts": `["-Xdoclint:all/protected"]`,
"target_compatible_with": `select({
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
"//conditions:default": [],
})`,
}),
+ MakeBazelTarget("java_binary", "java-binary-host-1", AttrNameToString{
+ "main_class": `"com.android.test.MainClass"`,
+ "jvm_flags": `["-Djava.library.path=$${RUNPATH}other"]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ "runtime_deps": `[":java-binary-host-1_lib"]`,
+ }),
},
})
}
@@ -122,15 +127,22 @@
}
`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("java_binary", "java-binary-host-libs", AttrNameToString{
- "main_class": `"com.android.test.MainClass"`,
- "srcs": `["a.java"]`,
- "deps": `[":java-lib-dep-1-neverlink"]`,
+ MakeBazelTarget("java_library", "java-binary-host-libs_lib", AttrNameToString{
+ "srcs": `["a.java"]`,
+ "deps": `[":java-lib-dep-1-neverlink"]`,
"target_compatible_with": `select({
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
"//conditions:default": [],
})`,
}),
+ MakeBazelTarget("java_binary", "java-binary-host-libs", AttrNameToString{
+ "main_class": `"com.android.test.MainClass"`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ "runtime_deps": `[":java-binary-host-libs_lib"]`,
+ }),
},
})
}
@@ -146,7 +158,7 @@
}
`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("kt_jvm_library", "java-binary-host_kt", AttrNameToString{
+ MakeBazelTarget("kt_jvm_library", "java-binary-host_lib", AttrNameToString{
"srcs": `[
"a.java",
"b.kt",
@@ -158,7 +170,7 @@
}),
MakeBazelTarget("java_binary", "java-binary-host", AttrNameToString{
"main_class": `"com.android.test.MainClass"`,
- "runtime_deps": `[":java-binary-host_kt"]`,
+ "runtime_deps": `[":java-binary-host_lib"]`,
"target_compatible_with": `select({
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
"//conditions:default": [],
@@ -180,7 +192,7 @@
}
`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("kt_jvm_library", "java-binary-host_kt", AttrNameToString{
+ MakeBazelTarget("kt_jvm_library", "java-binary-host_lib", AttrNameToString{
"srcs": `["a.java"]`,
"common_srcs": `["b.kt"]`,
"target_compatible_with": `select({
@@ -190,7 +202,7 @@
}),
MakeBazelTarget("java_binary", "java-binary-host", AttrNameToString{
"main_class": `"com.android.test.MainClass"`,
- "runtime_deps": `[":java-binary-host_kt"]`,
+ "runtime_deps": `[":java-binary-host_lib"]`,
"target_compatible_with": `select({
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
"//conditions:default": [],
@@ -216,7 +228,7 @@
}
`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("kt_jvm_library", "java-binary-host_kt", AttrNameToString{
+ MakeBazelTarget("kt_jvm_library", "java-binary-host_lib", AttrNameToString{
"srcs": `[
"a.java",
"b.kt",
@@ -233,7 +245,7 @@
}),
MakeBazelTarget("java_binary", "java-binary-host", AttrNameToString{
"main_class": `"com.android.test.MainClass"`,
- "runtime_deps": `[":java-binary-host_kt"]`,
+ "runtime_deps": `[":java-binary-host_lib"]`,
"target_compatible_with": `select({
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
"//conditions:default": [],
@@ -259,7 +271,7 @@
}
`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("kt_jvm_library", "java-binary-host_kt", AttrNameToString{
+ MakeBazelTarget("kt_jvm_library", "java-binary-host_lib", AttrNameToString{
"srcs": `[
"a.java",
"b.kt",
@@ -275,7 +287,42 @@
}),
MakeBazelTarget("java_binary", "java-binary-host", AttrNameToString{
"main_class": `"com.android.test.MainClass"`,
- "runtime_deps": `[":java-binary-host_kt"]`,
+ "runtime_deps": `[":java-binary-host_lib"]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
+
+func TestJavaBinaryHostKotlinCflags(t *testing.T) {
+ runJavaBinaryHostTestCase(t, Bp2buildTestCase{
+ Description: "java_binary_host with kotlincflags",
+ Filesystem: testFs,
+ Blueprint: `java_binary_host {
+ name: "java-binary-host",
+ manifest: "test.mf",
+ srcs: ["a.kt"],
+ kotlincflags: ["-flag1", "-flag2"],
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("kt_jvm_library", "java-binary-host_lib", AttrNameToString{
+ "srcs": `["a.kt"]`,
+ "kotlincflags": `[
+ "-flag1",
+ "-flag2",
+ ]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTarget("java_binary", "java-binary-host", AttrNameToString{
+ "main_class": `"com.android.test.MainClass"`,
+ "runtime_deps": `[":java-binary-host_lib"]`,
"target_compatible_with": `select({
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
"//conditions:default": [],
diff --git a/bp2build/java_host_for_device_conversion_test.go b/bp2build/java_host_for_device_conversion_test.go
new file mode 100644
index 0000000..448cba4
--- /dev/null
+++ b/bp2build/java_host_for_device_conversion_test.go
@@ -0,0 +1,65 @@
+// Copyright 2023 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 runJavaHostForDeviceTestCaseWithRegistrationCtxFunc(t *testing.T, tc Bp2buildTestCase, registrationCtxFunc func(ctx android.RegistrationContext)) {
+ t.Helper()
+ (&tc).ModuleTypeUnderTest = "java_host_for_device"
+ (&tc).ModuleTypeUnderTestFactory = java.HostForDeviceFactory
+ RunBp2BuildTestCase(t, registrationCtxFunc, tc)
+}
+
+func runJavaHostForDeviceTestCase(t *testing.T, tc Bp2buildTestCase) {
+ t.Helper()
+ runJavaHostForDeviceTestCaseWithRegistrationCtxFunc(t, tc, func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("java_library", java.LibraryFactory)
+ })
+}
+
+func TestJavaHostForDevice(t *testing.T) {
+ runJavaHostForDeviceTestCase(t, Bp2buildTestCase{
+ Description: "java_host_for_device test",
+ Blueprint: `java_host_for_device {
+ name: "java-lib-1",
+ 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_host_for_device", "java-lib-1", AttrNameToString{
+ "exports": `[":java-lib-2"]`,
+ }),
+ MakeNeverlinkDuplicateTargetWithAttrs("java_library", "java-lib-1", AttrNameToString{
+ "sdk_version": `"none"`,
+ }),
+ MakeBazelTarget("java_library", "java-lib-2", AttrNameToString{
+ "srcs": `["b.java"]`,
+ }),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-2"),
+ },
+ })
+}
diff --git a/bp2build/java_import_conversion_test.go b/bp2build/java_import_conversion_test.go
index a5c01cb..5661620 100644
--- a/bp2build/java_import_conversion_test.go
+++ b/bp2build/java_import_conversion_test.go
@@ -49,8 +49,9 @@
"jars": `["import.jar"]`,
}),
MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
- "exports": `[":example_import"]`,
- "neverlink": `True`,
+ "exports": `[":example_import"]`,
+ "neverlink": `True`,
+ "sdk_version": `"none"`,
}),
}})
}
@@ -86,8 +87,9 @@
})`,
}),
MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
- "exports": `[":example_import"]`,
- "neverlink": `True`,
+ "exports": `[":example_import"]`,
+ "neverlink": `True`,
+ "sdk_version": `"none"`,
}),
}})
}
@@ -112,8 +114,9 @@
"jars": `["import.jar"]`,
}),
MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
- "exports": `[":example_import"]`,
- "neverlink": `True`,
+ "exports": `[":example_import"]`,
+ "neverlink": `True`,
+ "sdk_version": `"none"`,
}),
}})
}
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index 0784f4b..24b763b 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -172,10 +172,13 @@
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "srcs": `["a.java"]`,
- "javacopts": `["-source 11 -target 11"]`,
+ "srcs": `["a.java"]`,
+ "java_version": `"11"`,
}),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
+ MakeNeverlinkDuplicateTargetWithAttrs(
+ "java_library",
+ "java-lib-1",
+ AttrNameToString{"java_version": `"11"`}),
},
})
}
@@ -493,6 +496,7 @@
"a.aidl",
"b.aidl",
]`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
}),
MakeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{
"deps": `[":aidl_files"]`,
@@ -673,7 +677,7 @@
func TestJavaLibraryKotlinSrcs(t *testing.T) {
runJavaLibraryTestCase(t, Bp2buildTestCase{
- Description: "java_library with kotlin srcs",
+ Description: "java_library with kotlin srcs",
Blueprint: `java_library {
name: "java-lib-1",
srcs: ["a.java", "b.java", "c.kt"],
@@ -693,9 +697,32 @@
})
}
+func TestJavaLibraryKotlincflags(t *testing.T) {
+ runJavaLibraryTestCase(t, Bp2buildTestCase{
+ Description: "java_library with kotlincfalgs",
+ Blueprint: `java_library {
+ name: "java-lib-1",
+ srcs: [ "a.kt"],
+ kotlincflags: ["-flag1", "-flag2"],
+ bazel_module: { bp2build_available: true },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("kt_jvm_library", "java-lib-1", AttrNameToString{
+ "srcs": `["a.kt"]`,
+ "kotlincflags": `[
+ "-flag1",
+ "-flag2",
+ ]`,
+ }),
+ MakeNeverlinkDuplicateTarget("kt_jvm_library", "java-lib-1"),
+ },
+ })
+}
+
func TestJavaLibraryKotlinCommonSrcs(t *testing.T) {
runJavaLibraryTestCase(t, Bp2buildTestCase{
- Description: "java_library with kotlin common_srcs",
+ Description: "java_library with kotlin common_srcs",
Blueprint: `java_library {
name: "java-lib-1",
srcs: ["a.java", "b.java"],
@@ -716,7 +743,7 @@
})
}
-func TestJavaLibraryArchVariantLibs(t *testing.T) {
+func TestJavaLibraryArchVariantDeps(t *testing.T) {
runJavaLibraryTestCase(t, Bp2buildTestCase{
Description: "java_library with arch variant libs",
Blueprint: `java_library {
@@ -726,6 +753,7 @@
target: {
android: {
libs: ["java-lib-3"],
+ static_libs: ["java-lib-4"],
},
},
bazel_module: { bp2build_available: true },
@@ -738,12 +766,23 @@
java_library{
name: "java-lib-3",
}
+
+ java_library{
+ name: "java-lib-4",
+}
`,
ExpectedBazelTargets: []string{
MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
"srcs": `["a.java"]`,
+ "exports": `select({
+ "//build/bazel/platforms/os:android": [":java-lib-4"],
+ "//conditions:default": [],
+ })`,
"deps": `[":java-lib-2-neverlink"] + select({
- "//build/bazel/platforms/os:android": [":java-lib-3-neverlink"],
+ "//build/bazel/platforms/os:android": [
+ ":java-lib-3-neverlink",
+ ":java-lib-4",
+ ],
"//conditions:default": [],
})`,
}),
@@ -752,6 +791,34 @@
MakeNeverlinkDuplicateTarget("java_library", "java-lib-2"),
MakeBazelTarget("java_library", "java-lib-3", AttrNameToString{}),
MakeNeverlinkDuplicateTarget("java_library", "java-lib-3"),
+ MakeBazelTarget("java_library", "java-lib-4", AttrNameToString{}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-4"),
+ },
+ })
+}
+
+func TestJavaLibraryArchVariantSrcsWithExcludes(t *testing.T) {
+ runJavaLibraryTestCase(t, Bp2buildTestCase{
+ Description: "java_library with arch variant libs",
+ Blueprint: `java_library {
+ name: "java-lib-1",
+ srcs: ["a.java", "b.java"],
+ target: {
+ android: {
+ exclude_srcs: ["a.java"],
+ },
+ },
+ bazel_module: { bp2build_available: true },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
+ "srcs": `["b.java"] + select({
+ "//build/bazel/platforms/os:android": [],
+ "//conditions:default": ["a.java"],
+ })`,
+ }),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
},
})
}
diff --git a/bp2build/java_library_host_conversion_test.go b/bp2build/java_library_host_conversion_test.go
index 14854c0..9e47b09 100644
--- a/bp2build/java_library_host_conversion_test.go
+++ b/bp2build/java_library_host_conversion_test.go
@@ -63,8 +63,8 @@
})`,
}),
MakeBazelTarget("java_library", "java-lib-host-2", AttrNameToString{
- "javacopts": `["-source 1.9 -target 1.9"]`,
- "srcs": `["c.java"]`,
+ "java_version": `"9"`,
+ "srcs": `["c.java"]`,
"target_compatible_with": `select({
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
"//conditions:default": [],
@@ -77,6 +77,7 @@
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
"//conditions:default": [],
})`,
+ "java_version": `"9"`,
}),
},
})
diff --git a/bp2build/java_plugin_conversion_test.go b/bp2build/java_plugin_conversion_test.go
index 8c6337b..f2b6f20 100644
--- a/bp2build/java_plugin_conversion_test.go
+++ b/bp2build/java_plugin_conversion_test.go
@@ -67,7 +67,7 @@
"a.java",
"b.java",
]`,
- "javacopts": `["-source 1.7 -target 1.7"]`,
+ "java_version": `"7"`,
}),
},
})
diff --git a/bp2build/java_proto_conversion_test.go b/bp2build/java_proto_conversion_test.go
index d25b7c4..f546cf4 100644
--- a/bp2build/java_proto_conversion_test.go
+++ b/bp2build/java_proto_conversion_test.go
@@ -114,13 +114,17 @@
"java_lite_proto_library",
"java-protos_java_proto_lite",
AttrNameToString{
- "deps": `[":java-protos_proto"]`,
+ "deps": `[":java-protos_proto"]`,
+ "java_version": `"7"`,
}),
MakeBazelTarget("java_library", "java-protos", AttrNameToString{
- "exports": `[":java-protos_java_proto_lite"]`,
- "javacopts": `["-source 1.7 -target 1.7"]`,
+ "exports": `[":java-protos_java_proto_lite"]`,
+ "java_version": `"7"`,
}),
- MakeNeverlinkDuplicateTarget("java_library", "java-protos"),
+ MakeNeverlinkDuplicateTargetWithAttrs(
+ "java_library",
+ "java-protos",
+ AttrNameToString{"java_version": `"7"`}),
},
})
}
diff --git a/bp2build/python_test_conversion_test.go b/bp2build/python_test_conversion_test.go
new file mode 100644
index 0000000..4ff1fa1
--- /dev/null
+++ b/bp2build/python_test_conversion_test.go
@@ -0,0 +1,66 @@
+// Copyright 2023 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/python"
+ "testing"
+)
+
+func TestPythonTestHostSimple(t *testing.T) {
+ runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+ Description: "simple python_test_host converts to a native py_test",
+ ModuleTypeUnderTest: "python_test_host",
+ ModuleTypeUnderTestFactory: python.PythonTestHostFactory,
+ Filesystem: map[string]string{
+ "a.py": "",
+ "b/c.py": "",
+ "b/d.py": "",
+ "b/e.py": "",
+ "files/data.txt": "",
+ },
+ Blueprint: `python_test_host {
+ name: "foo",
+ main: "a.py",
+ srcs: ["**/*.py"],
+ exclude_srcs: ["b/e.py"],
+ data: ["files/data.txt",],
+ libs: ["bar"],
+ bazel_module: { bp2build_available: true },
+}
+ python_library_host {
+ name: "bar",
+ srcs: ["b/e.py"],
+ bazel_module: { bp2build_available: false },
+ }`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("py_test", "foo", AttrNameToString{
+ "data": `["files/data.txt"]`,
+ "deps": `[":bar"]`,
+ "main": `"a.py"`,
+ "imports": `["."]`,
+ "srcs": `[
+ "a.py",
+ "b/c.py",
+ "b/d.py",
+ ]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go
index aac5e7d..5c33308 100644
--- a/bp2build/symlink_forest.go
+++ b/bp2build/symlink_forest.go
@@ -21,10 +21,13 @@
"path/filepath"
"regexp"
"sort"
+ "strconv"
+ "strings"
"sync"
"sync/atomic"
"android/soong/shared"
+
"github.com/google/blueprint/pathtools"
)
@@ -35,6 +38,13 @@
// excluded from symlinking. Otherwise, the node is not excluded, but one of its
// descendants is (otherwise the node in question would not exist)
+// This is a version int written to a file called symlink_forest_version at the root of the
+// symlink forest. If the version here does not match the version in the file, then we'll
+// clean the whole symlink forest and recreate it. This number can be bumped whenever there's
+// an incompatible change to the forest layout or a bug in incrementality that needs to be fixed
+// on machines that may still have the bug present in their forest.
+const symlinkForestVersion = 1
+
type instructionsNode struct {
name string
excluded bool // If false, this is just an intermediate node
@@ -123,6 +133,34 @@
}
newContents = append(newContents, srcBuildFileContent...)
+ // Say you run bp2build 4 times:
+ // - The first time there's only an Android.bp file. bp2build will convert it to a build file
+ // under out/soong/bp2build, then symlink from the forest to that generated file
+ // - Then you add a handcrafted BUILD file in the same directory. bp2build will merge this with
+ // the generated one, and write the result to the output file in the forest. But the output
+ // file was a symlink to out/soong/bp2build from the previous step! So we erroneously update
+ // the file in out/soong/bp2build instead. So far this doesn't cause any problems...
+ // - You run a 3rd bp2build with no relevant changes. Everything continues to work.
+ // - You then add a comment to the handcrafted BUILD file. This causes a merge with the
+ // generated file again. But since we wrote to the generated file in step 2, the generated
+ // file has an old copy of the handcrafted file in it! This probably causes duplicate bazel
+ // targets.
+ // To solve this, if we see that the output file is a symlink from a previous build, remove it.
+ stat, err := os.Lstat(output)
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ } else if err == nil {
+ if stat.Mode()&os.ModeSymlink == os.ModeSymlink {
+ if verbose {
+ fmt.Fprintf(os.Stderr, "Removing symlink so that we can replace it with a merged file: %s\n", output)
+ }
+ err = os.Remove(output)
+ if err != nil {
+ return err
+ }
+ }
+ }
+
return pathtools.WriteFileIfChanged(output, newContents, 0666)
}
@@ -202,6 +240,46 @@
return false
}
+// maybeCleanSymlinkForest will remove the whole symlink forest directory if the version recorded
+// in the symlink_forest_version file is not equal to symlinkForestVersion.
+func maybeCleanSymlinkForest(topdir, forest string, verbose bool) error {
+ versionFilePath := shared.JoinPath(topdir, forest, "symlink_forest_version")
+ versionFileContents, err := os.ReadFile(versionFilePath)
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+ versionFileString := strings.TrimSpace(string(versionFileContents))
+ symlinkForestVersionString := strconv.Itoa(symlinkForestVersion)
+ if err != nil || versionFileString != symlinkForestVersionString {
+ if verbose {
+ fmt.Fprintf(os.Stderr, "Old symlink_forest_version was %q, current is %q. Cleaning symlink forest before recreating...\n", versionFileString, symlinkForestVersionString)
+ }
+ err = os.RemoveAll(shared.JoinPath(topdir, forest))
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// maybeWriteVersionFile will write the symlink_forest_version file containing symlinkForestVersion
+// if it doesn't exist already. If it exists we know it must contain symlinkForestVersion because
+// we checked for that already in maybeCleanSymlinkForest
+func maybeWriteVersionFile(topdir, forest string) error {
+ versionFilePath := shared.JoinPath(topdir, forest, "symlink_forest_version")
+ _, err := os.Stat(versionFilePath)
+ if err != nil {
+ if !os.IsNotExist(err) {
+ return err
+ }
+ err = os.WriteFile(versionFilePath, []byte(strconv.Itoa(symlinkForestVersion)+"\n"), 0666)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
// Recursively plants a symlink forest at forestDir. The symlink tree will
// contain every file in buildFilesDir and srcDir excluding the files in
// instructions. Collects every directory encountered during the traversal of
@@ -395,6 +473,12 @@
symlinkCount: atomic.Uint64{},
}
+ err := maybeCleanSymlinkForest(topdir, forest, verbose)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+
instructions := instructionsFromExcludePathList(exclude)
go func() {
context.wg.Add(1)
@@ -407,5 +491,11 @@
deps = append(deps, dep)
}
+ err = maybeWriteVersionFile(topdir, forest)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+
return deps, context.mkdirCount.Load(), context.symlinkCount.Load()
}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index bac5383..fd99ff0 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -21,6 +21,7 @@
import (
"fmt"
+ "sort"
"strings"
"testing"
@@ -227,6 +228,7 @@
//
// If ignoreUnexpected=true then it will ignore directories for which there are no expected targets.
func (b BazelTestResult) CompareAllBazelTargets(t *testing.T, description string, expectedTargets map[string][]string, ignoreUnexpected bool) {
+ t.Helper()
actualTargets := b.buildFileToTargets
// Generate the sorted set of directories to check.
@@ -263,6 +265,12 @@
t.Errorf("%s: Expected %d bazel target (%s), got %d (%s)",
description, expectedCount, expectedContents, actualCount, actualTargets)
} else {
+ sort.SliceStable(actualTargets, func(i, j int) bool {
+ return actualTargets[i].name < actualTargets[j].name
+ })
+ sort.SliceStable(expectedContents, func(i, j int) bool {
+ return getTargetName(expectedContents[i]) < getTargetName(expectedContents[j])
+ })
for i, actualTarget := range actualTargets {
if w, g := expectedContents[i], actualTarget.content; w != g {
t.Errorf(
@@ -309,6 +317,8 @@
One_to_many_prop *bool
Api *string // File describing the APIs of this module
+
+ Test_config_setting *bool // Used to test generation of config_setting targets
}
type customModule struct {
@@ -482,6 +492,27 @@
}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
+
+ if proptools.Bool(m.props.Test_config_setting) {
+ m.createConfigSetting(ctx)
+ }
+
+}
+
+func (m *customModule) createConfigSetting(ctx android.TopDownMutatorContext) {
+ csa := bazel.ConfigSettingAttributes{
+ Flag_values: bazel.StringMapAttribute{
+ "//build/bazel/rules/my_string_setting": m.Name(),
+ },
+ }
+ ca := android.CommonAttributes{
+ Name: m.Name() + "_config_setting",
+ }
+ ctx.CreateBazelConfigSetting(
+ csa,
+ ca,
+ ctx.ModuleDir(),
+ )
}
var _ android.ApiProvider = (*customModule)(nil)
@@ -616,24 +647,40 @@
return ""
}
STUB_SUITE_ATTRS := map[string]string{
- "stubs_symbol_file": "symbol_file",
- "stubs_versions": "versions",
- "soname": "soname",
- "source_library": "source_library",
+ "stubs_symbol_file": "symbol_file",
+ "stubs_versions": "versions",
+ "soname": "soname",
+ "source_library_label": "source_library_label",
}
stubSuiteAttrs := AttrNameToString{}
for key, _ := range attrs {
if _, stubSuiteAttr := STUB_SUITE_ATTRS[key]; stubSuiteAttr {
stubSuiteAttrs[STUB_SUITE_ATTRS[key]] = attrs[key]
+ } else {
+ panic(fmt.Sprintf("unused cc_stub_suite attr %q\n", key))
}
}
return MakeBazelTarget("cc_stub_suite", name+"_stub_libs", stubSuiteAttrs)
}
func MakeNeverlinkDuplicateTarget(moduleType string, name string) string {
- return MakeBazelTarget(moduleType, name+"-neverlink", AttrNameToString{
- "neverlink": `True`,
- "exports": `[":` + name + `"]`,
- })
+ return MakeNeverlinkDuplicateTargetWithAttrs(moduleType, name, AttrNameToString{})
+}
+
+func MakeNeverlinkDuplicateTargetWithAttrs(moduleType string, name string, extraAttrs AttrNameToString) string {
+ attrs := extraAttrs
+ attrs["neverlink"] = `True`
+ attrs["exports"] = `[":` + name + `"]`
+ return MakeBazelTarget(moduleType, name+"-neverlink", attrs)
+}
+
+func getTargetName(targetContent string) string {
+ data := strings.Split(targetContent, "name = \"")
+ if len(data) < 2 {
+ return ""
+ } else {
+ endIndex := strings.Index(data[1], "\"")
+ return data[1][:endIndex]
+ }
}
diff --git a/cc/Android.bp b/cc/Android.bp
index 5fd9afe..be2cc5a 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -21,6 +21,8 @@
],
srcs: [
"afdo.go",
+ "fdo_profile.go",
+
"androidmk.go",
"api_level.go",
"bp2build.go",
diff --git a/cc/afdo.go b/cc/afdo.go
index d36f4af..49f6987 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -18,11 +18,13 @@
"fmt"
"strings"
- "github.com/google/blueprint/proptools"
-
"android/soong/android"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
)
+// TODO(b/267229066): Remove globalAfdoProfileProjects after implementing bp2build converter for fdo_profile
var (
globalAfdoProfileProjects = []string{
"vendor/google_data/pgo_profile/sampling/",
@@ -32,25 +34,25 @@
var afdoProfileProjectsConfigKey = android.NewOnceKey("AfdoProfileProjects")
-const afdoCFlagsFormat = "-funique-internal-linkage-names -fprofile-sample-accurate -fprofile-sample-use=%s"
-
-func getAfdoProfileProjects(config android.DeviceConfig) []string {
- return config.OnceStringSlice(afdoProfileProjectsConfigKey, func() []string {
- return globalAfdoProfileProjects
- })
-}
+const afdoCFlagsFormat = "-fprofile-sample-accurate -fprofile-sample-use=%s"
func recordMissingAfdoProfileFile(ctx android.BaseModuleContext, missing string) {
getNamedMapForConfig(ctx.Config(), modulesMissingProfileFileKey).Store(missing, true)
}
+type afdoRdep struct {
+ VariationName *string
+ ProfilePath *string
+}
+
type AfdoProperties struct {
// Afdo allows developers self-service enroll for
// automatic feedback-directed optimization using profile data.
Afdo bool
- AfdoTarget *string `blueprint:"mutated"`
- AfdoDeps []string `blueprint:"mutated"`
+ FdoProfilePath *string `blueprint:"mutated"`
+
+ AfdoRDeps []afdoRdep `blueprint:"mutated"`
}
type afdo struct {
@@ -61,79 +63,87 @@
return []interface{}{&afdo.Properties}
}
-func (afdo *afdo) AfdoEnabled() bool {
- return afdo != nil && afdo.Properties.Afdo && afdo.Properties.AfdoTarget != nil
-}
-
-// Get list of profile file names, ordered by level of specialisation. For example:
-// 1. libfoo_arm64.afdo
-// 2. libfoo.afdo
-//
-// Add more specialisation as needed.
-func getProfileFiles(ctx android.BaseModuleContext, moduleName string) []string {
- var files []string
- files = append(files, moduleName+"_"+ctx.Arch().ArchType.String()+".afdo")
- files = append(files, moduleName+".afdo")
- return files
-}
-
-func (props *AfdoProperties) GetAfdoProfileFile(ctx android.BaseModuleContext, module string) android.OptionalPath {
- // Test if the profile_file is present in any of the Afdo profile projects
- for _, profileFile := range getProfileFiles(ctx, module) {
- for _, profileProject := range getAfdoProfileProjects(ctx.DeviceConfig()) {
- path := android.ExistentPathForSource(ctx, profileProject, profileFile)
- if path.Valid() {
- return path
- }
- }
- }
-
- // Record that this module's profile file is absent
- missing := ctx.ModuleDir() + ":" + module
- recordMissingAfdoProfileFile(ctx, missing)
-
- return android.OptionalPathForPath(nil)
-}
-
-func (afdo *afdo) begin(ctx BaseModuleContext) {
- if ctx.Host() {
- return
- }
- if ctx.static() && !ctx.staticBinary() {
- return
- }
- if afdo.Properties.Afdo {
- module := ctx.ModuleName()
- if afdo.Properties.GetAfdoProfileFile(ctx, module).Valid() {
- afdo.Properties.AfdoTarget = proptools.StringPtr(module)
- }
- }
+// afdoEnabled returns true for binaries and shared libraries
+// that set afdo prop to True and there is a profile available
+func (afdo *afdo) afdoEnabled() bool {
+ return afdo != nil && afdo.Properties.Afdo
}
func (afdo *afdo) flags(ctx ModuleContext, flags Flags) Flags {
- if profile := afdo.Properties.AfdoTarget; profile != nil {
- if profileFile := afdo.Properties.GetAfdoProfileFile(ctx, *profile); profileFile.Valid() {
- profileFilePath := profileFile.Path()
+ if afdo.Properties.Afdo {
+ // We use `-funique-internal-linkage-names` to associate profiles to the right internal
+ // functions. This option should be used before generating a profile. Because a profile
+ // generated for a binary without unique names doesn't work well building a binary with
+ // unique names (they have different internal function names).
+ // To avoid a chicken-and-egg problem, we enable `-funique-internal-linkage-names` when
+ // `afdo=true`, whether a profile exists or not.
+ // The profile can take effect in three steps:
+ // 1. Add `afdo: true` in Android.bp, and build the binary.
+ // 2. Collect an AutoFDO profile for the binary.
+ // 3. Make the profile searchable by the build system. So it's used the next time the binary
+ // is built.
+ flags.Local.CFlags = append([]string{"-funique-internal-linkage-names"}, flags.Local.CFlags...)
+ }
+ if path := afdo.Properties.FdoProfilePath; path != nil {
+ // The flags are prepended to allow overriding.
+ profileUseFlag := fmt.Sprintf(afdoCFlagsFormat, *path)
+ flags.Local.CFlags = append([]string{profileUseFlag}, flags.Local.CFlags...)
+ flags.Local.LdFlags = append([]string{profileUseFlag, "-Wl,-mllvm,-no-warn-sample-unused=true"}, flags.Local.LdFlags...)
- profileUseFlag := fmt.Sprintf(afdoCFlagsFormat, profileFile)
- flags.Local.CFlags = append(flags.Local.CFlags, profileUseFlag)
- flags.Local.LdFlags = append(flags.Local.LdFlags, profileUseFlag)
- flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,-mllvm,-no-warn-sample-unused=true")
-
- // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
- // if profileFile gets updated
- flags.CFlagsDeps = append(flags.CFlagsDeps, profileFilePath)
- flags.LdFlagsDeps = append(flags.LdFlagsDeps, profileFilePath)
- }
+ // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
+ // if profileFile gets updated
+ pathForSrc := android.PathForSource(ctx, *path)
+ flags.CFlagsDeps = append(flags.CFlagsDeps, pathForSrc)
+ flags.LdFlagsDeps = append(flags.LdFlagsDeps, pathForSrc)
}
return flags
}
-// Propagate afdo requirements down from binaries
+func (afdo *afdo) addDep(ctx BaseModuleContext, actx android.BottomUpMutatorContext) {
+ if ctx.Host() {
+ return
+ }
+
+ if ctx.static() && !ctx.staticBinary() {
+ return
+ }
+
+ if c, ok := ctx.Module().(*Module); ok && c.Enabled() {
+ if fdoProfileName, err := actx.DeviceConfig().AfdoProfile(actx.ModuleName()); fdoProfileName != nil && err == nil {
+ actx.AddFarVariationDependencies(
+ []blueprint.Variation{
+ {Mutator: "arch", Variation: actx.Target().ArchVariation()},
+ {Mutator: "os", Variation: "android"},
+ },
+ FdoProfileTag,
+ []string{*fdoProfileName}...,
+ )
+ }
+ }
+}
+
+// FdoProfileMutator reads the FdoProfileProvider from a direct dep with FdoProfileTag
+// assigns FdoProfileInfo.Path to the FdoProfilePath mutated property
+func (c *Module) fdoProfileMutator(ctx android.BottomUpMutatorContext) {
+ if !c.Enabled() {
+ return
+ }
+
+ ctx.VisitDirectDepsWithTag(FdoProfileTag, func(m android.Module) {
+ if ctx.OtherModuleHasProvider(m, FdoProfileProvider) {
+ info := ctx.OtherModuleProvider(m, FdoProfileProvider).(FdoProfileInfo)
+ c.afdo.Properties.FdoProfilePath = proptools.StringPtr(info.Path.String())
+ }
+ })
+}
+
+var _ FdoProfileMutatorInterface = (*Module)(nil)
+
+// Propagate afdo requirements down from binaries and shared libraries
func afdoDepsMutator(mctx android.TopDownMutatorContext) {
- if m, ok := mctx.Module().(*Module); ok && m.afdo.AfdoEnabled() {
- afdoTarget := *m.afdo.Properties.AfdoTarget
+ if m, ok := mctx.Module().(*Module); ok && m.afdo.afdoEnabled() {
+ path := m.afdo.Properties.FdoProfilePath
mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
tag := mctx.OtherModuleDependencyTag(dep)
libTag, isLibTag := tag.(libraryDependencyTag)
@@ -150,7 +160,13 @@
}
if dep, ok := dep.(*Module); ok {
- dep.afdo.Properties.AfdoDeps = append(dep.afdo.Properties.AfdoDeps, afdoTarget)
+ dep.afdo.Properties.AfdoRDeps = append(
+ dep.afdo.Properties.AfdoRDeps,
+ afdoRdep{
+ VariationName: proptools.StringPtr(encodeTarget(m.Name())),
+ ProfilePath: path,
+ },
+ )
}
return true
@@ -161,16 +177,30 @@
// Create afdo variants for modules that need them
func afdoMutator(mctx android.BottomUpMutatorContext) {
if m, ok := mctx.Module().(*Module); ok && m.afdo != nil {
- if m.afdo.AfdoEnabled() && !m.static() {
- afdoTarget := *m.afdo.Properties.AfdoTarget
- mctx.SetDependencyVariation(encodeTarget(afdoTarget))
+ if !m.static() && m.afdo.Properties.Afdo {
+ mctx.SetDependencyVariation(encodeTarget(m.Name()))
+ return
}
variationNames := []string{""}
- afdoDeps := android.FirstUniqueStrings(m.afdo.Properties.AfdoDeps)
- for _, dep := range afdoDeps {
- variationNames = append(variationNames, encodeTarget(dep))
+
+ variantNameToProfilePath := make(map[string]*string)
+
+ for _, afdoRDep := range m.afdo.Properties.AfdoRDeps {
+ variantName := *afdoRDep.VariationName
+ // An rdep can be set twice in AfdoRDeps because there can be
+ // more than one path from an afdo-enabled module to
+ // a static dep such as
+ // afdo_enabled_foo -> static_bar ----> static_baz
+ // \ ^
+ // ----------------------|
+ // We only need to create one variant per unique rdep
+ if _, exists := variantNameToProfilePath[variantName]; !exists {
+ variationNames = append(variationNames, variantName)
+ variantNameToProfilePath[variantName] = afdoRDep.ProfilePath
+ }
}
+
if len(variationNames) > 1 {
modules := mctx.CreateVariations(variationNames...)
for i, name := range variationNames {
@@ -180,7 +210,8 @@
variation := modules[i].(*Module)
variation.Properties.PreventInstall = true
variation.Properties.HideFromMake = true
- variation.afdo.Properties.AfdoTarget = proptools.StringPtr(decodeTarget(name))
+ variation.afdo.Properties.Afdo = true
+ variation.afdo.Properties.FdoProfilePath = variantNameToProfilePath[name]
}
}
}
diff --git a/cc/afdo_test.go b/cc/afdo_test.go
index 335910c..b250ad1 100644
--- a/cc/afdo_test.go
+++ b/cc/afdo_test.go
@@ -58,38 +58,77 @@
srcs: ["bar.c"],
}
`
- prepareForAfdoTest := android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libTest.afdo", "TEST")
result := android.GroupFixturePreparers(
+ PrepareForTestWithFdoProfile,
prepareForCcTest,
- prepareForAfdoTest,
+ android.FixtureAddTextFile("afdo_profiles_package/libTest.afdo", ""),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.AfdoProfiles = []string{
+ "libTest://afdo_profiles_package:libTest_afdo",
+ }
+ }),
+ android.MockFS{
+ "afdo_profiles_package/Android.bp": []byte(`
+ fdo_profile {
+ name: "libTest_afdo",
+ profile: "libTest.afdo",
+ }
+ `),
+ }.AddToFixture(),
).RunTestWithBp(t, bp)
- libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
- libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
- libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_afdo-libTest")
+ expectedCFlag := "-fprofile-sample-use=afdo_profiles_package/libTest.afdo"
- if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
+ libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+ libFooAfdoVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
+ libBarAfdoVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_afdo-libTest")
+
+ // Check cFlags of afdo-enabled module and the afdo-variant of its static deps
+ cFlags := libTest.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ cFlags = libFooAfdoVariant.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libFooAfdoVariant' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ cFlags = libBarAfdoVariant.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libBarAfdoVariant' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ // Check dependency edge from afdo-enabled module to static deps
+ if !hasDirectDep(result, libTest.Module(), libFooAfdoVariant.Module()) {
t.Errorf("libTest missing dependency on afdo variant of libFoo")
}
- if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
+ if !hasDirectDep(result, libFooAfdoVariant.Module(), libBarAfdoVariant.Module()) {
t.Errorf("libTest missing dependency on afdo variant of libBar")
}
- cFlags := libTest.Rule("cc").Args["cFlags"]
- if w := "-fprofile-sample-accurate"; !strings.Contains(cFlags, w) {
- t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", w, cFlags)
- }
+ // Verify non-afdo variant exists and doesn't contain afdo
+ libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
+ libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
cFlags = libFoo.Rule("cc").Args["cFlags"]
- if w := "-fprofile-sample-accurate"; !strings.Contains(cFlags, w) {
- t.Errorf("Expected 'libFoo' to enable afdo, but did not find %q in cflags %q", w, cFlags)
+ if strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libFoo' to not enable afdo, but found %q in cflags %q", expectedCFlag, cFlags)
+ }
+ cFlags = libBar.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libBar' to not enable afdo, but found %q in cflags %q", expectedCFlag, cFlags)
}
- cFlags = libBar.Rule("cc").Args["cFlags"]
- if w := "-fprofile-sample-accurate"; !strings.Contains(cFlags, w) {
- t.Errorf("Expected 'libBar' to enable afdo, but did not find %q in cflags %q", w, cFlags)
+ // Check dependency edges of static deps
+ if hasDirectDep(result, libTest.Module(), libFoo.Module()) {
+ t.Errorf("libTest should not depend on non-afdo variant of libFoo")
+ }
+
+ if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
+ t.Errorf("libFoo missing dependency on non-afdo variant of libBar")
}
}
@@ -113,11 +152,21 @@
name: "libBar",
}
`
- prepareForAfdoTest := android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libFoo.afdo", "TEST")
result := android.GroupFixturePreparers(
prepareForCcTest,
- prepareForAfdoTest,
+ PrepareForTestWithFdoProfile,
+ android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libFoo.afdo", ""),
+ android.MockFS{
+ "afdo_profiles_package/Android.bp": []byte(`
+ soong_namespace {
+ }
+ fdo_profile {
+ name: "libFoo_afdo",
+ profile: "libFoo.afdo",
+ }
+ `),
+ }.AddToFixture(),
).RunTestWithBp(t, bp)
libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared").Module()
@@ -150,7 +199,6 @@
t.Errorf("Expected no afdo variant of 'bar', got %q", v)
}
}
-
}
func TestAfdoEnabledWithRuntimeDepNoAfdo(t *testing.T) {
@@ -166,11 +214,24 @@
name: "libFoo",
}
`
- prepareForAfdoTest := android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libTest.afdo", "TEST")
result := android.GroupFixturePreparers(
prepareForCcTest,
- prepareForAfdoTest,
+ PrepareForTestWithFdoProfile,
+ android.FixtureAddTextFile("afdo_profiles_package/libTest.afdo", ""),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.AfdoProfiles = []string{
+ "libTest://afdo_profiles_package:libTest_afdo",
+ }
+ }),
+ android.MockFS{
+ "afdo_profiles_package/Android.bp": []byte(`
+ fdo_profile {
+ name: "libTest_afdo",
+ profile: "libTest.afdo",
+ }
+ `),
+ }.AddToFixture(),
).RunTestWithBp(t, bp)
libFooVariants := result.ModuleVariantsForTests("libFoo")
@@ -180,3 +241,223 @@
}
}
}
+
+func TestAfdoEnabledWithMultiArchs(t *testing.T) {
+ bp := `
+ cc_library_shared {
+ name: "foo",
+ srcs: ["test.c"],
+ afdo: true,
+ compile_multilib: "both",
+ }
+`
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithFdoProfile,
+ prepareForCcTest,
+ android.FixtureAddTextFile("afdo_profiles_package/foo_arm.afdo", ""),
+ android.FixtureAddTextFile("afdo_profiles_package/foo_arm64.afdo", ""),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.AfdoProfiles = []string{
+ "foo://afdo_profiles_package:foo_afdo",
+ }
+ }),
+ android.MockFS{
+ "afdo_profiles_package/Android.bp": []byte(`
+ soong_namespace {
+ }
+ fdo_profile {
+ name: "foo_afdo",
+ arch: {
+ arm: {
+ profile: "foo_arm.afdo",
+ },
+ arm64: {
+ profile: "foo_arm64.afdo",
+ }
+ }
+ }
+ `),
+ }.AddToFixture(),
+ ).RunTestWithBp(t, bp)
+
+ fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon_shared")
+ fooArmCFlags := fooArm.Rule("cc").Args["cFlags"]
+ if w := "-fprofile-sample-use=afdo_profiles_package/foo_arm.afdo"; !strings.Contains(fooArmCFlags, w) {
+ t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArmCFlags)
+ }
+
+ fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a_shared")
+ fooArm64CFlags := fooArm64.Rule("cc").Args["cFlags"]
+ if w := "-fprofile-sample-use=afdo_profiles_package/foo_arm64.afdo"; !strings.Contains(fooArm64CFlags, w) {
+ t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArm64CFlags)
+ }
+}
+
+func TestMultipleAfdoRDeps(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library_shared {
+ name: "libTest",
+ srcs: ["test.c"],
+ static_libs: ["libFoo"],
+ afdo: true,
+ }
+
+ cc_library_shared {
+ name: "libBar",
+ srcs: ["bar.c"],
+ static_libs: ["libFoo"],
+ afdo: true,
+ }
+
+ cc_library_static {
+ name: "libFoo",
+ srcs: ["foo.c"],
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithFdoProfile,
+ prepareForCcTest,
+ android.FixtureAddTextFile("afdo_profiles_package/libTest.afdo", ""),
+ android.FixtureAddTextFile("afdo_profiles_package/libBar.afdo", ""),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.AfdoProfiles = []string{
+ "libTest://afdo_profiles_package:libTest_afdo",
+ "libBar://afdo_profiles_package:libBar_afdo",
+ }
+ }),
+ android.MockFS{
+ "afdo_profiles_package/Android.bp": []byte(`
+ fdo_profile {
+ name: "libTest_afdo",
+ profile: "libTest.afdo",
+ }
+ fdo_profile {
+ name: "libBar_afdo",
+ profile: "libBar.afdo",
+ }
+ `),
+ }.AddToFixture(),
+ ).RunTestWithBp(t, bp)
+
+ expectedCFlagLibTest := "-fprofile-sample-use=afdo_profiles_package/libTest.afdo"
+ expectedCFlagLibBar := "-fprofile-sample-use=afdo_profiles_package/libBar.afdo"
+
+ libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+ libFooAfdoVariantWithLibTest := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
+
+ libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_shared")
+ libFooAfdoVariantWithLibBar := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libBar")
+
+ // Check cFlags of afdo-enabled module and the afdo-variant of its static deps
+ cFlags := libTest.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlagLibTest) {
+ t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibTest, cFlags)
+ }
+ cFlags = libBar.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlagLibBar) {
+ t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
+ }
+
+ cFlags = libFooAfdoVariantWithLibTest.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlagLibTest) {
+ t.Errorf("Expected 'libFooAfdoVariantWithLibTest' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibTest, cFlags)
+ }
+
+ cFlags = libFooAfdoVariantWithLibBar.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlagLibBar) {
+ t.Errorf("Expected 'libBarAfdoVariant' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
+ }
+
+ // Check dependency edges of static deps
+ if !hasDirectDep(result, libTest.Module(), libFooAfdoVariantWithLibTest.Module()) {
+ t.Errorf("libTest missing dependency on afdo variant of libFoo")
+ }
+
+ if !hasDirectDep(result, libBar.Module(), libFooAfdoVariantWithLibBar.Module()) {
+ t.Errorf("libFoo missing dependency on non-afdo variant of libBar")
+ }
+}
+
+func TestAfdoDepsWithoutProfile(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library_shared {
+ name: "libTest",
+ srcs: ["test.c"],
+ static_libs: ["libFoo"],
+ afdo: true,
+ }
+
+ cc_library_static {
+ name: "libFoo",
+ srcs: ["foo.c"],
+ static_libs: ["libBar"],
+ }
+
+ cc_library_static {
+ name: "libBar",
+ srcs: ["bar.c"],
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithFdoProfile,
+ prepareForCcTest,
+ ).RunTestWithBp(t, bp)
+
+ // Even without a profile path, the afdo enabled libraries should be built with
+ // -funique-internal-linkage-names.
+ expectedCFlag := "-funique-internal-linkage-names"
+
+ libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+ libFooAfdoVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
+ libBarAfdoVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_afdo-libTest")
+
+ // Check cFlags of afdo-enabled module and the afdo-variant of its static deps
+ cFlags := libTest.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ cFlags = libFooAfdoVariant.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libFooAfdoVariant' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ cFlags = libBarAfdoVariant.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libBarAfdoVariant' to enable afdo, but did not find %q in cflags %q", expectedCFlag, cFlags)
+ }
+ // Check dependency edge from afdo-enabled module to static deps
+ if !hasDirectDep(result, libTest.Module(), libFooAfdoVariant.Module()) {
+ t.Errorf("libTest missing dependency on afdo variant of libFoo")
+ }
+
+ if !hasDirectDep(result, libFooAfdoVariant.Module(), libBarAfdoVariant.Module()) {
+ t.Errorf("libTest missing dependency on afdo variant of libBar")
+ }
+
+ // Verify non-afdo variant exists and doesn't contain afdo
+ libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
+ libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+
+ cFlags = libFoo.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libFoo' to not enable afdo, but found %q in cflags %q", expectedCFlag, cFlags)
+ }
+ cFlags = libBar.Rule("cc").Args["cFlags"]
+ if strings.Contains(cFlags, expectedCFlag) {
+ t.Errorf("Expected 'libBar' to not enable afdo, but found %q in cflags %q", expectedCFlag, cFlags)
+ }
+
+ // Check dependency edges of static deps
+ if hasDirectDep(result, libTest.Module(), libFoo.Module()) {
+ t.Errorf("libTest should not depend on non-afdo variant of libFoo")
+ }
+
+ if !hasDirectDep(result, libFoo.Module(), libBar.Module()) {
+ t.Errorf("libFoo missing dependency on non-afdo variant of libBar")
+ }
+}
diff --git a/cc/binary.go b/cc/binary.go
index 496c610..98b9923 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -512,7 +512,7 @@
}
binary.baseInstaller.subDir = "bootstrap"
}
- binary.baseInstaller.install(ctx, file)
+ binary.baseInstaller.installExecutable(ctx, file)
var preferredArchSymlinkPath android.OptionalPath
for _, symlink := range binary.symlinks {
@@ -661,7 +661,7 @@
// shared with cc_test
binaryAttrs := binaryBp2buildAttrs(ctx, m)
- tags := android.ApexAvailableTags(m)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{
Rule_class: "cc_binary",
Bzl_load_location: "//build/bazel/rules/cc:cc_binary.bzl",
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 8644bf6..1c94741 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -17,6 +17,7 @@
"fmt"
"path/filepath"
"strings"
+ "sync"
"android/soong/android"
"android/soong/bazel"
@@ -65,13 +66,17 @@
Native_coverage *bool
+ Apex_available []string
+
+ Features bazel.StringListAttribute
+
sdkAttributes
tidyAttributes
}
type tidyAttributes struct {
- Tidy *bool
+ Tidy *string
Tidy_flags []string
Tidy_checks []string
Tidy_checks_as_errors []string
@@ -82,7 +87,15 @@
func (m *Module) convertTidyAttributes(ctx android.BaseMutatorContext, moduleAttrs *tidyAttributes) {
for _, f := range m.features {
if tidy, ok := f.(*tidyFeature); ok {
- moduleAttrs.Tidy = tidy.Properties.Tidy
+ var tidyAttr *string
+ if tidy.Properties.Tidy != nil {
+ if *tidy.Properties.Tidy {
+ tidyAttr = proptools.StringPtr("local")
+ } else {
+ tidyAttr = proptools.StringPtr("never")
+ }
+ }
+ moduleAttrs.Tidy = tidyAttr
moduleAttrs.Tidy_flags = tidy.Properties.Tidy_flags
moduleAttrs.Tidy_checks = tidy.Properties.Tidy_checks
moduleAttrs.Tidy_checks_as_errors = tidy.Properties.Tidy_checks_as_errors
@@ -212,11 +225,11 @@
}
// Parses properties common to static and shared libraries. Also used for prebuilt libraries.
-func bp2buildParseStaticOrSharedProps(ctx android.BazelConversionPathContext, module *Module, _ *libraryDecorator, isStatic bool) staticOrSharedAttributes {
+func bp2buildParseStaticOrSharedProps(ctx android.BazelConversionPathContext, module *Module, lib *libraryDecorator, isStatic bool) staticOrSharedAttributes {
attrs := staticOrSharedAttributes{}
setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) {
- attrs.Copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag))
+ attrs.Copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag, filterOutHiddenVisibility))
attrs.Srcs.SetSelectValue(axis, config, android.BazelLabelForModuleSrc(ctx, props.Srcs))
attrs.System_dynamic_deps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, props.System_shared_libs))
@@ -236,13 +249,16 @@
// empty list -> no values specified
attrs.System_dynamic_deps.ForceSpecifyEmptyList = true
+ var apexAvailable []string
if isStatic {
+ apexAvailable = lib.StaticProperties.Static.Apex_available
bp2BuildPropParseHelper(ctx, module, &StaticProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
if staticOrSharedProps, ok := props.(*StaticProperties); ok {
setAttrs(axis, config, staticOrSharedProps.Static)
}
})
} else {
+ apexAvailable = lib.SharedProperties.Shared.Apex_available
bp2BuildPropParseHelper(ctx, module, &SharedProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
if staticOrSharedProps, ok := props.(*SharedProperties); ok {
setAttrs(axis, config, staticOrSharedProps.Shared)
@@ -255,6 +271,10 @@
attrs.Srcs_c = partitionedSrcs[cSrcPartition]
attrs.Srcs_as = partitionedSrcs[asSrcPartition]
+ attrs.Apex_available = android.ConvertApexAvailableToTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), apexAvailable)
+
+ attrs.Features.Append(convertHiddenVisibilityToFeatureStaticOrShared(ctx, module, isStatic))
+
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")
@@ -413,6 +433,12 @@
type filterOutFn func(string) bool
+// filterOutHiddenVisibility removes the flag specifying hidden visibility as
+// this flag is converted to a toolchain feature
+func filterOutHiddenVisibility(flag string) bool {
+ return flag == config.VisibilityHiddenFlag
+}
+
func filterOutStdFlag(flag string) bool {
return strings.HasPrefix(flag, "-std=")
}
@@ -475,7 +501,7 @@
// overridden. In Bazel we always allow overriding, via flags; however, this can cause
// incompatibilities, so we remove "-std=" flags from Cflag properties while leaving it in other
// cases.
- ca.copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag, filterOutClangUnknownCflags))
+ ca.copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag, filterOutClangUnknownCflags, filterOutHiddenVisibility))
ca.asFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Asflags, nil))
ca.conlyFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Conlyflags, filterOutClangUnknownCflags))
ca.cppFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Cppflags, filterOutClangUnknownCflags))
@@ -724,7 +750,7 @@
if baseLinkerProps, ok := archVariantLinkerProps[axis][cfg].(*BaseLinkerProperties); ok {
exportHdrs = baseLinkerProps.Export_generated_headers
- (&linkerAttrs).bp2buildForAxisAndConfig(ctx, module.Binary(), axis, cfg, baseLinkerProps)
+ (&linkerAttrs).bp2buildForAxisAndConfig(ctx, module, axis, cfg, baseLinkerProps)
}
headers := maybePartitionExportedAndImplementationsDeps(ctx, !module.Binary(), allHdrs, exportHdrs, android.BazelLabelForModuleDeps)
implementationHdrs.SetSelectValue(axis, cfg, headers.implementation)
@@ -747,8 +773,13 @@
if libraryProps, ok := archVariantLibraryProperties[axis][cfg].(*LibraryProperties); ok {
if axis == bazel.NoConfigAxis {
- compilerAttrs.stubsSymbolFile = libraryProps.Stubs.Symbol_file
- compilerAttrs.stubsVersions.SetSelectValue(axis, cfg, libraryProps.Stubs.Versions)
+ if libraryProps.Stubs.Symbol_file != nil {
+ compilerAttrs.stubsSymbolFile = libraryProps.Stubs.Symbol_file
+ versions := android.CopyOf(libraryProps.Stubs.Versions)
+ normalizeVersions(ctx, versions)
+ versions = addCurrentVersionIfNotPresent(versions)
+ compilerAttrs.stubsVersions.SetSelectValue(axis, cfg, versions)
+ }
}
if suffix := libraryProps.Suffix; suffix != nil {
compilerAttrs.suffix.SetSelectValue(axis, cfg, suffix)
@@ -818,6 +849,7 @@
features := compilerAttrs.features.Clone().Append(linkerAttrs.features).Append(bp2buildSanitizerFeatures(ctx, module))
features = features.Append(bp2buildLtoFeatures(ctx, module))
+ features = features.Append(convertHiddenVisibilityToFeatureBase(ctx, module))
features.DeduplicateAxesFromBase()
addMuslSystemDynamicDeps(ctx, linkerAttrs)
@@ -892,16 +924,20 @@
return false
})
+ apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), ctx.Module())
+ sdkAttrs := bp2BuildParseSdkAttributes(m)
+
if !aidlSrcs.IsEmpty() {
aidlLibName := m.Name() + "_aidl_library"
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "aidl_library",
- Bzl_load_location: "//build/bazel/rules/aidl:library.bzl",
+ Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
},
android.CommonAttributes{Name: aidlLibName},
&aidlLibraryAttributes{
Srcs: aidlSrcs,
+ Tags: apexAvailableTags,
},
)
aidlLibs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}})
@@ -909,15 +945,12 @@
if !aidlLibs.IsEmpty() {
ccAidlLibrarylabel := m.Name() + "_cc_aidl_library"
- // Since cc_aidl_library only needs the dynamic deps (aka shared libs) from the parent cc library for compiling,
- // we err on the side of not re-exporting the headers of the dynamic deps from cc_aidl_lirary
- // because the parent cc library already has all the dynamic deps
- implementationDynamicDeps := bazel.MakeLabelListAttribute(
- bazel.AppendBazelLabelLists(
- linkerAttrs.dynamicDeps.Value,
- linkerAttrs.implementationDynamicDeps.Value,
- ),
- )
+ // Since parent cc_library already has these dependencies, we can add them as implementation
+ // deps so that they don't re-export
+ implementationDeps := linkerAttrs.deps.Clone()
+ implementationDeps.Append(linkerAttrs.implementationDeps)
+ implementationDynamicDeps := linkerAttrs.dynamicDeps.Clone()
+ implementationDynamicDeps.Append(linkerAttrs.implementationDynamicDeps)
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
@@ -927,7 +960,10 @@
android.CommonAttributes{Name: ccAidlLibrarylabel},
&ccAidlLibraryAttributes{
Deps: aidlLibs,
- Implementation_dynamic_deps: implementationDynamicDeps,
+ Implementation_deps: *implementationDeps,
+ Implementation_dynamic_deps: *implementationDynamicDeps,
+ Tags: apexAvailableTags,
+ sdkAttributes: sdkAttrs,
},
)
label := &bazel.LabelAttribute{
@@ -1002,7 +1038,8 @@
la.implementationDeps.Append(staticExcludesLabelList)
}
-func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, isBinary bool, axis bazel.ConfigurationAxis, config string, props *BaseLinkerProperties) {
+func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, module *Module, axis bazel.ConfigurationAxis, config string, props *BaseLinkerProperties) {
+ isBinary := module.Binary()
// Use a single variable to capture usage of nocrt in arch variants, so there's only 1 error message for this module
var axisFeatures []string
@@ -1086,8 +1123,12 @@
// dependencies in NoConfigAxis and OsConfigurationAxis/OsAndroid are grouped by
// having stubs or not, so Bazel select() statement can be used to choose
// source/stub variants of them.
- setStubsForDynamicDeps(ctx, axis, config, sharedDeps.export, &la.dynamicDeps, 0)
- setStubsForDynamicDeps(ctx, axis, config, sharedDeps.implementation, &la.implementationDynamicDeps, 1)
+ apexAvailable := module.ApexAvailable()
+ setStubsForDynamicDeps(ctx, axis, config, apexAvailable, sharedDeps.export, &la.dynamicDeps, 0, false)
+ setStubsForDynamicDeps(ctx, axis, config, apexAvailable, sharedDeps.implementation, &la.implementationDynamicDeps, 1, false)
+ if len(systemSharedLibs) > 0 {
+ setStubsForDynamicDeps(ctx, axis, config, apexAvailable, bazelLabelForSharedDeps(ctx, systemSharedLibs), &la.systemDynamicDeps, 2, true)
+ }
}
if !BoolDefault(props.Pack_relocations, packRelocationsDefault) {
@@ -1144,13 +1185,86 @@
}
}
+var (
+ apiSurfaceModuleLibCurrentPackage = "@api_surfaces//" + android.ModuleLibApi.String() + "/current:"
+)
+
+func availableToSameApexes(a, b []string) bool {
+ if len(a) == 0 && len(b) == 0 {
+ return true
+ }
+ differ, _, _ := android.ListSetDifference(a, b)
+ return !differ
+}
+
+var (
+ apexConfigSettingKey = android.NewOnceKey("apexConfigSetting")
+ apexConfigSettingLock sync.Mutex
+)
+
+func getApexConfigSettingMap(config android.Config) *map[string]bool {
+ return config.Once(apexConfigSettingKey, func() interface{} {
+ return &map[string]bool{}
+ }).(*map[string]bool)
+}
+
+// Create a config setting for this apex in build/bazel/rules/apex
+// The use case for this is stub/impl selection in cc libraries
+// Long term, these config_setting(s) should be colocated with the respective apex definitions.
+// Note that this is an anti-pattern: The config_setting should be created from the apex definition
+// and not from a cc_library.
+// This anti-pattern is needed today since not all apexes have been allowlisted.
+func createInApexConfigSetting(ctx android.TopDownMutatorContext, apexName string) {
+ if apexName == android.AvailableToPlatform || apexName == android.AvailableToAnyApex {
+ // These correspond to android-non_apex and android-in_apex
+ return
+ }
+ apexConfigSettingLock.Lock()
+ defer apexConfigSettingLock.Unlock()
+
+ // Return if a config_setting has already been created
+ acsm := getApexConfigSettingMap(ctx.Config())
+ if _, exists := (*acsm)[apexName]; exists {
+ return
+ }
+ (*acsm)[apexName] = true
+
+ csa := bazel.ConfigSettingAttributes{
+ Flag_values: bazel.StringMapAttribute{
+ "//build/bazel/rules/apex:apex_name": apexName,
+ },
+ }
+ ca := android.CommonAttributes{
+ Name: "android-in_" + apexName,
+ }
+ ctx.CreateBazelConfigSetting(
+ csa,
+ ca,
+ "build/bazel/rules/apex",
+ )
+}
+
+func inApexConfigSetting(apexAvailable string) string {
+ if apexAvailable == android.AvailableToPlatform {
+ return bazel.AndroidAndNonApex
+ }
+ if apexAvailable == android.AvailableToAnyApex {
+ return bazel.AndroidAndInApex
+ }
+ return "//build/bazel/rules/apex:android-in_" + apexAvailable
+}
+
func setStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis,
- config string, dynamicLibs bazel.LabelList, dynamicDeps *bazel.LabelListAttribute, ind int) {
+ config string, apexAvailable []string, dynamicLibs bazel.LabelList, dynamicDeps *bazel.LabelListAttribute, ind int, buildNonApexWithStubs bool) {
+
depsWithStubs := []bazel.Label{}
for _, l := range dynamicLibs.Includes {
dep, _ := ctx.ModuleFromName(l.OriginalModuleName)
- if m, ok := dep.(*Module); ok && m.HasStubsVariants() {
- depsWithStubs = append(depsWithStubs, l)
+ if d, ok := dep.(*Module); ok && d.HasStubsVariants() {
+ depApexAvailable := d.ApexAvailable()
+ if !availableToSameApexes(apexAvailable, depApexAvailable) {
+ depsWithStubs = append(depsWithStubs, l)
+ }
}
}
if len(depsWithStubs) > 0 {
@@ -1159,26 +1273,39 @@
stubLibLabels := []bazel.Label{}
for _, l := range depsWithStubs {
- l.Label = l.Label + stubsSuffix
- stubLibLabels = append(stubLibLabels, l)
+ stubLabelInApiSurfaces := bazel.Label{
+ Label: apiSurfaceModuleLibCurrentPackage + strings.TrimPrefix(l.OriginalModuleName, ":"),
+ }
+ stubLibLabels = append(stubLibLabels, stubLabelInApiSurfaces)
}
inApexSelectValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex)
nonApexSelectValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex)
defaultSelectValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey)
+ nonApexDeps := depsWithStubs
+ if buildNonApexWithStubs {
+ nonApexDeps = stubLibLabels
+ }
if axis == bazel.NoConfigAxis {
(&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels))
- (&nonApexSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
+ (&nonApexSelectValue).Append(bazel.MakeLabelList(nonApexDeps))
(&defaultSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.FirstUniqueBazelLabelList(inApexSelectValue))
dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue))
dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, bazel.FirstUniqueBazelLabelList(defaultSelectValue))
} else if config == bazel.OsAndroid {
(&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels))
- (&nonApexSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
+ (&nonApexSelectValue).Append(bazel.MakeLabelList(nonApexDeps))
dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.FirstUniqueBazelLabelList(inApexSelectValue))
dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue))
}
}
+
+ // Create a config_setting for each apex_available.
+ // This will be used to select impl of a dep if dep is available to the same apex.
+ for _, aa := range apexAvailable {
+ createInApexConfigSetting(ctx.(android.TopDownMutatorContext), aa)
+ }
+
}
func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) {
@@ -1276,8 +1403,10 @@
la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, toRemove)
stubsToRemove := make([]bazel.Label, 0, len(la.usedSystemDynamicDepAsDynamicDep))
for _, lib := range toRemove.Includes {
- lib.Label += stubsSuffix
- stubsToRemove = append(stubsToRemove, lib)
+ stubLabelInApiSurfaces := bazel.Label{
+ Label: apiSurfaceModuleLibCurrentPackage + lib.OriginalModuleName,
+ }
+ stubsToRemove = append(stubsToRemove, stubLabelInApiSurfaces)
}
la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.MakeLabelList(stubsToRemove))
}
@@ -1506,3 +1635,38 @@
}
return ltoStringFeatures
}
+
+func convertHiddenVisibilityToFeatureBase(ctx android.BazelConversionPathContext, m *Module) bazel.StringListAttribute {
+ visibilityHiddenFeature := bazel.StringListAttribute{}
+ bp2BuildPropParseHelper(ctx, m, &BaseCompilerProperties{}, func(axis bazel.ConfigurationAxis, configString string, props interface{}) {
+ if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
+ convertHiddenVisibilityToFeatureHelper(&visibilityHiddenFeature, axis, configString, baseCompilerProps.Cflags)
+ }
+ })
+ return visibilityHiddenFeature
+}
+
+func convertHiddenVisibilityToFeatureStaticOrShared(ctx android.BazelConversionPathContext, m *Module, isStatic bool) bazel.StringListAttribute {
+ visibilityHiddenFeature := bazel.StringListAttribute{}
+ if isStatic {
+ bp2BuildPropParseHelper(ctx, m, &StaticProperties{}, func(axis bazel.ConfigurationAxis, configString string, props interface{}) {
+ if staticProps, ok := props.(*StaticProperties); ok {
+ convertHiddenVisibilityToFeatureHelper(&visibilityHiddenFeature, axis, configString, staticProps.Static.Cflags)
+ }
+ })
+ } else {
+ bp2BuildPropParseHelper(ctx, m, &SharedProperties{}, func(axis bazel.ConfigurationAxis, configString string, props interface{}) {
+ if sharedProps, ok := props.(*SharedProperties); ok {
+ convertHiddenVisibilityToFeatureHelper(&visibilityHiddenFeature, axis, configString, sharedProps.Shared.Cflags)
+ }
+ })
+ }
+
+ return visibilityHiddenFeature
+}
+
+func convertHiddenVisibilityToFeatureHelper(feature *bazel.StringListAttribute, axis bazel.ConfigurationAxis, configString string, cflags []string) {
+ if inList(config.VisibilityHiddenFlag, cflags) {
+ feature.SetSelectValue(axis, configString, []string{"visibility_hidden"})
+ }
+}
diff --git a/cc/cc.go b/cc/cc.go
index 0e88c56..adc93a7 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -52,6 +52,7 @@
ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
ctx.BottomUp("version", versionMutator).Parallel()
ctx.BottomUp("begin", BeginMutator).Parallel()
+ ctx.BottomUp("fdo_profile", fdoProfileMutator)
})
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -763,6 +764,7 @@
testPerSrcDepTag = dependencyTag{name: "test_per_src"}
stubImplDepTag = dependencyTag{name: "stub_impl"}
JniFuzzLibTag = dependencyTag{name: "jni_fuzz_lib_tag"}
+ FdoProfileTag = dependencyTag{name: "fdo_profile"}
)
func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
@@ -1336,7 +1338,7 @@
func (c *Module) isAfdoCompile() bool {
if afdo := c.afdo; afdo != nil {
- return afdo.Properties.AfdoTarget != nil
+ return afdo.Properties.FdoProfilePath != nil
}
return false
}
@@ -1473,7 +1475,7 @@
func InstallToBootstrap(name string, config android.Config) bool {
// NOTE: also update //build/bazel/rules/apex/cc.bzl#_installed_to_bootstrap
// if this list is updated.
- if name == "libclang_rt.hwasan" {
+ if name == "libclang_rt.hwasan" || name == "libc_hwasan" {
return true
}
return isBionic(name)
@@ -1856,6 +1858,10 @@
if c.SplitPerApiLevel() {
subName += "." + c.SdkVersion()
}
+ } else if c.IsStubs() && c.IsSdkVariant() {
+ // Public API surface (NDK)
+ // Add a suffix to this stub variant to distinguish it from the module-lib stub variant.
+ subName = sdkSuffix
}
return subName
@@ -1884,37 +1890,49 @@
c.bazelHandler.QueueBazelCall(ctx, c.getBazelModuleLabel(ctx))
}
-var (
- mixedBuildSupportedCcTest = []string{
- "adbd_test",
- "adb_crypto_test",
- "adb_pairing_auth_test",
- "adb_pairing_connection_test",
- "adb_tls_connection_test",
- }
-)
-
// IsMixedBuildSupported returns true if the module should be analyzed by Bazel
-// in any of the --bazel-mode(s). This filters at the module level and takes
-// precedence over the allowlists in allowlists/allowlists.go.
+// in any of the --bazel-mode(s).
func (c *Module) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
- _, isForTesting := ctx.Config().BazelContext.(android.MockBazelContext)
- if c.testBinary() && !android.InList(c.Name(), mixedBuildSupportedCcTest) && !isForTesting {
- // Per-module rollout of mixed-builds for cc_test modules.
+ if !allEnabledSanitizersSupportedByBazel(c) {
+ //TODO(b/278772861) support sanitizers in Bazel rules
return false
}
-
- // TODO(b/261058727): Remove this (enable mixed builds for modules with UBSan)
- // Currently we can only support ubsan when minimum runtime is used.
- return c.bazelHandler != nil && (!isUbsanEnabled(c) || c.MinimalRuntimeNeeded())
+ return c.bazelHandler != nil
}
-func isUbsanEnabled(c *Module) bool {
+func allEnabledSanitizersSupportedByBazel(c *Module) bool {
if c.sanitize == nil {
- return false
+ return true
}
sanitizeProps := &c.sanitize.Properties.SanitizeMutated
- return Bool(sanitizeProps.Integer_overflow) || len(sanitizeProps.Misc_undefined) > 0
+
+ unsupportedSanitizers := []*bool{
+ sanitizeProps.Safestack,
+ sanitizeProps.Cfi,
+ sanitizeProps.Scudo,
+ BoolPtr(len(c.sanitize.Properties.Sanitize.Recover) > 0),
+ BoolPtr(c.sanitize.Properties.Sanitize.Blocklist != nil),
+ }
+ for _, san := range unsupportedSanitizers {
+ if Bool(san) {
+ return false
+ }
+ }
+
+ for _, san := range Sanitizers {
+ if san == intOverflow {
+ // TODO(b/261058727): enable mixed builds for all modules with UBSan
+ // Currently we can only support ubsan when minimum runtime is used.
+ ubsanEnabled := Bool(sanitizeProps.Integer_overflow) || len(sanitizeProps.Misc_undefined) > 0
+ if ubsanEnabled && !c.MinimalRuntimeNeeded() {
+ return false
+ }
+ } else if c.sanitize.isSanitizerEnabled(san) {
+ return false
+ }
+ }
+
+ return true
}
func GetApexConfigKey(ctx android.BaseModuleContext) *android.ApexConfigKey {
@@ -1958,6 +1976,17 @@
c.maybeInstall(mctx, apexInfo)
}
+func moduleContextFromAndroidModuleContext(actx android.ModuleContext, c *Module) ModuleContext {
+ ctx := &moduleContext{
+ ModuleContext: actx,
+ moduleContextImpl: moduleContextImpl{
+ mod: c,
+ },
+ }
+ ctx.ctx = ctx
+ return ctx
+}
+
func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
// Handle the case of a test module split by `test_per_src` mutator.
//
@@ -1977,13 +2006,7 @@
c.makeLinkType = GetMakeLinkType(actx, c)
- ctx := &moduleContext{
- ModuleContext: actx,
- moduleContextImpl: moduleContextImpl{
- mod: c,
- },
- }
- ctx.ctx = ctx
+ ctx := moduleContextFromAndroidModuleContext(actx, c)
deps := c.depsToPaths(ctx)
if ctx.Failed() {
@@ -2162,9 +2185,6 @@
if c.lto != nil {
c.lto.begin(ctx)
}
- if c.afdo != nil {
- c.afdo.begin(ctx)
- }
if c.pgo != nil {
c.pgo.begin(ctx)
}
@@ -2239,6 +2259,10 @@
}
ctx.ctx = ctx
+ if !actx.Host() || !ctx.static() || ctx.staticBinary() {
+ c.afdo.addDep(ctx, actx)
+ }
+
c.begin(ctx)
}
@@ -2506,20 +2530,11 @@
if c.isNDKStubLibrary() {
// NDK stubs depend on their implementation because the ABI dumps are
// generated from the implementation library.
- apiImportName := c.BaseModuleName() + multitree.GetApiImportSuffix()
- // If original library exists as imported API, set dependency on the imported library
- if actx.OtherModuleExists(apiImportName) {
- actx.AddFarVariationDependencies(append(ctx.Target().Variations(),
- c.ImageVariation(),
- blueprint.Variation{Mutator: "link", Variation: "shared"},
- ), stubImplementation, apiImportName)
- } else {
- actx.AddFarVariationDependencies(append(ctx.Target().Variations(),
- c.ImageVariation(),
- blueprint.Variation{Mutator: "link", Variation: "shared"},
- ), stubImplementation, c.BaseModuleName())
- }
+ actx.AddFarVariationDependencies(append(ctx.Target().Variations(),
+ c.ImageVariation(),
+ blueprint.Variation{Mutator: "link", Variation: "shared"},
+ ), stubImplementation, c.BaseModuleName())
}
for _, lib := range deps.WholeStaticLibs {
@@ -2963,7 +2978,7 @@
ctx.VisitDirectDeps(func(dep android.Module) {
depName := ctx.OtherModuleName(dep)
if apiLibrary, ok := targetOrigModuleList[depName]; ok {
- if shouldUseStubForApex(ctx, dep) {
+ if ShouldUseStubForApex(ctx, dep) {
skipModuleList[depName] = true
} else {
skipModuleList[apiLibrary] = true
@@ -3316,7 +3331,7 @@
return depPaths
}
-func shouldUseStubForApex(ctx android.ModuleContext, dep android.Module) bool {
+func ShouldUseStubForApex(ctx android.ModuleContext, dep android.Module) bool {
depName := ctx.OtherModuleName(dep)
thisModule, ok := ctx.Module().(android.ApexModule)
if !ok {
@@ -3418,7 +3433,7 @@
if !libDepTag.explicitlyVersioned && len(sharedLibraryStubsInfo.SharedStubLibraries) > 0 {
// when to use (unspecified) stubs, use the latest one.
- if shouldUseStubForApex(ctx, dep) {
+ if ShouldUseStubForApex(ctx, dep) {
stubs := sharedLibraryStubsInfo.SharedStubLibraries
toUse := stubs[len(stubs)-1]
sharedLibraryInfo = toUse.SharedLibraryInfo
@@ -3475,7 +3490,6 @@
nonSystemVariantsExist := ccDep.HasNonSystemVariants() || isLLndk
if ccDepModule != nil {
- // TODO(ivanlozano) Support snapshots for Rust-produced C library variants.
// Use base module name for snapshots when exporting to Makefile.
if snapshotPrebuilt, ok := ccDepModule.linker.(SnapshotInterface); ok {
baseName := ccDepModule.BaseModuleName()
@@ -3880,6 +3894,7 @@
// When a vendor APEX needs a VNDK lib in it (use_vndk_as_stable: false), it should be a unique
// APEX variation. Otherwise, another vendor APEX with use_vndk_as_stable:true may use a wrong
// variation of the VNDK lib because APEX variations are merged/grouped.
+ // TODO(b/274401041) Find a way to merge APEX variations for vendor apexes.
return c.UseVndk() && c.IsVndk()
}
@@ -3920,8 +3935,8 @@
// TODO(b/244431896) properly convert cc_test_library to its own macro. This
// will let them add implicit compile deps on gtest, for example.
//
- // For now, treat them as regular shared libraries.
- return sharedLibrary
+ // For now, treat them as regular libraries.
+ return fullLibrary
} else if c.CcLibrary() {
static := false
shared := false
diff --git a/cc/cc_test.go b/cc/cc_test.go
index b02e037..f9e661f 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -59,7 +59,7 @@
func mixedBuildsPrepareMutator(ctx android.BottomUpMutatorContext) {
if m := ctx.Module(); m.Enabled() {
if mixedBuildMod, ok := m.(android.MixedBuildBuildable); ok {
- if mixedBuildMod.IsMixedBuildSupported(ctx) && android.MixedBuildsEnabled(ctx) {
+ if mixedBuildMod.IsMixedBuildSupported(ctx) && android.MixedBuildsEnabled(ctx) == android.MixedBuildEnabled {
mixedBuildMod.QueueBazelCall(ctx)
}
}
@@ -3114,6 +3114,11 @@
whole_static_libs: ["whole_static_dep"],
shared_libs: ["shared_dep"],
gtest: false,
+ sanitize: {
+ // cc_test modules default to memtag_heap: true,
+ // but this adds extra dependencies that we don't care about
+ never: true,
+ }
}
cc_binary {
name: "binary",
@@ -3572,6 +3577,235 @@
}
}
+func TestStubsForLibraryInMultipleApexes(t *testing.T) {
+ t.Parallel()
+ ctx := testCc(t, `
+ cc_library_shared {
+ name: "libFoo",
+ srcs: ["foo.c"],
+ stubs: {
+ symbol_file: "foo.map.txt",
+ versions: ["current"],
+ },
+ apex_available: ["bar", "a1"],
+ }
+
+ cc_library_shared {
+ name: "libBar",
+ srcs: ["bar.c"],
+ shared_libs: ["libFoo"],
+ apex_available: ["a1"],
+ }
+
+ cc_library_shared {
+ name: "libA1",
+ srcs: ["a1.c"],
+ shared_libs: ["libFoo"],
+ apex_available: ["a1"],
+ }
+
+ cc_library_shared {
+ name: "libBarA1",
+ srcs: ["bara1.c"],
+ shared_libs: ["libFoo"],
+ apex_available: ["bar", "a1"],
+ }
+
+ cc_library_shared {
+ name: "libAnyApex",
+ srcs: ["anyApex.c"],
+ shared_libs: ["libFoo"],
+ apex_available: ["//apex_available:anyapex"],
+ }
+
+ cc_library_shared {
+ name: "libBaz",
+ srcs: ["baz.c"],
+ shared_libs: ["libFoo"],
+ apex_available: ["baz"],
+ }
+
+ cc_library_shared {
+ name: "libQux",
+ srcs: ["qux.c"],
+ shared_libs: ["libFoo"],
+ apex_available: ["qux", "bar"],
+ }`)
+
+ variants := ctx.ModuleVariantsForTests("libFoo")
+ expectedVariants := []string{
+ "android_arm64_armv8-a_shared",
+ "android_arm64_armv8-a_shared_current",
+ "android_arm_armv7-a-neon_shared",
+ "android_arm_armv7-a-neon_shared_current",
+ }
+ variantsMismatch := false
+ if len(variants) != len(expectedVariants) {
+ variantsMismatch = true
+ } else {
+ for _, v := range expectedVariants {
+ if !inList(v, variants) {
+ variantsMismatch = false
+ }
+ }
+ }
+ if variantsMismatch {
+ t.Errorf("variants of libFoo expected:\n")
+ for _, v := range expectedVariants {
+ t.Errorf("%q\n", v)
+ }
+ t.Errorf(", but got:\n")
+ for _, v := range variants {
+ t.Errorf("%q\n", v)
+ }
+ }
+
+ linkAgainstFoo := []string{"libBarA1"}
+ linkAgainstFooStubs := []string{"libBar", "libA1", "libBaz", "libQux", "libAnyApex"}
+
+ libFooPath := "libFoo/android_arm64_armv8-a_shared/libFoo.so"
+ for _, lib := range linkAgainstFoo {
+ libLinkRule := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld")
+ libFlags := libLinkRule.Args["libFlags"]
+ if !strings.Contains(libFlags, libFooPath) {
+ t.Errorf("%q: %q is not found in %q", lib, libFooPath, libFlags)
+ }
+ }
+
+ libFooStubPath := "libFoo/android_arm64_armv8-a_shared_current/libFoo.so"
+ for _, lib := range linkAgainstFooStubs {
+ libLinkRule := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld")
+ libFlags := libLinkRule.Args["libFlags"]
+ if !strings.Contains(libFlags, libFooStubPath) {
+ t.Errorf("%q: %q is not found in %q", lib, libFooStubPath, libFlags)
+ }
+ }
+}
+
+func TestMixedBuildUsesStubs(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library_shared {
+ name: "libFoo",
+ bazel_module: { label: "//:libFoo" },
+ srcs: ["foo.c"],
+ stubs: {
+ symbol_file: "foo.map.txt",
+ versions: ["current"],
+ },
+ apex_available: ["bar", "a1"],
+ }
+
+ cc_library_shared {
+ name: "libBar",
+ srcs: ["bar.c"],
+ shared_libs: ["libFoo"],
+ apex_available: ["a1"],
+ }
+
+ cc_library_shared {
+ name: "libA1",
+ srcs: ["a1.c"],
+ shared_libs: ["libFoo"],
+ apex_available: ["a1"],
+ }
+
+ cc_library_shared {
+ name: "libBarA1",
+ srcs: ["bara1.c"],
+ shared_libs: ["libFoo"],
+ apex_available: ["bar", "a1"],
+ }
+
+ cc_library_shared {
+ name: "libAnyApex",
+ srcs: ["anyApex.c"],
+ shared_libs: ["libFoo"],
+ apex_available: ["//apex_available:anyapex"],
+ }
+
+ cc_library_shared {
+ name: "libBaz",
+ srcs: ["baz.c"],
+ shared_libs: ["libFoo"],
+ apex_available: ["baz"],
+ }
+
+ cc_library_shared {
+ name: "libQux",
+ srcs: ["qux.c"],
+ shared_libs: ["libFoo"],
+ apex_available: ["qux", "bar"],
+ }`
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: "out/bazel",
+ LabelToCcInfo: map[string]cquery.CcInfo{
+ "//:libFoo": {
+ RootDynamicLibraries: []string{"libFoo.so"},
+ },
+ "//:libFoo_stub_libs-current": {
+ RootDynamicLibraries: []string{"libFoo_stub_libs-current.so"},
+ },
+ },
+ }
+ }),
+ ).RunTestWithBp(t, bp)
+ ctx := result.TestContext
+
+ variants := ctx.ModuleVariantsForTests("libFoo")
+ expectedVariants := []string{
+ "android_arm64_armv8-a_shared",
+ "android_arm64_armv8-a_shared_current",
+ "android_arm_armv7-a-neon_shared",
+ "android_arm_armv7-a-neon_shared_current",
+ }
+ variantsMismatch := false
+ if len(variants) != len(expectedVariants) {
+ variantsMismatch = true
+ } else {
+ for _, v := range expectedVariants {
+ if !inList(v, variants) {
+ variantsMismatch = false
+ }
+ }
+ }
+ if variantsMismatch {
+ t.Errorf("variants of libFoo expected:\n")
+ for _, v := range expectedVariants {
+ t.Errorf("%q\n", v)
+ }
+ t.Errorf(", but got:\n")
+ for _, v := range variants {
+ t.Errorf("%q\n", v)
+ }
+ }
+
+ linkAgainstFoo := []string{"libBarA1"}
+ linkAgainstFooStubs := []string{"libBar", "libA1", "libBaz", "libQux", "libAnyApex"}
+
+ libFooPath := "out/bazel/execroot/__main__/libFoo.so"
+ for _, lib := range linkAgainstFoo {
+ libLinkRule := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld")
+ libFlags := libLinkRule.Args["libFlags"]
+ if !strings.Contains(libFlags, libFooPath) {
+ t.Errorf("%q: %q is not found in %q", lib, libFooPath, libFlags)
+ }
+ }
+
+ libFooStubPath := "out/bazel/execroot/__main__/libFoo_stub_libs-current.so"
+ for _, lib := range linkAgainstFooStubs {
+ libLinkRule := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld")
+ libFlags := libLinkRule.Args["libFlags"]
+ if !strings.Contains(libFlags, libFooStubPath) {
+ t.Errorf("%q: %q is not found in %q", lib, libFooStubPath, libFlags)
+ }
+ }
+}
+
func TestVersioningMacro(t *testing.T) {
t.Parallel()
for _, tc := range []struct{ moduleName, expected string }{
@@ -4993,3 +5227,256 @@
expectedOutputFiles := []string{"outputbase/execroot/__main__/foo.so"}
android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
}
+
+func TestDisableSanitizerVariantsInMixedBuilds(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library_static {
+ name: "foo_ubsan_minimal",
+ srcs: ["foo.cc"],
+ bazel_module: { label: "//foo_ubsan_minimal" },
+ sanitize: {
+ all_undefined: true,
+ integer_overflow: true,
+ },
+ }
+ cc_library_static {
+ name: "foo",
+ srcs: ["foo.cc"],
+ bazel_module: { label: "//foo" },
+ sanitize: {
+ address: true,
+ hwaddress: true,
+ fuzzer: true,
+ integer_overflow: true,
+ scs: true,
+ },
+ }
+ cc_library_static {
+ name: "foo_tsan",
+ srcs: ["foo.cc"],
+ bazel_module: { label: "//foo_tsan" },
+ sanitize: {
+ thread: true,
+ },
+ }
+ cc_library_static {
+ name: "foo_cfi",
+ srcs: ["foo.cc"],
+ bazel_module: { label: "//foo_cfi" },
+ sanitize: {
+ cfi: true,
+ },
+ }
+ cc_library_static {
+ name: "foo_memtag_stack",
+ srcs: ["foo.cc"],
+ bazel_module: { label: "//foo_memtag_stack" },
+ sanitize: {
+ memtag_stack: true,
+ },
+ }
+ cc_library_static {
+ name: "foo_memtag_heap",
+ srcs: ["foo.cc"],
+ bazel_module: { label: "//foo_memtag_heap" },
+ sanitize: {
+ memtag_heap: true,
+ },
+ }
+ cc_library_static {
+ name: "foo_safestack",
+ srcs: ["foo.cc"],
+ bazel_module: { label: "//foo_safestack" },
+ sanitize: {
+ safestack: true,
+ },
+ }
+ cc_library_static {
+ name: "foo_scudo",
+ srcs: ["foo.cc"],
+ bazel_module: { label: "//foo_scudo" },
+ sanitize: {
+ scudo: true,
+ },
+ }
+ `
+ testcases := []struct {
+ name string
+ variant string
+ expectedOutputPaths []string
+ }{
+ {
+ name: "foo_ubsan_minimal",
+ variant: "android_arm64_armv8-a_static_apex28",
+ expectedOutputPaths: []string{
+ "outputbase/execroot/__main__/foo_ubsan_minimal.a",
+ },
+ },
+ {
+ name: "foo",
+ variant: "android_arm64_armv8-a_static_apex28",
+ expectedOutputPaths: []string{
+ "outputbase/execroot/__main__/foo.a",
+ },
+ },
+ {
+ name: "foo",
+ variant: "android_arm_armv7-a-neon_static_asan_apex28",
+ expectedOutputPaths: []string{
+ "out/soong/.intermediates/foo/android_arm_armv7-a-neon_static_asan_apex28/foo.a",
+ },
+ },
+ {
+ name: "foo",
+ variant: "android_arm64_armv8-a_static_hwasan_apex28",
+ expectedOutputPaths: []string{
+ "out/soong/.intermediates/foo/android_arm64_armv8-a_static_hwasan_apex28/foo.a",
+ },
+ },
+ {
+ name: "foo",
+ variant: "android_arm64_armv8-a_static_fuzzer_apex28",
+ expectedOutputPaths: []string{
+ "out/soong/.intermediates/foo/android_arm64_armv8-a_static_fuzzer_apex28/foo.a",
+ },
+ },
+ {
+ name: "foo",
+ variant: "android_arm_armv7-a-neon_static_asan_fuzzer_apex28",
+ expectedOutputPaths: []string{
+ "out/soong/.intermediates/foo/android_arm_armv7-a-neon_static_asan_fuzzer_apex28/foo.a",
+ },
+ },
+ {
+ name: "foo",
+ variant: "android_arm64_armv8-a_static_hwasan_fuzzer_apex28",
+ expectedOutputPaths: []string{
+ "out/soong/.intermediates/foo/android_arm64_armv8-a_static_hwasan_fuzzer_apex28/foo.a",
+ },
+ },
+ {
+ name: "foo",
+ variant: "android_arm64_armv8-a_static_scs_apex28",
+ expectedOutputPaths: []string{
+ "out/soong/.intermediates/foo/android_arm64_armv8-a_static_scs_apex28/foo.a",
+ },
+ },
+ {
+ name: "foo",
+ variant: "android_arm64_armv8-a_static_hwasan_scs_apex28",
+ expectedOutputPaths: []string{
+ "out/soong/.intermediates/foo/android_arm64_armv8-a_static_hwasan_scs_apex28/foo.a",
+ },
+ },
+ {
+ name: "foo",
+ variant: "android_arm64_armv8-a_static_hwasan_scs_fuzzer_apex28",
+ expectedOutputPaths: []string{
+ "out/soong/.intermediates/foo/android_arm64_armv8-a_static_hwasan_scs_fuzzer_apex28/foo.a",
+ },
+ },
+ {
+ name: "foo_tsan",
+ variant: "android_arm64_armv8-a_static_apex28",
+ expectedOutputPaths: []string{
+ "outputbase/execroot/__main__/foo_tsan.a",
+ },
+ },
+ {
+ name: "foo_tsan",
+ variant: "android_arm64_armv8-a_static_tsan_apex28",
+ expectedOutputPaths: []string{
+ "out/soong/.intermediates/foo_tsan/android_arm64_armv8-a_static_tsan_apex28/foo_tsan.a",
+ },
+ },
+ {
+ name: "foo_cfi",
+ variant: "android_arm64_armv8-a_static_apex28",
+ expectedOutputPaths: []string{
+ "outputbase/execroot/__main__/foo_cfi.a",
+ },
+ },
+ {
+ name: "foo_cfi",
+ variant: "android_arm64_armv8-a_static_cfi_apex28",
+ expectedOutputPaths: []string{
+ "out/soong/.intermediates/foo_cfi/android_arm64_armv8-a_static_cfi_apex28/foo_cfi.a",
+ },
+ },
+ {
+ name: "foo_memtag_stack",
+ variant: "android_arm64_armv8-a_static_apex28",
+ expectedOutputPaths: []string{
+ "out/soong/.intermediates/foo_memtag_stack/android_arm64_armv8-a_static_apex28/foo_memtag_stack.a",
+ },
+ },
+ {
+ name: "foo_memtag_heap",
+ variant: "android_arm64_armv8-a_static_apex28",
+ expectedOutputPaths: []string{
+ "out/soong/.intermediates/foo_memtag_heap/android_arm64_armv8-a_static_apex28/foo_memtag_heap.a",
+ },
+ },
+ {
+ name: "foo_safestack",
+ variant: "android_arm64_armv8-a_static_apex28",
+ expectedOutputPaths: []string{
+ "out/soong/.intermediates/foo_safestack/android_arm64_armv8-a_static_apex28/foo_safestack.a",
+ },
+ },
+ {
+ name: "foo_scudo",
+ variant: "android_arm64_armv8-a_static_apex28",
+ expectedOutputPaths: []string{
+ "out/soong/.intermediates/foo_scudo/android_arm64_armv8-a_static_apex28/foo_scudo.a",
+ },
+ },
+ }
+
+ ctx := android.GroupFixturePreparers(
+ prepareForCcTest,
+ prepareForAsanTest,
+ android.FixtureRegisterWithContext(registerTestMutators),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: "outputbase",
+ LabelToCcInfo: map[string]cquery.CcInfo{
+ "//foo_ubsan_minimal": {
+ RootStaticArchives: []string{"foo_ubsan_minimal.a"},
+ },
+ "//foo": {
+ RootStaticArchives: []string{"foo.a"},
+ },
+ "//foo_tsan": {
+ RootStaticArchives: []string{"foo_tsan.a"},
+ },
+ "//foo_cfi": {
+ RootStaticArchives: []string{"foo_cfi.a"},
+ },
+ "//foo_memtag_stack": {
+ RootStaticArchives: []string{"INVALID_ARCHIVE.a"},
+ },
+ "//foo_memtag_heap": {
+ RootStaticArchives: []string{"INVALID_ARCHIVE.a"},
+ },
+ "//foo_safestack": {
+ RootStaticArchives: []string{"INVALID_ARCHIVE.a"},
+ },
+ "//foo_scudo": {
+ RootStaticArchives: []string{"INVALID_ARCHIVE.a"},
+ },
+ },
+ }
+ }),
+ ).RunTestWithBp(t, bp).TestContext
+
+ for _, tc := range testcases {
+ fooMod := ctx.ModuleForTests(tc.name, tc.variant).Module()
+ outputFiles, err := fooMod.(android.OutputFileProducer).OutputFiles("")
+ if err != nil {
+ t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
+ }
+ android.AssertPathsRelativeToTopEquals(t, "output files", tc.expectedOutputPaths, outputFiles)
+ }
+}
diff --git a/cc/check.go b/cc/check.go
index 3d290a9..58ff5b2 100644
--- a/cc/check.go
+++ b/cc/check.go
@@ -57,6 +57,10 @@
} else if strings.HasPrefix("../", path) {
ctx.PropertyErrorf(prop, "Path must not start with `../`: `%s`. Use include_dirs to -include from a different directory", flag)
}
+ } else if args[0] == "-mllvm" {
+ if len(args) > 2 {
+ ctx.PropertyErrorf(prop, "`-mllvm` only takes one argument: `%s`", flag)
+ }
} else if strings.HasPrefix(flag, "-D") && strings.Contains(flag, "=") {
// Do nothing in this case.
// For now, we allow space characters in -DNAME=def form to allow use cases
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 28f3682..ca2e05f 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -53,8 +53,7 @@
"-Wl,-z,separate-code",
}
- arm64Lldflags = append(arm64Ldflags,
- "-Wl,-z,max-page-size=4096")
+ arm64Lldflags = arm64Ldflags
arm64Cppflags = []string{}
@@ -93,7 +92,13 @@
func init() {
exportedVars.ExportStringListStaticVariable("Arm64Ldflags", arm64Ldflags)
- exportedVars.ExportStringListStaticVariable("Arm64Lldflags", arm64Lldflags)
+
+ exportedVars.ExportStringList("Arm64Lldflags", arm64Lldflags)
+ pctx.VariableFunc("Arm64Lldflags", func(ctx android.PackageVarContext) string {
+ maxPageSizeFlag := "-Wl,-z,max-page-size=" + ctx.Config().MaxPageSizeSupported()
+ flags := append(arm64Lldflags, maxPageSizeFlag)
+ return strings.Join(flags, " ")
+ })
exportedVars.ExportStringListStaticVariable("Arm64Cflags", arm64Cflags)
exportedVars.ExportStringListStaticVariable("Arm64Cppflags", arm64Cppflags)
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index 0704550..dec2b45 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -185,7 +185,12 @@
exportedVars.ExportString("ArmClangTriple", clangTriple)
exportedVars.ExportStringListStaticVariable("ArmLdflags", armLdflags)
- exportedVars.ExportStringListStaticVariable("ArmLldflags", armLldflags)
+ exportedVars.ExportStringList("ArmLldflags", armLldflags)
+ pctx.VariableFunc("ArmLldflags", func(ctx android.PackageVarContext) string {
+ maxPageSizeFlag := "-Wl,-z,max-page-size=" + ctx.Config().MaxPageSizeSupported()
+ flags := append(armLldflags, maxPageSizeFlag)
+ return strings.Join(flags, " ")
+ })
exportedVars.ExportStringListStaticVariable("ArmFixCortexA8LdFlags", armFixCortexA8LdFlags)
exportedVars.ExportStringListStaticVariable("ArmNoFixCortexA8LdFlags", armNoFixCortexA8LdFlags)
diff --git a/cc/config/global.go b/cc/config/global.go
index 05dc773..20298dd 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -111,6 +111,9 @@
// Turn off FMA which got enabled by default in clang-r445002 (http://b/218805949)
"-ffp-contract=off",
+
+ // Turn off stack protector check for noreturn calls. (http://b/264965700)
+ "-mllvm -disable-check-noreturn-call",
}
commonGlobalConlyflags = []string{}
@@ -147,6 +150,9 @@
commonGlobalLldflags = []string{
"-fuse-ld=lld",
"-Wl,--icf=safe",
+
+ // Turn off stack protector check for noreturn calls. (http://b/264965700)
+ "-Wl,-mllvm,-disable-check-noreturn-call",
}
deviceGlobalCppflags = []string{
@@ -193,6 +199,7 @@
noOverrideGlobalCflags = []string{
"-Werror=bool-operation",
+ "-Werror=format-insufficient-args",
"-Werror=implicit-int-float-conversion",
"-Werror=int-in-bool-context",
"-Werror=int-to-pointer-cast",
@@ -233,26 +240,28 @@
// New warnings to be fixed after clang-r433403
"-Wno-error=unused-but-set-variable", // http://b/197240255
"-Wno-error=unused-but-set-parameter", // http://b/197240255
- // New warnings to be fixed after clang-r458507
- "-Wno-error=unqualified-std-cast-call", // http://b/239662094
// New warnings to be fixed after clang-r468909
"-Wno-error=deprecated-builtins", // http://b/241601211
"-Wno-error=deprecated", // in external/googletest/googletest
// New warnings to be fixed after clang-r475365
"-Wno-error=single-bit-bitfield-constant-conversion", // http://b/243965903
- "-Wno-error=incompatible-function-pointer-types", // http://b/257101299
"-Wno-error=enum-constexpr-conversion", // http://b/243964282
}
noOverride64GlobalCflags = []string{}
noOverrideExternalGlobalCflags = []string{
+ // http://b/191699019
+ "-Wno-format-insufficient-args",
"-Wno-sizeof-array-div",
+ "-Wno-incompatible-function-pointer-types",
"-Wno-unused-but-set-variable",
"-Wno-unused-but-set-parameter",
+ "-Wno-unqualified-std-cast-call",
"-Wno-bitwise-instead-of-logical",
"-Wno-misleading-indentation",
"-Wno-array-parameter",
+ "-Wno-gnu-offsetof-extensions",
}
// Extra cflags for external third-party projects to disable warnings that
@@ -284,9 +293,6 @@
// http://b/239661264
"-Wno-deprecated-non-prototype",
-
- // http://b/191699019
- "-Wno-format-insufficient-args",
}
llvmNextExtraCommonGlobalCflags = []string{
@@ -305,14 +311,19 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r475365b"
- ClangDefaultShortVersion = "16.0.2"
+ ClangDefaultVersion = "clang-r487747b"
+ ClangDefaultShortVersion = "17"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
"device/",
"vendor/",
}
+
+ VersionScriptFlagPrefix = "-Wl,--version-script,"
+
+ VisibilityHiddenFlag = "-fvisibility=hidden"
+ VisibilityDefaultFlag = "-fvisibility=default"
)
// BazelCcToolchainVars generates bzl file content containing variables for
@@ -401,6 +412,11 @@
exportedVars.ExportString("ExperimentalCStdVersion", ExperimentalCStdVersion)
exportedVars.ExportString("ExperimentalCppStdVersion", ExperimentalCppStdVersion)
+ exportedVars.ExportString("VersionScriptFlagPrefix", VersionScriptFlagPrefix)
+
+ exportedVars.ExportString("VisibilityHiddenFlag", VisibilityHiddenFlag)
+ exportedVars.ExportString("VisibilityDefaultFlag", VisibilityDefaultFlag)
+
// Everything in these lists is a crime against abstraction and dependency tracking.
// Do not add anything to this list.
commonGlobalIncludes := []string{
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
index b3619c8..a63d5c2 100644
--- a/cc/config/riscv64_device.go
+++ b/cc/config/riscv64_device.go
@@ -26,6 +26,9 @@
// Help catch common 32/64-bit errors.
"-Werror=implicit-function-declaration",
"-fno-emulated-tls",
+ // A temporary fix for SExtWRemoval miscompilation bug.
+ "-mllvm",
+ "-riscv-disable-sextw-removal=true",
}
riscv64ArchVariantCflags = map[string][]string{}
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index 052832d..6a10e14 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -212,6 +212,14 @@
return LibclangRuntimeLibrary(t, "asan")
}
+func AddressSanitizerStaticRuntimeLibrary(t Toolchain) string {
+ return LibclangRuntimeLibrary(t, "asan.static")
+}
+
+func AddressSanitizerCXXStaticRuntimeLibrary(t Toolchain) string {
+ return LibclangRuntimeLibrary(t, "asan_cxx.static")
+}
+
func HWAddressSanitizerRuntimeLibrary(t Toolchain) string {
return LibclangRuntimeLibrary(t, "hwasan")
}
diff --git a/cc/coverage.go b/cc/coverage.go
index a7356f8..c0f6973 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -219,10 +219,14 @@
return properties
}
-// Coverage is an interface for non-CC modules to implement to be mutated for coverage
-type Coverage interface {
+type UseCoverage interface {
android.Module
IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool
+}
+
+// Coverage is an interface for non-CC modules to implement to be mutated for coverage
+type Coverage interface {
+ UseCoverage
SetPreventInstall()
HideFromMake()
MarkAsCoverageVariant(bool)
@@ -261,6 +265,11 @@
m[1].(Coverage).MarkAsCoverageVariant(true)
m[1].(Coverage).EnableCoverageIfNeeded()
+ } else if cov, ok := mctx.Module().(UseCoverage); ok && cov.IsNativeCoverageNeeded(mctx) {
+ // Module itself doesn't have to have "cov" variant, but it should use "cov" variants of
+ // deps.
+ mctx.CreateVariations("cov")
+ mctx.AliasVariation("cov")
}
}
diff --git a/cc/fdo_profile.go b/cc/fdo_profile.go
new file mode 100644
index 0000000..7fbe719
--- /dev/null
+++ b/cc/fdo_profile.go
@@ -0,0 +1,85 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cc
+
+import (
+ "android/soong/android"
+
+ "github.com/google/blueprint"
+)
+
+func init() {
+ RegisterFdoProfileBuildComponents(android.InitRegistrationContext)
+}
+
+func RegisterFdoProfileBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("fdo_profile", fdoProfileFactory)
+}
+
+type fdoProfile struct {
+ android.ModuleBase
+
+ properties fdoProfileProperties
+}
+
+type fdoProfileProperties struct {
+ Profile *string `android:"arch_variant"`
+}
+
+// FdoProfileInfo is provided by FdoProfileProvider
+type FdoProfileInfo struct {
+ Path android.Path
+}
+
+// FdoProfileProvider is used to provide path to an fdo profile
+var FdoProfileProvider = blueprint.NewMutatorProvider(FdoProfileInfo{}, "fdo_profile")
+
+// FdoProfileMutatorInterface is the interface implemented by fdo_profile module type
+// module types that can depend on an fdo_profile module
+type FdoProfileMutatorInterface interface {
+ // FdoProfileMutator eithers set or get FdoProfileProvider
+ fdoProfileMutator(ctx android.BottomUpMutatorContext)
+}
+
+var _ FdoProfileMutatorInterface = (*fdoProfile)(nil)
+
+// GenerateAndroidBuildActions of fdo_profile does not have any build actions
+func (fp *fdoProfile) GenerateAndroidBuildActions(ctx android.ModuleContext) {}
+
+// FdoProfileMutator sets FdoProfileProvider to fdo_profile module
+// or sets afdo.Properties.FdoProfilePath to path in FdoProfileProvider of the depended fdo_profile
+func (fp *fdoProfile) fdoProfileMutator(ctx android.BottomUpMutatorContext) {
+ if fp.properties.Profile != nil {
+ path := android.PathForModuleSrc(ctx, *fp.properties.Profile)
+ ctx.SetProvider(FdoProfileProvider, FdoProfileInfo{
+ Path: path,
+ })
+ }
+}
+
+// fdoProfileMutator calls the generic fdoProfileMutator function of fdoProfileMutator
+// which is implemented by cc and cc.FdoProfile
+func fdoProfileMutator(ctx android.BottomUpMutatorContext) {
+ if f, ok := ctx.Module().(FdoProfileMutatorInterface); ok {
+ f.fdoProfileMutator(ctx)
+ }
+}
+
+func fdoProfileFactory() android.Module {
+ m := &fdoProfile{}
+ m.AddProperties(&m.properties)
+ android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibBoth)
+ return m
+}
diff --git a/cc/installer.go b/cc/installer.go
index e2c0e7b..716a0df 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -100,6 +100,10 @@
installer.path = ctx.InstallFile(installer.installDir(ctx), file.Base(), file)
}
+func (installer *baseInstaller) installExecutable(ctx ModuleContext, file android.Path) {
+ installer.path = ctx.InstallExecutable(installer.installDir(ctx), file.Base(), file)
+}
+
func (installer *baseInstaller) everInstallable() bool {
// Most cc modules are installable.
return true
diff --git a/cc/library.go b/cc/library.go
index e73af81..13b333a 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -26,7 +26,6 @@
"android/soong/android"
"android/soong/bazel"
"android/soong/bazel/cquery"
- "android/soong/cc/config"
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
@@ -264,11 +263,15 @@
type aidlLibraryAttributes struct {
Srcs bazel.LabelListAttribute
Include_dir *string
+ Tags bazel.StringListAttribute
}
type ccAidlLibraryAttributes struct {
Deps bazel.LabelListAttribute
+ Implementation_deps bazel.LabelListAttribute
Implementation_dynamic_deps bazel.LabelListAttribute
+ Tags bazel.StringListAttribute
+ sdkAttributes
}
type stripAttributes struct {
@@ -308,6 +311,11 @@
asFlags = bazel.MakeStringListAttribute(nil)
}
+ sharedFeatures := baseAttributes.features.Clone().Append(sharedAttrs.Features)
+ sharedFeatures.DeduplicateAxesFromBase()
+ staticFeatures := baseAttributes.features.Clone().Append(staticAttrs.Features)
+ staticFeatures.DeduplicateAxesFromBase()
+
staticCommonAttrs := staticOrSharedAttributes{
Srcs: *srcs.Clone().Append(staticAttrs.Srcs),
Srcs_c: *compilerAttrs.cSrcs.Clone().Append(staticAttrs.Srcs_c),
@@ -363,7 +371,7 @@
Cpp_std: compilerAttrs.cppStd,
C_std: compilerAttrs.cStd,
- Features: baseAttributes.features,
+ Features: *staticFeatures,
}
sharedTargetAttrs := &bazelCcLibrarySharedAttributes{
@@ -387,7 +395,7 @@
Additional_linker_inputs: linkerAttrs.additionalLinkerInputs,
Strip: stripAttrsFromLinkerAttrs(&linkerAttrs),
- Features: baseAttributes.features,
+ Features: *sharedFeatures,
bazelCcHeaderAbiCheckerAttributes: bp2buildParseAbiCheckerProps(ctx, m),
Fdo_profile: compilerAttrs.fdoProfile,
@@ -425,10 +433,12 @@
var tagsForStaticVariant bazel.StringListAttribute
if compilerAttrs.stubsSymbolFile == nil && len(compilerAttrs.stubsVersions.Value) == 0 {
- tagsForStaticVariant = android.ApexAvailableTags(m)
+ tagsForStaticVariant = android.ApexAvailableTagsWithoutTestApexes(ctx, m)
}
+ tagsForStaticVariant.Append(bazel.StringListAttribute{Value: staticAttrs.Apex_available})
- tagsForSharedVariant := android.ApexAvailableTags(m)
+ tagsForSharedVariant := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
+ tagsForSharedVariant.Append(bazel.StringListAttribute{Value: sharedAttrs.Apex_available})
ctx.CreateBazelTargetModuleWithRestrictions(staticProps,
android.CommonAttributes{
@@ -454,16 +464,31 @@
}
soname := m.Name() + ".so"
stubSuitesAttrs := &bazelCcStubSuiteAttributes{
- Symbol_file: compilerAttrs.stubsSymbolFile,
- Versions: compilerAttrs.stubsVersions,
- Export_includes: exportedIncludes.Includes,
- Soname: &soname,
- Source_library: *bazel.MakeLabelAttribute(":" + m.Name()),
- Deps: baseAttributes.deps,
+ Symbol_file: compilerAttrs.stubsSymbolFile,
+ Versions: compilerAttrs.stubsVersions,
+ Export_includes: exportedIncludes.Includes,
+ Soname: &soname,
+ Source_library_label: proptools.StringPtr(m.GetBazelLabel(ctx, m)),
+ Deps: baseAttributes.deps,
}
ctx.CreateBazelTargetModule(stubSuitesProps,
android.CommonAttributes{Name: m.Name() + "_stub_libs"},
stubSuitesAttrs)
+
+ // Add alias for the stub shared_library in @api_surfaces repository
+ currentModuleLibApiDir := ctx.Config().ApiSurfacesDir(android.ModuleLibApi, "current")
+ actualLabelInMainWorkspace := bazel.Label{
+ Label: fmt.Sprintf("@//%s:%s%s", ctx.ModuleDir(), m.Name(), stubsSuffix),
+ }
+ ctx.CreateBazelTargetAliasInDir(currentModuleLibApiDir, m.Name(), actualLabelInMainWorkspace)
+
+ // Add alias for headers exported by the stub library
+ headerLabelInMainWorkspace := bazel.Label{
+ // This label is generated from cc_stub_suite macro
+ Label: fmt.Sprintf("@//%s:%s_stub_libs_%s_headers", ctx.ModuleDir(), m.Name(), android.ModuleLibApi.String()),
+ }
+ headerAlias := m.Name() + "_headers"
+ ctx.CreateBazelTargetAliasInDir(currentModuleLibApiDir, headerAlias, headerLabelInMainWorkspace)
}
}
@@ -911,9 +936,17 @@
func (handler *ccLibraryBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
bazelCtx := ctx.Config().BazelContext
bazelCtx.QueueBazelRequest(label, cquery.GetCcInfo, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx)))
+ if v := handler.module.library.stubsVersion(); v != "" {
+ stubsLabel := label + "_stub_libs-" + v
+ bazelCtx.QueueBazelRequest(stubsLabel, cquery.GetCcInfo, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx)))
+ }
}
func (handler *ccLibraryBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
+ if v := handler.module.library.stubsVersion(); v != "" {
+ // if we are a stubs variant, just use the Bazel stubs target
+ label = label + "_stub_libs-" + v
+ }
bazelCtx := ctx.Config().BazelContext
ccInfo, err := bazelCtx.GetCcInfo(label, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx)))
if err != nil {
@@ -942,6 +975,9 @@
}
handler.module.setAndroidMkVariablesFromCquery(ccInfo.CcAndroidMkInfo)
+
+ cctx := moduleContextFromAndroidModuleContext(ctx, handler.module)
+ addStubDependencyProviders(cctx)
}
func (library *libraryDecorator) setFlagExporterInfoFromCcInfo(ctx android.ModuleContext, ccInfo cquery.CcInfo) {
@@ -1767,6 +1803,12 @@
Target: ctx.Target(),
})
+ addStubDependencyProviders(ctx)
+
+ return unstrippedOutputFile
+}
+
+func addStubDependencyProviders(ctx ModuleContext) {
stubs := ctx.GetDirectDepsWithTag(stubImplDepTag)
if len(stubs) > 0 {
var stubsInfo []SharedStubLibrary
@@ -1781,12 +1823,9 @@
}
ctx.SetProvider(SharedLibraryStubsProvider, SharedLibraryStubsInfo{
SharedStubLibraries: stubsInfo,
-
- IsLLNDK: ctx.IsLlndk(),
+ IsLLNDK: ctx.IsLlndk(),
})
}
-
- return unstrippedOutputFile
}
func (library *libraryDecorator) unstrippedOutputFilePath() android.Path {
@@ -2173,7 +2212,16 @@
func (library *libraryDecorator) installSymlinkToRuntimeApex(ctx ModuleContext, file android.Path) {
dir := library.baseInstaller.installDir(ctx)
dirOnDevice := android.InstallPathToOnDevicePath(ctx, dir)
- target := "/" + filepath.Join("apex", "com.android.runtime", dir.Base(), "bionic", file.Base())
+ // libc_hwasan has relative_install_dir set, which would mess up the dir.Base() logic.
+ // hardcode here because it's the only target, if we have other targets that use this
+ // we can generalise this.
+ var target string
+ if ctx.baseModuleName() == "libc_hwasan" {
+ target = "/" + filepath.Join("apex", "com.android.runtime", "lib64", "bionic", "hwasan", file.Base())
+ } else {
+ base := dir.Base()
+ target = "/" + filepath.Join("apex", "com.android.runtime", base, "bionic", file.Base())
+ }
ctx.InstallAbsoluteSymlink(dir, file.Base(), target)
library.postInstallCmds = append(library.postInstallCmds, makeSymlinkCmd(dirOnDevice, file.Base(), target))
}
@@ -2240,8 +2288,7 @@
!ctx.useVndk() && !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() && ctx.Device() &&
library.baseLinker.sanitize.isUnsanitizedVariant() &&
ctx.isForPlatform() && !ctx.isPreventInstall() {
- installPath := getNdkSysrootBase(ctx).Join(
- ctx, "usr/lib", config.NDKTriple(ctx.toolchain()), file.Base())
+ installPath := getUnversionedLibraryInstallPath(ctx).Join(ctx, file.Base())
ctx.ModuleBuild(pctx, android.ModuleBuildParams{
Rule: android.Cp,
@@ -2364,7 +2411,10 @@
}
// Future API level is implicitly added if there isn't
- vers := library.Properties.Stubs.Versions
+ return addCurrentVersionIfNotPresent(library.Properties.Stubs.Versions)
+}
+
+func addCurrentVersionIfNotPresent(vers []string) []string {
if inList(android.FutureApiLevel.String(), vers) {
return vers
}
@@ -2629,7 +2679,7 @@
// normalizeVersions modifies `versions` in place, so that each raw version
// string becomes its normalized canonical form.
// Validates that the versions in `versions` are specified in least to greatest order.
-func normalizeVersions(ctx android.BaseModuleContext, versions []string) {
+func normalizeVersions(ctx android.BazelConversionPathContext, versions []string) {
var previous android.ApiLevel
for i, v := range versions {
ver, err := android.ApiLevelFromUser(ctx, v)
@@ -2853,6 +2903,9 @@
asFlags = bazel.MakeStringListAttribute(nil)
}
+ features := baseAttributes.features.Clone().Append(libSharedOrStaticAttrs.Features)
+ features.DeduplicateAxesFromBase()
+
commonAttrs := staticOrSharedAttributes{
Srcs: compilerAttrs.srcs,
Srcs_c: compilerAttrs.cSrcs,
@@ -2894,7 +2947,7 @@
Conlyflags: compilerAttrs.conlyFlags,
Asflags: asFlags,
- Features: baseAttributes.features,
+ Features: *features,
}
} else {
commonAttrs.Dynamic_deps.Add(baseAttributes.protoDependency)
@@ -2923,7 +2976,7 @@
Strip: stripAttrsFromLinkerAttrs(&linkerAttrs),
- Features: baseAttributes.features,
+ Features: *features,
Suffix: compilerAttrs.suffix,
@@ -2949,7 +3002,7 @@
Bzl_load_location: fmt.Sprintf("//build/bazel/rules/cc:%s.bzl", modType),
}
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name(), Tags: tags}, attrs)
}
@@ -3018,12 +3071,12 @@
}
type bazelCcStubSuiteAttributes struct {
- Symbol_file *string
- Versions bazel.StringListAttribute
- Export_includes bazel.StringListAttribute
- Source_library bazel.LabelAttribute
- Soname *string
- Deps bazel.LabelListAttribute
+ Symbol_file *string
+ Versions bazel.StringListAttribute
+ Export_includes bazel.StringListAttribute
+ Source_library_label *string
+ Soname *string
+ Deps bazel.LabelListAttribute
}
type bazelCcHeaderAbiCheckerAttributes struct {
diff --git a/cc/library_headers.go b/cc/library_headers.go
index 1dee726..ce9c4aa 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -151,7 +151,7 @@
Bzl_load_location: "//build/bazel/rules/cc:cc_library_headers.bzl",
}
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModule(props, android.CommonAttributes{
Name: module.Name(),
diff --git a/cc/linker.go b/cc/linker.go
index e49b97d..257fe86 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -15,11 +15,12 @@
package cc
import (
- "android/soong/android"
- "android/soong/cc/config"
"fmt"
"path/filepath"
+ "android/soong/android"
+ "android/soong/cc/config"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -542,13 +543,13 @@
ctx.PropertyErrorf("version_script", "Not supported on Darwin")
} else {
flags.Local.LdFlags = append(flags.Local.LdFlags,
- "-Wl,--version-script,"+versionScript.String())
+ config.VersionScriptFlagPrefix+versionScript.String())
flags.LdFlagsDeps = append(flags.LdFlagsDeps, versionScript.Path())
if linker.sanitize.isSanitizerEnabled(cfi) {
- cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath)
+ cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath+"/"+cfiExportsMapFilename)
flags.Local.LdFlags = append(flags.Local.LdFlags,
- "-Wl,--version-script,"+cfiExportsMap.String())
+ config.VersionScriptFlagPrefix+cfiExportsMap.String())
flags.LdFlagsDeps = append(flags.LdFlagsDeps, cfiExportsMap)
}
}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 2473ba2..f8a3559 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -342,7 +342,14 @@
if android.InList("hwaddress", config.SanitizeDevice()) {
return false
}
- return true
+ // http://b/156513478
+ // http://b/277624006
+ // This step is expensive. We're not able to do anything with the outputs of
+ // this step yet (canDiffAbi is flagged off because libabigail isn't able to
+ // handle all our libraries), disable it. There's no sense in protecting
+ // against checking in code that breaks abidw since by the time any of this
+ // can be turned on we'll need to migrate to STG anyway.
+ return false
}
// Feature flag to disable diffing against prebuilts.
@@ -528,17 +535,20 @@
return false
}
-func (stub *stubDecorator) install(ctx ModuleContext, path android.Path) {
- arch := ctx.Target().Arch.ArchType.Name
- // arm64 isn't actually a multilib toolchain, so unlike the other LP64
- // architectures it's just installed to lib.
- libDir := "lib"
- if ctx.toolchain().Is64Bit() && arch != "arm64" {
- libDir = "lib64"
- }
+// Returns the install path for unversioned NDK libraries (currently only static
+// libraries).
+func getUnversionedLibraryInstallPath(ctx ModuleContext) android.InstallPath {
+ return getNdkSysrootBase(ctx).Join(ctx, "usr/lib", config.NDKTriple(ctx.toolchain()))
+}
- installDir := getNdkInstallBase(ctx).Join(ctx, fmt.Sprintf(
- "platforms/android-%s/arch-%s/usr/%s", stub.apiLevel, arch, libDir))
+// Returns the install path for versioned NDK libraries. These are most often
+// stubs, but the same paths are used for CRT objects.
+func getVersionedLibraryInstallPath(ctx ModuleContext, apiLevel android.ApiLevel) android.InstallPath {
+ return getUnversionedLibraryInstallPath(ctx).Join(ctx, apiLevel.String())
+}
+
+func (stub *stubDecorator) install(ctx ModuleContext, path android.Path) {
+ installDir := getVersionedLibraryInstallPath(ctx, stub.apiLevel)
stub.installPath = ctx.InstallFile(installDir, path.Base(), path)
}
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index 51ec6b8..1d15cf8 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -15,15 +15,12 @@
package cc
import (
- "fmt"
"strings"
"android/soong/android"
- "android/soong/cc/config"
)
func init() {
- android.RegisterModuleType("ndk_prebuilt_object", NdkPrebuiltObjectFactory)
android.RegisterModuleType("ndk_prebuilt_static_stl", NdkPrebuiltStaticStlFactory)
android.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory)
}
@@ -34,68 +31,6 @@
// either (with the exception of the shared STLs, which are installed to the app's directory rather
// than to the system image).
-func getNdkLibDir(ctx android.ModuleContext, toolchain config.Toolchain, version string) android.SourcePath {
- suffix := ""
- // Most 64-bit NDK prebuilts store libraries in "lib64", except for arm64 which is not a
- // multilib toolchain and stores the libraries in "lib".
- if toolchain.Is64Bit() && ctx.Arch().ArchType != android.Arm64 {
- suffix = "64"
- }
- return android.PathForSource(ctx, fmt.Sprintf("prebuilts/ndk/current/platforms/android-%s/arch-%s/usr/lib%s",
- version, toolchain.Name(), suffix))
-}
-
-func ndkPrebuiltModuleToPath(ctx android.ModuleContext, toolchain config.Toolchain,
- ext string, version string) android.Path {
-
- // NDK prebuilts are named like: ndk_NAME.EXT.SDK_VERSION.
- // We want to translate to just NAME.EXT
- name := strings.Split(strings.TrimPrefix(ctx.ModuleName(), "ndk_"), ".")[0]
- dir := getNdkLibDir(ctx, toolchain, version)
- return dir.Join(ctx, name+ext)
-}
-
-type ndkPrebuiltObjectLinker struct {
- objectLinker
-}
-
-func (*ndkPrebuiltObjectLinker) linkerDeps(ctx DepsContext, deps Deps) Deps {
- // NDK objects can't have any dependencies
- return deps
-}
-
-// ndk_prebuilt_object exports a precompiled ndk object file for linking
-// operations. Soong's module name format is ndk_<NAME>.o.<sdk_version> where
-// the object is located under
-// ./prebuilts/ndk/current/platforms/android-<sdk_version>/arch-$(HOST_ARCH)/usr/lib/<NAME>.o.
-func NdkPrebuiltObjectFactory() android.Module {
- module := newBaseModule(android.DeviceSupported, android.MultilibBoth)
- module.linker = &ndkPrebuiltObjectLinker{
- objectLinker: objectLinker{
- baseLinker: NewBaseLinker(nil),
- },
- }
- module.Properties.AlwaysSdk = true
- module.Properties.Sdk_version = StringPtr("current")
- module.Properties.HideFromMake = true
- return module.Init()
-}
-
-func (c *ndkPrebuiltObjectLinker) link(ctx ModuleContext, flags Flags,
- deps PathDeps, objs Objects) android.Path {
- // A null build step, but it sets up the output path.
- if !strings.HasPrefix(ctx.ModuleName(), "ndk_crt") {
- ctx.ModuleErrorf("NDK prebuilt objects must have an ndk_crt prefixed name")
- }
-
- return ndkPrebuiltModuleToPath(ctx, flags.Toolchain, objectExtension, ctx.sdkVersion())
-}
-
-func (*ndkPrebuiltObjectLinker) availableFor(what string) bool {
- // ndk prebuilt objects are available to everywhere
- return true
-}
-
type ndkPrebuiltStlLinker struct {
*libraryDecorator
}
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 622558e..dffc6c6 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -142,6 +142,13 @@
staticLibInstallPaths, library.ndkSysrootPath)
}
}
+
+ if object, ok := m.linker.(*objectLinker); ok {
+ if object.ndkSysrootPath != nil {
+ staticLibInstallPaths = append(
+ staticLibInstallPaths, object.ndkSysrootPath)
+ }
+ }
}
})
diff --git a/cc/object.go b/cc/object.go
index ef44467..5d61872 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -44,6 +44,10 @@
type objectLinker struct {
*baseLinker
Properties ObjectLinkerProperties
+
+ // Location of the object in the sysroot. Empty if the object is not
+ // included in the NDK.
+ ndkSysrootPath android.Path
}
type objectBazelHandler struct {
@@ -99,6 +103,10 @@
// Indicates that this module is a CRT object. CRT objects will be split
// into a variant per-API level between min_sdk_version and current.
Crt *bool
+
+ // Indicates that this module should not be included in the NDK sysroot.
+ // Only applies to CRT objects. Defaults to false.
+ Exclude_from_ndk_sysroot *bool
}
func newObject(hod android.HostOrDeviceSupported) *Module {
@@ -218,7 +226,7 @@
Bzl_load_location: "//build/bazel/rules/cc:cc_object.bzl",
}
- tags := android.ApexAvailableTags(m)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
ctx.CreateBazelTargetModule(props, android.CommonAttributes{
Name: m.Name(),
@@ -268,17 +276,28 @@
objs = objs.Append(deps.Objs)
- var outputFile android.Path
+ var output android.WritablePath
builderFlags := flagsToBuilderFlags(flags)
outputName := ctx.ModuleName()
if !strings.HasSuffix(outputName, objectExtension) {
outputName += objectExtension
}
- if len(objs.objFiles) == 1 && String(object.Properties.Linker_script) == "" {
- output := android.PathForModuleOut(ctx, outputName)
- outputFile = output
+ // isForPlatform is terribly named and actually means isNotApex.
+ if Bool(object.Properties.Crt) &&
+ !Bool(object.Properties.Exclude_from_ndk_sysroot) && ctx.useSdk() &&
+ ctx.isSdkVariant() && ctx.isForPlatform() {
+ output = getVersionedLibraryInstallPath(ctx,
+ nativeApiLevelOrPanic(ctx, ctx.sdkVersion())).Join(ctx, outputName)
+ object.ndkSysrootPath = output
+ } else {
+ output = android.PathForModuleOut(ctx, outputName)
+ }
+
+ outputFile := output
+
+ if len(objs.objFiles) == 1 && String(object.Properties.Linker_script) == "" {
if String(object.Properties.Prefix_symbols) != "" {
transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), objs.objFiles[0],
builderFlags, output)
@@ -290,9 +309,6 @@
})
}
} else {
- output := android.PathForModuleOut(ctx, outputName)
- outputFile = output
-
if String(object.Properties.Prefix_symbols) != "" {
input := android.PathForModuleOut(ctx, "unprefixed", outputName)
transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), input,
diff --git a/cc/object_test.go b/cc/object_test.go
index 5359a35..b1e2a0f 100644
--- a/cc/object_test.go
+++ b/cc/object_test.go
@@ -65,7 +65,7 @@
variant := "android_arm64_armv8-a_sdk"
crt := ctx.ModuleForTests("bin", variant).Rule("ld").Args["crtBegin"]
android.AssertStringDoesContain(t, "crt dep of sdk variant", crt,
- variant+"_29/crtbegin_dynamic.o")
+ "29/crtbegin_dynamic.o")
// platform variant uses the crt object built for platform
variant = "android_arm64_armv8-a"
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index bb517ea..44cd0d7 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -16,7 +16,6 @@
import (
"path/filepath"
- "strings"
"android/soong/android"
"android/soong/bazel"
@@ -208,12 +207,13 @@
})
// TODO(b/220898484): Mainline module sdk prebuilts of stub libraries use a stub
- // library as their source and must not be installed, but libclang_rt.* libraries
- // have stubs because they are LLNDK libraries, but use an implementation library
- // as their source and need to be installed. This discrepancy should be resolved
- // without the prefix hack below.
- if p.hasStubsVariants() && !p.buildStubs() && !ctx.Host() &&
- !strings.HasPrefix(ctx.baseModuleName(), "libclang_rt.") {
+ // library as their source and must not be installed, but other prebuilts like
+ // libclang_rt.* libraries set `stubs` property because they are LLNDK libraries,
+ // but use an implementation library as their source and need to be installed.
+ // This discrepancy should be resolved without the prefix hack below.
+ isModuleSdkPrebuilts := android.HasAnyPrefix(ctx.ModuleDir(), []string{
+ "prebuilts/runtime/mainline/", "prebuilts/module_sdk/"})
+ if p.hasStubsVariants() && !p.buildStubs() && !ctx.Host() && isModuleSdkPrebuilts {
ctx.Module().MakeUninstallable()
}
@@ -352,6 +352,7 @@
Static_library bazel.LabelAttribute
Export_includes bazel.StringListAttribute
Export_system_includes bazel.StringListAttribute
+ Alwayslink bazel.BoolAttribute
}
// TODO(b/228623543): The below is not entirely true until the bug is fixed. For now, both targets are always generated
@@ -375,6 +376,7 @@
Static_library: prebuiltAttrs.Src,
Export_includes: exportedIncludes.Includes,
Export_system_includes: exportedIncludes.SystemIncludes,
+ // TODO: ¿Alwayslink?
}
props := bazel.BazelTargetModuleProperties{
@@ -387,19 +389,29 @@
name += "_bp2build_cc_library_static"
}
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModuleWithRestrictions(props, android.CommonAttributes{Name: name, Tags: tags}, attrs, prebuiltAttrs.Enabled)
+
+ _true := true
+ alwayslinkAttrs := *attrs
+ alwayslinkAttrs.Alwayslink.SetValue(&_true)
+ ctx.CreateBazelTargetModuleWithRestrictions(props, android.CommonAttributes{Name: name + "_alwayslink", Tags: tags}, &alwayslinkAttrs, prebuiltAttrs.Enabled)
}
type bazelPrebuiltLibrarySharedAttributes struct {
- Shared_library bazel.LabelAttribute
+ Shared_library bazel.LabelAttribute
+ Export_includes bazel.StringListAttribute
+ Export_system_includes bazel.StringListAttribute
}
func prebuiltLibrarySharedBp2Build(ctx android.TopDownMutatorContext, module *Module) {
prebuiltAttrs := Bp2BuildParsePrebuiltLibraryProps(ctx, module, false)
+ exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, nil)
attrs := &bazelPrebuiltLibrarySharedAttributes{
- Shared_library: prebuiltAttrs.Src,
+ Shared_library: prebuiltAttrs.Src,
+ Export_includes: exportedIncludes.Includes,
+ Export_system_includes: exportedIncludes.SystemIncludes,
}
props := bazel.BazelTargetModuleProperties{
@@ -408,7 +420,7 @@
}
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModuleWithRestrictions(props, android.CommonAttributes{Name: name, Tags: tags}, attrs, prebuiltAttrs.Enabled)
}
@@ -638,7 +650,7 @@
}
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name, Tags: tags}, attrs)
}
@@ -801,7 +813,7 @@
}
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name, Tags: tags}, attrs)
}
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index e3ec9d5..0c79e55 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -670,11 +670,15 @@
}
func TestPrebuiltStubNoinstall(t *testing.T) {
- testFunc := func(t *testing.T, bp string) {
+ testFunc := func(t *testing.T, expectLibfooOnSystemLib bool, fs android.MockFS) {
result := android.GroupFixturePreparers(
prepareForPrebuiltTest,
android.PrepareForTestWithMakevars,
- ).RunTestWithBp(t, bp)
+ android.FixtureMergeMockFs(fs),
+ ).RunTest(t)
+
+ ldRule := result.ModuleForTests("installedlib", "android_arm64_armv8-a_shared").Rule("ld")
+ android.AssertStringDoesContain(t, "", ldRule.Args["libFlags"], "android_arm64_armv8-a_shared/libfoo.so")
installRules := result.InstallMakeRulesForTesting(t)
var installedlibRule *android.InstallMakeRule
@@ -691,50 +695,83 @@
return
}
- android.AssertStringListDoesNotContain(t,
- "installedlib has install dependency on stub",
- installedlibRule.Deps,
- "out/target/product/test_device/system/lib/stublib.so")
- android.AssertStringListDoesNotContain(t,
- "installedlib has order-only install dependency on stub",
- installedlibRule.OrderOnlyDeps,
- "out/target/product/test_device/system/lib/stublib.so")
+ if expectLibfooOnSystemLib {
+ android.AssertStringListContains(t,
+ "installedlib doesn't have install dependency on libfoo impl",
+ installedlibRule.OrderOnlyDeps,
+ "out/target/product/test_device/system/lib/libfoo.so")
+ } else {
+ android.AssertStringListDoesNotContain(t,
+ "installedlib has install dependency on libfoo stub",
+ installedlibRule.Deps,
+ "out/target/product/test_device/system/lib/libfoo.so")
+ android.AssertStringListDoesNotContain(t,
+ "installedlib has order-only install dependency on libfoo stub",
+ installedlibRule.OrderOnlyDeps,
+ "out/target/product/test_device/system/lib/libfoo.so")
+ }
}
- const prebuiltStublibBp = `
+ prebuiltLibfooBp := []byte(`
cc_prebuilt_library {
- name: "stublib",
+ name: "libfoo",
prefer: true,
- srcs: ["foo.so"],
+ srcs: ["libfoo.so"],
stubs: {
versions: ["1"],
},
}
- `
+ `)
- const installedlibBp = `
+ installedlibBp := []byte(`
cc_library {
name: "installedlib",
- shared_libs: ["stublib"],
+ shared_libs: ["libfoo"],
}
- `
+ `)
- t.Run("prebuilt without source", func(t *testing.T) {
- testFunc(t, prebuiltStublibBp+installedlibBp)
+ t.Run("prebuilt stub (without source): no install", func(t *testing.T) {
+ testFunc(
+ t,
+ /*expectLibfooOnSystemLib=*/ false,
+ android.MockFS{
+ "prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
+ "Android.bp": installedlibBp,
+ },
+ )
})
- const disabledSourceStublibBp = `
+ disabledSourceLibfooBp := []byte(`
cc_library {
- name: "stublib",
+ name: "libfoo",
enabled: false,
stubs: {
versions: ["1"],
},
}
- `
+ `)
- t.Run("prebuilt with disabled source", func(t *testing.T) {
- testFunc(t, disabledSourceStublibBp+prebuiltStublibBp+installedlibBp)
+ t.Run("prebuilt stub (with disabled source): no install", func(t *testing.T) {
+ testFunc(
+ t,
+ /*expectLibfooOnSystemLib=*/ false,
+ android.MockFS{
+ "prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
+ "impl/Android.bp": disabledSourceLibfooBp,
+ "Android.bp": installedlibBp,
+ },
+ )
+ })
+
+ t.Run("prebuilt impl (with `stubs` property set): install", func(t *testing.T) {
+ testFunc(
+ t,
+ /*expectLibfooOnSystemLib=*/ true,
+ android.MockFS{
+ "impl/Android.bp": prebuiltLibfooBp,
+ "Android.bp": installedlibBp,
+ },
+ )
})
}
diff --git a/cc/proto.go b/cc/proto.go
index 97470e5..5d9aef6 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -207,7 +207,7 @@
protoAttrs.Min_sdk_version = m.Properties.Min_sdk_version
name := m.Name() + suffix
- tags := android.ApexAvailableTags(m)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), m)
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: rule_class,
diff --git a/cc/sanitize.go b/cc/sanitize.go
index aa61453..7fddc1b 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -62,14 +62,19 @@
"-fast-isel=false",
}
- cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
- "-fsanitize-ignorelist=external/compiler-rt/lib/cfi/cfi_blocklist.txt"}
+ cfiBlocklistPath = "external/compiler-rt/lib/cfi"
+ cfiBlocklistFilename = "cfi_blocklist.txt"
+ cfiCrossDsoFlag = "-fsanitize-cfi-cross-dso"
+ cfiCflags = []string{"-flto", cfiCrossDsoFlag,
+ "-fsanitize-ignorelist=" + cfiBlocklistPath + "/" + cfiBlocklistFilename}
// -flto and -fvisibility are required by clang when -fsanitize=cfi is
// used, but have no effect on assembly files
cfiAsflags = []string{"-flto", "-fvisibility=default"}
- cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi",
+ cfiLdflags = []string{"-flto", cfiCrossDsoFlag, "-fsanitize=cfi",
"-Wl,-plugin-opt,O1"}
- cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map"
+ cfiExportsMapPath = "build/soong/cc/config"
+ cfiExportsMapFilename = "cfi_exports.map"
+ cfiAssemblySupportFlag = "-fno-sanitize-cfi-canonical-jump-tables"
intOverflowCflags = []string{"-fsanitize-ignorelist=build/soong/cc/config/integer_overflow_blocklist.txt"}
@@ -77,7 +82,7 @@
"-fno-sanitize-recover=integer,undefined"}
hwasanGlobalOptions = []string{"heap_history_size=1023", "stack_history_size=512",
"export_memory_stats=0", "max_malloc_fill_size=131072", "malloc_fill_byte=0"}
- memtagStackCommonFlags = []string{"-march=armv8-a+memtag"}
+ memtagStackCommonFlags = []string{"-march=armv8-a+memtag", "-mllvm", "-dom-tree-reachability-max-bbs-to-explore=128"}
hostOnlySanitizeFlags = []string{"-fno-sanitize-recover=all"}
deviceOnlySanitizeFlags = []string{"-fsanitize-trap=all", "-ftrap-function=abort"}
@@ -254,7 +259,7 @@
// This should not be used in Android 11+ : https://source.android.com/devices/tech/debug/scudo
// deprecated
Scudo *bool `android:"arch_variant"`
- // shadow-call-stack sanitizer, only available on arm64
+ // shadow-call-stack sanitizer, only available on arm64/riscv64.
Scs *bool `android:"arch_variant"`
// Memory-tagging, only available on arm64
// if diag.memtag unset or false, enables async memory tagging
@@ -388,6 +393,20 @@
exportedVars.ExportStringListStaticVariable("HostOnlySanitizeFlags", hostOnlySanitizeFlags)
exportedVars.ExportStringList("DeviceOnlySanitizeFlags", deviceOnlySanitizeFlags)
+ // Leave out "-flto" from the slices exported to bazel, as we will use the
+ // dedicated LTO feature for this. For C Flags and Linker Flags, also leave
+ // out the cross DSO flag which will be added separately by transitions.
+ exportedVars.ExportStringList("CfiCFlags", cfiCflags[2:])
+ exportedVars.ExportStringList("CfiLdFlags", cfiLdflags[2:])
+ exportedVars.ExportStringList("CfiAsFlags", cfiAsflags[1:])
+
+ exportedVars.ExportString("CfiCrossDsoFlag", cfiCrossDsoFlag)
+ exportedVars.ExportString("CfiBlocklistPath", cfiBlocklistPath)
+ exportedVars.ExportString("CfiBlocklistFilename", cfiBlocklistFilename)
+ exportedVars.ExportString("CfiExportsMapPath", cfiExportsMapPath)
+ exportedVars.ExportString("CfiExportsMapFilename", cfiExportsMapFilename)
+ exportedVars.ExportString("CfiAssemblySupportFlag", cfiAssemblySupportFlag)
+
android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider)
android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider)
}
@@ -574,6 +593,12 @@
}
}
+ // Enable HWASan for all components in the include paths (for Aarch64 only)
+ if s.Hwaddress == nil && ctx.Config().HWASanEnabledForPath(ctx.ModuleDir()) &&
+ ctx.Arch().ArchType == android.Arm64 && ctx.toolchain().Bionic() {
+ s.Hwaddress = proptools.BoolPtr(true)
+ }
+
// Enable CFI for non-host components in the include paths
if s.Cfi == nil && ctx.Config().CFIEnabledForPath(ctx.ModuleDir()) && !ctx.Host() {
s.Cfi = proptools.BoolPtr(true)
@@ -593,8 +618,12 @@
s.Hwaddress = nil
}
- // SCS is only implemented on AArch64.
- if ctx.Arch().ArchType != android.Arm64 || !ctx.toolchain().Bionic() {
+ // SCS is only implemented on AArch64/riscv64.
+ if (ctx.Arch().ArchType != android.Arm64 && ctx.Arch().ArchType != android.Riscv64) || !ctx.toolchain().Bionic() {
+ s.Scs = nil
+ }
+ // ...but temporarily globally disabled on riscv64 (http://b/277909695).
+ if ctx.Arch().ArchType == android.Riscv64 {
s.Scs = nil
}
@@ -769,6 +798,13 @@
if Bool(sanProps.Writeonly) {
flags.Local.CFlags = append(flags.Local.CFlags, "-mllvm", "-hwasan-instrument-reads=0")
}
+ if !ctx.staticBinary() && !ctx.Host() {
+ if ctx.bootstrap() {
+ flags.DynamicLinker = "/system/bin/bootstrap/linker_hwasan64"
+ } else {
+ flags.DynamicLinker = "/system/bin/linker_hwasan64"
+ }
+ }
}
if Bool(sanProps.Fuzzer) {
@@ -810,7 +846,7 @@
flags.Local.CFlags = append(flags.Local.CFlags, cfiCflags...)
flags.Local.AsFlags = append(flags.Local.AsFlags, cfiAsflags...)
if Bool(s.Properties.Sanitize.Config.Cfi_assembly_support) {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-cfi-canonical-jump-tables")
+ flags.Local.CFlags = append(flags.Local.CFlags, cfiAssemblySupportFlag)
}
// Only append the default visibility flag if -fvisibility has not already been set
// to hidden.
@@ -1514,56 +1550,15 @@
diagSanitizers = sanitizers
}
- // Determine the runtime library required
- runtimeLibrary := ""
- alwaysStaticRuntime := false
- var extraStaticDeps []string
- toolchain := c.toolchain(mctx)
- if Bool(sanProps.Address) {
- runtimeLibrary = config.AddressSanitizerRuntimeLibrary(toolchain)
- } else if Bool(sanProps.Hwaddress) {
- if c.staticBinary() {
- runtimeLibrary = config.HWAddressSanitizerStaticLibrary(toolchain)
- extraStaticDeps = []string{"libdl"}
- } else {
- runtimeLibrary = config.HWAddressSanitizerRuntimeLibrary(toolchain)
- }
- } else if Bool(sanProps.Thread) {
- runtimeLibrary = config.ThreadSanitizerRuntimeLibrary(toolchain)
- } else if Bool(sanProps.Scudo) {
- if len(diagSanitizers) == 0 && !c.sanitize.Properties.UbsanRuntimeDep {
- runtimeLibrary = config.ScudoMinimalRuntimeLibrary(toolchain)
- } else {
- runtimeLibrary = config.ScudoRuntimeLibrary(toolchain)
- }
- } else if len(diagSanitizers) > 0 || c.sanitize.Properties.UbsanRuntimeDep ||
- Bool(sanProps.Fuzzer) ||
- Bool(sanProps.Undefined) ||
- Bool(sanProps.All_undefined) {
- runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)
- if c.staticBinary() || toolchain.Musl() {
- // Use a static runtime for static binaries.
- // Also use a static runtime for musl to match
- // what clang does for glibc. Otherwise dlopening
- // libraries that depend on libclang_rt.ubsan_standalone.so
- // fails with:
- // Error relocating ...: initial-exec TLS resolves to dynamic definition
- runtimeLibrary += ".static"
- alwaysStaticRuntime = true
- }
- }
-
- addStaticDeps := func(deps ...string) {
+ addStaticDeps := func(dep string, hideSymbols bool) {
// If we're using snapshots, redirect to snapshot whenever possible
snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo)
- for idx, dep := range deps {
- if lib, ok := snapshot.StaticLibs[dep]; ok {
- deps[idx] = lib
- }
+ if lib, ok := snapshot.StaticLibs[dep]; ok {
+ dep = lib
}
// static executable gets static runtime libs
- depTag := libraryDependencyTag{Kind: staticLibraryDependency, unexportedSymbols: true}
+ depTag := libraryDependencyTag{Kind: staticLibraryDependency, unexportedSymbols: hideSymbols}
variations := append(mctx.Target().Variations(),
blueprint.Variation{Mutator: "link", Variation: "static"})
if c.Device() {
@@ -1573,17 +1568,60 @@
variations = append(variations,
blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
}
- mctx.AddFarVariationDependencies(variations, depTag, deps...)
-
+ mctx.AddFarVariationDependencies(variations, depTag, dep)
}
+
+ // Determine the runtime library required
+ runtimeSharedLibrary := ""
+ toolchain := c.toolchain(mctx)
+ if Bool(sanProps.Address) {
+ if toolchain.Musl() || (c.staticBinary() && toolchain.Bionic()) {
+ // Use a static runtime for musl to match what clang does for glibc.
+ addStaticDeps(config.AddressSanitizerStaticRuntimeLibrary(toolchain), false)
+ addStaticDeps(config.AddressSanitizerCXXStaticRuntimeLibrary(toolchain), false)
+ } else {
+ runtimeSharedLibrary = config.AddressSanitizerRuntimeLibrary(toolchain)
+ }
+ } else if Bool(sanProps.Hwaddress) {
+ if c.staticBinary() {
+ addStaticDeps(config.HWAddressSanitizerStaticLibrary(toolchain), true)
+ addStaticDeps("libdl", false)
+ } else {
+ runtimeSharedLibrary = config.HWAddressSanitizerRuntimeLibrary(toolchain)
+ }
+ } else if Bool(sanProps.Thread) {
+ runtimeSharedLibrary = config.ThreadSanitizerRuntimeLibrary(toolchain)
+ } else if Bool(sanProps.Scudo) {
+ if len(diagSanitizers) == 0 && !c.sanitize.Properties.UbsanRuntimeDep {
+ runtimeSharedLibrary = config.ScudoMinimalRuntimeLibrary(toolchain)
+ } else {
+ runtimeSharedLibrary = config.ScudoRuntimeLibrary(toolchain)
+ }
+ } else if len(diagSanitizers) > 0 || c.sanitize.Properties.UbsanRuntimeDep ||
+ Bool(sanProps.Fuzzer) ||
+ Bool(sanProps.Undefined) ||
+ Bool(sanProps.All_undefined) {
+ if toolchain.Musl() || (c.staticBinary() && toolchain.Bionic()) {
+ // Use a static runtime for static binaries.
+ // Also use a static runtime for musl to match
+ // what clang does for glibc. Otherwise dlopening
+ // libraries that depend on libclang_rt.ubsan_standalone.so
+ // fails with:
+ // Error relocating ...: initial-exec TLS resolves to dynamic definition
+ addStaticDeps(config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)+".static", true)
+ } else {
+ runtimeSharedLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)
+ }
+ }
+
if enableMinimalRuntime(c.sanitize) || c.sanitize.Properties.MinimalRuntimeDep {
- addStaticDeps(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain))
+ addStaticDeps(config.UndefinedBehaviorSanitizerMinimalRuntimeLibrary(toolchain), true)
}
if c.sanitize.Properties.BuiltinsDep {
- addStaticDeps(config.BuiltinsRuntimeLibrary(toolchain))
+ addStaticDeps(config.BuiltinsRuntimeLibrary(toolchain), true)
}
- if runtimeLibrary != "" && (toolchain.Bionic() || toolchain.Musl() || c.sanitize.Properties.UbsanRuntimeDep) {
+ if runtimeSharedLibrary != "" && (toolchain.Bionic() || toolchain.Musl() || c.sanitize.Properties.UbsanRuntimeDep) {
// UBSan is supported on non-bionic linux host builds as well
// Adding dependency to the runtime library. We are using *FarVariation*
@@ -1593,14 +1631,17 @@
//
// Note that by adding dependency with {static|shared}DepTag, the lib is
// added to libFlags and LOCAL_SHARED_LIBRARIES by cc.Module
- if c.staticBinary() || alwaysStaticRuntime {
- addStaticDeps(runtimeLibrary)
- addStaticDeps(extraStaticDeps...)
+ if c.staticBinary() {
+ // Most sanitizers are either disabled for static binaries or have already
+ // handled the static binary case above through a direct call to addStaticDeps.
+ // If not, treat the runtime shared library as a static library and hope for
+ // the best.
+ addStaticDeps(runtimeSharedLibrary, true)
} else if !c.static() && !c.Header() {
// If we're using snapshots, redirect to snapshot whenever possible
snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo)
- if lib, ok := snapshot.SharedLibs[runtimeLibrary]; ok {
- runtimeLibrary = lib
+ if lib, ok := snapshot.SharedLibs[runtimeSharedLibrary]; ok {
+ runtimeSharedLibrary = lib
}
// Skip apex dependency check for sharedLibraryDependency
@@ -1624,7 +1665,7 @@
variations = append(variations,
blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
}
- AddSharedLibDependenciesWithVersions(mctx, c, variations, depTag, runtimeLibrary, "", true)
+ AddSharedLibDependenciesWithVersions(mctx, c, variations, depTag, runtimeSharedLibrary, "", true)
}
// static lib does not have dependency to the runtime library. The
// dependency will be added to the executables or shared libs using
diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go
index fe592dc..29b17d4 100644
--- a/cc/sanitize_test.go
+++ b/cc/sanitize_test.go
@@ -28,12 +28,22 @@
var prepareForAsanTest = android.FixtureAddFile("asan/Android.bp", []byte(`
cc_library_shared {
name: "libclang_rt.asan",
+ host_supported: true,
+ }
+ cc_library_static {
+ name: "libclang_rt.asan.static",
+ host_supported: true,
+ }
+ cc_library_static {
+ name: "libclang_rt.asan_cxx.static",
+ host_supported: true,
}
`))
var prepareForTsanTest = android.FixtureAddFile("tsan/Android.bp", []byte(`
cc_library_shared {
name: "libclang_rt.tsan",
+ host_supported: true,
}
`))
@@ -54,6 +64,19 @@
}
}
+// expectNoSharedLinkDep verifies that the from module links against the to module as a
+// shared library.
+func expectNoSharedLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
+ t.Helper()
+ fromLink := from.Description("link")
+ toInfo := ctx.ModuleProvider(to.Module(), SharedLibraryInfoProvider).(SharedLibraryInfo)
+
+ if g, w := fromLink.OrderOnly.Strings(), toInfo.SharedLibrary.RelativeToTop().String(); android.InList(w, g) {
+ t.Errorf("%s should not link against %s, expected %q, got %q",
+ from.Module(), to.Module(), w, g)
+ }
+}
+
// expectStaticLinkDep verifies that the from module links against the to module as a
// static library.
func expectStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
@@ -68,6 +91,20 @@
}
+// expectNoStaticLinkDep verifies that the from module links against the to module as a
+// static library.
+func expectNoStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
+ t.Helper()
+ fromLink := from.Description("link")
+ toInfo := ctx.ModuleProvider(to.Module(), StaticLibraryInfoProvider).(StaticLibraryInfo)
+
+ if g, w := fromLink.Implicits.Strings(), toInfo.StaticLibrary.RelativeToTop().String(); android.InList(w, g) {
+ t.Errorf("%s should not link against %s, expected %q, got %q",
+ from.Module(), to.Module(), w, g)
+ }
+
+}
+
// expectInstallDep verifies that the install rule of the from module depends on the
// install rule of the to module.
func expectInstallDep(t *testing.T, from, to android.TestingModule) {
@@ -85,6 +122,14 @@
}
}
+type expectedRuntimeLinkage int
+
+const (
+ RUNTIME_LINKAGE_NONE = expectedRuntimeLinkage(0)
+ RUNTIME_LINKAGE_SHARED = iota
+ RUNTIME_LINKAGE_STATIC
+)
+
func TestAsan(t *testing.T) {
t.Parallel()
bp := `
@@ -162,12 +207,14 @@
`
- result := android.GroupFixturePreparers(
+ preparer := android.GroupFixturePreparers(
prepareForCcTest,
prepareForAsanTest,
- ).RunTestWithBp(t, bp)
+ )
+ buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
- check := func(t *testing.T, result *android.TestResult, variant string) {
+ check := func(t *testing.T, variant string, runtimeLinkage expectedRuntimeLinkage, preparer android.FixturePreparer) {
+ result := preparer.RunTestWithBp(t, bp)
ctx := result.TestContext
asanVariant := variant + "_asan"
sharedVariant := variant + "_shared"
@@ -198,6 +245,10 @@
libStaticAsan := result.ModuleForTests("libstatic_asan", staticAsanVariant)
libStaticAsanNoAsanVariant := result.ModuleForTests("libstatic_asan", staticVariant)
+ libAsanSharedRuntime := result.ModuleForTests("libclang_rt.asan", sharedVariant)
+ libAsanStaticRuntime := result.ModuleForTests("libclang_rt.asan.static", staticVariant)
+ libAsanStaticCxxRuntime := result.ModuleForTests("libclang_rt.asan_cxx.static", staticVariant)
+
expectSharedLinkDep(t, ctx, binWithAsan, libShared)
expectSharedLinkDep(t, ctx, binWithAsan, libAsan)
expectSharedLinkDep(t, ctx, libShared, libTransitive)
@@ -227,10 +278,54 @@
expectInstallDep(t, binNoAsan, libTransitive)
expectInstallDep(t, libShared, libTransitive)
expectInstallDep(t, libAsan, libTransitive)
+
+ if runtimeLinkage == RUNTIME_LINKAGE_SHARED {
+ expectSharedLinkDep(t, ctx, binWithAsan, libAsanSharedRuntime)
+ expectNoSharedLinkDep(t, ctx, binNoAsan, libAsanSharedRuntime)
+ expectSharedLinkDep(t, ctx, libAsan, libAsanSharedRuntime)
+ expectNoSharedLinkDep(t, ctx, libShared, libAsanSharedRuntime)
+ expectNoSharedLinkDep(t, ctx, libTransitive, libAsanSharedRuntime)
+ } else {
+ expectNoSharedLinkDep(t, ctx, binWithAsan, libAsanSharedRuntime)
+ expectNoSharedLinkDep(t, ctx, binNoAsan, libAsanSharedRuntime)
+ expectNoSharedLinkDep(t, ctx, libAsan, libAsanSharedRuntime)
+ expectNoSharedLinkDep(t, ctx, libShared, libAsanSharedRuntime)
+ expectNoSharedLinkDep(t, ctx, libTransitive, libAsanSharedRuntime)
+ }
+
+ if runtimeLinkage == RUNTIME_LINKAGE_STATIC {
+ expectStaticLinkDep(t, ctx, binWithAsan, libAsanStaticRuntime)
+ expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticRuntime)
+ expectStaticLinkDep(t, ctx, libAsan, libAsanStaticRuntime)
+ expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticRuntime)
+ expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticRuntime)
+
+ expectStaticLinkDep(t, ctx, binWithAsan, libAsanStaticCxxRuntime)
+ expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticCxxRuntime)
+ expectStaticLinkDep(t, ctx, libAsan, libAsanStaticCxxRuntime)
+ expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticCxxRuntime)
+ expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticCxxRuntime)
+ } else {
+ expectNoStaticLinkDep(t, ctx, binWithAsan, libAsanStaticRuntime)
+ expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticRuntime)
+ expectNoStaticLinkDep(t, ctx, libAsan, libAsanStaticRuntime)
+ expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticRuntime)
+ expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticRuntime)
+
+ expectNoStaticLinkDep(t, ctx, binWithAsan, libAsanStaticCxxRuntime)
+ expectNoStaticLinkDep(t, ctx, binNoAsan, libAsanStaticCxxRuntime)
+ expectNoStaticLinkDep(t, ctx, libAsan, libAsanStaticCxxRuntime)
+ expectNoStaticLinkDep(t, ctx, libShared, libAsanStaticCxxRuntime)
+ expectNoStaticLinkDep(t, ctx, libTransitive, libAsanStaticCxxRuntime)
+ }
}
- t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) })
- t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") })
+ t.Run("host", func(t *testing.T) { check(t, buildOS, RUNTIME_LINKAGE_NONE, preparer) })
+ t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", RUNTIME_LINKAGE_SHARED, preparer) })
+ t.Run("host musl", func(t *testing.T) {
+ check(t, "linux_musl_x86_64", RUNTIME_LINKAGE_STATIC,
+ android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
+ })
}
func TestTsan(t *testing.T) {
@@ -278,12 +373,14 @@
}
`
- result := android.GroupFixturePreparers(
+ preparer := android.GroupFixturePreparers(
prepareForCcTest,
prepareForTsanTest,
- ).RunTestWithBp(t, bp)
+ )
+ buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
- check := func(t *testing.T, result *android.TestResult, variant string) {
+ check := func(t *testing.T, variant string, preparer android.FixturePreparer) {
+ result := preparer.RunTestWithBp(t, bp)
ctx := result.TestContext
tsanVariant := variant + "_tsan"
sharedVariant := variant + "_shared"
@@ -311,8 +408,11 @@
expectSharedLinkDep(t, ctx, libTsan, libTransitive)
}
- t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) })
- t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") })
+ t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })
+ t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", preparer) })
+ t.Run("host musl", func(t *testing.T) {
+ check(t, "linux_musl_x86_64", android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
+ })
}
func TestMiscUndefined(t *testing.T) {
@@ -369,11 +469,13 @@
}
`
- result := android.GroupFixturePreparers(
+ preparer := android.GroupFixturePreparers(
prepareForCcTest,
- ).RunTestWithBp(t, bp)
+ )
+ buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
- check := func(t *testing.T, result *android.TestResult, variant string) {
+ check := func(t *testing.T, variant string, preparer android.FixturePreparer) {
+ result := preparer.RunTestWithBp(t, bp)
ctx := result.TestContext
staticVariant := variant + "_static"
@@ -415,8 +517,11 @@
expectStaticLinkDep(t, ctx, binNoUbsan, libUbsan)
}
- t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) })
- t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") })
+ t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })
+ t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", preparer) })
+ t.Run("host musl", func(t *testing.T) {
+ check(t, "linux_musl_x86_64", android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
+ })
}
func TestFuzz(t *testing.T) {
@@ -647,11 +752,13 @@
}
`
- result := android.GroupFixturePreparers(
+ preparer := android.GroupFixturePreparers(
prepareForCcTest,
- ).RunTestWithBp(t, bp)
+ )
+ buildOS := preparer.RunTestWithBp(t, bp).Config.BuildOSTarget.String()
- check := func(t *testing.T, result *android.TestResult, variant string) {
+ check := func(t *testing.T, variant string, preparer android.FixturePreparer) {
+ result := preparer.RunTestWithBp(t, bp)
staticVariant := variant + "_static"
sharedVariant := variant + "_shared"
@@ -705,8 +812,11 @@
"-Wl,--exclude-libs="+minimalRuntime.OutputFiles(t, "")[0].Base())
}
- t.Run("host", func(t *testing.T) { check(t, result, result.Config.BuildOSTarget.String()) })
- t.Run("device", func(t *testing.T) { check(t, result, "android_arm64_armv8-a") })
+ t.Run("host", func(t *testing.T) { check(t, buildOS, preparer) })
+ t.Run("device", func(t *testing.T) { check(t, "android_arm64_armv8-a", preparer) })
+ t.Run("host musl", func(t *testing.T) {
+ check(t, "linux_musl_x86_64", android.GroupFixturePreparers(preparer, PrepareForTestWithHostMusl))
+ })
}
type MemtagNoteType int
@@ -1056,3 +1166,83 @@
checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_disable", variant), Sync)
checkHasMemtagNote(t, ctx.ModuleForTests("unset_test_override_default_sync", variant), Sync)
}
+
+func TestCfi(t *testing.T) {
+ t.Parallel()
+
+ bp := `
+ cc_library_shared {
+ name: "shared_with_cfi",
+ static_libs: [
+ "static_dep_with_cfi",
+ "static_dep_no_cfi",
+ ],
+ sanitize: {
+ cfi: true,
+ },
+ }
+
+ cc_library_shared {
+ name: "shared_no_cfi",
+ static_libs: [
+ "static_dep_with_cfi",
+ "static_dep_no_cfi",
+ ],
+ }
+
+ cc_library_static {
+ name: "static_dep_with_cfi",
+ sanitize: {
+ cfi: true,
+ },
+ }
+
+ cc_library_static {
+ name: "static_dep_no_cfi",
+ }
+
+ cc_library_shared {
+ name: "shared_rdep_no_cfi",
+ static_libs: ["static_dep_with_cfi_2"],
+ }
+
+ cc_library_static {
+ name: "static_dep_with_cfi_2",
+ sanitize: {
+ cfi: true,
+ },
+ }
+`
+ preparer := android.GroupFixturePreparers(
+ prepareForCcTest,
+ )
+ result := preparer.RunTestWithBp(t, bp)
+ ctx := result.TestContext
+
+ buildOs := "android_arm64_armv8-a"
+ shared_suffix := "_shared"
+ cfi_suffix := "_cfi"
+ static_suffix := "_static"
+
+ sharedWithCfiLib := result.ModuleForTests("shared_with_cfi", buildOs+shared_suffix+cfi_suffix)
+ sharedNoCfiLib := result.ModuleForTests("shared_no_cfi", buildOs+shared_suffix)
+ staticWithCfiLib := result.ModuleForTests("static_dep_with_cfi", buildOs+static_suffix)
+ staticWithCfiLibCfiVariant := result.ModuleForTests("static_dep_with_cfi", buildOs+static_suffix+cfi_suffix)
+ staticNoCfiLib := result.ModuleForTests("static_dep_no_cfi", buildOs+static_suffix)
+ staticNoCfiLibCfiVariant := result.ModuleForTests("static_dep_no_cfi", buildOs+static_suffix+cfi_suffix)
+ sharedRdepNoCfi := result.ModuleForTests("shared_rdep_no_cfi", buildOs+shared_suffix)
+ staticDepWithCfi2Lib := result.ModuleForTests("static_dep_with_cfi_2", buildOs+static_suffix)
+
+ // Confirm assumptions about propagation of CFI enablement
+ expectStaticLinkDep(t, ctx, sharedWithCfiLib, staticWithCfiLibCfiVariant)
+ expectStaticLinkDep(t, ctx, sharedNoCfiLib, staticWithCfiLib)
+ expectStaticLinkDep(t, ctx, sharedWithCfiLib, staticNoCfiLibCfiVariant)
+ expectStaticLinkDep(t, ctx, sharedNoCfiLib, staticNoCfiLib)
+ expectStaticLinkDep(t, ctx, sharedRdepNoCfi, staticDepWithCfi2Lib)
+
+ // Confirm that non-CFI variants do not add CFI flags
+ bazLibCflags := staticWithCfiLib.Rule("cc").Args["cFlags"]
+ if strings.Contains(bazLibCflags, "-fsanitize-cfi-cross-dso") {
+ t.Errorf("non-CFI variant of baz not expected to contain CFI flags ")
+ }
+}
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index 32878ca..bb6e257 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -522,6 +522,8 @@
return false
}
+var _ snapshotSanitizer = (*snapshotLibraryDecorator)(nil)
+
func (p *snapshotLibraryDecorator) isSanitizerAvailable(t SanitizerType) bool {
switch t {
case cfi:
@@ -644,8 +646,6 @@
return module.Init()
}
-var _ snapshotSanitizer = (*snapshotLibraryDecorator)(nil)
-
// Module definitions for snapshots of executable binaries.
//
// Modules (vendor|recovery)_snapshot_binary are defined here. They have their prebuilt executable
diff --git a/cc/sysprop.go b/cc/sysprop.go
index 2b1e354..7ddd476 100644
--- a/cc/sysprop.go
+++ b/cc/sysprop.go
@@ -22,11 +22,13 @@
// TODO(b/240463568): Additional properties will be added for API validation
type bazelSyspropLibraryAttributes struct {
Srcs bazel.LabelListAttribute
+ Tags bazel.StringListAttribute
}
type bazelCcSyspropLibraryAttributes struct {
Dep bazel.LabelAttribute
Min_sdk_version *string
+ Tags bazel.StringListAttribute
}
type SyspropLibraryLabels struct {
@@ -36,6 +38,7 @@
}
func Bp2buildSysprop(ctx android.Bp2buildMutatorContext, labels SyspropLibraryLabels, srcs bazel.LabelListAttribute, minSdkVersion *string) {
+ apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), ctx.Module())
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "sysprop_library",
@@ -44,11 +47,14 @@
android.CommonAttributes{Name: labels.SyspropLibraryLabel},
&bazelSyspropLibraryAttributes{
Srcs: srcs,
- })
+ Tags: apexAvailableTags,
+ },
+ )
attrs := &bazelCcSyspropLibraryAttributes{
Dep: *bazel.MakeLabelAttribute(":" + labels.SyspropLibraryLabel),
Min_sdk_version: minSdkVersion,
+ Tags: apexAvailableTags,
}
if labels.SharedLibraryLabel != "" {
diff --git a/cc/testing.go b/cc/testing.go
index 992069b..ced0929 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -40,7 +40,6 @@
ctx.RegisterModuleType("cc_genrule", GenRuleFactory)
ctx.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory)
ctx.RegisterModuleType("ndk_prebuilt_static_stl", NdkPrebuiltStaticStlFactory)
- ctx.RegisterModuleType("ndk_prebuilt_object", NdkPrebuiltObjectFactory)
ctx.RegisterModuleType("ndk_library", NdkLibraryFactory)
ctx.RegisterModuleType("ndk_headers", ndkHeadersFactory)
}
@@ -70,6 +69,7 @@
return `
cc_defaults {
name: "toolchain_libs_defaults",
+ host_supported: true,
vendor_available: true,
product_available: true,
recovery_available: true,
@@ -135,6 +135,12 @@
}
cc_prebuilt_library_static {
+ name: "libclang_rt.ubsan_standalone.static",
+ defaults: ["toolchain_libs_defaults"],
+ srcs: [""],
+ }
+
+ cc_prebuilt_library_static {
name: "libclang_rt.ubsan_minimal",
defaults: ["toolchain_libs_defaults"],
host_supported: true,
@@ -151,6 +157,12 @@
linux_glibc_x86: {
srcs: ["libclang_rt.ubsan_minimal.x86.a"],
},
+ linux_musl_x86_64: {
+ srcs: ["libclang_rt.ubsan_minimal.x86_64.a"],
+ },
+ linux_musl_x86: {
+ srcs: ["libclang_rt.ubsan_minimal.x86.a"],
+ },
},
}
@@ -619,6 +631,51 @@
}),
)
+// PrepareForTestWithHostMusl sets the host configuration to musl libc instead of glibc. It also disables the test
+// on mac, which doesn't support musl libc, and adds musl modules.
+var PrepareForTestWithHostMusl = android.GroupFixturePreparers(
+ android.FixtureModifyConfig(android.ModifyTestConfigForMusl),
+ android.PrepareForSkipTestOnMac,
+ android.FixtureAddTextFile("external/musl/Android.bp", `
+ cc_defaults {
+ name: "libc_musl_crt_defaults",
+ host_supported: true,
+ device_supported: false,
+ }
+
+ cc_object {
+ name: "libc_musl_crtbegin_so",
+ defaults: ["libc_musl_crt_defaults"],
+ }
+
+ cc_object {
+ name: "libc_musl_crtend_so",
+ defaults: ["libc_musl_crt_defaults"],
+ }
+
+ cc_object {
+ name: "libc_musl_crtbegin_dynamic",
+ defaults: ["libc_musl_crt_defaults"],
+ }
+
+ cc_object {
+ name: "libc_musl_crtbegin_static",
+ defaults: ["libc_musl_crt_defaults"],
+ }
+
+ cc_object {
+ name: "libc_musl_crtend",
+ defaults: ["libc_musl_crt_defaults"],
+ }
+ `),
+)
+
+// PrepareForTestWithFdoProfile registers module types to test with fdo_profile
+var PrepareForTestWithFdoProfile = android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("soong_namespace", android.NamespaceFactory)
+ ctx.RegisterModuleType("fdo_profile", fdoProfileFactory)
+})
+
// TestConfig is the legacy way of creating a test Config for testing cc modules.
//
// See testCc for an explanation as to how to stop using this deprecated method.
diff --git a/cc/util.go b/cc/util.go
index aa0f6b5..6d8ac43 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -100,17 +100,6 @@
"ln -sf " + target + " " + filepath.Join(dir, linkName)
}
-func combineNoticesRule(ctx android.SingletonContext, paths android.Paths, out string) android.OutputPath {
- outPath := android.PathForOutput(ctx, out)
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Cat,
- Inputs: paths,
- Output: outPath,
- Description: "combine notices for " + out,
- })
- return outPath
-}
-
// Dump a map to a list file as:
//
// {key1} {value1}
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 9b12bfa..e6e5660 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -157,9 +157,10 @@
// extra config files
InitRc []string `json:",omitempty"`
VintfFragments []string `json:",omitempty"`
+ MinSdkVersion string `json:",omitempty"`
}
-var ccSnapshotAction snapshot.GenerateSnapshotAction = func(s snapshot.SnapshotSingleton, ctx android.SingletonContext, snapshotArchDir string) android.Paths {
+var ccSnapshotAction snapshot.GenerateSnapshotAction = func(s snapshot.SnapshotSingleton, ctx android.SingletonContext, snapshotArchDir string) snapshot.SnapshotPaths {
/*
Vendor snapshot zipped artifacts directory structure for cc modules:
{SNAPSHOT_ARCH}/
@@ -194,10 +195,10 @@
*/
var snapshotOutputs android.Paths
+ var snapshotNotices android.Paths
includeDir := filepath.Join(snapshotArchDir, "include")
configsDir := filepath.Join(snapshotArchDir, "configs")
- noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
installedNotices := make(map[string]bool)
installedConfigs := make(map[string]bool)
@@ -227,7 +228,7 @@
prop := snapshotJsonFlags{}
// Common properties among snapshots.
- prop.ModuleName = ctx.ModuleName(m)
+ prop.InitBaseSnapshotPropsWithName(m, ctx.ModuleName(m))
if supportsVndkExt(s.Image) && m.IsVndkExt() {
// vndk exts are installed to /vendor/lib(64)?/vndk(-sp)?
if m.IsVndkSp() {
@@ -249,6 +250,7 @@
for _, path := range m.VintfFragments() {
prop.VintfFragments = append(prop.VintfFragments, filepath.Join("configs", path.Base()))
}
+ prop.MinSdkVersion = m.MinSdkVersion()
// install config files. ignores any duplicates.
for _, path := range append(m.InitRc(), m.VintfFragments()...) {
@@ -404,13 +406,10 @@
headers = append(headers, m.SnapshotHeaders()...)
}
- if len(m.EffectiveLicenseFiles()) > 0 {
- noticeName := ctx.ModuleName(m) + ".txt"
- noticeOut := filepath.Join(noticeDir, noticeName)
- // skip already copied notice file
- if !installedNotices[noticeOut] {
- installedNotices[noticeOut] = true
- snapshotOutputs = append(snapshotOutputs, combineNoticesRule(ctx, m.EffectiveLicenseFiles(), noticeOut))
+ for _, notice := range m.EffectiveLicenseFiles() {
+ if _, ok := installedNotices[notice.String()]; !ok {
+ installedNotices[notice.String()] = true
+ snapshotNotices = append(snapshotNotices, notice)
}
}
})
@@ -420,7 +419,7 @@
snapshotOutputs = append(snapshotOutputs, copyFile(ctx, header, filepath.Join(includeDir, header.String()), s.Fake))
}
- return snapshotOutputs
+ return snapshot.SnapshotPaths{OutputFiles: snapshotOutputs, NoticeFiles: snapshotNotices}
}
func init() {
diff --git a/cc/vndk.go b/cc/vndk.go
index 3b7c87d..30bfdd8 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -674,8 +674,12 @@
snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
configsDir := filepath.Join(snapshotArchDir, "configs")
+ noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
includeDir := filepath.Join(snapshotArchDir, "include")
+ // set of notice files copied.
+ noticeBuilt := make(map[string]bool)
+
// paths of VNDK modules for GPL license checking
modulePaths := make(map[string]string)
@@ -700,28 +704,38 @@
snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "shared", vndkType, libPath.Base())
ret = append(ret, snapshot.CopyFileRule(pctx, ctx, libPath, snapshotLibOut))
+ // json struct to export snapshot information
+ prop := struct {
+ MinSdkVersion string `json:",omitempty"`
+ LicenseKinds []string `json:",omitempty"`
+ LicenseTexts []string `json:",omitempty"`
+ ExportedDirs []string `json:",omitempty"`
+ ExportedSystemDirs []string `json:",omitempty"`
+ ExportedFlags []string `json:",omitempty"`
+ RelativeInstallPath string `json:",omitempty"`
+ }{}
+
+ prop.LicenseKinds = m.EffectiveLicenseKinds()
+ prop.LicenseTexts = m.EffectiveLicenseFiles().Strings()
+ prop.MinSdkVersion = m.MinSdkVersion()
+
if ctx.Config().VndkSnapshotBuildArtifacts() {
- prop := struct {
- ExportedDirs []string `json:",omitempty"`
- ExportedSystemDirs []string `json:",omitempty"`
- ExportedFlags []string `json:",omitempty"`
- RelativeInstallPath string `json:",omitempty"`
- }{}
exportedInfo := ctx.ModuleProvider(m, FlagExporterInfoProvider).(FlagExporterInfo)
prop.ExportedFlags = exportedInfo.Flags
prop.ExportedDirs = exportedInfo.IncludeDirs.Strings()
prop.ExportedSystemDirs = exportedInfo.SystemIncludeDirs.Strings()
prop.RelativeInstallPath = m.RelativeInstallPath()
-
- propOut := snapshotLibOut + ".json"
-
- j, err := json.Marshal(prop)
- if err != nil {
- ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
- return nil, false
- }
- ret = append(ret, snapshot.WriteStringToFileRule(ctx, string(j), propOut))
}
+
+ propOut := snapshotLibOut + ".json"
+
+ j, err := json.Marshal(prop)
+ if err != nil {
+ ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
+ return nil, false
+ }
+ ret = append(ret, snapshot.WriteStringToFileRule(ctx, string(j), propOut))
+
return ret, true
}
@@ -761,6 +775,14 @@
moduleNames[stem] = ctx.ModuleName(m)
modulePaths[stem] = ctx.ModuleDir(m)
+ for _, notice := range m.EffectiveLicenseFiles() {
+ if _, ok := noticeBuilt[notice.String()]; !ok {
+ noticeBuilt[notice.String()] = true
+ snapshotOutputs = append(snapshotOutputs, snapshot.CopyFileRule(
+ pctx, ctx, notice, filepath.Join(noticeDir, notice.String())))
+ }
+ }
+
if ctx.Config().VndkSnapshotBuildArtifacts() {
headers = append(headers, m.SnapshotHeaders()...)
}
diff --git a/cmd/extract_apks/main.go b/cmd/extract_apks/main.go
index 82db634..2e71fe1 100644
--- a/cmd/extract_apks/main.go
+++ b/cmd/extract_apks/main.go
@@ -41,6 +41,7 @@
abis map[android_bundle_proto.Abi_AbiAlias]int
allowPrereleased bool
stem string
+ skipSdkCheck bool
}
// An APK set is a zip archive. An entry 'toc.pb' describes its contents.
@@ -322,6 +323,12 @@
func (m sdkVersionTargetingMatcher) matches(config TargetConfig) bool {
const preReleaseVersion = 10000
+ // TODO (b274518686) This check should only be used while SHA based targeting is active
+ // Once we have switched to an SDK version, this can be changed to throw an error if
+ // it was accidentally set
+ if config.skipSdkCheck == true {
+ return true
+ }
if m.SdkVersionTargeting == nil {
return true
}
@@ -572,7 +579,7 @@
func processArgs() {
flag.Usage = func() {
fmt.Fprintln(os.Stderr, `usage: extract_apks -o <output-file> [-zip <output-zip-file>] `+
- `-sdk-version value -abis value `+
+ `-sdk-version value -abis value [-skip-sdk-check]`+
`-screen-densities value {-stem value | -extract-single} [-allow-prereleased] `+
`[-apkcerts <apkcerts output file> -partition <partition>] <APK set>`)
flag.PrintDefaults()
@@ -585,6 +592,7 @@
"'all' or comma-separated list of screen density names (NODPI LDPI MDPI TVDPI HDPI XHDPI XXHDPI XXXHDPI)")
flag.BoolVar(&targetConfig.allowPrereleased, "allow-prereleased", false,
"allow prereleased")
+ flag.BoolVar(&targetConfig.skipSdkCheck, "skip-sdk-check", false, "Skip the SDK version check")
flag.StringVar(&targetConfig.stem, "stem", "", "output entries base name in the output zip file")
flag.Parse()
if (*outputFile == "") || len(flag.Args()) != 1 || *version == 0 ||
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index 91e3540..fc56dd5 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -390,7 +390,7 @@
}
}
- const maxErrors = 10
+ const maxErrors = 25
if len(incorrectOutputDirectoryErrors) > 0 {
errorMessage := ""
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 5c187f6..53e0e55 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -24,6 +24,7 @@
"time"
"android/soong/android"
+ "android/soong/android/allowlists"
"android/soong/bazel"
"android/soong/bp2build"
"android/soong/shared"
@@ -78,11 +79,13 @@
flag.StringVar(&cmdlineArgs.OutFile, "o", "build.ninja", "the Ninja file to output")
flag.StringVar(&cmdlineArgs.BazelForceEnabledModules, "bazel-force-enabled-modules", "", "additional modules to build with Bazel. Comma-delimited")
flag.BoolVar(&cmdlineArgs.EmptyNinjaFile, "empty-ninja-file", false, "write out a 0-byte ninja file")
+ flag.BoolVar(&cmdlineArgs.MultitreeBuild, "multitree-build", false, "this is a multitree build")
flag.BoolVar(&cmdlineArgs.BazelMode, "bazel-mode", false, "use bazel for analysis of certain modules")
flag.BoolVar(&cmdlineArgs.BazelModeStaging, "bazel-mode-staging", false, "use bazel for analysis of certain near-ready modules")
flag.BoolVar(&cmdlineArgs.BazelModeDev, "bazel-mode-dev", false, "use bazel for analysis of a large number of modules (less stable)")
flag.BoolVar(&cmdlineArgs.UseBazelProxy, "use-bazel-proxy", false, "communicate with bazel using unix socket proxy instead of spawning subprocesses")
-
+ flag.BoolVar(&cmdlineArgs.BuildFromTextStub, "build-from-text-stub", false, "build Java stubs from API text files instead of source files")
+ flag.BoolVar(&cmdlineArgs.EnsureAllowlistIntegrity, "ensure-allowlist-integrity", false, "verify that allowlisted modules are mixed-built")
// Flags that probably shouldn't be flags of soong_build, but we haven't found
// the time to remove them yet
flag.BoolVar(&cmdlineArgs.RunGoTests, "t", false, "build and run go tests during bootstrap")
@@ -103,6 +106,7 @@
ctx.SetNameInterface(newNameResolver(configuration))
ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
ctx.AddIncludeTags(configuration.IncludeTags()...)
+ ctx.AddSourceRootDirs(configuration.SourceRootDirs()...)
return ctx
}
@@ -136,7 +140,7 @@
ctx.EventHandler.Begin("queryview")
defer ctx.EventHandler.End("queryview")
codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.QueryView, topDir)
- err := createBazelWorkspace(codegenContext, shared.JoinPath(topDir, queryviewDir))
+ err := createBazelWorkspace(codegenContext, shared.JoinPath(topDir, queryviewDir), false)
maybeQuit(err, "")
touch(shared.JoinPath(topDir, queryviewMarker))
}
@@ -174,7 +178,28 @@
// Run codegen to generate BUILD files
codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.ApiBp2build, topDir)
absoluteApiBp2buildDir := shared.JoinPath(topDir, cmdlineArgs.BazelApiBp2buildDir)
- err := createBazelWorkspace(codegenContext, absoluteApiBp2buildDir)
+ // Always generate bp2build_all_srcs filegroups in api_bp2build.
+ // This is necessary to force each Android.bp file to create an equivalent BUILD file
+ // and prevent package boundray issues.
+ // e.g.
+ // Source
+ // f/b/Android.bp
+ // java_library{
+ // name: "foo",
+ // api: "api/current.txt",
+ // }
+ //
+ // f/b/api/Android.bp <- will cause package boundary issues
+ //
+ // Gen
+ // f/b/BUILD
+ // java_contribution{
+ // name: "foo.contribution",
+ // api: "//f/b/api:current.txt",
+ // }
+ //
+ // If we don't generate f/b/api/BUILD, foo.contribution will be unbuildable.
+ err := createBazelWorkspace(codegenContext, absoluteApiBp2buildDir, true)
maybeQuit(err, "")
ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
@@ -230,6 +255,29 @@
return ret
}
+func writeNinjaHint(ctx *android.Context) error {
+ wantModules := make([]string, len(allowlists.HugeModulesMap))
+ i := 0
+ for k := range allowlists.HugeModulesMap {
+ wantModules[i] = k
+ i += 1
+ }
+ outputsMap := ctx.Context.GetOutputsFromModuleNames(wantModules)
+ var outputBuilder strings.Builder
+ for k, v := range allowlists.HugeModulesMap {
+ for _, output := range outputsMap[k] {
+ outputBuilder.WriteString(fmt.Sprintf("%s,%d\n", output, v))
+ }
+ }
+ weightListFile := filepath.Join(topDir, ctx.Config().OutDir(), ".ninja_weight_list")
+
+ err := os.WriteFile(weightListFile, []byte(outputBuilder.String()), 0644)
+ if err != nil {
+ return fmt.Errorf("could not write ninja weight list file %s", err)
+ }
+ return nil
+}
+
func writeMetrics(configuration android.Config, eventHandler *metrics.EventHandler, metricsDir string) {
if len(metricsDir) < 1 {
fmt.Fprintf(os.Stderr, "\nMissing required env var for generating soong metrics: LOG_DIR\n")
@@ -240,6 +288,46 @@
maybeQuit(err, "error writing soong_build metrics %s", metricsFile)
}
+// Errors out if any modules expected to be mixed_built were not, unless
+// there is a platform incompatibility.
+func checkForAllowlistIntegrityError(configuration android.Config, isStagingMode bool) error {
+ modules := findModulesNotMixedBuiltForAnyVariant(configuration, isStagingMode)
+ if len(modules) == 0 {
+ return nil
+ }
+
+ return fmt.Errorf("Error: expected the following modules to be mixed_built: %s", modules)
+}
+
+// Returns the list of modules that should have been mixed_built (per the
+// allowlists and cmdline flags) but were not.
+func findModulesNotMixedBuiltForAnyVariant(configuration android.Config, isStagingMode bool) []string {
+ retval := []string{}
+ forceEnabledModules := configuration.BazelModulesForceEnabledByFlag()
+
+ mixedBuildsEnabled := configuration.GetMixedBuildsEnabledModules()
+ for _, module := range allowlists.ProdMixedBuildsEnabledList {
+ if _, ok := mixedBuildsEnabled[module]; !ok && module != "" {
+ retval = append(retval, module)
+ }
+ }
+
+ if isStagingMode {
+ for _, module := range allowlists.StagingMixedBuildsEnabledList {
+ if _, ok := mixedBuildsEnabled[module]; !ok && module != "" {
+ retval = append(retval, module)
+ }
+ }
+ }
+
+ for module, _ := range forceEnabledModules {
+ if _, ok := mixedBuildsEnabled[module]; !ok && module != "" {
+ retval = append(retval, module)
+ }
+ }
+ return retval
+}
+
func writeJsonModuleGraphAndActions(ctx *android.Context, cmdArgs android.CmdArgs) {
graphFile, graphErr := os.Create(shared.JoinPath(topDir, cmdArgs.ModuleGraphFile))
maybeQuit(graphErr, "graph err")
@@ -385,11 +473,20 @@
writeMetrics(configuration, ctx.EventHandler, metricsDir)
default:
ctx.Register()
- if configuration.IsMixedBuildsEnabled() {
+ isMixedBuildsEnabled := configuration.IsMixedBuildsEnabled()
+ if isMixedBuildsEnabled {
finalOutputFile = runMixedModeBuild(ctx, extraNinjaDeps)
+ if cmdlineArgs.EnsureAllowlistIntegrity {
+ if err := checkForAllowlistIntegrityError(configuration, cmdlineArgs.BazelModeStaging); err != nil {
+ maybeQuit(err, "")
+ }
+ }
} else {
finalOutputFile = runSoongOnlyBuild(ctx, extraNinjaDeps)
}
+ if ctx.Config().IsEnvTrue("SOONG_GENERATES_NINJA_HINT") {
+ writeNinjaHint(ctx)
+ }
writeMetrics(configuration, ctx.EventHandler, metricsDir)
}
writeUsedEnvironmentFile(configuration, finalOutputFile)
diff --git a/cmd/soong_build/queryview.go b/cmd/soong_build/queryview.go
index 35ae009..67cb6cf 100644
--- a/cmd/soong_build/queryview.go
+++ b/cmd/soong_build/queryview.go
@@ -15,6 +15,7 @@
package main
import (
+ "android/soong/starlark_import"
"io/fs"
"io/ioutil"
"os"
@@ -25,11 +26,11 @@
)
// A helper function to generate a Read-only Bazel workspace in outDir
-func createBazelWorkspace(ctx *bp2build.CodegenContext, outDir string) error {
+func createBazelWorkspace(ctx *bp2build.CodegenContext, outDir string, generateFilegroups bool) error {
os.RemoveAll(outDir)
ruleShims := bp2build.CreateRuleShims(android.ModuleTypeFactories())
- res, err := bp2build.GenerateBazelTargets(ctx, false)
+ res, err := bp2build.GenerateBazelTargets(ctx, generateFilegroups)
if err != nil {
panic(err)
}
@@ -47,6 +48,14 @@
}
}
+ // Add starlark deps here, so that they apply to both queryview and apibp2build which
+ // both run this function.
+ starlarkDeps, err2 := starlark_import.GetNinjaDeps()
+ if err2 != nil {
+ return err2
+ }
+ ctx.AddNinjaFileDeps(starlarkDeps...)
+
return nil
}
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index ae026ba..301246a 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -169,7 +169,7 @@
// Create a new Status instance, which manages action counts and event output channels.
stat := &status.Status{}
- defer stat.Finish()
+
// Hook up the terminal output and tracer to Status.
stat.AddOutput(output)
stat.AddOutput(trace.StatusTracer())
@@ -180,14 +180,15 @@
log.Cleanup()
stat.Finish()
})
-
+ criticalPath := status.NewCriticalPath()
buildCtx := build.Context{ContextImpl: &build.ContextImpl{
- Context: ctx,
- Logger: log,
- Metrics: met,
- Tracer: trace,
- Writer: output,
- Status: stat,
+ Context: ctx,
+ Logger: log,
+ Metrics: met,
+ Tracer: trace,
+ Writer: output,
+ Status: stat,
+ CriticalPath: criticalPath,
}}
config := c.config(buildCtx, args...)
@@ -220,11 +221,14 @@
trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
- if !config.SkipMetricsUpload() {
- defer build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, bazelProfileFile, bazelMetricsFile, metricsFiles...)
- }
- defer met.Dump(soongMetricsFile)
-
+ defer func() {
+ stat.Finish()
+ criticalPath.WriteToMetrics(met)
+ met.Dump(soongMetricsFile)
+ if !config.SkipMetricsUpload() {
+ build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, bazelProfileFile, bazelMetricsFile, metricsFiles...)
+ }
+ }()
c.run(buildCtx, config, args)
}
@@ -254,7 +258,7 @@
stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, logsPrefix+"verbose.log")))
stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, logsPrefix+"error.log")))
stat.AddOutput(status.NewProtoErrorLog(log, buildErrorFile))
- stat.AddOutput(status.NewCriticalPath(log))
+ stat.AddOutput(status.NewCriticalPathLogger(log, buildCtx.CriticalPath))
stat.AddOutput(status.NewBuildProgressLog(log, filepath.Join(logsDir, logsPrefix+"build_progress.pb")))
buildCtx.Verbosef("Detected %.3v GB total RAM", float32(config.TotalRAM())/(1024*1024*1024))
diff --git a/cmd/zip2zip/zip2zip.go b/cmd/zip2zip/zip2zip.go
index 491267b..5ab9656 100644
--- a/cmd/zip2zip/zip2zip.go
+++ b/cmd/zip2zip/zip2zip.go
@@ -128,12 +128,6 @@
}
for _, arg := range args {
- // Reserve escaping for future implementation, so make sure no
- // one is using \ and expecting a certain behavior.
- if strings.Contains(arg, "\\") {
- return fmt.Errorf("\\ characters are not currently supported")
- }
-
input, output := includeSplit(arg)
var includeMatches []pair
diff --git a/cmd/zip2zip/zip2zip_test.go b/cmd/zip2zip/zip2zip_test.go
index 2c4e005..c238098 100644
--- a/cmd/zip2zip/zip2zip_test.go
+++ b/cmd/zip2zip/zip2zip_test.go
@@ -38,13 +38,6 @@
storedFiles []string
err error
}{
- {
- name: "unsupported \\",
-
- args: []string{"a\\b:b"},
-
- err: fmt.Errorf("\\ characters are not currently supported"),
- },
{ // This is modelled after the update package build rules in build/make/core/Makefile
name: "filter globs",
@@ -406,6 +399,13 @@
"b/a/b",
},
},
+ {
+ name: "escaping",
+
+ inputFiles: []string{"a"},
+ args: []string{"\\a"},
+ outputFiles: []string{"a"},
+ },
}
func errorString(e error) string {
diff --git a/cuj/cuj.go b/cuj/cuj.go
index 869e0f7..de6f10d 100644
--- a/cuj/cuj.go
+++ b/cuj/cuj.go
@@ -94,7 +94,7 @@
stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, "verbose.log")))
stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, "error.log")))
stat.AddOutput(status.NewProtoErrorLog(log, filepath.Join(logsDir, "build_error")))
- stat.AddOutput(status.NewCriticalPath(log))
+ stat.AddOutput(status.NewCriticalPathLogger(log, nil))
defer met.Dump(filepath.Join(logsDir, "soong_metrics"))
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index dcd7fdc..6817dce 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -617,7 +617,7 @@
return true
}
-func generatePrebuiltSnapshot(s snapshot.SnapshotSingleton, ctx android.SingletonContext, snapshotArchDir string) android.Paths {
+func generatePrebuiltSnapshot(s snapshot.SnapshotSingleton, ctx android.SingletonContext, snapshotArchDir string) snapshot.SnapshotPaths {
/*
Snapshot zipped artifacts directory structure for etc modules:
{SNAPSHOT_ARCH}/
@@ -631,7 +631,7 @@
(notice files)
*/
var snapshotOutputs android.Paths
- noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
+ var snapshotNotices android.Paths
installedNotices := make(map[string]bool)
ctx.VisitAllModules(func(module android.Module) {
@@ -651,7 +651,7 @@
prop := snapshot.SnapshotJsonFlags{}
propOut := snapshotLibOut + ".json"
- prop.ModuleName = m.BaseModuleName()
+ prop.InitBaseSnapshotProps(m)
if m.subdirProperties.Relative_install_path != nil {
prop.RelativeInstallPath = *m.subdirProperties.Relative_install_path
}
@@ -667,27 +667,16 @@
}
snapshotOutputs = append(snapshotOutputs, snapshot.WriteStringToFileRule(ctx, string(j), propOut))
- if len(m.EffectiveLicenseFiles()) > 0 {
- noticeName := ctx.ModuleName(m) + ".txt"
- noticeOut := filepath.Join(noticeDir, noticeName)
- // skip already copied notice file
- if !installedNotices[noticeOut] {
- installedNotices[noticeOut] = true
-
- noticeOutPath := android.PathForOutput(ctx, noticeOut)
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Cat,
- Inputs: m.EffectiveLicenseFiles(),
- Output: noticeOutPath,
- Description: "combine notices for " + noticeOut,
- })
- snapshotOutputs = append(snapshotOutputs, noticeOutPath)
+ for _, notice := range m.EffectiveLicenseFiles() {
+ if _, ok := installedNotices[notice.String()]; !ok {
+ installedNotices[notice.String()] = true
+ snapshotNotices = append(snapshotNotices, notice)
}
}
})
- return snapshotOutputs
+ return snapshot.SnapshotPaths{OutputFiles: snapshotOutputs, NoticeFiles: snapshotNotices}
}
// For Bazel / bp2build
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 25b8fe8..023c69a 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -22,6 +22,7 @@
"strings"
"android/soong/android"
+ "android/soong/cc"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -498,3 +499,11 @@
}
return fmt.Sprintf("%x", h.Sum(nil))
}
+
+// Base cc.UseCoverage
+
+var _ cc.UseCoverage = (*filesystem)(nil)
+
+func (*filesystem) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool {
+ return ctx.Device() && ctx.DeviceConfig().NativeCoverageEnabled()
+}
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index a65d9dd..aef4756 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -20,6 +20,9 @@
"android/soong/android"
"android/soong/cc"
+ "android/soong/etc"
+
+ "github.com/google/blueprint/proptools"
)
func TestMain(m *testing.M) {
@@ -28,6 +31,7 @@
var fixture = android.GroupFixturePreparers(
android.PrepareForIntegrationTestWithAndroid,
+ etc.PrepareForTestWithPrebuiltEtc,
cc.PrepareForIntegrationTestWithCc,
PrepareForTestWithFilesystemBuildComponents,
)
@@ -225,3 +229,56 @@
inputs.Strings(),
"out/soong/.intermediates/libbar/android_arm64_armv8-a_shared/libbar.so")
}
+
+func TestFileSystemWithCoverageVariants(t *testing.T) {
+ context := android.GroupFixturePreparers(
+ fixture,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.GcovCoverage = proptools.BoolPtr(true)
+ variables.Native_coverage = proptools.BoolPtr(true)
+ }),
+ )
+
+ result := context.RunTestWithBp(t, `
+ prebuilt_etc {
+ name: "prebuilt",
+ src: ":myfilesystem",
+ }
+
+ android_system_image {
+ name: "myfilesystem",
+ deps: [
+ "libfoo",
+ ],
+ linker_config_src: "linker.config.json",
+ }
+
+ cc_library {
+ name: "libfoo",
+ shared_libs: [
+ "libbar",
+ ],
+ stl: "none",
+ }
+
+ cc_library {
+ name: "libbar",
+ stl: "none",
+ }
+ `)
+
+ filesystem := result.ModuleForTests("myfilesystem", "android_common_cov")
+ inputs := filesystem.Output("deps.zip").Implicits
+ android.AssertStringListContains(t, "filesystem should have libfoo(cov)",
+ inputs.Strings(),
+ "out/soong/.intermediates/libfoo/android_arm64_armv8-a_shared_cov/libfoo.so")
+ android.AssertStringListContains(t, "filesystem should have libbar(cov)",
+ inputs.Strings(),
+ "out/soong/.intermediates/libbar/android_arm64_armv8-a_shared_cov/libbar.so")
+
+ filesystemOutput := filesystem.Output("myfilesystem.img").Output
+ prebuiltInput := result.ModuleForTests("prebuilt", "android_arm64_armv8-a").Rule("Cp").Input
+ if filesystemOutput != prebuiltInput {
+ t.Error("prebuilt should use cov variant of filesystem")
+ }
+}
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index 8175a37..f76529d 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -338,6 +338,8 @@
IsJni *bool `json:"is_jni,omitempty"`
// List of modules for monitoring coverage drops in directories (e.g. "libicu")
Target_modules []string `json:"target_modules,omitempty"`
+ // Specifies a bug assignee to replace default ISE assignment
+ Triage_assignee string `json:"triage_assignee,omitempty"`
}
type FuzzFrameworks struct {
diff --git a/genrule/genrule.go b/genrule/genrule.go
index f5da50e..00adb70 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -940,7 +940,7 @@
}
}
- tags := android.ApexAvailableTags(m)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
if ctx.ModuleType() == "gensrcs" {
// The Output_extension prop is not in an immediately accessible field
diff --git a/go.mod b/go.mod
index a5d9dd5..4a511c5 100644
--- a/go.mod
+++ b/go.mod
@@ -6,4 +6,5 @@
github.com/google/blueprint v0.0.0
google.golang.org/protobuf v0.0.0
prebuilts/bazel/common/proto/analysis_v2 v0.0.0
+ go.starlark.net v0.0.0
)
diff --git a/go.work b/go.work
index 737a9df..67f6549 100644
--- a/go.work
+++ b/go.work
@@ -4,6 +4,7 @@
.
../../external/go-cmp
../../external/golang-protobuf
+ ../../external/starlark-go
../../prebuilts/bazel/common/proto/analysis_v2
../../prebuilts/bazel/common/proto/build
../blueprint
@@ -16,4 +17,5 @@
google.golang.org/protobuf v0.0.0 => ../../external/golang-protobuf
prebuilts/bazel/common/proto/analysis_v2 v0.0.0 => ../../prebuilts/bazel/common/proto/analysis_v2
prebuilts/bazel/common/proto/build v0.0.0 => ../../prebuilts/bazel/common/proto/build
+ go.starlark.net v0.0.0 => ../../external/starlark-go
)
diff --git a/java/aar.go b/java/aar.go
index 7c45efe..f1b137d 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -220,12 +220,12 @@
linkDeps = append(linkDeps, assetDeps...)
// Returns the effective version for {min|target}_sdk_version
- effectiveVersionString := func(sdkVersion android.SdkSpec, minSdkVersion android.SdkSpec) string {
+ effectiveVersionString := func(sdkVersion android.SdkSpec, minSdkVersion android.ApiLevel) string {
// If {min|target}_sdk_version is current, use sdk_version to determine the effective level
// This is necessary for vendor modules.
// The effective version does not _only_ depend on {min|target}_sdk_version(level),
// but also on the sdk_version (kind+level)
- if minSdkVersion.ApiLevel.IsCurrent() {
+ if minSdkVersion.IsCurrent() {
ret, err := sdkVersion.EffectiveVersionString(ctx)
if err != nil {
ctx.ModuleErrorf("invalid sdk_version: %s", err)
@@ -689,7 +689,7 @@
jniPackages android.Paths
sdkVersion android.SdkSpec
- minSdkVersion android.SdkSpec
+ minSdkVersion android.ApiLevel
}
var _ android.OutputFileProducer = (*AARImport)(nil)
@@ -714,19 +714,19 @@
return ""
}
-func (a *AARImport) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+func (a *AARImport) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
if a.properties.Min_sdk_version != nil {
- return android.SdkSpecFrom(ctx, *a.properties.Min_sdk_version)
+ return android.ApiLevelFrom(ctx, *a.properties.Min_sdk_version)
}
- return a.SdkVersion(ctx)
+ return a.SdkVersion(ctx).ApiLevel
}
-func (a *AARImport) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
- return android.SdkSpecFrom(ctx, "")
+func (a *AARImport) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
+ return android.SdkSpecFrom(ctx, "").ApiLevel
}
-func (a *AARImport) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
- return a.SdkVersion(ctx)
+func (a *AARImport) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+ return a.SdkVersion(ctx).ApiLevel
}
func (a *AARImport) javaVersion() string {
@@ -1015,9 +1015,10 @@
}
type bazelAndroidLibraryImport struct {
- Aar bazel.Label
- Deps bazel.LabelListAttribute
- Exports bazel.LabelListAttribute
+ Aar bazel.Label
+ Deps bazel.LabelListAttribute
+ Exports bazel.LabelListAttribute
+ Sdk_version bazel.StringAttribute
}
func (a *aapt) convertAaptAttrsWithBp2Build(ctx android.TopDownMutatorContext) *bazelAapt {
@@ -1059,28 +1060,35 @@
},
android.CommonAttributes{Name: name},
&bazelAndroidLibraryImport{
- Aar: aars.Includes[0],
- Deps: bazel.MakeLabelListAttribute(deps),
- Exports: bazel.MakeLabelListAttribute(exports),
+ Aar: aars.Includes[0],
+ Deps: bazel.MakeLabelListAttribute(deps),
+ Exports: bazel.MakeLabelListAttribute(exports),
+ Sdk_version: bazel.StringAttribute{Value: a.properties.Sdk_version},
},
)
neverlink := true
ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "android_library",
- Bzl_load_location: "//build/bazel/rules/android:rules.bzl",
- },
+ AndroidLibraryBazelTargetModuleProperties(),
android.CommonAttributes{Name: name + "-neverlink"},
&bazelAndroidLibrary{
javaLibraryAttributes: &javaLibraryAttributes{
Neverlink: bazel.BoolAttribute{Value: &neverlink},
Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
+ javaCommonAttributes: &javaCommonAttributes{
+ Sdk_version: bazel.StringAttribute{Value: a.properties.Sdk_version},
+ },
},
},
)
}
+func AndroidLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties {
+ return bazel.BazelTargetModuleProperties{
+ Rule_class: "android_library",
+ Bzl_load_location: "//build/bazel/rules/android:rules.bzl",
+ }
+}
func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
commonAttrs, bp2buildInfo := a.convertLibraryAttrsBp2Build(ctx)
@@ -1093,10 +1101,7 @@
ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
}
name := a.Name()
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "android_library",
- Bzl_load_location: "//build/bazel/rules/android:rules.bzl",
- }
+ props := AndroidLibraryBazelTargetModuleProperties()
ctx.CreateBazelTargetModule(
props,
@@ -1119,6 +1124,10 @@
javaLibraryAttributes: &javaLibraryAttributes{
Neverlink: bazel.BoolAttribute{Value: &neverlink},
Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
+ javaCommonAttributes: &javaCommonAttributes{
+ Sdk_version: bazel.StringAttribute{Value: a.deviceProperties.Sdk_version},
+ Java_version: bazel.StringAttribute{Value: a.properties.Java_version},
+ },
},
},
)
diff --git a/java/android_manifest.go b/java/android_manifest.go
index f6457a0..f2ebfa6 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -44,14 +44,14 @@
// 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, params ManifestFixerParams) string {
- targetSdkVersionSpec := params.SdkContext.TargetSdkVersion(ctx)
+ targetSdkVersionLevel := params.SdkContext.TargetSdkVersion(ctx)
// Check if we want to return 10000
// TODO(b/240294501): Determine the rules for handling test apexes
- if shouldReturnFinalOrFutureInt(ctx, targetSdkVersionSpec, params.EnforceDefaultTargetSdkVersion) {
+ if shouldReturnFinalOrFutureInt(ctx, targetSdkVersionLevel, params.EnforceDefaultTargetSdkVersion) {
return strconv.Itoa(android.FutureApiLevel.FinalOrFutureInt())
}
- targetSdkVersion, err := targetSdkVersionSpec.EffectiveVersionString(ctx)
+ targetSdkVersion, err := targetSdkVersionLevel.EffectiveVersionString(ctx)
if err != nil {
ctx.ModuleErrorf("invalid targetSdkVersion: %s", err)
}
@@ -62,11 +62,13 @@
// 1. The module is built in unbundled mode (TARGET_BUILD_APPS not empty)
// 2. The module is run as part of MTS, and should be testable on stable branches
// Do not return 10000 if we are enforcing default targetSdkVersion and sdk has been finalised
-func shouldReturnFinalOrFutureInt(ctx android.ModuleContext, targetSdkVersionSpec android.SdkSpec, enforceDefaultTargetSdkVersion bool) bool {
- if enforceDefaultTargetSdkVersion && ctx.Config().PlatformSdkFinal() {
+func shouldReturnFinalOrFutureInt(ctx android.ModuleContext, targetSdkVersionLevel android.ApiLevel, enforceDefaultTargetSdkVersion bool) bool {
+ // If this is a REL branch, do not return 10000
+ if ctx.Config().PlatformSdkFinal() {
return false
}
- return targetSdkVersionSpec.ApiLevel.IsPreview() && (ctx.Config().UnbundledBuildApps() || includedInMts(ctx.Module()))
+ // If this a module targeting an unreleased SDK (MTS or unbundled builds), return 10000
+ return targetSdkVersionLevel.IsPreview() && (ctx.Config().UnbundledBuildApps() || includedInMts(ctx.Module()))
}
// Helper function that casts android.Module to java.androidTestApp
diff --git a/java/androidmk.go b/java/androidmk.go
index a4dac80..148d7c2 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -733,3 +733,22 @@
},
}
}
+
+func (al *ApiLibrary) AndroidMkEntries() []android.AndroidMkEntries {
+ var entriesList []android.AndroidMkEntries
+
+ entriesList = append(entriesList, android.AndroidMkEntries{
+ Class: "JAVA_LIBRARIES",
+ OutputFile: android.OptionalPathForPath(al.stubsJar),
+ Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true)
+ entries.SetPath("LOCAL_SOONG_CLASSES_JAR", al.stubsJar)
+ entries.SetPath("LOCAL_SOONG_HEADER_JAR", al.stubsJar)
+ },
+ },
+ })
+
+ return entriesList
+}
diff --git a/java/app.go b/java/app.go
index f596673..7bb8cdb 100755
--- a/java/app.go
+++ b/java/app.go
@@ -752,7 +752,7 @@
type appDepsInterface interface {
SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec
- MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec
+ MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel
RequiresStableAPIs(ctx android.BaseModuleContext) bool
}
@@ -865,10 +865,10 @@
} else {
toMinSdkVersion := "(no version)"
if m, ok := to.(interface {
- MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec
+ MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel
}); ok {
- if v := m.MinSdkVersion(ctx); !v.ApiLevel.IsNone() {
- toMinSdkVersion = v.ApiLevel.String()
+ if v := m.MinSdkVersion(ctx); !v.IsNone() {
+ toMinSdkVersion = v.String()
}
} else if m, ok := to.(interface{ MinSdkVersion() string }); ok {
// TODO(b/175678607) eliminate the use of MinSdkVersion returning
@@ -1461,10 +1461,8 @@
// verifyUsesLibrariesAPK checks the <uses-library> tags in the manifest of an APK against the build
// system and returns the path to a copy of the APK.
-func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path) android.Path {
+func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path) {
u.verifyUsesLibraries(ctx, apk, nil) // for APKs manifest_check does not write output file
- outputFile := android.PathForModuleOut(ctx, "verify_uses_libraries", apk.Base())
- return outputFile
}
// For Bazel / bp2build
@@ -1495,6 +1493,10 @@
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
}
+type manifestValueAttribute struct {
+ MinSdkVersion *string
+}
+
type bazelAndroidAppAttributes struct {
*javaCommonAttributes
*bazelAapt
@@ -1502,6 +1504,7 @@
Custom_package *string
Certificate bazel.LabelAttribute
Certificate_name bazel.StringAttribute
+ Manifest_values *manifestValueAttribute
}
// ConvertWithBp2build is used to convert android_app to Bazel.
@@ -1516,11 +1519,23 @@
certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableAppProperties.Certificate)
+ manifestValues := &manifestValueAttribute{}
+ // TODO(b/274474008 ): Directly convert deviceProperties.Min_sdk_version in bp2build
+ // MinSdkVersion(ctx) calls SdkVersion(ctx) if no value for min_sdk_version is set
+ minSdkVersion := a.MinSdkVersion(ctx)
+ if !minSdkVersion.IsPreview() && !minSdkVersion.IsInvalid() {
+ minSdkStr, err := minSdkVersion.EffectiveVersionString(ctx)
+ if err == nil {
+ manifestValues.MinSdkVersion = &minSdkStr
+ }
+ }
+
appAttrs := &bazelAndroidAppAttributes{
// TODO(b/209576404): handle package name override by product variable PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES
Custom_package: a.overridableAppProperties.Package_name,
Certificate: certificate,
Certificate_name: certificateName,
+ Manifest_values: manifestValues,
}
props := bazel.BazelTargetModuleProperties{
@@ -1535,10 +1550,7 @@
} else {
ktName := a.Name() + "_kt"
ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "android_library",
- Bzl_load_location: "//build/bazel/rules/android:rules.bzl",
- },
+ AndroidLibraryBazelTargetModuleProperties(),
android.CommonAttributes{Name: ktName},
&bazelAndroidLibrary{
javaLibraryAttributes: &javaLibraryAttributes{
@@ -1551,6 +1563,9 @@
appAttrs.bazelAapt = &bazelAapt{Manifest: aapt.Manifest}
appAttrs.Deps = bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + ktName})
+ appAttrs.javaCommonAttributes = &javaCommonAttributes{
+ Sdk_version: commonAttrs.Sdk_version,
+ }
}
ctx.CreateBazelTargetModule(
diff --git a/java/app_import.go b/java/app_import.go
index e24e780..bfd6767 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -17,9 +17,10 @@
// This file contains the module implementations for android_app_import and android_test_import.
import (
- "github.com/google/blueprint"
"reflect"
+ "github.com/google/blueprint"
+
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -48,6 +49,17 @@
CommandDeps: []string{"${config.Zip2ZipCmd}"},
Description: "Uncompress dex files",
})
+
+ checkJniAndDexLibsAreUncompressedRule = pctx.AndroidStaticRule("check-jni-and-dex-libs-are-uncompressed", blueprint.RuleParams{
+ // grep -v ' stor ' will search for lines that don't have ' stor '. stor means the file is stored uncompressed
+ Command: "if (zipinfo $in 'lib/*.so' '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then " +
+ "echo $in: Contains compressed JNI libraries and/or dex files >&2;" +
+ "exit 1; " +
+ "else " +
+ "touch $out; " +
+ "fi",
+ Description: "Check for compressed JNI libs or dex files",
+ })
)
func RegisterAppImportBuildComponents(ctx android.RegistrationContext) {
@@ -72,8 +84,6 @@
usesLibrary usesLibrary
- preprocessed bool
-
installPath android.InstallPath
hideApexVariantFromMake bool
@@ -127,6 +137,13 @@
// Optional. Install to a subdirectory of the default install path for the module
Relative_install_path *string
+
+ // Whether the prebuilt apk can be installed without additional processing. Default is false.
+ Preprocessed *bool
+
+ // Whether or not to skip checking the preprocessed apk for proper alignment and uncompressed
+ // JNI libs and dex files. Default is false
+ Skip_preprocessed_apk_checks *bool
}
func (a *AndroidAppImport) IsInstallable() bool {
@@ -177,10 +194,6 @@
}
}
-func (a *AndroidAppImport) isPrebuiltFrameworkRes() bool {
- return a.Name() == "prebuilt_framework-res"
-}
-
func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) {
cert := android.SrcIsModule(String(a.properties.Certificate))
if cert != "" {
@@ -197,14 +210,14 @@
}
}
- a.usesLibrary.deps(ctx, !a.isPrebuiltFrameworkRes())
+ a.usesLibrary.deps(ctx, true)
}
func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) {
// Test apps don't need their JNI libraries stored uncompressed. As a matter of fact, messing
// with them may invalidate pre-existing signature data.
- if ctx.InstallInTestcases() && (Bool(a.properties.Presigned) || a.preprocessed) {
+ if ctx.InstallInTestcases() && (Bool(a.properties.Presigned) || Bool(a.properties.Preprocessed)) {
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
Output: outputPath,
@@ -222,7 +235,7 @@
// Returns whether this module should have the dex file stored uncompressed in the APK.
func (a *AndroidAppImport) shouldUncompressDex(ctx android.ModuleContext) bool {
- if ctx.Config().UnbundledBuild() || a.preprocessed {
+ if ctx.Config().UnbundledBuild() || proptools.Bool(a.properties.Preprocessed) {
return false
}
@@ -243,6 +256,10 @@
}
func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext) {
+ if a.Name() == "prebuilt_framework-res" {
+ ctx.ModuleErrorf("prebuilt_framework-res found. This used to have special handling in soong, but was removed due to prebuilt_framework-res no longer existing. This check is to ensure it doesn't come back without readding the special handling.")
+ }
+
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
if !apexInfo.IsForPlatform() {
a.hideApexVariantFromMake = true
@@ -278,14 +295,7 @@
var pathFragments []string
relInstallPath := String(a.properties.Relative_install_path)
- if a.isPrebuiltFrameworkRes() {
- // framework-res.apk is installed as system/framework/framework-res.apk
- if relInstallPath != "" {
- ctx.PropertyErrorf("relative_install_path", "Relative_install_path cannot be set for framework-res")
- }
- pathFragments = []string{"framework"}
- a.preprocessed = true
- } else if Bool(a.properties.Privileged) {
+ if Bool(a.properties.Privileged) {
pathFragments = []string{"priv-app", relInstallPath, a.BaseModuleName()}
} else if ctx.InstallInTestcases() {
pathFragments = []string{relInstallPath, a.BaseModuleName(), ctx.DeviceConfig().DeviceArch()}
@@ -303,7 +313,7 @@
a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
if a.usesLibrary.enforceUsesLibraries() {
- srcApk = a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
+ a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
}
a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
@@ -323,14 +333,15 @@
// Sign or align the package if package has not been preprocessed
- if a.isPrebuiltFrameworkRes() {
- a.outputFile = srcApk
- a.certificate, certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
- if len(certificates) != 1 {
- ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates)
- }
- } else if a.preprocessed {
- a.outputFile = srcApk
+ if proptools.Bool(a.properties.Preprocessed) {
+ output := srcApk
+ // TODO(b/185811447) Uncomment this after all existing failing apks set skip_preprocessed_apk_checks: true
+ //if !proptools.Bool(a.properties.Skip_preprocessed_apk_checks) {
+ // writableOutput := android.PathForModuleOut(ctx, "validated-prebuilt", apkFilename)
+ // a.validatePreprocessedApk(ctx, srcApk, writableOutput)
+ // output = writableOutput
+ //}
+ a.outputFile = output
a.certificate = PresignedCertificate
} else if !Bool(a.properties.Presigned) {
// If the certificate property is empty at this point, default_dev_cert must be set to true.
@@ -364,6 +375,30 @@
// TODO: androidmk converter jni libs
}
+func (a *AndroidAppImport) validatePreprocessedApk(ctx android.ModuleContext, srcApk android.Path, dstApk android.WritablePath) {
+ alignmentStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "alignment.stamp")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: checkZipAlignment,
+ Input: srcApk,
+ Output: alignmentStamp,
+ })
+ compressionStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "compression.stamp")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: checkJniAndDexLibsAreUncompressedRule,
+ Input: srcApk,
+ Output: compressionStamp,
+ })
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: srcApk,
+ Output: dstApk,
+ Validations: []android.Path{
+ alignmentStamp,
+ compressionStamp,
+ },
+ })
+}
+
func (a *AndroidAppImport) Prebuilt() *android.Prebuilt {
return &a.prebuilt
}
@@ -426,8 +461,8 @@
return android.SdkSpecPrivate
}
-func (a *AndroidAppImport) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
- return android.SdkSpecPrivate
+func (a *AndroidAppImport) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+ return android.SdkSpecPrivate.ApiLevel
}
func (a *AndroidAppImport) LintDepSets() LintDepSets {
@@ -499,11 +534,6 @@
return module
}
-type androidTestImportProperties struct {
- // Whether the prebuilt apk can be installed without additional processing. Default is false.
- Preprocessed *bool
-}
-
type AndroidTestImport struct {
AndroidAppImport
@@ -520,14 +550,10 @@
Per_testcase_directory *bool
}
- testImportProperties androidTestImportProperties
-
data android.Paths
}
func (a *AndroidTestImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- a.preprocessed = Bool(a.testImportProperties.Preprocessed)
-
a.generateAndroidBuildActions(ctx)
a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
@@ -544,7 +570,6 @@
module.AddProperties(&module.properties)
module.AddProperties(&module.dexpreoptProperties)
module.AddProperties(&module.testProperties)
- module.AddProperties(&module.testImportProperties)
module.populateAllVariantStructs()
android.AddLoadHook(module, func(ctx android.LoadHookContext) {
module.processVariants(ctx)
diff --git a/java/app_import_test.go b/java/app_import_test.go
index 528fffe..845a962 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -505,67 +505,6 @@
}
}
-func TestAndroidAppImport_frameworkRes(t *testing.T) {
- ctx, _ := testJava(t, `
- android_app_import {
- name: "framework-res",
- certificate: "platform",
- apk: "package-res.apk",
- prefer: true,
- export_package_resources: true,
- // Disable dexpreopt and verify_uses_libraries check as the app
- // contains no Java code to be dexpreopted.
- enforce_uses_libs: false,
- dex_preopt: {
- enabled: false,
- },
- }
- `)
-
- mod := ctx.ModuleForTests("prebuilt_framework-res", "android_common").Module()
- a := mod.(*AndroidAppImport)
-
- if !a.preprocessed {
- t.Errorf("prebuilt framework-res is not preprocessed")
- }
-
- expectedInstallPath := "out/soong/target/product/test_device/system/framework/framework-res.apk"
-
- android.AssertPathRelativeToTopEquals(t, "prebuilt framework-res install location", expectedInstallPath, a.dexpreopter.installPath)
-
- entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
-
- expectedPath := "."
- // From apk property above, in the root of the source tree.
- expectedPrebuiltModuleFile := "package-res.apk"
- // Verify that the apk is preprocessed: The export package is the same
- // as the prebuilt.
- expectedSoongResourceExportPackage := expectedPrebuiltModuleFile
-
- actualPath := entries.EntryMap["LOCAL_PATH"]
- actualPrebuiltModuleFile := entries.EntryMap["LOCAL_PREBUILT_MODULE_FILE"]
- actualSoongResourceExportPackage := entries.EntryMap["LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE"]
-
- if len(actualPath) != 1 {
- t.Errorf("LOCAL_PATH incorrect len %d", len(actualPath))
- } else if actualPath[0] != expectedPath {
- t.Errorf("LOCAL_PATH mismatch, actual: %s, expected: %s", actualPath[0], expectedPath)
- }
-
- if len(actualPrebuiltModuleFile) != 1 {
- t.Errorf("LOCAL_PREBUILT_MODULE_FILE incorrect len %d", len(actualPrebuiltModuleFile))
- } else if actualPrebuiltModuleFile[0] != expectedPrebuiltModuleFile {
- t.Errorf("LOCAL_PREBUILT_MODULE_FILE mismatch, actual: %s, expected: %s", actualPrebuiltModuleFile[0], expectedPrebuiltModuleFile)
- }
-
- if len(actualSoongResourceExportPackage) != 1 {
- t.Errorf("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE incorrect len %d", len(actualSoongResourceExportPackage))
- } else if actualSoongResourceExportPackage[0] != expectedSoongResourceExportPackage {
- t.Errorf("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE mismatch, actual: %s, expected: %s", actualSoongResourceExportPackage[0], expectedSoongResourceExportPackage)
- }
- android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "android_app_import", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
-}
-
func TestAndroidAppImport_relativeInstallPath(t *testing.T) {
bp := `
android_app_import {
@@ -582,13 +521,6 @@
}
android_app_import {
- name: "framework-res",
- apk: "prebuilts/apk/app.apk",
- presigned: true,
- prefer: true,
- }
-
- android_app_import {
name: "privileged_relative_install_path",
apk: "prebuilts/apk/app.apk",
presigned: true,
@@ -612,11 +544,6 @@
errorMessage: "Install path is not correct for app when relative_install_path is present",
},
{
- name: "prebuilt_framework-res",
- expectedInstallPath: "out/soong/target/product/test_device/system/framework/framework-res.apk",
- errorMessage: "Install path is not correct for framework-res",
- },
- {
name: "privileged_relative_install_path",
expectedInstallPath: "out/soong/target/product/test_device/system/priv-app/my/path/privileged_relative_install_path/privileged_relative_install_path.apk",
errorMessage: "Install path is not correct for privileged app when relative_install_path is present",
@@ -730,6 +657,30 @@
}
}
+// TODO(b/185811447) Uncomment this after all existing failing apks set skip_preprocessed_apk_checks: true
+//func TestAndroidAppImport_Preprocessed(t *testing.T) {
+// ctx, _ := testJava(t, `
+// android_app_import {
+// name: "foo",
+// apk: "prebuilts/apk/app.apk",
+// presigned: true,
+// preprocessed: true,
+// }
+// `)
+//
+// apkName := "foo.apk"
+// variant := ctx.ModuleForTests("foo", "android_common")
+// outputBuildParams := variant.Output("validated-prebuilt/" + apkName).BuildParams
+// if outputBuildParams.Rule.String() != android.Cp.String() {
+// t.Errorf("Unexpected prebuilt android_app_import rule: " + outputBuildParams.Rule.String())
+// }
+//
+// // Make sure compression and aligning were validated.
+// if len(outputBuildParams.Validations) != 2 {
+// t.Errorf("Expected compression/alignment validation rules, found %d validations", len(outputBuildParams.Validations))
+// }
+//}
+
func TestAndroidTestImport_UncompressDex(t *testing.T) {
testCases := []struct {
name string
diff --git a/java/app_set.go b/java/app_set.go
index 0f55b77..d2d3b06 100644
--- a/java/app_set.go
+++ b/java/app_set.go
@@ -142,6 +142,7 @@
"allow-prereleased": strconv.FormatBool(proptools.Bool(as.properties.Prerelease)),
"screen-densities": screenDensities,
"sdk-version": ctx.Config().PlatformSdkVersion().String(),
+ "skip-sdk-check": strconv.FormatBool(ctx.Config().IsEnvTrue("SOONG_SKIP_APPSET_SDK_CHECK")),
"stem": as.BaseModuleName(),
"apkcerts": as.apkcertsFile.String(),
"partition": as.PartitionTag(ctx.DeviceConfig()),
diff --git a/java/app_set_test.go b/java/app_set_test.go
index 03eb667..10bc5de 100644
--- a/java/app_set_test.go
+++ b/java/app_set_test.go
@@ -89,6 +89,7 @@
"allow-prereleased": "false",
"screen-densities": "LDPI,XXHDPI",
"sdk-version": "29",
+ "skip-sdk-check": "false",
"stem": "foo",
},
},
@@ -105,6 +106,7 @@
"allow-prereleased": "false",
"screen-densities": "all",
"sdk-version": "30",
+ "skip-sdk-check": "false",
"stem": "foo",
},
},
diff --git a/java/app_test.go b/java/app_test.go
index 5b16cea..7e97b0f 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -3034,11 +3034,13 @@
func TestTargetSdkVersionManifestFixer(t *testing.T) {
platform_sdk_codename := "Tiramisu"
+ platform_sdk_version := 33
testCases := []struct {
name string
targetSdkVersionInBp string
targetSdkVersionExpected string
unbundledBuild bool
+ platformSdkFinal bool
}{
{
name: "Non-Unbundled build: Android.bp has targetSdkVersion",
@@ -3075,20 +3077,34 @@
targetSdkVersionExpected: "10000",
unbundledBuild: true,
},
+ {
+ name: "Bundled build in REL branches",
+ targetSdkVersionExpected: "33",
+ unbundledBuild: false,
+ platformSdkFinal: true,
+ },
}
for _, testCase := range testCases {
+ targetSdkVersionTemplate := ""
+ if testCase.targetSdkVersionInBp != "" {
+ targetSdkVersionTemplate = fmt.Sprintf(`target_sdk_version: "%s",`, testCase.targetSdkVersionInBp)
+ }
bp := fmt.Sprintf(`
android_app {
name: "foo",
sdk_version: "current",
- target_sdk_version: "%v",
+ %s
}
- `, testCase.targetSdkVersionInBp)
+ `, targetSdkVersionTemplate)
fixture := android.GroupFixturePreparers(
prepareForJavaTest,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ if testCase.platformSdkFinal {
+ variables.Platform_sdk_final = proptools.BoolPtr(true)
+ }
// explicitly set platform_sdk_codename to make the test deterministic
variables.Platform_sdk_codename = &platform_sdk_codename
+ variables.Platform_sdk_version = &platform_sdk_version
variables.Platform_version_active_codenames = []string{platform_sdk_codename}
// create a non-empty list if unbundledBuild==true
if testCase.unbundledBuild {
@@ -3161,16 +3177,20 @@
},
}
for _, testCase := range testCases {
+ targetSdkVersionTemplate := ""
+ if testCase.targetSdkVersionInBp != nil {
+ targetSdkVersionTemplate = fmt.Sprintf(`target_sdk_version: "%s",`, *testCase.targetSdkVersionInBp)
+ }
bp := fmt.Sprintf(`
android_app {
name: "foo",
sdk_version: "current",
min_sdk_version: "29",
- target_sdk_version: "%v",
+ %s
updatable: %t,
enforce_default_target_sdk_version: %t
}
- `, proptools.String(testCase.targetSdkVersionInBp), testCase.updatable, testCase.updatable) // enforce default target sdk version if app is updatable
+ `, targetSdkVersionTemplate, testCase.updatable, testCase.updatable) // enforce default target sdk version if app is updatable
fixture := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
diff --git a/java/base.go b/java/base.go
index 85f4a5e..374138c 100644
--- a/java/base.go
+++ b/java/base.go
@@ -489,8 +489,8 @@
hideApexVariantFromMake bool
sdkVersion android.SdkSpec
- minSdkVersion android.SdkSpec
- maxSdkVersion android.SdkSpec
+ minSdkVersion android.ApiLevel
+ maxSdkVersion android.ApiLevel
sourceExtensions []string
}
@@ -665,34 +665,38 @@
return proptools.String(j.deviceProperties.System_modules)
}
-func (j *Module) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+func (j *Module) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
if j.deviceProperties.Min_sdk_version != nil {
- return android.SdkSpecFrom(ctx, *j.deviceProperties.Min_sdk_version)
+ return android.ApiLevelFrom(ctx, *j.deviceProperties.Min_sdk_version)
}
- return j.SdkVersion(ctx)
+ return j.SdkVersion(ctx).ApiLevel
}
-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) MaxSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+ if j.deviceProperties.Max_sdk_version != nil {
+ return android.ApiLevelFrom(ctx, *j.deviceProperties.Max_sdk_version)
+ }
+ // Default is PrivateApiLevel
+ return android.SdkSpecPrivate.ApiLevel
}
-func (j *Module) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
- replaceMaxSdkVersionPlaceholder := proptools.StringDefault(j.deviceProperties.Replace_max_sdk_version_placeholder, "")
- return android.SdkSpecFrom(ctx, replaceMaxSdkVersionPlaceholder)
+func (j *Module) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
+ if j.deviceProperties.Replace_max_sdk_version_placeholder != nil {
+ return android.ApiLevelFrom(ctx, *j.deviceProperties.Replace_max_sdk_version_placeholder)
+ }
+ // Default is PrivateApiLevel
+ return android.SdkSpecPrivate.ApiLevel
}
func (j *Module) MinSdkVersionString() string {
- return j.minSdkVersion.Raw
+ return j.minSdkVersion.String()
}
-func (j *Module) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+func (j *Module) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
if j.deviceProperties.Target_sdk_version != nil {
- return android.SdkSpecFrom(ctx, *j.deviceProperties.Target_sdk_version)
+ return android.ApiLevelFrom(ctx, *j.deviceProperties.Target_sdk_version)
}
- return j.SdkVersion(ctx)
+ return j.SdkVersion(ctx).ApiLevel
}
func (j *Module) AvailableFor(what string) bool {
@@ -881,7 +885,7 @@
j.ignoredAidlPermissionList = android.PathsForModuleSrcExcludes(ctx, exceptions, nil)
}
- aidlMinSdkVersion := j.MinSdkVersion(ctx).ApiLevel.String()
+ aidlMinSdkVersion := j.MinSdkVersion(ctx).String()
flags = append(flags, "--min_sdk_version="+aidlMinSdkVersion)
return strings.Join(flags, " "), deps
@@ -1542,9 +1546,9 @@
}
if ctx.Device() {
- lintSDKVersion := func(sdkSpec android.SdkSpec) int {
- if v := sdkSpec.ApiLevel; !v.IsPreview() {
- return v.FinalInt()
+ lintSDKVersion := func(apiLevel android.ApiLevel) int {
+ if !apiLevel.IsPreview() {
+ return apiLevel.FinalInt()
} else {
// When running metalava, we pass --version-codename. When that value
// is not REL, metalava will add 1 to the --current-version argument.
@@ -1576,7 +1580,7 @@
j.linter.classes = j.implementationJarFile
j.linter.minSdkVersion = lintSDKVersion(j.MinSdkVersion(ctx))
j.linter.targetSdkVersion = lintSDKVersion(j.TargetSdkVersion(ctx))
- j.linter.compileSdkVersion = lintSDKVersion(j.SdkVersion(ctx))
+ j.linter.compileSdkVersion = lintSDKVersion(j.SdkVersion(ctx).ApiLevel)
j.linter.compileSdkKind = j.SdkVersion(ctx).Kind
j.linter.javaLanguageLevel = flags.javaVersion.String()
j.linter.kotlinLanguageLevel = "1.3"
@@ -1846,15 +1850,14 @@
// Implements android.ApexModule
func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
sdkVersionSpec := j.SdkVersion(ctx)
- minSdkVersionSpec := j.MinSdkVersion(ctx)
- if !minSdkVersionSpec.Specified() {
+ minSdkVersion := j.MinSdkVersion(ctx)
+ if !minSdkVersion.Specified() {
return fmt.Errorf("min_sdk_version is not specified")
}
// If the module is compiling against core (via sdk_version), skip comparison check.
if sdkVersionSpec.Kind == android.SdkCore {
return nil
}
- minSdkVersion := minSdkVersionSpec.ApiLevel
if minSdkVersion.GreaterThan(sdkVersion) {
return fmt.Errorf("newer SDK(%v)", minSdkVersion)
}
@@ -1920,19 +1923,22 @@
func (m *Module) getSdkLinkType(ctx android.BaseModuleContext, name string) (ret sdkLinkType, stubs bool) {
switch name {
- case "core.current.stubs", "legacy.core.platform.api.stubs", "stable.core.platform.api.stubs",
+ case android.SdkCore.JavaLibraryName(ctx.Config()),
+ android.JavaApiLibraryName(ctx.Config(), "legacy.core.platform.api.stubs"),
+ android.JavaApiLibraryName(ctx.Config(), "stable.core.platform.api.stubs"),
"stub-annotations", "private-stub-annotations-jar",
- "core-lambda-stubs", "core-generated-annotation-stubs":
+ android.JavaApiLibraryName(ctx.Config(), "core-lambda-stubs"),
+ "core-generated-annotation-stubs":
return javaCore, true
- case "android_stubs_current":
+ case android.SdkPublic.JavaLibraryName(ctx.Config()):
return javaSdk, true
- case "android_system_stubs_current":
+ case android.SdkSystem.JavaLibraryName(ctx.Config()):
return javaSystem, true
- case "android_module_lib_stubs_current":
+ case android.SdkModule.JavaLibraryName(ctx.Config()):
return javaModule, true
- case "android_system_server_stubs_current":
+ case android.SdkSystemServer.JavaLibraryName(ctx.Config()):
return javaSystemServer, true
- case "android_test_stubs_current":
+ case android.SdkTest.JavaLibraryName(ctx.Config()):
return javaSystem, true
}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index c07a94a..f692563 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -499,6 +499,8 @@
for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
// Add a dependency onto a possibly scope specific stub library.
scopeSpecificDependency := apiScope.scopeSpecificStubModule(ctx, additionalStubModule)
+ // Use JavaApiLibraryName function to be redirected to stubs generated from .txt if applicable
+ scopeSpecificDependency = android.JavaApiLibraryName(ctx.Config(), scopeSpecificDependency)
tag := hiddenAPIStubsDependencyTag{apiScope: apiScope, fromAdditionalDependency: true}
ctx.AddVariationDependencies(nil, tag, scopeSpecificDependency)
}
diff --git a/java/builder.go b/java/builder.go
index 6f8eec9..0c57738 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -131,13 +131,13 @@
blueprint.RuleParams{
Command: `rm -rf "$out" && ` +
`${config.ExtractApksCmd} -o "${out}" -zip "${zip}" -allow-prereleased=${allow-prereleased} ` +
- `-sdk-version=${sdk-version} -abis=${abis} ` +
+ `-sdk-version=${sdk-version} -skip-sdk-check=${skip-sdk-check} -abis=${abis} ` +
`--screen-densities=${screen-densities} --stem=${stem} ` +
`-apkcerts=${apkcerts} -partition=${partition} ` +
`${in}`,
CommandDeps: []string{"${config.ExtractApksCmd}"},
},
- "abis", "allow-prereleased", "screen-densities", "sdk-version", "stem", "apkcerts", "partition", "zip")
+ "abis", "allow-prereleased", "screen-densities", "sdk-version", "skip-sdk-check", "stem", "apkcerts", "partition", "zip")
turbine, turbineRE = pctx.RemoteStaticRules("turbine",
blueprint.RuleParams{
@@ -246,6 +246,19 @@
CommandDeps: []string{"${config.ZipAlign}"},
},
)
+
+ checkZipAlignment = pctx.AndroidStaticRule("checkzipalign",
+ blueprint.RuleParams{
+ Command: "if ! ${config.ZipAlign} -c -p 4 $in > /dev/null; then " +
+ "echo $in: Improper package alignment >&2; " +
+ "exit 1; " +
+ "else " +
+ "touch $out; " +
+ "fi",
+ CommandDeps: []string{"${config.ZipAlign}"},
+ Description: "Check zip alignment",
+ },
+ )
)
func init() {
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index cf81ddb..bc9de50 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -130,17 +130,17 @@
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() {
+ if s.minSdkVersion.IsCurrent() {
jar.minSdkVersion = ctx.Config().DefaultAppTargetSdk(ctx).String()
} else {
- jar.minSdkVersion = s.minSdkVersion.ApiLevel.String()
+ jar.minSdkVersion = s.minSdkVersion.String()
}
}
if s.maxSdkVersion.Specified() {
- if s.maxSdkVersion.ApiLevel.IsCurrent() {
+ if s.maxSdkVersion.IsCurrent() {
jar.maxSdkVersion = ctx.Config().DefaultAppTargetSdk(ctx).String()
} else {
- jar.maxSdkVersion = s.maxSdkVersion.ApiLevel.String()
+ jar.maxSdkVersion = s.maxSdkVersion.String()
}
}
}
diff --git a/java/config/config.go b/java/config/config.go
index 838d007..b82a137 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -94,10 +94,14 @@
"-JXX:+TieredCompilation",
"-JXX:TieredStopAtLevel=1",
"-JDcom.android.tools.r8.emitRecordAnnotationsInDex",
+ "-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex",
+ "-JDcom.android.tools.r8.emitRecordAnnotationsExInDex",
}, dexerJavaVmFlagsList...))
exportedVars.ExportStringListStaticVariable("R8Flags", append([]string{
"-JXmx2048M",
"-JDcom.android.tools.r8.emitRecordAnnotationsInDex",
+ "-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex",
+ "-JDcom.android.tools.r8.emitRecordAnnotationsExInDex",
}, dexerJavaVmFlagsList...))
exportedVars.ExportStringListStaticVariable("CommonJdkFlags", []string{
diff --git a/java/config/makevars.go b/java/config/makevars.go
index 273aca0..d383d98 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -28,8 +28,11 @@
ctx.Strict("FRAMEWORK_LIBRARIES", strings.Join(FrameworkLibraries, " "))
// These are used by make when LOCAL_PRIVATE_PLATFORM_APIS is set (equivalent to platform_apis in blueprint):
- ctx.Strict("LEGACY_CORE_PLATFORM_BOOTCLASSPATH_LIBRARIES", strings.Join(LegacyCorePlatformBootclasspathLibraries, " "))
- ctx.Strict("LEGACY_CORE_PLATFORM_SYSTEM_MODULES", LegacyCorePlatformSystemModules)
+ ctx.Strict("LEGACY_CORE_PLATFORM_BOOTCLASSPATH_LIBRARIES",
+ strings.Join(android.JavaApiLibraryNames(ctx.Config(), LegacyCorePlatformBootclasspathLibraries), " "))
+ ctx.Strict("LEGACY_CORE_PLATFORM_SYSTEM_MODULES",
+ android.JavaApiLibraryName(ctx.Config(), LegacyCorePlatformSystemModules),
+ )
ctx.Strict("ANDROID_JAVA_HOME", "${JavaHome}")
ctx.Strict("ANDROID_JAVA8_HOME", "prebuilts/jdk/jdk8/${hostPrebuiltTag}")
diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp
index b9332dd..958f4ce 100644
--- a/java/core-libraries/Android.bp
+++ b/java/core-libraries/Android.bp
@@ -79,16 +79,25 @@
],
}
+// Defaults module to strip out android annotations
+java_defaults {
+ name: "system-modules-no-annotations",
+ sdk_version: "none",
+ system_modules: "none",
+ jarjar_rules: "jarjar-strip-annotations-rules.txt",
+}
+
// Same as core-current-stubs-for-system-modules, but android annotations are
// stripped.
java_library {
name: "core-current-stubs-for-system-modules-no-annotations",
visibility: ["//development/sdk"],
+ defaults: [
+ "system-modules-no-annotations",
+ ],
static_libs: [
"core-current-stubs-for-system-modules",
],
- sdk_version: "none",
- system_modules: "none",
dists: [
{
// Legacy dist location for the public file.
@@ -100,7 +109,6 @@
targets: dist_targets,
},
],
- jarjar_rules: "jarjar-strip-annotations-rules.txt",
}
// Used when compiling higher-level code against core.current.stubs.
@@ -158,16 +166,16 @@
java_library {
name: "core-module-lib-stubs-for-system-modules-no-annotations",
visibility: ["//visibility:private"],
+ defaults: [
+ "system-modules-no-annotations",
+ ],
static_libs: [
"core-module-lib-stubs-for-system-modules",
],
- sdk_version: "none",
- system_modules: "none",
dist: {
dest: "system-modules/module-lib/core-for-system-modules-no-annotations.jar",
targets: dist_targets,
},
- jarjar_rules: "jarjar-strip-annotations-rules.txt",
}
// Used when compiling higher-level code with sdk_version "module_current"
@@ -212,16 +220,16 @@
java_library {
name: "legacy.core.platform.api.no.annotations.stubs",
visibility: core_platform_visibility,
+ defaults: [
+ "system-modules-no-annotations",
+ ],
hostdex: true,
compile_dex: true,
- sdk_version: "none",
- system_modules: "none",
static_libs: [
"legacy.core.platform.api.stubs",
],
patch_module: "java.base",
- jarjar_rules: "jarjar-strip-annotations-rules.txt",
}
java_library {
@@ -247,16 +255,16 @@
java_library {
name: "stable.core.platform.api.no.annotations.stubs",
visibility: core_platform_visibility,
+ defaults: [
+ "system-modules-no-annotations",
+ ],
hostdex: true,
compile_dex: true,
- sdk_version: "none",
- system_modules: "none",
static_libs: [
"stable.core.platform.api.stubs",
],
patch_module: "java.base",
- jarjar_rules: "jarjar-strip-annotations-rules.txt",
}
// Used when compiling higher-level code against *.core.platform.api.stubs.
@@ -307,12 +315,6 @@
// the UnsupportedAppUsage, CorePlatformApi and IntraCoreApi
// annotations.
"art.module.api.annotations.for.system.modules",
-
- // Make nullability annotations available when compiling public stubs.
- // They are provided as a separate library because while the
- // annotations are not themselves part of the public API provided by
- // this module they are used in the stubs.
- "stub-annotations",
],
}
@@ -349,3 +351,7 @@
"art-module-intra-core-api-stubs-system-modules-lib",
],
}
+
+build = [
+ "TxtStubLibraries.bp",
+]
diff --git a/java/core-libraries/TxtStubLibraries.bp b/java/core-libraries/TxtStubLibraries.bp
new file mode 100644
index 0000000..813187e
--- /dev/null
+++ b/java/core-libraries/TxtStubLibraries.bp
@@ -0,0 +1,156 @@
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file contains java_system_modules provided by the SDK.
+// These system modules transitively depend on core stub libraries generated from .txt files.
+
+// Same as core-public-stubs-system-modules, but the stubs are generated from .txt files
+java_system_modules {
+ name: "core-public-stubs-system-modules.from-text",
+ visibility: ["//visibility:public"],
+ libs: [
+ "core-current-stubs-for-system-modules-no-annotations.from-text",
+ ],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+java_library {
+ name: "core-current-stubs-for-system-modules-no-annotations.from-text",
+ visibility: ["//visibility:private"],
+ defaults: [
+ "system-modules-no-annotations",
+ ],
+ static_libs: [
+ "core.current.stubs.from-text",
+ "core-lambda-stubs.from-text",
+ ],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+// Same as core-module-lib-stubs-system-modules, but the stubs are generated from .txt files
+java_system_modules {
+ name: "core-module-lib-stubs-system-modules.from-text",
+ visibility: ["//visibility:public"],
+ libs: [
+ "core-module-lib-stubs-for-system-modules-no-annotations.from-text",
+ ],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+java_library {
+ name: "core-module-lib-stubs-for-system-modules-no-annotations.from-text",
+ visibility: ["//visibility:private"],
+ defaults: [
+ "system-modules-no-annotations",
+ ],
+ static_libs: [
+ "core.module_lib.stubs.from-text",
+ "core-lambda-stubs.from-text",
+ ],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+java_library {
+ name: "core.module_lib.stubs.from-text",
+ static_libs: [
+ "art.module.public.api.stubs.module_lib.from-text",
+
+ // Replace the following with the module-lib correspondence when Conscrypt or i18N module
+ // provides @SystemApi(MODULE_LIBRARIES). Currently, assume that only ART module provides
+ // @SystemApi(MODULE_LIBRARIES).
+ "conscrypt.module.public.api.stubs.from-text",
+ "i18n.module.public.api.stubs.from-text",
+ ],
+ sdk_version: "none",
+ system_modules: "none",
+ visibility: ["//visibility:private"],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+// Same as legacy-core-platform-api-stubs-system-modules, but the stubs are generated from .txt files
+java_system_modules {
+ name: "legacy-core-platform-api-stubs-system-modules.from-text",
+ visibility: core_platform_visibility,
+ libs: [
+ "legacy.core.platform.api.no.annotations.stubs.from-text",
+ "core-lambda-stubs.from-text",
+ ],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+java_library {
+ name: "legacy.core.platform.api.no.annotations.stubs.from-text",
+ visibility: core_platform_visibility,
+ defaults: [
+ "system-modules-no-annotations",
+ ],
+ hostdex: true,
+ compile_dex: true,
+
+ static_libs: [
+ "legacy.core.platform.api.stubs.from-text",
+ ],
+ patch_module: "java.base",
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+// Same as stable-core-platform-api-stubs-system-modules, but the stubs are generated from .txt files
+java_system_modules {
+ name: "stable-core-platform-api-stubs-system-modules.from-text",
+ visibility: core_platform_visibility,
+ libs: [
+ "stable.core.platform.api.no.annotations.stubs.from-text",
+ "core-lambda-stubs.from-text",
+ ],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+java_library {
+ name: "stable.core.platform.api.no.annotations.stubs.from-text",
+ visibility: core_platform_visibility,
+ defaults: [
+ "system-modules-no-annotations",
+ ],
+ hostdex: true,
+ compile_dex: true,
+
+ static_libs: [
+ "stable.core.platform.api.stubs.from-text",
+ ],
+ patch_module: "java.base",
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
+
+java_api_library {
+ name: "core-lambda-stubs.from-text",
+ api_surface: "toolchain",
+ api_contributions: [
+ "art.module.toolchain.api.api.contribution",
+ ],
+ libs: [
+ // LambdaMetaFactory depends on CallSite etc. which is part of the Core API surface
+ "core.current.stubs.from-text",
+ ],
+ // TODO: Enable after stub generation from .txt file is available
+ enabled: false,
+}
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 4abdcc6..3581040 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -19,12 +19,16 @@
"io"
"android/soong/android"
+ "android/soong/bazel"
"android/soong/dexpreopt"
+
+ "github.com/google/blueprint/proptools"
)
type DeviceHostConverter struct {
android.ModuleBase
android.DefaultableModuleBase
+ android.BazelModuleBase
properties DeviceHostConverterProperties
@@ -76,6 +80,7 @@
module.AddProperties(&module.properties)
InitJavaModule(module, android.DeviceSupported)
+ android.InitBazelModule(module)
return module
}
@@ -186,3 +191,32 @@
},
}
}
+
+type bazelDeviceHostConverterAttributes struct {
+ Exports bazel.LabelListAttribute
+}
+
+func (d *DeviceHostConverter) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "java_host_for_device",
+ Bzl_load_location: "//build/bazel/rules/java:host_for_device.bzl",
+ },
+ android.CommonAttributes{Name: d.Name()},
+ &bazelDeviceHostConverterAttributes{
+ Exports: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, d.properties.Libs)),
+ },
+ )
+ neverLinkAttrs := &javaLibraryAttributes{
+ Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + d.Name()}),
+ Neverlink: bazel.BoolAttribute{Value: proptools.BoolPtr(true)},
+ javaCommonAttributes: &javaCommonAttributes{
+ Sdk_version: bazel.StringAttribute{Value: proptools.StringPtr("none")},
+ },
+ }
+ ctx.CreateBazelTargetModule(
+ javaLibraryBazelTargetModuleProperties(),
+ android.CommonAttributes{Name: d.Name() + "-neverlink"},
+ neverLinkAttrs)
+
+}
diff --git a/java/dex.go b/java/dex.go
index 7b6a99a..4d6aa34 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -343,7 +343,7 @@
type compileDexParams struct {
flags javaBuilderFlags
sdkVersion android.SdkSpec
- minSdkVersion android.SdkSpec
+ minSdkVersion android.ApiLevel
classesJar android.Path
jarName string
}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index e0a0629..0ffedf6 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -293,6 +293,12 @@
isSystemServerJar := global.AllSystemServerJars(ctx).ContainsJar(moduleName(ctx))
bootImage := defaultBootImageConfig(ctx)
+ // When `global.PreoptWithUpdatableBcp` is true, `bcpForDexpreopt` below includes the mainline
+ // boot jars into bootclasspath, so we should include the mainline boot image as well because it's
+ // generated from those jars.
+ if global.PreoptWithUpdatableBcp {
+ bootImage = mainlineBootImageConfig(ctx)
+ }
dexFiles, dexLocations := bcpForDexpreopt(ctx, global.PreoptWithUpdatableBcp)
targets := ctx.MultiTargets()
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 373b478..f4827ea 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -291,6 +291,9 @@
// The "--compiler-filter" argument.
compilerFilter string
+
+ // The "--single-image" argument.
+ singleImage bool
}
// Target-dependent description of a boot image.
@@ -398,6 +401,9 @@
for _, ext := range exts {
ret = append(ret, dir.Join(ctx, name+ext))
}
+ if image.singleImage {
+ break
+ }
}
return ret
}
@@ -768,6 +774,10 @@
cmd.FlagWithArg("--compiler-filter=", image.compilerFilter)
}
+ if image.singleImage {
+ cmd.Flag("--single-image")
+ }
+
// Use the default variant/features for host builds.
// The map below contains only device CPU info (which might be x86 on some devices).
if image.target.Os == android.Android {
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 76c78cb..8c62c33 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -44,6 +44,8 @@
bootImageConfigRawKey = android.NewOnceKey("bootImageConfigRaw")
artBootImageName = "art"
frameworkBootImageName = "boot"
+ mainlineBootImageName = "mainline"
+ bootImageStem = "boot"
)
func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig {
@@ -52,37 +54,52 @@
artModules := global.ArtApexJars
frameworkModules := global.BootJars.RemoveList(artModules)
+ mainlineBcpModules := global.ApexBootJars
+ 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",
+ stem: bootImageStem,
installDirOnHost: "apex/art_boot_images/javalib",
- installDirOnDevice: "system/framework",
+ installDirOnDevice: frameworkSubdir,
profileInstallPathInApex: "etc/boot-image.prof",
modules: artModules,
preloadedClassesFile: "art/build/boot/preloaded-classes",
compilerFilter: "speed-profile",
+ singleImage: false,
}
// 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,
- stem: "boot",
+ stem: bootImageStem,
installDirOnHost: frameworkSubdir,
installDirOnDevice: frameworkSubdir,
modules: frameworkModules,
preloadedClassesFile: "frameworks/base/config/preloaded-classes",
compilerFilter: "speed-profile",
+ singleImage: false,
+ }
+
+ mainlineCfg := bootImageConfig{
+ extends: &frameworkCfg,
+ name: mainlineBootImageName,
+ stem: bootImageStem,
+ installDirOnHost: frameworkSubdir,
+ installDirOnDevice: frameworkSubdir,
+ modules: mainlineBcpModules,
+ compilerFilter: "verify",
+ singleImage: true,
}
return map[string]*bootImageConfig{
artBootImageName: &artCfg,
frameworkBootImageName: &frameworkCfg,
+ mainlineBootImageName: &mainlineCfg,
}
}).(map[string]*bootImageConfig)
}
@@ -174,6 +191,10 @@
return genBootImageConfigs(ctx)[frameworkBootImageName]
}
+func mainlineBootImageConfig(ctx android.PathContext) *bootImageConfig {
+ return genBootImageConfigs(ctx)[mainlineBootImageName]
+}
+
// Apex boot config allows to access build/install paths of apex boot jars without going
// through the usual trouble of registering dependencies on those modules and extracting build paths
// from those dependencies.
diff --git a/java/dexpreopt_config_test.go b/java/dexpreopt_config_test.go
index b704d09..cd7f295 100644
--- a/java/dexpreopt_config_test.go
+++ b/java/dexpreopt_config_test.go
@@ -28,8 +28,10 @@
result := android.GroupFixturePreparers(
PrepareForBootImageConfigTest,
+ PrepareApexBootJarConfigs,
).RunTest(t)
CheckArtBootImageConfig(t, result)
CheckFrameworkBootImageConfig(t, result)
+ CheckMainlineBootImageConfig(t, result)
}
diff --git a/java/dexpreopt_config_testing.go b/java/dexpreopt_config_testing.go
index c509c1b..86dd329 100644
--- a/java/dexpreopt_config_testing.go
+++ b/java/dexpreopt_config_testing.go
@@ -39,6 +39,78 @@
FixtureConfigureBootJars("com.android.art:core1", "com.android.art:core2", "platform:framework"),
)
+var PrepareApexBootJarConfigs = FixtureConfigureApexBootJars(
+ "com.android.foo:framework-foo", "com.android.bar:framework-bar")
+
+var PrepareApexBootJarConfigsAndModules = android.GroupFixturePreparers(
+ PrepareApexBootJarConfigs,
+ prepareApexBootJarModule("com.android.foo", "framework-foo"),
+ prepareApexBootJarModule("com.android.bar", "framework-bar"),
+)
+
+var ApexBootJarFragmentsForPlatformBootclasspath = fmt.Sprintf(`
+ {
+ apex: "%[1]s",
+ module: "%[1]s-bootclasspathfragment",
+ },
+ {
+ apex: "%[2]s",
+ module: "%[2]s-bootclasspathfragment",
+ },
+`, "com.android.foo", "com.android.bar")
+
+var ApexBootJarDexJarPaths = []string{
+ "out/soong/.intermediates/packages/modules/com.android.bar/framework-bar/android_common_apex10000/aligned/framework-bar.jar",
+ "out/soong/.intermediates/packages/modules/com.android.foo/framework-foo/android_common_apex10000/aligned/framework-foo.jar",
+}
+
+func prepareApexBootJarModule(apexName string, moduleName string) android.FixturePreparer {
+ moduleSourceDir := fmt.Sprintf("packages/modules/%s", apexName)
+ return android.GroupFixturePreparers(
+ android.FixtureAddTextFile(moduleSourceDir+"/Android.bp", fmt.Sprintf(`
+ apex {
+ name: "%[1]s",
+ key: "%[1]s.key",
+ bootclasspath_fragments: [
+ "%[1]s-bootclasspathfragment",
+ ],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "%[1]s.key",
+ public_key: "%[1]s.avbpubkey",
+ private_key: "%[1]s.pem",
+ }
+
+ bootclasspath_fragment {
+ name: "%[1]s-bootclasspathfragment",
+ contents: ["%[2]s"],
+ apex_available: ["%[1]s"],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+
+ java_library {
+ name: "%[2]s",
+ srcs: ["%[2]s.java"],
+ system_modules: "none",
+ sdk_version: "none",
+ compile_dex: true,
+ apex_available: ["%[1]s"],
+ }
+ `, apexName, moduleName)),
+ android.FixtureMergeMockFs(android.MockFS{
+ fmt.Sprintf("%s/apex_manifest.json", moduleSourceDir): nil,
+ fmt.Sprintf("%s/%s.avbpubkey", moduleSourceDir, apexName): nil,
+ fmt.Sprintf("%s/%s.pem", moduleSourceDir, apexName): nil,
+ fmt.Sprintf("system/sepolicy/apex/%s-file_contexts", apexName): nil,
+ fmt.Sprintf("%s/%s.java", moduleSourceDir, moduleName): nil,
+ }),
+ )
+}
+
// normalizedInstall represents a android.RuleBuilderInstall that has been normalized to remove
// test specific parts of the From path.
type normalizedInstall struct {
@@ -601,6 +673,290 @@
checkBootImageConfig(t, imageConfig, mutated, expected)
}
+// getMainlineImageConfig gets the framework bootImageConfig that was created during the test.
+func getMainlineImageConfig(result *android.TestResult) *bootImageConfig {
+ pathCtx := &android.TestPathContext{TestResult: result}
+ imageConfig := mainlineBootImageConfig(pathCtx)
+ return imageConfig
+}
+
+// CheckMainlineBootImageConfig checks the status of the fields of the bootImageConfig and
+// bootImageVariant structures that are returned from mainlineBootImageConfig.
+//
+// This is before any fields are mutated.
+func CheckMainlineBootImageConfig(t *testing.T, result *android.TestResult) {
+ expectedLicenseMetadataFile := ""
+ imageConfig := getMainlineImageConfig(result)
+
+ expected := &expectedConfig{
+ name: "mainline",
+ stem: "boot",
+ dir: "out/soong/test_device/dex_mainlinejars",
+ symbolsDir: "out/soong/test_device/dex_mainlinejars_unstripped",
+ installDirOnDevice: "system/framework",
+ installDirOnHost: "system/framework",
+ profileInstallPathInApex: "",
+ modules: android.CreateTestConfiguredJarList([]string{
+ "com.android.foo:framework-foo",
+ "com.android.bar:framework-bar",
+ }),
+ dexPaths: []string{
+ "out/soong/test_device/dex_mainlinejars_input/framework-foo.jar",
+ "out/soong/test_device/dex_mainlinejars_input/framework-bar.jar",
+ },
+ dexPathsDeps: []string{
+ "out/soong/test_device/dex_artjars_input/core1.jar",
+ "out/soong/test_device/dex_artjars_input/core2.jar",
+ "out/soong/test_device/dex_bootjars_input/framework.jar",
+ "out/soong/test_device/dex_mainlinejars_input/framework-foo.jar",
+ "out/soong/test_device/dex_mainlinejars_input/framework-bar.jar",
+ },
+ zip: "out/soong/test_device/dex_mainlinejars/mainline.zip",
+ variants: []*expectedVariant{
+ {
+ archType: android.Arm64,
+ dexLocations: []string{
+ "/apex/com.android.foo/javalib/framework-foo.jar",
+ "/apex/com.android.bar/javalib/framework-bar.jar",
+ },
+ dexLocationsDeps: []string{
+ "/apex/com.android.art/javalib/core1.jar",
+ "/apex/com.android.art/javalib/core2.jar",
+ "/system/framework/framework.jar",
+ "/apex/com.android.foo/javalib/framework-foo.jar",
+ "/apex/com.android.bar/javalib/framework-bar.jar",
+ },
+ imagePathOnHost: "out/soong/test_device/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.art",
+ imagePathOnDevice: "/system/framework/arm64/boot-framework-foo.art",
+ imagesDeps: []string{
+ "out/soong/test_device/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.art",
+ "out/soong/test_device/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.oat",
+ "out/soong/test_device/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.vdex",
+ },
+ baseImages: []string{
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art",
+ "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art",
+ },
+ baseImagesDeps: []string{
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex",
+ "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art",
+ "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.oat",
+ "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.vdex",
+ },
+ installs: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.art",
+ to: "/system/framework/arm64/boot-framework-foo.art",
+ },
+ {
+ from: "out/soong/test_device/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.oat",
+ to: "/system/framework/arm64/boot-framework-foo.oat",
+ },
+ },
+ vdexInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.vdex",
+ to: "/system/framework/arm64/boot-framework-foo.vdex",
+ },
+ },
+ unstrippedInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_mainlinejars_unstripped/android/system/framework/arm64/boot-framework-foo.oat",
+ to: "/system/framework/arm64/boot-framework-foo.oat",
+ },
+ },
+ licenseMetadataFile: expectedLicenseMetadataFile,
+ },
+ {
+ archType: android.Arm,
+ dexLocations: []string{
+ "/apex/com.android.foo/javalib/framework-foo.jar",
+ "/apex/com.android.bar/javalib/framework-bar.jar",
+ },
+ dexLocationsDeps: []string{
+ "/apex/com.android.art/javalib/core1.jar",
+ "/apex/com.android.art/javalib/core2.jar",
+ "/system/framework/framework.jar",
+ "/apex/com.android.foo/javalib/framework-foo.jar",
+ "/apex/com.android.bar/javalib/framework-bar.jar",
+ },
+ imagePathOnHost: "out/soong/test_device/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.art",
+ imagePathOnDevice: "/system/framework/arm/boot-framework-foo.art",
+ imagesDeps: []string{
+ "out/soong/test_device/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.art",
+ "out/soong/test_device/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.oat",
+ "out/soong/test_device/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.vdex",
+ },
+ baseImages: []string{
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art",
+ "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.art",
+ },
+ baseImagesDeps: []string{
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex",
+ "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.art",
+ "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.oat",
+ "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.vdex",
+ },
+ installs: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.art",
+ to: "/system/framework/arm/boot-framework-foo.art",
+ },
+ {
+ from: "out/soong/test_device/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.oat",
+ to: "/system/framework/arm/boot-framework-foo.oat",
+ },
+ },
+ vdexInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.vdex",
+ to: "/system/framework/arm/boot-framework-foo.vdex",
+ },
+ },
+ unstrippedInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_mainlinejars_unstripped/android/system/framework/arm/boot-framework-foo.oat",
+ to: "/system/framework/arm/boot-framework-foo.oat",
+ },
+ },
+ licenseMetadataFile: expectedLicenseMetadataFile,
+ },
+ {
+ archType: android.X86_64,
+ dexLocations: []string{
+ "host/linux-x86/apex/com.android.foo/javalib/framework-foo.jar",
+ "host/linux-x86/apex/com.android.bar/javalib/framework-bar.jar",
+ },
+ dexLocationsDeps: []string{
+ "host/linux-x86/apex/com.android.art/javalib/core1.jar",
+ "host/linux-x86/apex/com.android.art/javalib/core2.jar",
+ "host/linux-x86/system/framework/framework.jar",
+ "host/linux-x86/apex/com.android.foo/javalib/framework-foo.jar",
+ "host/linux-x86/apex/com.android.bar/javalib/framework-bar.jar",
+ },
+ imagePathOnHost: "out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.art",
+ imagePathOnDevice: "/system/framework/x86_64/boot-framework-foo.art",
+ imagesDeps: []string{
+ "out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.art",
+ "out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.oat",
+ "out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.vdex",
+ },
+ baseImages: []string{
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art",
+ "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art",
+ },
+ baseImagesDeps: []string{
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex",
+ "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art",
+ "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat",
+ "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex",
+ },
+ installs: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.art",
+ to: "/system/framework/x86_64/boot-framework-foo.art",
+ },
+ {
+ from: "out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.oat",
+ to: "/system/framework/x86_64/boot-framework-foo.oat",
+ },
+ },
+ vdexInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.vdex",
+ to: "/system/framework/x86_64/boot-framework-foo.vdex",
+ },
+ },
+ unstrippedInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_mainlinejars_unstripped/linux_glibc/system/framework/x86_64/boot-framework-foo.oat",
+ to: "/system/framework/x86_64/boot-framework-foo.oat",
+ },
+ },
+ licenseMetadataFile: expectedLicenseMetadataFile,
+ },
+ {
+ archType: android.X86,
+ dexLocations: []string{
+ "host/linux-x86/apex/com.android.foo/javalib/framework-foo.jar",
+ "host/linux-x86/apex/com.android.bar/javalib/framework-bar.jar",
+ },
+ dexLocationsDeps: []string{
+ "host/linux-x86/apex/com.android.art/javalib/core1.jar",
+ "host/linux-x86/apex/com.android.art/javalib/core2.jar",
+ "host/linux-x86/system/framework/framework.jar",
+ "host/linux-x86/apex/com.android.foo/javalib/framework-foo.jar",
+ "host/linux-x86/apex/com.android.bar/javalib/framework-bar.jar",
+ },
+ imagePathOnHost: "out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.art",
+ imagePathOnDevice: "/system/framework/x86/boot-framework-foo.art",
+ imagesDeps: []string{
+ "out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.art",
+ "out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.oat",
+ "out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.vdex",
+ },
+ baseImages: []string{
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art",
+ "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art",
+ },
+ baseImagesDeps: []string{
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex",
+ "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art",
+ "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat",
+ "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex",
+ },
+ installs: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.art",
+ to: "/system/framework/x86/boot-framework-foo.art",
+ },
+ {
+ from: "out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.oat",
+ to: "/system/framework/x86/boot-framework-foo.oat",
+ },
+ },
+ vdexInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.vdex",
+ to: "/system/framework/x86/boot-framework-foo.vdex",
+ },
+ },
+ unstrippedInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_mainlinejars_unstripped/linux_glibc/system/framework/x86/boot-framework-foo.oat",
+ to: "/system/framework/x86/boot-framework-foo.oat",
+ },
+ },
+ licenseMetadataFile: expectedLicenseMetadataFile,
+ },
+ },
+ profileInstalls: []normalizedInstall{},
+ profileLicenseMetadataFile: expectedLicenseMetadataFile,
+ }
+
+ checkBootImageConfig(t, imageConfig, false, expected)
+}
+
// clearMutatedFields clears fields in the expectedConfig that correspond to fields in the
// bootImageConfig/bootImageVariant structs which are mutated outside the call to
// genBootImageConfigs.
@@ -712,6 +1068,10 @@
DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_arm64=out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art:/system/framework/arm64/boot-framework.art out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.oat:/system/framework/arm64/boot-framework.oat
DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_host_x86=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art:/system/framework/x86/boot-framework.art out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat:/system/framework/x86/boot-framework.oat
DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_host_x86_64=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art:/system/framework/x86_64/boot-framework.art out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat:/system/framework/x86_64/boot-framework.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_arm=out/soong/test_device/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.art:/system/framework/arm/boot-framework-foo.art out/soong/test_device/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.oat:/system/framework/arm/boot-framework-foo.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_arm64=out/soong/test_device/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.art:/system/framework/arm64/boot-framework-foo.art out/soong/test_device/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.oat:/system/framework/arm64/boot-framework-foo.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_host_x86=out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.art:/system/framework/x86/boot-framework-foo.art out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.oat:/system/framework/x86/boot-framework-foo.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_mainline_host_x86_64=out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.art:/system/framework/x86_64/boot-framework-foo.art out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.oat:/system/framework/x86_64/boot-framework-foo.oat
DEXPREOPT_IMAGE_DEPS_art_arm=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex
DEXPREOPT_IMAGE_DEPS_art_arm64=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex
DEXPREOPT_IMAGE_DEPS_art_host_x86=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex
@@ -720,6 +1080,10 @@
DEXPREOPT_IMAGE_DEPS_boot_arm64=out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.oat out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.vdex
DEXPREOPT_IMAGE_DEPS_boot_host_x86=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex
DEXPREOPT_IMAGE_DEPS_boot_host_x86_64=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex
+DEXPREOPT_IMAGE_DEPS_mainline_arm=out/soong/test_device/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.art out/soong/test_device/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.oat out/soong/test_device/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.vdex
+DEXPREOPT_IMAGE_DEPS_mainline_arm64=out/soong/test_device/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.art out/soong/test_device/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.oat out/soong/test_device/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.vdex
+DEXPREOPT_IMAGE_DEPS_mainline_host_x86=out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.art out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.oat out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.vdex
+DEXPREOPT_IMAGE_DEPS_mainline_host_x86_64=out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.art out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.oat out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.vdex
DEXPREOPT_IMAGE_LICENSE_METADATA_art_arm=%[1]s
DEXPREOPT_IMAGE_LICENSE_METADATA_art_arm64=%[1]s
DEXPREOPT_IMAGE_LICENSE_METADATA_art_host_x86=%[1]s
@@ -728,11 +1092,17 @@
DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86_64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_arm64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_mainline_host_x86_64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEart=/system/framework/boot.art
DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEboot=/system/framework/boot.art:/system/framework/boot-framework.art
+DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEmainline=/system/framework/boot.art:/system/framework/boot-framework.art:/system/framework/boot-framework-foo.art
DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTart=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/boot.art
DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTboot=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/boot.art:out/soong/test_device/dex_bootjars/android/system/framework/boot-framework.art
-DEXPREOPT_IMAGE_NAMES=art boot
+DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTmainline=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/boot.art:out/soong/test_device/dex_bootjars/android/system/framework/boot-framework.art:out/soong/test_device/dex_mainlinejars/android/system/framework/boot-framework-foo.art
+DEXPREOPT_IMAGE_NAMES=art boot mainline
DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED=out/soong/test_device/dex_bootjars/boot.bprof:/system/etc/boot-image.bprof out/soong/test_device/dex_bootjars/boot.prof:/system/etc/boot-image.prof
DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm=out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat
@@ -743,6 +1113,10 @@
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_arm64=out/soong/test_device/dex_bootjars_unstripped/android/system/framework/arm64/boot-framework.oat:/system/framework/arm64/boot-framework.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_host_x86=out/soong/test_device/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot-framework.oat:/system/framework/x86/boot-framework.oat
DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_host_x86_64=out/soong/test_device/dex_bootjars_unstripped/linux_glibc/system/framework/x86_64/boot-framework.oat:/system/framework/x86_64/boot-framework.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_arm=out/soong/test_device/dex_mainlinejars_unstripped/android/system/framework/arm/boot-framework-foo.oat:/system/framework/arm/boot-framework-foo.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_arm64=out/soong/test_device/dex_mainlinejars_unstripped/android/system/framework/arm64/boot-framework-foo.oat:/system/framework/arm64/boot-framework-foo.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_host_x86=out/soong/test_device/dex_mainlinejars_unstripped/linux_glibc/system/framework/x86/boot-framework-foo.oat:/system/framework/x86/boot-framework-foo.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_mainline_host_x86_64=out/soong/test_device/dex_mainlinejars_unstripped/linux_glibc/system/framework/x86_64/boot-framework-foo.oat:/system/framework/x86_64/boot-framework-foo.oat
DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex:/apex/art_boot_images/javalib/arm/boot.vdex out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex:/apex/art_boot_images/javalib/arm/boot-core2.vdex
DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm64=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex:/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex:/apex/art_boot_images/javalib/arm64/boot-core2.vdex
DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex:/apex/art_boot_images/javalib/x86/boot.vdex out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex:/apex/art_boot_images/javalib/x86/boot-core2.vdex
@@ -751,8 +1125,13 @@
DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_arm64=out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.vdex:/system/framework/arm64/boot-framework.vdex
DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_host_x86=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex:/system/framework/x86/boot-framework.vdex
DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_host_x86_64=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex:/system/framework/x86_64/boot-framework.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_mainline_arm=out/soong/test_device/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.vdex:/system/framework/arm/boot-framework-foo.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_mainline_arm64=out/soong/test_device/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.vdex:/system/framework/arm64/boot-framework-foo.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_mainline_host_x86=out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.vdex:/system/framework/x86/boot-framework-foo.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_mainline_host_x86_64=out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.vdex:/system/framework/x86_64/boot-framework-foo.vdex
DEXPREOPT_IMAGE_ZIP_art=out/soong/test_device/dex_artjars/art.zip
DEXPREOPT_IMAGE_ZIP_boot=out/soong/test_device/dex_bootjars/boot.zip
+DEXPREOPT_IMAGE_ZIP_mainline=out/soong/test_device/dex_mainlinejars/mainline.zip
DEXPREOPT_IMAGE_art_arm=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art
DEXPREOPT_IMAGE_art_arm64=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art
DEXPREOPT_IMAGE_art_host_x86=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art
@@ -761,6 +1140,10 @@
DEXPREOPT_IMAGE_boot_arm64=out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art
DEXPREOPT_IMAGE_boot_host_x86=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art
DEXPREOPT_IMAGE_boot_host_x86_64=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art
+DEXPREOPT_IMAGE_mainline_arm=out/soong/test_device/dex_mainlinejars/android/system/framework/arm/boot-framework-foo.art
+DEXPREOPT_IMAGE_mainline_arm64=out/soong/test_device/dex_mainlinejars/android/system/framework/arm64/boot-framework-foo.art
+DEXPREOPT_IMAGE_mainline_host_x86=out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86/boot-framework-foo.art
+DEXPREOPT_IMAGE_mainline_host_x86_64=out/soong/test_device/dex_mainlinejars/linux_glibc/system/framework/x86_64/boot-framework-foo.art
`
expected := strings.TrimSpace(fmt.Sprintf(format, expectedLicenseMetadataFile))
actual := strings.TrimSpace(out.String())
diff --git a/java/droiddoc.go b/java/droiddoc.go
index e98b9ea..dbe021d 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -248,16 +248,16 @@
return proptools.String(j.properties.System_modules)
}
-func (j *Javadoc) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
- return j.SdkVersion(ctx)
+func (j *Javadoc) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+ return j.SdkVersion(ctx).ApiLevel
}
-func (j *Javadoc) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
- return j.SdkVersion(ctx)
+func (j *Javadoc) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
+ return j.SdkVersion(ctx).ApiLevel
}
-func (j *Javadoc) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
- return j.SdkVersion(ctx)
+func (j *Javadoc) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+ return j.SdkVersion(ctx).ApiLevel
}
func (j *Javadoc) addDeps(ctx android.BottomUpMutatorContext) {
@@ -304,7 +304,7 @@
flags = append(flags, "-I"+src.String())
}
- minSdkVersion := j.MinSdkVersion(ctx).ApiLevel.FinalOrFutureInt()
+ minSdkVersion := j.MinSdkVersion(ctx).FinalOrFutureInt()
flags = append(flags, fmt.Sprintf("--min_sdk_version=%v", minSdkVersion))
return strings.Join(flags, " "), deps
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index c4fc65f..d25096b 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -73,7 +73,7 @@
android.Module
hiddenAPIIntf
- MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec
+ MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel
}
type hiddenAPIIntf interface {
@@ -157,7 +157,7 @@
// Create a copy of the dex jar which has been encoded with hiddenapi flags.
flagsCSV := hiddenAPISingletonPaths(ctx).flags
outputDir := android.PathForModuleOut(ctx, "hiddenapi").OutputPath
- encodedDex := hiddenAPIEncodeDex(ctx, dexJar, flagsCSV, uncompressDex, android.SdkSpecNone, outputDir)
+ encodedDex := hiddenAPIEncodeDex(ctx, dexJar, flagsCSV, uncompressDex, android.NoneApiLevel, outputDir)
// Use the encoded dex jar from here onwards.
return encodedDex
@@ -253,7 +253,7 @@
// The encode dex rule requires unzipping, encoding and rezipping the classes.dex files along with
// all the resources from the input jar. It also ensures that if it was uncompressed in the input
// it stays uncompressed in the output.
-func hiddenAPIEncodeDex(ctx android.ModuleContext, dexInput, flagsCSV android.Path, uncompressDex bool, minSdkVersion android.SdkSpec, outputDir android.OutputPath) android.OutputPath {
+func hiddenAPIEncodeDex(ctx android.ModuleContext, dexInput, flagsCSV android.Path, uncompressDex bool, minSdkVersion android.ApiLevel, outputDir android.OutputPath) android.OutputPath {
// The output file has the same name as the input file and is in the output directory.
output := outputDir.Join(ctx, dexInput.Base())
@@ -283,7 +283,7 @@
// If the library is targeted for Q and/or R then make sure that they do not
// have any S+ flags encoded as that will break the runtime.
- minApiLevel := minSdkVersion.ApiLevel
+ minApiLevel := minSdkVersion
if !minApiLevel.IsNone() {
if minApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(ctx, "R")) {
hiddenapiFlags = hiddenapiFlags + " --max-hiddenapi-level=max-target-r"
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index be4a48e..96e084a 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -236,12 +236,12 @@
testStubModules = append(testStubModules, "sdk_test_current_android")
} else {
// Use stub modules built from source
- publicStubModules = append(publicStubModules, "android_stubs_current")
- systemStubModules = append(systemStubModules, "android_system_stubs_current")
- testStubModules = append(testStubModules, "android_test_stubs_current")
+ publicStubModules = append(publicStubModules, android.SdkPublic.JavaLibraryName(config))
+ systemStubModules = append(systemStubModules, android.SdkSystem.JavaLibraryName(config))
+ testStubModules = append(testStubModules, android.SdkTest.JavaLibraryName(config))
}
// We do not have prebuilts of the core platform api yet
- corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
+ corePlatformStubModules = append(corePlatformStubModules, android.JavaApiLibraryName(config, "legacy.core.platform.api.stubs"))
// Allow products to define their own stubs for custom product jars that apps can use.
publicStubModules = append(publicStubModules, config.ProductHiddenAPIStubs()...)
@@ -1278,7 +1278,7 @@
uncompressDex bool
// The minimum sdk version that the dex jar will be used on.
- minSdkVersion android.SdkSpec
+ minSdkVersion android.ApiLevel
}
// bootDexInfoByModule is a map from module name (as returned by module.Name()) to the boot dex
diff --git a/java/java.go b/java/java.go
index 63c4416..0da7328 100644
--- a/java/java.go
+++ b/java/java.go
@@ -388,6 +388,8 @@
jniLibTag = dependencyTag{name: "jnilib", runtimeLinked: true}
r8LibraryJarTag = dependencyTag{name: "r8-libraryjar", runtimeLinked: true}
syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
+ javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
+ depApiSrcsTag = dependencyTag{name: "dep-api-srcs"}
jniInstallTag = installDependencyTag{name: "jni install"}
binaryInstallTag = installDependencyTag{name: "binary install"}
usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false)
@@ -454,7 +456,9 @@
ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...)
ctx.AddVariationDependencies(nil, sdkLibTag, sdkDep.classpath...)
if d.effectiveOptimizeEnabled() && sdkDep.hasStandardLibs() {
- ctx.AddVariationDependencies(nil, proguardRaiseTag, config.LegacyCorePlatformBootclasspathLibraries...)
+ ctx.AddVariationDependencies(nil, proguardRaiseTag,
+ android.JavaApiLibraryNames(ctx.Config(), config.LegacyCorePlatformBootclasspathLibraries)...,
+ )
}
if d.effectiveOptimizeEnabled() && sdkDep.hasFrameworkLibs() {
ctx.AddVariationDependencies(nil, proguardRaiseTag, config.FrameworkLibraries...)
@@ -811,7 +815,7 @@
// If the min_sdk_version was set then add the canonical representation of the API level to the
// snapshot.
if j.deviceProperties.Min_sdk_version != nil {
- canonical := android.ReplaceFinalizedCodenames(ctx.SdkModuleContext().Config(), j.minSdkVersion.ApiLevel.String())
+ canonical := android.ReplaceFinalizedCodenames(ctx.SdkModuleContext().Config(), j.minSdkVersion.String())
p.MinSdkVersion = proptools.StringPtr(canonical)
}
@@ -1609,14 +1613,28 @@
})
}
+type JavaApiLibraryDepsInfo struct {
+ JavaInfo
+ StubsSrcJar android.Path
+}
+
+var JavaApiLibraryDepsProvider = blueprint.NewProvider(JavaApiLibraryDepsInfo{})
+
type ApiLibrary struct {
android.ModuleBase
android.DefaultableModuleBase
+ hiddenAPI
+ dexer
+
properties JavaApiLibraryProperties
- stubsSrcJar android.WritablePath
- stubsJar android.WritablePath
+ stubsSrcJar android.WritablePath
+ stubsJar android.WritablePath
+ stubsJarWithoutStaticLibs android.WritablePath
+ extractedSrcJar android.WritablePath
+ // .dex of stubs, used for hiddenapi processing
+ dexJarFile OptionalDexJarPath
}
type JavaApiLibraryProperties struct {
@@ -1640,8 +1658,13 @@
Libs []string
// List of java libs that this module has static dependencies to and will be
- // passed in metalava invocation
+ // merge zipped after metalava invocation
Static_libs []string
+
+ // Java Api library to provide the full API surface text files and jar file.
+ // If this property is set, the provided full API surface text files and
+ // jar file are passed to metalava invocation.
+ Dep_api_srcs *string
}
func ApiLibraryFactory() android.Module {
@@ -1692,6 +1715,12 @@
Flag("--color").
Flag("--quiet").
Flag("--format=v2").
+ Flag("--include-annotations").
+ // The flag makes nullability issues as warnings rather than errors by replacing
+ // @Nullable/@NonNull in the listed packages APIs with @RecentlyNullable/@RecentlyNonNull,
+ // and these packages are meant to have everything annotated
+ // @RecentlyNullable/@RecentlyNonNull.
+ FlagWithArg("--force-convert-to-warning-nullability-annotations ", "+*:-android.*:+android.icu.*:-dalvik.*").
FlagWithArg("--repeat-errors-max ", "10").
FlagWithArg("--hide ", "UnresolvedImport").
FlagWithArg("--hide ", "InvalidNullabilityOverride").
@@ -1700,13 +1729,50 @@
return cmd
}
+func (al *ApiLibrary) HeaderJars() android.Paths {
+ return android.Paths{al.stubsJar}
+}
+
+func (al *ApiLibrary) OutputDirAndDeps() (android.Path, android.Paths) {
+ return nil, nil
+}
+
func (al *ApiLibrary) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath) {
if stubsDir.Valid() {
cmd.FlagWithArg("--stubs ", stubsDir.String())
}
}
-var javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
+// This method extracts the stub java files from the srcjar file provided from dep_api_srcs module
+// and replaces the java stubs generated by invoking metalava in this module.
+// This method is used because metalava can generate compilable from-text stubs only when
+// the codebase encompasses all classes listed in the input API text file, but a class can extend
+// a class that is not within the same API domain.
+func (al *ApiLibrary) extractApiSrcs(ctx android.ModuleContext, rule *android.RuleBuilder, stubsDir android.OptionalPath, depApiSrcsSrcJar android.Path) {
+ generatedStubsList := android.PathForModuleOut(ctx, "metalava", "sources.txt")
+ unzippedSrcJarDir := android.PathForModuleOut(ctx, "metalava", "unzipDir")
+
+ rule.Command().
+ BuiltTool("list_files").
+ Text(stubsDir.String()).
+ FlagWithOutput("--out ", generatedStubsList).
+ FlagWithArg("--extensions ", ".java").
+ FlagWithArg("--root ", unzippedSrcJarDir.String())
+
+ rule.Command().
+ Text("unzip").
+ Flag("-q").
+ Input(depApiSrcsSrcJar).
+ FlagWithArg("-d ", unzippedSrcJarDir.String())
+
+ rule.Command().
+ BuiltTool("soong_zip").
+ Flag("-srcjar").
+ Flag("-write_if_changed").
+ FlagWithArg("-C ", unzippedSrcJarDir.String()).
+ FlagWithInput("-l ", generatedStubsList).
+ FlagWithOutput("-o ", al.stubsSrcJar)
+}
func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
apiContributions := al.properties.Api_contributions
@@ -1715,6 +1781,9 @@
}
ctx.AddVariationDependencies(nil, libTag, al.properties.Libs...)
ctx.AddVariationDependencies(nil, staticLibTag, al.properties.Static_libs...)
+ if al.properties.Dep_api_srcs != nil {
+ ctx.AddVariationDependencies(nil, depApiSrcsTag, String(al.properties.Dep_api_srcs))
+ }
}
func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1735,6 +1804,7 @@
var srcFiles android.Paths
var classPaths android.Paths
var staticLibs android.Paths
+ var depApiSrcsStubsSrcJar android.Path
ctx.VisitDirectDeps(func(dep android.Module) {
tag := ctx.OtherModuleDependencyTag(dep)
switch tag {
@@ -1751,6 +1821,10 @@
case staticLibTag:
provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
staticLibs = append(staticLibs, provider.HeaderJars...)
+ case depApiSrcsTag:
+ provider := ctx.OtherModuleProvider(dep, JavaApiLibraryDepsProvider).(JavaApiLibraryDepsInfo)
+ classPaths = append(classPaths, provider.HeaderJars...)
+ depApiSrcsStubsSrcJar = provider.StubsSrcJar
}
})
@@ -1761,21 +1835,31 @@
srcFiles = append(srcFiles, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), api))
}
+ if srcFiles == nil {
+ ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName())
+ }
+
cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir)
al.stubsFlags(ctx, cmd, stubsDir)
al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
- rule.Command().
- BuiltTool("soong_zip").
- Flag("-write_if_changed").
- Flag("-jar").
- FlagWithOutput("-o ", al.stubsSrcJar).
- FlagWithArg("-C ", stubsDir.String()).
- FlagWithArg("-D ", stubsDir.String())
+
+ if depApiSrcsStubsSrcJar != nil {
+ al.extractApiSrcs(ctx, rule, stubsDir, depApiSrcsStubsSrcJar)
+ } else {
+ rule.Command().
+ BuiltTool("soong_zip").
+ Flag("-write_if_changed").
+ Flag("-jar").
+ FlagWithOutput("-o ", al.stubsSrcJar).
+ FlagWithArg("-C ", stubsDir.String()).
+ FlagWithArg("-D ", stubsDir.String())
+ }
rule.Build("metalava", "metalava merged")
- compiledStubs := android.PathForModuleOut(ctx, ctx.ModuleName(), "stubs.jar")
+
+ al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, ctx.ModuleName(), "stubs.jar")
al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName()))
var flags javaBuilderFlags
@@ -1783,24 +1867,74 @@
flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
flags.classpath = classpath(classPaths)
- TransformJavaToClasses(ctx, compiledStubs, 0, android.Paths{},
+ TransformJavaToClasses(ctx, al.stubsJarWithoutStaticLibs, 0, android.Paths{},
android.Paths{al.stubsSrcJar}, flags, android.Paths{})
builder := android.NewRuleBuilder(pctx, ctx)
builder.Command().
BuiltTool("merge_zips").
Output(al.stubsJar).
- Inputs(android.Paths{compiledStubs}).
+ Inputs(android.Paths{al.stubsJarWithoutStaticLibs}).
Inputs(staticLibs)
builder.Build("merge_zips", "merge jar files")
+ // compile stubs to .dex for hiddenapi processing
+ dexParams := &compileDexParams{
+ flags: javaBuilderFlags{},
+ sdkVersion: al.SdkVersion(ctx),
+ minSdkVersion: al.MinSdkVersion(ctx),
+ classesJar: al.stubsJar,
+ jarName: ctx.ModuleName() + ".jar",
+ }
+ dexOutputFile := al.dexer.compileDex(ctx, dexParams)
+ uncompressed := true
+ al.initHiddenAPI(ctx, makeDexJarPathFromPath(dexOutputFile), al.stubsJar, &uncompressed)
+ dexOutputFile = al.hiddenAPIEncodeDex(ctx, dexOutputFile)
+ al.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
+
ctx.Phony(ctx.ModuleName(), al.stubsJar)
ctx.SetProvider(JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(al.stubsJar),
+ HeaderJars: android.PathsIfNonNil(al.stubsJar),
+ ImplementationAndResourcesJars: android.PathsIfNonNil(al.stubsJar),
+ ImplementationJars: android.PathsIfNonNil(al.stubsJar),
+ AidlIncludeDirs: android.Paths{},
+ })
+
+ ctx.SetProvider(JavaApiLibraryDepsProvider, JavaApiLibraryDepsInfo{
+ JavaInfo: JavaInfo{
+ HeaderJars: android.PathsIfNonNil(al.stubsJar),
+ },
+ StubsSrcJar: al.stubsSrcJar,
})
}
+func (al *ApiLibrary) DexJarBuildPath() OptionalDexJarPath {
+ return al.dexJarFile
+}
+
+func (al *ApiLibrary) DexJarInstallPath() android.Path {
+ return al.dexJarFile.Path()
+}
+
+func (al *ApiLibrary) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
+ return nil
+}
+
+// java_api_library constitutes the sdk, and does not build against one
+func (al *ApiLibrary) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+ return android.SdkSpecNone
+}
+
+// java_api_library is always at "current". Return FutureApiLevel
+func (al *ApiLibrary) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+ return android.FutureApiLevel
+}
+
+// implement the following interfaces for hiddenapi processing
+var _ hiddenAPIModule = (*ApiLibrary)(nil)
+var _ UsesLibraryDependency = (*ApiLibrary)(nil)
+
//
// Java prebuilts
//
@@ -1874,7 +2008,7 @@
hideApexVariantFromMake bool
sdkVersion android.SdkSpec
- minSdkVersion android.SdkSpec
+ minSdkVersion android.ApiLevel
}
var _ PermittedPackagesForUpdatableBootJars = (*Import)(nil)
@@ -1891,22 +2025,23 @@
return "none"
}
-func (j *Import) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+func (j *Import) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
if j.properties.Min_sdk_version != nil {
- return android.SdkSpecFrom(ctx, *j.properties.Min_sdk_version)
+ return android.ApiLevelFrom(ctx, *j.properties.Min_sdk_version)
}
- return j.SdkVersion(ctx)
+ return j.SdkVersion(ctx).ApiLevel
}
-func (j *Import) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
+func (j *Import) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
if j.properties.Replace_max_sdk_version_placeholder != nil {
- return android.SdkSpecFrom(ctx, *j.properties.Replace_max_sdk_version_placeholder)
+ return android.ApiLevelFrom(ctx, *j.properties.Replace_max_sdk_version_placeholder)
}
- return android.SdkSpecFrom(ctx, "")
+ // Default is PrivateApiLevel
+ return android.SdkSpecPrivate.ApiLevel
}
-func (j *Import) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
- return j.SdkVersion(ctx)
+func (j *Import) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+ return j.SdkVersion(ctx).ApiLevel
}
func (j *Import) Prebuilt() *android.Prebuilt {
@@ -2161,15 +2296,14 @@
func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
sdkVersion android.ApiLevel) error {
sdkVersionSpec := j.SdkVersion(ctx)
- minSdkVersionSpec := j.MinSdkVersion(ctx)
- if !minSdkVersionSpec.Specified() {
+ minSdkVersion := j.MinSdkVersion(ctx)
+ if !minSdkVersion.Specified() {
return fmt.Errorf("min_sdk_version is not specified")
}
// If the module is compiling against core (via sdk_version), skip comparison check.
if sdkVersionSpec.Kind == android.SdkCore {
return nil
}
- minSdkVersion := minSdkVersionSpec.ApiLevel
if minSdkVersion.GreaterThan(sdkVersion) {
return fmt.Errorf("newer SDK(%v)", minSdkVersion)
}
@@ -2608,9 +2742,11 @@
type javaCommonAttributes struct {
*javaResourcesAttributes
*kotlinAttributes
- Srcs bazel.LabelListAttribute
- Plugins bazel.LabelListAttribute
- Javacopts bazel.StringListAttribute
+ Srcs bazel.LabelListAttribute
+ Plugins bazel.LabelListAttribute
+ Javacopts bazel.StringListAttribute
+ Sdk_version bazel.StringAttribute
+ Java_version bazel.StringAttribute
}
type javaDependencyLabels struct {
@@ -2626,10 +2762,12 @@
type aidlLibraryAttributes struct {
Srcs bazel.LabelListAttribute
+ Tags bazel.StringListAttribute
}
type javaAidlLibraryAttributes struct {
Deps bazel.LabelListAttribute
+ Tags bazel.StringListAttribute
}
// bp2BuildJavaInfo has information needed for the conversion of java*_modules
@@ -2660,6 +2798,7 @@
}
}
}
+ srcs.ResolveExcludes()
javaSrcPartition := "java"
protoSrcPartition := "proto"
@@ -2700,16 +2839,19 @@
return android.IsConvertedToAidlLibrary(ctx, src.OriginalModuleName)
})
+ apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx, ctx.Module())
+
if !aidlSrcs.IsEmpty() {
aidlLibName := m.Name() + "_aidl_library"
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "aidl_library",
- Bzl_load_location: "//build/bazel/rules/aidl:library.bzl",
+ Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
},
android.CommonAttributes{Name: aidlLibName},
&aidlLibraryAttributes{
Srcs: aidlSrcs,
+ Tags: apexAvailableTags,
},
)
aidlLibs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}})
@@ -2719,11 +2861,12 @@
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "java_aidl_library",
- Bzl_load_location: "//build/bazel/rules/java:aidl_library.bzl",
+ Bzl_load_location: "//build/bazel/rules/java:java_aidl_library.bzl",
},
android.CommonAttributes{Name: javaAidlLibName},
&javaAidlLibraryAttributes{
Deps: aidlLibs,
+ Tags: apexAvailableTags,
},
)
@@ -2734,10 +2877,6 @@
if m.properties.Javacflags != nil {
javacopts = append(javacopts, m.properties.Javacflags...)
}
- if m.properties.Java_version != nil {
- javaVersion := normalizeJavaVersion(ctx, *m.properties.Java_version).String()
- javacopts = append(javacopts, fmt.Sprintf("-source %s -target %s", javaVersion, javaVersion))
- }
epEnabled := m.properties.Errorprone.Enabled
//TODO(b/227504307) add configuration that depends on RUN_ERROR_PRONE environment variable
@@ -2751,7 +2890,9 @@
Plugins: bazel.MakeLabelListAttribute(
android.BazelLabelForModuleDeps(ctx, m.properties.Plugins),
),
- Javacopts: bazel.MakeStringListAttribute(javacopts),
+ Javacopts: bazel.MakeStringListAttribute(javacopts),
+ Java_version: bazel.StringAttribute{Value: m.properties.Java_version},
+ Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
}
for axis, configToProps := range archVariantProps {
@@ -2768,10 +2909,6 @@
}
}
- if m.properties.Static_libs != nil {
- staticDeps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Static_libs))))
- }
-
protoDepLabel := bp2buildProto(ctx, &m.Module, srcPartitions[protoSrcPartition])
// Soong does not differentiate between a java_library and the Bazel equivalent of
// a java_proto_library + proto_library pair. Instead, in Soong proto sources are
@@ -2783,14 +2920,26 @@
depLabels := &javaDependencyLabels{}
depLabels.Deps = deps
- depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps)
+
+ for axis, configToProps := range archVariantProps {
+ for config, _props := range configToProps {
+ if archProps, ok := _props.(*CommonProperties); ok {
+ archStaticLibs := android.BazelLabelForModuleDeps(
+ ctx,
+ android.LastUniqueStrings(android.CopyOf(archProps.Static_libs)))
+ depLabels.StaticDeps.SetSelectValue(axis, config, archStaticLibs)
+ }
+ }
+ }
+ depLabels.StaticDeps.Value.Append(staticDeps)
hasKotlin := !kotlinSrcs.IsEmpty()
+ commonAttrs.kotlinAttributes = &kotlinAttributes{
+ Kotlincflags: &m.properties.Kotlincflags,
+ }
if len(m.properties.Common_srcs) != 0 {
hasKotlin = true
- commonAttrs.kotlinAttributes = &kotlinAttributes{
- bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Common_srcs)),
- }
+ commonAttrs.kotlinAttributes.Common_srcs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Common_srcs))
}
bp2BuildInfo := &bp2BuildJavaInfo{
@@ -2809,7 +2958,22 @@
}
type kotlinAttributes struct {
- Common_srcs bazel.LabelListAttribute
+ Common_srcs bazel.LabelListAttribute
+ Kotlincflags *[]string
+}
+
+func ktJvmLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties {
+ return bazel.BazelTargetModuleProperties{
+ Rule_class: "kt_jvm_library",
+ Bzl_load_location: "//build/bazel/rules/kotlin:rules.bzl",
+ }
+}
+
+func javaLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties {
+ return bazel.BazelTargetModuleProperties{
+ Rule_class: "java_library",
+ Bzl_load_location: "//build/bazel/rules/java:rules.bzl",
+ }
}
func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
@@ -2819,19 +2983,9 @@
deps := depLabels.Deps
if !commonAttrs.Srcs.IsEmpty() {
deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
-
- sdkVersion := m.SdkVersion(ctx)
- if sdkVersion.Kind == android.SdkPublic && sdkVersion.ApiLevel == android.FutureApiLevel {
- // TODO(b/220869005) remove forced dependency on current public android.jar
- deps.Add(bazel.MakeLabelAttribute("//prebuilts/sdk:public_current_android_sdk_java_import"))
- } else if sdkVersion.Kind == android.SdkSystem && sdkVersion.ApiLevel == android.FutureApiLevel {
- // TODO(b/215230098) remove forced dependency on current public android.jar
- deps.Add(bazel.MakeLabelAttribute("//prebuilts/sdk:system_current_android_sdk_java_import"))
- }
} else if !deps.IsEmpty() {
ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
}
-
var props bazel.BazelTargetModuleProperties
attrs := &javaLibraryAttributes{
javaCommonAttributes: commonAttrs,
@@ -2841,15 +2995,9 @@
name := m.Name()
if !bp2BuildInfo.hasKotlin {
- props = bazel.BazelTargetModuleProperties{
- Rule_class: "java_library",
- Bzl_load_location: "//build/bazel/rules/java:library.bzl",
- }
+ props = javaLibraryBazelTargetModuleProperties()
} else {
- props = bazel.BazelTargetModuleProperties{
- Rule_class: "kt_jvm_library",
- Bzl_load_location: "//build/bazel/rules/kotlin:kt_jvm_library.bzl",
- }
+ props = ktJvmLibraryBazelTargetModuleProperties()
}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
@@ -2857,6 +3005,10 @@
neverLinkAttrs := &javaLibraryAttributes{
Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
Neverlink: bazel.BoolAttribute{Value: &neverlinkProp},
+ javaCommonAttributes: &javaCommonAttributes{
+ Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
+ Java_version: bazel.StringAttribute{Value: m.properties.Java_version},
+ },
}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name + "-neverlink"}, neverLinkAttrs)
@@ -2928,35 +3080,38 @@
}
props := bazel.BazelTargetModuleProperties{
- Rule_class: "java_binary",
+ Rule_class: "java_binary",
+ Bzl_load_location: "//build/bazel/rules/java:rules.bzl",
}
- attrs := &javaBinaryHostAttributes{
+ binAttrs := &javaBinaryHostAttributes{
Runtime_deps: runtimeDeps,
Main_class: mainClass,
Jvm_flags: jvmFlags,
}
- if !bp2BuildInfo.hasKotlin {
- attrs.javaCommonAttributes = commonAttrs
- attrs.Deps = deps
- } else {
- ktName := m.Name() + "_kt"
- ktProps := bazel.BazelTargetModuleProperties{
- Rule_class: "kt_jvm_library",
- Bzl_load_location: "//build/bazel/rules/kotlin:kt_jvm_library.bzl",
- }
-
- ktAttrs := &javaLibraryAttributes{
- Deps: deps,
- javaCommonAttributes: commonAttrs,
- }
-
- ctx.CreateBazelTargetModule(ktProps, android.CommonAttributes{Name: ktName}, ktAttrs)
- attrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + ktName}})
+ if commonAttrs.Srcs.IsEmpty() {
+ binAttrs.javaCommonAttributes = commonAttrs
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, binAttrs)
+ return
}
+ libName := m.Name() + "_lib"
+ var libProps bazel.BazelTargetModuleProperties
+ if bp2BuildInfo.hasKotlin {
+ libProps = ktJvmLibraryBazelTargetModuleProperties()
+ } else {
+ libProps = javaLibraryBazelTargetModuleProperties()
+ }
+ libAttrs := &javaLibraryAttributes{
+ Deps: deps,
+ javaCommonAttributes: commonAttrs,
+ }
+
+ ctx.CreateBazelTargetModule(libProps, android.CommonAttributes{Name: libName}, libAttrs)
+ binAttrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}})
+
// Create the BazelTargetModule.
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, binAttrs)
}
type bazelJavaImportAttributes struct {
@@ -2980,7 +3135,10 @@
attrs := &bazelJavaImportAttributes{
Jars: jars,
}
- props := bazel.BazelTargetModuleProperties{Rule_class: "java_import"}
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "java_import",
+ Bzl_load_location: "//build/bazel/rules/java:rules.bzl",
+ }
name := android.RemoveOptionalPrebuiltPrefix(i.Name())
@@ -2990,8 +3148,14 @@
neverlinkAttrs := &javaLibraryAttributes{
Neverlink: bazel.BoolAttribute{Value: &neverlink},
Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
+ javaCommonAttributes: &javaCommonAttributes{
+ Sdk_version: bazel.StringAttribute{Value: proptools.StringPtr("none")},
+ },
}
- ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{Rule_class: "java_library"}, android.CommonAttributes{Name: name + "-neverlink"}, neverlinkAttrs)
+ ctx.CreateBazelTargetModule(
+ javaLibraryBazelTargetModuleProperties(),
+ android.CommonAttributes{Name: name + "-neverlink"},
+ neverlinkAttrs)
}
diff --git a/java/java_test.go b/java/java_test.go
index 68b749b..553b762 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -2209,6 +2209,50 @@
}
}
+func TestJavaApiLibraryDepApiSrcs(t *testing.T) {
+ provider_bp_a := `
+ java_api_contribution {
+ name: "foo1",
+ api_file: "foo1.txt",
+ }
+ `
+ provider_bp_b := `
+ java_api_contribution {
+ name: "foo2",
+ api_file: "foo2.txt",
+ }
+ `
+ lib_bp_a := `
+ java_api_library {
+ name: "lib1",
+ api_surface: "public",
+ api_contributions: ["foo1", "foo2"],
+ }
+ `
+
+ ctx, _ := testJavaWithFS(t, `
+ java_api_library {
+ name: "bar1",
+ api_surface: "public",
+ api_contributions: ["foo1"],
+ dep_api_srcs: "lib1",
+ }
+ `,
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ "c/Android.bp": []byte(lib_bp_a),
+ })
+
+ m := ctx.ModuleForTests("bar1", "android_common")
+ manifest := m.Output("metalava.sbox.textproto")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+ manifestCommand := sboxProto.Commands[0].GetCommand()
+
+ android.AssertStringDoesContain(t, "Command expected to contain module srcjar file", manifestCommand, "bar1-stubs.srcjar")
+ android.AssertStringDoesContain(t, "Command expected to contain output files list text file flag", manifestCommand, "--out __SBOX_SANDBOX_DIR__/out/sources.txt")
+}
+
func TestTradefedOptions(t *testing.T) {
result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, `
java_test_host {
diff --git a/java/legacy_core_platform_api_usage.go b/java/legacy_core_platform_api_usage.go
index 6cb549e..04c6d05 100644
--- a/java/legacy_core_platform_api_usage.go
+++ b/java/legacy_core_platform_api_usage.go
@@ -93,16 +93,16 @@
func corePlatformSystemModules(ctx android.EarlyModuleContext) string {
if useLegacyCorePlatformApi(ctx, ctx.ModuleName()) {
- return config.LegacyCorePlatformSystemModules
+ return android.JavaApiLibraryName(ctx.Config(), config.LegacyCorePlatformSystemModules)
} else {
- return config.StableCorePlatformSystemModules
+ return android.JavaApiLibraryName(ctx.Config(), config.StableCorePlatformSystemModules)
}
}
func corePlatformBootclasspathLibraries(ctx android.EarlyModuleContext) []string {
if useLegacyCorePlatformApi(ctx, ctx.ModuleName()) {
- return config.LegacyCorePlatformBootclasspathLibraries
+ return android.JavaApiLibraryNames(ctx.Config(), config.LegacyCorePlatformBootclasspathLibraries)
} else {
- return config.StableCorePlatformBootclasspathLibraries
+ return android.JavaApiLibraryNames(ctx.Config(), config.StableCorePlatformBootclasspathLibraries)
}
}
diff --git a/java/lint.go b/java/lint.go
index 58b43df..40ef484 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -496,7 +496,6 @@
FlagWithArg("--java-language-level ", l.javaLanguageLevel).
FlagWithArg("--kotlin-language-level ", l.kotlinLanguageLevel).
FlagWithArg("--url ", fmt.Sprintf(".=.,%s=out", android.PathForOutput(ctx).String())).
- Flag("--exitcode").
Flag("--apply-suggestions"). // applies suggested fixes to files in the sandbox
Flags(l.properties.Lint.Flags).
Implicit(annotationsZipPath).
@@ -505,6 +504,10 @@
rule.Temporary(lintPaths.projectXML)
rule.Temporary(lintPaths.configXML)
+ if exitCode := ctx.Config().Getenv("ANDROID_LINT_SUPPRESS_EXIT_CODE"); exitCode == "" {
+ cmd.Flag("--exitcode")
+ }
+
if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" {
cmd.FlagWithArg("--check ", checkOnly)
}
diff --git a/java/lint_defaults.txt b/java/lint_defaults.txt
index 061f4d0..1bb4996 100644
--- a/java/lint_defaults.txt
+++ b/java/lint_defaults.txt
@@ -40,6 +40,13 @@
# NewApi checks will continue to be enforced for apex deps since
# lint.strict_updatability_linting will be true for those Soong modules
--disable_check NewApi
+# Disable ChromeOS specific checks
+--disable_check PermissionImpliesUnsupportedChromeOsHardware
+# Disable UnsafeImplicitIntentLaunch until it can avoid false positives/crash
+# TODO(265425607)
+--disable_check UnsafeImplicitIntentLaunch
+# InvalidId will give errors on ids defined like android:id="@androidprv:id/contentPanel"
+--disable_check InvalidId
# Downgrade existing errors to warnings
--warning_check AppCompatResource # 55 occurences in 10 modules
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 5824f08..0ea3609 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -414,6 +414,7 @@
frameworkBootImageConfig := defaultBootImageConfig(ctx)
bootFrameworkProfileRule(ctx, frameworkBootImageConfig)
b.generateBootImage(ctx, frameworkBootImageName, platformModules)
+ b.generateBootImage(ctx, mainlineBootImageName, apexModules)
b.copyApexBootJarsForAppsDexpreopt(ctx, apexModules)
dumpOatRules(ctx, frameworkBootImageConfig)
}
diff --git a/java/proto.go b/java/proto.go
index 5280077..c732d98 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -143,7 +143,9 @@
}
type protoAttributes struct {
- Deps bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Sdk_version bazel.StringAttribute
+ Java_version bazel.StringAttribute
}
func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute) *bazel.Label {
@@ -175,8 +177,11 @@
}
protoLabel := bazel.Label{Label: ":" + m.Name() + "_proto"}
- var protoAttrs protoAttributes
- protoAttrs.Deps.SetValue(bazel.LabelList{Includes: []bazel.Label{protoLabel}})
+ protoAttrs := &protoAttributes{
+ Deps: bazel.MakeSingleLabelListAttribute(protoLabel),
+ Java_version: bazel.StringAttribute{Value: m.properties.Java_version},
+ Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
+ }
name := m.Name() + suffix
@@ -186,7 +191,7 @@
Bzl_load_location: "//build/bazel/rules/java:proto.bzl",
},
android.CommonAttributes{Name: name},
- &protoAttrs)
+ protoAttrs)
return &bazel.Label{Label: ":" + name}
}
diff --git a/java/rro.go b/java/rro.go
index 9d0667c..53faca0 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -175,19 +175,19 @@
return ""
}
-func (r *RuntimeResourceOverlay) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+func (r *RuntimeResourceOverlay) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
if r.properties.Min_sdk_version != nil {
- return android.SdkSpecFrom(ctx, *r.properties.Min_sdk_version)
+ return android.ApiLevelFrom(ctx, *r.properties.Min_sdk_version)
}
- return r.SdkVersion(ctx)
+ return r.SdkVersion(ctx).ApiLevel
}
-func (r *RuntimeResourceOverlay) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
- return android.SdkSpecFrom(ctx, "")
+func (r *RuntimeResourceOverlay) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
+ return android.SdkSpecPrivate.ApiLevel
}
-func (r *RuntimeResourceOverlay) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
- return r.SdkVersion(ctx)
+func (r *RuntimeResourceOverlay) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+ return r.SdkVersion(ctx).ApiLevel
}
func (r *RuntimeResourceOverlay) Certificate() Certificate {
diff --git a/java/sdk.go b/java/sdk.go
index 1e7727b..8b4918a 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -148,10 +148,11 @@
toModule := func(module string, aidl android.Path) sdkDep {
// Select the kind of system modules needed for the sdk version.
systemModulesKind := systemModuleKind(sdkVersion.Kind, android.FutureApiLevel)
+ systemModules := android.JavaApiLibraryName(ctx.Config(), fmt.Sprintf("core-%s-stubs-system-modules", systemModulesKind))
return sdkDep{
useModule: true,
- bootclasspath: []string{module, config.DefaultLambdaStubsLibrary},
- systemModules: fmt.Sprintf("core-%s-stubs-system-modules", systemModulesKind),
+ bootclasspath: []string{module, android.JavaApiLibraryName(ctx.Config(), config.DefaultLambdaStubsLibrary)},
+ systemModules: systemModules,
java9Classpath: []string{module},
frameworkResModule: "framework-res",
aidl: android.OptionalPathForPath(aidl),
@@ -191,25 +192,21 @@
bootclasspath: corePlatformBootclasspathLibraries(ctx),
noFrameworksLibs: true,
}
- case android.SdkPublic:
- return toModule("android_stubs_current", sdkFrameworkAidlPath(ctx))
- case android.SdkSystem:
- return toModule("android_system_stubs_current", sdkFrameworkAidlPath(ctx))
- case android.SdkTest:
- return toModule("android_test_stubs_current", sdkFrameworkAidlPath(ctx))
+ case android.SdkPublic, android.SdkSystem, android.SdkTest:
+ return toModule(sdkVersion.Kind.JavaLibraryName(ctx.Config()), sdkFrameworkAidlPath(ctx))
case android.SdkCore:
return sdkDep{
useModule: true,
- bootclasspath: []string{"core.current.stubs", config.DefaultLambdaStubsLibrary},
- systemModules: "core-public-stubs-system-modules",
+ bootclasspath: []string{android.SdkCore.JavaLibraryName(ctx.Config()), android.JavaApiLibraryName(ctx.Config(), config.DefaultLambdaStubsLibrary)},
+ systemModules: android.JavaApiLibraryName(ctx.Config(), "core-public-stubs-system-modules"),
noFrameworksLibs: true,
}
case android.SdkModule:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
- return toModule("android_module_lib_stubs_current", nonUpdatableFrameworkAidlPath(ctx))
+ return toModule(sdkVersion.Kind.JavaLibraryName(ctx.Config()), nonUpdatableFrameworkAidlPath(ctx))
case android.SdkSystemServer:
// TODO(146757305): provide .apk and .aidl that have more APIs for modules
- return toModule("android_system_server_stubs_current", sdkFrameworkAidlPath(ctx))
+ return toModule(sdkVersion.Kind.JavaLibraryName(ctx.Config()), sdkFrameworkAidlPath(ctx))
default:
panic(fmt.Errorf("invalid sdk %q", sdkVersion.Raw))
}
@@ -272,9 +269,9 @@
// Create framework.aidl by extracting anything that implements android.os.Parcelable from the SDK stubs modules.
func createSdkFrameworkAidl(ctx android.SingletonContext) {
stubsModules := []string{
- "android_stubs_current",
- "android_test_stubs_current",
- "android_system_stubs_current",
+ android.SdkPublic.JavaLibraryName(ctx.Config()),
+ android.SdkTest.JavaLibraryName(ctx.Config()),
+ android.SdkSystem.JavaLibraryName(ctx.Config()),
}
combinedAidl := sdkFrameworkAidlPath(ctx)
@@ -289,7 +286,7 @@
// Creates a version of framework.aidl for the non-updatable part of the platform.
func createNonUpdatableFrameworkAidl(ctx android.SingletonContext) {
- stubsModules := []string{"android_module_lib_stubs_current"}
+ stubsModules := []string{android.SdkModule.JavaLibraryName(ctx.Config())}
combinedAidl := nonUpdatableFrameworkAidlPath(ctx)
tempPath := tempPathForRestat(ctx, combinedAidl)
diff --git a/java/sdk_library.go b/java/sdk_library.go
index d2fbfd9..103f1ac 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1231,7 +1231,7 @@
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) {
+ android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx), 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 {
@@ -1267,7 +1267,10 @@
func (module *SdkLibrary) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
for _, apiScope := range module.getGeneratedApiScopes(ctx) {
// Add dependencies to the stubs library
- ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsLibraryModuleName(apiScope))
+ stubModuleName := module.stubsLibraryModuleName(apiScope)
+ // Use JavaApiLibraryName function to be redirected to stubs generated from .txt if applicable
+ stubModuleName = android.JavaApiLibraryName(ctx.Config(), stubModuleName)
+ ctx.AddVariationDependencies(nil, apiScope.stubsTag, stubModuleName)
// Add a dependency on the stubs source in order to access both stubs source and api information.
ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceModuleName(apiScope))
@@ -1775,7 +1778,7 @@
// Creates the xml file that publicizes the runtime library
func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
- moduleMinApiLevel := module.Library.MinSdkVersion(mctx).ApiLevel
+ moduleMinApiLevel := module.Library.MinSdkVersion(mctx)
var moduleMinApiLevelStr = moduleMinApiLevel.String()
if moduleMinApiLevel == android.NoneApiLevel {
moduleMinApiLevelStr = "current"
@@ -2414,8 +2417,8 @@
}
// MinSdkVersion - Implements hiddenAPIModule
-func (module *SdkLibraryImport) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
- return android.SdkSpecNone
+func (module *SdkLibraryImport) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+ return android.NoneApiLevel
}
var _ hiddenAPIModule = (*SdkLibraryImport)(nil)
diff --git a/java/testing.go b/java/testing.go
index 63d7dba..f68e12f 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -368,6 +368,7 @@
"core.current.stubs",
"legacy.core.platform.api.stubs",
"stable.core.platform.api.stubs",
+
"kotlin-stdlib",
"kotlin-stdlib-jdk7",
"kotlin-stdlib-jdk8",
@@ -387,6 +388,28 @@
`, extra)
}
+ extraApiLibraryModules := map[string]string{
+ "android_stubs_current.from-text": "api/current.txt",
+ "android_system_stubs_current.from-text": "api/system-current.txt",
+ "android_test_stubs_current.from-text": "api/test-current.txt",
+ "android_module_lib_stubs_current.from-text": "api/module-lib-current.txt",
+ "android_module_lib_stubs_current_full.from-text": "api/module-lib-current.txt",
+ "android_system_server_stubs_current.from-text": "api/system-server-current.txt",
+ "core.current.stubs.from-text": "api/current.txt",
+ "legacy.core.platform.api.stubs.from-text": "api/current.txt",
+ "stable.core.platform.api.stubs.from-text": "api/current.txt",
+ "core-lambda-stubs.from-text": "api/current.txt",
+ }
+
+ for libName, apiFile := range extraApiLibraryModules {
+ bp += fmt.Sprintf(`
+ java_api_library {
+ name: "%s",
+ api_files: ["%s"],
+ }
+ `, libName, apiFile)
+ }
+
bp += `
java_library {
name: "framework",
@@ -409,6 +432,10 @@
"core-module-lib-stubs-system-modules",
"legacy-core-platform-api-stubs-system-modules",
"stable-core-platform-api-stubs-system-modules",
+ "core-public-stubs-system-modules.from-text",
+ "core-module-lib-stubs-system-modules.from-text",
+ "legacy-core-platform-api-stubs-system-modules.from-text",
+ "stable-core-platform-api-stubs-system-modules.from-text",
}
for _, extra := range systemModules {
diff --git a/licenses/Android.bp b/licenses/Android.bp
index 7267cf3..dee72ed 100644
--- a/licenses/Android.bp
+++ b/licenses/Android.bp
@@ -923,7 +923,10 @@
license_kind {
name: "SPDX-license-identifier-Linux-syscall-note",
// expanding visibility requires approval from an OSPO lawyer or pcounsel
- visibility: ["//external/libbpf:__subpackages__"],
+ visibility: [
+ "//external/libbpf:__subpackages__",
+ "//prebuilts/vsdk:__subpackages__",
+ ],
conditions: ["permissive"],
url: "https://spdx.org/licenses/Linux-syscall-note.html",
}
diff --git a/mk2rbc/Android.bp b/mk2rbc/Android.bp
index 4fa3eb6..cd80a4d 100644
--- a/mk2rbc/Android.bp
+++ b/mk2rbc/Android.bp
@@ -19,7 +19,7 @@
blueprint_go_binary {
name: "mk2rbc",
- srcs: ["cmd/mk2rbc.go"],
+ srcs: ["mk2rbc/mk2rbc.go"],
deps: [
"mk2rbc-lib",
"androidmk-parser",
diff --git a/mk2rbc/cmd/mk2rbc.go b/mk2rbc/mk2rbc/mk2rbc.go
similarity index 100%
rename from mk2rbc/cmd/mk2rbc.go
rename to mk2rbc/mk2rbc/mk2rbc.go
diff --git a/mk2rbc/soong_variables.go b/mk2rbc/soong_variables.go
index a52ec4f..7a6aa5f 100644
--- a/mk2rbc/soong_variables.go
+++ b/mk2rbc/soong_variables.go
@@ -67,7 +67,11 @@
var valueType starlarkType
switch typeString {
case "bool":
- valueType = starlarkTypeBool
+ // TODO: We run into several issues later on if we type this as a bool:
+ // - We still assign bool-typed variables to strings
+ // - When emitting the final results as make code, some bool's false values have to
+ // be an empty string, and some have to be false in order to match the make variables.
+ valueType = starlarkTypeString
case "csv":
// Only PLATFORM_VERSION_ALL_CODENAMES, and it's a list
valueType = starlarkTypeList
diff --git a/python/binary.go b/python/binary.go
index 75135f3..a5db2f6 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -37,7 +37,7 @@
// this file must also be listed in srcs.
// If left unspecified, module name is used instead.
// If name doesn’t match any filename in srcs, main must be specified.
- Main *string `android:"arch_variant"`
+ Main *string
// set the name of the output binary.
Stem *string `android:"arch_variant"`
diff --git a/python/bp2build.go b/python/bp2build.go
index bdac2dc..cd3f2a1 100644
--- a/python/bp2build.go
+++ b/python/bp2build.go
@@ -15,7 +15,6 @@
package python
import (
- "fmt"
"path/filepath"
"strings"
@@ -118,42 +117,19 @@
return attrs
}
-func pythonLibBp2Build(ctx android.TopDownMutatorContext, m *PythonLibraryModule) {
- // 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.
+func (m *PythonLibraryModule) bp2buildPythonVersion(ctx android.TopDownMutatorContext) *string {
py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, true)
py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
- var python_version *string
if py2Enabled && !py3Enabled {
- python_version = &pyVersion2
+ return &pyVersion2
} else if !py2Enabled && py3Enabled {
- python_version = &pyVersion3
+ return &pyVersion3
} else if !py2Enabled && !py3Enabled {
ctx.ModuleErrorf("bp2build converter doesn't understand having neither py2 nor py3 enabled")
+ return &pyVersion3
} else {
- // do nothing, since python_version defaults to PY2ANDPY3
+ return &pyVersion2And3
}
-
- baseAttrs := m.makeArchVariantBaseAttributes(ctx)
-
- attrs := &bazelPythonLibraryAttributes{
- Srcs: baseAttrs.Srcs,
- Deps: baseAttrs.Deps,
- Srcs_version: python_version,
- Imports: baseAttrs.Imports,
- }
-
- props := bazel.BazelTargetModuleProperties{
- // Use the native py_library rule.
- Rule_class: "py_library",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: m.Name(),
- Data: baseAttrs.Data,
- }, attrs)
}
type bazelPythonBinaryAttributes struct {
@@ -164,43 +140,71 @@
Imports bazel.StringListAttribute
}
-func pythonBinaryBp2Build(ctx android.TopDownMutatorContext, m *PythonBinaryModule) {
+func (p *PythonLibraryModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ // 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.
+ baseAttrs := p.makeArchVariantBaseAttributes(ctx)
+ pyVersion := p.bp2buildPythonVersion(ctx)
+ if *pyVersion == pyVersion2And3 {
+ // Libraries default to python 2 and 3
+ pyVersion = nil
+ }
+
+ attrs := &bazelPythonLibraryAttributes{
+ Srcs: baseAttrs.Srcs,
+ Deps: baseAttrs.Deps,
+ Srcs_version: pyVersion,
+ Imports: baseAttrs.Imports,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ // Use the native py_library rule.
+ Rule_class: "py_library",
+ }
+
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{
+ Name: p.Name(),
+ Data: baseAttrs.Data,
+ }, attrs)
+}
+
+func (p *PythonBinaryModule) bp2buildBinaryProperties(ctx android.TopDownMutatorContext) (*bazelPythonBinaryAttributes, bazel.LabelListAttribute) {
// 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_binary_host modules
// under Bionic.
- py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, false)
- py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
- 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 = &pyVersion2
- } else {
- // do nothing, since python_version defaults to PY3.
+
+ baseAttrs := p.makeArchVariantBaseAttributes(ctx)
+ pyVersion := p.bp2buildPythonVersion(ctx)
+ if *pyVersion == pyVersion3 {
+ // Binaries default to python 3
+ pyVersion = nil
+ } else if *pyVersion == pyVersion2And3 {
+ ctx.ModuleErrorf("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.", p.Name())
}
- baseAttrs := m.makeArchVariantBaseAttributes(ctx)
attrs := &bazelPythonBinaryAttributes{
Main: nil,
Srcs: baseAttrs.Srcs,
Deps: baseAttrs.Deps,
- Python_version: python_version,
+ Python_version: pyVersion,
Imports: baseAttrs.Imports,
}
- for _, propIntf := range m.GetProperties() {
- if props, ok := propIntf.(*BinaryProperties); ok {
- // main is optional.
- if props.Main != nil {
- main := android.BazelLabelForModuleSrcSingle(ctx, *props.Main)
- attrs.Main = &main
- break
- }
- }
+ // main is optional.
+ if p.binaryProperties.Main != nil {
+ main := android.BazelLabelForModuleSrcSingle(ctx, *p.binaryProperties.Main)
+ attrs.Main = &main
}
+ return attrs, baseAttrs.Data
+}
+
+func (p *PythonBinaryModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ attrs, data := p.bp2buildBinaryProperties(ctx)
props := bazel.BazelTargetModuleProperties{
// Use the native py_binary rule.
@@ -208,19 +212,22 @@
}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: m.Name(),
- Data: baseAttrs.Data,
+ Name: p.Name(),
+ Data: data,
}, attrs)
}
-func (p *PythonLibraryModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- pythonLibBp2Build(ctx, p)
-}
+func (p *PythonTestModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ // Python tests are currently exactly the same as binaries, but with a different module type
+ attrs, data := p.bp2buildBinaryProperties(ctx)
-func (p *PythonBinaryModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- pythonBinaryBp2Build(ctx, p)
-}
+ props := bazel.BazelTargetModuleProperties{
+ // Use the native py_binary rule.
+ Rule_class: "py_test",
+ }
-func (p *PythonTestModule) ConvertWithBp2build(_ android.TopDownMutatorContext) {
- // Tests are currently unsupported
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{
+ Name: p.Name(),
+ Data: data,
+ }, attrs)
}
diff --git a/python/python.go b/python/python.go
index 0ae7b36..1a12973 100644
--- a/python/python.go
+++ b/python/python.go
@@ -239,6 +239,7 @@
protoExt = ".proto"
pyVersion2 = "PY2"
pyVersion3 = "PY3"
+ pyVersion2And3 = "PY2ANDPY3"
internalPath = "internal"
)
@@ -263,6 +264,12 @@
versionProps = append(versionProps, props.Version.Py3)
}
if proptools.BoolDefault(props.Version.Py2.Enabled, false) {
+ if !mctx.DeviceConfig().BuildBrokenUsesSoongPython2Modules() &&
+ mctx.ModuleName() != "par_test" &&
+ mctx.ModuleName() != "py2-cmd" &&
+ mctx.ModuleName() != "py2-stdlib" {
+ mctx.PropertyErrorf("version.py2.enabled", "Python 2 is no longer supported, please convert to python 3. This error can be temporarily overridden by setting BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES := true in the product configuration")
+ }
versionNames = append(versionNames, pyVersion2)
versionProps = append(versionProps, props.Version.Py2)
}
diff --git a/python/scripts/stub_template_host.txt b/python/scripts/stub_template_host.txt
index 5eedc18..2d1bd4a 100644
--- a/python/scripts/stub_template_host.txt
+++ b/python/scripts/stub_template_host.txt
@@ -3,6 +3,7 @@
import os
import tempfile
import shutil
+import signal
import sys
import subprocess
import zipfile
@@ -43,7 +44,18 @@
sys.stdout.flush()
# close_fds=False so that you can run binaries with files provided on the command line:
# my_python_app --file <(echo foo)
- sys.exit(subprocess.call(args, close_fds=False))
+ p = subprocess.Popen(args, close_fds=False)
+
+ def handler(sig, frame):
+ p.send_signal(sig)
+
+ # Redirect SIGINT and SIGTERM to subprocess
+ signal.signal(signal.SIGINT, handler)
+ signal.signal(signal.SIGTERM, handler)
+
+ p.wait()
+
+ sys.exit(p.returncode)
finally:
shutil.rmtree(runfiles_path, ignore_errors=True)
diff --git a/python/test.go b/python/test.go
index fb8e918..31da17e 100644
--- a/python/test.go
+++ b/python/test.go
@@ -15,6 +15,8 @@
package python
import (
+ "fmt"
+
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -63,7 +65,22 @@
Java_data []string
// Test options.
- Test_options android.CommonTestOptions
+ Test_options TestOptions
+}
+
+type TestOptions struct {
+ android.CommonTestOptions
+
+ // Runner for the test. Supports "tradefed" and "mobly" (for multi-device tests). Default is "tradefed".
+ Runner *string
+
+ // Metadata to describe the test configuration.
+ Metadata []Metadata
+}
+
+type Metadata struct {
+ Name string
+ Value string
}
type PythonTestModule struct {
@@ -94,14 +111,41 @@
p.PythonLibraryModule.GenerateAndroidBuildActions(ctx)
p.buildBinary(ctx)
- p.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
- TestConfigProp: p.testProperties.Test_config,
- TestConfigTemplateProp: p.testProperties.Test_config_template,
- TestSuites: p.binaryProperties.Test_suites,
- AutoGenConfig: p.binaryProperties.Auto_gen_config,
- DeviceTemplate: "${PythonBinaryHostTestConfigTemplate}",
- HostTemplate: "${PythonBinaryHostTestConfigTemplate}",
- })
+ var configs []tradefed.Option
+ for _, metadata := range p.testProperties.Test_options.Metadata {
+ configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: metadata.Name, Value: metadata.Value})
+ }
+
+ runner := proptools.StringDefault(p.testProperties.Test_options.Runner, "tradefed")
+ if runner == "tradefed" {
+ p.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
+ TestConfigProp: p.testProperties.Test_config,
+ TestConfigTemplateProp: p.testProperties.Test_config_template,
+ TestSuites: p.binaryProperties.Test_suites,
+ OptionsForAutogenerated: configs,
+ AutoGenConfig: p.binaryProperties.Auto_gen_config,
+ DeviceTemplate: "${PythonBinaryHostTestConfigTemplate}",
+ HostTemplate: "${PythonBinaryHostTestConfigTemplate}",
+ })
+ } else if runner == "mobly" {
+ if p.testProperties.Test_config != nil || p.testProperties.Test_config_template != nil || p.binaryProperties.Auto_gen_config != nil {
+ panic(fmt.Errorf("cannot set test_config, test_config_template or auto_gen_config for mobly test"))
+ }
+
+ for _, testSuite := range p.binaryProperties.Test_suites {
+ if testSuite == "cts" {
+ configs = append(configs, tradefed.Option{Name: "test-suite-tag", Value: "cts"})
+ break
+ }
+ }
+ p.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
+ OptionsForAutogenerated: configs,
+ DeviceTemplate: "${PythonBinaryHostMoblyTestConfigTemplate}",
+ HostTemplate: "${PythonBinaryHostMoblyTestConfigTemplate}",
+ })
+ } else {
+ panic(fmt.Errorf("unknown python test runner '%s', should be 'tradefed' or 'mobly'", runner))
+ }
p.installedDest = ctx.InstallFile(installDir(ctx, "nativetest", "nativetest64", ctx.ModuleName()), p.installSource.Base(), p.installSource)
diff --git a/rust/Android.bp b/rust/Android.bp
index 3fd68e5..b01a94a 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -42,6 +42,7 @@
"toolchain_library.go",
],
testSrcs: [
+ "afdo_test.go",
"benchmark_test.go",
"binary_test.go",
"bindgen_test.go",
diff --git a/rust/afdo.go b/rust/afdo.go
index 996fd7e..3534ee6 100644
--- a/rust/afdo.go
+++ b/rust/afdo.go
@@ -17,7 +17,10 @@
import (
"fmt"
+ "android/soong/android"
"android/soong/cc"
+
+ "github.com/google/blueprint"
)
const afdoFlagFormat = "-Zprofile-sample-use=%s"
@@ -30,19 +33,49 @@
return []interface{}{&afdo.Properties}
}
-func (afdo *afdo) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) {
+func (afdo *afdo) addDep(ctx BaseModuleContext, actx android.BottomUpMutatorContext) {
+ // afdo is not supported outside of Android
+ if ctx.Host() {
+ return
+ }
+
+ if mod, ok := ctx.Module().(*Module); ok && mod.Enabled() {
+ fdoProfileName, err := actx.DeviceConfig().AfdoProfile(actx.ModuleName())
+ if err != nil {
+ ctx.ModuleErrorf("%s", err.Error())
+ }
+ if fdoProfileName != nil {
+ actx.AddFarVariationDependencies(
+ []blueprint.Variation{
+ {Mutator: "arch", Variation: actx.Target().ArchVariation()},
+ {Mutator: "os", Variation: "android"},
+ },
+ cc.FdoProfileTag,
+ []string{*fdoProfileName}...,
+ )
+ }
+ }
+}
+
+func (afdo *afdo) flags(ctx android.ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) {
if ctx.Host() {
return flags, deps
}
- if afdo != nil && afdo.Properties.Afdo {
- if profileFile := afdo.Properties.GetAfdoProfileFile(ctx, ctx.ModuleName()); profileFile.Valid() {
- profileUseFlag := fmt.Sprintf(afdoFlagFormat, profileFile)
+ if !afdo.Properties.Afdo {
+ return flags, deps
+ }
+
+ ctx.VisitDirectDepsWithTag(cc.FdoProfileTag, func(m android.Module) {
+ if ctx.OtherModuleHasProvider(m, cc.FdoProfileProvider) {
+ info := ctx.OtherModuleProvider(m, cc.FdoProfileProvider).(cc.FdoProfileInfo)
+ path := info.Path
+ profileUseFlag := fmt.Sprintf(afdoFlagFormat, path.String())
flags.RustFlags = append(flags.RustFlags, profileUseFlag)
- profileFilePath := profileFile.Path()
- deps.AfdoProfiles = append(deps.AfdoProfiles, profileFilePath)
+ deps.AfdoProfiles = append(deps.AfdoProfiles, path)
}
- }
+ })
+
return flags, deps
}
diff --git a/rust/afdo_test.go b/rust/afdo_test.go
new file mode 100644
index 0000000..0cdf704
--- /dev/null
+++ b/rust/afdo_test.go
@@ -0,0 +1,112 @@
+// Copyright 2023 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 rust
+
+import (
+ "android/soong/android"
+ "android/soong/cc"
+ "fmt"
+ "strings"
+ "testing"
+)
+
+func TestAfdoEnabled(t *testing.T) {
+ bp := `
+ rust_binary {
+ name: "foo",
+ srcs: ["foo.rs"],
+ afdo: true,
+ }
+`
+ result := android.GroupFixturePreparers(
+ prepareForRustTest,
+ cc.PrepareForTestWithFdoProfile,
+ android.FixtureAddTextFile("afdo_profiles_package/foo.afdo", ""),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.AfdoProfiles = []string{
+ "foo://afdo_profiles_package:foo_afdo",
+ }
+ }),
+ android.MockFS{
+ "afdo_profiles_package/Android.bp": []byte(`
+ fdo_profile {
+ name: "foo_afdo",
+ profile: "foo.afdo",
+ }
+ `),
+ }.AddToFixture(),
+ rustMockedFiles.AddToFixture(),
+ ).RunTestWithBp(t, bp)
+
+ foo := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
+
+ expectedCFlag := fmt.Sprintf(afdoFlagFormat, "afdo_profiles_package/foo.afdo")
+
+ if !strings.Contains(foo.Args["rustcFlags"], expectedCFlag) {
+ t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", expectedCFlag, foo.Args["rustcFlags"])
+ }
+}
+
+func TestAfdoEnabledWithMultiArchs(t *testing.T) {
+ bp := `
+ rust_binary {
+ name: "foo",
+ srcs: ["foo.rs"],
+ afdo: true,
+ compile_multilib: "both",
+ }
+`
+ result := android.GroupFixturePreparers(
+ prepareForRustTest,
+ cc.PrepareForTestWithFdoProfile,
+ android.FixtureAddTextFile("afdo_profiles_package/foo_arm.afdo", ""),
+ android.FixtureAddTextFile("afdo_profiles_package/foo_arm64.afdo", ""),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.AfdoProfiles = []string{
+ "foo://afdo_profiles_package:foo_afdo",
+ }
+ }),
+ android.MockFS{
+ "afdo_profiles_package/Android.bp": []byte(`
+ fdo_profile {
+ name: "foo_afdo",
+ arch: {
+ arm: {
+ profile: "foo_arm.afdo",
+ },
+ arm64: {
+ profile: "foo_arm64.afdo",
+ }
+ }
+ }
+ `),
+ }.AddToFixture(),
+ rustMockedFiles.AddToFixture(),
+ ).RunTestWithBp(t, bp)
+
+ fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon").Rule("rustc")
+ fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
+
+ expectedCFlagArm := fmt.Sprintf(afdoFlagFormat, "afdo_profiles_package/foo_arm.afdo")
+ expectedCFlagArm64 := fmt.Sprintf(afdoFlagFormat, "afdo_profiles_package/foo_arm64.afdo")
+
+ if !strings.Contains(fooArm.Args["rustcFlags"], expectedCFlagArm) {
+ t.Errorf("Expected 'fooArm' to enable afdo, but did not find %q in cflags %q", expectedCFlagArm, fooArm.Args["rustcFlags"])
+ }
+
+ if !strings.Contains(fooArm64.Args["rustcFlags"], expectedCFlagArm64) {
+ t.Errorf("Expected 'fooArm64' to enable afdo, but did not find %q in cflags %q", expectedCFlagArm64, fooArm64.Args["rustcFlags"])
+ }
+}
diff --git a/rust/androidmk.go b/rust/androidmk.go
index 20e9919..5e680b0 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -43,6 +43,10 @@
}
}
+func (mod *Module) AndroidMkSuffix() string {
+ return mod.Properties.RustSubName + mod.Properties.SubName
+}
+
func (mod *Module) AndroidMkEntries() []android.AndroidMkEntries {
if mod.Properties.HideFromMake || mod.hideApexVariantFromMake {
@@ -79,8 +83,7 @@
mod.SubAndroidMk(&ret, mod.sanitize)
}
- ret.SubName += mod.Properties.RustSubName
- ret.SubName += mod.Properties.SubName
+ ret.SubName += mod.AndroidMkSuffix()
return []android.AndroidMkEntries{ret}
}
@@ -152,6 +155,11 @@
})
}
+func (library *snapshotLibraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
+ ctx.SubAndroidMk(ret, library.libraryDecorator)
+ ret.SubName = library.SnapshotAndroidMkSuffix()
+}
+
func (procMacro *procMacroDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
ctx.SubAndroidMk(ret, procMacro.baseCompiler)
diff --git a/rust/binary.go b/rust/binary.go
index 056888e..2de92c1 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -72,11 +72,14 @@
func (binary *binaryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
flags = binary.baseCompiler.compilerFlags(ctx, flags)
+ if ctx.Os().Linux() {
+ flags.LinkFlags = append(flags.LinkFlags, "-Wl,--gc-sections")
+ }
+
if ctx.toolchain().Bionic() {
// no-undefined-version breaks dylib compilation since __rust_*alloc* functions aren't defined,
// but we can apply this to binaries.
flags.LinkFlags = append(flags.LinkFlags,
- "-Wl,--gc-sections",
"-Wl,-z,nocopyreloc",
"-Wl,--no-undefined-version")
@@ -136,7 +139,7 @@
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
- flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects.Strings()...)
if binary.stripper.NeedsStrip(ctx) {
strippedOutputFile := outputFile
diff --git a/rust/binary_test.go b/rust/binary_test.go
index 7dac249..dd4f993 100644
--- a/rust/binary_test.go
+++ b/rust/binary_test.go
@@ -123,7 +123,7 @@
bootstrap: true,
}`)
- foo := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
+ foo := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustLink")
flag := "-Wl,-dynamic-linker,/system/bin/bootstrap/linker64"
if !strings.Contains(foo.Args["linkFlags"], flag) {
@@ -140,10 +140,11 @@
}`)
fizzOut := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Rule("rustc")
+ fizzOutLink := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Rule("rustLink")
fizzMod := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Module().(*Module)
flags := fizzOut.Args["rustcFlags"]
- linkFlags := fizzOut.Args["linkFlags"]
+ linkFlags := fizzOutLink.Args["linkFlags"]
if !strings.Contains(flags, "-C relocation-model=static") {
t.Errorf("static binary missing '-C relocation-model=static' in rustcFlags, found: %#v", flags)
}
@@ -173,7 +174,7 @@
name: "libfoo",
}`)
- fizzBuzz := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Rule("rustc")
+ fizzBuzz := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Rule("rustLink")
linkFlags := fizzBuzz.Args["linkFlags"]
if !strings.Contains(linkFlags, "/libfoo.so") {
t.Errorf("missing shared dependency 'libfoo.so' in linkFlags: %#v", linkFlags)
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 8cec918..13fa81e 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -29,7 +29,7 @@
defaultBindgenFlags = []string{""}
// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
- bindgenClangVersion = "clang-r475365b"
+ bindgenClangVersion = "clang-r487747"
_ = 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 4b20e2b..0aa2225 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -26,14 +26,14 @@
var (
_ = pctx.SourcePathVariable("rustcCmd", "${config.RustBin}/rustc")
+ _ = pctx.SourcePathVariable("mkcraterspCmd", "build/soong/scripts/mkcratersp.py")
rustc = pctx.AndroidStaticRule("rustc",
blueprint.RuleParams{
Command: "$envVars $rustcCmd " +
- "-C linker=${config.RustLinker} " +
- "-C link-args=\"${crtBegin} ${config.RustLinkerArgs} ${linkFlags} ${crtEnd}\" " +
+ "-C linker=$mkcraterspCmd " +
"--emit link -o $out --emit dep-info=$out.d.raw $in ${libFlags} $rustcFlags" +
" && grep \"^$out:\" $out.d.raw > $out.d",
- CommandDeps: []string{"$rustcCmd"},
+ CommandDeps: []string{"$rustcCmd", "$mkcraterspCmd"},
// Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633
// Rustc emits unneeded dependency lines for the .d and input .rs files.
// Those extra lines cause ninja warning:
@@ -42,7 +42,12 @@
Deps: blueprint.DepsGCC,
Depfile: "$out.d",
},
- "rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "envVars")
+ "rustcFlags", "libFlags", "envVars")
+ rustLink = pctx.AndroidStaticRule("rustLink",
+ blueprint.RuleParams{
+ Command: "${config.RustLinker} -o $out ${crtBegin} ${config.RustLinkerArgs} @$in ${linkFlags} ${crtEnd}",
+ },
+ "linkFlags", "crtBegin", "crtEnd")
_ = pctx.SourcePathVariable("rustdocCmd", "${config.RustBin}/rustdoc")
rustdoc = pctx.AndroidStaticRule("rustdoc",
@@ -101,14 +106,13 @@
`KYTHE_CANONICALIZE_VNAME_PATHS=prefer-relative ` +
`$rustExtractor $envVars ` +
`$rustcCmd ` +
- `-C linker=${config.RustLinker} ` +
- `-C link-args="${crtBegin} ${config.RustLinkerArgs} ${linkFlags} ${crtEnd}" ` +
+ `-C linker=true ` +
`$in ${libFlags} $rustcFlags`,
CommandDeps: []string{"$rustExtractor", "$kytheVnames"},
Rspfile: "${out}.rsp",
RspfileContent: "$in",
},
- "rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "envVars")
+ "rustcFlags", "libFlags", "envVars")
)
type buildOutput struct {
@@ -208,6 +212,9 @@
outDirPrefix = ""
}
envVars = append(envVars, "OUT_DIR="+filepath.Join(outDirPrefix, moduleGenDir.String()))
+ } else {
+ // TODO(pcc): Change this to "OUT_DIR=" after fixing crates to not rely on this value.
+ envVars = append(envVars, "OUT_DIR=out")
}
return envVars
@@ -217,10 +224,9 @@
outputFile android.WritablePath, crateType string) buildOutput {
var inputs android.Paths
- var implicits android.Paths
+ var implicits, linkImplicits, linkOrderOnly android.Paths
var output buildOutput
var rustcFlags, linkFlags []string
- var implicitOutputs android.WritablePaths
output.outputFile = outputFile
crateName := ctx.RustModule().CrateName()
@@ -255,7 +261,7 @@
// Disallow experimental features
modulePath := android.PathForModuleSrc(ctx).String()
if !(android.IsThirdPartyPath(modulePath) || strings.HasPrefix(modulePath, "prebuilts")) {
- rustcFlags = append(rustcFlags, "-Zallow-features=\"default_alloc_error_handler,custom_inner_attributes,mixed_integer_ops\"")
+ rustcFlags = append(rustcFlags, "-Zallow-features=\"custom_inner_attributes,mixed_integer_ops\"")
}
// Collect linker flags
@@ -277,13 +283,15 @@
implicits = append(implicits, rustLibsToPaths(deps.RLibs)...)
implicits = append(implicits, rustLibsToPaths(deps.DyLibs)...)
implicits = append(implicits, rustLibsToPaths(deps.ProcMacros)...)
- implicits = append(implicits, deps.StaticLibs...)
- implicits = append(implicits, deps.SharedLibDeps...)
- implicits = append(implicits, deps.srcProviderFiles...)
implicits = append(implicits, deps.AfdoProfiles...)
+ implicits = append(implicits, deps.srcProviderFiles...)
+ implicits = append(implicits, deps.WholeStaticLibs...)
- implicits = append(implicits, deps.CrtBegin...)
- implicits = append(implicits, deps.CrtEnd...)
+ linkImplicits = append(linkImplicits, deps.LibDeps...)
+ linkImplicits = append(linkImplicits, deps.CrtBegin...)
+ linkImplicits = append(linkImplicits, deps.CrtEnd...)
+
+ linkOrderOnly = append(linkOrderOnly, deps.linkObjects...)
if len(deps.SrcDeps) > 0 {
moduleGenDir := ctx.RustModule().compiler.CargoOutDir()
@@ -322,15 +330,16 @@
}
}
+ envVars = append(envVars, "AR=${cc_config.ClangBin}/llvm-ar")
+
if flags.Clippy {
clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy")
ctx.Build(pctx, android.BuildParams{
- Rule: clippyDriver,
- Description: "clippy " + main.Rel(),
- Output: clippyFile,
- ImplicitOutputs: nil,
- Inputs: inputs,
- Implicits: implicits,
+ Rule: clippyDriver,
+ Description: "clippy " + main.Rel(),
+ Output: clippyFile,
+ Inputs: inputs,
+ Implicits: implicits,
Args: map[string]string{
"rustcFlags": strings.Join(rustcFlags, " "),
"libFlags": strings.Join(libFlags, " "),
@@ -342,23 +351,41 @@
implicits = append(implicits, clippyFile)
}
+ rustcOutputFile := outputFile
+ usesLinker := crateType == "bin" || crateType == "dylib" || crateType == "cdylib" || crateType == "proc-macro"
+ if usesLinker {
+ rustcOutputFile = android.PathForModuleOut(ctx, outputFile.Base()+".rsp")
+ }
+
ctx.Build(pctx, android.BuildParams{
- Rule: rustc,
- Description: "rustc " + main.Rel(),
- Output: outputFile,
- ImplicitOutputs: implicitOutputs,
- Inputs: inputs,
- Implicits: implicits,
+ Rule: rustc,
+ Description: "rustc " + main.Rel(),
+ Output: rustcOutputFile,
+ Inputs: inputs,
+ Implicits: implicits,
Args: map[string]string{
"rustcFlags": strings.Join(rustcFlags, " "),
- "linkFlags": strings.Join(linkFlags, " "),
"libFlags": strings.Join(libFlags, " "),
- "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
- "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
"envVars": strings.Join(envVars, " "),
},
})
+ if usesLinker {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: rustLink,
+ Description: "rustLink " + main.Rel(),
+ Output: outputFile,
+ Inputs: android.Paths{rustcOutputFile},
+ Implicits: linkImplicits,
+ OrderOnly: linkOrderOnly,
+ Args: map[string]string{
+ "linkFlags": strings.Join(linkFlags, " "),
+ "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
+ "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
+ },
+ })
+ }
+
if flags.EmitXrefs {
kytheFile := android.PathForModuleOut(ctx, outputFile.Base()+".kzip")
ctx.Build(pctx, android.BuildParams{
@@ -369,10 +396,7 @@
Implicits: implicits,
Args: map[string]string{
"rustcFlags": strings.Join(rustcFlags, " "),
- "linkFlags": strings.Join(linkFlags, " "),
"libFlags": strings.Join(libFlags, " "),
- "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
- "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
"envVars": strings.Join(envVars, " "),
},
})
diff --git a/rust/config/global.go b/rust/config/global.go
index 9375022..2d1f0c1 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
var pctx = android.NewPackageContext("android/soong/rust/config")
var (
- RustDefaultVersion = "1.67.1"
+ RustDefaultVersion = "1.68.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2021"
Stdlibs = []string{
@@ -104,7 +104,7 @@
pctx.ImportAs("cc_config", "android/soong/cc/config")
pctx.StaticVariable("RustLinker", "${cc_config.ClangBin}/clang++")
- pctx.StaticVariable("RustLinkerArgs", "")
+ pctx.StaticVariable("RustLinkerArgs", "-Wl,--as-needed")
pctx.StaticVariable("DeviceGlobalLinkFlags", strings.Join(deviceGlobalLinkFlags, " "))
diff --git a/rust/coverage.go b/rust/coverage.go
index bc6504d..5216d60 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -65,7 +65,7 @@
"-C instrument-coverage", "-g")
flags.LinkFlags = append(flags.LinkFlags,
profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open")
- deps.StaticLibs = append(deps.StaticLibs, coverage.OutputFile().Path())
+ deps.LibDeps = append(deps.LibDeps, coverage.OutputFile().Path())
// no_std modules are missing libprofiler_builtins which provides coverage, so we need to add it as a dependency.
if rustModule, ok := ctx.Module().(*Module); ok && rustModule.compiler.noStdlibs() {
diff --git a/rust/coverage_test.go b/rust/coverage_test.go
index 0f599d7..64077cf 100644
--- a/rust/coverage_test.go
+++ b/rust/coverage_test.go
@@ -55,6 +55,10 @@
libbarNoCov := ctx.ModuleForTests("libbar_nocov", "android_arm64_armv8-a_dylib").Rule("rustc")
fizzCov := ctx.ModuleForTests("fizz_cov", "android_arm64_armv8-a_cov").Rule("rustc")
buzzNoCov := ctx.ModuleForTests("buzzNoCov", "android_arm64_armv8-a").Rule("rustc")
+ libfooCovLink := ctx.ModuleForTests("libfoo_cov", "android_arm64_armv8-a_dylib_cov").Rule("rustLink")
+ libbarNoCovLink := ctx.ModuleForTests("libbar_nocov", "android_arm64_armv8-a_dylib").Rule("rustLink")
+ fizzCovLink := ctx.ModuleForTests("fizz_cov", "android_arm64_armv8-a_cov").Rule("rustLink")
+ buzzNoCovLink := ctx.ModuleForTests("buzzNoCov", "android_arm64_armv8-a").Rule("rustLink")
rustcCoverageFlags := []string{"-C instrument-coverage", " -g "}
for _, flag := range rustcCoverageFlags {
@@ -80,17 +84,17 @@
missingErrorStr := "missing rust linker flag '%s' for '%s' module with coverage enabled; rustcFlags: %#v"
containsErrorStr := "contains rust linker flag '%s' for '%s' module with coverage disabled; rustcFlags: %#v"
- if !strings.Contains(fizzCov.Args["linkFlags"], flag) {
- t.Fatalf(missingErrorStr, flag, "fizz_cov", fizzCov.Args["linkFlags"])
+ if !strings.Contains(fizzCovLink.Args["linkFlags"], flag) {
+ t.Fatalf(missingErrorStr, flag, "fizz_cov", fizzCovLink.Args["linkFlags"])
}
- if !strings.Contains(libfooCov.Args["linkFlags"], flag) {
- t.Fatalf(missingErrorStr, flag, "libfoo_cov dylib", libfooCov.Args["linkFlags"])
+ if !strings.Contains(libfooCovLink.Args["linkFlags"], flag) {
+ t.Fatalf(missingErrorStr, flag, "libfoo_cov dylib", libfooCovLink.Args["linkFlags"])
}
- if strings.Contains(buzzNoCov.Args["linkFlags"], flag) {
- t.Fatalf(containsErrorStr, flag, "buzzNoCov", buzzNoCov.Args["linkFlags"])
+ if strings.Contains(buzzNoCovLink.Args["linkFlags"], flag) {
+ t.Fatalf(containsErrorStr, flag, "buzzNoCov", buzzNoCovLink.Args["linkFlags"])
}
- if strings.Contains(libbarNoCov.Args["linkFlags"], flag) {
- t.Fatalf(containsErrorStr, flag, "libbar_cov", libbarNoCov.Args["linkFlags"])
+ if strings.Contains(libbarNoCovLink.Args["linkFlags"], flag) {
+ t.Fatalf(containsErrorStr, flag, "libbar_cov", libbarNoCovLink.Args["linkFlags"])
}
}
@@ -103,7 +107,7 @@
srcs: ["foo.rs"],
}`)
- fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a_cov").Rule("rustc")
+ fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a_cov").Rule("rustLink")
if !strings.Contains(fizz.Args["linkFlags"], "libprofile-clang-extras.a") {
t.Fatalf("missing expected coverage 'libprofile-clang-extras' dependency in linkFlags: %#v", fizz.Args["linkFlags"])
}
diff --git a/rust/library.go b/rust/library.go
index bc9c9aa..a3a5672 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -520,7 +520,7 @@
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
- flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects.Strings()...)
if library.dylib() {
// We need prefer-dynamic for now to avoid linking in the static stdlib. See:
@@ -543,6 +543,7 @@
if library.rlib() || library.dylib() {
library.flagExporter.exportLinkDirs(deps.linkDirs...)
library.flagExporter.exportLinkObjects(deps.linkObjects...)
+ library.flagExporter.exportLibDeps(deps.LibDeps...)
}
if library.static() || library.shared() {
diff --git a/rust/library_test.go b/rust/library_test.go
index e3e4d0f..d4b525f 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -148,7 +148,7 @@
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared")
- libfooOutput := libfoo.Rule("rustc")
+ libfooOutput := libfoo.Rule("rustLink")
if !strings.Contains(libfooOutput.Args["linkFlags"], "-Wl,-soname=libfoo.so") {
t.Errorf("missing expected -Wl,-soname linker flag for libfoo shared lib, linkFlags: %#v",
libfooOutput.Args["linkFlags"])
diff --git a/rust/protobuf.go b/rust/protobuf.go
index 88e80fe..0cf6e8c 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -52,6 +52,10 @@
// List of libraries which export include paths required for this module
Header_libs []string `android:"arch_variant,variant_prepend"`
+
+ // Use protobuf version 3.x. This will be deleted once we migrate all current users
+ // of protobuf off of 2.x.
+ Use_protobuf3 *bool
}
type protobufDecorator struct {
@@ -65,6 +69,10 @@
protoFlags android.ProtoFlags
}
+func (proto *protobufDecorator) useProtobuf3() bool {
+ return Bool(proto.Properties.Use_protobuf3)
+}
+
func (proto *protobufDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) android.Path {
var protoFlags android.ProtoFlags
var grpcProtoFlags android.ProtoFlags
@@ -73,7 +81,13 @@
outDir := android.PathForModuleOut(ctx)
protoFiles := android.PathsForModuleSrc(ctx, proto.Properties.Protos)
grpcFiles := android.PathsForModuleSrc(ctx, proto.Properties.Grpc_protos)
- protoPluginPath := ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
+
+ // For now protobuf2 (the deprecated version) remains the default. This will change in the
+ // future as we update the various users.
+ protoPluginPath := ctx.Config().HostToolPath(ctx, "protoc-gen-rust-deprecated")
+ if proto.useProtobuf3() == true {
+ protoPluginPath = ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
+ }
commonProtoFlags = append(commonProtoFlags, defaultProtobufFlags...)
commonProtoFlags = append(commonProtoFlags, proto.Properties.Proto_flags...)
@@ -206,10 +220,20 @@
func (proto *protobufDecorator) SourceProviderDeps(ctx DepsContext, deps Deps) Deps {
deps = proto.BaseSourceProvider.SourceProviderDeps(ctx, deps)
- deps.Rustlibs = append(deps.Rustlibs, "libprotobuf")
+ useProtobuf3 := proto.useProtobuf3()
+ if useProtobuf3 == true {
+ deps.Rustlibs = append(deps.Rustlibs, "libprotobuf")
+ } else {
+ deps.Rustlibs = append(deps.Rustlibs, "libprotobuf_deprecated")
+ }
deps.HeaderLibs = append(deps.SharedLibs, proto.Properties.Header_libs...)
if len(proto.Properties.Grpc_protos) > 0 {
+ if useProtobuf3 == true {
+ ctx.PropertyErrorf("protos", "rust_protobuf with grpc_protos defined must currently use "+
+ "`use_protobuf3: false,` in the Android.bp file. This is temporary until the "+
+ "grpcio crate is updated to use the current version of the protobuf crate.")
+ }
deps.Rustlibs = append(deps.Rustlibs, "libgrpcio", "libfutures")
deps.HeaderLibs = append(deps.HeaderLibs, "libprotobuf-cpp-full")
}
diff --git a/rust/protobuf_test.go b/rust/protobuf_test.go
index f0f5ec0..b723f3f 100644
--- a/rust/protobuf_test.go
+++ b/rust/protobuf_test.go
@@ -42,6 +42,55 @@
`)
// Check that libprotobuf is added as a dependency.
librust_proto := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_dylib").Module().(*Module)
+ if !android.InList("libprotobuf_deprecated", librust_proto.Properties.AndroidMkDylibs) {
+ t.Errorf("libprotobuf_deprecated dependency missing for rust_protobuf (dependency missing from AndroidMkDylibs)")
+ }
+
+ // Make sure the correct plugin is being used.
+ librust_proto_out := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").Output("buf.rs")
+ cmd := librust_proto_out.RuleParams.Command
+ if w := "protoc-gen-rust-deprecated"; !strings.Contains(cmd, w) {
+ t.Errorf("expected %q in %q", w, cmd)
+ }
+
+ // Check exported include directories
+ if w := "-Ishared_include"; !strings.Contains(cmd, w) {
+ t.Errorf("expected %q in %q", w, cmd)
+ }
+ if w := "-Istatic_include"; !strings.Contains(cmd, w) {
+ t.Errorf("expected %q in %q", w, cmd)
+ }
+
+ // Check proto.rs, the second protobuf, is listed as an output
+ librust_proto_outputs := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").AllOutputs()
+ if android.InList("proto.rs", librust_proto_outputs) {
+ t.Errorf("rust_protobuf is not producing multiple outputs; expected 'proto.rs' in list, got: %#v ",
+ librust_proto_outputs)
+ }
+}
+
+func TestRustProtobuf3(t *testing.T) {
+ ctx := testRust(t, `
+ rust_protobuf {
+ name: "librust_proto",
+ protos: ["buf.proto", "proto.proto"],
+ crate_name: "rust_proto",
+ source_stem: "buf",
+ use_protobuf3: true,
+ shared_libs: ["libfoo_shared"],
+ static_libs: ["libfoo_static"],
+ }
+ cc_library_shared {
+ name: "libfoo_shared",
+ export_include_dirs: ["shared_include"],
+ }
+ cc_library_static {
+ name: "libfoo_static",
+ export_include_dirs: ["static_include"],
+ }
+ `)
+ // Check that libprotobuf is added as a dependency.
+ librust_proto := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_dylib").Module().(*Module)
if !android.InList("libprotobuf", librust_proto.Properties.AndroidMkDylibs) {
t.Errorf("libprotobuf dependency missing for rust_protobuf (dependency missing from AndroidMkDylibs)")
}
diff --git a/rust/rust.go b/rust/rust.go
index 8a13ba3..7b520cd 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -26,6 +26,7 @@
"android/soong/cc"
cc_config "android/soong/cc/config"
"android/soong/fuzz"
+ "android/soong/multitree"
"android/soong/rust/config"
"android/soong/snapshot"
)
@@ -38,7 +39,6 @@
ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
ctx.BottomUp("rust_stdlinkage", LibstdMutator).Parallel()
ctx.BottomUp("rust_begin", BeginMutator).Parallel()
-
})
android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("rust_sanitizers", rustSanitizerRuntimeMutator).Parallel()
@@ -420,13 +420,12 @@
}
type PathDeps struct {
- DyLibs RustLibraries
- RLibs RustLibraries
- SharedLibs android.Paths
- SharedLibDeps android.Paths
- StaticLibs android.Paths
- ProcMacros RustLibraries
- AfdoProfiles android.Paths
+ DyLibs RustLibraries
+ RLibs RustLibraries
+ LibDeps android.Paths
+ WholeStaticLibs android.Paths
+ ProcMacros RustLibraries
+ AfdoProfiles android.Paths
// depFlags and depLinkFlags are rustc and linker (clang) flags.
depFlags []string
@@ -435,7 +434,7 @@
// linkDirs are link paths passed via -L to rustc. linkObjects are objects passed directly to the linker.
// Both of these are exported and propagate to dependencies.
linkDirs []string
- linkObjects []string
+ linkObjects android.Paths
// Used by bindgen modules which call clang
depClangFlags []string
@@ -498,7 +497,7 @@
type exportedFlagsProducer interface {
exportLinkDirs(...string)
- exportLinkObjects(...string)
+ exportLinkObjects(...android.Path)
}
type xref interface {
@@ -507,21 +506,27 @@
type flagExporter struct {
linkDirs []string
- linkObjects []string
+ linkObjects android.Paths
+ libDeps android.Paths
}
func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) {
flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...))
}
-func (flagExporter *flagExporter) exportLinkObjects(flags ...string) {
- flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...))
+func (flagExporter *flagExporter) exportLinkObjects(flags ...android.Path) {
+ flagExporter.linkObjects = android.FirstUniquePaths(append(flagExporter.linkObjects, flags...))
+}
+
+func (flagExporter *flagExporter) exportLibDeps(paths ...android.Path) {
+ flagExporter.libDeps = android.FirstUniquePaths(append(flagExporter.libDeps, paths...))
}
func (flagExporter *flagExporter) setProvider(ctx ModuleContext) {
ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{
LinkDirs: flagExporter.linkDirs,
LinkObjects: flagExporter.linkObjects,
+ LibDeps: flagExporter.libDeps,
})
}
@@ -534,7 +539,8 @@
type FlagExporterInfo struct {
Flags []string
LinkDirs []string // TODO: this should be android.Paths
- LinkObjects []string // TODO: this should be android.Paths
+ LinkObjects android.Paths
+ LibDeps android.Paths
}
var FlagExporterInfoProvider = blueprint.NewProvider(FlagExporterInfo{})
@@ -919,7 +925,7 @@
// Calculate rustc flags
if mod.afdo != nil {
- flags, deps = mod.afdo.flags(ctx, flags, deps)
+ flags, deps = mod.afdo.flags(actx, flags, deps)
}
if mod.compiler != nil {
flags = mod.compiler.compilerFlags(ctx, flags)
@@ -1111,6 +1117,17 @@
return nil
}
+func rustMakeLibName(ctx android.ModuleContext, c cc.LinkableInterface, dep cc.LinkableInterface, depName string) string {
+ if rustDep, ok := dep.(*Module); ok {
+ // Use base module name for snapshots when exporting to Makefile.
+ if snapshotPrebuilt, ok := rustDep.compiler.(cc.SnapshotInterface); ok {
+ baseName := rustDep.BaseModuleName()
+ return baseName + snapshotPrebuilt.SnapshotAndroidMkSuffix() + rustDep.AndroidMkSuffix()
+ }
+ }
+ return cc.MakeLibName(ctx, c, dep, depName)
+}
+
func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
var depPaths PathDeps
@@ -1136,13 +1153,59 @@
mod.apexSdkVersion = android.FutureApiLevel
}
+ skipModuleList := map[string]bool{}
+
+ var apiImportInfo multitree.ApiImportInfo
+ hasApiImportInfo := false
+
+ ctx.VisitDirectDeps(func(dep android.Module) {
+ if dep.Name() == "api_imports" {
+ apiImportInfo = ctx.OtherModuleProvider(dep, multitree.ApiImportsProvider).(multitree.ApiImportInfo)
+ hasApiImportInfo = true
+ }
+ })
+
+ if hasApiImportInfo {
+ targetStubModuleList := map[string]string{}
+ targetOrigModuleList := map[string]string{}
+
+ // Search for dependency which both original module and API imported library with APEX stub exists
+ ctx.VisitDirectDeps(func(dep android.Module) {
+ depName := ctx.OtherModuleName(dep)
+ if apiLibrary, ok := apiImportInfo.ApexSharedLibs[depName]; ok {
+ targetStubModuleList[apiLibrary] = depName
+ }
+ })
+ ctx.VisitDirectDeps(func(dep android.Module) {
+ depName := ctx.OtherModuleName(dep)
+ if origLibrary, ok := targetStubModuleList[depName]; ok {
+ targetOrigModuleList[origLibrary] = depName
+ }
+ })
+
+ // Decide which library should be used between original and API imported library
+ ctx.VisitDirectDeps(func(dep android.Module) {
+ depName := ctx.OtherModuleName(dep)
+ if apiLibrary, ok := targetOrigModuleList[depName]; ok {
+ if cc.ShouldUseStubForApex(ctx, dep) {
+ skipModuleList[depName] = true
+ } else {
+ skipModuleList[apiLibrary] = true
+ }
+ }
+ })
+ }
+
ctx.VisitDirectDeps(func(dep android.Module) {
depName := ctx.OtherModuleName(dep)
depTag := ctx.OtherModuleDependencyTag(dep)
+ if _, exists := skipModuleList[depName]; exists {
+ return
+ }
if rustDep, ok := dep.(*Module); ok && !rustDep.CcLibraryInterface() {
//Handle Rust Modules
- makeLibName := cc.MakeLibName(ctx, mod, rustDep, depName+rustDep.Properties.RustSubName)
+ makeLibName := rustMakeLibName(ctx, mod, rustDep, depName+rustDep.Properties.RustSubName)
switch depTag {
case dylibDepTag:
@@ -1193,6 +1256,7 @@
depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...)
depPaths.depFlags = append(depPaths.depFlags, exportedInfo.Flags...)
depPaths.linkObjects = append(depPaths.linkObjects, exportedInfo.LinkObjects...)
+ depPaths.LibDeps = append(depPaths.LibDeps, exportedInfo.LibDeps...)
}
if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag {
@@ -1236,6 +1300,7 @@
depPaths.depLinkFlags = append(depPaths.depLinkFlags, []string{"-Wl,--whole-archive", linkObject.Path().String(), "-Wl,--no-whole-archive"}...)
} else if libName, ok := libNameFromFilePath(linkObject.Path()); ok {
depPaths.depFlags = append(depPaths.depFlags, "-lstatic="+libName)
+ depPaths.WholeStaticLibs = append(depPaths.WholeStaticLibs, linkObject.Path())
} else {
ctx.ModuleErrorf("'%q' cannot be listed as a whole_static_library in Rust modules unless the output is prefixed by 'lib'", depName, ctx.ModuleName())
}
@@ -1243,7 +1308,7 @@
// Add this to linkObjects to pass the library directly to the linker as well. This propagates
// to dependencies to avoid having to redeclare static libraries for dependents of the dylib variant.
- depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
+ depPaths.linkObjects = append(depPaths.linkObjects, linkObject.AsPaths()...)
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
@@ -1269,7 +1334,7 @@
linkPath = linkPathFromFilePath(linkObject.Path())
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
- depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
+ depPaths.linkObjects = append(depPaths.linkObjects, linkObject.AsPaths()...)
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
@@ -1295,7 +1360,9 @@
// Make sure these dependencies are propagated
if lib, ok := mod.compiler.(exportedFlagsProducer); ok && exportDep {
lib.exportLinkDirs(linkPath)
- lib.exportLinkObjects(linkObject.String())
+ if linkObject.Valid() {
+ lib.exportLinkObjects(linkObject.Path())
+ }
}
} else {
switch {
@@ -1327,19 +1394,16 @@
procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: dep.CrateName()})
}
- var staticLibDepFiles android.Paths
+ var libDepFiles android.Paths
for _, dep := range directStaticLibDeps {
- staticLibDepFiles = append(staticLibDepFiles, dep.OutputFile().Path())
+ libDepFiles = append(libDepFiles, dep.OutputFile().Path())
}
- var sharedLibFiles android.Paths
- var sharedLibDepFiles android.Paths
for _, dep := range directSharedLibDeps {
- sharedLibFiles = append(sharedLibFiles, dep.SharedLibrary)
if dep.TableOfContents.Valid() {
- sharedLibDepFiles = append(sharedLibDepFiles, dep.TableOfContents.Path())
+ libDepFiles = append(libDepFiles, dep.TableOfContents.Path())
} else {
- sharedLibDepFiles = append(sharedLibDepFiles, dep.SharedLibrary)
+ libDepFiles = append(libDepFiles, dep.SharedLibrary)
}
}
@@ -1355,15 +1419,13 @@
depPaths.RLibs = append(depPaths.RLibs, rlibDepFiles...)
depPaths.DyLibs = append(depPaths.DyLibs, dylibDepFiles...)
- depPaths.SharedLibs = append(depPaths.SharedLibs, sharedLibDepFiles...)
- depPaths.SharedLibDeps = append(depPaths.SharedLibDeps, sharedLibDepFiles...)
- depPaths.StaticLibs = append(depPaths.StaticLibs, staticLibDepFiles...)
+ depPaths.LibDeps = append(depPaths.LibDeps, libDepFiles...)
depPaths.ProcMacros = append(depPaths.ProcMacros, procMacroDepFiles...)
depPaths.SrcDeps = append(depPaths.SrcDeps, srcProviderDepFiles...)
// Dedup exported flags from dependencies
depPaths.linkDirs = android.FirstUniqueStrings(depPaths.linkDirs)
- depPaths.linkObjects = android.FirstUniqueStrings(depPaths.linkObjects)
+ depPaths.linkObjects = android.FirstUniquePaths(depPaths.linkObjects)
depPaths.depFlags = android.FirstUniqueStrings(depPaths.depFlags)
depPaths.depClangFlags = android.FirstUniqueStrings(depPaths.depClangFlags)
depPaths.depIncludePaths = android.FirstUniquePaths(depPaths.depIncludePaths)
@@ -1395,6 +1457,16 @@
return strings.Split(filepath.String(), filepath.Base())[0]
}
+// usePublicApi returns true if the rust variant should link against NDK (publicapi)
+func (r *Module) usePublicApi() bool {
+ return r.Device() && r.UseSdk()
+}
+
+// useVendorApi returns true if the rust variant should link against LLNDK (vendorapi)
+func (r *Module) useVendorApi() bool {
+ return r.Device() && (r.InVendor() || r.InProduct())
+}
+
func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
ctx := &depsContext{
BottomUpMutatorContext: actx,
@@ -1405,8 +1477,10 @@
var snapshotInfo *cc.SnapshotInfo
apiImportInfo := cc.GetApiImports(mod, actx)
- for idx, lib := range deps.SharedLibs {
- deps.SharedLibs[idx] = cc.GetReplaceModuleName(lib, apiImportInfo.SharedLibs)
+ if mod.usePublicApi() || mod.useVendorApi() {
+ for idx, lib := range deps.SharedLibs {
+ deps.SharedLibs[idx] = cc.GetReplaceModuleName(lib, apiImportInfo.SharedLibs)
+ }
}
if ctx.Os() == android.Android {
@@ -1446,7 +1520,7 @@
for _, lib := range deps.Rustlibs {
if autoDep.depTag == rlibDepTag {
// Handle the rlib deptag case
- addRlibDependency(actx, lib, mod, snapshotInfo, rlibDepVariations)
+ addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations)
} else {
// autoDep.depTag is a dylib depTag. Not all rustlibs may be available as a dylib however.
// Check for the existence of the dylib deptag variant. Select it if available,
@@ -1457,7 +1531,7 @@
actx.AddVariationDependencies(autoDepVariations, autoDep.depTag, lib)
} else {
// If there's no dylib dependency available, try to add the rlib dependency instead.
- addRlibDependency(actx, lib, mod, snapshotInfo, rlibDepVariations)
+ addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations)
}
}
}
@@ -1486,7 +1560,15 @@
variations := []blueprint.Variation{
{Mutator: "link", Variation: "shared"},
}
- cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, name, version, false)
+ // For core variant, add a dep on the implementation (if it exists) and its .apiimport (if it exists)
+ // GenerateAndroidBuildActions will pick the correct impl/stub based on the api_domain boundary
+ if _, ok := apiImportInfo.ApexSharedLibs[name]; !ok || ctx.OtherModuleExists(name) {
+ cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, name, version, false)
+ }
+
+ if apiLibraryName, ok := apiImportInfo.ApexSharedLibs[name]; ok {
+ cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, apiLibraryName, version, false)
+ }
}
for _, lib := range deps.WholeStaticLibs {
@@ -1535,11 +1617,13 @@
// proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy.
actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), procMacroDepTag, deps.ProcMacros...)
+
+ mod.afdo.addDep(ctx, actx)
}
// addRlibDependency will add an rlib dependency, rewriting to the snapshot library if available.
-func addRlibDependency(actx android.BottomUpMutatorContext, lib string, mod *Module, snapshotInfo *cc.SnapshotInfo, variations []blueprint.Variation) {
- lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs)
+func addRlibDependency(actx android.BottomUpMutatorContext, lib string, mod *Module, snapshotInfo **cc.SnapshotInfo, variations []blueprint.Variation) {
+ lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, snapshotInfo, actx).Rlibs)
actx.AddVariationDependencies(variations, rlibDepTag, lib)
}
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 3bcd58c..2a38b89 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -209,6 +209,10 @@
// Test to make sure dependencies are being picked up correctly.
func TestDepsTracking(t *testing.T) {
ctx := testRust(t, `
+ cc_library {
+ host_supported: true,
+ name: "cc_stubs_dep",
+ }
rust_ffi_host_static {
name: "libstatic",
srcs: ["foo.rs"],
@@ -235,6 +239,7 @@
crate_name: "rlib",
static_libs: ["libstatic"],
whole_static_libs: ["libwholestatic"],
+ shared_libs: ["cc_stubs_dep"],
}
rust_proc_macro {
name: "libpm",
@@ -253,6 +258,7 @@
`)
module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
rustc := ctx.ModuleForTests("librlib", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
+ rustLink := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Rule("rustLink")
// Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up.
if !android.InList("libdylib", module.Properties.AndroidMkDylibs) {
@@ -279,6 +285,17 @@
t.Errorf("-lstatic flag not being passed to rustc for static library %#v", rustc.Args["rustcFlags"])
}
+ if !strings.Contains(rustLink.Args["linkFlags"], "cc_stubs_dep.so") {
+ t.Errorf("shared cc_library not being passed to rustc linkFlags %#v", rustLink.Args["linkFlags"])
+ }
+
+ if !android.SuffixInList(rustLink.OrderOnly.Strings(), "cc_stubs_dep.so") {
+ t.Errorf("shared cc dep not being passed as order-only to rustc %#v", rustLink.OrderOnly.Strings())
+ }
+
+ if !android.SuffixInList(rustLink.Implicits.Strings(), "cc_stubs_dep.so.toc") {
+ t.Errorf("shared cc dep TOC not being passed as implicit to rustc %#v", rustLink.Implicits.Strings())
+ }
}
func TestSourceProviderDeps(t *testing.T) {
@@ -331,7 +348,7 @@
source_stem: "bindings",
host_supported: true,
wrapper_src: "src/any.h",
- }
+ }
`)
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_rlib_dylib-std").Rule("rustc")
@@ -371,7 +388,6 @@
if !android.InList("libbindings.rlib-std", libprocmacroMod.Properties.AndroidMkRlibs) {
t.Errorf("bindgen dependency not detected as a rlib dependency (dependency missing from AndroidMkRlibs)")
}
-
}
func TestSourceProviderTargetMismatch(t *testing.T) {
diff --git a/rust/sanitize_test.go b/rust/sanitize_test.go
index d6a14b2..43e95f4 100644
--- a/rust/sanitize_test.go
+++ b/rust/sanitize_test.go
@@ -35,7 +35,7 @@
note_sync := "note_memtag_heap_sync"
found := None
- implicits := m.Rule("rustc").Implicits
+ implicits := m.Rule("rustLink").Implicits
for _, lib := range implicits {
if strings.Contains(lib.Rel(), note_async) {
found = Async
diff --git a/rust/testing.go b/rust/testing.go
index 24ca3d6..0a6a870 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -133,6 +133,12 @@
host_supported: true,
}
rust_library {
+ name: "libprotobuf_deprecated",
+ crate_name: "protobuf",
+ srcs: ["foo.rs"],
+ host_supported: true,
+ }
+ rust_library {
name: "libgrpcio",
crate_name: "grpcio",
srcs: ["foo.rs"],
diff --git a/rust/vendor_snapshot_test.go b/rust/vendor_snapshot_test.go
index 7be0042..2e7a330 100644
--- a/rust/vendor_snapshot_test.go
+++ b/rust/vendor_snapshot_test.go
@@ -424,6 +424,14 @@
compile_multilib: "32",
srcs: ["bin.rs"],
}
+
+ rust_library {
+ name: "librust_vendor_available",
+ crate_name: "rust_vendor",
+ vendor_available: true,
+ srcs: ["client.rs"],
+ }
+
`
vndkBp := `
@@ -499,13 +507,6 @@
system_shared_libs: [],
}
- rust_library {
- name: "librust_vendor_available",
- crate_name: "rust_vendor",
- vendor_available: true,
- srcs: ["client.rs"],
- }
-
rust_ffi_shared {
name: "libclient",
crate_name: "client",
@@ -940,7 +941,7 @@
ctx := testRustVndkFsVersions(t, "", mockFS, "30", "current", "31")
// libclient uses libvndk.vndk.30.arm64, libvendor.vendor_static.30.arm64, libvendor_without_snapshot
- libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("rustc").Args["linkFlags"]
+ libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("rustLink").Args["linkFlags"]
for _, input := range [][]string{
[]string{sharedVariant, "libvndk.vndk.30.arm64"},
[]string{staticVariant, "libvendor.vendor_static.30.arm64"},
@@ -963,7 +964,7 @@
}
libclientAndroidMkRlibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkRlibs
- if g, w := libclientAndroidMkRlibs, []string{"librust_vendor_available.vendor_rlib.30.arm64.rlib-std", "libstd.vendor_rlib.30.arm64"}; !reflect.DeepEqual(g, w) {
+ if g, w := libclientAndroidMkRlibs, []string{"librust_vendor_available.vendor.rlib-std", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
t.Errorf("wanted libclient libclientAndroidMkRlibs %q, got %q", w, g)
}
@@ -978,11 +979,25 @@
}
libclientRustAndroidMkRlibs := ctx.ModuleForTests("libclient_rust", rlibVariant).Module().(*Module).Properties.AndroidMkRlibs
- if g, w := libclientRustAndroidMkRlibs, []string{"librust_vendor_available.vendor_rlib.30.arm64.rlib-std", "libstd.vendor_rlib.30.arm64"}; !reflect.DeepEqual(g, w) {
+ if g, w := libclientRustAndroidMkRlibs, []string{"librust_vendor_available.vendor.rlib-std", "libstd.vendor"}; !reflect.DeepEqual(g, w) {
t.Errorf("wanted libclient libclientAndroidMkRlibs %q, got %q", w, g)
}
- binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("rustc").Args["linkFlags"]
+ // rust vendor snapshot must have ".vendor" suffix in AndroidMk
+ librustVendorAvailableSnapshotModule := ctx.ModuleForTests("librust_vendor_available.vendor_rlib.30.arm64", rlibVariant).Module()
+ librustVendorSnapshotMkName := android.AndroidMkEntriesForTest(t, ctx, librustVendorAvailableSnapshotModule)[0].EntryMap["LOCAL_MODULE"][0]
+ expectedRustVendorSnapshotName := "librust_vendor_available.vendor.rlib-std"
+ if librustVendorSnapshotMkName != expectedRustVendorSnapshotName {
+ t.Errorf("Unexpected rust vendor snapshot name in AndroidMk: %q, expected: %q\n", librustVendorSnapshotMkName, expectedRustVendorSnapshotName)
+ }
+
+ rustVendorBinModule := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Module()
+ rustVendorBinMkRlibName := android.AndroidMkEntriesForTest(t, ctx, rustVendorBinModule)[0].EntryMap["LOCAL_RLIB_LIBRARIES"][0]
+ if rustVendorBinMkRlibName != expectedRustVendorSnapshotName {
+ t.Errorf("Unexpected rust rlib name in AndroidMk: %q, expected: %q\n", rustVendorBinMkRlibName, expectedRustVendorSnapshotName)
+ }
+
+ binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("rustLink").Args["linkFlags"]
libVndkStaticOutputPaths := cc.GetOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.30.arm64"})
if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) {
t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v",
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 5dd45cd..9367ff0 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -189,6 +189,18 @@
libs: [
"linker_config_proto",
],
+ visibility: ["//system/linkerconfig"],
+}
+
+python_test_host {
+ name: "conv_linker_config_test",
+ main: "conv_linker_config_test.py",
+ srcs: [
+ "conv_linker_config_test.py",
+ "conv_linker_config.py",
+ ],
+ libs: ["linker_config_proto"],
+ test_suites: ["general-tests"],
}
python_binary_host {
@@ -220,3 +232,8 @@
srcs: ["rustfmt.toml"],
visibility: ["//visibility:public"],
}
+
+sh_binary_host {
+ name: "jars-to-module-info-java",
+ src: "jars-to-module-info-java.sh",
+}
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index b57963b..0d14019 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -19,7 +19,12 @@
exit 1
fi
-TARGET_PRODUCT=ndk build/soong/soong_ui.bash --make-mode --soong-only ${OUT_DIR}/soong/ndk.timestamp
+# TODO: remove ALLOW_MISSING_DEPENDENCIES=true when all the riscv64
+# dependencies exist (currently blocked by http://b/273792258).
+# TODO: remove BUILD_BROKEN_DISABLE_BAZEL=1 when bazel supports riscv64 (http://b/262192655).
+ALLOW_MISSING_DEPENDENCIES=true \
+BUILD_BROKEN_DISABLE_BAZEL=1 \
+ TARGET_PRODUCT=ndk build/soong/soong_ui.bash --make-mode --soong-only ${OUT_DIR}/soong/ndk.timestamp
if [ -n "${DIST_DIR}" ]; then
mkdir -p ${DIST_DIR} || true
diff --git a/scripts/conv_linker_config.py b/scripts/conv_linker_config.py
index 784a92f..3ac1b7e 100644
--- a/scripts/conv_linker_config.py
+++ b/scripts/conv_linker_config.py
@@ -27,6 +27,19 @@
from google.protobuf.text_format import MessageToString
+def LoadJsonMessage(path):
+ """
+ Loads a message from a .json file with `//` comments strippedfor convenience.
+ """
+ json_content = ''
+ with open(path) as f:
+ for line in f:
+ if not line.lstrip().startswith('//'):
+ json_content += line
+ obj = json.loads(json_content, object_pairs_hook=collections.OrderedDict)
+ return ParseDict(obj, linker_config_pb2.LinkerConfig())
+
+
def Proto(args):
"""
Merges input json files (--source) into a protobuf message (--output).
@@ -48,13 +61,7 @@
if args.source:
for input in args.source.split(':'):
- json_content = ''
- with open(input) as f:
- for line in f:
- if not line.lstrip().startswith('//'):
- json_content += line
- obj = json.loads(json_content, object_pairs_hook=collections.OrderedDict)
- ParseDict(obj, pb)
+ pb.MergeFrom(LoadJsonMessage(input))
with open(args.output, 'wb') as f:
f.write(pb.SerializeToString())
diff --git a/scripts/conv_linker_config_test.py b/scripts/conv_linker_config_test.py
new file mode 100644
index 0000000..d19a47b
--- /dev/null
+++ b/scripts/conv_linker_config_test.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Unit tests for conv_linker_config.py."""
+
+import io
+import os
+import shutil
+import tempfile
+import unittest
+
+import conv_linker_config
+from contextlib import redirect_stderr
+from linker_config_pb2 import LinkerConfig
+
+class FileArgs:
+ def __init__(self, files, sep = ':'):
+ self.files = files
+ self.sep = sep
+
+
+class FileArg:
+ def __init__(self, file):
+ self.file = file
+
+
+class TempDirTest(unittest.TestCase):
+
+ def setUp(self):
+ self.tempdir = tempfile.mkdtemp()
+
+
+ def tearDown(self):
+ shutil.rmtree(self.tempdir)
+
+
+ def write(self, name, contents):
+ with open(os.path.join(self.tempdir, name), 'wb') as f:
+ f.write(contents)
+
+
+ def read(self, name):
+ with open(os.path.join(self.tempdir, name), 'rb') as f:
+ return f.read()
+
+
+ def resolve_paths(self, args):
+ for i in range(len(args)):
+ if isinstance(args[i], FileArgs):
+ args[i] = args[i].sep.join(os.path.join(self.tempdir, f.file) for f in args[i].files)
+ elif isinstance(args[i], FileArg):
+ args[i] = os.path.join(self.tempdir, args[i].file)
+ return args
+
+
+class ConvLinkerConfigTest(TempDirTest):
+ """Unit tests for conv_linker_config."""
+
+
+ def test_Proto_empty_input(self):
+ self.command(['proto', '-s', '-o', FileArg('out.pb')])
+ pb = LinkerConfig()
+ pb.ParseFromString(self.read('out.pb'))
+ self.assertEqual(pb, LinkerConfig())
+
+
+ def test_Proto_single_input(self):
+ self.write('foo.json', b'{ "provideLibs": ["libfoo.so"]}')
+ self.command(['proto', '-s', FileArg('foo.json'), '-o', FileArg('out.pb')])
+ pb = LinkerConfig()
+ pb.ParseFromString(self.read('out.pb'))
+ self.assertSequenceEqual(pb.provideLibs, ['libfoo.so'])
+
+
+ def test_Proto_with_multiple_input(self):
+ self.write('foo.json', b'{ "provideLibs": ["libfoo.so"]}')
+ self.write('bar.json', b'{ "provideLibs": ["libbar.so"]}')
+ self.command(['proto', '-s', FileArgs([FileArg('foo.json'), FileArg('bar.json')]), '-o', FileArg('out.pb')])
+ pb = LinkerConfig()
+ pb.ParseFromString(self.read('out.pb'))
+ self.assertSetEqual(set(pb.provideLibs), set(['libfoo.so', 'libbar.so']))
+
+
+ def test_Proto_with_existing_output(self):
+ self.write('out.pb', LinkerConfig(provideLibs=['libfoo.so']).SerializeToString())
+ buf = io.StringIO()
+ with self.assertRaises(SystemExit) as err:
+ with redirect_stderr(buf):
+ self.command(['proto', '-o', FileArg('out.pb')])
+ self.assertEqual(err.exception.code, 1)
+ self.assertRegex(buf.getvalue(), r'.*out\.pb exists')
+
+
+ def test_Proto_with_append(self):
+ self.write('out.pb', LinkerConfig(provideLibs=['libfoo.so']).SerializeToString())
+ self.write('bar.json', b'{ "provideLibs": ["libbar.so"]}')
+ self.command(['proto', '-s', FileArg('bar.json'), '-o', FileArg('out.pb'), '-a'])
+ pb = LinkerConfig()
+ pb.ParseFromString(self.read('out.pb'))
+ self.assertSetEqual(set(pb.provideLibs), set(['libfoo.so', 'libbar.so']))
+
+
+ def test_Proto_with_force(self):
+ self.write('out.pb', LinkerConfig(provideLibs=['libfoo.so']).SerializeToString())
+ self.write('bar.json', b'{ "provideLibs": ["libbar.so"]}')
+ self.command(['proto', '-s', FileArg('bar.json'), '-o', FileArg('out.pb'), '-f'])
+ pb = LinkerConfig()
+ pb.ParseFromString(self.read('out.pb'))
+ self.assertSetEqual(set(pb.provideLibs), set(['libbar.so']))
+
+
+ def command(self, args):
+ parser = conv_linker_config.GetArgParser()
+ parsed_args = parser.parse_args(self.resolve_paths(args))
+ parsed_args.func(parsed_args)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/scripts/mkcratersp.py b/scripts/mkcratersp.py
new file mode 100755
index 0000000..86b4aa3
--- /dev/null
+++ b/scripts/mkcratersp.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""
+This script is used as a replacement for the Rust linker. It converts a linker
+command line into a rspfile that can be used during the link phase.
+"""
+
+import os
+import shutil
+import subprocess
+import sys
+
+def create_archive(out, objects, archives):
+ mricmd = f'create {out}\n'
+ for o in objects:
+ mricmd += f'addmod {o}\n'
+ for a in archives:
+ mricmd += f'addlib {a}\n'
+ mricmd += 'save\nend\n'
+ subprocess.run([os.getenv('AR'), '-M'], encoding='utf-8', input=mricmd, check=True)
+
+objects = []
+archives = []
+linkdirs = []
+libs = []
+temp_archives = []
+version_script = None
+
+for i, arg in enumerate(sys.argv):
+ if arg == '-o':
+ out = sys.argv[i+1]
+ if arg == '-L':
+ linkdirs.append(sys.argv[i+1])
+ if arg.startswith('-l') or arg == '-shared':
+ libs.append(arg)
+ if arg.startswith('-Wl,--version-script='):
+ version_script = arg[21:]
+ if arg[0] == '-':
+ continue
+ if arg.endswith('.o') or arg.endswith('.rmeta'):
+ objects.append(arg)
+ if arg.endswith('.rlib'):
+ if arg.startswith(os.getenv('TMPDIR')):
+ temp_archives.append(arg)
+ else:
+ archives.append(arg)
+
+create_archive(f'{out}.whole.a', objects, [])
+create_archive(f'{out}.a', [], temp_archives)
+
+with open(out, 'w') as f:
+ print(f'-Wl,--whole-archive', file=f)
+ print(f'{out}.whole.a', file=f)
+ print(f'-Wl,--no-whole-archive', file=f)
+ print(f'{out}.a', file=f)
+ for a in archives:
+ print(a, file=f)
+ for linkdir in linkdirs:
+ print(f'-L{linkdir}', file=f)
+ for l in libs:
+ print(l, file=f)
+ if version_script:
+ shutil.copyfile(version_script, f'{out}.version_script')
+ print(f'-Wl,--version-script={out}.version_script', file=f)
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index d81635e..0d6496d 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -27,6 +27,11 @@
// fixtureAddPlatformBootclasspathForBootclasspathFragment adds a platform_bootclasspath module that
// references the bootclasspath fragment.
func fixtureAddPlatformBootclasspathForBootclasspathFragment(apex, fragment string) android.FixturePreparer {
+ return fixtureAddPlatformBootclasspathForBootclasspathFragmentWithExtra(apex, fragment, "")
+}
+
+// fixtureAddPlatformBootclasspathForBootclasspathFragmentWithExtra is the same as above, but also adds extra fragments.
+func fixtureAddPlatformBootclasspathForBootclasspathFragmentWithExtra(apex, fragment, extraFragments string) android.FixturePreparer {
return android.GroupFixturePreparers(
// Add a platform_bootclasspath module.
android.FixtureAddTextFile("frameworks/base/boot/Android.bp", fmt.Sprintf(`
@@ -37,9 +42,10 @@
apex: "%s",
module: "%s",
},
+ %s
],
}
- `, apex, fragment)),
+ `, apex, fragment, extraFragments)),
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),
@@ -79,9 +85,11 @@
}),
// Add a platform_bootclasspath that depends on the fragment.
- fixtureAddPlatformBootclasspathForBootclasspathFragment("com.android.art", "mybootclasspathfragment"),
+ fixtureAddPlatformBootclasspathForBootclasspathFragmentWithExtra(
+ "com.android.art", "mybootclasspathfragment", java.ApexBootJarFragmentsForPlatformBootclasspath),
java.PrepareForBootImageConfigTest,
+ java.PrepareApexBootJarConfigsAndModules,
android.FixtureWithRootAndroidBp(`
sdk {
name: "mysdk",
@@ -196,9 +204,15 @@
snapshotTestChecker(checkSnapshotWithoutSource, func(t *testing.T, result *android.TestResult) {
// Make sure that the boot jars package check rule includes the dex jars retrieved from the prebuilt apex.
checkBootJarsPackageCheckRule(t, result,
- "out/soong/.intermediates/prebuilts/apex/com.android.art.deapexer/android_common/deapexer/javalib/core1.jar",
- "out/soong/.intermediates/prebuilts/apex/com.android.art.deapexer/android_common/deapexer/javalib/core2.jar",
- "out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar")
+ append(
+ []string{
+ "out/soong/.intermediates/prebuilts/apex/com.android.art.deapexer/android_common/deapexer/javalib/core1.jar",
+ "out/soong/.intermediates/prebuilts/apex/com.android.art.deapexer/android_common/deapexer/javalib/core2.jar",
+ "out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar",
+ },
+ java.ApexBootJarDexJarPaths...,
+ )...,
+ )
java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/snapshot/mybootclasspathfragment/android_common_com.android.art/meta_lic")
java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic")
}),
@@ -222,9 +236,15 @@
// Make sure that the boot jars package check rule includes the dex jars created from the source.
checkBootJarsPackageCheckRule(t, result,
- "out/soong/.intermediates/core1/android_common_apex10000/aligned/core1.jar",
- "out/soong/.intermediates/core2/android_common_apex10000/aligned/core2.jar",
- "out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar")
+ append(
+ []string{
+ "out/soong/.intermediates/core1/android_common_apex10000/aligned/core1.jar",
+ "out/soong/.intermediates/core2/android_common_apex10000/aligned/core2.jar",
+ "out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar",
+ },
+ java.ApexBootJarDexJarPaths...,
+ )...,
+ )
}
// checkBootJarsPackageCheckRule checks that the supplied module is an input to the boot jars
@@ -819,6 +839,7 @@
compile_dex: true,
public: {enabled: true},
permitted_packages: ["mysdklibrary"],
+ min_sdk_version: "current",
}
java_sdk_library {
diff --git a/sdk/update.go b/sdk/update.go
index 0820d62..d98ab68 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -357,6 +357,12 @@
// If the minApiLevel of the member is greater than the target API level then exclude it from
// this snapshot.
exclude := memberVariantDep.minApiLevel.GreaterThan(targetApiLevel)
+ // Always include host variants (e.g. host tools) in the snapshot.
+ // Host variants should not be guarded by a min_sdk_version check. In fact, host variants
+ // do not have a `min_sdk_version`.
+ if memberVariantDep.Host() {
+ exclude = false
+ }
addMember(name, export, exclude)
@@ -1263,6 +1269,11 @@
minApiLevel android.ApiLevel
}
+// Host returns true if the sdk member is a host variant (e.g. host tool)
+func (s *sdkMemberVariantDep) Host() bool {
+ return s.variant.Target().Os.Class == android.Host
+}
+
var _ android.SdkMember = (*sdkMember)(nil)
// sdkMember groups all the variants of a specific member module together along with the name of the
diff --git a/snapshot/host_snapshot.go b/snapshot/host_snapshot.go
index 9793218..edcc163 100644
--- a/snapshot/host_snapshot.go
+++ b/snapshot/host_snapshot.go
@@ -96,6 +96,7 @@
var jsonData []SnapshotJsonFlags
var metaPaths android.Paths
+ installedNotices := make(map[string]bool)
metaZipFile := android.PathForModuleOut(ctx, fileName).OutputPath
// Create JSON file based on the direct dependencies
@@ -104,12 +105,14 @@
if desc != nil {
jsonData = append(jsonData, *desc)
}
- if len(dep.EffectiveLicenseFiles()) > 0 {
- noticeFile := android.PathForModuleOut(ctx, "NOTICE_FILES", dep.Name()+".txt").OutputPath
- android.CatFileRule(ctx, dep.EffectiveLicenseFiles(), noticeFile)
- metaPaths = append(metaPaths, noticeFile)
+ for _, notice := range dep.EffectiveLicenseFiles() {
+ if _, ok := installedNotices[notice.String()]; !ok {
+ installedNotices[notice.String()] = true
+ noticeOut := android.PathForModuleOut(ctx, "NOTICE_FILES", notice.String()).OutputPath
+ CopyFileToOutputPathRule(pctx, ctx, notice, noticeOut)
+ metaPaths = append(metaPaths, noticeOut)
+ }
}
-
})
// Sort notice paths and json data for repeatble build
sort.Slice(jsonData, func(i, j int) bool {
@@ -220,8 +223,7 @@
}
if path.Valid() && path.String() != "" {
- return &SnapshotJsonFlags{
- ModuleName: m.Name(),
+ props := &SnapshotJsonFlags{
ModuleStemName: moduleStem,
Filename: path.String(),
Required: append(m.HostRequiredModuleNames(), m.RequiredModuleNames()...),
@@ -229,6 +231,8 @@
RustProcMacro: procMacro,
CrateName: crateName,
}
+ props.InitBaseSnapshotProps(m)
+ return props
}
return nil
}
diff --git a/snapshot/snapshot.go b/snapshot/snapshot.go
index 206ecc9..c95a537 100644
--- a/snapshot/snapshot.go
+++ b/snapshot/snapshot.go
@@ -26,6 +26,10 @@
var pctx = android.NewPackageContext("android/soong/snapshot")
+func init() {
+ pctx.Import("android/soong/android")
+}
+
type SnapshotSingleton struct {
// Name, e.g., "vendor", "recovery", "ramdisk".
name string
@@ -48,8 +52,18 @@
Fake bool
}
+// The output files to be included in the snapshot.
+type SnapshotPaths struct {
+ // All files to be included in the snapshot
+ OutputFiles android.Paths
+
+ // Notice files of the snapshot output files
+ NoticeFiles android.Paths
+}
+
// Interface of function to capture snapshot from each module
-type GenerateSnapshotAction func(snapshot SnapshotSingleton, ctx android.SingletonContext, snapshotArchDir string) android.Paths
+// Returns snapshot ouputs and notice files.
+type GenerateSnapshotAction func(snapshot SnapshotSingleton, ctx android.SingletonContext, snapshotArchDir string) SnapshotPaths
var snapshotActionList []GenerateSnapshotAction
@@ -74,9 +88,19 @@
snapshotDir = filepath.Join("fake", snapshotDir)
}
snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
+ noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
+ installedNotices := make(map[string]bool)
for _, f := range snapshotActionList {
- snapshotOutputs = append(snapshotOutputs, f(*c, ctx, snapshotArchDir)...)
+ snapshotPaths := f(*c, ctx, snapshotArchDir)
+ snapshotOutputs = append(snapshotOutputs, snapshotPaths.OutputFiles...)
+ for _, notice := range snapshotPaths.NoticeFiles {
+ if _, ok := installedNotices[notice.String()]; !ok {
+ installedNotices[notice.String()] = true
+ snapshotOutputs = append(snapshotOutputs, CopyFileRule(
+ pctx, ctx, notice, filepath.Join(noticeDir, notice.String())))
+ }
+ }
}
// All artifacts are ready. Sort them to normalize ninja and then zip.
diff --git a/snapshot/snapshot_base.go b/snapshot/snapshot_base.go
index 809ca3d..fb4ee0c 100644
--- a/snapshot/snapshot_base.go
+++ b/snapshot/snapshot_base.go
@@ -120,4 +120,19 @@
// dependencies
Required []string `json:",omitempty"`
Overrides []string `json:",omitempty"`
+
+ // license information
+ LicenseKinds []string `json:",omitempty"`
+ LicenseTexts []string `json:",omitempty"`
+}
+
+func (prop *SnapshotJsonFlags) InitBaseSnapshotPropsWithName(m android.Module, name string) {
+ prop.ModuleName = name
+
+ prop.LicenseKinds = m.EffectiveLicenseKinds()
+ prop.LicenseTexts = m.EffectiveLicenseFiles().Strings()
+}
+
+func (prop *SnapshotJsonFlags) InitBaseSnapshotProps(m android.Module) {
+ prop.InitBaseSnapshotPropsWithName(m, m.Name())
}
diff --git a/snapshot/util.go b/snapshot/util.go
index 806ac90..c87c508 100644
--- a/snapshot/util.go
+++ b/snapshot/util.go
@@ -21,17 +21,25 @@
return outPath
}
-func CopyFileRule(pctx android.PackageContext, ctx android.SingletonContext, path android.Path, out string) android.OutputPath {
- outPath := android.PathForOutput(ctx, out)
+type buildContext interface {
+ Build(pctx android.PackageContext, params android.BuildParams)
+}
+
+func CopyFileToOutputPathRule(pctx android.PackageContext, ctx buildContext, path android.Path, outPath android.OutputPath) {
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
Input: path,
Output: outPath,
- Description: "copy " + path.String() + " -> " + out,
+ Description: "copy " + path.String() + " -> " + outPath.String(),
Args: map[string]string{
- "cpFlags": "-f -L",
+ "cpFlags": "-L",
},
})
+}
+
+func CopyFileRule(pctx android.PackageContext, ctx android.SingletonContext, path android.Path, out string) android.OutputPath {
+ outPath := android.PathForOutput(ctx, out)
+ CopyFileToOutputPathRule(pctx, ctx, path, outPath)
return outPath
}
diff --git a/soong_ui.bash b/soong_ui.bash
index 1d027c4..8e7cd19 100755
--- a/soong_ui.bash
+++ b/soong_ui.bash
@@ -33,8 +33,8 @@
source ${TOP}/build/soong/scripts/microfactory.bash
soong_build_go soong_ui android/soong/cmd/soong_ui
-soong_build_go mk2rbc android/soong/mk2rbc/cmd
-soong_build_go rbcrun rbcrun/cmd
+soong_build_go mk2rbc android/soong/mk2rbc/mk2rbc
+soong_build_go rbcrun rbcrun/rbcrun
cd ${TOP}
exec "$(getoutdir)/soong_ui" "$@"
diff --git a/starlark_fmt/format.go b/starlark_fmt/format.go
index 064fc21..4209507 100644
--- a/starlark_fmt/format.go
+++ b/starlark_fmt/format.go
@@ -35,7 +35,11 @@
// PrintBool returns a Starlark compatible bool string.
func PrintBool(item bool) string {
- return strings.Title(fmt.Sprintf("%t", item))
+ if item {
+ return "True"
+ } else {
+ return "False"
+ }
}
// PrintsStringList returns a Starlark-compatible string of a list of Strings/Labels.
@@ -95,6 +99,16 @@
return PrintDict(valDict, indentLevel)
}
+// PrintStringStringDict returns a Starlark-compatible string formatted as dictionary with
+// string keys and string values.
+func PrintStringStringDict(dict map[string]string, indentLevel int) string {
+ valDict := make(map[string]string, len(dict))
+ for k, v := range dict {
+ valDict[k] = fmt.Sprintf(`"%s"`, v)
+ }
+ return PrintDict(valDict, indentLevel)
+}
+
// PrintDict returns a starlark-compatible string containing a dictionary with string keys and
// values printed with no additional formatting.
func PrintDict(dict map[string]string, indentLevel int) string {
diff --git a/starlark_import/Android.bp b/starlark_import/Android.bp
new file mode 100644
index 0000000..b43217b
--- /dev/null
+++ b/starlark_import/Android.bp
@@ -0,0 +1,36 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-starlark",
+ pkgPath: "android/soong/starlark_import",
+ srcs: [
+ "starlark_import.go",
+ "unmarshal.go",
+ ],
+ testSrcs: [
+ "starlark_import_test.go",
+ "unmarshal_test.go",
+ ],
+ deps: [
+ "go-starlark-starlark",
+ "go-starlark-starlarkstruct",
+ "go-starlark-starlarkjson",
+ "go-starlark-starlarktest",
+ ],
+}
diff --git a/starlark_import/README.md b/starlark_import/README.md
new file mode 100644
index 0000000..e444759
--- /dev/null
+++ b/starlark_import/README.md
@@ -0,0 +1,14 @@
+# starlark_import package
+
+This allows soong to read constant information from starlark files. At package initialization
+time, soong will read `build/bazel/constants_exported_to_soong.bzl`, and then make the
+variables from that file available via `starlark_import.GetStarlarkValue()`. So to import
+a new variable, it must be added to `constants_exported_to_soong.bzl` and then it can
+be accessed by name.
+
+Only constant information can be read, since this is not a full bazel execution but a
+standalone starlark interpreter. This means you can't use bazel contructs like `rule`,
+`provider`, `select`, `glob`, etc.
+
+All starlark files that were loaded must be added as ninja deps that cause soong to rerun.
+The loaded files can be retrieved via `starlark_import.GetNinjaDeps()`.
diff --git a/starlark_import/starlark_import.go b/starlark_import/starlark_import.go
new file mode 100644
index 0000000..ebe4247
--- /dev/null
+++ b/starlark_import/starlark_import.go
@@ -0,0 +1,306 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package starlark_import
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "sort"
+ "strings"
+ "sync"
+ "time"
+
+ "go.starlark.net/starlark"
+ "go.starlark.net/starlarkjson"
+ "go.starlark.net/starlarkstruct"
+)
+
+func init() {
+ go func() {
+ startTime := time.Now()
+ v, d, err := runStarlarkFile("//build/bazel/constants_exported_to_soong.bzl")
+ endTime := time.Now()
+ //fmt.Fprintf(os.Stderr, "starlark run time: %s\n", endTime.Sub(startTime).String())
+ globalResult.Set(starlarkResult{
+ values: v,
+ ninjaDeps: d,
+ err: err,
+ startTime: startTime,
+ endTime: endTime,
+ })
+ }()
+}
+
+type starlarkResult struct {
+ values starlark.StringDict
+ ninjaDeps []string
+ err error
+ startTime time.Time
+ endTime time.Time
+}
+
+// setOnce wraps a value and exposes Set() and Get() accessors for it.
+// The Get() calls will block until a Set() has been called.
+// A second call to Set() will panic.
+// setOnce must be created using newSetOnce()
+type setOnce[T any] struct {
+ value T
+ lock sync.Mutex
+ wg sync.WaitGroup
+ isSet bool
+}
+
+func (o *setOnce[T]) Set(value T) {
+ o.lock.Lock()
+ defer o.lock.Unlock()
+ if o.isSet {
+ panic("Value already set")
+ }
+
+ o.value = value
+ o.isSet = true
+ o.wg.Done()
+}
+
+func (o *setOnce[T]) Get() T {
+ if !o.isSet {
+ o.wg.Wait()
+ }
+ return o.value
+}
+
+func newSetOnce[T any]() *setOnce[T] {
+ result := &setOnce[T]{}
+ result.wg.Add(1)
+ return result
+}
+
+var globalResult = newSetOnce[starlarkResult]()
+
+func GetStarlarkValue[T any](key string) (T, error) {
+ result := globalResult.Get()
+ if result.err != nil {
+ var zero T
+ return zero, result.err
+ }
+ if !result.values.Has(key) {
+ var zero T
+ return zero, fmt.Errorf("a starlark variable by that name wasn't found, did you update //build/bazel/constants_exported_to_soong.bzl?")
+ }
+ return Unmarshal[T](result.values[key])
+}
+
+func GetNinjaDeps() ([]string, error) {
+ result := globalResult.Get()
+ if result.err != nil {
+ return nil, result.err
+ }
+ return result.ninjaDeps, nil
+}
+
+func getTopDir() (string, error) {
+ // It's hard to communicate the top dir to this package in any other way than reading the
+ // arguments directly, because we need to know this at package initialization time. Many
+ // soong constants that we'd like to read from starlark are initialized during package
+ // initialization.
+ for i, arg := range os.Args {
+ if arg == "--top" {
+ if i < len(os.Args)-1 && os.Args[i+1] != "" {
+ return os.Args[i+1], nil
+ }
+ }
+ }
+
+ // When running tests, --top is not passed. Instead, search for the top dir manually
+ cwd, err := os.Getwd()
+ if err != nil {
+ return "", err
+ }
+ for cwd != "/" {
+ if _, err := os.Stat(filepath.Join(cwd, "build/soong/soong_ui.bash")); err == nil {
+ return cwd, nil
+ }
+ cwd = filepath.Dir(cwd)
+ }
+ return "", fmt.Errorf("could not find top dir")
+}
+
+const callerDirKey = "callerDir"
+
+type modentry struct {
+ globals starlark.StringDict
+ err error
+}
+
+func unsupportedMethod(t *starlark.Thread, fn *starlark.Builtin, _ starlark.Tuple, _ []starlark.Tuple) (starlark.Value, error) {
+ return nil, fmt.Errorf("%sthis file is read by soong, and must therefore be pure starlark and include only constant information. %q is not allowed", t.CallStack().String(), fn.Name())
+}
+
+var builtins = starlark.StringDict{
+ "aspect": starlark.NewBuiltin("aspect", unsupportedMethod),
+ "glob": starlark.NewBuiltin("glob", unsupportedMethod),
+ "json": starlarkjson.Module,
+ "provider": starlark.NewBuiltin("provider", unsupportedMethod),
+ "rule": starlark.NewBuiltin("rule", unsupportedMethod),
+ "struct": starlark.NewBuiltin("struct", starlarkstruct.Make),
+ "select": starlark.NewBuiltin("select", unsupportedMethod),
+ "transition": starlark.NewBuiltin("transition", unsupportedMethod),
+}
+
+// Takes a module name (the first argument to the load() function) and returns the path
+// it's trying to load, stripping out leading //, and handling leading :s.
+func cleanModuleName(moduleName string, callerDir string) (string, error) {
+ if strings.Count(moduleName, ":") > 1 {
+ return "", fmt.Errorf("at most 1 colon must be present in starlark path: %s", moduleName)
+ }
+
+ // We don't have full support for external repositories, but at least support skylib's dicts.
+ if moduleName == "@bazel_skylib//lib:dicts.bzl" {
+ return "external/bazel-skylib/lib/dicts.bzl", nil
+ }
+
+ localLoad := false
+ if strings.HasPrefix(moduleName, "@//") {
+ moduleName = moduleName[3:]
+ } else if strings.HasPrefix(moduleName, "//") {
+ moduleName = moduleName[2:]
+ } else if strings.HasPrefix(moduleName, ":") {
+ moduleName = moduleName[1:]
+ localLoad = true
+ } else {
+ return "", fmt.Errorf("load path must start with // or :")
+ }
+
+ if ix := strings.LastIndex(moduleName, ":"); ix >= 0 {
+ moduleName = moduleName[:ix] + string(os.PathSeparator) + moduleName[ix+1:]
+ }
+
+ if filepath.Clean(moduleName) != moduleName {
+ return "", fmt.Errorf("load path must be clean, found: %s, expected: %s", moduleName, filepath.Clean(moduleName))
+ }
+ if strings.HasPrefix(moduleName, "../") {
+ return "", fmt.Errorf("load path must not start with ../: %s", moduleName)
+ }
+ if strings.HasPrefix(moduleName, "/") {
+ return "", fmt.Errorf("load path starts with /, use // for a absolute path: %s", moduleName)
+ }
+
+ if localLoad {
+ return filepath.Join(callerDir, moduleName), nil
+ }
+
+ return moduleName, nil
+}
+
+// loader implements load statement. The format of the loaded module URI is
+//
+// [//path]:base
+//
+// The file path is $ROOT/path/base if path is present, <caller_dir>/base otherwise.
+func loader(thread *starlark.Thread, module string, topDir string, moduleCache map[string]*modentry, moduleCacheLock *sync.Mutex, filesystem map[string]string) (starlark.StringDict, error) {
+ modulePath, err := cleanModuleName(module, thread.Local(callerDirKey).(string))
+ if err != nil {
+ return nil, err
+ }
+ moduleCacheLock.Lock()
+ e, ok := moduleCache[modulePath]
+ if e == nil {
+ if ok {
+ moduleCacheLock.Unlock()
+ return nil, fmt.Errorf("cycle in load graph")
+ }
+
+ // Add a placeholder to indicate "load in progress".
+ moduleCache[modulePath] = nil
+ moduleCacheLock.Unlock()
+
+ childThread := &starlark.Thread{Name: "exec " + module, Load: thread.Load}
+
+ // Cheating for the sake of testing:
+ // propagate starlarktest's Reporter key, otherwise testing
+ // the load function may cause panic in starlarktest code.
+ const testReporterKey = "Reporter"
+ if v := thread.Local(testReporterKey); v != nil {
+ childThread.SetLocal(testReporterKey, v)
+ }
+
+ childThread.SetLocal(callerDirKey, filepath.Dir(modulePath))
+
+ if filesystem != nil {
+ globals, err := starlark.ExecFile(childThread, filepath.Join(topDir, modulePath), filesystem[modulePath], builtins)
+ e = &modentry{globals, err}
+ } else {
+ globals, err := starlark.ExecFile(childThread, filepath.Join(topDir, modulePath), nil, builtins)
+ e = &modentry{globals, err}
+ }
+
+ // Update the cache.
+ moduleCacheLock.Lock()
+ moduleCache[modulePath] = e
+ }
+ moduleCacheLock.Unlock()
+ return e.globals, e.err
+}
+
+// Run runs the given starlark file and returns its global variables and a list of all starlark
+// files that were loaded. The top dir for starlark's // is found via getTopDir().
+func runStarlarkFile(filename string) (starlark.StringDict, []string, error) {
+ topDir, err := getTopDir()
+ if err != nil {
+ return nil, nil, err
+ }
+ return runStarlarkFileWithFilesystem(filename, topDir, nil)
+}
+
+func runStarlarkFileWithFilesystem(filename string, topDir string, filesystem map[string]string) (starlark.StringDict, []string, error) {
+ if !strings.HasPrefix(filename, "//") && !strings.HasPrefix(filename, ":") {
+ filename = "//" + filename
+ }
+ filename, err := cleanModuleName(filename, "")
+ if err != nil {
+ return nil, nil, err
+ }
+ moduleCache := make(map[string]*modentry)
+ moduleCache[filename] = nil
+ moduleCacheLock := &sync.Mutex{}
+ mainThread := &starlark.Thread{
+ Name: "main",
+ Print: func(_ *starlark.Thread, msg string) {
+ // Ignore prints
+ },
+ Load: func(thread *starlark.Thread, module string) (starlark.StringDict, error) {
+ return loader(thread, module, topDir, moduleCache, moduleCacheLock, filesystem)
+ },
+ }
+ mainThread.SetLocal(callerDirKey, filepath.Dir(filename))
+
+ var result starlark.StringDict
+ if filesystem != nil {
+ result, err = starlark.ExecFile(mainThread, filepath.Join(topDir, filename), filesystem[filename], builtins)
+ } else {
+ result, err = starlark.ExecFile(mainThread, filepath.Join(topDir, filename), nil, builtins)
+ }
+ return result, sortedStringKeys(moduleCache), err
+}
+
+func sortedStringKeys(m map[string]*modentry) []string {
+ s := make([]string, 0, len(m))
+ for k := range m {
+ s = append(s, k)
+ }
+ sort.Strings(s)
+ return s
+}
diff --git a/starlark_import/starlark_import_test.go b/starlark_import/starlark_import_test.go
new file mode 100644
index 0000000..8a58e3b
--- /dev/null
+++ b/starlark_import/starlark_import_test.go
@@ -0,0 +1,122 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package starlark_import
+
+import (
+ "strings"
+ "testing"
+
+ "go.starlark.net/starlark"
+)
+
+func TestBasic(t *testing.T) {
+ globals, _, err := runStarlarkFileWithFilesystem("a.bzl", "", map[string]string{
+ "a.bzl": `
+my_string = "hello, world!"
+`})
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ if globals["my_string"].(starlark.String) != "hello, world!" {
+ t.Errorf("Expected %q, got %q", "hello, world!", globals["my_string"].String())
+ }
+}
+
+func TestLoad(t *testing.T) {
+ globals, _, err := runStarlarkFileWithFilesystem("a.bzl", "", map[string]string{
+ "a.bzl": `
+load("//b.bzl", _b_string = "my_string")
+my_string = "hello, " + _b_string
+`,
+ "b.bzl": `
+my_string = "world!"
+`})
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ if globals["my_string"].(starlark.String) != "hello, world!" {
+ t.Errorf("Expected %q, got %q", "hello, world!", globals["my_string"].String())
+ }
+}
+
+func TestLoadRelative(t *testing.T) {
+ globals, ninjaDeps, err := runStarlarkFileWithFilesystem("a.bzl", "", map[string]string{
+ "a.bzl": `
+load(":b.bzl", _b_string = "my_string")
+load("//foo/c.bzl", _c_string = "my_string")
+my_string = "hello, " + _b_string
+c_string = _c_string
+`,
+ "b.bzl": `
+my_string = "world!"
+`,
+ "foo/c.bzl": `
+load(":d.bzl", _d_string = "my_string")
+my_string = "hello, " + _d_string
+`,
+ "foo/d.bzl": `
+my_string = "world!"
+`})
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ if globals["my_string"].(starlark.String) != "hello, world!" {
+ t.Errorf("Expected %q, got %q", "hello, world!", globals["my_string"].String())
+ }
+
+ expectedNinjaDeps := []string{
+ "a.bzl",
+ "b.bzl",
+ "foo/c.bzl",
+ "foo/d.bzl",
+ }
+ if !slicesEqual(ninjaDeps, expectedNinjaDeps) {
+ t.Errorf("Expected %v ninja deps, got %v", expectedNinjaDeps, ninjaDeps)
+ }
+}
+
+func TestLoadCycle(t *testing.T) {
+ _, _, err := runStarlarkFileWithFilesystem("a.bzl", "", map[string]string{
+ "a.bzl": `
+load(":b.bzl", _b_string = "my_string")
+my_string = "hello, " + _b_string
+`,
+ "b.bzl": `
+load(":a.bzl", _a_string = "my_string")
+my_string = "hello, " + _a_string
+`})
+ if err == nil || !strings.Contains(err.Error(), "cycle in load graph") {
+ t.Errorf("Expected cycle in load graph, got: %v", err)
+ return
+ }
+}
+
+func slicesEqual[T comparable](a []T, b []T) bool {
+ if len(a) != len(b) {
+ return false
+ }
+ for i := range a {
+ if a[i] != b[i] {
+ return false
+ }
+ }
+ return true
+}
diff --git a/starlark_import/unmarshal.go b/starlark_import/unmarshal.go
new file mode 100644
index 0000000..1b54437
--- /dev/null
+++ b/starlark_import/unmarshal.go
@@ -0,0 +1,288 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package starlark_import
+
+import (
+ "fmt"
+ "math"
+ "reflect"
+ "unsafe"
+
+ "go.starlark.net/starlark"
+ "go.starlark.net/starlarkstruct"
+)
+
+func Unmarshal[T any](value starlark.Value) (T, error) {
+ var zero T
+ x, err := UnmarshalReflect(value, reflect.TypeOf(zero))
+ return x.Interface().(T), err
+}
+
+func UnmarshalReflect(value starlark.Value, ty reflect.Type) (reflect.Value, error) {
+ zero := reflect.Zero(ty)
+ var result reflect.Value
+ if ty.Kind() == reflect.Interface {
+ var err error
+ ty, err = typeOfStarlarkValue(value)
+ if err != nil {
+ return zero, err
+ }
+ }
+ if ty.Kind() == reflect.Map {
+ result = reflect.MakeMap(ty)
+ } else {
+ result = reflect.Indirect(reflect.New(ty))
+ }
+
+ switch v := value.(type) {
+ case starlark.String:
+ if result.Type().Kind() != reflect.String {
+ return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
+ }
+ result.SetString(v.GoString())
+ case starlark.Int:
+ signedValue, signedOk := v.Int64()
+ unsignedValue, unsignedOk := v.Uint64()
+ switch result.Type().Kind() {
+ case reflect.Int64:
+ if !signedOk {
+ return zero, fmt.Errorf("starlark int didn't fit in go int64")
+ }
+ result.SetInt(signedValue)
+ case reflect.Int32:
+ if !signedOk || signedValue > math.MaxInt32 || signedValue < math.MinInt32 {
+ return zero, fmt.Errorf("starlark int didn't fit in go int32")
+ }
+ result.SetInt(signedValue)
+ case reflect.Int16:
+ if !signedOk || signedValue > math.MaxInt16 || signedValue < math.MinInt16 {
+ return zero, fmt.Errorf("starlark int didn't fit in go int16")
+ }
+ result.SetInt(signedValue)
+ case reflect.Int8:
+ if !signedOk || signedValue > math.MaxInt8 || signedValue < math.MinInt8 {
+ return zero, fmt.Errorf("starlark int didn't fit in go int8")
+ }
+ result.SetInt(signedValue)
+ case reflect.Int:
+ if !signedOk || signedValue > math.MaxInt || signedValue < math.MinInt {
+ return zero, fmt.Errorf("starlark int didn't fit in go int")
+ }
+ result.SetInt(signedValue)
+ case reflect.Uint64:
+ if !unsignedOk {
+ return zero, fmt.Errorf("starlark int didn't fit in go uint64")
+ }
+ result.SetUint(unsignedValue)
+ case reflect.Uint32:
+ if !unsignedOk || unsignedValue > math.MaxUint32 {
+ return zero, fmt.Errorf("starlark int didn't fit in go uint32")
+ }
+ result.SetUint(unsignedValue)
+ case reflect.Uint16:
+ if !unsignedOk || unsignedValue > math.MaxUint16 {
+ return zero, fmt.Errorf("starlark int didn't fit in go uint16")
+ }
+ result.SetUint(unsignedValue)
+ case reflect.Uint8:
+ if !unsignedOk || unsignedValue > math.MaxUint8 {
+ return zero, fmt.Errorf("starlark int didn't fit in go uint8")
+ }
+ result.SetUint(unsignedValue)
+ case reflect.Uint:
+ if !unsignedOk || unsignedValue > math.MaxUint {
+ return zero, fmt.Errorf("starlark int didn't fit in go uint")
+ }
+ result.SetUint(unsignedValue)
+ default:
+ return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
+ }
+ case starlark.Float:
+ f := float64(v)
+ switch result.Type().Kind() {
+ case reflect.Float64:
+ result.SetFloat(f)
+ case reflect.Float32:
+ if f > math.MaxFloat32 || f < -math.MaxFloat32 {
+ return zero, fmt.Errorf("starlark float didn't fit in go float32")
+ }
+ result.SetFloat(f)
+ default:
+ return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
+ }
+ case starlark.Bool:
+ if result.Type().Kind() != reflect.Bool {
+ return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
+ }
+ result.SetBool(bool(v))
+ case starlark.Tuple:
+ if result.Type().Kind() != reflect.Slice {
+ return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
+ }
+ elemType := result.Type().Elem()
+ // TODO: Add this grow call when we're on go 1.20
+ //result.Grow(v.Len())
+ for i := 0; i < v.Len(); i++ {
+ elem, err := UnmarshalReflect(v.Index(i), elemType)
+ if err != nil {
+ return zero, err
+ }
+ result = reflect.Append(result, elem)
+ }
+ case *starlark.List:
+ if result.Type().Kind() != reflect.Slice {
+ return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
+ }
+ elemType := result.Type().Elem()
+ // TODO: Add this grow call when we're on go 1.20
+ //result.Grow(v.Len())
+ for i := 0; i < v.Len(); i++ {
+ elem, err := UnmarshalReflect(v.Index(i), elemType)
+ if err != nil {
+ return zero, err
+ }
+ result = reflect.Append(result, elem)
+ }
+ case *starlark.Dict:
+ if result.Type().Kind() != reflect.Map {
+ return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
+ }
+ keyType := result.Type().Key()
+ valueType := result.Type().Elem()
+ for _, pair := range v.Items() {
+ key := pair.Index(0)
+ value := pair.Index(1)
+
+ unmarshalledKey, err := UnmarshalReflect(key, keyType)
+ if err != nil {
+ return zero, err
+ }
+ unmarshalledValue, err := UnmarshalReflect(value, valueType)
+ if err != nil {
+ return zero, err
+ }
+
+ result.SetMapIndex(unmarshalledKey, unmarshalledValue)
+ }
+ case *starlarkstruct.Struct:
+ if result.Type().Kind() != reflect.Struct {
+ return zero, fmt.Errorf("starlark type was %s, but %s requested", v.Type(), result.Type().Kind().String())
+ }
+ if result.NumField() != len(v.AttrNames()) {
+ return zero, fmt.Errorf("starlark struct and go struct have different number of fields (%d and %d)", len(v.AttrNames()), result.NumField())
+ }
+ for _, attrName := range v.AttrNames() {
+ attr, err := v.Attr(attrName)
+ if err != nil {
+ return zero, err
+ }
+
+ // TODO(b/279787235): this should probably support tags to rename the field
+ resultField := result.FieldByName(attrName)
+ if resultField == (reflect.Value{}) {
+ return zero, fmt.Errorf("starlark struct had field %s, but requested struct type did not", attrName)
+ }
+ // This hack allows us to change unexported fields
+ resultField = reflect.NewAt(resultField.Type(), unsafe.Pointer(resultField.UnsafeAddr())).Elem()
+ x, err := UnmarshalReflect(attr, resultField.Type())
+ if err != nil {
+ return zero, err
+ }
+ resultField.Set(x)
+ }
+ default:
+ return zero, fmt.Errorf("unimplemented starlark type: %s", value.Type())
+ }
+
+ return result, nil
+}
+
+func typeOfStarlarkValue(value starlark.Value) (reflect.Type, error) {
+ var err error
+ switch v := value.(type) {
+ case starlark.String:
+ return reflect.TypeOf(""), nil
+ case *starlark.List:
+ innerType := reflect.TypeOf("")
+ if v.Len() > 0 {
+ innerType, err = typeOfStarlarkValue(v.Index(0))
+ if err != nil {
+ return nil, err
+ }
+ }
+ for i := 1; i < v.Len(); i++ {
+ innerTypeI, err := typeOfStarlarkValue(v.Index(i))
+ if err != nil {
+ return nil, err
+ }
+ if innerType != innerTypeI {
+ return nil, fmt.Errorf("List must contain elements of entirely the same type, found %v and %v", innerType, innerTypeI)
+ }
+ }
+ return reflect.SliceOf(innerType), nil
+ case *starlark.Dict:
+ keyType := reflect.TypeOf("")
+ valueType := reflect.TypeOf("")
+ keys := v.Keys()
+ if v.Len() > 0 {
+ firstKey := keys[0]
+ keyType, err = typeOfStarlarkValue(firstKey)
+ if err != nil {
+ return nil, err
+ }
+ firstValue, found, err := v.Get(firstKey)
+ if !found {
+ err = fmt.Errorf("value not found")
+ }
+ if err != nil {
+ return nil, err
+ }
+ valueType, err = typeOfStarlarkValue(firstValue)
+ if err != nil {
+ return nil, err
+ }
+ }
+ for _, key := range keys {
+ keyTypeI, err := typeOfStarlarkValue(key)
+ if err != nil {
+ return nil, err
+ }
+ if keyType != keyTypeI {
+ return nil, fmt.Errorf("dict must contain elements of entirely the same type, found %v and %v", keyType, keyTypeI)
+ }
+ value, found, err := v.Get(key)
+ if !found {
+ err = fmt.Errorf("value not found")
+ }
+ if err != nil {
+ return nil, err
+ }
+ valueTypeI, err := typeOfStarlarkValue(value)
+ if valueType.Kind() != reflect.Interface && valueTypeI != valueType {
+ // If we see conflicting value types, change the result value type to an empty interface
+ valueType = reflect.TypeOf([]interface{}{}).Elem()
+ }
+ }
+ return reflect.MapOf(keyType, valueType), nil
+ case starlark.Int:
+ return reflect.TypeOf(0), nil
+ case starlark.Float:
+ return reflect.TypeOf(0.0), nil
+ case starlark.Bool:
+ return reflect.TypeOf(true), nil
+ default:
+ return nil, fmt.Errorf("unimplemented starlark type: %s", value.Type())
+ }
+}
diff --git a/starlark_import/unmarshal_test.go b/starlark_import/unmarshal_test.go
new file mode 100644
index 0000000..ee7a9e3
--- /dev/null
+++ b/starlark_import/unmarshal_test.go
@@ -0,0 +1,133 @@
+// Copyright 2023 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package starlark_import
+
+import (
+ "reflect"
+ "testing"
+
+ "go.starlark.net/starlark"
+)
+
+func createStarlarkValue(t *testing.T, code string) starlark.Value {
+ t.Helper()
+ result, err := starlark.ExecFile(&starlark.Thread{}, "main.bzl", "x = "+code, builtins)
+ if err != nil {
+ panic(err)
+ }
+ return result["x"]
+}
+
+func TestUnmarshallConcreteType(t *testing.T) {
+ x, err := Unmarshal[string](createStarlarkValue(t, `"foo"`))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if x != "foo" {
+ t.Errorf(`Expected "foo", got %q`, x)
+ }
+}
+
+func TestUnmarshallConcreteTypeWithInterfaces(t *testing.T) {
+ x, err := Unmarshal[map[string]map[string]interface{}](createStarlarkValue(t,
+ `{"foo": {"foo2": "foo3"}, "bar": {"bar2": ["bar3"]}}`))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ expected := map[string]map[string]interface{}{
+ "foo": {"foo2": "foo3"},
+ "bar": {"bar2": []string{"bar3"}},
+ }
+ if !reflect.DeepEqual(x, expected) {
+ t.Errorf(`Expected %v, got %v`, expected, x)
+ }
+}
+
+func TestUnmarshall(t *testing.T) {
+ testCases := []struct {
+ input string
+ expected interface{}
+ }{
+ {
+ input: `"foo"`,
+ expected: "foo",
+ },
+ {
+ input: `5`,
+ expected: 5,
+ },
+ {
+ input: `["foo", "bar"]`,
+ expected: []string{"foo", "bar"},
+ },
+ {
+ input: `("foo", "bar")`,
+ expected: []string{"foo", "bar"},
+ },
+ {
+ input: `("foo",5)`,
+ expected: []interface{}{"foo", 5},
+ },
+ {
+ input: `{"foo": 5, "bar": 10}`,
+ expected: map[string]int{"foo": 5, "bar": 10},
+ },
+ {
+ input: `{"foo": ["qux"], "bar": []}`,
+ expected: map[string][]string{"foo": {"qux"}, "bar": nil},
+ },
+ {
+ input: `struct(Foo="foo", Bar=5)`,
+ expected: struct {
+ Foo string
+ Bar int
+ }{Foo: "foo", Bar: 5},
+ },
+ {
+ // Unexported fields version of the above
+ input: `struct(foo="foo", bar=5)`,
+ expected: struct {
+ foo string
+ bar int
+ }{foo: "foo", bar: 5},
+ },
+ {
+ input: `{"foo": "foo2", "bar": ["bar2"], "baz": 5, "qux": {"qux2": "qux3"}, "quux": {"quux2": "quux3", "quux4": 5}}`,
+ expected: map[string]interface{}{
+ "foo": "foo2",
+ "bar": []string{"bar2"},
+ "baz": 5,
+ "qux": map[string]string{"qux2": "qux3"},
+ "quux": map[string]interface{}{
+ "quux2": "quux3",
+ "quux4": 5,
+ },
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ x, err := UnmarshalReflect(createStarlarkValue(t, tc.input), reflect.TypeOf(tc.expected))
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+ if !reflect.DeepEqual(x.Interface(), tc.expected) {
+ t.Errorf(`Expected %#v, got %#v`, tc.expected, x.Interface())
+ }
+ }
+}
diff --git a/tests/apex_cc_module_arch_variant_tests.sh b/tests/apex_cc_module_arch_variant_tests.sh
index b0cade1..1f5e003 100755
--- a/tests/apex_cc_module_arch_variant_tests.sh
+++ b/tests/apex_cc_module_arch_variant_tests.sh
@@ -56,12 +56,12 @@
# Number of CppCompile actions with arch variant flag
actions_with_arch_variant_num=$(call_bazel aquery --config=bp2build --config=ci --config=android \
- 'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex))' | grep -c \'-march=$ARCH_VARIANT_CFLAG\')
+ 'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))' | grep -c \'-march=$ARCH_VARIANT_CFLAG\')
# Number of all CppCompile actions
all_cppcompile_actions_num=0
aquery_summary=$(call_bazel aquery --config=bp2build --config=ci --config=android --output=summary \
- 'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex))' \
+ 'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))' \
| egrep -o '.*opt-ST.*: ([0-9]+)$' \
| cut -d: -f2 -)
@@ -82,7 +82,7 @@
then
# Number of CppCompiler actions with cpu variant flag
actions_with_cpu_variant_num=$(call_bazel aquery --config=bp2build --config=ci --config=android \
- 'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex))' | grep -c "\-mcpu=$CPU_VARIANT_CFLAG")
+ 'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))' | grep -c "\-mcpu=$CPU_VARIANT_CFLAG")
if [ $actions_with_cpu_variant_num -eq $all_cppcompile_actions_num ]
then
@@ -91,4 +91,4 @@
echo "Error: number of CppCompile actions with cpu variant set: actual=$actions_with_cpu_variant_num, expected=$all_cppcompile_actions_num"
exit 1
fi
-fi
\ No newline at end of file
+fi
diff --git a/tests/apex_comparison_tests.sh b/tests/apex_comparison_tests.sh
index 5007078..e350323 100755
--- a/tests/apex_comparison_tests.sh
+++ b/tests/apex_comparison_tests.sh
@@ -66,10 +66,10 @@
call_bazel build --config=bp2build --config=ci --config=android \
//packages/modules/adb/apex:com.android.adbd \
//system/timezone/apex:com.android.tzdata \
- //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex
+ //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal
BAZEL_ADBD="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //packages/modules/adb/apex:com.android.adbd))"
BAZEL_TZDATA="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //system/timezone/apex:com.android.tzdata))"
-BAZEL_MINIMAL="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex))"
+BAZEL_MINIMAL="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))"
# # Build debugfs separately, as it's not a dep of apexer, but needs to be an explicit arg.
call_bazel build --config=bp2build --config=linux_x86_64 //external/e2fsprogs/debugfs //system/apex/tools:deapexer
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
index 1ff1b5b..71e6af0 100755
--- a/tests/bp2build_bazel_test.sh
+++ b/tests/bp2build_bazel_test.sh
@@ -53,6 +53,20 @@
if [[ "$buildfile_mtime1" != "$buildfile_mtime2" ]]; then
fail "BUILD.bazel was updated even though contents are same"
fi
+
+ # Force bp2build to rerun by updating the timestamp of the constants_exported_to_soong.bzl file.
+ touch build/bazel/constants_exported_to_soong.bzl
+
+ run_soong bp2build
+ local -r buildfile_mtime3=$(stat -c "%y" out/soong/bp2build/pkg/BUILD.bazel)
+ local -r marker_mtime3=$(stat -c "%y" out/soong/bp2build_workspace_marker)
+
+ if [[ "$marker_mtime2" == "$marker_mtime3" ]]; then
+ fail "Expected bp2build marker file to change"
+ fi
+ if [[ "$buildfile_mtime2" != "$buildfile_mtime3" ]]; then
+ fail "BUILD.bazel was updated even though contents are same"
+ fi
}
# Tests that blueprint files that are deleted are not present when the
@@ -343,4 +357,29 @@
run_bazel build --config=android --config=api_bp2build //:empty
}
+# Verify that an *_api_contribution target can refer to an api file from
+# another Bazel package.
+function test_api_export_from_another_bazel_package() {
+ setup
+ # Parent dir Android.bp
+ mkdir -p foo
+ cat > foo/Android.bp << 'EOF'
+cc_library {
+ name: "libfoo",
+ stubs: {
+ symbol_file: "api/libfoo.map.txt",
+ },
+}
+EOF
+ # Child dir Android.bp
+ mkdir -p foo/api
+ cat > foo/api/Android.bp << 'EOF'
+package{}
+EOF
+ touch foo/api/libfoo.map.txt
+ # Run test
+ run_soong api_bp2build
+ run_bazel build --config=android --config=api_bp2build //foo:libfoo.contribution
+}
+
scan_and_run_tests
diff --git a/tests/dcla_apex_comparison_test.sh b/tests/dcla_apex_comparison_test.sh
index 2ecb876..97ae97e 100755
--- a/tests/dcla_apex_comparison_test.sh
+++ b/tests/dcla_apex_comparison_test.sh
@@ -112,7 +112,7 @@
sha="${sha% *}"
if [ "${prev_sha}" == "" ]; then
prev_sha="${sha}"
- elif [ "${sha}" != "${prev_sha}" ]; then
+ elif [ "${sha}" != "${prev_sha}" ] && { [ "${lib}" != "libcrypto.so" ] || [ "${module}" != "com.android.tethering" ]; }; then
echo "Test failed, ${lib} has different hash value"
exit 1
fi
diff --git a/tests/lib.sh b/tests/lib.sh
index 0973beb..715eac1 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -91,11 +91,14 @@
symlink_directory prebuilts/go
symlink_directory prebuilts/build-tools
symlink_directory prebuilts/clang/host
+ symlink_directory external/compiler-rt
symlink_directory external/go-cmp
symlink_directory external/golang-protobuf
+ symlink_directory external/licenseclassifier
symlink_directory external/starlark-go
symlink_directory external/python
symlink_directory external/sqlite
+ symlink_directory external/spdx-tools
touch "$MOCK_TOP/Android.bp"
}
@@ -164,5 +167,6 @@
fi
for f in ${test_fns[*]}; do
$f
+ info "Completed test case \e[96;1m$f\e[0m"
done
}
diff --git a/tests/mixed_mode_test.sh b/tests/mixed_mode_test.sh
index 7b3151b..ca63fdf 100755
--- a/tests/mixed_mode_test.sh
+++ b/tests/mixed_mode_test.sh
@@ -1,4 +1,4 @@
-#!/bin/bash -eu
+#!/bin/bash
set -o pipefail
@@ -63,4 +63,37 @@
fi
}
-scan_and_run_tests
\ No newline at end of file
+function test_force_enabled_modules {
+ setup
+ # b/273910287 - test force enable modules
+ mkdir -p soong_tests/a/b
+ cat > soong_tests/a/b/Android.bp <<'EOF'
+genrule {
+ name: "touch-file",
+ out: ["fake-out.txt"],
+ cmd: "touch $(out)",
+ bazel_module: { bp2build_available: true },
+}
+
+genrule {
+ name: "unenabled-touch-file",
+ out: ["fake-out2.txt"],
+ cmd: "touch $(out)",
+ bazel_module: { bp2build_available: false },
+}
+EOF
+ run_soong --bazel-mode-staging --bazel-force-enabled-modules=touch-file nothing
+ local bazel_contained=`grep out/soong/.intermediates/soong_tests/a/b/touch-file/gen/fake-out.txt out/soong/build.ninja`
+ if [[ $bazel_contained == '' ]]; then
+ fail "Bazel actions not found for force-enabled module"
+ fi
+
+ unused=`run_soong --bazel-force-enabled-modules=unenabled-touch-file --ensure-allowlist-integrity nothing >/dev/null`
+
+ if [[ $? -ne 1 ]]; then
+ fail "Expected failure due to force-enabling an unenabled module "
+ fi
+}
+
+
+scan_and_run_tests
diff --git a/tests/persistent_bazel_test.sh b/tests/persistent_bazel_test.sh
index 4e2982a..9b7b58f 100755
--- a/tests/persistent_bazel_test.sh
+++ b/tests/persistent_bazel_test.sh
@@ -73,8 +73,8 @@
USE_PERSISTENT_BAZEL=1 run_soong nothing 1>out/failurelog.txt 2>&1 && fail "Expected build failure" || true
- if ! grep -sq "'build/bazel/rules' is not a package" out/failurelog.txt ; then
- fail "Expected error to contain 'build/bazel/rules' is not a package, instead got:\n$(cat out/failurelog.txt)"
+ if ! grep -sq "cannot load //build/bazel/rules/common/api_constants.bzl" out/failurelog.txt ; then
+ fail "Expected error to contain 'cannot load //build/bazel/rules/common/api_constants.bzl', instead got:\n$(cat out/failurelog.txt)"
fi
kill $(cat out/bazel/output/server/server.pid.txt) 2>/dev/null || true
diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh
index a762952..e1aa70c 100755
--- a/tests/run_integration_tests.sh
+++ b/tests/run_integration_tests.sh
@@ -20,3 +20,5 @@
"$TOP/build/soong/tests/apex_cc_module_arch_variant_tests.sh"
"$TOP/build/soong/tests/apex_cc_module_arch_variant_tests.sh" "aosp_arm" "armv7-a"
"$TOP/build/soong/tests/apex_cc_module_arch_variant_tests.sh" "aosp_cf_arm64_phone" "armv8-a" "cortex-a53"
+
+"$TOP/build/soong/tests/sbom_test.sh"
diff --git a/tests/sbom_test.sh b/tests/sbom_test.sh
new file mode 100755
index 0000000..2f154cd
--- /dev/null
+++ b/tests/sbom_test.sh
@@ -0,0 +1,214 @@
+#!/bin/bash
+
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -uo pipefail
+
+# Integration test for verifying generated SBOM for cuttlefish device.
+
+if [ ! -e "build/make/core/Makefile" ]; then
+ echo "$0 must be run from the top of the Android source tree."
+ exit 1
+fi
+
+tmp_dir="$(mktemp -d tmp.XXXXXX)"
+function cleanup {
+ rm -rf "${tmp_dir}"
+}
+trap cleanup EXIT
+
+out_dir=$tmp_dir
+droid_target=droid
+
+debug=false
+if [ $debug = "true" ]; then
+ out_dir=out
+ droid_target=
+fi
+
+function run_soong {
+ TARGET_PRODUCT="aosp_cf_x86_64_phone" TARGET_BUILD_VARIANT=userdebug OUT_DIR=$out_dir \
+ build/soong/soong_ui.bash --make-mode "$@"
+}
+
+# m droid, build sbom later in case additional dependencies might be built and included in partition images.
+run_soong $droid_target dump.erofs lz4
+
+product_out=$out_dir/target/product/vsoc_x86_64
+sbom_test=$product_out/sbom_test
+mkdir $sbom_test
+cp $product_out/*.img $sbom_test
+
+# m sbom
+run_soong sbom
+
+# Generate installed file list from .img files in PRODUCT_OUT
+dump_erofs=$out_dir/host/linux-x86/bin/dump.erofs
+lz4=$out_dir/host/linux-x86/bin/lz4
+
+declare -A diff_excludes
+diff_excludes[odm]="-I /odm/lib/modules"
+diff_excludes[vendor]=\
+"-I /vendor/lib64/libkeystore2_crypto.so \
+ -I /vendor/lib/modules \
+ -I /vendor/odm"
+diff_excludes[system]=\
+"-I /bin \
+ -I /bugreports \
+ -I /cache \
+ -I /d \
+ -I /etc \
+ -I /init \
+ -I /odm/app \
+ -I /odm/bin \
+ -I /odm_dlkm/etc \
+ -I /odm/etc \
+ -I /odm/firmware \
+ -I /odm/framework \
+ -I /odm/lib \
+ -I /odm/lib64 \
+ -I /odm/overlay \
+ -I /odm/priv-app \
+ -I /odm/usr \
+ -I /sdcard \
+ -I /system/lib64/android.hardware.confirmationui@1.0.so \
+ -I /system/lib64/android.hardware.confirmationui-V1-ndk.so \
+ -I /system/lib64/android.hardware.keymaster@4.1.so \
+ -I /system/lib64/android.hardware.security.rkp-V3-ndk.so \
+ -I /system/lib64/android.hardware.security.sharedsecret-V1-ndk.so \
+ -I /system/lib64/android.security.compat-ndk.so \
+ -I /system/lib64/libkeymaster4_1support.so \
+ -I /system/lib64/libkeymint.so \
+ -I /system/lib64/libkeystore2_aaid.so \
+ -I /system/lib64/libkeystore2_apc_compat.so \
+ -I /system/lib64/libkeystore2_crypto.so \
+ -I /system/lib64/libkm_compat_service.so \
+ -I /system/lib64/libkm_compat.so \
+ -I /system/lib64/vndk-29 \
+ -I /system/lib64/vndk-sp-29 \
+ -I /system/lib/vndk-29 \
+ -I /system/lib/vndk-sp-29 \
+ -I /system/usr/icu \
+ -I /vendor_dlkm/etc"
+
+function diff_files {
+ file_list_file="$1"; shift
+ files_in_spdx_file="$1"; shift
+ partition_name="$1"; shift
+ exclude=
+ if [ -v 'diff_excludes[$partition_name]' ]; then
+ exclude=${diff_excludes[$partition_name]}
+ fi
+
+ diff "$file_list_file" "$files_in_spdx_file" $exclude
+ if [ $? != "0" ]; then
+ echo Found diffs in $f and SBOM.
+ exit 1
+ else
+ echo No diffs.
+ fi
+ }
+
+# Example output of dump.erofs is as below, and the data used in the test start
+# at line 11. Column 1 is inode id, column 2 is inode type and column 3 is name.
+# Each line is captured in variable "entry", awk is used to get type and name.
+# Output of dump.erofs:
+# File : /
+# Size: 160 On-disk size: 160 directory
+# NID: 39 Links: 10 Layout: 2 Compression ratio: 100.00%
+# Inode size: 64 Extent size: 0 Xattr size: 16
+# Uid: 0 Gid: 0 Access: 0755/rwxr-xr-x
+# Timestamp: 2023-02-14 01:15:54.000000000
+#
+# NID TYPE FILENAME
+# 39 2 .
+# 39 2 ..
+# 47 2 app
+# 1286748 2 bin
+# 1286754 2 etc
+# 5304814 2 lib
+# 5309056 2 lib64
+# 5309130 2 media
+# 5388910 2 overlay
+# 5479537 2 priv-app
+EROFS_IMAGES="\
+ $sbom_test/product.img \
+ $sbom_test/system.img \
+ $sbom_test/system_ext.img \
+ $sbom_test/system_dlkm.img \
+ $sbom_test/system_other.img \
+ $sbom_test/odm.img \
+ $sbom_test/odm_dlkm.img \
+ $sbom_test/vendor.img \
+ $sbom_test/vendor_dlkm.img"
+for f in $EROFS_IMAGES; do
+ partition_name=$(basename $f | cut -d. -f1)
+ file_list_file="${sbom_test}/sbom-${partition_name}-files.txt"
+ files_in_spdx_file="${sbom_test}/sbom-${partition_name}-files-in-spdx.txt"
+ rm "$file_list_file" > /dev/null 2>&1
+ all_dirs="/"
+ while [ ! -z "$all_dirs" ]; do
+ dir=$(echo "$all_dirs" | cut -d ' ' -f1)
+ all_dirs=$(echo "$all_dirs" | cut -d ' ' -f1 --complement -s)
+ entries=$($dump_erofs --ls --path "$dir" $f | tail -n +11)
+ while read -r entry; do
+ inode_type=$(echo $entry | awk -F ' ' '{print $2}')
+ name=$(echo $entry | awk -F ' ' '{print $3}')
+ case $inode_type in
+ "2") # directory
+ all_dirs=$(echo "$all_dirs $dir/$name" | sed 's/^\s*//')
+ ;;
+ "1"|"7") # 1: file, 7: symlink
+ (
+ if [ "$partition_name" != "system" ]; then
+ # system partition is mounted to /, not to prepend partition name.
+ printf %s "/$partition_name"
+ fi
+ echo "$dir/$name" | sed 's#^//#/#'
+ ) >> "$file_list_file"
+ ;;
+ esac
+ done <<< "$entries"
+ done
+ sort -n -o "$file_list_file" "$file_list_file"
+
+ grep "FileName: /${partition_name}/" $product_out/sbom.spdx | sed 's/^FileName: //' > "$files_in_spdx_file"
+ if [ "$partition_name" = "system" ]; then
+ # system partition is mounted to /, so include FileName starts with /root/ too.
+ grep "FileName: /root/" $product_out/sbom.spdx | sed 's/^FileName: \/root//' >> "$files_in_spdx_file"
+ fi
+ sort -n -o "$files_in_spdx_file" "$files_in_spdx_file"
+
+ echo ============ Diffing files in $f and SBOM
+ diff_files "$file_list_file" "$files_in_spdx_file" "$partition_name"
+done
+
+RAMDISK_IMAGES="$product_out/ramdisk.img"
+for f in $RAMDISK_IMAGES; do
+ partition_name=$(basename $f | cut -d. -f1)
+ file_list_file="${sbom_test}/sbom-${partition_name}-files.txt"
+ files_in_spdx_file="${sbom_test}/sbom-${partition_name}-files-in-spdx.txt"
+ # lz4 decompress $f to stdout
+ # cpio list all entries like ls -l
+ # grep filter normal files and symlinks
+ # awk get entry names
+ # sed remove partition name from entry names
+ $lz4 -c -d $f | cpio -tv 2>/dev/null | grep '^[-l]' | awk -F ' ' '{print $9}' | sed "s:^:/$partition_name/:" | sort -n > "$file_list_file"
+
+ grep "FileName: /${partition_name}/" $product_out/sbom.spdx | sed 's/^FileName: //' | sort -n > "$files_in_spdx_file"
+
+ echo ============ Diffing files in $f and SBOM
+ diff_files "$file_list_file" "$files_in_spdx_file" "$partition_name"
+done
\ No newline at end of file
diff --git a/third_party/zip/writer.go b/third_party/zip/writer.go
index f526838..8a957e1 100644
--- a/third_party/zip/writer.go
+++ b/third_party/zip/writer.go
@@ -162,9 +162,17 @@
if records > uint16max {
records = uint16max
}
+ // Only store uint32max for the size and the offset if they don't fit.
+ // Robolectric currently doesn't support zip64 and fails to find the
+ // offset to the central directory when the number of files in the zip
+ // is larger than 2^16.
+ if size > uint32max {
+ size = uint32max
+ }
+ if offset > uint32max {
+ offset = uint32max
+ }
// END ANDROID CHANGE
- size = uint32max
- offset = uint32max
}
// write end record
diff --git a/tradefed/config.go b/tradefed/config.go
index 999424c..326a006 100644
--- a/tradefed/config.go
+++ b/tradefed/config.go
@@ -31,6 +31,7 @@
pctx.SourcePathVariable("NativeBenchmarkTestConfigTemplate", "build/make/core/native_benchmark_test_config_template.xml")
pctx.SourcePathVariable("NativeHostTestConfigTemplate", "build/make/core/native_host_test_config_template.xml")
pctx.SourcePathVariable("NativeTestConfigTemplate", "build/make/core/native_test_config_template.xml")
+ pctx.SourcePathVariable("PythonBinaryHostMoblyTestConfigTemplate", "build/make/core/python_binary_host_mobly_test_config_template.xml")
pctx.SourcePathVariable("PythonBinaryHostTestConfigTemplate", "build/make/core/python_binary_host_test_config_template.xml")
pctx.SourcePathVariable("RustDeviceTestConfigTemplate", "build/make/core/rust_device_test_config_template.xml")
pctx.SourcePathVariable("RustHostTestConfigTemplate", "build/make/core/rust_host_test_config_template.xml")
diff --git a/tradefed/suite_harness/tradefed_binary.go b/tradefed/suite_harness/tradefed_binary.go
index a421d8b..1ce94bc 100644
--- a/tradefed/suite_harness/tradefed_binary.go
+++ b/tradefed/suite_harness/tradefed_binary.go
@@ -78,7 +78,6 @@
// Add dependencies required by all tradefed_binary modules.
props.Libs = []string{
"tradefed",
- "tradefed-test-framework",
"loganalysis",
"compatibility-host-util",
}
diff --git a/ui/build/build.go b/ui/build/build.go
index edc595d..6874ef7 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -259,10 +259,16 @@
startGoma(ctx, config)
}
+ rbeCh := make(chan bool)
if config.StartRBE() {
cleanupRBELogsDir(ctx, config)
- startRBE(ctx, config)
+ go func() {
+ startRBE(ctx, config)
+ close(rbeCh)
+ }()
defer DumpRBEMetrics(ctx, config, filepath.Join(config.LogsDir(), "rbe_metrics.pb"))
+ } else {
+ close(rbeCh)
}
if what&RunProductConfig != 0 {
@@ -315,11 +321,11 @@
testForDanglingRules(ctx, config)
}
+ <-rbeCh
if what&RunNinja != 0 {
if what&RunKati != 0 {
installCleanIfNecessary(ctx, config)
}
-
runNinjaForBuild(ctx, config)
}
diff --git a/ui/build/config.go b/ui/build/config.go
index b5ee440..2dda52a 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -45,7 +45,8 @@
)
var (
- rbeRandPrefix int
+ rbeRandPrefix int
+ googleProdCredsExistCache bool
)
func init() {
@@ -66,26 +67,29 @@
logsPrefix string
// From the arguments
- parallel int
- keepGoing int
- verbose bool
- checkbuild bool
- dist bool
- jsonModuleGraph bool
- apiBp2build bool // Generate BUILD files for Soong modules that contribute APIs
- bp2build bool
- queryview bool
- reportMkMetrics bool // Collect and report mk2bp migration progress metrics.
- soongDocs bool
- skipConfig bool
- skipKati bool
- skipKatiNinja bool
- skipSoong bool
- skipNinja bool
- skipSoongTests bool
- searchApiDir bool // Scan the Android.bp files generated in out/api_surfaces
- skipMetricsUpload bool
- buildStartedTime int64 // For metrics-upload-only - manually specify a build-started time
+ parallel int
+ keepGoing int
+ verbose bool
+ checkbuild bool
+ dist bool
+ jsonModuleGraph bool
+ apiBp2build bool // Generate BUILD files for Soong modules that contribute APIs
+ bp2build bool
+ queryview bool
+ reportMkMetrics bool // Collect and report mk2bp migration progress metrics.
+ soongDocs bool
+ multitreeBuild bool // This is a multitree build.
+ skipConfig bool
+ skipKati bool
+ skipKatiNinja bool
+ skipSoong bool
+ skipNinja bool
+ skipSoongTests bool
+ searchApiDir bool // Scan the Android.bp files generated in out/api_surfaces
+ skipMetricsUpload bool
+ buildStartedTime int64 // For metrics-upload-only - manually specify a build-started time
+ buildFromTextStub bool
+ ensureAllowlistIntegrity bool // For CI builds - make sure modules are mixed-built
// From the product config
katiArgs []string
@@ -115,9 +119,27 @@
bazelForceEnabledModules string
- includeTags []string
+ includeTags []string
+ sourceRootDirs []string
+
+ // Data source to write ninja weight list
+ ninjaWeightListSource NinjaWeightListSource
}
+type NinjaWeightListSource uint
+
+const (
+ // ninja doesn't use weight list.
+ NOT_USED NinjaWeightListSource = iota
+ // ninja uses weight list based on previous builds by ninja log
+ NINJA_LOG
+ // ninja thinks every task has the same weight.
+ EVENLY_DISTRIBUTED
+ // ninja uses an external custom weight list
+ EXTERNAL_FILE
+ // ninja uses a prioritized module list from Soong
+ HINT_FROM_SOONG
+)
const srcDirFileCheck = "build/soong/root.bp"
var buildFiles = []string{"Android.mk", "Android.bp"}
@@ -302,6 +324,10 @@
ret.totalRAM = detectTotalRAM(ctx)
ret.parseArgs(ctx, args)
+
+ if ret.ninjaWeightListSource == HINT_FROM_SOONG {
+ ret.environ.Set("SOONG_GENERATES_NINJA_HINT", "true")
+ }
// Make sure OUT_DIR is set appropriately
if outDir, ok := ret.environ.Get("OUT_DIR"); ok {
ret.environ.Set("OUT_DIR", filepath.Clean(outDir))
@@ -474,6 +500,10 @@
ret.environ.Set("ANDROID_JAVA11_HOME", java11Home)
ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
+ if ret.MultitreeBuild() {
+ ret.environ.Set("MULTITREE_BUILD", "true")
+ }
+
outDir := ret.OutDir()
buildDateTimeFile := filepath.Join(outDir, "build_date.txt")
if buildDateTime, ok := ret.environ.Get("BUILD_DATETIME"); ok && buildDateTime != "" {
@@ -490,6 +520,11 @@
}
}
+ if ret.BuildFromTextStub() {
+ // TODO(b/271443071): support hidden api check for from-text stub build
+ ret.environ.Set("UNSAFE_DISABLE_HIDDENAPI_FLAGS", "true")
+ }
+
bpd := ret.BazelMetricsDir()
if err := os.RemoveAll(bpd); err != nil {
ctx.Fatalf("Unable to remove bazel profile directory %q: %v", bpd, err)
@@ -522,6 +557,21 @@
ctx.Metrics.SystemResourceInfo(s)
}
+func getNinjaWeightListSourceInMetric(s NinjaWeightListSource) *smpb.BuildConfig_NinjaWeightListSource {
+ switch s {
+ case NINJA_LOG:
+ return smpb.BuildConfig_NINJA_LOG.Enum()
+ case EVENLY_DISTRIBUTED:
+ return smpb.BuildConfig_EVENLY_DISTRIBUTED.Enum()
+ case EXTERNAL_FILE:
+ return smpb.BuildConfig_EXTERNAL_FILE.Enum()
+ case HINT_FROM_SOONG:
+ return smpb.BuildConfig_HINT_FROM_SOONG.Enum()
+ default:
+ return smpb.BuildConfig_NOT_USED.Enum()
+ }
+}
+
func buildConfig(config Config) *smpb.BuildConfig {
c := &smpb.BuildConfig{
ForceUseGoma: proto.Bool(config.ForceUseGoma()),
@@ -529,6 +579,7 @@
UseRbe: proto.Bool(config.UseRBE()),
BazelMixedBuild: proto.Bool(config.BazelBuildEnabled()),
ForceDisableBazelMixedBuild: proto.Bool(config.IsBazelMixedBuildForceDisabled()),
+ NinjaWeightListSource: getNinjaWeightListSourceInMetric(config.NinjaWeightListSource()),
}
c.Targets = append(c.Targets, config.arguments...)
@@ -763,9 +814,6 @@
// by a previous build.
c.skipConfig = true
c.skipKati = true
- } else if arg == "--skip-kati" {
- // TODO: remove --skip-kati once module builds have been migrated to --song-only
- c.skipKati = true
} else if arg == "--soong-only" {
c.skipKati = true
c.skipKatiNinja = true
@@ -781,6 +829,8 @@
c.skipMetricsUpload = true
} else if arg == "--mk-metrics" {
c.reportMkMetrics = true
+ } else if arg == "--multitree-build" {
+ c.multitreeBuild = true
} else if arg == "--bazel-mode" {
c.bazelProdMode = true
} else if arg == "--bazel-mode-dev" {
@@ -789,6 +839,32 @@
c.bazelStagingMode = true
} else if arg == "--search-api-dir" {
c.searchApiDir = true
+ } else if strings.HasPrefix(arg, "--ninja_weight_source=") {
+ source := strings.TrimPrefix(arg, "--ninja_weight_source=")
+ if source == "ninja_log" {
+ c.ninjaWeightListSource = NINJA_LOG
+ } else if source == "evenly_distributed" {
+ c.ninjaWeightListSource = EVENLY_DISTRIBUTED
+ } else if source == "not_used" {
+ c.ninjaWeightListSource = NOT_USED
+ } else if source == "soong" {
+ c.ninjaWeightListSource = HINT_FROM_SOONG
+ } else if strings.HasPrefix(source, "file,") {
+ c.ninjaWeightListSource = EXTERNAL_FILE
+ filePath := strings.TrimPrefix(source, "file,")
+ err := validateNinjaWeightList(filePath)
+ if err != nil {
+ ctx.Fatalf("Malformed weight list from %s: %s", filePath, err)
+ }
+ _, err = copyFile(filePath, filepath.Join(c.OutDir(), ".ninja_weight_list"))
+ if err != nil {
+ ctx.Fatalf("Error to copy ninja weight list from %s: %s", filePath, err)
+ }
+ } else {
+ ctx.Fatalf("unknown option for ninja_weight_source: %s", source)
+ }
+ } else if arg == "--build-from-text-stub" {
+ c.buildFromTextStub = true
} else if strings.HasPrefix(arg, "--build-command=") {
buildCmd := strings.TrimPrefix(arg, "--build-command=")
// remove quotations
@@ -805,6 +881,8 @@
} else {
ctx.Fatalf("Error parsing build-time-started-unix-millis", err)
}
+ } else if arg == "--ensure-allowlist-integrity" {
+ c.ensureAllowlistIntegrity = true
} else if len(arg) > 0 && arg[0] == '-' {
parseArgNum := func(def int) int {
if len(arg) > 2 {
@@ -859,6 +937,25 @@
}
}
+func validateNinjaWeightList(weightListFilePath string) (err error) {
+ data, err := os.ReadFile(weightListFilePath)
+ if err != nil {
+ return
+ }
+ lines := strings.Split(strings.TrimSpace(string(data)), "\n")
+ for _, line := range lines {
+ fields := strings.Split(line, ",")
+ if len(fields) != 2 {
+ return fmt.Errorf("wrong format, each line should have two fields, but '%s'", line)
+ }
+ _, err = strconv.Atoi(fields[1])
+ if err != nil {
+ return
+ }
+ }
+ return
+}
+
func (c *configImpl) configureLocale(ctx Context) {
cmd := Command(ctx, Config{c}, "locale", "locale", "-a")
output, err := cmd.Output()
@@ -1079,6 +1176,14 @@
return c.verbose
}
+func (c *configImpl) MultitreeBuild() bool {
+ return c.multitreeBuild
+}
+
+func (c *configImpl) NinjaWeightListSource() NinjaWeightListSource {
+ return c.ninjaWeightListSource
+}
+
func (c *configImpl) SkipKati() bool {
return c.skipKati
}
@@ -1103,6 +1208,10 @@
return c.skipConfig
}
+func (c *configImpl) BuildFromTextStub() bool {
+ return c.buildFromTextStub
+}
+
func (c *configImpl) TargetProduct() string {
if v, ok := c.environ.Get("TARGET_PRODUCT"); ok {
return v
@@ -1133,6 +1242,14 @@
return c.parallel
}
+func (c *configImpl) GetSourceRootDirs() []string {
+ return c.sourceRootDirs
+}
+
+func (c *configImpl) SetSourceRootDirs(i []string) {
+ c.sourceRootDirs = i
+}
+
func (c *configImpl) GetIncludeTags() []string {
return c.includeTags
}
@@ -1257,6 +1374,15 @@
return filepath.Join(buildTmpDir, "rbe")
}
+func (c *configImpl) rbeCacheDir() string {
+ for _, f := range []string{"RBE_cache_dir", "FLAG_cache_dir"} {
+ if v, ok := c.environ.Get(f); ok {
+ return v
+ }
+ }
+ return shared.JoinPath(c.SoongOutDir(), "rbe")
+}
+
func (c *configImpl) shouldCleanupRBELogsDir() bool {
// Perform a log directory cleanup only when the log directory
// is auto created by the build rather than user-specified.
@@ -1347,9 +1473,13 @@
// GoogleProdCredsExist determine whether credentials exist on the
// Googler machine to use remote execution.
func (c *configImpl) GoogleProdCredsExist() bool {
+ if googleProdCredsExistCache {
+ return googleProdCredsExistCache
+ }
if _, err := exec.Command("/usr/bin/prodcertstatus", "--simple_output", "--nocheck_loas").Output(); err != nil {
return false
}
+ googleProdCredsExistCache = true
return true
}
@@ -1580,6 +1710,10 @@
return c.skipMetricsUpload
}
+func (c *configImpl) EnsureAllowlistIntegrity() bool {
+ return c.ensureAllowlistIntegrity
+}
+
// Returns a Time object if one was passed via a command-line flag.
// Otherwise returns the passed default.
func (c *configImpl) BuildStartedTimeOrDefault(defaultTime time.Time) time.Time {
diff --git a/ui/build/config_test.go b/ui/build/config_test.go
index 940d85c..a1eccf0 100644
--- a/ui/build/config_test.go
+++ b/ui/build/config_test.go
@@ -903,6 +903,15 @@
tidyOnly: "",
expectedArgs: []string{},
}, {
+ description: "multitree build action executed at root directory",
+ dirsInTrees: []string{},
+ buildFiles: []string{},
+ rootSymlink: false,
+ args: []string{"--multitree-build"},
+ curDir: ".",
+ tidyOnly: "",
+ expectedArgs: []string{"--multitree-build"},
+ }, {
description: "build action executed at root directory in symlink",
dirsInTrees: []string{},
buildFiles: []string{},
@@ -1023,6 +1032,7 @@
UseRbe: proto.Bool(false),
BazelMixedBuild: proto.Bool(false),
ForceDisableBazelMixedBuild: proto.Bool(false),
+ NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
{
@@ -1034,6 +1044,7 @@
UseRbe: proto.Bool(false),
BazelMixedBuild: proto.Bool(false),
ForceDisableBazelMixedBuild: proto.Bool(false),
+ NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
{
@@ -1045,6 +1056,7 @@
UseRbe: proto.Bool(false),
BazelMixedBuild: proto.Bool(false),
ForceDisableBazelMixedBuild: proto.Bool(false),
+ NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
{
@@ -1056,6 +1068,7 @@
UseRbe: proto.Bool(true),
BazelMixedBuild: proto.Bool(false),
ForceDisableBazelMixedBuild: proto.Bool(false),
+ NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
{
@@ -1067,6 +1080,7 @@
UseRbe: proto.Bool(false),
BazelMixedBuild: proto.Bool(false),
ForceDisableBazelMixedBuild: proto.Bool(true),
+ NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
{
@@ -1079,6 +1093,7 @@
UseRbe: proto.Bool(false),
BazelMixedBuild: proto.Bool(false),
ForceDisableBazelMixedBuild: proto.Bool(false),
+ NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
{
@@ -1091,6 +1106,7 @@
UseRbe: proto.Bool(false),
BazelMixedBuild: proto.Bool(true),
ForceDisableBazelMixedBuild: proto.Bool(false),
+ NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
{
@@ -1103,6 +1119,7 @@
UseRbe: proto.Bool(false),
BazelMixedBuild: proto.Bool(true),
ForceDisableBazelMixedBuild: proto.Bool(false),
+ NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
{
@@ -1115,6 +1132,7 @@
UseRbe: proto.Bool(false),
BazelMixedBuild: proto.Bool(true),
ForceDisableBazelMixedBuild: proto.Bool(false),
+ NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
{
@@ -1129,6 +1147,7 @@
BazelMixedBuild: proto.Bool(false),
Targets: []string{"droid", "dist"},
ForceDisableBazelMixedBuild: proto.Bool(false),
+ NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
{
@@ -1147,6 +1166,7 @@
UseRbe: proto.Bool(true),
BazelMixedBuild: proto.Bool(true),
ForceDisableBazelMixedBuild: proto.Bool(true),
+ NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
}
diff --git a/ui/build/context.go b/ui/build/context.go
index 2fef0d0..fd20e26 100644
--- a/ui/build/context.go
+++ b/ui/build/context.go
@@ -40,6 +40,8 @@
Thread tracer.Thread
Tracer tracer.Tracer
+
+ CriticalPath *status.CriticalPath
}
// BeginTrace starts a new Duration Event.
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index a9c298f..efe7478 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -148,6 +148,7 @@
"PLATFORM_VERSION_CODENAME",
"PLATFORM_VERSION",
"PRODUCT_INCLUDE_TAGS",
+ "PRODUCT_SOURCE_ROOT_DIRS",
"TARGET_PRODUCT",
"TARGET_BUILD_VARIANT",
"TARGET_BUILD_APPS",
@@ -299,4 +300,5 @@
config.SetBuildBrokenUsesNetwork(makeVars["BUILD_BROKEN_USES_NETWORK"] == "true")
config.SetBuildBrokenNinjaUsesEnvVars(strings.Fields(makeVars["BUILD_BROKEN_NINJA_USES_ENV_VARS"]))
config.SetIncludeTags(strings.Fields(makeVars["PRODUCT_INCLUDE_TAGS"]))
+ config.SetSourceRootDirs(strings.Fields(makeVars["PRODUCT_SOURCE_ROOT_DIRS"]))
}
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index 28f3c38..5d56531 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -30,9 +30,53 @@
const (
// File containing the environment state when ninja is executed
- ninjaEnvFileName = "ninja.environment"
+ ninjaEnvFileName = "ninja.environment"
+ ninjaLogFileName = ".ninja_log"
+ ninjaWeightListFileName = ".ninja_weight_list"
)
+func useNinjaBuildLog(ctx Context, config Config, cmd *Cmd) {
+ ninjaLogFile := filepath.Join(config.OutDir(), ninjaLogFileName)
+ data, err := os.ReadFile(ninjaLogFile)
+ var outputBuilder strings.Builder
+ if err == nil {
+ lines := strings.Split(strings.TrimSpace(string(data)), "\n")
+ // ninja log: <start> <end> <restat> <name> <cmdhash>
+ // ninja weight list: <name>,<end-start+1>
+ for _, line := range lines {
+ if strings.HasPrefix(line, "#") {
+ continue
+ }
+ fields := strings.Split(line, "\t")
+ path := fields[3]
+ start, err := strconv.Atoi(fields[0])
+ if err != nil {
+ continue
+ }
+ end, err := strconv.Atoi(fields[1])
+ if err != nil {
+ continue
+ }
+ outputBuilder.WriteString(path)
+ outputBuilder.WriteString(",")
+ outputBuilder.WriteString(strconv.Itoa(end-start+1) + "\n")
+ }
+ } else {
+ // If there is no ninja log file, just pass empty ninja weight list.
+ // Because it is still efficient with critical path calculation logic even without weight.
+ ctx.Verbosef("There is an error during reading ninja log, so ninja will use empty weight list: %s", err)
+ }
+
+ weightListFile := filepath.Join(config.OutDir(), ninjaWeightListFileName)
+
+ err = os.WriteFile(weightListFile, []byte(outputBuilder.String()), 0644)
+ if err == nil {
+ cmd.Args = append(cmd.Args, "-o", "usesweightlist="+weightListFile)
+ } else {
+ ctx.Panicf("Could not write ninja weight list file %s", err)
+ }
+}
+
// Constructs and runs the Ninja command line with a restricted set of
// environment variables. It's important to restrict the environment Ninja runs
// for hermeticity reasons, and to avoid spurious rebuilds.
@@ -85,6 +129,20 @@
cmd.Environment.AppendFromKati(config.KatiEnvFile())
}
+ switch config.NinjaWeightListSource() {
+ case NINJA_LOG:
+ useNinjaBuildLog(ctx, config, cmd)
+ case EVENLY_DISTRIBUTED:
+ // pass empty weight list means ninja considers every tasks's weight as 1(default value).
+ cmd.Args = append(cmd.Args, "-o", "usesweightlist=/dev/null")
+ case EXTERNAL_FILE:
+ fallthrough
+ case HINT_FROM_SOONG:
+ // The weight list is already copied/generated.
+ ninjaWeightListPath := filepath.Join(config.OutDir(), ninjaWeightListFileName)
+ cmd.Args = append(cmd.Args, "-o", "usesweightlist="+ninjaWeightListPath)
+ }
+
// Allow both NINJA_ARGS and NINJA_EXTRA_ARGS, since both have been
// used in the past to specify extra ninja arguments.
if extra, ok := cmd.Environment.Get("NINJA_ARGS"); ok {
@@ -215,7 +273,7 @@
ticker := time.NewTicker(ninjaHeartbeatDuration)
defer ticker.Stop()
ninjaChecker := &ninjaStucknessChecker{
- logPath: filepath.Join(config.OutDir(), ".ninja_log"),
+ logPath: filepath.Join(config.OutDir(), ninjaLogFileName),
}
go func() {
for {
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index 1d17216..6479925 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -60,6 +60,7 @@
"RBE_exec_root": config.rbeExecRoot(),
"RBE_output_dir": config.rbeProxyLogsDir(),
"RBE_proxy_log_dir": config.rbeProxyLogsDir(),
+ "RBE_cache_dir": config.rbeCacheDir(),
"RBE_platform": "container-image=" + remoteexec.DefaultImage,
}
if config.StartRBE() {
diff --git a/ui/build/soong.go b/ui/build/soong.go
index a5a3263..563199b 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -168,6 +168,13 @@
commonArgs = append(commonArgs, "-t")
}
+ if pb.config.multitreeBuild {
+ commonArgs = append(commonArgs, "--multitree-build")
+ }
+ if pb.config.buildFromTextStub {
+ commonArgs = append(commonArgs, "--build-from-text-stub")
+ }
+
commonArgs = append(commonArgs, "-l", filepath.Join(pb.config.FileListDir(), "Android.bp.list"))
invocationEnv := make(map[string]string)
if pb.debugPort != "" {
@@ -275,6 +282,15 @@
if len(config.bazelForceEnabledModules) > 0 {
mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--bazel-force-enabled-modules="+config.bazelForceEnabledModules)
}
+ if config.MultitreeBuild() {
+ mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--multitree-build")
+ }
+ if config.buildFromTextStub {
+ mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--build-from-text-stub")
+ }
+ if config.ensureAllowlistIntegrity {
+ mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--ensure-allowlist-integrity")
+ }
queryviewDir := filepath.Join(config.SoongOutDir(), "queryview")
// The BUILD files will be generated in out/soong/.api_bp2build (no symlinks to src files)
@@ -403,6 +419,7 @@
blueprintCtx := blueprint.NewContext()
blueprintCtx.AddIncludeTags(config.GetIncludeTags()...)
+ blueprintCtx.AddSourceRootDirs(config.GetSourceRootDirs()...)
blueprintCtx.SetIgnoreUnknownModuleTypes(true)
blueprintConfig := BlueprintConfig{
soongOutDir: config.SoongOutDir(),
diff --git a/ui/metrics/BUILD.bazel b/ui/metrics/BUILD.bazel
new file mode 100644
index 0000000..15ebb88
--- /dev/null
+++ b/ui/metrics/BUILD.bazel
@@ -0,0 +1,30 @@
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load("//build/bazel/rules/python:py_proto.bzl", "py_proto_library")
+
+py_proto_library(
+ name = "metrics-py-proto",
+ visibility = ["//build/bazel/scripts/incremental_build:__pkg__"],
+ deps = [":metrics-proto"],
+)
+
+proto_library(
+ name = "metrics-proto",
+ srcs = [
+ "bp2build_metrics_proto/bp2build_metrics.proto",
+ "metrics_proto/metrics.proto",
+ ],
+ strip_import_prefix = "",
+)
diff --git a/ui/metrics/bazel_metrics_proto/bazel_metrics.pb.go b/ui/metrics/bazel_metrics_proto/bazel_metrics.pb.go
index f8b8fd6..bf5e80b 100644
--- a/ui/metrics/bazel_metrics_proto/bazel_metrics.pb.go
+++ b/ui/metrics/bazel_metrics_proto/bazel_metrics.pb.go
@@ -14,8 +14,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.28.0
-// protoc v3.21.7
+// protoc-gen-go v1.30.0
+// protoc v3.21.12
// source: bazel_metrics.proto
package bazel_metrics_proto
@@ -41,6 +41,7 @@
PhaseTimings []*PhaseTiming `protobuf:"bytes,1,rep,name=phase_timings,json=phaseTimings,proto3" json:"phase_timings,omitempty"`
Total *int64 `protobuf:"varint,2,opt,name=total,proto3,oneof" json:"total,omitempty"`
+ ExitCode *int32 `protobuf:"varint,3,opt,name=exit_code,json=exitCode,proto3,oneof" json:"exit_code,omitempty"`
}
func (x *BazelMetrics) Reset() {
@@ -89,6 +90,13 @@
return 0
}
+func (x *BazelMetrics) GetExitCode() int32 {
+ if x != nil && x.ExitCode != nil {
+ return *x.ExitCode
+ }
+ return 0
+}
+
type PhaseTiming struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -161,15 +169,18 @@
0x0a, 0x13, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69,
0x6c, 0x64, 0x5f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
- 0x22, 0x80, 0x01, 0x0a, 0x0c, 0x42, 0x61, 0x7a, 0x65, 0x6c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x22, 0xb0, 0x01, 0x0a, 0x0c, 0x42, 0x61, 0x7a, 0x65, 0x6c, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
0x73, 0x12, 0x4b, 0x0a, 0x0d, 0x70, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x69, 0x6e,
0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67,
0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x65, 0x74,
0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x68, 0x61, 0x73, 0x65, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67,
0x52, 0x0c, 0x70, 0x68, 0x61, 0x73, 0x65, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x19,
0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52,
- 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x74, 0x6f,
- 0x74, 0x61, 0x6c, 0x22, 0xd1, 0x01, 0x0a, 0x0b, 0x50, 0x68, 0x61, 0x73, 0x65, 0x54, 0x69, 0x6d,
+ 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x65, 0x78, 0x69,
+ 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x48, 0x01, 0x52, 0x08,
+ 0x65, 0x78, 0x69, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f,
+ 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x63,
+ 0x6f, 0x64, 0x65, 0x22, 0xd1, 0x01, 0x0a, 0x0b, 0x50, 0x68, 0x61, 0x73, 0x65, 0x54, 0x69, 0x6d,
0x69, 0x6e, 0x67, 0x12, 0x22, 0x0a, 0x0a, 0x70, 0x68, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d,
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x70, 0x68, 0x61, 0x73, 0x65,
0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x2a, 0x0a, 0x0e, 0x64, 0x75, 0x72, 0x61, 0x74,
diff --git a/ui/metrics/bazel_metrics_proto/bazel_metrics.proto b/ui/metrics/bazel_metrics_proto/bazel_metrics.proto
index 57eed4c..9073080 100644
--- a/ui/metrics/bazel_metrics_proto/bazel_metrics.proto
+++ b/ui/metrics/bazel_metrics_proto/bazel_metrics.proto
@@ -20,6 +20,7 @@
message BazelMetrics {
repeated PhaseTiming phase_timings = 1;
optional int64 total = 2;
+ optional int32 exit_code = 3;
}
message PhaseTiming {
diff --git a/ui/metrics/event.go b/ui/metrics/event.go
index b3a027e..cbdeb27 100644
--- a/ui/metrics/event.go
+++ b/ui/metrics/event.go
@@ -135,8 +135,8 @@
e := t.peek()
e.procResInfo = append(e.procResInfo, &soong_metrics_proto.ProcessResourceInfo{
Name: proto.String(name),
- UserTimeMicros: proto.Uint64(uint64(rusage.Utime.Usec)),
- SystemTimeMicros: proto.Uint64(uint64(rusage.Stime.Usec)),
+ UserTimeMicros: proto.Uint64(uint64(state.UserTime().Microseconds())),
+ SystemTimeMicros: proto.Uint64(uint64(state.SystemTime().Microseconds())),
MinorPageFaults: proto.Uint64(uint64(rusage.Minflt)),
MajorPageFaults: proto.Uint64(uint64(rusage.Majflt)),
// ru_inblock and ru_oublock are measured in blocks of 512 bytes.
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index 717530c..82d11ed 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -39,6 +39,7 @@
"time"
"android/soong/shared"
+
"google.golang.org/protobuf/proto"
soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
@@ -125,6 +126,10 @@
}
}
+func (m *Metrics) SetCriticalPathInfo(criticalPathInfo soong_metrics_proto.CriticalPathInfo) {
+ m.metrics.CriticalPathInfo = &criticalPathInfo
+}
+
// SetFatalOrPanicMessage stores a non-zero exit and the relevant message in the latest event if
// available or the metrics base.
func (m *Metrics) SetFatalOrPanicMessage(errMsg string) {
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index faa9b0a..32d4dc0 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -14,7 +14,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.28.0
+// protoc-gen-go v1.30.0
// protoc v3.21.7
// source: metrics.proto
@@ -158,6 +158,71 @@
return file_metrics_proto_rawDescGZIP(), []int{0, 1}
}
+type BuildConfig_NinjaWeightListSource int32
+
+const (
+ BuildConfig_NOT_USED BuildConfig_NinjaWeightListSource = 0
+ BuildConfig_NINJA_LOG BuildConfig_NinjaWeightListSource = 1
+ BuildConfig_EVENLY_DISTRIBUTED BuildConfig_NinjaWeightListSource = 2
+ BuildConfig_EXTERNAL_FILE BuildConfig_NinjaWeightListSource = 3
+ BuildConfig_HINT_FROM_SOONG BuildConfig_NinjaWeightListSource = 4
+)
+
+// Enum value maps for BuildConfig_NinjaWeightListSource.
+var (
+ BuildConfig_NinjaWeightListSource_name = map[int32]string{
+ 0: "NOT_USED",
+ 1: "NINJA_LOG",
+ 2: "EVENLY_DISTRIBUTED",
+ 3: "EXTERNAL_FILE",
+ 4: "HINT_FROM_SOONG",
+ }
+ BuildConfig_NinjaWeightListSource_value = map[string]int32{
+ "NOT_USED": 0,
+ "NINJA_LOG": 1,
+ "EVENLY_DISTRIBUTED": 2,
+ "EXTERNAL_FILE": 3,
+ "HINT_FROM_SOONG": 4,
+ }
+)
+
+func (x BuildConfig_NinjaWeightListSource) Enum() *BuildConfig_NinjaWeightListSource {
+ p := new(BuildConfig_NinjaWeightListSource)
+ *p = x
+ return p
+}
+
+func (x BuildConfig_NinjaWeightListSource) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (BuildConfig_NinjaWeightListSource) Descriptor() protoreflect.EnumDescriptor {
+ return file_metrics_proto_enumTypes[2].Descriptor()
+}
+
+func (BuildConfig_NinjaWeightListSource) Type() protoreflect.EnumType {
+ return &file_metrics_proto_enumTypes[2]
+}
+
+func (x BuildConfig_NinjaWeightListSource) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *BuildConfig_NinjaWeightListSource) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = BuildConfig_NinjaWeightListSource(num)
+ return nil
+}
+
+// Deprecated: Use BuildConfig_NinjaWeightListSource.Descriptor instead.
+func (BuildConfig_NinjaWeightListSource) EnumDescriptor() ([]byte, []int) {
+ return file_metrics_proto_rawDescGZIP(), []int{1, 0}
+}
+
type ModuleTypeInfo_BuildSystem int32
const (
@@ -191,11 +256,11 @@
}
func (ModuleTypeInfo_BuildSystem) Descriptor() protoreflect.EnumDescriptor {
- return file_metrics_proto_enumTypes[2].Descriptor()
+ return file_metrics_proto_enumTypes[3].Descriptor()
}
func (ModuleTypeInfo_BuildSystem) Type() protoreflect.EnumType {
- return &file_metrics_proto_enumTypes[2]
+ return &file_metrics_proto_enumTypes[3]
}
func (x ModuleTypeInfo_BuildSystem) Number() protoreflect.EnumNumber {
@@ -253,11 +318,11 @@
}
func (ExpConfigFetcher_ConfigStatus) Descriptor() protoreflect.EnumDescriptor {
- return file_metrics_proto_enumTypes[3].Descriptor()
+ return file_metrics_proto_enumTypes[4].Descriptor()
}
func (ExpConfigFetcher_ConfigStatus) Type() protoreflect.EnumType {
- return &file_metrics_proto_enumTypes[3]
+ return &file_metrics_proto_enumTypes[4]
}
func (x ExpConfigFetcher_ConfigStatus) Number() protoreflect.EnumNumber {
@@ -329,7 +394,7 @@
// Deprecated because instead of embedding in a MetricsBase, we keep
// SoongBuildMetrics in its own file
//
- // Deprecated: Do not use.
+ // Deprecated: Marked as deprecated in metrics.proto.
SoongBuildMetrics *SoongBuildMetrics `protobuf:"bytes,22,opt,name=soong_build_metrics,json=soongBuildMetrics" json:"soong_build_metrics,omitempty"`
BuildConfig *BuildConfig `protobuf:"bytes,23,opt,name=build_config,json=buildConfig" json:"build_config,omitempty"`
// The hostname of the machine.
@@ -353,6 +418,8 @@
// The branch on which the build occurred.
// Example: refs/heads/master
Branch *string `protobuf:"bytes,32,opt,name=branch" json:"branch,omitempty"`
+ // The metric of critical path in build
+ CriticalPathInfo *CriticalPathInfo `protobuf:"bytes,33,opt,name=critical_path_info,json=criticalPathInfo" json:"critical_path_info,omitempty"`
}
// Default values for MetricsBase fields.
@@ -542,7 +609,7 @@
return nil
}
-// Deprecated: Do not use.
+// Deprecated: Marked as deprecated in metrics.proto.
func (x *MetricsBase) GetSoongBuildMetrics() *SoongBuildMetrics {
if x != nil {
return x.SoongBuildMetrics
@@ -620,6 +687,13 @@
return ""
}
+func (x *MetricsBase) GetCriticalPathInfo() *CriticalPathInfo {
+ if x != nil {
+ return x.CriticalPathInfo
+ }
+ return nil
+}
+
type BuildConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -638,8 +712,19 @@
Targets []string `protobuf:"bytes,6,rep,name=targets" json:"targets,omitempty"`
// Whether the user explicitly disabled bazel mixed builds for this build.
ForceDisableBazelMixedBuild *bool `protobuf:"varint,7,opt,name=force_disable_bazel_mixed_build,json=forceDisableBazelMixedBuild" json:"force_disable_bazel_mixed_build,omitempty"`
+ // NOT_USED - ninja doesn't use weight list.
+ // NINJA_LOG - ninja uses weight list based on previous builds by ninja log
+ // EVENLY_DISTRIBUTED - ninja thinks every task has the same weight.
+ // EXTERNAL_FILE - ninja uses an external custom weight list
+ // HINT_FROM_SOONG - ninja uses a prioritized module list from Soong
+ NinjaWeightListSource *BuildConfig_NinjaWeightListSource `protobuf:"varint,8,opt,name=ninja_weight_list_source,json=ninjaWeightListSource,enum=soong_build_metrics.BuildConfig_NinjaWeightListSource,def=0" json:"ninja_weight_list_source,omitempty"`
}
+// Default values for BuildConfig fields.
+const (
+ Default_BuildConfig_NinjaWeightListSource = BuildConfig_NOT_USED
+)
+
func (x *BuildConfig) Reset() {
*x = BuildConfig{}
if protoimpl.UnsafeEnabled {
@@ -721,6 +806,13 @@
return false
}
+func (x *BuildConfig) GetNinjaWeightListSource() BuildConfig_NinjaWeightListSource {
+ if x != nil && x.NinjaWeightListSource != nil {
+ return *x.NinjaWeightListSource
+ }
+ return Default_BuildConfig_NinjaWeightListSource
+}
+
type SystemResourceInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -795,7 +887,7 @@
RealTime *uint64 `protobuf:"varint,4,opt,name=real_time,json=realTime" json:"real_time,omitempty"`
// The number of MB for memory use (deprecated as it is too generic).
//
- // Deprecated: Do not use.
+ // Deprecated: Marked as deprecated in metrics.proto.
MemoryUse *uint64 `protobuf:"varint,5,opt,name=memory_use,json=memoryUse" json:"memory_use,omitempty"`
// The resource information of each executed process.
ProcessesResourceInfo []*ProcessResourceInfo `protobuf:"bytes,6,rep,name=processes_resource_info,json=processesResourceInfo" json:"processes_resource_info,omitempty"`
@@ -866,7 +958,7 @@
return 0
}
-// Deprecated: Do not use.
+// Deprecated: Marked as deprecated in metrics.proto.
func (x *PerfInfo) GetMemoryUse() uint64 {
if x != nil && x.MemoryUse != nil {
return *x.MemoryUse
@@ -1428,12 +1520,146 @@
return nil
}
+// CriticalPathInfo contains critical path nodes's information.
+// A critical path is a path determining the minimum time needed for the whole build given perfect parallelism.
+type CriticalPathInfo struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Real time which the build system spent in microseconds
+ ElapsedTimeMicros *uint64 `protobuf:"varint,1,opt,name=elapsed_time_micros,json=elapsedTimeMicros" json:"elapsed_time_micros,omitempty"`
+ // The sum of execution time of the longest path from leave to the root in microseconds
+ CriticalPathTimeMicros *uint64 `protobuf:"varint,2,opt,name=critical_path_time_micros,json=criticalPathTimeMicros" json:"critical_path_time_micros,omitempty"`
+ // Detailed job information in a critical path.
+ CriticalPath []*JobInfo `protobuf:"bytes,4,rep,name=critical_path,json=criticalPath" json:"critical_path,omitempty"`
+ // Detailed job information for long running jobs (>30 seconds). These may or may not also be on a critical path.
+ LongRunningJobs []*JobInfo `protobuf:"bytes,5,rep,name=long_running_jobs,json=longRunningJobs" json:"long_running_jobs,omitempty"`
+}
+
+func (x *CriticalPathInfo) Reset() {
+ *x = CriticalPathInfo{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_metrics_proto_msgTypes[11]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CriticalPathInfo) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CriticalPathInfo) ProtoMessage() {}
+
+func (x *CriticalPathInfo) ProtoReflect() protoreflect.Message {
+ mi := &file_metrics_proto_msgTypes[11]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CriticalPathInfo.ProtoReflect.Descriptor instead.
+func (*CriticalPathInfo) Descriptor() ([]byte, []int) {
+ return file_metrics_proto_rawDescGZIP(), []int{11}
+}
+
+func (x *CriticalPathInfo) GetElapsedTimeMicros() uint64 {
+ if x != nil && x.ElapsedTimeMicros != nil {
+ return *x.ElapsedTimeMicros
+ }
+ return 0
+}
+
+func (x *CriticalPathInfo) GetCriticalPathTimeMicros() uint64 {
+ if x != nil && x.CriticalPathTimeMicros != nil {
+ return *x.CriticalPathTimeMicros
+ }
+ return 0
+}
+
+func (x *CriticalPathInfo) GetCriticalPath() []*JobInfo {
+ if x != nil {
+ return x.CriticalPath
+ }
+ return nil
+}
+
+func (x *CriticalPathInfo) GetLongRunningJobs() []*JobInfo {
+ if x != nil {
+ return x.LongRunningJobs
+ }
+ return nil
+}
+
+type JobInfo struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Real time which a job spent in microseconds
+ ElapsedTimeMicros *uint64 `protobuf:"varint,1,opt,name=elapsed_time_micros,json=elapsedTimeMicros" json:"elapsed_time_micros,omitempty"`
+ // Description of a job
+ JobDescription *string `protobuf:"bytes,2,opt,name=job_description,json=jobDescription" json:"job_description,omitempty"`
+}
+
+func (x *JobInfo) Reset() {
+ *x = JobInfo{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_metrics_proto_msgTypes[12]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *JobInfo) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*JobInfo) ProtoMessage() {}
+
+func (x *JobInfo) ProtoReflect() protoreflect.Message {
+ mi := &file_metrics_proto_msgTypes[12]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use JobInfo.ProtoReflect.Descriptor instead.
+func (*JobInfo) Descriptor() ([]byte, []int) {
+ return file_metrics_proto_rawDescGZIP(), []int{12}
+}
+
+func (x *JobInfo) GetElapsedTimeMicros() uint64 {
+ if x != nil && x.ElapsedTimeMicros != nil {
+ return *x.ElapsedTimeMicros
+ }
+ return 0
+}
+
+func (x *JobInfo) GetJobDescription() string {
+ if x != nil && x.JobDescription != nil {
+ return *x.JobDescription
+ }
+ return ""
+}
+
var File_metrics_proto protoreflect.FileDescriptor
var file_metrics_proto_rawDesc = []byte{
0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x13, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x22, 0xb5, 0x0e, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x72, 0x69, 0x63, 0x73, 0x22, 0x8a, 0x0f, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
0x42, 0x61, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x61,
0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01,
0x28, 0x03, 0x52, 0x12, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d,
@@ -1541,162 +1767,205 @@
0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x5f, 0x75, 0x72,
0x6c, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73,
0x74, 0x55, 0x72, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x20,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0x30, 0x0a, 0x0c,
- 0x42, 0x75, 0x69, 0x6c, 0x64, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x12, 0x08, 0x0a, 0x04,
- 0x55, 0x53, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x53, 0x45, 0x52, 0x44, 0x45,
- 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x4e, 0x47, 0x10, 0x02, 0x22, 0x3c,
- 0x0a, 0x04, 0x41, 0x72, 0x63, 0x68, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57,
- 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x52, 0x4d, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05,
- 0x41, 0x52, 0x4d, 0x36, 0x34, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x58, 0x38, 0x36, 0x10, 0x03,
- 0x12, 0x0a, 0x0a, 0x06, 0x58, 0x38, 0x36, 0x5f, 0x36, 0x34, 0x10, 0x04, 0x22, 0x99, 0x02, 0x0a,
- 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x19, 0x0a, 0x08,
- 0x75, 0x73, 0x65, 0x5f, 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
- 0x75, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x5f, 0x72,
- 0x62, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x75, 0x73, 0x65, 0x52, 0x62, 0x65,
- 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x67, 0x6f,
- 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x55,
- 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f,
- 0x61, 0x73, 0x5f, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c,
- 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x41, 0x73, 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x12, 0x2a, 0x0a, 0x11,
- 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c,
- 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x4d, 0x69,
- 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67,
- 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65,
- 0x74, 0x73, 0x12, 0x44, 0x0a, 0x1f, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x61,
- 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f,
- 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x66, 0x6f, 0x72,
- 0x63, 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x61, 0x7a, 0x65, 0x6c, 0x4d, 0x69,
- 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x22, 0x6f, 0x0a, 0x12, 0x53, 0x79, 0x73, 0x74,
- 0x65, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x32,
- 0x0a, 0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c,
- 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x74,
- 0x6f, 0x74, 0x61, 0x6c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x4d, 0x65, 0x6d, 0x6f,
- 0x72, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f,
- 0x63, 0x70, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x76, 0x61, 0x69,
- 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x70, 0x75, 0x73, 0x22, 0xca, 0x02, 0x0a, 0x08, 0x50, 0x65,
- 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73,
- 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a,
- 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04,
- 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72,
- 0x65, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08,
- 0x72, 0x65, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x6f,
- 0x72, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18, 0x01,
- 0x52, 0x09, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x17, 0x70,
- 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63,
- 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73,
- 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65,
- 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x0a,
- 0x0d, 0x6e, 0x6f, 0x6e, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18, 0x07,
- 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x6e, 0x5a, 0x65, 0x72, 0x6f, 0x45, 0x78, 0x69,
- 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61,
- 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d,
- 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xb9, 0x03, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x63, 0x65,
- 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x12, 0x53, 0x0a, 0x12,
+ 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x69, 0x6e,
+ 0x66, 0x6f, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67,
+ 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x43,
+ 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x52,
+ 0x10, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x66,
+ 0x6f, 0x22, 0x30, 0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e,
+ 0x74, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x55,
+ 0x53, 0x45, 0x52, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x4e,
+ 0x47, 0x10, 0x02, 0x22, 0x3c, 0x0a, 0x04, 0x41, 0x72, 0x63, 0x68, 0x12, 0x0b, 0x0a, 0x07, 0x55,
+ 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x52, 0x4d, 0x10,
+ 0x01, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x52, 0x4d, 0x36, 0x34, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03,
+ 0x58, 0x38, 0x36, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x58, 0x38, 0x36, 0x5f, 0x36, 0x34, 0x10,
+ 0x04, 0x22, 0x8a, 0x04, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+ 0x67, 0x12, 0x19, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x5f, 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x07, 0x75, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x17, 0x0a, 0x07,
+ 0x75, 0x73, 0x65, 0x5f, 0x72, 0x62, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x75,
+ 0x73, 0x65, 0x52, 0x62, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x75,
+ 0x73, 0x65, 0x5f, 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66,
+ 0x6f, 0x72, 0x63, 0x65, 0x55, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x62,
+ 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x61, 0x73, 0x5f, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x18, 0x04, 0x20,
+ 0x01, 0x28, 0x08, 0x52, 0x0c, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x41, 0x73, 0x4e, 0x69, 0x6e, 0x6a,
+ 0x61, 0x12, 0x2a, 0x0a, 0x11, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x64,
+ 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x62, 0x61,
+ 0x7a, 0x65, 0x6c, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x18, 0x0a,
+ 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07,
+ 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x12, 0x44, 0x0a, 0x1f, 0x66, 0x6f, 0x72, 0x63, 0x65,
+ 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d,
+ 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08,
+ 0x52, 0x1b, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x61,
+ 0x7a, 0x65, 0x6c, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x79, 0x0a,
+ 0x18, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x5f, 0x6c, 0x69,
+ 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32,
+ 0x36, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+ 0x67, 0x2e, 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69, 0x73,
+ 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x3a, 0x08, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45,
+ 0x44, 0x52, 0x15, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69,
+ 0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x74, 0x0a, 0x15, 0x4e, 0x69, 0x6e, 0x6a,
+ 0x61, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63,
+ 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x4e, 0x4f, 0x54, 0x5f, 0x55, 0x53, 0x45, 0x44, 0x10, 0x00, 0x12,
+ 0x0d, 0x0a, 0x09, 0x4e, 0x49, 0x4e, 0x4a, 0x41, 0x5f, 0x4c, 0x4f, 0x47, 0x10, 0x01, 0x12, 0x16,
+ 0x0a, 0x12, 0x45, 0x56, 0x45, 0x4e, 0x4c, 0x59, 0x5f, 0x44, 0x49, 0x53, 0x54, 0x52, 0x49, 0x42,
+ 0x55, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x45, 0x58, 0x54, 0x45, 0x52, 0x4e,
+ 0x41, 0x4c, 0x5f, 0x46, 0x49, 0x4c, 0x45, 0x10, 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x48, 0x49, 0x4e,
+ 0x54, 0x5f, 0x46, 0x52, 0x4f, 0x4d, 0x5f, 0x53, 0x4f, 0x4f, 0x4e, 0x47, 0x10, 0x04, 0x22, 0x6f,
+ 0x0a, 0x12, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+ 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x32, 0x0a, 0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x68,
+ 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x04, 0x52, 0x13, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63,
+ 0x61, 0x6c, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x76, 0x61, 0x69,
+ 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x70, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
+ 0x52, 0x0d, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x70, 0x75, 0x73, 0x22,
+ 0xca, 0x02, 0x0a, 0x08, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b,
+ 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12,
+ 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
+ 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d,
+ 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04,
+ 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x72, 0x65, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21,
+ 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01,
+ 0x28, 0x04, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73,
+ 0x65, 0x12, 0x60, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x72,
+ 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64,
+ 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+ 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x15, 0x70, 0x72,
+ 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49,
+ 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x6f, 0x6e, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x5f,
+ 0x65, 0x78, 0x69, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x6e, 0x5a,
+ 0x65, 0x72, 0x6f, 0x45, 0x78, 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72,
+ 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
+ 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xb9, 0x03, 0x0a,
+ 0x13, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+ 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x73, 0x65, 0x72,
+ 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01,
+ 0x28, 0x04, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72,
+ 0x6f, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69, 0x6d,
+ 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10,
+ 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73,
+ 0x12, 0x1c, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b, 0x62, 0x18, 0x04,
+ 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b, 0x62, 0x12, 0x2a,
+ 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75,
+ 0x6c, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x6f, 0x72,
+ 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x61,
+ 0x6a, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18,
+ 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65,
+ 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f, 0x69, 0x6e, 0x70,
+ 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6f, 0x49,
+ 0x6e, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f, 0x6f, 0x75, 0x74,
+ 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x6f,
+ 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76, 0x6f, 0x6c, 0x75,
+ 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77,
+ 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18, 0x76, 0x6f,
+ 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77,
+ 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75,
+ 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77,
+ 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x69, 0x6e,
+ 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
+ 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x0e, 0x4d, 0x6f, 0x64,
+ 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x5b, 0x0a, 0x0c, 0x62,
+ 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0e, 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x3a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x0b, 0x62, 0x75, 0x69,
+ 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x75,
+ 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d,
+ 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x75, 0x6d,
+ 0x5f, 0x6f, 0x66, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4f, 0x66, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22,
+ 0x2f, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x0b,
+ 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x53,
+ 0x4f, 0x4f, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4b, 0x45, 0x10, 0x02,
+ 0x22, 0x6c, 0x0a, 0x1a, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72,
+ 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x12,
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
- 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f,
- 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x75, 0x73,
- 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x2c, 0x0a, 0x12,
- 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72,
- 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
- 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x1c, 0x0a, 0x0a, 0x6d, 0x61,
- 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b, 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08,
- 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b, 0x62, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x6f,
- 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x05, 0x20,
- 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61,
- 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x70, 0x61,
- 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52,
- 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73,
- 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18,
- 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6f, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4b, 0x62,
- 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62,
- 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74,
- 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f,
- 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73,
- 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72,
- 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73,
- 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f,
- 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73,
- 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74,
- 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68,
- 0x65, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70,
- 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x5b, 0x0a, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x73,
- 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x73, 0x6f,
+ 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c,
+ 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x42, 0x61, 0x73, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x62,
+ 0x0a, 0x1b, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f,
+ 0x75, 0x72, 0x6e, 0x65, 0x79, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x43, 0x0a,
+ 0x04, 0x63, 0x75, 0x6a, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x73, 0x6f,
0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f,
- 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3a, 0x07, 0x55, 0x4e,
- 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74,
- 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70,
- 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54,
- 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x6f, 0x66, 0x5f, 0x6d, 0x6f,
- 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d,
- 0x4f, 0x66, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x2f, 0x0a, 0x0b, 0x42, 0x75, 0x69,
- 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e,
- 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x4f, 0x4f, 0x4e, 0x47, 0x10, 0x01,
- 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4b, 0x45, 0x10, 0x02, 0x22, 0x6c, 0x0a, 0x1a, 0x43, 0x72,
- 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65,
- 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x07,
- 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e,
- 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x42, 0x61, 0x73, 0x65, 0x52,
- 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x62, 0x0a, 0x1b, 0x43, 0x72, 0x69, 0x74,
- 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x73,
- 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x43, 0x0a, 0x04, 0x63, 0x75, 0x6a, 0x73, 0x18,
- 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
- 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x43, 0x72, 0x69, 0x74,
- 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x04, 0x63, 0x75, 0x6a, 0x73, 0x22, 0xcc, 0x02, 0x0a,
- 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08,
- 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08,
- 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x6f, 0x74, 0x61,
- 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x43,
- 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c,
- 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e,
- 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x22,
- 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18,
- 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x48, 0x65, 0x61, 0x70, 0x53, 0x69,
- 0x7a, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64,
- 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66,
- 0x6f, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x50, 0x0a, 0x11, 0x6d, 0x69, 0x78,
- 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x07,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69,
- 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x69, 0x78, 0x65, 0x64,
- 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x6d, 0x69, 0x78, 0x65,
- 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xdb, 0x01, 0x0a, 0x10,
- 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72,
- 0x12, 0x4a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
- 0x32, 0x32, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d,
- 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
- 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74,
- 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08,
- 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
- 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x69, 0x63, 0x72,
- 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73,
- 0x22, 0x47, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
- 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x00, 0x12,
- 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45,
- 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e,
- 0x47, 0x5f, 0x47, 0x43, 0x45, 0x52, 0x54, 0x10, 0x03, 0x22, 0x91, 0x01, 0x0a, 0x0f, 0x4d, 0x69,
- 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3d, 0x0a,
- 0x1b, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x65, 0x6e, 0x61,
- 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03,
- 0x28, 0x09, 0x52, 0x18, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x45, 0x6e,
- 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x3f, 0x0a, 0x1c,
- 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x69, 0x73, 0x61,
- 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03,
- 0x28, 0x09, 0x52, 0x19, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x69,
- 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x42, 0x28, 0x5a,
- 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75,
- 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x73, 0x2e, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f,
+ 0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x04, 0x63, 0x75,
+ 0x6a, 0x73, 0x22, 0xcc, 0x02, 0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c,
+ 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75,
+ 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
+ 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x2a,
+ 0x0a, 0x11, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x63, 0x6f,
+ 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c,
+ 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f,
+ 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04,
+ 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63,
+ 0x53, 0x69, 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x70,
+ 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78,
+ 0x48, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e,
+ 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67,
+ 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50,
+ 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12,
+ 0x50, 0x0a, 0x11, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x5f,
+ 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x6f, 0x6f,
+ 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x2e, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f,
+ 0x52, 0x0f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66,
+ 0x6f, 0x22, 0xdb, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46,
+ 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62,
+ 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x45, 0x78, 0x70,
+ 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x43, 0x6f,
+ 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74,
+ 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16,
+ 0x0a, 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06,
+ 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x22, 0x47, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f, 0x43, 0x4f, 0x4e,
+ 0x46, 0x49, 0x47, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10,
+ 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d,
+ 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x43, 0x45, 0x52, 0x54, 0x10, 0x03, 0x22,
+ 0x91, 0x01, 0x0a, 0x0f, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49,
+ 0x6e, 0x66, 0x6f, 0x12, 0x3d, 0x0a, 0x1b, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69,
+ 0x6c, 0x64, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
+ 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x18, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42,
+ 0x75, 0x69, 0x6c, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c,
+ 0x65, 0x73, 0x12, 0x3f, 0x0a, 0x1c, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c,
+ 0x64, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
+ 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x19, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42,
+ 0x75, 0x69, 0x6c, 0x64, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75,
+ 0x6c, 0x65, 0x73, 0x22, 0x8a, 0x02, 0x0a, 0x10, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x6c, 0x61, 0x70,
+ 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x54, 0x69,
+ 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x39, 0x0a, 0x19, 0x63, 0x72, 0x69, 0x74,
+ 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d,
+ 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x63, 0x72, 0x69,
+ 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63,
+ 0x72, 0x6f, 0x73, 0x12, 0x41, 0x0a, 0x0d, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f,
+ 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x6f, 0x6f,
+ 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0c, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63,
+ 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x11, 0x6c, 0x6f, 0x6e, 0x67, 0x5f, 0x72,
+ 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6a, 0x6f, 0x62, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28,
+ 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x52,
+ 0x0f, 0x6c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x4a, 0x6f, 0x62, 0x73,
+ 0x22, 0x62, 0x0a, 0x07, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x13, 0x65,
+ 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72,
+ 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65,
+ 0x64, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6a,
+ 0x6f, 0x62, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6a, 0x6f, 0x62, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
+ 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x28, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+ 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
@@ -1711,52 +1980,59 @@
return file_metrics_proto_rawDescData
}
-var file_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
-var file_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
+var file_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 5)
+var file_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
var file_metrics_proto_goTypes = []interface{}{
- (MetricsBase_BuildVariant)(0), // 0: soong_build_metrics.MetricsBase.BuildVariant
- (MetricsBase_Arch)(0), // 1: soong_build_metrics.MetricsBase.Arch
- (ModuleTypeInfo_BuildSystem)(0), // 2: soong_build_metrics.ModuleTypeInfo.BuildSystem
- (ExpConfigFetcher_ConfigStatus)(0), // 3: soong_build_metrics.ExpConfigFetcher.ConfigStatus
- (*MetricsBase)(nil), // 4: soong_build_metrics.MetricsBase
- (*BuildConfig)(nil), // 5: soong_build_metrics.BuildConfig
- (*SystemResourceInfo)(nil), // 6: soong_build_metrics.SystemResourceInfo
- (*PerfInfo)(nil), // 7: soong_build_metrics.PerfInfo
- (*ProcessResourceInfo)(nil), // 8: soong_build_metrics.ProcessResourceInfo
- (*ModuleTypeInfo)(nil), // 9: soong_build_metrics.ModuleTypeInfo
- (*CriticalUserJourneyMetrics)(nil), // 10: soong_build_metrics.CriticalUserJourneyMetrics
- (*CriticalUserJourneysMetrics)(nil), // 11: soong_build_metrics.CriticalUserJourneysMetrics
- (*SoongBuildMetrics)(nil), // 12: soong_build_metrics.SoongBuildMetrics
- (*ExpConfigFetcher)(nil), // 13: soong_build_metrics.ExpConfigFetcher
- (*MixedBuildsInfo)(nil), // 14: soong_build_metrics.MixedBuildsInfo
+ (MetricsBase_BuildVariant)(0), // 0: soong_build_metrics.MetricsBase.BuildVariant
+ (MetricsBase_Arch)(0), // 1: soong_build_metrics.MetricsBase.Arch
+ (BuildConfig_NinjaWeightListSource)(0), // 2: soong_build_metrics.BuildConfig.NinjaWeightListSource
+ (ModuleTypeInfo_BuildSystem)(0), // 3: soong_build_metrics.ModuleTypeInfo.BuildSystem
+ (ExpConfigFetcher_ConfigStatus)(0), // 4: soong_build_metrics.ExpConfigFetcher.ConfigStatus
+ (*MetricsBase)(nil), // 5: soong_build_metrics.MetricsBase
+ (*BuildConfig)(nil), // 6: soong_build_metrics.BuildConfig
+ (*SystemResourceInfo)(nil), // 7: soong_build_metrics.SystemResourceInfo
+ (*PerfInfo)(nil), // 8: soong_build_metrics.PerfInfo
+ (*ProcessResourceInfo)(nil), // 9: soong_build_metrics.ProcessResourceInfo
+ (*ModuleTypeInfo)(nil), // 10: soong_build_metrics.ModuleTypeInfo
+ (*CriticalUserJourneyMetrics)(nil), // 11: soong_build_metrics.CriticalUserJourneyMetrics
+ (*CriticalUserJourneysMetrics)(nil), // 12: soong_build_metrics.CriticalUserJourneysMetrics
+ (*SoongBuildMetrics)(nil), // 13: soong_build_metrics.SoongBuildMetrics
+ (*ExpConfigFetcher)(nil), // 14: soong_build_metrics.ExpConfigFetcher
+ (*MixedBuildsInfo)(nil), // 15: soong_build_metrics.MixedBuildsInfo
+ (*CriticalPathInfo)(nil), // 16: soong_build_metrics.CriticalPathInfo
+ (*JobInfo)(nil), // 17: soong_build_metrics.JobInfo
}
var file_metrics_proto_depIdxs = []int32{
0, // 0: soong_build_metrics.MetricsBase.target_build_variant:type_name -> soong_build_metrics.MetricsBase.BuildVariant
1, // 1: soong_build_metrics.MetricsBase.target_arch:type_name -> soong_build_metrics.MetricsBase.Arch
1, // 2: soong_build_metrics.MetricsBase.host_arch:type_name -> soong_build_metrics.MetricsBase.Arch
1, // 3: soong_build_metrics.MetricsBase.host_2nd_arch:type_name -> soong_build_metrics.MetricsBase.Arch
- 7, // 4: soong_build_metrics.MetricsBase.setup_tools:type_name -> soong_build_metrics.PerfInfo
- 7, // 5: soong_build_metrics.MetricsBase.kati_runs:type_name -> soong_build_metrics.PerfInfo
- 7, // 6: soong_build_metrics.MetricsBase.soong_runs:type_name -> soong_build_metrics.PerfInfo
- 7, // 7: soong_build_metrics.MetricsBase.ninja_runs:type_name -> soong_build_metrics.PerfInfo
- 7, // 8: soong_build_metrics.MetricsBase.total:type_name -> soong_build_metrics.PerfInfo
- 12, // 9: soong_build_metrics.MetricsBase.soong_build_metrics:type_name -> soong_build_metrics.SoongBuildMetrics
- 5, // 10: soong_build_metrics.MetricsBase.build_config:type_name -> soong_build_metrics.BuildConfig
- 6, // 11: soong_build_metrics.MetricsBase.system_resource_info:type_name -> soong_build_metrics.SystemResourceInfo
- 7, // 12: soong_build_metrics.MetricsBase.bazel_runs:type_name -> soong_build_metrics.PerfInfo
- 13, // 13: soong_build_metrics.MetricsBase.exp_config_fetcher:type_name -> soong_build_metrics.ExpConfigFetcher
- 8, // 14: soong_build_metrics.PerfInfo.processes_resource_info:type_name -> soong_build_metrics.ProcessResourceInfo
- 2, // 15: soong_build_metrics.ModuleTypeInfo.build_system:type_name -> soong_build_metrics.ModuleTypeInfo.BuildSystem
- 4, // 16: soong_build_metrics.CriticalUserJourneyMetrics.metrics:type_name -> soong_build_metrics.MetricsBase
- 10, // 17: soong_build_metrics.CriticalUserJourneysMetrics.cujs:type_name -> soong_build_metrics.CriticalUserJourneyMetrics
- 7, // 18: soong_build_metrics.SoongBuildMetrics.events:type_name -> soong_build_metrics.PerfInfo
- 14, // 19: soong_build_metrics.SoongBuildMetrics.mixed_builds_info:type_name -> soong_build_metrics.MixedBuildsInfo
- 3, // 20: soong_build_metrics.ExpConfigFetcher.status:type_name -> soong_build_metrics.ExpConfigFetcher.ConfigStatus
- 21, // [21:21] is the sub-list for method output_type
- 21, // [21:21] is the sub-list for method input_type
- 21, // [21:21] is the sub-list for extension type_name
- 21, // [21:21] is the sub-list for extension extendee
- 0, // [0:21] is the sub-list for field type_name
+ 8, // 4: soong_build_metrics.MetricsBase.setup_tools:type_name -> soong_build_metrics.PerfInfo
+ 8, // 5: soong_build_metrics.MetricsBase.kati_runs:type_name -> soong_build_metrics.PerfInfo
+ 8, // 6: soong_build_metrics.MetricsBase.soong_runs:type_name -> soong_build_metrics.PerfInfo
+ 8, // 7: soong_build_metrics.MetricsBase.ninja_runs:type_name -> soong_build_metrics.PerfInfo
+ 8, // 8: soong_build_metrics.MetricsBase.total:type_name -> soong_build_metrics.PerfInfo
+ 13, // 9: soong_build_metrics.MetricsBase.soong_build_metrics:type_name -> soong_build_metrics.SoongBuildMetrics
+ 6, // 10: soong_build_metrics.MetricsBase.build_config:type_name -> soong_build_metrics.BuildConfig
+ 7, // 11: soong_build_metrics.MetricsBase.system_resource_info:type_name -> soong_build_metrics.SystemResourceInfo
+ 8, // 12: soong_build_metrics.MetricsBase.bazel_runs:type_name -> soong_build_metrics.PerfInfo
+ 14, // 13: soong_build_metrics.MetricsBase.exp_config_fetcher:type_name -> soong_build_metrics.ExpConfigFetcher
+ 16, // 14: soong_build_metrics.MetricsBase.critical_path_info:type_name -> soong_build_metrics.CriticalPathInfo
+ 2, // 15: soong_build_metrics.BuildConfig.ninja_weight_list_source:type_name -> soong_build_metrics.BuildConfig.NinjaWeightListSource
+ 9, // 16: soong_build_metrics.PerfInfo.processes_resource_info:type_name -> soong_build_metrics.ProcessResourceInfo
+ 3, // 17: soong_build_metrics.ModuleTypeInfo.build_system:type_name -> soong_build_metrics.ModuleTypeInfo.BuildSystem
+ 5, // 18: soong_build_metrics.CriticalUserJourneyMetrics.metrics:type_name -> soong_build_metrics.MetricsBase
+ 11, // 19: soong_build_metrics.CriticalUserJourneysMetrics.cujs:type_name -> soong_build_metrics.CriticalUserJourneyMetrics
+ 8, // 20: soong_build_metrics.SoongBuildMetrics.events:type_name -> soong_build_metrics.PerfInfo
+ 15, // 21: soong_build_metrics.SoongBuildMetrics.mixed_builds_info:type_name -> soong_build_metrics.MixedBuildsInfo
+ 4, // 22: soong_build_metrics.ExpConfigFetcher.status:type_name -> soong_build_metrics.ExpConfigFetcher.ConfigStatus
+ 17, // 23: soong_build_metrics.CriticalPathInfo.critical_path:type_name -> soong_build_metrics.JobInfo
+ 17, // 24: soong_build_metrics.CriticalPathInfo.long_running_jobs:type_name -> soong_build_metrics.JobInfo
+ 25, // [25:25] is the sub-list for method output_type
+ 25, // [25:25] is the sub-list for method input_type
+ 25, // [25:25] is the sub-list for extension type_name
+ 25, // [25:25] is the sub-list for extension extendee
+ 0, // [0:25] is the sub-list for field type_name
}
func init() { file_metrics_proto_init() }
@@ -1897,14 +2173,38 @@
return nil
}
}
+ file_metrics_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CriticalPathInfo); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_metrics_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*JobInfo); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_metrics_proto_rawDesc,
- NumEnums: 4,
- NumMessages: 11,
+ NumEnums: 5,
+ NumMessages: 13,
NumExtensions: 0,
NumServices: 0,
},
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index b7dc91a..6db83e9 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -128,9 +128,20 @@
// The branch on which the build occurred.
// Example: refs/heads/master
optional string branch = 32;
+
+ // The metric of critical path in build
+ optional CriticalPathInfo critical_path_info = 33;
}
message BuildConfig {
+ enum NinjaWeightListSource {
+ NOT_USED = 0;
+ NINJA_LOG = 1;
+ EVENLY_DISTRIBUTED = 2;
+ EXTERNAL_FILE = 3;
+ HINT_FROM_SOONG = 4;
+ }
+
optional bool use_goma = 1;
optional bool use_rbe = 2;
@@ -150,6 +161,13 @@
// Whether the user explicitly disabled bazel mixed builds for this build.
optional bool force_disable_bazel_mixed_build = 7;
+
+ // NOT_USED - ninja doesn't use weight list.
+ // NINJA_LOG - ninja uses weight list based on previous builds by ninja log
+ // EVENLY_DISTRIBUTED - ninja thinks every task has the same weight.
+ // EXTERNAL_FILE - ninja uses an external custom weight list
+ // HINT_FROM_SOONG - ninja uses a prioritized module list from Soong
+ optional NinjaWeightListSource ninja_weight_list_source = 8 [default = NOT_USED];
}
message SystemResourceInfo {
@@ -314,3 +332,23 @@
// Modules that are not enabled for MixedBuilds
repeated string mixed_build_disabled_modules = 2;
}
+
+// CriticalPathInfo contains critical path nodes's information.
+// A critical path is a path determining the minimum time needed for the whole build given perfect parallelism.
+message CriticalPathInfo {
+ // Real time which the build system spent in microseconds
+ optional uint64 elapsed_time_micros = 1;
+ // The sum of execution time of the longest path from leave to the root in microseconds
+ optional uint64 critical_path_time_micros = 2;
+ // Detailed job information in a critical path.
+ repeated JobInfo critical_path = 4;
+ // Detailed job information for long running jobs (>30 seconds). These may or may not also be on a critical path.
+ repeated JobInfo long_running_jobs = 5;
+}
+
+message JobInfo {
+ // Real time which a job spent in microseconds
+ optional uint64 elapsed_time_micros = 1;
+ // Description of a job
+ optional string job_description = 2;
+}
diff --git a/ui/status/Android.bp b/ui/status/Android.bp
index a46a007..b724bc9 100644
--- a/ui/status/Android.bp
+++ b/ui/status/Android.bp
@@ -28,6 +28,7 @@
],
srcs: [
"critical_path.go",
+ "critical_path_logger.go",
"kati.go",
"log.go",
"ninja.go",
diff --git a/ui/status/critical_path.go b/ui/status/critical_path.go
index 8065c60..bf32c58 100644
--- a/ui/status/critical_path.go
+++ b/ui/status/critical_path.go
@@ -15,23 +15,23 @@
package status
import (
+ "android/soong/ui/metrics"
+
+ soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
"time"
- "android/soong/ui/logger"
+ "google.golang.org/protobuf/proto"
)
-func NewCriticalPath(log logger.Logger) StatusOutput {
- return &criticalPath{
- log: log,
+func NewCriticalPath() *CriticalPath {
+ return &CriticalPath{
running: make(map[*Action]time.Time),
nodes: make(map[string]*node),
clock: osClock{},
}
}
-type criticalPath struct {
- log logger.Logger
-
+type CriticalPath struct {
nodes map[string]*node
running map[*Action]time.Time
@@ -57,7 +57,7 @@
input *node
}
-func (cp *criticalPath) StartAction(action *Action, counts Counts) {
+func (cp *CriticalPath) StartAction(action *Action) {
start := cp.clock.Now()
if cp.start.IsZero() {
cp.start = start
@@ -65,13 +65,13 @@
cp.running[action] = start
}
-func (cp *criticalPath) FinishAction(result ActionResult, counts Counts) {
- if start, ok := cp.running[result.Action]; ok {
- delete(cp.running, result.Action)
+func (cp *CriticalPath) FinishAction(action *Action) {
+ if start, ok := cp.running[action]; ok {
+ delete(cp.running, action)
// Determine the input to this edge with the longest cumulative duration
var criticalPathInput *node
- for _, input := range result.Action.Inputs {
+ for _, input := range action.Inputs {
if x := cp.nodes[input]; x != nil {
if criticalPathInput == nil || x.cumulativeDuration > criticalPathInput.cumulativeDuration {
criticalPathInput = x
@@ -88,13 +88,13 @@
}
node := &node{
- action: result.Action,
+ action: action,
cumulativeDuration: cumulativeDuration,
duration: duration,
input: criticalPathInput,
}
- for _, output := range result.Action.Outputs {
+ for _, output := range action.Outputs {
cp.nodes[output] = node
}
@@ -102,37 +102,7 @@
}
}
-func (cp *criticalPath) Flush() {
- criticalPath := cp.criticalPath()
-
- if len(criticalPath) > 0 {
- // Log the critical path to the verbose log
- criticalTime := criticalPath[0].cumulativeDuration.Round(time.Second)
- cp.log.Verbosef("critical path took %s", criticalTime.String())
- if !cp.start.IsZero() {
- elapsedTime := cp.end.Sub(cp.start).Round(time.Second)
- cp.log.Verbosef("elapsed time %s", elapsedTime.String())
- if elapsedTime > 0 {
- cp.log.Verbosef("perfect parallelism ratio %d%%",
- int(float64(criticalTime)/float64(elapsedTime)*100))
- }
- }
- cp.log.Verbose("critical path:")
- for i := len(criticalPath) - 1; i >= 0; i-- {
- duration := criticalPath[i].duration
- duration = duration.Round(time.Second)
- seconds := int(duration.Seconds())
- cp.log.Verbosef(" %2d:%02d %s",
- seconds/60, seconds%60, criticalPath[i].action.Description)
- }
- }
-}
-
-func (cp *criticalPath) Message(level MsgLevel, msg string) {}
-
-func (cp *criticalPath) Write(p []byte) (n int, err error) { return len(p), nil }
-
-func (cp *criticalPath) criticalPath() []*node {
+func (cp *CriticalPath) criticalPath() (path []*node, elapsedTime time.Duration, criticalTime time.Duration) {
var max *node
// Find the node with the longest critical path
@@ -142,13 +112,46 @@
}
}
- // Follow the critical path back to the leaf node
- var criticalPath []*node
node := max
for node != nil {
- criticalPath = append(criticalPath, node)
+ path = append(path, node)
node = node.input
}
+ if len(path) > 0 {
+ // Log the critical path to the verbose log
+ criticalTime = path[0].cumulativeDuration
+ if !cp.start.IsZero() {
+ elapsedTime = cp.end.Sub(cp.start)
+ }
+ }
+ return
+}
- return criticalPath
+func (cp *CriticalPath) longRunningJobs() (nodes []*node) {
+ threshold := time.Second * 30
+ for _, node := range cp.nodes {
+ if node != nil && node.duration > threshold {
+ nodes = append(nodes, node)
+ }
+ }
+ return
+}
+
+func addJobInfos(jobInfos *[]*soong_metrics_proto.JobInfo, sources []*node) {
+ for _, job := range sources {
+ jobInfo := soong_metrics_proto.JobInfo{}
+ jobInfo.ElapsedTimeMicros = proto.Uint64(uint64(job.duration.Microseconds()))
+ jobInfo.JobDescription = &job.action.Description
+ *jobInfos = append(*jobInfos, &jobInfo)
+ }
+}
+
+func (cp *CriticalPath) WriteToMetrics(met *metrics.Metrics) {
+ criticalPathInfo := soong_metrics_proto.CriticalPathInfo{}
+ path, elapsedTime, criticalTime := cp.criticalPath()
+ criticalPathInfo.ElapsedTimeMicros = proto.Uint64(uint64(elapsedTime.Microseconds()))
+ criticalPathInfo.CriticalPathTimeMicros = proto.Uint64(uint64(criticalTime.Microseconds()))
+ addJobInfos(&criticalPathInfo.LongRunningJobs, cp.longRunningJobs())
+ addJobInfos(&criticalPathInfo.CriticalPath, path)
+ met.SetCriticalPathInfo(criticalPathInfo)
}
diff --git a/ui/status/critical_path_logger.go b/ui/status/critical_path_logger.go
new file mode 100644
index 0000000..f8b49d1
--- /dev/null
+++ b/ui/status/critical_path_logger.go
@@ -0,0 +1,73 @@
+// Copyright 2023 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 status
+
+import (
+ "time"
+
+ "android/soong/ui/logger"
+)
+
+// Create a new CriticalPathLogger. if criticalPath is nil, it creates a new criticalPath,
+// if not, it uses that.(its purpose is using a critical path outside logger)
+func NewCriticalPathLogger(log logger.Logger, criticalPath *CriticalPath) StatusOutput {
+ if criticalPath == nil {
+ criticalPath = NewCriticalPath()
+ }
+ return &criticalPathLogger{
+ log: log,
+ criticalPath: criticalPath,
+ }
+}
+
+type criticalPathLogger struct {
+ log logger.Logger
+ criticalPath *CriticalPath
+}
+
+func (cp *criticalPathLogger) StartAction(action *Action, counts Counts) {
+ cp.criticalPath.StartAction(action)
+}
+
+func (cp *criticalPathLogger) FinishAction(result ActionResult, counts Counts) {
+ cp.criticalPath.FinishAction(result.Action)
+}
+
+func (cp *criticalPathLogger) Flush() {
+ criticalPath, elapsedTime, criticalTime := cp.criticalPath.criticalPath()
+
+ if len(criticalPath) > 0 {
+ cp.log.Verbosef("critical path took %s", criticalTime.String())
+ if !cp.criticalPath.start.IsZero() {
+ cp.log.Verbosef("elapsed time %s", elapsedTime.String())
+ if elapsedTime > 0 {
+ cp.log.Verbosef("perfect parallelism ratio %d%%",
+ int(float64(criticalTime)/float64(elapsedTime)*100))
+ }
+ }
+ cp.log.Verbose("critical path:")
+ for i := len(criticalPath) - 1; i >= 0; i-- {
+ duration := criticalPath[i].duration
+ duration = duration.Round(time.Second)
+ seconds := int(duration.Seconds())
+ cp.log.Verbosef(" %2d:%02d %s",
+ seconds/60, seconds%60, criticalPath[i].action.Description)
+ }
+ }
+}
+
+func (cp *criticalPathLogger) Message(level MsgLevel, msg string) {}
+
+func (cp *criticalPathLogger) Write(p []byte) (n int, err error) { return len(p), nil }
diff --git a/ui/status/critical_path_test.go b/ui/status/critical_path_test.go
index 965e0ad..369e805 100644
--- a/ui/status/critical_path_test.go
+++ b/ui/status/critical_path_test.go
@@ -21,7 +21,7 @@
)
type testCriticalPath struct {
- *criticalPath
+ *CriticalPath
Counts
actions map[int]*Action
@@ -40,14 +40,12 @@
}
t.actions[id] = action
- t.StartAction(action, t.Counts)
+ t.StartAction(action)
}
func (t *testCriticalPath) finish(id int, endTime time.Duration) {
t.clock = testClock(time.Unix(0, 0).Add(endTime))
- t.FinishAction(ActionResult{
- Action: t.actions[id],
- }, t.Counts)
+ t.FinishAction(t.actions[id])
}
func TestCriticalPath(t *testing.T) {
@@ -137,13 +135,13 @@
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cp := &testCriticalPath{
- criticalPath: NewCriticalPath(nil).(*criticalPath),
+ CriticalPath: NewCriticalPath(),
actions: make(map[int]*Action),
}
tt.msgs(cp)
- criticalPath := cp.criticalPath.criticalPath()
+ criticalPath, _, _ := cp.CriticalPath.criticalPath()
var descs []string
for _, x := range criticalPath {