Merge "Move libFlags as well to the RSP file for link actions"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index ccfad00..af82942 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -37,182 +37,186 @@
var (
Bp2buildDefaultConfig = Bp2BuildConfig{
- "prebuilts/runtime/mainline/platform/sdk": Bp2BuildDefaultTrueRecursively,
- "art/libartpalette": Bp2BuildDefaultTrueRecursively,
- "art/libdexfile": Bp2BuildDefaultTrueRecursively,
- "art/libnativebridge": Bp2BuildDefaultTrueRecursively,
- "art/runtime": Bp2BuildDefaultTrueRecursively,
- "art/tools": Bp2BuildDefaultTrue,
- "bionic": Bp2BuildDefaultTrueRecursively,
- "bootable/recovery/tools/recovery_l10n": Bp2BuildDefaultTrue,
- "build/bazel/examples/apex/minimal": Bp2BuildDefaultTrueRecursively,
- "build/bazel/examples/soong_config_variables": Bp2BuildDefaultTrueRecursively,
- "build/bazel/examples/python": Bp2BuildDefaultTrueRecursively,
- "build/bazel/examples/gensrcs": Bp2BuildDefaultTrueRecursively,
- "build/make/target/product/security": Bp2BuildDefaultTrue,
- "build/make/tools/signapk": Bp2BuildDefaultTrue,
- "build/make/tools/zipalign": Bp2BuildDefaultTrueRecursively,
- "build/soong": Bp2BuildDefaultTrue,
- "build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir
- "build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue,
- "build/soong/cc/symbolfile": Bp2BuildDefaultTrue,
- "build/soong/linkerconfig": Bp2BuildDefaultTrueRecursively,
- "build/soong/scripts": Bp2BuildDefaultTrueRecursively,
- "cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively,
- "development/apps/DevelopmentSettings": Bp2BuildDefaultTrue,
- "development/apps/Fallback": Bp2BuildDefaultTrue,
- "development/apps/WidgetPreview": Bp2BuildDefaultTrue,
- "development/samples/BasicGLSurfaceView": Bp2BuildDefaultTrue,
- "development/samples/BluetoothChat": Bp2BuildDefaultTrue,
- "development/samples/BrokenKeyDerivation": Bp2BuildDefaultTrue,
- "development/samples/Compass": Bp2BuildDefaultTrue,
- "development/samples/ContactManager": Bp2BuildDefaultTrue,
- "development/samples/FixedGridLayout": Bp2BuildDefaultTrue,
- "development/samples/HelloEffects": Bp2BuildDefaultTrue,
- "development/samples/Home": Bp2BuildDefaultTrue,
- "development/samples/HoneycombGallery": Bp2BuildDefaultTrue,
- "development/samples/JetBoy": Bp2BuildDefaultTrue,
- "development/samples/KeyChainDemo": Bp2BuildDefaultTrue,
- "development/samples/LceDemo": Bp2BuildDefaultTrue,
- "development/samples/LunarLander": Bp2BuildDefaultTrue,
- "development/samples/MultiResolution": Bp2BuildDefaultTrue,
- "development/samples/MultiWindow": Bp2BuildDefaultTrue,
- "development/samples/NotePad": Bp2BuildDefaultTrue,
- "development/samples/Obb": Bp2BuildDefaultTrue,
- "development/samples/RSSReader": Bp2BuildDefaultTrue,
- "development/samples/ReceiveShareDemo": Bp2BuildDefaultTrue,
- "development/samples/SearchableDictionary": Bp2BuildDefaultTrue,
- "development/samples/SipDemo": Bp2BuildDefaultTrue,
- "development/samples/SkeletonApp": Bp2BuildDefaultTrue,
- "development/samples/Snake": Bp2BuildDefaultTrue,
- "development/samples/SpellChecker/": Bp2BuildDefaultTrueRecursively,
- "development/samples/ThemedNavBarKeyboard": Bp2BuildDefaultTrue,
- "development/samples/ToyVpn": Bp2BuildDefaultTrue,
- "development/samples/TtsEngine": Bp2BuildDefaultTrue,
- "development/samples/USB/AdbTest": Bp2BuildDefaultTrue,
- "development/samples/USB/MissileLauncher": Bp2BuildDefaultTrue,
- "development/samples/VoiceRecognitionService": Bp2BuildDefaultTrue,
- "development/samples/VoicemailProviderDemo": Bp2BuildDefaultTrue,
- "development/samples/WiFiDirectDemo": Bp2BuildDefaultTrue,
- "development/sdk": Bp2BuildDefaultTrueRecursively,
- "external/aac": Bp2BuildDefaultTrueRecursively,
- "external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
- "external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively,
- "external/auto/common": Bp2BuildDefaultTrueRecursively,
- "external/auto/service": Bp2BuildDefaultTrueRecursively,
- "external/boringssl": Bp2BuildDefaultTrueRecursively,
- "external/bouncycastle": Bp2BuildDefaultTrue,
- "external/brotli": Bp2BuildDefaultTrue,
- "external/conscrypt": Bp2BuildDefaultTrue,
- "external/e2fsprogs": Bp2BuildDefaultTrueRecursively,
- "external/eigen": Bp2BuildDefaultTrueRecursively,
- "external/erofs-utils": Bp2BuildDefaultTrueRecursively,
- "external/error_prone": Bp2BuildDefaultTrueRecursively,
- "external/f2fs-tools": Bp2BuildDefaultTrue,
- "external/flac": Bp2BuildDefaultTrueRecursively,
- "external/fmtlib": Bp2BuildDefaultTrueRecursively,
- "external/google-benchmark": Bp2BuildDefaultTrueRecursively,
- "external/googletest": Bp2BuildDefaultTrueRecursively,
- "external/gwp_asan": Bp2BuildDefaultTrueRecursively,
- "external/hamcrest": Bp2BuildDefaultTrueRecursively,
- "external/icu": Bp2BuildDefaultTrueRecursively,
- "external/icu/android_icu4j": Bp2BuildDefaultFalse, // java rules incomplete
- "external/icu/icu4j": Bp2BuildDefaultFalse, // java rules incomplete
- "external/jarjar": Bp2BuildDefaultTrueRecursively,
- "external/javapoet": Bp2BuildDefaultTrueRecursively,
- "external/jemalloc_new": Bp2BuildDefaultTrueRecursively,
- "external/jsoncpp": Bp2BuildDefaultTrueRecursively,
- "external/junit": Bp2BuildDefaultTrueRecursively,
- "external/libavc": Bp2BuildDefaultTrueRecursively,
- "external/libcap": Bp2BuildDefaultTrueRecursively,
- "external/libcxx": Bp2BuildDefaultTrueRecursively,
- "external/libcxxabi": Bp2BuildDefaultTrueRecursively,
- "external/libevent": Bp2BuildDefaultTrueRecursively,
- "external/libgav1": Bp2BuildDefaultTrueRecursively,
- "external/libhevc": Bp2BuildDefaultTrueRecursively,
- "external/libmpeg2": Bp2BuildDefaultTrueRecursively,
- "external/libpng": Bp2BuildDefaultTrueRecursively,
- "external/lz4/lib": Bp2BuildDefaultTrue,
- "external/lzma/C": Bp2BuildDefaultTrueRecursively,
- "external/mdnsresponder": Bp2BuildDefaultTrueRecursively,
- "external/minijail": Bp2BuildDefaultTrueRecursively,
- "external/pcre": Bp2BuildDefaultTrueRecursively,
- "external/protobuf": Bp2BuildDefaultTrueRecursively,
- "external/python/six": Bp2BuildDefaultTrueRecursively,
- "external/rappor": Bp2BuildDefaultTrueRecursively,
- "external/scudo": Bp2BuildDefaultTrueRecursively,
- "external/selinux/libselinux": Bp2BuildDefaultTrueRecursively,
- "external/selinux/libsepol": Bp2BuildDefaultTrueRecursively,
- "external/zlib": Bp2BuildDefaultTrueRecursively,
- "external/zopfli": Bp2BuildDefaultTrueRecursively,
- "external/zstd": Bp2BuildDefaultTrueRecursively,
- "frameworks/av/media/codecs/g711/decoder": Bp2BuildDefaultTrueRecursively,
- "frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively,
- "frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue,
- "frameworks/base/startop/apps/test": Bp2BuildDefaultTrue,
- "frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively,
- "frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively,
- "frameworks/native/libs/arect": Bp2BuildDefaultTrueRecursively,
- "frameworks/native/libs/math": Bp2BuildDefaultTrueRecursively,
- "frameworks/native/libs/nativebase": Bp2BuildDefaultTrueRecursively,
- "frameworks/native/opengl/tests/gl2_cameraeye": Bp2BuildDefaultTrue,
- "frameworks/native/opengl/tests/gl2_java": Bp2BuildDefaultTrue,
- "frameworks/native/opengl/tests/testLatency": Bp2BuildDefaultTrue,
- "frameworks/native/opengl/tests/testPauseResume": Bp2BuildDefaultTrue,
- "frameworks/native/opengl/tests/testViewport": Bp2BuildDefaultTrue,
- "frameworks/proto_logging/stats/stats_log_api_gen": Bp2BuildDefaultTrueRecursively,
- "libnativehelper": Bp2BuildDefaultTrueRecursively,
- "packages/apps/DevCamera": Bp2BuildDefaultTrue,
- "packages/apps/HTMLViewer": Bp2BuildDefaultTrue,
- "packages/apps/Protips": Bp2BuildDefaultTrue,
- "packages/modules/StatsD/lib/libstatssocket": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb": Bp2BuildDefaultTrue,
- "packages/modules/adb/apex": Bp2BuildDefaultTrue,
- "packages/modules/adb/crypto": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb/libs": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb/pairing_auth": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb/pairing_connection": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb/proto": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb/tls": Bp2BuildDefaultTrueRecursively,
- "packages/providers/MediaProvider/tools/dialogs": Bp2BuildDefaultTrue,
- "packages/screensavers/Basic": Bp2BuildDefaultTrue,
- "packages/services/Car/tests/SampleRearViewCamera": Bp2BuildDefaultTrue,
- "prebuilts/clang/host/linux-x86": Bp2BuildDefaultTrueRecursively,
- "prebuilts/tools/common/m2": Bp2BuildDefaultTrue,
- "system/apex": Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures
- "system/apex/apexer": Bp2BuildDefaultTrue,
- "system/apex/libs": Bp2BuildDefaultTrueRecursively,
- "system/apex/proto": Bp2BuildDefaultTrueRecursively,
- "system/apex/tools": Bp2BuildDefaultTrueRecursively,
- "system/core/debuggerd": Bp2BuildDefaultTrueRecursively,
- "system/core/diagnose_usb": Bp2BuildDefaultTrueRecursively,
- "system/core/libasyncio": Bp2BuildDefaultTrue,
- "system/core/libcrypto_utils": Bp2BuildDefaultTrueRecursively,
- "system/core/libcutils": Bp2BuildDefaultTrueRecursively,
- "system/core/libpackagelistparser": Bp2BuildDefaultTrueRecursively,
- "system/core/libprocessgroup": Bp2BuildDefaultTrue,
- "system/core/libprocessgroup/cgrouprc": Bp2BuildDefaultTrue,
- "system/core/libprocessgroup/cgrouprc_format": Bp2BuildDefaultTrue,
- "system/core/libsystem": Bp2BuildDefaultTrueRecursively,
- "system/core/libutils": Bp2BuildDefaultTrueRecursively,
- "system/core/libvndksupport": Bp2BuildDefaultTrueRecursively,
- "system/core/property_service/libpropertyinfoparser": Bp2BuildDefaultTrueRecursively,
- "system/libartpalette": Bp2BuildDefaultTrueRecursively,
- "system/libbase": Bp2BuildDefaultTrueRecursively,
- "system/libfmq": Bp2BuildDefaultTrue,
- "system/libhwbinder": Bp2BuildDefaultTrueRecursively,
- "system/libprocinfo": Bp2BuildDefaultTrue,
- "system/libziparchive": Bp2BuildDefaultTrueRecursively,
- "system/logging/liblog": Bp2BuildDefaultTrueRecursively,
- "system/media/audio": Bp2BuildDefaultTrueRecursively,
- "system/memory/libion": Bp2BuildDefaultTrueRecursively,
- "system/memory/libmemunreachable": Bp2BuildDefaultTrueRecursively,
- "system/sepolicy/apex": Bp2BuildDefaultTrueRecursively,
- "system/timezone/apex": Bp2BuildDefaultTrueRecursively,
- "system/timezone/output_data": Bp2BuildDefaultTrueRecursively,
- "system/unwinding/libunwindstack": Bp2BuildDefaultTrueRecursively,
- "tools/apksig": Bp2BuildDefaultTrue,
- "tools/platform-compat/java/android/compat": Bp2BuildDefaultTrueRecursively,
+ "prebuilts/runtime/mainline/platform/sdk": Bp2BuildDefaultTrueRecursively,
+ "art/libartpalette": Bp2BuildDefaultTrueRecursively,
+ "art/libartbase": Bp2BuildDefaultTrueRecursively,
+ "art/libdexfile": Bp2BuildDefaultTrueRecursively,
+ "art/libnativebridge": Bp2BuildDefaultTrueRecursively,
+ "art/runtime": Bp2BuildDefaultTrueRecursively,
+ "art/tools": Bp2BuildDefaultTrue,
+ "bionic": Bp2BuildDefaultTrueRecursively,
+ "bootable/recovery/tools/recovery_l10n": Bp2BuildDefaultTrue,
+ "build/bazel/examples/apex/minimal": Bp2BuildDefaultTrueRecursively,
+ "build/bazel/examples/soong_config_variables": Bp2BuildDefaultTrueRecursively,
+ "build/bazel/examples/python": Bp2BuildDefaultTrueRecursively,
+ "build/bazel/examples/gensrcs": Bp2BuildDefaultTrueRecursively,
+ "build/make/target/product/security": Bp2BuildDefaultTrue,
+ "build/make/tools/signapk": Bp2BuildDefaultTrue,
+ "build/make/tools/zipalign": Bp2BuildDefaultTrueRecursively,
+ "build/soong": Bp2BuildDefaultTrue,
+ "build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir
+ "build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue,
+ "build/soong/cc/symbolfile": Bp2BuildDefaultTrue,
+ "build/soong/linkerconfig": Bp2BuildDefaultTrueRecursively,
+ "build/soong/scripts": Bp2BuildDefaultTrueRecursively,
+ "cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively,
+ "development/apps/DevelopmentSettings": Bp2BuildDefaultTrue,
+ "development/apps/Fallback": Bp2BuildDefaultTrue,
+ "development/apps/WidgetPreview": Bp2BuildDefaultTrue,
+ "development/samples/BasicGLSurfaceView": Bp2BuildDefaultTrue,
+ "development/samples/BluetoothChat": Bp2BuildDefaultTrue,
+ "development/samples/BrokenKeyDerivation": Bp2BuildDefaultTrue,
+ "development/samples/Compass": Bp2BuildDefaultTrue,
+ "development/samples/ContactManager": Bp2BuildDefaultTrue,
+ "development/samples/FixedGridLayout": Bp2BuildDefaultTrue,
+ "development/samples/HelloEffects": Bp2BuildDefaultTrue,
+ "development/samples/Home": Bp2BuildDefaultTrue,
+ "development/samples/HoneycombGallery": Bp2BuildDefaultTrue,
+ "development/samples/JetBoy": Bp2BuildDefaultTrue,
+ "development/samples/KeyChainDemo": Bp2BuildDefaultTrue,
+ "development/samples/LceDemo": Bp2BuildDefaultTrue,
+ "development/samples/LunarLander": Bp2BuildDefaultTrue,
+ "development/samples/MultiResolution": Bp2BuildDefaultTrue,
+ "development/samples/MultiWindow": Bp2BuildDefaultTrue,
+ "development/samples/NotePad": Bp2BuildDefaultTrue,
+ "development/samples/Obb": Bp2BuildDefaultTrue,
+ "development/samples/RSSReader": Bp2BuildDefaultTrue,
+ "development/samples/ReceiveShareDemo": Bp2BuildDefaultTrue,
+ "development/samples/SearchableDictionary": Bp2BuildDefaultTrue,
+ "development/samples/SipDemo": Bp2BuildDefaultTrue,
+ "development/samples/SkeletonApp": Bp2BuildDefaultTrue,
+ "development/samples/Snake": Bp2BuildDefaultTrue,
+ "development/samples/SpellChecker/": Bp2BuildDefaultTrueRecursively,
+ "development/samples/ThemedNavBarKeyboard": Bp2BuildDefaultTrue,
+ "development/samples/ToyVpn": Bp2BuildDefaultTrue,
+ "development/samples/TtsEngine": Bp2BuildDefaultTrue,
+ "development/samples/USB/AdbTest": Bp2BuildDefaultTrue,
+ "development/samples/USB/MissileLauncher": Bp2BuildDefaultTrue,
+ "development/samples/VoiceRecognitionService": Bp2BuildDefaultTrue,
+ "development/samples/VoicemailProviderDemo": Bp2BuildDefaultTrue,
+ "development/samples/WiFiDirectDemo": Bp2BuildDefaultTrue,
+ "development/sdk": Bp2BuildDefaultTrueRecursively,
+ "external/aac": Bp2BuildDefaultTrueRecursively,
+ "external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
+ "external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively,
+ "external/auto/common": Bp2BuildDefaultTrueRecursively,
+ "external/auto/service": Bp2BuildDefaultTrueRecursively,
+ "external/boringssl": Bp2BuildDefaultTrueRecursively,
+ "external/bouncycastle": Bp2BuildDefaultTrue,
+ "external/brotli": Bp2BuildDefaultTrue,
+ "external/conscrypt": Bp2BuildDefaultTrue,
+ "external/e2fsprogs": Bp2BuildDefaultTrueRecursively,
+ "external/eigen": Bp2BuildDefaultTrueRecursively,
+ "external/erofs-utils": Bp2BuildDefaultTrueRecursively,
+ "external/error_prone": Bp2BuildDefaultTrueRecursively,
+ "external/expat": Bp2BuildDefaultTrueRecursively,
+ "external/f2fs-tools": Bp2BuildDefaultTrue,
+ "external/flac": Bp2BuildDefaultTrueRecursively,
+ "external/fmtlib": Bp2BuildDefaultTrueRecursively,
+ "external/google-benchmark": Bp2BuildDefaultTrueRecursively,
+ "external/googletest": Bp2BuildDefaultTrueRecursively,
+ "external/gwp_asan": Bp2BuildDefaultTrueRecursively,
+ "external/hamcrest": Bp2BuildDefaultTrueRecursively,
+ "external/icu": Bp2BuildDefaultTrueRecursively,
+ "external/icu/android_icu4j": Bp2BuildDefaultFalse, // java rules incomplete
+ "external/icu/icu4j": Bp2BuildDefaultFalse, // java rules incomplete
+ "external/jarjar": Bp2BuildDefaultTrueRecursively,
+ "external/javapoet": Bp2BuildDefaultTrueRecursively,
+ "external/jemalloc_new": Bp2BuildDefaultTrueRecursively,
+ "external/jsoncpp": Bp2BuildDefaultTrueRecursively,
+ "external/junit": Bp2BuildDefaultTrueRecursively,
+ "external/libavc": Bp2BuildDefaultTrueRecursively,
+ "external/libcap": Bp2BuildDefaultTrueRecursively,
+ "external/libcxx": Bp2BuildDefaultTrueRecursively,
+ "external/libcxxabi": Bp2BuildDefaultTrueRecursively,
+ "external/libevent": Bp2BuildDefaultTrueRecursively,
+ "external/libgav1": Bp2BuildDefaultTrueRecursively,
+ "external/libhevc": Bp2BuildDefaultTrueRecursively,
+ "external/libmpeg2": Bp2BuildDefaultTrueRecursively,
+ "external/libpng": Bp2BuildDefaultTrueRecursively,
+ "external/lz4/lib": Bp2BuildDefaultTrue,
+ "external/lzma/C": Bp2BuildDefaultTrueRecursively,
+ "external/mdnsresponder": Bp2BuildDefaultTrueRecursively,
+ "external/minijail": Bp2BuildDefaultTrueRecursively,
+ "external/pcre": Bp2BuildDefaultTrueRecursively,
+ "external/protobuf": Bp2BuildDefaultTrueRecursively,
+ "external/python/six": Bp2BuildDefaultTrueRecursively,
+ "external/rappor": Bp2BuildDefaultTrueRecursively,
+ "external/scudo": Bp2BuildDefaultTrueRecursively,
+ "external/selinux/libselinux": Bp2BuildDefaultTrueRecursively,
+ "external/selinux/libsepol": Bp2BuildDefaultTrueRecursively,
+ "external/zlib": Bp2BuildDefaultTrueRecursively,
+ "external/zopfli": Bp2BuildDefaultTrueRecursively,
+ "external/zstd": Bp2BuildDefaultTrueRecursively,
+ "frameworks/av/media/codecs": Bp2BuildDefaultTrueRecursively,
+ "frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively,
+ "frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue,
+ "frameworks/base/startop/apps/test": Bp2BuildDefaultTrue,
+ "frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively,
+ "frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively,
+ "frameworks/native/libs/arect": Bp2BuildDefaultTrueRecursively,
+ "frameworks/native/libs/math": Bp2BuildDefaultTrueRecursively,
+ "frameworks/native/libs/nativebase": Bp2BuildDefaultTrueRecursively,
+ "frameworks/native/opengl/tests/gl2_cameraeye": Bp2BuildDefaultTrue,
+ "frameworks/native/opengl/tests/gl2_java": Bp2BuildDefaultTrue,
+ "frameworks/native/opengl/tests/testLatency": Bp2BuildDefaultTrue,
+ "frameworks/native/opengl/tests/testPauseResume": Bp2BuildDefaultTrue,
+ "frameworks/native/opengl/tests/testViewport": Bp2BuildDefaultTrue,
+ "frameworks/proto_logging/stats/stats_log_api_gen": Bp2BuildDefaultTrueRecursively,
+ "libnativehelper": Bp2BuildDefaultTrueRecursively,
+ "packages/apps/DevCamera": Bp2BuildDefaultTrue,
+ "packages/apps/HTMLViewer": Bp2BuildDefaultTrue,
+ "packages/apps/Protips": Bp2BuildDefaultTrue,
+ "packages/modules/StatsD/lib/libstatssocket": Bp2BuildDefaultTrueRecursively,
+ "packages/modules/adb": Bp2BuildDefaultTrue,
+ "packages/modules/adb/apex": Bp2BuildDefaultTrue,
+ "packages/modules/adb/crypto": Bp2BuildDefaultTrueRecursively,
+ "packages/modules/adb/libs": Bp2BuildDefaultTrueRecursively,
+ "packages/modules/adb/pairing_auth": Bp2BuildDefaultTrueRecursively,
+ "packages/modules/adb/pairing_connection": Bp2BuildDefaultTrueRecursively,
+ "packages/modules/adb/proto": Bp2BuildDefaultTrueRecursively,
+ "packages/modules/adb/tls": Bp2BuildDefaultTrueRecursively,
+ "packages/providers/MediaProvider/tools/dialogs": Bp2BuildDefaultTrue,
+ "packages/screensavers/Basic": Bp2BuildDefaultTrue,
+ "packages/services/Car/tests/SampleRearViewCamera": Bp2BuildDefaultTrue,
+ "prebuilts/clang/host/linux-x86": Bp2BuildDefaultTrueRecursively,
+ "prebuilts/tools/common/m2": Bp2BuildDefaultTrue,
+ "system/apex": Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures
+ "system/apex/apexer": Bp2BuildDefaultTrue,
+ "system/apex/libs": Bp2BuildDefaultTrueRecursively,
+ "system/apex/proto": Bp2BuildDefaultTrueRecursively,
+ "system/apex/tools": Bp2BuildDefaultTrueRecursively,
+ "system/core/debuggerd": Bp2BuildDefaultTrueRecursively,
+ "system/core/diagnose_usb": Bp2BuildDefaultTrueRecursively,
+ "system/core/libasyncio": Bp2BuildDefaultTrue,
+ "system/core/libcrypto_utils": Bp2BuildDefaultTrueRecursively,
+ "system/core/libcutils": Bp2BuildDefaultTrueRecursively,
+ "system/core/libpackagelistparser": Bp2BuildDefaultTrueRecursively,
+ "system/core/libprocessgroup": Bp2BuildDefaultTrue,
+ "system/core/libprocessgroup/cgrouprc": Bp2BuildDefaultTrue,
+ "system/core/libprocessgroup/cgrouprc_format": Bp2BuildDefaultTrue,
+ "system/core/libsystem": Bp2BuildDefaultTrueRecursively,
+ "system/core/libutils": Bp2BuildDefaultTrueRecursively,
+ "system/core/libvndksupport": Bp2BuildDefaultTrueRecursively,
+ "system/core/property_service/libpropertyinfoparser": Bp2BuildDefaultTrueRecursively,
+ "system/core/property_service/libpropertyinfoserializer": Bp2BuildDefaultTrueRecursively,
+ "system/libartpalette": Bp2BuildDefaultTrueRecursively,
+ "system/libbase": Bp2BuildDefaultTrueRecursively,
+ "system/libfmq": Bp2BuildDefaultTrue,
+ "system/libhwbinder": Bp2BuildDefaultTrueRecursively,
+ "system/libprocinfo": Bp2BuildDefaultTrue,
+ "system/libziparchive": Bp2BuildDefaultTrueRecursively,
+ "system/logging/liblog": Bp2BuildDefaultTrueRecursively,
+ "system/media/audio": Bp2BuildDefaultTrueRecursively,
+ "system/memory/libion": Bp2BuildDefaultTrueRecursively,
+ "system/memory/libmemunreachable": Bp2BuildDefaultTrueRecursively,
+ "system/sepolicy/apex": Bp2BuildDefaultTrueRecursively,
+ "system/timezone/apex": Bp2BuildDefaultTrueRecursively,
+ "system/timezone/output_data": Bp2BuildDefaultTrueRecursively,
+ "system/tools/sysprop": Bp2BuildDefaultTrue,
+ "system/unwinding/libunwindstack": Bp2BuildDefaultTrueRecursively,
+ "tools/apksig": Bp2BuildDefaultTrue,
+ "tools/platform-compat/java/android/compat": Bp2BuildDefaultTrueRecursively,
}
Bp2buildKeepExistingBuildFile = map[string]bool{
@@ -280,39 +284,49 @@
"flatbuffer_headers",
"gemmlowp_headers",
"gl_headers",
+ "libandroid_runtime_lazy",
"libandroid_runtime_vm_headers",
"libaudioclient_aidl_conversion_util",
"libaudioutils_fixedfft",
+ "libbinder_headers",
"libbinder_headers_platform_shared",
"libbluetooth-types-header",
+ "libbufferhub_headers",
+ "libcodec2",
"libcodec2_headers",
"libcodec2_internal",
"libdmabufheap",
+ "libdvr_headers",
"libgsm",
"libgui_bufferqueue_sources",
+ "libhardware",
"libhardware_headers",
+ "libincfs_headers",
"libnativeloader-headers",
"libnativewindow_headers",
"libneuralnetworks_headers",
"libopus",
+ "libpdx_headers",
"libprocpartition",
+ "libruy_static",
"libserviceutils",
- "libstagefright_amrnb_common",
- "libstagefright_amrwbdec",
"libstagefright_enc_common",
"libstagefright_foundation_headers",
"libstagefright_headers",
- "libstagefright_m4vh263dec",
- "libstagefright_m4vh263enc",
- "libstagefright_mp3dec_headers",
+ "libsurfaceflinger_headers",
"libsync",
"libtextclassifier_hash_headers",
"libtextclassifier_hash_static",
+ "libtflite_kernel_utils",
+ "libtinyxml2",
"libui-types",
+ "libui_headers",
"libvorbisidec",
"media_ndk_headers",
+ "media_plugin_headers",
"mediaswcodec.policy",
"mediaswcodec.xml",
+ "philox_random",
"philox_random_headers",
"server_configurable_flags",
"tensorflow_headers",
@@ -361,10 +375,13 @@
"gen-kotlin-build-file.py", // TODO(b/198619163) module has same name as source
"libgtest_ndk_c++", "libgtest_main_ndk_c++", // TODO(b/201816222): Requires sdk_version support.
"linkerconfig", "mdnsd", // TODO(b/202876379): has arch-variant static_executable
- "linker", // TODO(b/228316882): cc_binary uses link_crt
- "libdebuggerd", // TODO(b/228314770): support product variable-specific header_libs
- "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
- "apexer_test", // Requires aapt2
+ "linker", // TODO(b/228316882): cc_binary uses link_crt
+ "libdebuggerd", // TODO(b/228314770): support product variable-specific header_libs
+ "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
+ "libspeexresampler", // TODO(b/231995978): Filter out unknown cflags
+ "libjpeg", "libvpx", // TODO(b/233948256): Convert .asm files
+ "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",
@@ -383,6 +400,9 @@
"prebuilt_platform-robolectric-4.4-prebuilt", // aosp/1999250, needs .aar support in Jars
"prebuilt_platform-robolectric-4.5.1-prebuilt", // aosp/1999250, needs .aar support in Jars
+ // proto support
+ "libstats_proto_host", // TODO(b/236055697): handle protos from other packages
+
// path property for filegroups
"conscrypt", // TODO(b/210751803), we don't handle path property for filegroups
"conscrypt-for-host", // TODO(b/210751803), we don't handle path property for filegroups
@@ -451,9 +471,11 @@
"stats-log-api-gen", // depends on unconverted modules: libstats_proto_host
"statslog.cpp", "statslog.h", "statslog.rs", // depends on unconverted modules: stats-log-api-gen
"statslog_art.cpp", "statslog_art.h", "statslog_header.rs", // depends on unconverted modules: stats-log-api-gen
- "timezone-host", // depends on unconverted modules: art.module.api.annotations
- "truth-host-prebuilt", // depends on unconverted modules: truth-prebuilt
- "truth-prebuilt", // depends on unconverted modules: asm-7.0, guava
+ "timezone-host", // depends on unconverted modules: art.module.api.annotations
+ "truth-host-prebuilt", // depends on unconverted modules: truth-prebuilt
+ "truth-prebuilt", // depends on unconverted modules: asm-7.0, guava
+ "libartbase-art-gtest", // depends on unconverted modules: libgtest_isolated, libart, libart-compiler, libdexfile, libprofile
+ "libartbased-art-gtest", // depends on unconverted modules: libgtest_isolated, libartd, libartd-compiler, libdexfiled, libprofiled
// b/215723302; awaiting tz{data,_version} to then rename targets conflicting with srcs
"tzdata",
@@ -463,6 +485,8 @@
Bp2buildCcLibraryStaticOnlyList = []string{}
MixedBuildsDisabledList = []string{
+ "libruy_static", "libtflite_kernel_utils", // TODO(b/237315968); Depend on prebuilt stl, not from source
+
"art_libdexfile_dex_instruction_list_header", // breaks libart_mterp.armng, header not found
"libbrotli", // http://b/198585397, ld.lld: error: bionic/libc/arch-arm64/generic/bionic/memmove.S:95:(.text+0x10): relocation R_AARCH64_CONDBR19 out of range: -1404176 is not in [-1048576, 1048575]; references __memcpy
diff --git a/android/androidmk.go b/android/androidmk.go
index 6b675a6..d6fe06d 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -605,7 +605,7 @@
}
if len(base.noticeFiles) > 0 {
- a.SetString("LOCAL_NOTICE_FILE", strings.Join(base.noticeFiles.Strings(), " "))
+ a.AddStrings("LOCAL_NOTICE_FILE", strings.Join(base.noticeFiles.Strings(), " "))
}
if host {
@@ -945,7 +945,10 @@
return !module.Enabled() ||
module.commonProperties.HideFromMake ||
// Make does not understand LinuxBionic
- module.Os() == LinuxBionic
+ module.Os() == LinuxBionic ||
+ // Make does not understand LinuxMusl, except when we are building with USE_HOST_MUSL=true
+ // and all host binaries are LinuxMusl
+ (module.Os() == LinuxMusl && module.Target().HostCross)
}
// A utility func to format LOCAL_TEST_DATA outputs. See the comments on DataPath to understand how
diff --git a/android/apex.go b/android/apex.go
index 019efdd..c53ceb3 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -836,40 +836,6 @@
ctx.Phony(fmt.Sprintf("%s-depsinfo", ctx.ModuleName()), d.fullListPath, d.flatListPath)
}
-// TODO(b/158059172): remove minSdkVersion allowlist
-var minSdkVersionAllowlist = func(apiMap map[string]int) map[string]ApiLevel {
- list := make(map[string]ApiLevel, len(apiMap))
- for name, finalApiInt := range apiMap {
- list[name] = uncheckedFinalApiLevel(finalApiInt)
- }
- return list
-}(map[string]int{
- "androidx-constraintlayout_constraintlayout-solver-nodeps": 29,
- "apache-commons-compress": 29,
- "bouncycastle_ike_digests": 30,
- "brotli-java": 29,
- "flatbuffer_headers": 30,
- "gemmlowp_headers": 30,
- "ike-internals": 30,
- "libbrotli": 30,
- "libcrypto_static": 30,
- "libeigen": 30,
- "liblz4": 30,
- "libmdnssd": 30,
- "libprocpartition": 30,
- "libprotobuf-java-lite": 30,
- "libprotoutil": 30,
- "libtextclassifier_hash_headers": 30,
- "libtextclassifier_hash_static": 30,
- "libtflite_kernel_utils": 30,
- "libzstd": 30,
- "net-utils-framework-common": 29,
- "philox_random_headers": 30,
- "philox_random": 30,
- "tensorflow_headers": 30,
- "xz-java": 29,
-})
-
// Function called while walking an APEX's payload dependencies.
//
// Return true if the `to` module should be visited, false otherwise.
@@ -921,15 +887,13 @@
}
if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil {
toName := ctx.OtherModuleName(to)
- if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver.GreaterThan(minSdkVersion) {
- ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v."+
- "\n\nDependency path: %s\n\n"+
- "Consider adding 'min_sdk_version: %q' to %q",
- minSdkVersion, ctx.ModuleName(), err.Error(),
- ctx.GetPathString(false),
- minSdkVersion, toName)
- return false
- }
+ ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v."+
+ "\n\nDependency path: %s\n\n"+
+ "Consider adding 'min_sdk_version: %q' to %q",
+ minSdkVersion, ctx.ModuleName(), err.Error(),
+ ctx.GetPathString(false),
+ minSdkVersion, toName)
+ return false
}
return true
})
diff --git a/android/api_levels.go b/android/api_levels.go
index 41b338c..da50b19 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -54,6 +54,14 @@
isPreview bool
}
+func (this ApiLevel) FinalInt() int {
+ if this.IsPreview() {
+ panic("Requested a final int from a non-final ApiLevel")
+ } else {
+ return this.number
+ }
+}
+
func (this ApiLevel) FinalOrFutureInt() int {
if this.IsPreview() {
return FutureApiLevelInt
diff --git a/android/arch.go b/android/arch.go
index 382a7df..6acc8ad 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -655,7 +655,8 @@
prefer32 := os == Windows
// Determine the multilib selection for this module.
- multilib, extraMultilib := decodeMultilib(base, os)
+ ignorePrefer32OnDevice := mctx.Config().IgnorePrefer32OnDevice()
+ multilib, extraMultilib := decodeMultilib(base, os, ignorePrefer32OnDevice)
// Convert the multilib selection into a list of Targets.
targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
@@ -730,7 +731,7 @@
// multilib from the factory's call to InitAndroidArchModule if none was set. For modules that
// called InitAndroidMultiTargetsArchModule it always returns "common" for multilib, and returns
// the actual multilib in extraMultilib.
-func decodeMultilib(base *ModuleBase, os OsType) (multilib, extraMultilib string) {
+func decodeMultilib(base *ModuleBase, os OsType, ignorePrefer32OnDevice bool) (multilib, extraMultilib string) {
// First check the "android.compile_multilib" or "host.compile_multilib" properties.
switch os.Class {
case Device:
@@ -749,6 +750,13 @@
multilib = base.commonProperties.Default_multilib
}
+ // If a device is configured with multiple targets, this option
+ // force all device targets that prefer32 to be compiled only as
+ // the first target.
+ if ignorePrefer32OnDevice && os.Class == Device && (multilib == "prefer32" || multilib == "first_prefer32") {
+ multilib = "first"
+ }
+
if base.commonProperties.UseTargetVariants {
// Darwin has the concept of "universal binaries" which is implemented in Soong by
// building both x86_64 and arm64 variants, and having select module types know how to
@@ -1825,7 +1833,9 @@
for _, t := range targets {
if _, found := set[t.Os.String()]; !found {
set[t.Os.String()] = true
- ret = append(ret, commonTargetMap[t.Os.String()])
+ common := commonTargetMap[t.Os.String()]
+ common.HostCross = t.HostCross
+ ret = append(ret, common)
}
}
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 27255d1..3be9805 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -34,6 +34,21 @@
"android/soong/bazel"
)
+var (
+ writeBazelFile = pctx.AndroidStaticRule("bazelWriteFileRule", blueprint.RuleParams{
+ Command: `sed "s/\\\\n/\n/g" ${out}.rsp >${out}`,
+ Rspfile: "${out}.rsp",
+ RspfileContent: "${content}",
+ }, "content")
+ _ = pctx.HostBinToolVariable("bazelBuildRunfilesTool", "build-runfiles")
+ buildRunfilesRule = pctx.AndroidStaticRule("bazelBuildRunfiles", blueprint.RuleParams{
+ Command: "${bazelBuildRunfilesTool} ${in} ${outDir}",
+ Depfile: "",
+ Description: "",
+ CommandDeps: []string{"${bazelBuildRunfilesTool}"},
+ }, "outDir")
+)
+
func init() {
RegisterMixedBuildsMutator(InitRegistrationContext)
}
@@ -173,26 +188,26 @@
LabelToPythonBinary map[string]string
}
-func (m MockBazelContext) QueueBazelRequest(label string, requestType cqueryRequest, cfgKey configKey) {
+func (m MockBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
panic("unimplemented")
}
-func (m MockBazelContext) GetOutputFiles(label string, cfgKey configKey) ([]string, error) {
+func (m MockBazelContext) GetOutputFiles(label string, _ configKey) ([]string, error) {
result, _ := m.LabelToOutputFiles[label]
return result, nil
}
-func (m MockBazelContext) GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, error) {
+func (m MockBazelContext) GetCcInfo(label string, _ configKey) (cquery.CcInfo, error) {
result, _ := m.LabelToCcInfo[label]
return result, nil
}
-func (m MockBazelContext) GetPythonBinary(label string, cfgKey configKey) (string, error) {
+func (m MockBazelContext) GetPythonBinary(label string, _ configKey) (string, error) {
result, _ := m.LabelToPythonBinary[label]
return result, nil
}
-func (m MockBazelContext) InvokeBazel(config Config) error {
+func (m MockBazelContext) InvokeBazel(_ Config) error {
panic("unimplemented")
}
@@ -246,23 +261,23 @@
return "", fmt.Errorf("no bazel response found for %v", key)
}
-func (n noopBazelContext) QueueBazelRequest(label string, requestType cqueryRequest, cfgKey configKey) {
+func (n noopBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
panic("unimplemented")
}
-func (n noopBazelContext) GetOutputFiles(label string, cfgKey configKey) ([]string, error) {
+func (n noopBazelContext) GetOutputFiles(_ string, _ configKey) ([]string, error) {
panic("unimplemented")
}
-func (n noopBazelContext) GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, error) {
+func (n noopBazelContext) GetCcInfo(_ string, _ configKey) (cquery.CcInfo, error) {
panic("unimplemented")
}
-func (n noopBazelContext) GetPythonBinary(label string, cfgKey configKey) (string, error) {
+func (n noopBazelContext) GetPythonBinary(_ string, _ configKey) (string, error) {
panic("unimplemented")
}
-func (n noopBazelContext) InvokeBazel(config Config) error {
+func (n noopBazelContext) InvokeBazel(_ Config) error {
panic("unimplemented")
}
@@ -304,7 +319,7 @@
p := bazelPaths{
soongOutDir: c.soongOutDir,
}
- missingEnvVars := []string{}
+ var missingEnvVars []string
if len(c.Getenv("BAZEL_HOME")) > 1 {
p.homeDir = c.Getenv("BAZEL_HOME")
} else {
@@ -365,10 +380,8 @@
extraFlags []string
}
-func (r *mockBazelRunner) issueBazelCommand(paths *bazelPaths,
- runName bazel.RunName,
- command bazelCommand,
- extraFlags ...string) (string, string, error) {
+func (r *mockBazelRunner) issueBazelCommand(_ *bazelPaths, _ bazel.RunName,
+ command bazelCommand, extraFlags ...string) (string, string, error) {
r.commands = append(r.commands, command)
r.extraFlags = append(r.extraFlags, strings.Join(extraFlags, " "))
if ret, ok := r.bazelCommandResults[command]; ok {
@@ -396,26 +409,30 @@
command.command,
}
cmdFlags = append(cmdFlags, command.expression)
- cmdFlags = append(cmdFlags, "--profile="+shared.BazelMetricsFilename(paths, runName))
+ cmdFlags = append(cmdFlags,
+ // 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.
- cmdFlags = append(cmdFlags,
- fmt.Sprintf("--platforms=%s", "//build/bazel/platforms:android_target"))
- cmdFlags = append(cmdFlags,
- fmt.Sprintf("--extra_toolchains=%s", "//prebuilts/clang/host/linux-x86:all"))
- // This should be parameterized on the host OS, but let's restrict to linux
- // to keep things simple for now.
- cmdFlags = append(cmdFlags,
- fmt.Sprintf("--host_platform=%s", "//build/bazel/platforms:linux_x86_64"))
+ // 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("--platforms=%s", "//build/bazel/platforms:android_target"),
+ fmt.Sprintf("--extra_toolchains=%s", "//prebuilts/clang/host/linux-x86:all"),
- // Explicitly disable downloading rules (such as canonical C++ and Java rules) from the network.
- cmdFlags = append(cmdFlags, "--experimental_repository_disable_download")
+ // This should be parameterized on the host OS, but let's restrict to linux
+ // to keep things simple for now.
+ fmt.Sprintf("--host_platform=%s", "//build/bazel/platforms:linux_x86_64"),
+
+ // Explicitly disable downloading rules (such as canonical C++ and Java rules) from the network.
+ "--experimental_repository_disable_download",
+
+ // Suppress noise
+ "--ui_event_filters=-INFO",
+ "--noshow_progress")
cmdFlags = append(cmdFlags, extraFlags...)
bazelCmd := exec.Command(paths.bazelPath, cmdFlags...)
@@ -682,8 +699,6 @@
func (context *bazelContext) InvokeBazel(config Config) error {
context.results = make(map[cqueryKey]string)
- var cqueryOutput string
- var cqueryErr string
var err error
soongInjectionPath := absolutePath(context.paths.injectedFilesDir())
@@ -700,45 +715,27 @@
return err
}
}
- err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666)
- if err != nil {
+ if err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil {
return err
}
-
- err = ioutil.WriteFile(
- filepath.Join(mixedBuildsPath, "main.bzl"),
- context.mainBzlFileContents(), 0666)
- if err != nil {
+ if err = ioutil.WriteFile(filepath.Join(mixedBuildsPath, "main.bzl"), context.mainBzlFileContents(), 0666); err != nil {
return err
}
-
- err = ioutil.WriteFile(
- filepath.Join(mixedBuildsPath, "BUILD.bazel"),
- context.mainBuildFileContents(), 0666)
- if err != nil {
+ if err = ioutil.WriteFile(filepath.Join(mixedBuildsPath, "BUILD.bazel"), context.mainBuildFileContents(), 0666); err != nil {
return err
}
cqueryFileRelpath := filepath.Join(context.paths.injectedFilesDir(), "buildroot.cquery")
- err = ioutil.WriteFile(
- absolutePath(cqueryFileRelpath),
- context.cqueryStarlarkFileContents(), 0666)
- if err != nil {
+ if err = ioutil.WriteFile(absolutePath(cqueryFileRelpath), context.cqueryStarlarkFileContents(), 0666); err != nil {
return err
}
- buildrootLabel := "@soong_injection//mixed_builds:buildroot"
- cqueryOutput, cqueryErr, err = context.issueBazelCommand(
- context.paths,
- bazel.CqueryBuildRootRunName,
- bazelCommand{"cquery", fmt.Sprintf("deps(%s, 2)", buildrootLabel)},
- "--output=starlark",
- "--starlark:file="+absolutePath(cqueryFileRelpath))
- err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"),
- []byte(cqueryOutput), 0666)
+ const buildrootLabel = "@soong_injection//mixed_builds:buildroot"
+ cqueryCmd := bazelCommand{"cquery", fmt.Sprintf("deps(%s, 2)", buildrootLabel)}
+ cqueryOutput, cqueryErr, err := context.issueBazelCommand(context.paths, bazel.CqueryBuildRootRunName, cqueryCmd,
+ "--output=starlark", "--starlark:file="+absolutePath(cqueryFileRelpath))
if err != nil {
- return err
+ err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"), []byte(cqueryOutput), 0666)
}
-
if err != nil {
return err
}
@@ -750,7 +747,6 @@
cqueryResults[splitLine[0]] = splitLine[1]
}
}
-
for val := range context.requests {
if cqueryResult, ok := cqueryResults[getCqueryId(val)]; ok {
context.results[val] = cqueryResult
@@ -762,37 +758,27 @@
// Issue an aquery command to retrieve action information about the bazel build tree.
//
- var aqueryOutput string
- var coverageFlags []string
+ // Use jsonproto instead of proto; actual proto parsing would require a dependency on Bazel's
+ // proto sources, which would add a number of unnecessary dependencies.
+ extraFlags := []string{"--output=jsonproto", "--include_file_write_contents"}
if Bool(config.productVariables.ClangCoverage) {
- coverageFlags = append(coverageFlags, "--collect_code_coverage")
- if len(config.productVariables.NativeCoveragePaths) > 0 ||
- len(config.productVariables.NativeCoverageExcludePaths) > 0 {
- includePaths := JoinWithPrefixAndSeparator(config.productVariables.NativeCoveragePaths, "+", ",")
- excludePaths := JoinWithPrefixAndSeparator(config.productVariables.NativeCoverageExcludePaths, "-", ",")
- if len(includePaths) > 0 && len(excludePaths) > 0 {
- includePaths += ","
- }
- coverageFlags = append(coverageFlags, fmt.Sprintf(`--instrumentation_filter=%s`,
- includePaths+excludePaths))
+ extraFlags = append(extraFlags, "--collect_code_coverage")
+ paths := make([]string, 0, 2)
+ if p := config.productVariables.NativeCoveragePaths; len(p) > 0 {
+ paths = append(paths, JoinWithPrefixAndSeparator(p, "+", ","))
+ }
+ if p := config.productVariables.NativeCoverageExcludePaths; len(p) > 0 {
+ paths = append(paths, JoinWithPrefixAndSeparator(p, "-", ","))
+ }
+ if len(paths) > 0 {
+ extraFlags = append(extraFlags, "--instrumentation_filter="+strings.Join(paths, ","))
}
}
-
- extraFlags := append([]string{"--output=jsonproto"}, coverageFlags...)
-
- aqueryOutput, _, err = context.issueBazelCommand(
- context.paths,
- bazel.AqueryBuildRootRunName,
- bazelCommand{"aquery", fmt.Sprintf("deps(%s)", buildrootLabel)},
- // Use jsonproto instead of proto; actual proto parsing would require a dependency on Bazel's
- // proto sources, which would add a number of unnecessary dependencies.
- extraFlags...)
-
- if err != nil {
- return err
+ aqueryCmd := bazelCommand{"aquery", fmt.Sprintf("deps(%s)", buildrootLabel)}
+ if aqueryOutput, _, err := context.issueBazelCommand(context.paths, bazel.AqueryBuildRootRunName, aqueryCmd,
+ extraFlags...); err == nil {
+ context.buildStatements, context.depsets, err = bazel.AqueryBuildStatements([]byte(aqueryOutput))
}
-
- context.buildStatements, context.depsets, err = bazel.AqueryBuildStatements([]byte(aqueryOutput))
if err != nil {
return err
}
@@ -800,12 +786,8 @@
// 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.paths,
- bazel.BazelBuildPhonyRootRunName,
- bazelCommand{"build", "@soong_injection//mixed_builds:phonyroot"})
-
- if err != nil {
+ buildCmd := bazelCommand{"build", "@soong_injection//mixed_builds:phonyroot"}
+ if _, _, err = context.issueBazelCommand(context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd); err != nil {
return err
}
@@ -874,19 +856,56 @@
executionRoot := path.Join(ctx.Config().BazelContext.OutputBase(), "execroot", "__main__")
bazelOutDir := path.Join(executionRoot, "bazel-out")
for index, buildStatement := range ctx.Config().BazelContext.BuildStatementsToRegister() {
- if len(buildStatement.Command) < 1 {
+ if len(buildStatement.Command) > 0 {
+ rule := NewRuleBuilder(pctx, ctx)
+ createCommand(rule.Command(), buildStatement, executionRoot, bazelOutDir, ctx)
+ desc := fmt.Sprintf("%s: %s", buildStatement.Mnemonic, buildStatement.OutputPaths)
+ rule.Build(fmt.Sprintf("bazel %d", index), desc)
+ continue
+ }
+ // Certain actions returned by aquery (for instance FileWrite) do not contain a command
+ // and thus require special treatment. If BuildStatement were an interface implementing
+ // buildRule(ctx) function, the code here would just call it.
+ // Unfortunately, the BuildStatement is defined in
+ // the 'bazel' package, which cannot depend on 'android' package where ctx is defined,
+ // because this would cause circular dependency. So, until we move aquery processing
+ // to the 'android' package, we need to handle special cases here.
+ if buildStatement.Mnemonic == "FileWrite" || buildStatement.Mnemonic == "SourceSymlinkManifest" {
+ // Pass file contents as the value of the rule's "content" argument.
+ // Escape newlines and $ in the contents (the action "writeBazelFile" restores "\\n"
+ // back to the newline, and Ninja reads $$ as $.
+ escaped := strings.ReplaceAll(strings.ReplaceAll(buildStatement.FileContents, "\n", "\\n"),
+ "$", "$$")
+ ctx.Build(pctx, BuildParams{
+ Rule: writeBazelFile,
+ Output: PathForBazelOut(ctx, buildStatement.OutputPaths[0]),
+ Description: fmt.Sprintf("%s %s", buildStatement.Mnemonic, buildStatement.OutputPaths[0]),
+ Args: map[string]string{
+ "content": escaped,
+ },
+ })
+ } else if buildStatement.Mnemonic == "SymlinkTree" {
+ // build-runfiles arguments are the manifest file and the target directory
+ // where it creates the symlink tree according to this manifest (and then
+ // writes the MANIFEST file to it).
+ outManifest := PathForBazelOut(ctx, buildStatement.OutputPaths[0])
+ outManifestPath := outManifest.String()
+ if !strings.HasSuffix(outManifestPath, "MANIFEST") {
+ panic("the base name of the symlink tree action should be MANIFEST, got " + outManifestPath)
+ }
+ outDir := filepath.Dir(outManifestPath)
+ ctx.Build(pctx, BuildParams{
+ Rule: buildRunfilesRule,
+ Output: outManifest,
+ Inputs: []Path{PathForBazelOut(ctx, buildStatement.InputPaths[0])},
+ Description: "symlink tree for " + outDir,
+ Args: map[string]string{
+ "outDir": outDir,
+ },
+ })
+ } else {
panic(fmt.Sprintf("unhandled build statement: %v", buildStatement))
}
- rule := NewRuleBuilder(pctx, ctx)
- createCommand(rule.Command(), buildStatement, executionRoot, bazelOutDir, ctx)
- // This is required to silence warnings pertaining to unexpected timestamps. Particularly,
- // some Bazel builtins (such as files in the bazel_tools directory) have far-future
- // timestamps. Without restat, Ninja would emit warnings that the input files of a
- // build statement have later timestamps than the outputs.
- rule.Restat()
-
- desc := fmt.Sprintf("%s: %s", buildStatement.Mnemonic, buildStatement.OutputPaths)
- rule.Build(fmt.Sprintf("bazel %d", index), desc)
}
}
@@ -899,7 +918,7 @@
if len(buildStatement.OutputPaths) > 0 {
cmd.Text("rm -f")
for _, outputPath := range buildStatement.OutputPaths {
- cmd.Text(outputPath)
+ cmd.Text(fmt.Sprintf("'%s'", outputPath))
}
cmd.Text("&&")
}
@@ -949,8 +968,15 @@
func getConfigString(key cqueryKey) string {
arch := key.configKey.arch
if len(arch) == 0 || arch == "common" {
- // Use host platform, which is currently hardcoded to be x86_64.
- arch = "x86_64"
+ if key.configKey.osType.Class == Device {
+ // For the generic Android, the expected result is "target|android", which
+ // corresponds to the product_variable_config named "android_target" in
+ // build/bazel/platforms/BUILD.bazel.
+ arch = "target"
+ } else {
+ // Use host platform, which is currently hardcoded to be x86_64.
+ arch = "x86_64"
+ }
}
osName := key.configKey.osType.Name
if len(osName) == 0 || osName == "common_os" || osName == "linux_glibc" {
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index 935ce4e..ec2541b 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -65,13 +65,9 @@
var testCases = []testCase{
{`
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }, {
- "id": 2,
- "pathFragmentId": 2
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 },
+ { "id": 2, "pathFragmentId": 2 }],
"actions": [{
"targetId": 1,
"actionKey": "x",
@@ -81,28 +77,18 @@
"outputIds": [1],
"primaryOutputId": 1
}],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [1, 2]
- }],
- "pathFragments": [{
- "id": 1,
- "label": "one"
- }, {
- "id": 2,
- "label": "two"
- }]
+ "depSetOfFiles": [
+ { "id": 1, "directArtifactIds": [1, 2] }],
+ "pathFragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" }]
}`,
- "cd 'er' && rm -f one && touch foo",
+ "cd 'test/exec_root' && rm -f 'one' && touch foo",
}, {`
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 10
- }, {
- "id": 2,
- "pathFragmentId": 20
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 10 },
+ { "id": 2, "pathFragmentId": 20 }],
"actions": [{
"targetId": 100,
"actionKey": "x",
@@ -111,41 +97,33 @@
"outputIds": [1, 2],
"primaryOutputId": 1
}],
- "pathFragments": [{
- "id": 10,
- "label": "one",
- "parentId": 30
- }, {
- "id": 20,
- "label": "one.d",
- "parentId": 30
- }, {
- "id": 30,
- "label": "parent"
- }]
+ "pathFragments": [
+ { "id": 10, "label": "one", "parentId": 30 },
+ { "id": 20, "label": "one.d", "parentId": 30 },
+ { "id": 30, "label": "parent" }]
}`,
- `cd 'er' && rm -f parent/one && bogus command && sed -i'' -E 's@(^|\s|")bazel-out/@\1bo/@g' 'parent/one.d'`,
+ `cd 'test/exec_root' && rm -f 'parent/one' && bogus command && sed -i'' -E 's@(^|\s|")bazel-out/@\1test/bazel_out/@g' 'parent/one.d'`,
},
}
- for _, testCase := range testCases {
+ for i, testCase := range testCases {
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: testCase.input})
err := bazelContext.InvokeBazel(testConfig)
if err != nil {
- t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
+ t.Fatalf("testCase #%d: did not expect error invoking Bazel, but got %s", i+1, err)
}
got := bazelContext.BuildStatementsToRegister()
if want := 1; len(got) != want {
- t.Errorf("expected %d registered build statements, but got %#v", want, got)
+ t.Fatalf("expected %d registered build statements, but got %#v", want, got)
}
cmd := RuleBuilderCommand{}
- createCommand(&cmd, got[0], "er", "bo", PathContextForTesting(TestConfig("out", nil, "", nil)))
- if actual := cmd.buf.String(); testCase.command != actual {
- t.Errorf("expected: [%s], actual: [%s]", testCase.command, actual)
+ createCommand(&cmd, got[0], "test/exec_root", "test/bazel_out", PathContextForTesting(TestConfig("out", nil, "", nil)))
+ if actual, expected := cmd.buf.String(), testCase.command; expected != actual {
+ t.Errorf("expected: [%s], actual: [%s]", expected, actual)
}
}
}
diff --git a/android/config.go b/android/config.go
index 47346fc..a5337d0 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1725,6 +1725,10 @@
return c.config.productVariables.GenerateAidlNdkPlatformBackend
}
+func (c *config) IgnorePrefer32OnDevice() bool {
+ return c.productVariables.IgnorePrefer32OnDevice
+}
+
// The ConfiguredJarList struct provides methods for handling a list of (apex, jar) pairs.
// Such lists are used in the build system for things like bootclasspath jars or system server jars.
// The apex part is either an apex name, or a special names "platform" or "system_ext". Jar is a
diff --git a/android/module.go b/android/module.go
index 2925081..7173c0d 100644
--- a/android/module.go
+++ b/android/module.go
@@ -2328,14 +2328,6 @@
}
if optPath.Valid() {
m.noticeFiles = append(m.noticeFiles, optPath.Path())
- } else {
- for _, notice = range []string{"LICENSE", "LICENCE", "NOTICE"} {
- noticePath := filepath.Join(ctx.ModuleDir(), notice)
- optPath = ExistentPathForSource(ctx, noticePath)
- if optPath.Valid() {
- m.noticeFiles = append(m.noticeFiles, optPath.Path())
- }
- }
}
licensesPropertyFlattener(ctx)
diff --git a/android/sdk.go b/android/sdk.go
index 2dc0bd7..a71f7f2 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -661,6 +661,10 @@
// an Android.bp file.
RequiresBpProperty() bool
+ // SupportedBuildReleases returns the string representation of a set of target build releases that
+ // support this member type.
+ SupportedBuildReleases() string
+
// UsableWithSdkAndSdkSnapshot returns true if the member type supports the sdk/sdk_snapshot,
// false otherwise.
UsableWithSdkAndSdkSnapshot() bool
@@ -673,6 +677,10 @@
// SupportedLinkages returns the names of the linkage variants supported by this module.
SupportedLinkages() []string
+ // ArePrebuiltsRequired returns true if prebuilts are required in the sdk snapshot, false
+ // otherwise.
+ ArePrebuiltsRequired() bool
+
// AddDependencies adds dependencies from the SDK module to all the module variants the member
// type contributes to the SDK. `names` is the list of module names given in the member type
// property (as returned by SdkPropertyName()) in the SDK module. The exact set of variants
@@ -773,7 +781,17 @@
// property to be specifiable in an Android.bp file.
BpPropertyNotRequired bool
- SupportsSdk bool
+ // The name of the first targeted build release.
+ //
+ // If not specified then it is assumed to be available on all targeted build releases.
+ SupportedBuildReleaseSpecification string
+
+ // Set to true if this must be usable with the sdk/sdk_snapshot module types. Otherwise, it will
+ // only be usable with module_exports/module_exports_snapshots module types.
+ SupportsSdk bool
+
+ // Set to true if prebuilt host artifacts of this member may be specific to the host OS. Only
+ // applicable to modules where HostSupported() is true.
HostOsDependent bool
// When set to true UseSourceModuleTypeInSnapshot indicates that the member type creates a source
@@ -781,6 +799,11 @@
// code from automatically adding a prefer: true flag.
UseSourceModuleTypeInSnapshot bool
+ // Set to proptools.BoolPtr(false) if this member does not generate prebuilts but is only provided
+ // to allow the sdk to gather members from this member's dependencies. If not specified then
+ // defaults to true.
+ PrebuiltsRequired *bool
+
// The list of supported traits.
Traits []SdkMemberTrait
}
@@ -793,6 +816,10 @@
return !b.BpPropertyNotRequired
}
+func (b *SdkMemberTypeBase) SupportedBuildReleases() string {
+ return b.SupportedBuildReleaseSpecification
+}
+
func (b *SdkMemberTypeBase) UsableWithSdkAndSdkSnapshot() bool {
return b.SupportsSdk
}
@@ -801,6 +828,10 @@
return b.HostOsDependent
}
+func (b *SdkMemberTypeBase) ArePrebuiltsRequired() bool {
+ return proptools.BoolDefault(b.PrebuiltsRequired, true)
+}
+
func (b *SdkMemberTypeBase) UsesSourceModuleTypeInSnapshot() bool {
return b.UseSourceModuleTypeInSnapshot
}
@@ -954,6 +985,10 @@
// RequiresTrait returns true if this member is expected to provide the specified trait.
RequiresTrait(trait SdkMemberTrait) bool
+
+ // IsTargetBuildBeforeTiramisu return true if the target build release for which this snapshot is
+ // being generated is before Tiramisu, i.e. S.
+ IsTargetBuildBeforeTiramisu() bool
}
// ExportedComponentsInfo contains information about the components that this module exports to an
diff --git a/android/sdk_version.go b/android/sdk_version.go
index 2004c92..c188c48 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -28,6 +28,9 @@
// MinSdkVersion returns SdkSpec that corresponds to the min_sdk_version property of the current module,
// or from sdk_version if it is not set.
MinSdkVersion(ctx EarlyModuleContext) SdkSpec
+ // ReplaceMaxSdkVersionPlaceholder returns SdkSpec 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,
// or from sdk_version if it is not set.
TargetSdkVersion(ctx EarlyModuleContext) SdkSpec
diff --git a/android/variable.go b/android/variable.go
index 50fc304..874b69d 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -447,6 +447,8 @@
SepolicyFreezeTestExtraPrebuiltDirs []string `json:",omitempty"`
GenerateAidlNdkPlatformBackend bool `json:",omitempty"`
+
+ IgnorePrefer32OnDevice bool `json:",omitempty"`
}
func boolPtr(v bool) *bool {
diff --git a/apex/Android.bp b/apex/Android.bp
index fcdf8e6..6533c61 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -23,6 +23,7 @@
srcs: [
"androidmk.go",
"apex.go",
+ "apex_sdk_member.go",
"apex_singleton.go",
"builder.go",
"constants.go",
diff --git a/apex/apex.go b/apex/apex.go
index 7e913e8..7b6707c 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -606,6 +606,18 @@
// replacement. This is needed because some prebuilt modules do not provide all the information
// needed by the apex.
sourceOnly bool
+
+ // If not-nil and an APEX is a member of an SDK then dependencies of that APEX with this tag will
+ // also be added as exported members of that SDK.
+ memberType android.SdkMemberType
+}
+
+func (d *dependencyTag) SdkMemberType(_ android.Module) android.SdkMemberType {
+ return d.memberType
+}
+
+func (d *dependencyTag) ExportMember() bool {
+ return true
}
func (d *dependencyTag) String() string {
@@ -617,6 +629,7 @@
}
var _ android.ReplaceSourceWithPrebuilt = &dependencyTag{}
+var _ android.SdkMemberDependencyTag = &dependencyTag{}
var (
androidAppTag = &dependencyTag{name: "androidApp", payload: true}
@@ -624,8 +637,8 @@
certificateTag = &dependencyTag{name: "certificate"}
executableTag = &dependencyTag{name: "executable", payload: true}
fsTag = &dependencyTag{name: "filesystem", payload: true}
- bcpfTag = &dependencyTag{name: "bootclasspathFragment", payload: true, sourceOnly: true}
- sscpfTag = &dependencyTag{name: "systemserverclasspathFragment", payload: true, sourceOnly: true}
+ bcpfTag = &dependencyTag{name: "bootclasspathFragment", payload: true, sourceOnly: true, memberType: java.BootclasspathFragmentSdkMemberType}
+ sscpfTag = &dependencyTag{name: "systemserverclasspathFragment", payload: true, sourceOnly: true, memberType: java.SystemServerClasspathFragmentSdkMemberType}
compatConfigTag = &dependencyTag{name: "compatConfig", payload: true, sourceOnly: true}
javaLibTag = &dependencyTag{name: "javaLib", payload: true}
jniLibTag = &dependencyTag{name: "jniLib", payload: true}
@@ -1338,7 +1351,7 @@
var _ android.DepIsInSameApex = (*apexBundle)(nil)
// Implements android.DepInInSameApex
-func (a *apexBundle) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+func (a *apexBundle) DepIsInSameApex(_ android.BaseModuleContext, _ android.Module) bool {
// direct deps of an APEX bundle are all part of the APEX bundle
// TODO(jiyong): shouldn't we look into the payload field of the dependencyTag?
return true
@@ -1474,7 +1487,7 @@
}
// Then follow the global setting
- globalSanitizerNames := []string{}
+ var globalSanitizerNames []string
if a.Host() {
globalSanitizerNames = config.SanitizeHost()
} else {
@@ -1790,6 +1803,382 @@
}
}
+type visitorContext struct {
+ // all the files that will be included in this APEX
+ filesInfo []apexFile
+
+ // native lib dependencies
+ provideNativeLibs []string
+ requireNativeLibs []string
+
+ handleSpecialLibs bool
+}
+
+func (vctx *visitorContext) normalizeFileInfo() {
+ encountered := make(map[string]apexFile)
+ for _, f := range vctx.filesInfo {
+ dest := filepath.Join(f.installDir, f.builtFile.Base())
+ if e, ok := encountered[dest]; !ok {
+ encountered[dest] = f
+ } else {
+ // If a module is directly included and also transitively depended on
+ // consider it as directly included.
+ e.transitiveDep = e.transitiveDep && f.transitiveDep
+ encountered[dest] = e
+ }
+ }
+ vctx.filesInfo = vctx.filesInfo[:0]
+ for _, v := range encountered {
+ vctx.filesInfo = append(vctx.filesInfo, v)
+ }
+ sort.Slice(vctx.filesInfo, func(i, j int) bool {
+ // Sort by destination path so as to ensure consistent ordering even if the source of the files
+ // changes.
+ return vctx.filesInfo[i].path() < vctx.filesInfo[j].path()
+ })
+}
+
+func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext, child, parent blueprint.Module) bool {
+ depTag := ctx.OtherModuleDependencyTag(child)
+ if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
+ return false
+ }
+ if mod, ok := child.(android.Module); ok && !mod.Enabled() {
+ return false
+ }
+ depName := ctx.OtherModuleName(child)
+ if _, isDirectDep := parent.(*apexBundle); isDirectDep {
+ switch depTag {
+ case sharedLibTag, jniLibTag:
+ isJniLib := depTag == jniLibTag
+ switch ch := child.(type) {
+ case *cc.Module:
+ fi := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs)
+ fi.isJniLib = isJniLib
+ vctx.filesInfo = append(vctx.filesInfo, fi)
+ // Collect the list of stub-providing libs except:
+ // - VNDK libs are only for vendors
+ // - bootstrap bionic libs are treated as provided by system
+ if ch.HasStubsVariants() && !a.vndkApex && !cc.InstallToBootstrap(ch.BaseModuleName(), ctx.Config()) {
+ vctx.provideNativeLibs = append(vctx.provideNativeLibs, fi.stem())
+ }
+ return true // track transitive dependencies
+ case *rust.Module:
+ fi := apexFileForRustLibrary(ctx, ch)
+ fi.isJniLib = isJniLib
+ vctx.filesInfo = append(vctx.filesInfo, fi)
+ return true // track transitive dependencies
+ default:
+ propertyName := "native_shared_libs"
+ if isJniLib {
+ propertyName = "jni_libs"
+ }
+ ctx.PropertyErrorf(propertyName, "%q is not a cc_library or cc_library_shared module", depName)
+ }
+ case executableTag:
+ switch ch := child.(type) {
+ case *cc.Module:
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, ch))
+ return true // track transitive dependencies
+ case *python.Module:
+ if ch.HostToolPath().Valid() {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForPyBinary(ctx, ch))
+ }
+ case bootstrap.GoBinaryTool:
+ if a.Host() {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForGoBinary(ctx, depName, ch))
+ }
+ case *rust.Module:
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForRustExecutable(ctx, ch))
+ return true // track transitive dependencies
+ default:
+ ctx.PropertyErrorf("binaries",
+ "%q is neither cc_binary, rust_binary, (embedded) py_binary, (host) blueprint_go_binary, nor (host) bootstrap_go_binary", depName)
+ }
+ case shBinaryTag:
+ if csh, ok := child.(*sh.ShBinary); ok {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForShBinary(ctx, csh))
+ } else {
+ ctx.PropertyErrorf("sh_binaries", "%q is not a sh_binary module", depName)
+ }
+ case bcpfTag:
+ bcpfModule, ok := child.(*java.BootclasspathFragmentModule)
+ if !ok {
+ ctx.PropertyErrorf("bootclasspath_fragments", "%q is not a bootclasspath_fragment module", depName)
+ return false
+ }
+
+ vctx.filesInfo = append(vctx.filesInfo, apexBootclasspathFragmentFiles(ctx, child)...)
+ for _, makeModuleName := range bcpfModule.BootImageDeviceInstallMakeModules() {
+ a.requiredDeps = append(a.requiredDeps, makeModuleName)
+ }
+ return true
+ case sscpfTag:
+ if _, ok := child.(*java.SystemServerClasspathModule); !ok {
+ ctx.PropertyErrorf("systemserverclasspath_fragments",
+ "%q is not a systemserverclasspath_fragment module", depName)
+ return false
+ }
+ if af := apexClasspathFragmentProtoFile(ctx, child); af != nil {
+ vctx.filesInfo = append(vctx.filesInfo, *af)
+ }
+ return true
+ case javaLibTag:
+ switch child.(type) {
+ case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport, *java.Import:
+ af := apexFileForJavaModule(ctx, child.(javaModule))
+ if !af.ok() {
+ ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
+ return false
+ }
+ vctx.filesInfo = append(vctx.filesInfo, af)
+ return true // track transitive dependencies
+ default:
+ ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
+ }
+ case androidAppTag:
+ switch ap := child.(type) {
+ case *java.AndroidApp:
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForAndroidApp(ctx, ap))
+ return true // track transitive dependencies
+ case *java.AndroidAppImport:
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForAndroidApp(ctx, ap))
+ case *java.AndroidTestHelperApp:
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForAndroidApp(ctx, ap))
+ case *java.AndroidAppSet:
+ appDir := "app"
+ if ap.Privileged() {
+ appDir = "priv-app"
+ }
+ // TODO(b/224589412, b/226559955): Ensure that the dirname is
+ // suffixed so that PackageManager correctly invalidates the
+ // existing installed apk in favour of the new APK-in-APEX.
+ // See bugs for more information.
+ appDirName := filepath.Join(appDir, ap.BaseModuleName()+"@"+sanitizedBuildIdForPath(ctx))
+ af := newApexFile(ctx, ap.OutputFile(), ap.BaseModuleName(), appDirName, appSet, ap)
+ af.certificate = java.PresignedCertificate
+ vctx.filesInfo = append(vctx.filesInfo, af)
+ default:
+ ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
+ }
+ case rroTag:
+ if rro, ok := child.(java.RuntimeResourceOverlayModule); ok {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForRuntimeResourceOverlay(ctx, rro))
+ } else {
+ ctx.PropertyErrorf("rros", "%q is not an runtime_resource_overlay module", depName)
+ }
+ case bpfTag:
+ if bpfProgram, ok := child.(bpf.BpfModule); ok {
+ filesToCopy, _ := bpfProgram.OutputFiles("")
+ apex_sub_dir := bpfProgram.SubDir()
+ for _, bpfFile := range filesToCopy {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForBpfProgram(ctx, bpfFile, apex_sub_dir, bpfProgram))
+ }
+ } else {
+ ctx.PropertyErrorf("bpfs", "%q is not a bpf module", depName)
+ }
+ case fsTag:
+ if fs, ok := child.(filesystem.Filesystem); ok {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForFilesystem(ctx, fs.OutputPath(), fs))
+ } else {
+ ctx.PropertyErrorf("filesystems", "%q is not a filesystem module", depName)
+ }
+ case prebuiltTag:
+ if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
+ } else {
+ ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
+ }
+ case compatConfigTag:
+ if compatConfig, ok := child.(java.PlatformCompatConfigIntf); ok {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForCompatConfig(ctx, compatConfig, depName))
+ } else {
+ ctx.PropertyErrorf("compat_configs", "%q is not a platform_compat_config module", depName)
+ }
+ case testTag:
+ if ccTest, ok := child.(*cc.Module); ok {
+ if ccTest.IsTestPerSrcAllTestsVariation() {
+ // Multiple-output test module (where `test_per_src: true`).
+ //
+ // `ccTest` is the "" ("all tests") variation of a `test_per_src` module.
+ // We do not add this variation to `filesInfo`, as it has no output;
+ // however, we do add the other variations of this module as indirect
+ // dependencies (see below).
+ } else {
+ // Single-output test module (where `test_per_src: false`).
+ af := apexFileForExecutable(ctx, ccTest)
+ af.class = nativeTest
+ vctx.filesInfo = append(vctx.filesInfo, af)
+ }
+ return true // track transitive dependencies
+ } else {
+ ctx.PropertyErrorf("tests", "%q is not a cc module", depName)
+ }
+ case keyTag:
+ if key, ok := child.(*apexKey); ok {
+ a.privateKeyFile = key.privateKeyFile
+ a.publicKeyFile = key.publicKeyFile
+ } else {
+ ctx.PropertyErrorf("key", "%q is not an apex_key module", depName)
+ }
+ case certificateTag:
+ if dep, ok := child.(*java.AndroidAppCertificate); ok {
+ a.containerCertificateFile = dep.Certificate.Pem
+ a.containerPrivateKeyFile = dep.Certificate.Key
+ } else {
+ ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", depName)
+ }
+ case android.PrebuiltDepTag:
+ // If the prebuilt is force disabled, remember to delete the prebuilt file
+ // that might have been installed in the previous builds
+ if prebuilt, ok := child.(prebuilt); ok && prebuilt.isForceDisabled() {
+ a.prebuiltFileToDelete = prebuilt.InstallFilename()
+ }
+ }
+ return false
+ }
+
+ if a.vndkApex {
+ return false
+ }
+
+ // indirect dependencies
+ am, ok := child.(android.ApexModule)
+ if !ok {
+ return false
+ }
+ // We cannot use a switch statement on `depTag` here as the checked
+ // tags used below are private (e.g. `cc.sharedDepTag`).
+ if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) {
+ if ch, ok := child.(*cc.Module); ok {
+ if ch.UseVndk() && proptools.Bool(a.properties.Use_vndk_as_stable) && ch.IsVndk() {
+ vctx.requireNativeLibs = append(vctx.requireNativeLibs, ":vndk")
+ return false
+ }
+ af := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs)
+ af.transitiveDep = true
+
+ // Always track transitive dependencies for host.
+ if a.Host() {
+ vctx.filesInfo = append(vctx.filesInfo, af)
+ return true
+ }
+
+ abInfo := ctx.Provider(ApexBundleInfoProvider).(ApexBundleInfo)
+ if !abInfo.Contents.DirectlyInApex(depName) && (ch.IsStubs() || ch.HasStubsVariants()) {
+ // If the dependency is a stubs lib, don't include it in this APEX,
+ // but make sure that the lib is installed on the device.
+ // In case no APEX is having the lib, the lib is installed to the system
+ // partition.
+ //
+ // Always include if we are a host-apex however since those won't have any
+ // system libraries.
+ if !am.DirectlyInAnyApex() {
+ // we need a module name for Make
+ name := ch.ImplementationModuleNameForMake(ctx) + ch.Properties.SubName
+ if !android.InList(name, a.requiredDeps) {
+ a.requiredDeps = append(a.requiredDeps, name)
+ }
+ }
+ vctx.requireNativeLibs = append(vctx.requireNativeLibs, af.stem())
+ // Don't track further
+ return false
+ }
+
+ // If the dep is not considered to be in the same
+ // apex, don't add it to filesInfo so that it is not
+ // included in this APEX.
+ // TODO(jiyong): move this to at the top of the
+ // else-if clause for the indirect dependencies.
+ // Currently, that's impossible because we would
+ // like to record requiredNativeLibs even when
+ // DepIsInSameAPex is false. We also shouldn't do
+ // this for host.
+ //
+ // TODO(jiyong): explain why the same module is passed in twice.
+ // Switching the first am to parent breaks lots of tests.
+ if !android.IsDepInSameApex(ctx, am, am) {
+ return false
+ }
+
+ vctx.filesInfo = append(vctx.filesInfo, af)
+ return true // track transitive dependencies
+ } else if rm, ok := child.(*rust.Module); ok {
+ af := apexFileForRustLibrary(ctx, rm)
+ af.transitiveDep = true
+ vctx.filesInfo = append(vctx.filesInfo, af)
+ return true // track transitive dependencies
+ }
+ } else if cc.IsTestPerSrcDepTag(depTag) {
+ if ch, ok := child.(*cc.Module); ok {
+ af := apexFileForExecutable(ctx, ch)
+ // Handle modules created as `test_per_src` variations of a single test module:
+ // use the name of the generated test binary (`fileToCopy`) instead of the name
+ // of the original test module (`depName`, shared by all `test_per_src`
+ // variations of that module).
+ af.androidMkModuleName = filepath.Base(af.builtFile.String())
+ // these are not considered transitive dep
+ af.transitiveDep = false
+ vctx.filesInfo = append(vctx.filesInfo, af)
+ return true // track transitive dependencies
+ }
+ } else if cc.IsHeaderDepTag(depTag) {
+ // nothing
+ } else if java.IsJniDepTag(depTag) {
+ // Because APK-in-APEX embeds jni_libs transitively, we don't need to track transitive deps
+ } else if java.IsXmlPermissionsFileDepTag(depTag) {
+ if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
+ vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
+ }
+ } else if rust.IsDylibDepTag(depTag) {
+ if rustm, ok := child.(*rust.Module); ok && rustm.IsInstallableToApex() {
+ af := apexFileForRustLibrary(ctx, rustm)
+ af.transitiveDep = true
+ vctx.filesInfo = append(vctx.filesInfo, af)
+ return true // track transitive dependencies
+ }
+ } else if rust.IsRlibDepTag(depTag) {
+ // Rlib is statically linked, but it might have shared lib
+ // dependencies. Track them.
+ return true
+ } else if java.IsBootclasspathFragmentContentDepTag(depTag) {
+ // Add the contents of the bootclasspath fragment to the apex.
+ switch child.(type) {
+ case *java.Library, *java.SdkLibrary:
+ javaModule := child.(javaModule)
+ af := apexFileForBootclasspathFragmentContentModule(ctx, parent, javaModule)
+ if !af.ok() {
+ ctx.PropertyErrorf("bootclasspath_fragments",
+ "bootclasspath_fragment content %q is not configured to be compiled into dex", depName)
+ return false
+ }
+ vctx.filesInfo = append(vctx.filesInfo, af)
+ return true // track transitive dependencies
+ default:
+ ctx.PropertyErrorf("bootclasspath_fragments",
+ "bootclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child))
+ }
+ } else if java.IsSystemServerClasspathFragmentContentDepTag(depTag) {
+ // Add the contents of the systemserverclasspath fragment to the apex.
+ switch child.(type) {
+ case *java.Library, *java.SdkLibrary:
+ af := apexFileForJavaModule(ctx, child.(javaModule))
+ vctx.filesInfo = append(vctx.filesInfo, af)
+ return true // track transitive dependencies
+ default:
+ ctx.PropertyErrorf("systemserverclasspath_fragments",
+ "systemserverclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child))
+ }
+ } else if _, ok := depTag.(android.CopyDirectlyInAnyApexTag); ok {
+ // nothing
+ } else if depTag == android.DarwinUniversalVariantTag {
+ // nothing
+ } else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
+ ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName)
+ }
+ return false
+}
+
// Creates build rules for an APEX. It consists of the following major steps:
//
// 1) do some validity checks such as apex_available, min_sdk_version, etc.
@@ -1812,386 +2201,23 @@
////////////////////////////////////////////////////////////////////////////////////////////
// 2) traverse the dependency tree to collect apexFile structs from them.
- // all the files that will be included in this APEX
- var filesInfo []apexFile
-
- // native lib dependencies
- var provideNativeLibs []string
- var requireNativeLibs []string
-
- handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
-
// Collect the module directory for IDE info in java/jdeps.go.
a.modulePaths = append(a.modulePaths, ctx.ModuleDir())
// TODO(jiyong): do this using WalkPayloadDeps
// TODO(jiyong): make this clean!!!
- ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
- depTag := ctx.OtherModuleDependencyTag(child)
- if _, ok := depTag.(android.ExcludeFromApexContentsTag); ok {
- return false
- }
- if mod, ok := child.(android.Module); ok && !mod.Enabled() {
- return false
- }
- depName := ctx.OtherModuleName(child)
- if _, isDirectDep := parent.(*apexBundle); isDirectDep {
- switch depTag {
- case sharedLibTag, jniLibTag:
- isJniLib := depTag == jniLibTag
- if c, ok := child.(*cc.Module); ok {
- fi := apexFileForNativeLibrary(ctx, c, handleSpecialLibs)
- fi.isJniLib = isJniLib
- filesInfo = append(filesInfo, fi)
- // Collect the list of stub-providing libs except:
- // - VNDK libs are only for vendors
- // - bootstrap bionic libs are treated as provided by system
- if c.HasStubsVariants() && !a.vndkApex && !cc.InstallToBootstrap(c.BaseModuleName(), ctx.Config()) {
- provideNativeLibs = append(provideNativeLibs, fi.stem())
- }
- return true // track transitive dependencies
- } else if r, ok := child.(*rust.Module); ok {
- fi := apexFileForRustLibrary(ctx, r)
- fi.isJniLib = isJniLib
- filesInfo = append(filesInfo, fi)
- return true // track transitive dependencies
- } else {
- propertyName := "native_shared_libs"
- if isJniLib {
- propertyName = "jni_libs"
- }
- ctx.PropertyErrorf(propertyName, "%q is not a cc_library or cc_library_shared module", depName)
- }
- case executableTag:
- if cc, ok := child.(*cc.Module); ok {
- filesInfo = append(filesInfo, apexFileForExecutable(ctx, cc))
- return true // track transitive dependencies
- } else if py, ok := child.(*python.Module); ok && py.HostToolPath().Valid() {
- filesInfo = append(filesInfo, apexFileForPyBinary(ctx, py))
- } else if gb, ok := child.(bootstrap.GoBinaryTool); ok && a.Host() {
- filesInfo = append(filesInfo, apexFileForGoBinary(ctx, depName, gb))
- } else if rust, ok := child.(*rust.Module); ok {
- filesInfo = append(filesInfo, apexFileForRustExecutable(ctx, rust))
- return true // track transitive dependencies
- } else {
- ctx.PropertyErrorf("binaries", "%q is neither cc_binary, rust_binary, (embedded) py_binary, (host) blueprint_go_binary, nor (host) bootstrap_go_binary", depName)
- }
- case shBinaryTag:
- if sh, ok := child.(*sh.ShBinary); ok {
- filesInfo = append(filesInfo, apexFileForShBinary(ctx, sh))
- } else {
- ctx.PropertyErrorf("sh_binaries", "%q is not a sh_binary module", depName)
- }
- case bcpfTag:
- {
- bcpfModule, ok := child.(*java.BootclasspathFragmentModule)
- if !ok {
- ctx.PropertyErrorf("bootclasspath_fragments", "%q is not a bootclasspath_fragment module", depName)
- return false
- }
-
- filesToAdd := apexBootclasspathFragmentFiles(ctx, child)
- filesInfo = append(filesInfo, filesToAdd...)
- for _, makeModuleName := range bcpfModule.BootImageDeviceInstallMakeModules() {
- a.requiredDeps = append(a.requiredDeps, makeModuleName)
- }
- return true
- }
- case sscpfTag:
- {
- if _, ok := child.(*java.SystemServerClasspathModule); !ok {
- ctx.PropertyErrorf("systemserverclasspath_fragments", "%q is not a systemserverclasspath_fragment module", depName)
- return false
- }
- if af := apexClasspathFragmentProtoFile(ctx, child); af != nil {
- filesInfo = append(filesInfo, *af)
- }
- return true
- }
- case javaLibTag:
- switch child.(type) {
- case *java.Library, *java.SdkLibrary, *java.DexImport, *java.SdkLibraryImport, *java.Import:
- af := apexFileForJavaModule(ctx, child.(javaModule))
- if !af.ok() {
- ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
- return false
- }
- filesInfo = append(filesInfo, af)
- return true // track transitive dependencies
- default:
- ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
- }
- case androidAppTag:
- if ap, ok := child.(*java.AndroidApp); ok {
- filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap))
- return true // track transitive dependencies
- } else if ap, ok := child.(*java.AndroidAppImport); ok {
- filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap))
- } else if ap, ok := child.(*java.AndroidTestHelperApp); ok {
- filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap))
- } else if ap, ok := child.(*java.AndroidAppSet); ok {
- appDir := "app"
- if ap.Privileged() {
- appDir = "priv-app"
- }
- // TODO(b/224589412, b/226559955): Ensure that the dirname is
- // suffixed so that PackageManager correctly invalidates the
- // existing installed apk in favour of the new APK-in-APEX.
- // See bugs for more information.
- appDirName := filepath.Join(appDir, ap.BaseModuleName()+"@"+sanitizedBuildIdForPath(ctx))
- af := newApexFile(ctx, ap.OutputFile(), ap.BaseModuleName(), appDirName, appSet, ap)
- af.certificate = java.PresignedCertificate
- filesInfo = append(filesInfo, af)
- } else {
- ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
- }
- case rroTag:
- if rro, ok := child.(java.RuntimeResourceOverlayModule); ok {
- filesInfo = append(filesInfo, apexFileForRuntimeResourceOverlay(ctx, rro))
- } else {
- ctx.PropertyErrorf("rros", "%q is not an runtime_resource_overlay module", depName)
- }
- case bpfTag:
- if bpfProgram, ok := child.(bpf.BpfModule); ok {
- filesToCopy, _ := bpfProgram.OutputFiles("")
- apex_sub_dir := bpfProgram.SubDir()
- for _, bpfFile := range filesToCopy {
- filesInfo = append(filesInfo, apexFileForBpfProgram(ctx, bpfFile, apex_sub_dir, bpfProgram))
- }
- } else {
- ctx.PropertyErrorf("bpfs", "%q is not a bpf module", depName)
- }
- case fsTag:
- if fs, ok := child.(filesystem.Filesystem); ok {
- filesInfo = append(filesInfo, apexFileForFilesystem(ctx, fs.OutputPath(), fs))
- } else {
- ctx.PropertyErrorf("filesystems", "%q is not a filesystem module", depName)
- }
- case prebuiltTag:
- if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
- filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
- } else {
- ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
- }
- case compatConfigTag:
- if compatConfig, ok := child.(java.PlatformCompatConfigIntf); ok {
- filesInfo = append(filesInfo, apexFileForCompatConfig(ctx, compatConfig, depName))
- } else {
- ctx.PropertyErrorf("compat_configs", "%q is not a platform_compat_config module", depName)
- }
- case testTag:
- if ccTest, ok := child.(*cc.Module); ok {
- if ccTest.IsTestPerSrcAllTestsVariation() {
- // Multiple-output test module (where `test_per_src: true`).
- //
- // `ccTest` is the "" ("all tests") variation of a `test_per_src` module.
- // We do not add this variation to `filesInfo`, as it has no output;
- // however, we do add the other variations of this module as indirect
- // dependencies (see below).
- } else {
- // Single-output test module (where `test_per_src: false`).
- af := apexFileForExecutable(ctx, ccTest)
- af.class = nativeTest
- filesInfo = append(filesInfo, af)
- }
- return true // track transitive dependencies
- } else {
- ctx.PropertyErrorf("tests", "%q is not a cc module", depName)
- }
- case keyTag:
- if key, ok := child.(*apexKey); ok {
- a.privateKeyFile = key.privateKeyFile
- a.publicKeyFile = key.publicKeyFile
- } else {
- ctx.PropertyErrorf("key", "%q is not an apex_key module", depName)
- }
- return false
- case certificateTag:
- if dep, ok := child.(*java.AndroidAppCertificate); ok {
- a.containerCertificateFile = dep.Certificate.Pem
- a.containerPrivateKeyFile = dep.Certificate.Key
- } else {
- ctx.ModuleErrorf("certificate dependency %q must be an android_app_certificate module", depName)
- }
- case android.PrebuiltDepTag:
- // If the prebuilt is force disabled, remember to delete the prebuilt file
- // that might have been installed in the previous builds
- if prebuilt, ok := child.(prebuilt); ok && prebuilt.isForceDisabled() {
- a.prebuiltFileToDelete = prebuilt.InstallFilename()
- }
- }
- } else if !a.vndkApex {
- // indirect dependencies
- if am, ok := child.(android.ApexModule); ok {
- // We cannot use a switch statement on `depTag` here as the checked
- // tags used below are private (e.g. `cc.sharedDepTag`).
- if cc.IsSharedDepTag(depTag) || cc.IsRuntimeDepTag(depTag) {
- if cc, ok := child.(*cc.Module); ok {
- if cc.UseVndk() && proptools.Bool(a.properties.Use_vndk_as_stable) && cc.IsVndk() {
- requireNativeLibs = append(requireNativeLibs, ":vndk")
- return false
- }
- af := apexFileForNativeLibrary(ctx, cc, handleSpecialLibs)
- af.transitiveDep = true
-
- // Always track transitive dependencies for host.
- if a.Host() {
- filesInfo = append(filesInfo, af)
- return true
- }
-
- abInfo := ctx.Provider(ApexBundleInfoProvider).(ApexBundleInfo)
- if !abInfo.Contents.DirectlyInApex(depName) && (cc.IsStubs() || cc.HasStubsVariants()) {
- // If the dependency is a stubs lib, don't include it in this APEX,
- // but make sure that the lib is installed on the device.
- // In case no APEX is having the lib, the lib is installed to the system
- // partition.
- //
- // Always include if we are a host-apex however since those won't have any
- // system libraries.
- if !am.DirectlyInAnyApex() {
- // we need a module name for Make
- name := cc.ImplementationModuleNameForMake(ctx) + cc.Properties.SubName
- if !android.InList(name, a.requiredDeps) {
- a.requiredDeps = append(a.requiredDeps, name)
- }
- }
- requireNativeLibs = append(requireNativeLibs, af.stem())
- // Don't track further
- return false
- }
-
- // If the dep is not considered to be in the same
- // apex, don't add it to filesInfo so that it is not
- // included in this APEX.
- // TODO(jiyong): move this to at the top of the
- // else-if clause for the indirect dependencies.
- // Currently, that's impossible because we would
- // like to record requiredNativeLibs even when
- // DepIsInSameAPex is false. We also shouldn't do
- // this for host.
- //
- // TODO(jiyong): explain why the same module is passed in twice.
- // Switching the first am to parent breaks lots of tests.
- if !android.IsDepInSameApex(ctx, am, am) {
- return false
- }
-
- filesInfo = append(filesInfo, af)
- return true // track transitive dependencies
- } else if rm, ok := child.(*rust.Module); ok {
- af := apexFileForRustLibrary(ctx, rm)
- af.transitiveDep = true
- filesInfo = append(filesInfo, af)
- return true // track transitive dependencies
- }
- } else if cc.IsTestPerSrcDepTag(depTag) {
- if cc, ok := child.(*cc.Module); ok {
- af := apexFileForExecutable(ctx, cc)
- // Handle modules created as `test_per_src` variations of a single test module:
- // use the name of the generated test binary (`fileToCopy`) instead of the name
- // of the original test module (`depName`, shared by all `test_per_src`
- // variations of that module).
- af.androidMkModuleName = filepath.Base(af.builtFile.String())
- // these are not considered transitive dep
- af.transitiveDep = false
- filesInfo = append(filesInfo, af)
- return true // track transitive dependencies
- }
- } else if cc.IsHeaderDepTag(depTag) {
- // nothing
- } else if java.IsJniDepTag(depTag) {
- // Because APK-in-APEX embeds jni_libs transitively, we don't need to track transitive deps
- return false
- } else if java.IsXmlPermissionsFileDepTag(depTag) {
- if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
- filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
- }
- } else if rust.IsDylibDepTag(depTag) {
- if rustm, ok := child.(*rust.Module); ok && rustm.IsInstallableToApex() {
- af := apexFileForRustLibrary(ctx, rustm)
- af.transitiveDep = true
- filesInfo = append(filesInfo, af)
- return true // track transitive dependencies
- }
- } else if rust.IsRlibDepTag(depTag) {
- // Rlib is statically linked, but it might have shared lib
- // dependencies. Track them.
- return true
- } else if java.IsBootclasspathFragmentContentDepTag(depTag) {
- // Add the contents of the bootclasspath fragment to the apex.
- switch child.(type) {
- case *java.Library, *java.SdkLibrary:
- javaModule := child.(javaModule)
- af := apexFileForBootclasspathFragmentContentModule(ctx, parent, javaModule)
- if !af.ok() {
- ctx.PropertyErrorf("bootclasspath_fragments", "bootclasspath_fragment content %q is not configured to be compiled into dex", depName)
- return false
- }
- filesInfo = append(filesInfo, af)
- return true // track transitive dependencies
- default:
- ctx.PropertyErrorf("bootclasspath_fragments", "bootclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child))
- }
- } else if java.IsSystemServerClasspathFragmentContentDepTag(depTag) {
- // Add the contents of the systemserverclasspath fragment to the apex.
- switch child.(type) {
- case *java.Library, *java.SdkLibrary:
- af := apexFileForJavaModule(ctx, child.(javaModule))
- filesInfo = append(filesInfo, af)
- return true // track transitive dependencies
- default:
- ctx.PropertyErrorf("systemserverclasspath_fragments", "systemserverclasspath_fragment content %q of type %q is not supported", depName, ctx.OtherModuleType(child))
- }
- } else if _, ok := depTag.(android.CopyDirectlyInAnyApexTag); ok {
- // nothing
- } else if depTag == android.DarwinUniversalVariantTag {
- // nothing
- } else if am.CanHaveApexVariants() && am.IsInstallableToApex() {
- ctx.ModuleErrorf("unexpected tag %s for indirect dependency %q", android.PrettyPrintTag(depTag), depName)
- }
- }
- }
- return false
- })
+ vctx := visitorContext{handleSpecialLibs: !android.Bool(a.properties.Ignore_system_library_special_case)}
+ ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool { return a.depVisitor(&vctx, ctx, child, parent) })
+ vctx.normalizeFileInfo()
if a.privateKeyFile == nil {
ctx.PropertyErrorf("key", "private_key for %q could not be found", String(a.overridableProperties.Key))
return
}
- // Remove duplicates in filesInfo
- removeDup := func(filesInfo []apexFile) []apexFile {
- encountered := make(map[string]apexFile)
- for _, f := range filesInfo {
- dest := filepath.Join(f.installDir, f.builtFile.Base())
- if e, ok := encountered[dest]; !ok {
- encountered[dest] = f
- } else {
- // If a module is directly included and also transitively depended on
- // consider it as directly included.
- e.transitiveDep = e.transitiveDep && f.transitiveDep
- encountered[dest] = e
- }
- }
- var result []apexFile
- for _, v := range encountered {
- result = append(result, v)
- }
- return result
- }
- filesInfo = removeDup(filesInfo)
-
- // Sort to have consistent build rules
- sort.Slice(filesInfo, func(i, j int) bool {
- // Sort by destination path so as to ensure consistent ordering even if the source of the files
- // changes.
- return filesInfo[i].path() < filesInfo[j].path()
- })
-
////////////////////////////////////////////////////////////////////////////////////////////
// 3) some fields in apexBundle struct are configured
a.installDir = android.PathForModuleInstall(ctx, "apex")
- a.filesInfo = filesInfo
+ a.filesInfo = vctx.filesInfo
// Set suffix and primaryApexType depending on the ApexType
buildFlattenedAsDefault := ctx.Config().FlattenApex()
@@ -2267,7 +2293,7 @@
////////////////////////////////////////////////////////////////////////////////////////////
// 4) generate the build rules to create the APEX. This is done in builder.go.
- a.buildManifest(ctx, provideNativeLibs, requireNativeLibs)
+ a.buildManifest(ctx, vctx.provideNativeLibs, vctx.requireNativeLibs)
if a.properties.ApexType == flattenedApex {
a.buildFlattenedApex(ctx)
} else {
@@ -2458,7 +2484,7 @@
android.BazelModuleBase
}
-func (o *OverrideApex) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func (o *OverrideApex) GenerateAndroidBuildActions(_ android.ModuleContext) {
// All the overrides happen in the base module.
}
diff --git a/apex/apex_sdk_member.go b/apex/apex_sdk_member.go
new file mode 100644
index 0000000..284158f
--- /dev/null
+++ b/apex/apex_sdk_member.go
@@ -0,0 +1,58 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package apex
+
+import (
+ "android/soong/android"
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+// This file contains support for using apex modules within an sdk.
+
+func init() {
+ // Register sdk member types.
+ android.RegisterSdkMemberType(&apexSdkMemberType{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
+ PropertyName: "apexes",
+ SupportsSdk: true,
+
+ // The apexes property does not need to be included in the snapshot as adding an apex to an
+ // sdk does not produce any prebuilts of the apex.
+ PrebuiltsRequired: proptools.BoolPtr(false),
+ },
+ })
+}
+
+type apexSdkMemberType struct {
+ android.SdkMemberTypeBase
+}
+
+func (mt *apexSdkMemberType) AddDependencies(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) {
+ ctx.AddVariationDependencies(nil, dependencyTag, names...)
+}
+
+func (mt *apexSdkMemberType) IsInstance(module android.Module) bool {
+ _, ok := module.(*apexBundle)
+ return ok
+}
+
+func (mt *apexSdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
+ panic("Sdk does not create prebuilts of the apexes in its snapshot")
+}
+
+func (mt *apexSdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
+ panic("Sdk does not create prebuilts of the apexes in its snapshot")
+}
diff --git a/apex/builder.go b/apex/builder.go
index fc9bb3b..1956b44 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -76,11 +76,12 @@
Command: `rm -f $out && ${jsonmodify} $in ` +
`-a provideNativeLibs ${provideNativeLibs} ` +
`-a requireNativeLibs ${requireNativeLibs} ` +
+ `-se version 0 ${default_version} ` +
`${opt} ` +
`-o $out`,
CommandDeps: []string{"${jsonmodify}"},
Description: "prepare ${out}",
- }, "provideNativeLibs", "requireNativeLibs", "opt")
+ }, "provideNativeLibs", "requireNativeLibs", "default_version", "opt")
stripApexManifestRule = pctx.StaticRule("stripApexManifestRule", blueprint.RuleParams{
Command: `rm -f $out && ${conv_apex_manifest} strip $in -o $out`,
@@ -213,6 +214,7 @@
Args: map[string]string{
"provideNativeLibs": strings.Join(provideNativeLibs, " "),
"requireNativeLibs": strings.Join(requireNativeLibs, " "),
+ "default_version": defaultManifestVersion,
"opt": strings.Join(optCommands, " "),
},
})
@@ -655,8 +657,6 @@
optFlags = append(optFlags, "--manifest_json "+a.manifestJsonOut.String())
}
- optFlags = append(optFlags, "--apex_version "+defaultManifestVersion)
-
optFlags = append(optFlags, "--payload_fs_type "+a.payloadFsType.string())
ctx.Build(pctx, android.BuildParams{
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 6829698..ae2b107 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -21,7 +21,6 @@
"fmt"
"path/filepath"
"reflect"
- "regexp"
"sort"
"strings"
@@ -83,6 +82,7 @@
OutputIds []artifactId
TemplateContent string
Substitutions []KeyValuePair
+ FileContents string
}
// actionGraphContainer contains relevant portions of Bazel's aquery proto, ActionGraphContainer.
@@ -110,11 +110,14 @@
// input path string, but not both.
InputDepsetHashes []string
InputPaths []string
+ FileContents string
}
// A helper type for aquery processing which facilitates retrieval of path IDs from their
// less readable Bazel structures (depset and path fragment).
type aqueryArtifactHandler struct {
+ // Switches to true if any depset contains only `bazelToolsDependencySentinel`
+ bazelToolsDependencySentinelNeeded bool
// Maps depset id to AqueryDepset, a representation of depset which is
// post-processed for middleman artifact handling, unhandled artifact
// dropping, content hashing, etc.
@@ -137,12 +140,12 @@
"%python_binary%": "python3",
}
-// This pattern matches the MANIFEST file created for a py_binary target.
-var manifestFilePattern = regexp.MustCompile(".*/.+\\.runfiles/MANIFEST$")
-
// The file name of py3wrapper.sh, which is used by py_binary targets.
const py3wrapperFileName = "/py3wrapper.sh"
+// A file to be put into depsets that are otherwise empty
+const bazelToolsDependencySentinel = "BAZEL_TOOLS_DEPENDENCY_SENTINEL"
+
func indexBy[K comparable, V any](values []V, keyFn func(v V) K) map[K]V {
m := map[K]V{}
for _, v := range values {
@@ -219,20 +222,15 @@
if depsetsToUse, isMiddleman := middlemanIdToDepsetIds[artifactId]; isMiddleman {
// Swap middleman artifacts with their corresponding depsets and drop the middleman artifacts.
transitiveDepsetIds = append(transitiveDepsetIds, depsetsToUse...)
- } else if strings.HasSuffix(path, py3wrapperFileName) || manifestFilePattern.MatchString(path) {
+ } else if strings.HasSuffix(path, py3wrapperFileName) ||
+ strings.HasPrefix(path, "../bazel_tools") {
// Drop these artifacts.
// See go/python-binary-host-mixed-build for more details.
- // 1) For py3wrapper.sh, there is no action for creating py3wrapper.sh in the aquery output of
- // Bazel py_binary targets, so there is no Ninja build statements generated for creating it.
- // 2) For MANIFEST file, SourceSymlinkManifest action is in aquery output of Bazel py_binary targets,
- // but it doesn't contain sufficient information so no Ninja build statements are generated
- // for creating it.
- // So in mixed build mode, when these two are used as input of some Ninja build statement,
- // since there is no build statement to create them, they should be removed from input paths.
- // TODO(b/197135294): Clean up this custom runfiles handling logic when
- // SourceSymlinkManifest and SymlinkTree actions are supported.
+ // 1) Drop py3wrapper.sh, just use python binary, the launcher script generated by the
+ // TemplateExpandAction handles everything necessary to launch a Pythin application.
+ // 2) ../bazel_tools: they have MODIFY timestamp 10years in the future and would cause the
+ // containing depset to always be considered newer than their outputs.
} else {
- // TODO(b/216194240): Filter out bazel tools.
directArtifactPaths = append(directArtifactPaths, path)
}
}
@@ -249,6 +247,13 @@
}
childDepsetHashes = append(childDepsetHashes, childAqueryDepset.ContentHash)
}
+ if len(directArtifactPaths) == 0 && len(childDepsetHashes) == 0 {
+ // We could omit this depset altogether but that requires cleanup on
+ // transitive dependents.
+ // As a simpler alternative, we use this sentinel file as a dependency.
+ directArtifactPaths = append(directArtifactPaths, bazelToolsDependencySentinel)
+ a.bazelToolsDependencySentinelNeeded = true
+ }
aqueryDepset := AqueryDepset{
ContentHash: depsetContentHash(directArtifactPaths, childDepsetHashes),
DirectArtifacts: directArtifactPaths,
@@ -317,6 +322,13 @@
}
var buildStatements []BuildStatement
+ if aqueryHandler.bazelToolsDependencySentinelNeeded {
+ buildStatements = append(buildStatements, BuildStatement{
+ Command: fmt.Sprintf("touch '%s'", bazelToolsDependencySentinel),
+ OutputPaths: []string{bazelToolsDependencySentinel},
+ Mnemonic: bazelToolsDependencySentinel,
+ })
+ }
for _, actionEntry := range aqueryResult.Actions {
if shouldSkipAction(actionEntry) {
@@ -324,12 +336,14 @@
}
var buildStatement BuildStatement
- if isSymlinkAction(actionEntry) {
+ if actionEntry.isSymlinkAction() {
buildStatement, err = aqueryHandler.symlinkActionBuildStatement(actionEntry)
- } else if isTemplateExpandAction(actionEntry) && len(actionEntry.Arguments) < 1 {
+ } else if actionEntry.isTemplateExpandAction() && len(actionEntry.Arguments) < 1 {
buildStatement, err = aqueryHandler.templateExpandActionBuildStatement(actionEntry)
- } else if isPythonZipperAction(actionEntry) {
- buildStatement, err = aqueryHandler.pythonZipperActionBuildStatement(actionEntry, buildStatements)
+ } else if actionEntry.isFileWriteAction() {
+ buildStatement, err = aqueryHandler.fileWriteActionBuildStatement(actionEntry)
+ } else if actionEntry.isSymlinkTreeAction() {
+ buildStatement, err = aqueryHandler.symlinkTreeActionBuildStatement(actionEntry)
} else if len(actionEntry.Arguments) < 1 {
return nil, nil, fmt.Errorf("received action with no command: [%s]", actionEntry.Mnemonic)
} else {
@@ -430,54 +444,6 @@
return buildStatement, nil
}
-func (a *aqueryArtifactHandler) pythonZipperActionBuildStatement(actionEntry action, prevBuildStatements []BuildStatement) (BuildStatement, error) {
- inputPaths, err := a.getInputPaths(actionEntry.InputDepSetIds)
- if err != nil {
- return BuildStatement{}, err
- }
- outputPaths, depfile, err := a.getOutputPaths(actionEntry)
- if err != nil {
- return BuildStatement{}, err
- }
-
- if len(inputPaths) < 1 || len(outputPaths) != 1 {
- return BuildStatement{}, fmt.Errorf("Expect 1+ input and 1 output to python zipper action, got: input %q, output %q", inputPaths, outputPaths)
- }
- command := strings.Join(proptools.ShellEscapeListIncludingSpaces(actionEntry.Arguments), " ")
- inputPaths, command = removePy3wrapperScript(inputPaths, command)
- command = addCommandForPyBinaryRunfilesDir(command, inputPaths[0], outputPaths[0])
- // Add the python zip file as input of the corresponding python binary stub script in Ninja build statements.
- // In Ninja build statements, the outputs of dependents of a python binary have python binary stub script as input,
- // which is not sufficient without the python zip file from which runfiles directory is created for py_binary.
- //
- // The following logic relies on that Bazel aquery output returns actions in the order that
- // PythonZipper is after TemplateAction of creating Python binary stub script. If later Bazel doesn't return actions
- // in that order, the following logic might not find the build statement generated for Python binary
- // stub script and the build might fail. So the check of pyBinaryFound is added to help debug in case later Bazel might change aquery output.
- // See go/python-binary-host-mixed-build for more details.
- pythonZipFilePath := outputPaths[0]
- pyBinaryFound := false
- for i := range prevBuildStatements {
- if len(prevBuildStatements[i].OutputPaths) == 1 && prevBuildStatements[i].OutputPaths[0]+".zip" == pythonZipFilePath {
- prevBuildStatements[i].InputPaths = append(prevBuildStatements[i].InputPaths, pythonZipFilePath)
- pyBinaryFound = true
- }
- }
- if !pyBinaryFound {
- return BuildStatement{}, fmt.Errorf("Could not find the correspondinging Python binary stub script of PythonZipper: %q", outputPaths)
- }
-
- buildStatement := BuildStatement{
- Command: command,
- Depfile: depfile,
- OutputPaths: outputPaths,
- InputPaths: inputPaths,
- Env: actionEntry.EnvironmentVariables,
- Mnemonic: actionEntry.Mnemonic,
- }
- return buildStatement, nil
-}
-
func (a *aqueryArtifactHandler) templateExpandActionBuildStatement(actionEntry action) (BuildStatement, error) {
outputPaths, depfile, err := a.getOutputPaths(actionEntry)
if err != nil {
@@ -510,6 +476,47 @@
return buildStatement, nil
}
+func (a *aqueryArtifactHandler) fileWriteActionBuildStatement(actionEntry action) (BuildStatement, error) {
+ outputPaths, _, err := a.getOutputPaths(actionEntry)
+ var depsetHashes []string
+ if err == nil {
+ depsetHashes, err = a.depsetContentHashes(actionEntry.InputDepSetIds)
+ }
+ if err != nil {
+ return BuildStatement{}, err
+ }
+ return BuildStatement{
+ Depfile: nil,
+ OutputPaths: outputPaths,
+ Env: actionEntry.EnvironmentVariables,
+ Mnemonic: actionEntry.Mnemonic,
+ InputDepsetHashes: depsetHashes,
+ FileContents: actionEntry.FileContents,
+ }, nil
+}
+
+func (a *aqueryArtifactHandler) symlinkTreeActionBuildStatement(actionEntry action) (BuildStatement, error) {
+ outputPaths, _, err := a.getOutputPaths(actionEntry)
+ if err != nil {
+ return BuildStatement{}, err
+ }
+ inputPaths, err := a.getInputPaths(actionEntry.InputDepSetIds)
+ if err != nil {
+ return BuildStatement{}, err
+ }
+ if len(inputPaths) != 1 || len(outputPaths) != 1 {
+ return BuildStatement{}, fmt.Errorf("Expect 1 input and 1 output to symlink action, got: input %q, output %q", inputPaths, outputPaths)
+ }
+ // The actual command is generated in bazelSingleton.GenerateBuildActions
+ return BuildStatement{
+ Depfile: nil,
+ OutputPaths: outputPaths,
+ Env: actionEntry.EnvironmentVariables,
+ Mnemonic: actionEntry.Mnemonic,
+ InputPaths: inputPaths,
+ }, nil
+}
+
func (a *aqueryArtifactHandler) symlinkActionBuildStatement(actionEntry action) (BuildStatement, error) {
outputPaths, depfile, err := a.getOutputPaths(actionEntry)
if err != nil {
@@ -592,76 +599,35 @@
return replacer.Replace(str)
}
-// removePy3wrapperScript removes py3wrapper.sh from the input paths and command of the action of
-// creating python zip file in mixed build mode. py3wrapper.sh is returned as input by aquery but
-// there is no action returned by aquery for creating it. So in mixed build "python3" is used
-// as the PYTHON_BINARY in python binary stub script, and py3wrapper.sh is not needed and should be
-// removed from input paths and command of creating python zip file.
-// See go/python-binary-host-mixed-build for more details.
-// TODO(b/205879240) remove this after py3wrapper.sh could be created in the mixed build mode.
-func removePy3wrapperScript(inputPaths []string, command string) (newInputPaths []string, newCommand string) {
- // Remove from inputs
- filteredInputPaths := []string{}
- for _, path := range inputPaths {
- if !strings.HasSuffix(path, py3wrapperFileName) {
- filteredInputPaths = append(filteredInputPaths, path)
- }
- }
- newInputPaths = filteredInputPaths
-
- // Remove from command line
- var re = regexp.MustCompile(`\S*` + py3wrapperFileName)
- newCommand = re.ReplaceAllString(command, "")
- return
-}
-
-// addCommandForPyBinaryRunfilesDir adds commands creating python binary runfiles directory.
-// runfiles directory is created by using MANIFEST file and MANIFEST file is the output of
-// SourceSymlinkManifest action is in aquery output of Bazel py_binary targets,
-// but since SourceSymlinkManifest doesn't contain sufficient information
-// so MANIFEST file could not be created, which also blocks the creation of runfiles directory.
-// See go/python-binary-host-mixed-build for more details.
-// TODO(b/197135294) create runfiles directory from MANIFEST file once it can be created from SourceSymlinkManifest action.
-func addCommandForPyBinaryRunfilesDir(oldCommand string, zipperCommandPath, zipFilePath string) string {
- // Unzip the zip file, zipFilePath looks like <python_binary>.zip
- runfilesDirName := zipFilePath[0:len(zipFilePath)-4] + ".runfiles"
- command := fmt.Sprintf("%s x %s -d %s", zipperCommandPath, zipFilePath, runfilesDirName)
- // Create a symbolic link in <python_binary>.runfiles/, which is the expected structure
- // when running the python binary stub script.
- command += fmt.Sprintf(" && ln -sf runfiles/__main__ %s", runfilesDirName)
- return oldCommand + " && " + command
-}
-
-func isSymlinkAction(a action) bool {
+func (a action) isSymlinkAction() bool {
return a.Mnemonic == "Symlink" || a.Mnemonic == "SolibSymlink" || a.Mnemonic == "ExecutableSymlink"
}
-func isTemplateExpandAction(a action) bool {
+func (a action) isTemplateExpandAction() bool {
return a.Mnemonic == "TemplateExpand"
}
-func isPythonZipperAction(a action) bool {
- return a.Mnemonic == "PythonZipper"
+func (a action) isFileWriteAction() bool {
+ return a.Mnemonic == "FileWrite" || a.Mnemonic == "SourceSymlinkManifest"
+}
+
+func (a action) isSymlinkTreeAction() bool {
+ return a.Mnemonic == "SymlinkTree"
}
func shouldSkipAction(a action) bool {
- // TODO(b/180945121): Handle complex symlink actions.
- if a.Mnemonic == "SymlinkTree" || a.Mnemonic == "SourceSymlinkManifest" {
- return true
- }
// Middleman actions are not handled like other actions; they are handled separately as a
// preparatory step so that their inputs may be relayed to actions depending on middleman
// artifacts.
if a.Mnemonic == "Middleman" {
return true
}
- // Skip "Fail" actions, which are placeholder actions designed to always fail.
- if a.Mnemonic == "Fail" {
+ // PythonZipper is bogus action returned by aquery, ignore it (b/236198693)
+ if a.Mnemonic == "PythonZipper" {
return true
}
- // TODO(b/180946980): Handle FileWrite. The aquery proto currently contains no information
- // about the contents that are written.
- if a.Mnemonic == "FileWrite" {
+ // Skip "Fail" actions, which are placeholder actions designed to always fail.
+ if a.Mnemonic == "Fail" {
return true
}
if a.Mnemonic == "BaselineCoverage" {
diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go
index 1da6340..3a2bf0f 100644
--- a/bazel/aquery_test.go
+++ b/bazel/aquery_test.go
@@ -25,28 +25,14 @@
// This input string is retrieved from a real build of bionic-related genrules.
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }, {
- "id": 2,
- "pathFragmentId": 6
- }, {
- "id": 3,
- "pathFragmentId": 8
- }, {
- "id": 4,
- "pathFragmentId": 12
- }, {
- "id": 5,
- "pathFragmentId": 19
- }, {
- "id": 6,
- "pathFragmentId": 20
- }, {
- "id": 7,
- "pathFragmentId": 21
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 },
+ { "id": 2, "pathFragmentId": 6 },
+ { "id": 3, "pathFragmentId": 8 },
+ { "id": 4, "pathFragmentId": 12 },
+ { "id": 5, "pathFragmentId": 19 },
+ { "id": 6, "pathFragmentId": 20 },
+ { "id": 7, "pathFragmentId": 21 }],
"actions": [{
"targetId": 1,
"actionKey": "ab53f6ecbdc2ee8cb8812613b63205464f1f5083f6dca87081a0a398c0f1ecf7",
@@ -100,129 +86,45 @@
"outputIds": [7],
"primaryOutputId": 7
}],
- "targets": [{
- "id": 1,
- "label": "@sourceroot//bionic/libc:syscalls-arm",
- "ruleClassId": 1
- }, {
- "id": 2,
- "label": "@sourceroot//bionic/libc:syscalls-x86",
- "ruleClassId": 1
- }, {
- "id": 3,
- "label": "@sourceroot//bionic/libc:syscalls-x86_64",
- "ruleClassId": 1
- }, {
- "id": 4,
- "label": "@sourceroot//bionic/libc:syscalls-arm64",
- "ruleClassId": 1
- }],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [1, 2, 3]
- }, {
- "id": 2,
- "directArtifactIds": [1, 2, 3]
- }, {
- "id": 3,
- "directArtifactIds": [1, 2, 3]
- }, {
- "id": 4,
- "directArtifactIds": [1, 2, 3]
- }],
+ "targets": [
+ { "id": 1, "label": "@sourceroot//bionic/libc:syscalls-arm", "ruleClassId": 1 },
+ { "id": 2, "label": "@sourceroot//bionic/libc:syscalls-x86", "ruleClassId": 1 },
+ { "id": 3, "label": "@sourceroot//bionic/libc:syscalls-x86_64", "ruleClassId": 1 },
+ { "id": 4, "label": "@sourceroot//bionic/libc:syscalls-arm64", "ruleClassId": 1 }],
+ "depSetOfFiles": [
+ { "id": 1, "directArtifactIds": [1, 2, 3] },
+ { "id": 2, "directArtifactIds": [1, 2, 3] },
+ { "id": 3, "directArtifactIds": [1, 2, 3] },
+ { "id": 4, "directArtifactIds": [1, 2, 3] }],
"configuration": [{
"id": 1,
"mnemonic": "k8-fastbuild",
"platformName": "k8",
"checksum": "485c362832c178e367d972177f68e69e0981e51e67ef1c160944473db53fe046"
}],
- "ruleClasses": [{
- "id": 1,
- "name": "genrule"
- }],
- "pathFragments": [{
- "id": 5,
- "label": ".."
- }, {
- "id": 4,
- "label": "sourceroot",
- "parentId": 5
- }, {
- "id": 3,
- "label": "bionic",
- "parentId": 4
- }, {
- "id": 2,
- "label": "libc",
- "parentId": 3
- }, {
- "id": 1,
- "label": "SYSCALLS.TXT",
- "parentId": 2
- }, {
- "id": 7,
- "label": "tools",
- "parentId": 2
- }, {
- "id": 6,
- "label": "gensyscalls.py",
- "parentId": 7
- }, {
- "id": 11,
- "label": "bazel_tools",
- "parentId": 5
- }, {
- "id": 10,
- "label": "tools",
- "parentId": 11
- }, {
- "id": 9,
- "label": "genrule",
- "parentId": 10
- }, {
- "id": 8,
- "label": "genrule-setup.sh",
- "parentId": 9
- }, {
- "id": 18,
- "label": "bazel-out"
- }, {
- "id": 17,
- "label": "sourceroot",
- "parentId": 18
- }, {
- "id": 16,
- "label": "k8-fastbuild",
- "parentId": 17
- }, {
- "id": 15,
- "label": "bin",
- "parentId": 16
- }, {
- "id": 14,
- "label": "bionic",
- "parentId": 15
- }, {
- "id": 13,
- "label": "libc",
- "parentId": 14
- }, {
- "id": 12,
- "label": "syscalls-arm.S",
- "parentId": 13
- }, {
- "id": 19,
- "label": "syscalls-x86.S",
- "parentId": 13
- }, {
- "id": 20,
- "label": "syscalls-x86_64.S",
- "parentId": 13
- }, {
- "id": 21,
- "label": "syscalls-arm64.S",
- "parentId": 13
- }]
+ "ruleClasses": [{ "id": 1, "name": "genrule"}],
+ "pathFragments": [
+ { "id": 5, "label": ".." },
+ { "id": 4, "label": "sourceroot", "parentId": 5 },
+ { "id": 3, "label": "bionic", "parentId": 4 },
+ { "id": 2, "label": "libc", "parentId": 3 },
+ { "id": 1, "label": "SYSCALLS.TXT", "parentId": 2 },
+ { "id": 7, "label": "tools", "parentId": 2 },
+ { "id": 6, "label": "gensyscalls.py", "parentId": 7 },
+ { "id": 11, "label": "bazel_tools", "parentId": 5 },
+ { "id": 10, "label": "tools", "parentId": 11 },
+ { "id": 9, "label": "genrule", "parentId": 10 },
+ { "id": 8, "label": "genrule-setup.sh", "parentId": 9 },
+ { "id": 18, "label": "bazel-out" },
+ { "id": 17, "label": "sourceroot", "parentId": 18 },
+ { "id": 16, "label": "k8-fastbuild", "parentId": 17 },
+ { "id": 15, "label": "bin", "parentId": 16 },
+ { "id": 14, "label": "bionic", "parentId": 15 },
+ { "id": 13, "label": "libc", "parentId": 14 },
+ { "id": 12, "label": "syscalls-arm.S", "parentId": 13 },
+ { "id": 19, "label": "syscalls-x86.S", "parentId": 13 },
+ { "id": 20, "label": "syscalls-x86_64.S", "parentId": 13 },
+ { "id": 21, "label": "syscalls-arm64.S", "parentId": 13 }]
}`
actualbuildStatements, actualDepsets, _ := AqueryBuildStatements([]byte(inputString))
var expectedBuildStatements []BuildStatement
@@ -246,7 +148,6 @@
expectedFlattenedInputs := []string{
"../sourceroot/bionic/libc/SYSCALLS.TXT",
"../sourceroot/bionic/libc/tools/gensyscalls.py",
- "../bazel_tools/tools/genrule/genrule-setup.sh",
}
// In this example, each depset should have the same expected inputs.
for _, actualDepset := range actualDepsets {
@@ -260,13 +161,9 @@
func TestInvalidOutputId(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }, {
- "id": 2,
- "pathFragmentId": 2
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 },
+ { "id": 2, "pathFragmentId": 2 }],
"actions": [{
"targetId": 1,
"actionKey": "x",
@@ -276,17 +173,11 @@
"outputIds": [3],
"primaryOutputId": 3
}],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [1, 2]
- }],
- "pathFragments": [{
- "id": 1,
- "label": "one"
- }, {
- "id": 2,
- "label": "two"
- }]
+ "depSetOfFiles": [
+ { "id": 1, "directArtifactIds": [1, 2] }],
+ "pathFragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" }]
}`
_, _, err := AqueryBuildStatements([]byte(inputString))
@@ -296,13 +187,9 @@
func TestInvalidInputDepsetIdFromAction(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }, {
- "id": 2,
- "pathFragmentId": 2
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 },
+ { "id": 2, "pathFragmentId": 2 }],
"actions": [{
"targetId": 1,
"actionKey": "x",
@@ -312,17 +199,11 @@
"outputIds": [1],
"primaryOutputId": 1
}],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [1, 2]
- }],
- "pathFragments": [{
- "id": 1,
- "label": "one"
- }, {
- "id": 2,
- "label": "two"
- }]
+ "depSetOfFiles": [
+ { "id": 1, "directArtifactIds": [1, 2] }],
+ "pathFragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" }]
}`
_, _, err := AqueryBuildStatements([]byte(inputString))
@@ -332,13 +213,9 @@
func TestInvalidInputDepsetIdFromDepset(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }, {
- "id": 2,
- "pathFragmentId": 2
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 },
+ { "id": 2, "pathFragmentId": 2 }],
"actions": [{
"targetId": 1,
"actionKey": "x",
@@ -348,18 +225,11 @@
"outputIds": [1],
"primaryOutputId": 1
}],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [1, 2],
- "transitiveDepSetIds": [42]
- }],
- "pathFragments": [{
- "id": 1,
- "label": "one"
- }, {
- "id": 2,
- "label": "two"
- }]
+ "depSetOfFiles": [
+ { "id": 1, "directArtifactIds": [1, 2], "transitiveDepSetIds": [42] }],
+ "pathFragments": [
+ { "id": 1, "label": "one"},
+ { "id": 2, "label": "two" }]
}`
_, _, err := AqueryBuildStatements([]byte(inputString))
@@ -369,13 +239,9 @@
func TestInvalidInputArtifactId(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }, {
- "id": 2,
- "pathFragmentId": 2
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 },
+ { "id": 2, "pathFragmentId": 2 }],
"actions": [{
"targetId": 1,
"actionKey": "x",
@@ -385,17 +251,11 @@
"outputIds": [1],
"primaryOutputId": 1
}],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [1, 3]
- }],
- "pathFragments": [{
- "id": 1,
- "label": "one"
- }, {
- "id": 2,
- "label": "two"
- }]
+ "depSetOfFiles": [
+ { "id": 1, "directArtifactIds": [1, 3] }],
+ "pathFragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" }]
}`
_, _, err := AqueryBuildStatements([]byte(inputString))
@@ -405,13 +265,9 @@
func TestInvalidPathFragmentId(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }, {
- "id": 2,
- "pathFragmentId": 2
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 },
+ { "id": 2, "pathFragmentId": 2 }],
"actions": [{
"targetId": 1,
"actionKey": "x",
@@ -421,18 +277,11 @@
"outputIds": [1],
"primaryOutputId": 1
}],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [1, 2]
- }],
- "pathFragments": [{
- "id": 1,
- "label": "one"
- }, {
- "id": 2,
- "label": "two",
- "parentId": 3
- }]
+ "depSetOfFiles": [
+ { "id": 1, "directArtifactIds": [1, 2] }],
+ "pathFragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two", "parentId": 3 }]
}`
_, _, err := AqueryBuildStatements([]byte(inputString))
@@ -442,16 +291,10 @@
func TestDepfiles(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }, {
- "id": 2,
- "pathFragmentId": 2
- }, {
- "id": 3,
- "pathFragmentId": 3
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 },
+ { "id": 2, "pathFragmentId": 2 },
+ { "id": 3, "pathFragmentId": 3 }],
"actions": [{
"targetId": 1,
"actionKey": "x",
@@ -461,20 +304,12 @@
"outputIds": [2, 3],
"primaryOutputId": 2
}],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [1, 2, 3]
- }],
- "pathFragments": [{
- "id": 1,
- "label": "one"
- }, {
- "id": 2,
- "label": "two"
- }, {
- "id": 3,
- "label": "two.d"
- }]
+ "depSetOfFiles": [
+ { "id": 1, "directArtifactIds": [1, 2, 3] }],
+ "pathFragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" },
+ { "id": 3, "label": "two.d" }]
}`
actual, _, err := AqueryBuildStatements([]byte(inputString))
@@ -497,19 +332,11 @@
func TestMultipleDepfiles(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }, {
- "id": 2,
- "pathFragmentId": 2
- }, {
- "id": 3,
- "pathFragmentId": 3
- }, {
- "id": 4,
- "pathFragmentId": 4
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 },
+ { "id": 2, "pathFragmentId": 2 },
+ { "id": 3, "pathFragmentId": 3 },
+ { "id": 4, "pathFragmentId": 4 }],
"actions": [{
"targetId": 1,
"actionKey": "x",
@@ -523,19 +350,11 @@
"id": 1,
"directArtifactIds": [1, 2, 3, 4]
}],
- "pathFragments": [{
- "id": 1,
- "label": "one"
- }, {
- "id": 2,
- "label": "two"
- }, {
- "id": 3,
- "label": "two.d"
- }, {
- "id": 4,
- "label": "other.d"
- }]
+ "pathFragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" },
+ { "id": 3, "label": "two.d" },
+ { "id": 4, "label": "other.d" }]
}`
_, _, err := AqueryBuildStatements([]byte(inputString))
@@ -547,70 +366,28 @@
// a single action with many inputs given via a deep depset.
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }, {
- "id": 2,
- "pathFragmentId": 7
- }, {
- "id": 3,
- "pathFragmentId": 8
- }, {
- "id": 4,
- "pathFragmentId": 9
- }, {
- "id": 5,
- "pathFragmentId": 10
- }, {
- "id": 6,
- "pathFragmentId": 11
- }, {
- "id": 7,
- "pathFragmentId": 12
- }, {
- "id": 8,
- "pathFragmentId": 13
- }, {
- "id": 9,
- "pathFragmentId": 14
- }, {
- "id": 10,
- "pathFragmentId": 15
- }, {
- "id": 11,
- "pathFragmentId": 16
- }, {
- "id": 12,
- "pathFragmentId": 17
- }, {
- "id": 13,
- "pathFragmentId": 18
- }, {
- "id": 14,
- "pathFragmentId": 19
- }, {
- "id": 15,
- "pathFragmentId": 20
- }, {
- "id": 16,
- "pathFragmentId": 21
- }, {
- "id": 17,
- "pathFragmentId": 22
- }, {
- "id": 18,
- "pathFragmentId": 23
- }, {
- "id": 19,
- "pathFragmentId": 24
- }, {
- "id": 20,
- "pathFragmentId": 25
- }, {
- "id": 21,
- "pathFragmentId": 26
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 },
+ { "id": 2, "pathFragmentId": 7 },
+ { "id": 3, "pathFragmentId": 8 },
+ { "id": 4, "pathFragmentId": 9 },
+ { "id": 5, "pathFragmentId": 10 },
+ { "id": 6, "pathFragmentId": 11 },
+ { "id": 7, "pathFragmentId": 12 },
+ { "id": 8, "pathFragmentId": 13 },
+ { "id": 9, "pathFragmentId": 14 },
+ { "id": 10, "pathFragmentId": 15 },
+ { "id": 11, "pathFragmentId": 16 },
+ { "id": 12, "pathFragmentId": 17 },
+ { "id": 13, "pathFragmentId": 18 },
+ { "id": 14, "pathFragmentId": 19 },
+ { "id": 15, "pathFragmentId": 20 },
+ { "id": 16, "pathFragmentId": 21 },
+ { "id": 17, "pathFragmentId": 22 },
+ { "id": 18, "pathFragmentId": 23 },
+ { "id": 19, "pathFragmentId": 24 },
+ { "id": 20, "pathFragmentId": 25 },
+ { "id": 21, "pathFragmentId": 26 }],
"actions": [{
"targetId": 1,
"actionKey": "3b826d17fadbbbcd8313e456b90ec47c078c438088891dd45b4adbcd8889dc50",
@@ -621,128 +398,39 @@
"outputIds": [21],
"primaryOutputId": 21
}],
- "depSetOfFiles": [{
- "id": 3,
- "directArtifactIds": [1, 2, 3, 4, 5]
- }, {
- "id": 4,
- "directArtifactIds": [6, 7, 8, 9, 10]
- }, {
- "id": 2,
- "transitiveDepSetIds": [3, 4],
- "directArtifactIds": [11, 12, 13, 14, 15]
- }, {
- "id": 5,
- "directArtifactIds": [16, 17, 18, 19]
- }, {
- "id": 1,
- "transitiveDepSetIds": [2, 5],
- "directArtifactIds": [20]
- }],
- "pathFragments": [{
- "id": 6,
- "label": "bazel-out"
- }, {
- "id": 5,
- "label": "sourceroot",
- "parentId": 6
- }, {
- "id": 4,
- "label": "k8-fastbuild",
- "parentId": 5
- }, {
- "id": 3,
- "label": "bin",
- "parentId": 4
- }, {
- "id": 2,
- "label": "testpkg",
- "parentId": 3
- }, {
- "id": 1,
- "label": "test_1",
- "parentId": 2
- }, {
- "id": 7,
- "label": "test_2",
- "parentId": 2
- }, {
- "id": 8,
- "label": "test_3",
- "parentId": 2
- }, {
- "id": 9,
- "label": "test_4",
- "parentId": 2
- }, {
- "id": 10,
- "label": "test_5",
- "parentId": 2
- }, {
- "id": 11,
- "label": "test_6",
- "parentId": 2
- }, {
- "id": 12,
- "label": "test_7",
- "parentId": 2
- }, {
- "id": 13,
- "label": "test_8",
- "parentId": 2
- }, {
- "id": 14,
- "label": "test_9",
- "parentId": 2
- }, {
- "id": 15,
- "label": "test_10",
- "parentId": 2
- }, {
- "id": 16,
- "label": "test_11",
- "parentId": 2
- }, {
- "id": 17,
- "label": "test_12",
- "parentId": 2
- }, {
- "id": 18,
- "label": "test_13",
- "parentId": 2
- }, {
- "id": 19,
- "label": "test_14",
- "parentId": 2
- }, {
- "id": 20,
- "label": "test_15",
- "parentId": 2
- }, {
- "id": 21,
- "label": "test_16",
- "parentId": 2
- }, {
- "id": 22,
- "label": "test_17",
- "parentId": 2
- }, {
- "id": 23,
- "label": "test_18",
- "parentId": 2
- }, {
- "id": 24,
- "label": "test_19",
- "parentId": 2
- }, {
- "id": 25,
- "label": "test_root",
- "parentId": 2
- }, {
- "id": 26,
- "label": "test_out",
- "parentId": 2
- }]
+ "depSetOfFiles": [
+ { "id": 3, "directArtifactIds": [1, 2, 3, 4, 5] },
+ { "id": 4, "directArtifactIds": [6, 7, 8, 9, 10] },
+ { "id": 2, "transitiveDepSetIds": [3, 4], "directArtifactIds": [11, 12, 13, 14, 15] },
+ { "id": 5, "directArtifactIds": [16, 17, 18, 19] },
+ { "id": 1, "transitiveDepSetIds": [2, 5], "directArtifactIds": [20] }],
+ "pathFragments": [
+ { "id": 6, "label": "bazel-out" },
+ { "id": 5, "label": "sourceroot", "parentId": 6 },
+ { "id": 4, "label": "k8-fastbuild", "parentId": 5 },
+ { "id": 3, "label": "bin", "parentId": 4 },
+ { "id": 2, "label": "testpkg", "parentId": 3 },
+ { "id": 1, "label": "test_1", "parentId": 2 },
+ { "id": 7, "label": "test_2", "parentId": 2 },
+ { "id": 8, "label": "test_3", "parentId": 2 },
+ { "id": 9, "label": "test_4", "parentId": 2 },
+ { "id": 10, "label": "test_5", "parentId": 2 },
+ { "id": 11, "label": "test_6", "parentId": 2 },
+ { "id": 12, "label": "test_7", "parentId": 2 },
+ { "id": 13, "label": "test_8", "parentId": 2 },
+ { "id": 14, "label": "test_9", "parentId": 2 },
+ { "id": 15, "label": "test_10", "parentId": 2 },
+ { "id": 16, "label": "test_11", "parentId": 2 },
+ { "id": 17, "label": "test_12", "parentId": 2 },
+ { "id": 18, "label": "test_13", "parentId": 2 },
+ { "id": 19, "label": "test_14", "parentId": 2 },
+ { "id": 20, "label": "test_15", "parentId": 2 },
+ { "id": 21, "label": "test_16", "parentId": 2 },
+ { "id": 22, "label": "test_17", "parentId": 2 },
+ { "id": 23, "label": "test_18", "parentId": 2 },
+ { "id": 24, "label": "test_19", "parentId": 2 },
+ { "id": 25, "label": "test_root", "parentId": 2 },
+ { "id": 26,"label": "test_out", "parentId": 2 }]
}`
actualbuildStatements, actualDepsets, _ := AqueryBuildStatements([]byte(inputString))
@@ -772,54 +460,149 @@
}
}
+func TestSymlinkTree(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 },
+ { "id": 2, "pathFragmentId": 2 }],
+ "actions": [{
+ "targetId": 1,
+ "actionKey": "x",
+ "mnemonic": "SymlinkTree",
+ "configurationId": 1,
+ "inputDepSetIds": [1],
+ "outputIds": [2],
+ "primaryOutputId": 2,
+ "executionPlatform": "//build/bazel/platforms:linux_x86_64"
+ }],
+ "pathFragments": [
+ { "id": 1, "label": "foo.manifest" },
+ { "id": 2, "label": "foo.runfiles/MANIFEST" }],
+ "depSetOfFiles": [
+ { "id": 1, "directArtifactIds": [1] }]
+}
+`
+ actual, _, err := AqueryBuildStatements([]byte(inputString))
+ if err != nil {
+ t.Errorf("Unexpected error %q", err)
+ }
+ assertBuildStatements(t, []BuildStatement{
+ {
+ Command: "",
+ OutputPaths: []string{"foo.runfiles/MANIFEST"},
+ Mnemonic: "SymlinkTree",
+ InputPaths: []string{"foo.manifest"},
+ },
+ }, actual)
+}
+
+func TestBazelOutRemovalFromInputDepsets(t *testing.T) {
+ const inputString = `{
+ "artifacts": [{
+ "id": 1,
+ "pathFragmentId": 10
+ }, {
+ "id": 2,
+ "pathFragmentId": 20
+ }, {
+ "id": 3,
+ "pathFragmentId": 30
+ }, {
+ "id": 4,
+ "pathFragmentId": 40
+ }],
+ "depSetOfFiles": [{
+ "id": 1111,
+ "directArtifactIds": [3 , 4]
+ }],
+ "actions": [{
+ "targetId": 100,
+ "actionKey": "x",
+ "inputDepSetIds": [1111],
+ "mnemonic": "x",
+ "arguments": ["bogus", "command"],
+ "outputIds": [2],
+ "primaryOutputId": 1
+ }],
+ "pathFragments": [{
+ "id": 10,
+ "label": "input"
+ }, {
+ "id": 20,
+ "label": "output"
+ }, {
+ "id": 30,
+ "label": "dep1",
+ "parentId": 50
+ }, {
+ "id": 40,
+ "label": "dep2",
+ "parentId": 60
+ }, {
+ "id": 50,
+ "label": "bazel_tools",
+ "parentId": 60
+ }, {
+ "id": 60,
+ "label": ".."
+ }]
+}`
+ actualBuildStatements, actualDepsets, _ := AqueryBuildStatements([]byte(inputString))
+ if len(actualDepsets) != 1 {
+ t.Errorf("expected 1 depset but found %#v", actualDepsets)
+ return
+ }
+ dep2Found := false
+ for _, dep := range flattenDepsets([]string{actualDepsets[0].ContentHash}, actualDepsets) {
+ if dep == "../bazel_tools/dep1" {
+ t.Errorf("dependency %s expected to be removed but still exists", dep)
+ } else if dep == "../dep2" {
+ dep2Found = true
+ }
+ }
+ if !dep2Found {
+ t.Errorf("dependency ../dep2 expected but not found")
+ }
+
+ expectedBuildStatement := BuildStatement{
+ Command: "bogus command",
+ OutputPaths: []string{"output"},
+ Mnemonic: "x",
+ }
+ buildStatementFound := false
+ for _, actualBuildStatement := range actualBuildStatements {
+ if buildStatementEquals(actualBuildStatement, expectedBuildStatement) == "" {
+ buildStatementFound = true
+ break
+ }
+ }
+ if !buildStatementFound {
+ t.Errorf("expected but missing %#v in %#v", expectedBuildStatement, actualBuildStatements)
+ return
+ }
+}
+
func TestMiddlemenAction(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }, {
- "id": 2,
- "pathFragmentId": 2
- }, {
- "id": 3,
- "pathFragmentId": 3
- }, {
- "id": 4,
- "pathFragmentId": 4
- }, {
- "id": 5,
- "pathFragmentId": 5
- }, {
- "id": 6,
- "pathFragmentId": 6
- }],
- "pathFragments": [{
- "id": 1,
- "label": "middleinput_one"
- }, {
- "id": 2,
- "label": "middleinput_two"
- }, {
- "id": 3,
- "label": "middleman_artifact"
- }, {
- "id": 4,
- "label": "maininput_one"
- }, {
- "id": 5,
- "label": "maininput_two"
- }, {
- "id": 6,
- "label": "output"
- }],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [1, 2]
- }, {
- "id": 2,
- "directArtifactIds": [3, 4, 5]
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 },
+ { "id": 2, "pathFragmentId": 2 },
+ { "id": 3, "pathFragmentId": 3 },
+ { "id": 4, "pathFragmentId": 4 },
+ { "id": 5, "pathFragmentId": 5 },
+ { "id": 6, "pathFragmentId": 6 }],
+ "pathFragments": [
+ { "id": 1, "label": "middleinput_one" },
+ { "id": 2, "label": "middleinput_two" },
+ { "id": 3, "label": "middleman_artifact" },
+ { "id": 4, "label": "maininput_one" },
+ { "id": 5, "label": "maininput_two" },
+ { "id": 6, "label": "output" }],
+ "depSetOfFiles": [
+ { "id": 1, "directArtifactIds": [1, 2] },
+ { "id": 2, "directArtifactIds": [3, 4, 5] }],
"actions": [{
"targetId": 1,
"actionKey": "x",
@@ -911,13 +694,9 @@
func TestSimpleSymlink(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 3
- }, {
- "id": 2,
- "pathFragmentId": 5
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 3 },
+ { "id": 2, "pathFragmentId": 5 }],
"actions": [{
"targetId": 1,
"actionKey": "x",
@@ -926,30 +705,14 @@
"outputIds": [2],
"primaryOutputId": 2
}],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [1]
- }],
- "pathFragments": [{
- "id": 1,
- "label": "one"
- }, {
- "id": 2,
- "label": "file_subdir",
- "parentId": 1
- }, {
- "id": 3,
- "label": "file",
- "parentId": 2
- }, {
- "id": 4,
- "label": "symlink_subdir",
- "parentId": 1
- }, {
- "id": 5,
- "label": "symlink",
- "parentId": 4
- }]
+ "depSetOfFiles": [
+ { "id": 1, "directArtifactIds": [1] }],
+ "pathFragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "file_subdir", "parentId": 1 },
+ { "id": 3, "label": "file", "parentId": 2 },
+ { "id": 4, "label": "symlink_subdir", "parentId": 1 },
+ { "id": 5, "label": "symlink", "parentId": 4 }]
}`
actual, _, err := AqueryBuildStatements([]byte(inputString))
@@ -975,13 +738,9 @@
func TestSymlinkQuotesPaths(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 3
- }, {
- "id": 2,
- "pathFragmentId": 5
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 3 },
+ { "id": 2, "pathFragmentId": 5 }],
"actions": [{
"targetId": 1,
"actionKey": "x",
@@ -990,30 +749,14 @@
"outputIds": [2],
"primaryOutputId": 2
}],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [1]
- }],
- "pathFragments": [{
- "id": 1,
- "label": "one"
- }, {
- "id": 2,
- "label": "file subdir",
- "parentId": 1
- }, {
- "id": 3,
- "label": "file",
- "parentId": 2
- }, {
- "id": 4,
- "label": "symlink subdir",
- "parentId": 1
- }, {
- "id": 5,
- "label": "symlink",
- "parentId": 4
- }]
+ "depSetOfFiles": [
+ { "id": 1, "directArtifactIds": [1] }],
+ "pathFragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "file subdir", "parentId": 1 },
+ { "id": 3, "label": "file", "parentId": 2 },
+ { "id": 4, "label": "symlink subdir", "parentId": 1 },
+ { "id": 5, "label": "symlink", "parentId": 4 }]
}`
actual, _, err := AqueryBuildStatements([]byte(inputString))
@@ -1039,16 +782,10 @@
func TestSymlinkMultipleInputs(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }, {
- "id": 2,
- "pathFragmentId": 2
- }, {
- "id": 3,
- "pathFragmentId": 3
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 },
+ { "id": 2, "pathFragmentId": 2 },
+ { "id": 3, "pathFragmentId": 3 }],
"actions": [{
"targetId": 1,
"actionKey": "x",
@@ -1057,20 +794,11 @@
"outputIds": [3],
"primaryOutputId": 3
}],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [1,2]
- }],
- "pathFragments": [{
- "id": 1,
- "label": "file"
- }, {
- "id": 2,
- "label": "other_file"
- }, {
- "id": 3,
- "label": "symlink"
- }]
+ "depSetOfFiles": [{ "id": 1, "directArtifactIds": [1,2] }],
+ "pathFragments": [
+ { "id": 1, "label": "file" },
+ { "id": 2, "label": "other_file" },
+ { "id": 3, "label": "symlink" }]
}`
_, _, err := AqueryBuildStatements([]byte(inputString))
@@ -1080,16 +808,10 @@
func TestSymlinkMultipleOutputs(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }, {
- "id": 2,
- "pathFragmentId": 2
- }, {
- "id": 3,
- "pathFragmentId": 3
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 },
+ { "id": 2, "pathFragmentId": 2 },
+ { "id": 3, "pathFragmentId": 3 }],
"actions": [{
"targetId": 1,
"actionKey": "x",
@@ -1098,20 +820,12 @@
"outputIds": [2,3],
"primaryOutputId": 2
}],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [1]
- }],
- "pathFragments": [{
- "id": 1,
- "label": "file"
- }, {
- "id": 2,
- "label": "symlink"
- }, {
- "id": 3,
- "label": "other_symlink"
- }]
+ "depSetOfFiles": [
+ { "id": 1, "directArtifactIds": [1] }],
+ "pathFragments": [
+ { "id": 1, "label": "file" },
+ { "id": 2, "label": "symlink" },
+ { "id": 3, "label": "other_symlink" }]
}`
_, _, err := AqueryBuildStatements([]byte(inputString))
@@ -1134,18 +848,12 @@
"primaryOutputId": 1,
"executionPlatform": "//build/bazel/platforms:linux_x86_64",
"templateContent": "Test template substitutions: %token1%, %python_binary%",
- "substitutions": [{
- "key": "%token1%",
- "value": "abcd"
- },{
- "key": "%python_binary%",
- "value": "python3"
- }]
+ "substitutions": [
+ { "key": "%token1%", "value": "abcd" },
+ { "key": "%python_binary%", "value": "python3" }]
}],
- "pathFragments": [{
- "id": 1,
- "label": "template_file"
- }]
+ "pathFragments": [
+ { "id": 1, "label": "template_file" }]
}`
actual, _, err := AqueryBuildStatements([]byte(inputString))
@@ -1168,10 +876,8 @@
func TestTemplateExpandActionNoOutput(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 }],
"actions": [{
"targetId": 1,
"actionKey": "x",
@@ -1180,291 +886,79 @@
"primaryOutputId": 1,
"executionPlatform": "//build/bazel/platforms:linux_x86_64",
"templateContent": "Test template substitutions: %token1%, %python_binary%",
- "substitutions": [{
- "key": "%token1%",
- "value": "abcd"
- },{
- "key": "%python_binary%",
- "value": "python3"
- }]
+ "substitutions": [
+ { "key": "%token1%", "value": "abcd" },
+ { "key": "%python_binary%", "value": "python3" }]
}],
- "pathFragments": [{
- "id": 1,
- "label": "template_file"
- }]
+ "pathFragments": [
+ { "id": 1, "label": "template_file" }]
}`
_, _, err := AqueryBuildStatements([]byte(inputString))
assertError(t, err, `Expect 1 output to template expand action, got: output []`)
}
-func TestPythonZipperActionSuccess(t *testing.T) {
+func TestFileWrite(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- },{
- "id": 2,
- "pathFragmentId": 2
- },{
- "id": 3,
- "pathFragmentId": 3
- },{
- "id": 4,
- "pathFragmentId": 4
- },{
- "id": 5,
- "pathFragmentId": 10
- },{
- "id": 10,
- "pathFragmentId": 20
- }],
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 }],
"actions": [{
"targetId": 1,
"actionKey": "x",
- "mnemonic": "TemplateExpand",
+ "mnemonic": "FileWrite",
"configurationId": 1,
"outputIds": [1],
"primaryOutputId": 1,
"executionPlatform": "//build/bazel/platforms:linux_x86_64",
- "templateContent": "Test template substitutions: %token1%, %python_binary%",
- "substitutions": [{
- "key": "%token1%",
- "value": "abcd"
- },{
- "key": "%python_binary%",
- "value": "python3"
- }]
- },{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "PythonZipper",
- "configurationId": 1,
- "arguments": ["../bazel_tools/tools/zip/zipper/zipper", "cC", "python_binary.zip", "__main__.py\u003dbazel-out/k8-fastbuild/bin/python_binary.temp", "__init__.py\u003d", "runfiles/__main__/__init__.py\u003d", "runfiles/__main__/python_binary.py\u003dpython_binary.py", "runfiles/bazel_tools/tools/python/py3wrapper.sh\u003dbazel-out/bazel_tools/k8-fastbuild/bin/tools/python/py3wrapper.sh"],
- "outputIds": [2],
- "inputDepSetIds": [1],
- "primaryOutputId": 2
+ "fileContents": "file data\n"
}],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [4, 3, 5]
- }],
- "pathFragments": [{
- "id": 1,
- "label": "python_binary"
- },{
- "id": 2,
- "label": "python_binary.zip"
- },{
- "id": 3,
- "label": "python_binary.py"
- },{
- "id": 9,
- "label": ".."
- }, {
- "id": 8,
- "label": "bazel_tools",
- "parentId": 9
- }, {
- "id": 7,
- "label": "tools",
- "parentId": 8
- }, {
- "id": 6,
- "label": "zip",
- "parentId": 7
- }, {
- "id": 5,
- "label": "zipper",
- "parentId": 6
- }, {
- "id": 4,
- "label": "zipper",
- "parentId": 5
- },{
- "id": 16,
- "label": "bazel-out"
- },{
- "id": 15,
- "label": "bazel_tools",
- "parentId": 16
- }, {
- "id": 14,
- "label": "k8-fastbuild",
- "parentId": 15
- }, {
- "id": 13,
- "label": "bin",
- "parentId": 14
- }, {
- "id": 12,
- "label": "tools",
- "parentId": 13
- }, {
- "id": 11,
- "label": "python",
- "parentId": 12
- }, {
- "id": 10,
- "label": "py3wrapper.sh",
- "parentId": 11
- },{
- "id": 20,
- "label": "python_binary"
- }]
-}`
+ "pathFragments": [
+ { "id": 1, "label": "foo.manifest" }]
+}
+`
actual, _, err := AqueryBuildStatements([]byte(inputString))
-
if err != nil {
t.Errorf("Unexpected error %q", err)
}
+ assertBuildStatements(t, []BuildStatement{
+ {
+ OutputPaths: []string{"foo.manifest"},
+ Mnemonic: "FileWrite",
+ FileContents: "file data\n",
+ },
+ }, actual)
+}
- expectedBuildStatements := []BuildStatement{
- {
- Command: "/bin/bash -c 'echo \"Test template substitutions: abcd, python3\" | sed \"s/\\\\\\\\n/\\\\n/g\" > python_binary && " +
- "chmod a+x python_binary'",
- InputPaths: []string{"python_binary.zip"},
- OutputPaths: []string{"python_binary"},
- Mnemonic: "TemplateExpand",
- },
- {
- Command: "../bazel_tools/tools/zip/zipper/zipper cC python_binary.zip __main__.py=bazel-out/k8-fastbuild/bin/python_binary.temp " +
- "__init__.py= runfiles/__main__/__init__.py= runfiles/__main__/python_binary.py=python_binary.py && " +
- "../bazel_tools/tools/zip/zipper/zipper x python_binary.zip -d python_binary.runfiles && ln -sf runfiles/__main__ python_binary.runfiles",
- InputPaths: []string{"../bazel_tools/tools/zip/zipper/zipper", "python_binary.py"},
- OutputPaths: []string{"python_binary.zip"},
- Mnemonic: "PythonZipper",
- },
+func TestSourceSymlinkManifest(t *testing.T) {
+ const inputString = `
+{
+ "artifacts": [
+ { "id": 1, "pathFragmentId": 1 }],
+ "actions": [{
+ "targetId": 1,
+ "actionKey": "x",
+ "mnemonic": "SourceSymlinkManifest",
+ "configurationId": 1,
+ "outputIds": [1],
+ "primaryOutputId": 1,
+ "executionPlatform": "//build/bazel/platforms:linux_x86_64",
+ "fileContents": "symlink target\n"
+ }],
+ "pathFragments": [
+ { "id": 1, "label": "foo.manifest" }]
+}
+`
+ actual, _, err := AqueryBuildStatements([]byte(inputString))
+ if err != nil {
+ t.Errorf("Unexpected error %q", err)
}
- assertBuildStatements(t, expectedBuildStatements, actual)
-}
-
-func TestPythonZipperActionNoInput(t *testing.T) {
- const inputString = `
-{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- },{
- "id": 2,
- "pathFragmentId": 2
- }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "PythonZipper",
- "configurationId": 1,
- "arguments": ["../bazel_tools/tools/zip/zipper/zipper", "cC", "python_binary.zip", "__main__.py\u003dbazel-out/k8-fastbuild/bin/python_binary.temp", "__init__.py\u003d", "runfiles/__main__/__init__.py\u003d", "runfiles/__main__/python_binary.py\u003dpython_binary.py", "runfiles/bazel_tools/tools/python/py3wrapper.sh\u003dbazel-out/bazel_tools/k8-fastbuild/bin/tools/python/py3wrapper.sh"],
- "outputIds": [2],
- "primaryOutputId": 2
- }],
- "pathFragments": [{
- "id": 1,
- "label": "python_binary"
- },{
- "id": 2,
- "label": "python_binary.zip"
- }]
-}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
- assertError(t, err, `Expect 1+ input and 1 output to python zipper action, got: input [], output ["python_binary.zip"]`)
-}
-
-func TestPythonZipperActionNoOutput(t *testing.T) {
- const inputString = `
-{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- },{
- "id": 2,
- "pathFragmentId": 2
- },{
- "id": 3,
- "pathFragmentId": 3
- },{
- "id": 4,
- "pathFragmentId": 4
- },{
- "id": 5,
- "pathFragmentId": 10
- }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "PythonZipper",
- "configurationId": 1,
- "arguments": ["../bazel_tools/tools/zip/zipper/zipper", "cC", "python_binary.zip", "__main__.py\u003dbazel-out/k8-fastbuild/bin/python_binary.temp", "__init__.py\u003d", "runfiles/__main__/__init__.py\u003d", "runfiles/__main__/python_binary.py\u003dpython_binary.py", "runfiles/bazel_tools/tools/python/py3wrapper.sh\u003dbazel-out/bazel_tools/k8-fastbuild/bin/tools/python/py3wrapper.sh"],
- "inputDepSetIds": [1]
- }],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [4, 3, 5]
- }],
- "pathFragments": [{
- "id": 1,
- "label": "python_binary"
- },{
- "id": 2,
- "label": "python_binary.zip"
- },{
- "id": 3,
- "label": "python_binary.py"
- },{
- "id": 9,
- "label": ".."
- }, {
- "id": 8,
- "label": "bazel_tools",
- "parentId": 9
- }, {
- "id": 7,
- "label": "tools",
- "parentId": 8
- }, {
- "id": 6,
- "label": "zip",
- "parentId": 7
- }, {
- "id": 5,
- "label": "zipper",
- "parentId": 6
- }, {
- "id": 4,
- "label": "zipper",
- "parentId": 5
- },{
- "id": 16,
- "label": "bazel-out"
- },{
- "id": 15,
- "label": "bazel_tools",
- "parentId": 16
- }, {
- "id": 14,
- "label": "k8-fastbuild",
- "parentId": 15
- }, {
- "id": 13,
- "label": "bin",
- "parentId": 14
- }, {
- "id": 12,
- "label": "tools",
- "parentId": 13
- }, {
- "id": 11,
- "label": "python",
- "parentId": 12
- }, {
- "id": 10,
- "label": "py3wrapper.sh",
- "parentId": 11
- }]
-}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
- assertError(t, err, `Expect 1+ input and 1 output to python zipper action, got: input ["../bazel_tools/tools/zip/zipper/zipper" "python_binary.py"], output []`)
+ assertBuildStatements(t, []BuildStatement{
+ {
+ OutputPaths: []string{"foo.manifest"},
+ Mnemonic: "SourceSymlinkManifest",
+ },
+ }, actual)
}
func assertError(t *testing.T, err error, expected string) {
@@ -1497,7 +991,7 @@
expectedStatement := expected[i]
if differingField := buildStatementEquals(actualStatement, expectedStatement); differingField != "" {
t.Errorf("%s differs\nunexpected build statement %#v.\nexpected: %#v",
- differingField, actualStatement, expected)
+ differingField, actualStatement, expectedStatement)
return
}
}
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 2b54d45..641984b 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -324,3 +324,69 @@
},
})
}
+
+func TestCcLibraryHeadersExportedStaticLibHeadersReexported(t *testing.T) {
+ runCcLibraryHeadersTestCase(t, bp2buildTestCase{
+ description: "cc_library_headers exported_static_lib_headers is reexported",
+ moduleTypeUnderTest: "cc_library_headers",
+ moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
+ filesystem: map[string]string{},
+ blueprint: soongCcLibraryHeadersPreamble + `
+cc_library_headers {
+ name: "foo_headers",
+ export_static_lib_headers: ["foo_export"],
+ static_libs: ["foo_export", "foo_no_reexport"],
+ bazel_module: { bp2build_available: true },
+}
+` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"),
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_headers", "foo_headers", attrNameToString{
+ "deps": `[":foo_export"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryHeadersExportedSharedLibHeadersReexported(t *testing.T) {
+ runCcLibraryHeadersTestCase(t, bp2buildTestCase{
+ description: "cc_library_headers exported_shared_lib_headers is reexported",
+ moduleTypeUnderTest: "cc_library_headers",
+ moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
+ filesystem: map[string]string{},
+ blueprint: soongCcLibraryHeadersPreamble + `
+cc_library_headers {
+ name: "foo_headers",
+ export_shared_lib_headers: ["foo_export"],
+ shared_libs: ["foo_export", "foo_no_reexport"],
+ bazel_module: { bp2build_available: true },
+}
+` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"),
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_headers", "foo_headers", attrNameToString{
+ "deps": `[":foo_export"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryHeadersExportedHeaderLibHeadersReexported(t *testing.T) {
+ runCcLibraryHeadersTestCase(t, bp2buildTestCase{
+ description: "cc_library_headers exported_header_lib_headers is reexported",
+ moduleTypeUnderTest: "cc_library_headers",
+ moduleTypeUnderTestFactory: cc.LibraryHeaderFactory,
+ filesystem: map[string]string{},
+ blueprint: soongCcLibraryHeadersPreamble + `
+cc_library_headers {
+ name: "foo_headers",
+ export_header_lib_headers: ["foo_export"],
+ header_libs: ["foo_export", "foo_no_reexport"],
+ bazel_module: { bp2build_available: true },
+}
+` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"),
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_headers", "foo_headers", attrNameToString{
+ "deps": `[":foo_export"]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index be10e86..36c46a4 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -18,6 +18,7 @@
"android/soong/android"
"android/soong/cc"
"android/soong/genrule"
+ "fmt"
"testing"
)
@@ -204,8 +205,8 @@
":whole_static_lib_1",
":whole_static_lib_2",
]`,
- "sdk_version": `"current"`,
- "min_sdk_version": `"29"`,
+ "sdk_version": `"current"`,
+ "min_sdk_version": `"29"`,
}),
},
})
@@ -1489,3 +1490,72 @@
},
})
}
+
+func TestCcLibraryStaticStl(t *testing.T) {
+ testCases := []struct {
+ desc string
+ prop string
+ attr attrNameToString
+ }{
+ {
+ desc: "c++_shared deduped to libc++",
+ prop: `stl: "c++_shared",`,
+ attr: attrNameToString{
+ "stl": `"libc++"`,
+ },
+ },
+ {
+ desc: "libc++ to libc++",
+ prop: `stl: "libc++",`,
+ attr: attrNameToString{
+ "stl": `"libc++"`,
+ },
+ },
+ {
+ desc: "c++_static to libc++_static",
+ prop: `stl: "c++_static",`,
+ attr: attrNameToString{
+ "stl": `"libc++_static"`,
+ },
+ },
+ {
+ desc: "libc++_static to libc++_static",
+ prop: `stl: "libc++_static",`,
+ attr: attrNameToString{
+ "stl": `"libc++_static"`,
+ },
+ },
+ {
+ desc: "system to system",
+ prop: `stl: "system",`,
+ attr: attrNameToString{
+ "stl": `"system"`,
+ },
+ },
+ {
+ desc: "none to none",
+ prop: `stl: "none",`,
+ attr: attrNameToString{
+ "stl": `"none"`,
+ },
+ },
+ {
+ desc: "empty to empty",
+ attr: attrNameToString{},
+ },
+ }
+ for _, tc := range testCases {
+ t.Run(tc.desc, func(*testing.T) {
+ runCcLibraryStaticTestCase(t, bp2buildTestCase{
+ blueprint: fmt.Sprintf(`cc_library_static {
+ name: "foo",
+ include_build_directory: false,
+ %s
+}`, tc.prop),
+ expectedBazelTargets: []string{
+ makeBazelTarget("cc_library_static", "foo", tc.attr),
+ },
+ })
+ })
+ }
+}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index d891007..fa30d09 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -376,7 +376,8 @@
return
}
if ca.stl == nil {
- ca.stl = stlProps.Stl
+ stl := deduplicateStlInput(*stlProps.Stl)
+ ca.stl = &stl
} else if ca.stl != stlProps.Stl {
ctx.ModuleErrorf("Unsupported conversion: module with different stl for different variants: %s and %s", *ca.stl, stlProps.Stl)
}
diff --git a/cc/cc.go b/cc/cc.go
index f04b6f0..bc95813 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -61,6 +61,9 @@
ctx.TopDown("sanitize_runtime_deps", sanitizerRuntimeDepsMutator).Parallel()
ctx.BottomUp("sanitize_runtime", sanitizerRuntimeMutator).Parallel()
+ ctx.TopDown("fuzz_deps", fuzzMutatorDeps)
+ ctx.BottomUp("fuzz", fuzzMutator)
+
ctx.BottomUp("coverage", coverageMutator).Parallel()
ctx.TopDown("afdo_deps", afdoDepsMutator)
@@ -838,6 +841,7 @@
stl *stl
sanitize *sanitize
coverage *coverage
+ fuzzer *fuzzer
sabi *sabi
vndkdep *vndkdep
lto *lto
@@ -1163,6 +1167,9 @@
if c.coverage != nil {
c.AddProperties(c.coverage.props()...)
}
+ if c.fuzzer != nil {
+ c.AddProperties(c.fuzzer.props()...)
+ }
if c.sabi != nil {
c.AddProperties(c.sabi.props()...)
}
@@ -1680,6 +1687,7 @@
module.stl = &stl{}
module.sanitize = &sanitize{}
module.coverage = &coverage{}
+ module.fuzzer = &fuzzer{}
module.sabi = &sabi{}
module.vndkdep = &vndkdep{}
module.lto = <o{}
@@ -1901,6 +1909,9 @@
if c.coverage != nil {
flags, deps = c.coverage.flags(ctx, flags, deps)
}
+ if c.fuzzer != nil {
+ flags = c.fuzzer.flags(ctx, flags)
+ }
if c.lto != nil {
flags = c.lto.flags(ctx, flags)
}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index b6d196c..24732bf 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -3342,6 +3342,125 @@
`)
}
+func TestAFLFuzzTarget(t *testing.T) {
+ ctx := testCc(t, `
+ cc_afl_fuzz {
+ name: "test_afl_fuzz_target",
+ srcs: ["foo.c"],
+ host_supported: true,
+ static_libs: [
+ "afl_fuzz_static_lib",
+ ],
+ shared_libs: [
+ "afl_fuzz_shared_lib",
+ ],
+ }
+ cc_fuzz {
+ name: "test_fuzz_target",
+ srcs: ["foo.c"],
+ static_libs: [
+ "afl_fuzz_static_lib",
+ "libfuzzer_only_static_lib",
+ ],
+ shared_libs: [
+ "afl_fuzz_shared_lib",
+ ],
+ }
+ cc_library {
+ name: "afl_fuzz_static_lib",
+ host_supported: true,
+ srcs: ["static_file.c"],
+ }
+ cc_library {
+ name: "libfuzzer_only_static_lib",
+ host_supported: true,
+ srcs: ["static_file.c"],
+ }
+ cc_library {
+ name: "afl_fuzz_shared_lib",
+ host_supported: true,
+ srcs: ["shared_file.c"],
+ static_libs: [
+ "second_static_lib",
+ ],
+ }
+ cc_library_headers {
+ name: "libafl_headers",
+ vendor_available: true,
+ host_supported: true,
+ export_include_dirs: [
+ "include",
+ "instrumentation",
+ ],
+ }
+ cc_object {
+ name: "afl-compiler-rt",
+ vendor_available: true,
+ host_supported: true,
+ cflags: [
+ "-fPIC",
+ ],
+ srcs: [
+ "instrumentation/afl-compiler-rt.o.c",
+ ],
+ }
+ cc_library {
+ name: "second_static_lib",
+ host_supported: true,
+ srcs: ["second_file.c"],
+ }
+ filegroup {
+ name: "aflpp_driver",
+ srcs: [
+ "aflpp_driver.c",
+ ],
+ }`)
+
+ checkPcGuardFlag := func(
+ modName string, variantName string, shouldHave bool) {
+ cc := ctx.ModuleForTests(modName, variantName).Rule("cc")
+
+ cFlags, ok := cc.Args["cFlags"]
+ if !ok {
+ t.Errorf("Could not find cFlags for module %s and variant %s",
+ modName, variantName)
+ }
+
+ if strings.Contains(
+ cFlags, "-fsanitize-coverage=trace-pc-guard") != shouldHave {
+ t.Errorf("Flag was found: %t. Expected to find flag: %t. "+
+ "Test failed for module %s and variant %s",
+ !shouldHave, shouldHave, modName, variantName)
+ }
+ }
+
+ for _, vnt := range ctx.ModuleVariantsForTests("libfuzzer_only_static_lib") {
+ if strings.Contains(vnt, "fuzzer_afl") {
+ t.Errorf("libfuzzer_only_static_lib has afl variant and should not")
+ }
+ }
+
+ moduleName := "test_afl_fuzz_target"
+ variantName := "android_arm64_armv8-a_fuzzer_afl"
+ checkPcGuardFlag(moduleName, variantName, true)
+
+ moduleName = "afl_fuzz_static_lib"
+ variantName = "android_arm64_armv8-a_static"
+ checkPcGuardFlag(moduleName, variantName, false)
+ checkPcGuardFlag(moduleName, variantName+"_fuzzer", false)
+ checkPcGuardFlag(moduleName, variantName+"_fuzzer_afl", true)
+
+ moduleName = "second_static_lib"
+ checkPcGuardFlag(moduleName, variantName, false)
+ checkPcGuardFlag(moduleName, variantName+"_fuzzer", false)
+ checkPcGuardFlag(moduleName, variantName+"_fuzzer_afl", true)
+
+ ctx.ModuleForTests("afl_fuzz_shared_lib",
+ "android_arm64_armv8-a_shared").Rule("cc")
+ ctx.ModuleForTests("afl_fuzz_shared_lib",
+ "android_arm64_armv8-a_shared_fuzzer_afl").Rule("cc")
+}
+
// Simple smoke test for the cc_fuzz target that ensures the rule compiles
// correctly.
func TestFuzzTarget(t *testing.T) {
diff --git a/cc/config/global.go b/cc/config/global.go
index c5fde55..6999089 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -280,6 +280,11 @@
"-Wno-string-concatenation",
}
+ llvmNextExtraCommonGlobalCflags = []string{
+ "-Wno-unqualified-std-cast-call",
+ "-Wno-deprecated-non-prototype",
+ }
+
IllegalFlags = []string{
"-w",
}
@@ -361,6 +366,11 @@
if ctx.Config().IsEnvTrue("USE_CCACHE") {
flags = append(flags, "-Wno-unused-command-line-argument")
}
+
+ if ctx.Config().IsEnvTrue("LLVM_NEXT") {
+ flags = append(flags, llvmNextExtraCommonGlobalCflags...)
+ }
+
return strings.Join(flags, " ")
})
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 23d81d6..d6af97f 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -27,29 +27,113 @@
)
func init() {
- android.RegisterModuleType("cc_fuzz", FuzzFactory)
+ android.RegisterModuleType("cc_afl_fuzz", AFLFuzzFactory)
+ android.RegisterModuleType("cc_fuzz", LibFuzzFactory)
android.RegisterSingletonType("cc_fuzz_packaging", fuzzPackagingFactory)
+ android.RegisterSingletonType("cc_afl_fuzz_packaging", fuzzAFLPackagingFactory)
+}
+
+type FuzzProperties struct {
+ AFLEnabled bool `blueprint:"mutated"`
+ AFLAddFlags bool `blueprint:"mutated"`
+}
+
+type fuzzer struct {
+ Properties FuzzProperties
+}
+
+func (fuzzer *fuzzer) flags(ctx ModuleContext, flags Flags) Flags {
+ if fuzzer.Properties.AFLAddFlags {
+ flags.Local.CFlags = append(flags.Local.CFlags, "-fsanitize-coverage=trace-pc-guard")
+ }
+
+ return flags
+}
+
+func (fuzzer *fuzzer) props() []interface{} {
+ return []interface{}{&fuzzer.Properties}
+}
+
+func fuzzMutatorDeps(mctx android.TopDownMutatorContext) {
+ currentModule, ok := mctx.Module().(*Module)
+ if !ok {
+ return
+ }
+
+ if currentModule.fuzzer == nil || !currentModule.fuzzer.Properties.AFLEnabled {
+ return
+ }
+
+ mctx.WalkDeps(func(child android.Module, parent android.Module) bool {
+ c, ok := child.(*Module)
+ if !ok {
+ return false
+ }
+
+ if c.sanitize == nil {
+ return false
+ }
+
+ isFuzzerPointer := c.sanitize.getSanitizerBoolPtr(Fuzzer)
+ if isFuzzerPointer == nil || !*isFuzzerPointer {
+ return false
+ }
+
+ if c.fuzzer == nil {
+ return false
+ }
+
+ c.fuzzer.Properties.AFLEnabled = true
+ c.fuzzer.Properties.AFLAddFlags = true
+ return true
+ })
+}
+
+func fuzzMutator(mctx android.BottomUpMutatorContext) {
+ if c, ok := mctx.Module().(*Module); ok && c.fuzzer != nil {
+ if !c.fuzzer.Properties.AFLEnabled {
+ return
+ }
+
+ if c.Binary() {
+ m := mctx.CreateVariations("afl")
+ m[0].(*Module).fuzzer.Properties.AFLEnabled = true
+ m[0].(*Module).fuzzer.Properties.AFLAddFlags = true
+ } else {
+ m := mctx.CreateVariations("", "afl")
+ m[0].(*Module).fuzzer.Properties.AFLEnabled = false
+ m[0].(*Module).fuzzer.Properties.AFLAddFlags = false
+
+ m[1].(*Module).fuzzer.Properties.AFLEnabled = true
+ m[1].(*Module).fuzzer.Properties.AFLAddFlags = true
+ }
+ }
}
// cc_fuzz creates a host/device fuzzer binary. Host binaries can be found at
// $ANDROID_HOST_OUT/fuzz/, and device binaries can be found at /data/fuzz on
// your device, or $ANDROID_PRODUCT_OUT/data/fuzz in your build tree.
-func FuzzFactory() android.Module {
- module := NewFuzz(android.HostAndDeviceSupported)
+func LibFuzzFactory() android.Module {
+ module := NewFuzzer(android.HostAndDeviceSupported, fuzz.Cc)
return module.Init()
}
-func NewFuzzInstaller() *baseInstaller {
- return NewBaseInstaller("fuzz", "fuzz", InstallInData)
+// cc_afl_fuzz creates a host/device AFL++ fuzzer binary.
+// AFL++ is an open source framework used to fuzz libraries
+// Host binaries can be found at $ANDROID_HOST_OUT/afl_fuzz/ and device
+// binaries can be found at $ANDROID_PRODUCT_OUT/data/afl_fuzz in your
+// build tree
+func AFLFuzzFactory() android.Module {
+ module := NewFuzzer(android.HostAndDeviceSupported, fuzz.AFL)
+ return module.Init()
}
type fuzzBinary struct {
*binaryDecorator
*baseCompiler
-
- fuzzPackagedModule fuzz.FuzzPackagedModule
-
+ fuzzPackagedModule fuzz.FuzzPackagedModule
installedSharedDeps []string
+ fuzzType fuzz.FuzzType
}
func (fuzz *fuzzBinary) fuzzBinary() bool {
@@ -66,11 +150,17 @@
fuzz.binaryDecorator.linkerInit(ctx)
}
-func (fuzz *fuzzBinary) linkerDeps(ctx DepsContext, deps Deps) Deps {
- deps.StaticLibs = append(deps.StaticLibs,
- config.LibFuzzerRuntimeLibrary(ctx.toolchain()))
- deps = fuzz.binaryDecorator.linkerDeps(ctx, deps)
- return deps
+func (fuzzBin *fuzzBinary) linkerDeps(ctx DepsContext, deps Deps) Deps {
+ if fuzzBin.fuzzType == fuzz.AFL {
+ deps.HeaderLibs = append(deps.HeaderLibs, "libafl_headers")
+ deps = fuzzBin.binaryDecorator.linkerDeps(ctx, deps)
+ return deps
+
+ } else {
+ deps.StaticLibs = append(deps.StaticLibs, config.LibFuzzerRuntimeLibrary(ctx.toolchain()))
+ deps = fuzzBin.binaryDecorator.linkerDeps(ctx, deps)
+ return deps
+ }
}
func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
@@ -80,6 +170,7 @@
// target packages.
flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/lib`)
+
return flags
}
@@ -149,63 +240,68 @@
}
func sharedLibraryInstallLocation(
- libraryPath android.Path, isHost bool, archString string) string {
+ libraryPath android.Path, isHost bool, fuzzDir string, archString string) string {
installLocation := "$(PRODUCT_OUT)/data"
if isHost {
installLocation = "$(HOST_OUT)"
}
installLocation = filepath.Join(
- installLocation, "fuzz", archString, "lib", libraryPath.Base())
+ installLocation, fuzzDir, archString, "lib", libraryPath.Base())
return installLocation
}
// Get the device-only shared library symbols install directory.
-func sharedLibrarySymbolsInstallLocation(libraryPath android.Path, archString string) string {
- return filepath.Join("$(PRODUCT_OUT)/symbols/data/fuzz/", archString, "/lib/", libraryPath.Base())
+func sharedLibrarySymbolsInstallLocation(libraryPath android.Path, fuzzDir string, archString string) string {
+ return filepath.Join("$(PRODUCT_OUT)/symbols/data/", fuzzDir, archString, "/lib/", libraryPath.Base())
}
-func (fuzz *fuzzBinary) install(ctx ModuleContext, file android.Path) {
- fuzz.binaryDecorator.baseInstaller.dir = filepath.Join(
- "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
- fuzz.binaryDecorator.baseInstaller.dir64 = filepath.Join(
- "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
- fuzz.binaryDecorator.baseInstaller.install(ctx, file)
+func (fuzzBin *fuzzBinary) install(ctx ModuleContext, file android.Path) {
+ installBase := "fuzz"
+ if fuzzBin.fuzzType == fuzz.AFL {
+ installBase = "afl_fuzz"
+ }
- fuzz.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzz.fuzzPackagedModule.FuzzProperties.Corpus)
+ fuzzBin.binaryDecorator.baseInstaller.dir = filepath.Join(
+ installBase, ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
+ fuzzBin.binaryDecorator.baseInstaller.dir64 = filepath.Join(
+ installBase, ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
+ fuzzBin.binaryDecorator.baseInstaller.install(ctx, file)
+
+ fuzzBin.fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzzBin.fuzzPackagedModule.FuzzProperties.Corpus)
builder := android.NewRuleBuilder(pctx, ctx)
intermediateDir := android.PathForModuleOut(ctx, "corpus")
- for _, entry := range fuzz.fuzzPackagedModule.Corpus {
+ for _, entry := range fuzzBin.fuzzPackagedModule.Corpus {
builder.Command().Text("cp").
Input(entry).
Output(intermediateDir.Join(ctx, entry.Base()))
}
builder.Build("copy_corpus", "copy corpus")
- fuzz.fuzzPackagedModule.CorpusIntermediateDir = intermediateDir
+ fuzzBin.fuzzPackagedModule.CorpusIntermediateDir = intermediateDir
- fuzz.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzz.fuzzPackagedModule.FuzzProperties.Data)
+ fuzzBin.fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzzBin.fuzzPackagedModule.FuzzProperties.Data)
builder = android.NewRuleBuilder(pctx, ctx)
intermediateDir = android.PathForModuleOut(ctx, "data")
- for _, entry := range fuzz.fuzzPackagedModule.Data {
+ for _, entry := range fuzzBin.fuzzPackagedModule.Data {
builder.Command().Text("cp").
Input(entry).
Output(intermediateDir.Join(ctx, entry.Rel()))
}
builder.Build("copy_data", "copy data")
- fuzz.fuzzPackagedModule.DataIntermediateDir = intermediateDir
+ fuzzBin.fuzzPackagedModule.DataIntermediateDir = intermediateDir
- if fuzz.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
- fuzz.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzz.fuzzPackagedModule.FuzzProperties.Dictionary)
- if fuzz.fuzzPackagedModule.Dictionary.Ext() != ".dict" {
+ if fuzzBin.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
+ fuzzBin.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzzBin.fuzzPackagedModule.FuzzProperties.Dictionary)
+ if fuzzBin.fuzzPackagedModule.Dictionary.Ext() != ".dict" {
ctx.PropertyErrorf("dictionary",
"Fuzzer dictionary %q does not have '.dict' extension",
- fuzz.fuzzPackagedModule.Dictionary.String())
+ fuzzBin.fuzzPackagedModule.Dictionary.String())
}
}
- if fuzz.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
+ if fuzzBin.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
- android.WriteFileRule(ctx, configPath, fuzz.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
- fuzz.fuzzPackagedModule.Config = configPath
+ android.WriteFileRule(ctx, configPath, fuzzBin.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
+ fuzzBin.fuzzPackagedModule.Config = configPath
}
// Grab the list of required shared libraries.
@@ -225,31 +321,36 @@
})
for _, lib := range sharedLibraries {
- fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
+ fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
sharedLibraryInstallLocation(
- lib, ctx.Host(), ctx.Arch().ArchType.String()))
+ lib, ctx.Host(), installBase, ctx.Arch().ArchType.String()))
// Also add the dependency on the shared library symbols dir.
if !ctx.Host() {
- fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
- sharedLibrarySymbolsInstallLocation(lib, ctx.Arch().ArchType.String()))
+ fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
+ sharedLibrarySymbolsInstallLocation(lib, installBase, ctx.Arch().ArchType.String()))
}
}
}
-func NewFuzz(hod android.HostOrDeviceSupported) *Module {
+func NewFuzzer(hod android.HostOrDeviceSupported, fuzzType fuzz.FuzzType) *Module {
module, binary := newBinary(hod, false)
+ baseInstallerPath := "fuzz"
+ if fuzzType == fuzz.AFL {
+ baseInstallerPath = "afl_fuzz"
+ }
- binary.baseInstaller = NewFuzzInstaller()
+ binary.baseInstaller = NewBaseInstaller(baseInstallerPath, baseInstallerPath, InstallInData)
module.sanitize.SetSanitizer(Fuzzer, true)
- fuzz := &fuzzBinary{
+ fuzzBin := &fuzzBinary{
binaryDecorator: binary,
baseCompiler: NewBaseCompiler(),
+ fuzzType: fuzzType,
}
- module.compiler = fuzz
- module.linker = fuzz
- module.installer = fuzz
+ module.compiler = fuzzBin
+ module.linker = fuzzBin
+ module.installer = fuzzBin
// The fuzzer runtime is not present for darwin host modules, disable cc_fuzz modules when targeting darwin.
android.AddLoadHook(module, func(ctx android.LoadHookContext) {
@@ -268,6 +369,17 @@
ctx.AppendProperties(&disableDarwinAndLinuxBionic)
})
+ if fuzzType == fuzz.AFL {
+ // Add cc_objects to Srcs
+ fuzzBin.baseCompiler.Properties.Srcs = append(fuzzBin.baseCompiler.Properties.Srcs, ":aflpp_driver", ":afl-compiler-rt")
+ module.fuzzer.Properties.AFLEnabled = true
+ module.compiler.appendCflags([]string{
+ "-Wno-unused-result",
+ "-Wno-unused-parameter",
+ "-Wno-unused-function",
+ })
+ }
+
return module
}
@@ -275,10 +387,30 @@
// their architecture & target/host specific zip file.
type ccFuzzPackager struct {
fuzz.FuzzPackager
+ fuzzPackagingArchModules string
+ fuzzTargetSharedDepsInstallPairs string
+ allFuzzTargetsName string
}
func fuzzPackagingFactory() android.Singleton {
- return &ccFuzzPackager{}
+
+ fuzzPackager := &ccFuzzPackager{
+ fuzzPackagingArchModules: "SOONG_FUZZ_PACKAGING_ARCH_MODULES",
+ fuzzTargetSharedDepsInstallPairs: "FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
+ allFuzzTargetsName: "ALL_FUZZ_TARGETS",
+ }
+ fuzzPackager.FuzzType = fuzz.Cc
+ return fuzzPackager
+}
+
+func fuzzAFLPackagingFactory() android.Singleton {
+ fuzzPackager := &ccFuzzPackager{
+ fuzzPackagingArchModules: "SOONG_AFL_FUZZ_PACKAGING_ARCH_MODULES",
+ fuzzTargetSharedDepsInstallPairs: "AFL_FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
+ allFuzzTargetsName: "ALL_AFL_FUZZ_TARGETS",
+ }
+ fuzzPackager.FuzzType = fuzz.AFL
+ return fuzzPackager
}
func (s *ccFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
@@ -306,8 +438,9 @@
return
}
+ sharedLibsInstallDirPrefix := "lib"
fuzzModule, ok := ccModule.compiler.(*fuzzBinary)
- if !ok {
+ if !ok || fuzzModule.fuzzType != s.FuzzType {
return
}
@@ -316,8 +449,18 @@
hostOrTargetString = "host"
}
+ fpm := fuzz.FuzzPackagedModule{}
+ if ok {
+ fpm = fuzzModule.fuzzPackagedModule
+ }
+
+ intermediatePath := "fuzz"
+ if s.FuzzType == fuzz.AFL {
+ intermediatePath = "afl_fuzz"
+ }
+
archString := ccModule.Arch().ArchType.String()
- archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
+ archDir := android.PathForIntermediates(ctx, intermediatePath, hostOrTargetString, archString)
archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
// Grab the list of required shared libraries.
@@ -327,22 +470,21 @@
builder := android.NewRuleBuilder(pctx, ctx)
// Package the corpus, data, dict and config into a zipfile.
- files = s.PackageArtifacts(ctx, module, fuzzModule.fuzzPackagedModule, archDir, builder)
+ files = s.PackageArtifacts(ctx, module, fpm, archDir, builder)
// Package shared libraries
- files = append(files, GetSharedLibsToZip(sharedLibraries, ccModule, &s.FuzzPackager, archString, &sharedLibraryInstalled)...)
+ files = append(files, GetSharedLibsToZip(sharedLibraries, ccModule, &s.FuzzPackager, archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...)
// The executable.
files = append(files, fuzz.FileToZip{ccModule.UnstrippedOutputFile(), ""})
- archDirs[archOs], ok = s.BuildZipFile(ctx, module, fuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
+ archDirs[archOs], ok = s.BuildZipFile(ctx, module, fpm, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
if !ok {
return
}
})
- s.CreateFuzzPackage(ctx, archDirs, fuzz.Cc, pctx)
-
+ s.CreateFuzzPackage(ctx, archDirs, s.FuzzType, pctx)
}
func (s *ccFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
@@ -353,27 +495,34 @@
// ready to handle phony targets created in Soong. In the meantime, this
// exports the phony 'fuzz' target and dependencies on packages to
// core/main.mk so that we can use dist-for-goals.
- ctx.Strict("SOONG_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
- ctx.Strict("FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
+
+ ctx.Strict(s.fuzzPackagingArchModules, strings.Join(packages, " "))
+
+ ctx.Strict(s.fuzzTargetSharedDepsInstallPairs,
strings.Join(s.FuzzPackager.SharedLibInstallStrings, " "))
// Preallocate the slice of fuzz targets to minimise memory allocations.
- s.PreallocateSlice(ctx, "ALL_FUZZ_TARGETS")
+ s.PreallocateSlice(ctx, s.allFuzzTargetsName)
}
// GetSharedLibsToZip finds and marks all the transiently-dependent shared libraries for
// packaging.
-func GetSharedLibsToZip(sharedLibraries android.Paths, module LinkableInterface, s *fuzz.FuzzPackager, archString string, sharedLibraryInstalled *map[string]bool) []fuzz.FileToZip {
+func GetSharedLibsToZip(sharedLibraries android.Paths, module LinkableInterface, s *fuzz.FuzzPackager, archString string, destinationPathPrefix string, sharedLibraryInstalled *map[string]bool) []fuzz.FileToZip {
var files []fuzz.FileToZip
+ fuzzDir := "fuzz"
+ if s.FuzzType == fuzz.AFL {
+ fuzzDir = "afl_fuzz"
+ }
+
for _, library := range sharedLibraries {
- files = append(files, fuzz.FileToZip{library, "lib"})
+ files = append(files, fuzz.FileToZip{library, destinationPathPrefix})
// For each architecture-specific shared library dependency, we need to
// install it to the output directory. Setup the install destination here,
// which will be used by $(copy-many-files) in the Make backend.
installDestination := sharedLibraryInstallLocation(
- library, module.Host(), archString)
+ library, module.Host(), fuzzDir, archString)
if (*sharedLibraryInstalled)[installDestination] {
continue
}
@@ -391,7 +540,7 @@
// we want symbolization tools (like `stack`) to be able to find the symbols
// in $ANDROID_PRODUCT_OUT/symbols automagically.
if !module.Host() {
- symbolsInstallDestination := sharedLibrarySymbolsInstallLocation(library, archString)
+ symbolsInstallDestination := sharedLibrarySymbolsInstallLocation(library, fuzzDir, archString)
symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$")
s.SharedLibInstallStrings = append(s.SharedLibInstallStrings,
library.String()+":"+symbolsInstallDestination)
diff --git a/cc/library_headers.go b/cc/library_headers.go
index 77c2523..970d8d1 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -125,6 +125,7 @@
baseAttributes := bp2BuildParseBaseProps(ctx, module)
exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, &baseAttributes.includes)
linkerAttrs := baseAttributes.linkerAttributes
+ (&linkerAttrs.deps).Append(linkerAttrs.dynamicDeps)
attrs := &bazelCcLibraryHeadersAttributes{
Export_includes: exportedIncludes.Includes,
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 92987f7..86472a2 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -430,7 +430,7 @@
}
// Enable Memtag for all components in the include paths (for Aarch64 only)
- if ctx.Arch().ArchType == android.Arm64 {
+ if ctx.Arch().ArchType == android.Arm64 && ctx.toolchain().Bionic() {
if ctx.Config().MemtagHeapSyncEnabledForPath(ctx.ModuleDir()) {
if s.Memtag_heap == nil {
s.Memtag_heap = proptools.BoolPtr(true)
@@ -460,17 +460,17 @@
}
// HWASan requires AArch64 hardware feature (top-byte-ignore).
- if ctx.Arch().ArchType != android.Arm64 {
+ if ctx.Arch().ArchType != android.Arm64 || !ctx.toolchain().Bionic() {
s.Hwaddress = nil
}
// SCS is only implemented on AArch64.
- if ctx.Arch().ArchType != android.Arm64 {
+ if ctx.Arch().ArchType != android.Arm64 || !ctx.toolchain().Bionic() {
s.Scs = nil
}
// Memtag_heap is only implemented on AArch64.
- if ctx.Arch().ArchType != android.Arm64 {
+ if ctx.Arch().ArchType != android.Arm64 || !ctx.toolchain().Bionic() {
s.Memtag_heap = nil
}
@@ -710,8 +710,13 @@
// Host sanitizers only link symbols in the final executable, so
// there will always be undefined symbols in intermediate libraries.
_, flags.Global.LdFlags = removeFromList("-Wl,--no-undefined", flags.Global.LdFlags)
+ }
- // non-Bionic toolchain prebuilts are missing UBSan's vptr and function san
+ if !ctx.toolchain().Bionic() {
+ // non-Bionic toolchain prebuilts are missing UBSan's vptr and function san.
+ // Musl toolchain prebuilts have vptr and function sanitizers, but enabling them
+ // implicitly enables RTTI which causes RTTI mismatch issues with dependencies.
+
flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize=vptr,function")
}
diff --git a/cc/stl.go b/cc/stl.go
index 0f2a878..85a06da 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -25,6 +25,16 @@
return family
}
+func deduplicateStlInput(stl string) string {
+ switch stl {
+ case "c++_shared":
+ return "libc++"
+ case "c++_static":
+ return "libc++_static"
+ }
+ return stl
+}
+
func getNdkStlFamilyAndLinkType(m LinkableInterface) (string, string) {
stl := m.SelectedStl()
switch stl {
@@ -66,18 +76,18 @@
} else if ctx.header() {
s = "none"
}
+ if s == "none" {
+ return ""
+ }
+ s = deduplicateStlInput(s)
if ctx.useSdk() && ctx.Device() {
switch s {
case "", "system":
return "ndk_system"
- case "c++_shared", "c++_static":
- return "ndk_lib" + s
case "libc++":
return "ndk_libc++_shared"
case "libc++_static":
return "ndk_libc++_static"
- case "none":
- return ""
default:
ctx.ModuleErrorf("stl: %q is not a supported STL with sdk_version set", s)
return ""
@@ -87,8 +97,6 @@
case "libc++", "libc++_static", "":
// Only use static libc++ for Windows.
return "libc++_static"
- case "none":
- return ""
default:
ctx.ModuleErrorf("stl: %q is not a supported STL for windows", s)
return ""
@@ -97,12 +105,6 @@
switch s {
case "libc++", "libc++_static":
return s
- case "c++_shared":
- return "libc++"
- case "c++_static":
- return "libc++_static"
- case "none":
- return ""
case "", "system":
if ctx.static() {
return "libc++_static"
diff --git a/cc/testing.go b/cc/testing.go
index 077fcda..6b858d5 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -534,7 +534,8 @@
android.PrepareForTestWithAndroidBuildComponents,
android.FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
+ ctx.RegisterModuleType("cc_fuzz", LibFuzzFactory)
+ ctx.RegisterModuleType("cc_afl_fuzz", AFLFuzzFactory)
ctx.RegisterModuleType("cc_test", TestFactory)
ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
@@ -648,7 +649,8 @@
func CreateTestContext(config android.Config) *android.TestContext {
ctx := android.NewTestArchContext(config)
genrule.RegisterGenruleBuildComponents(ctx)
- ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
+ ctx.RegisterModuleType("cc_fuzz", LibFuzzFactory)
+ ctx.RegisterModuleType("cc_afl_fuzz", AFLFuzzFactory)
ctx.RegisterModuleType("cc_test", TestFactory)
ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index de139c4..d8011d6 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -394,10 +394,14 @@
if !android.PrefixInList(preoptFlags, "--compiler-filter=") {
var compilerFilter string
if systemServerJars.ContainsJar(module.Name) {
- // Jars of system server, use the product option if it is set, speed otherwise.
if global.SystemServerCompilerFilter != "" {
+ // Use the product option if it is set.
compilerFilter = global.SystemServerCompilerFilter
+ } else if profile != nil {
+ // Use "speed-profile" for system server jars that have a profile.
+ compilerFilter = "speed-profile"
} else {
+ // Use "speed" for system server jars that do not have a profile.
compilerFilter = "speed"
}
} else if contains(global.SpeedApps, module.Name) || contains(global.SystemServerApps, module.Name) {
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index 700cdf0..1a87b30 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -18,6 +18,7 @@
import (
"encoding/json"
+ "fmt"
"sort"
"strings"
@@ -26,12 +27,13 @@
"android/soong/android"
)
-type Lang string
+type FuzzType string
const (
- Cc Lang = ""
- Rust Lang = "rust"
- Java Lang = "java"
+ Cc FuzzType = ""
+ Rust FuzzType = "rust"
+ Java FuzzType = "java"
+ AFL FuzzType = "AFL"
)
var BoolDefault = proptools.BoolDefault
@@ -46,6 +48,7 @@
Packages android.Paths
FuzzTargets map[string]bool
SharedLibInstallStrings []string
+ FuzzType FuzzType
}
type FileToZip struct {
@@ -59,9 +62,65 @@
Dir string
}
+type PrivilegedLevel string
+
+const (
+ // Environment with the most minimal permissions.
+ Constrained PrivilegedLevel = "Constrained"
+ // Typical execution environment running unprivileged code.
+ Unprivileged = "Unprivileged"
+ // May have access to elevated permissions.
+ Privileged = "Privileged"
+ // Trusted computing base.
+ Tcb = "TCB"
+ // Bootloader chain.
+ Bootloader = "Bootloader"
+ // Tusted execution environment.
+ Tee = "Tee"
+ // Secure enclave.
+ Se = "Se"
+ // Other.
+ Other = "Other"
+)
+
+func IsValidConfig(fuzzModule FuzzPackagedModule, moduleName string) bool {
+ var config = fuzzModule.FuzzProperties.Fuzz_config
+ if config != nil {
+ var level = PrivilegedLevel(config.Privilege_level)
+ if level != "" {
+ switch level {
+ case Constrained, Unprivileged, Privileged, Tcb, Bootloader, Tee, Se, Other:
+ return true
+ }
+ panic(fmt.Errorf("Invalid privileged level in fuzz config in %s", moduleName))
+ }
+ return true
+ } else {
+ return false
+ }
+}
+
type FuzzConfig struct {
// Email address of people to CC on bugs or contact about this fuzz target.
Cc []string `json:"cc,omitempty"`
+ // A brief description of what the fuzzed code does.
+ Description string `json:"description,omitempty"`
+ // Can this code be triggered remotely or only locally.
+ Remotely_accessible bool `json:"remotely_accessible,omitempty"`
+ // Is the fuzzed code host only, i.e. test frameworks or support utilities.
+ Host_only bool `json:"host_only,omitempty"`
+ // Can third party/untrusted apps supply data to fuzzed code.
+ Untrusted_data bool `json:"untrusted_data,omitempty"`
+ // Is the code being fuzzed in a privileged, constrained or any other
+ // context from:
+ // https://source.android.com/security/overview/updates-resources#context_types.
+ Privilege_level PrivilegedLevel `json:"privilege_level,omitempty"`
+ // Can the fuzzed code isolated or can be called by multiple users/processes.
+ Isolated bool `json:"users_isolation,omitempty"`
+ // When code was relaeased or will be released.
+ Production_date string `json:"production_date,omitempty"`
+ // Prevents critical service functionality like phone calls, bluetooth, etc.
+ Critical bool `json:"critical,omitempty"`
// Specify whether to enable continuous fuzzing on devices. Defaults to true.
Fuzz_on_haiku_device *bool `json:"fuzz_on_haiku_device,omitempty"`
// Specify whether to enable continuous fuzzing on host. Defaults to true.
@@ -157,7 +216,7 @@
}
// Additional fuzz config.
- if fuzzModule.Config != nil {
+ if fuzzModule.Config != nil && IsValidConfig(fuzzModule, module.Name()) {
files = append(files, FileToZip{fuzzModule.Config, ""})
}
@@ -208,7 +267,7 @@
return string(b)
}
-func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs map[ArchOs][]FileToZip, lang Lang, pctx android.PackageContext) {
+func (s *FuzzPackager) CreateFuzzPackage(ctx android.SingletonContext, archDirs map[ArchOs][]FileToZip, fuzzType FuzzType, pctx android.PackageContext) {
var archOsList []ArchOs
for archOs := range archDirs {
archOsList = append(archOsList, archOs)
@@ -221,12 +280,15 @@
hostOrTarget := archOs.HostOrTarget
builder := android.NewRuleBuilder(pctx, ctx)
zipFileName := "fuzz-" + hostOrTarget + "-" + arch + ".zip"
- if lang == Rust {
+ if fuzzType == Rust {
zipFileName = "fuzz-rust-" + hostOrTarget + "-" + arch + ".zip"
}
- if lang == Java {
+ if fuzzType == Java {
zipFileName = "fuzz-java-" + hostOrTarget + "-" + arch + ".zip"
}
+ if fuzzType == AFL {
+ zipFileName = "fuzz-afl-" + hostOrTarget + "-" + arch + ".zip"
+ }
outputFile := android.PathForOutput(ctx, zipFileName)
s.Packages = append(s.Packages, outputFile)
@@ -237,7 +299,6 @@
Flag("-L 0") // No need to try and re-compress the zipfiles.
for _, fileToZip := range filesToZip {
-
if fileToZip.DestinationPathPrefix != "" {
command.FlagWithArg("-P ", fileToZip.DestinationPathPrefix)
} else {
@@ -256,6 +317,7 @@
for target, _ := range s.FuzzTargets {
fuzzTargets = append(fuzzTargets, target)
}
+
sort.Strings(fuzzTargets)
ctx.Strict(targets, strings.Join(fuzzTargets, " "))
}
diff --git a/java/aar.go b/java/aar.go
index 00ff7e7..cf84309 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -678,6 +678,10 @@
return a.SdkVersion(ctx)
}
+func (a *AARImport) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
+ return android.SdkSpecFrom(ctx, "")
+}
+
func (a *AARImport) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
return a.SdkVersion(ctx)
}
diff --git a/java/android_manifest.go b/java/android_manifest.go
index a297b2c..c61823d 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -136,6 +136,11 @@
ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
}
+ replaceMaxSdkVersionPlaceholder, err := params.SdkContext.ReplaceMaxSdkVersionPlaceholder(ctx).EffectiveVersion(ctx)
+ if err != nil {
+ ctx.ModuleErrorf("invalid ReplaceMaxSdkVersionPlaceholder: %s", err)
+ }
+
if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
deps = append(deps, ApiFingerprintPath(ctx))
@@ -145,6 +150,7 @@
ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
}
args = append(args, "--minSdkVersion ", minSdkVersion)
+ args = append(args, "--replaceMaxSdkVersionPlaceholder ", strconv.Itoa(replaceMaxSdkVersionPlaceholder.FinalOrFutureInt()))
args = append(args, "--raise-min-sdk-version")
}
diff --git a/java/base.go b/java/base.go
index 0900daa..94daf37 100644
--- a/java/base.go
+++ b/java/base.go
@@ -204,6 +204,10 @@
// Defaults to empty string "". See sdk_version for possible values.
Max_sdk_version *string
+ // if not blank, set the maxSdkVersion properties of permission and uses-permission tags.
+ // Defaults to empty string "". See sdk_version for possible values.
+ Replace_max_sdk_version_placeholder *string
+
// if not blank, set the targetSdkVersion in the AndroidManifest.xml.
// Defaults to sdk_version if not set. See sdk_version for possible values.
Target_sdk_version *string
@@ -649,6 +653,11 @@
return android.SdkSpecFrom(ctx, maxSdkVersion)
}
+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) MinSdkVersionString() string {
return j.minSdkVersion.Raw
}
@@ -1418,17 +1427,18 @@
j.implementationAndResourcesJar = implementationAndResourcesJar
// Enable dex compilation for the APEX variants, unless it is disabled explicitly
+ compileDex := j.dexProperties.Compile_dex
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
if j.DirectlyInAnyApex() && !apexInfo.IsForPlatform() {
- if j.dexProperties.Compile_dex == nil {
- j.dexProperties.Compile_dex = proptools.BoolPtr(true)
+ if compileDex == nil {
+ compileDex = proptools.BoolPtr(true)
}
if j.deviceProperties.Hostdex == nil {
j.deviceProperties.Hostdex = proptools.BoolPtr(true)
}
}
- if ctx.Device() && (Bool(j.properties.Installable) || Bool(j.dexProperties.Compile_dex)) {
+ if ctx.Device() && (Bool(j.properties.Installable) || Bool(compileDex)) {
if j.hasCode(ctx) {
if j.shouldInstrumentStatic(ctx) {
j.dexer.extraProguardFlagFiles = append(j.dexer.extraProguardFlagFiles,
@@ -1484,11 +1494,30 @@
}
if ctx.Device() {
- lintSDKVersion := func(sdkSpec android.SdkSpec) android.ApiLevel {
+ lintSDKVersion := func(sdkSpec android.SdkSpec) int {
if v := sdkSpec.ApiLevel; !v.IsPreview() {
- return v
+ return v.FinalInt()
} else {
- return ctx.Config().DefaultAppTargetSdk(ctx)
+ // When running metalava, we pass --version-codename. When that value
+ // is not REL, metalava will add 1 to the --current-version argument.
+ // On old branches, PLATFORM_SDK_VERSION is the latest version (for that
+ // branch) and the codename is REL, except potentially on the most
+ // recent non-master branch. On that branch, it goes through two other
+ // phases before it gets to the phase previously described:
+ // - PLATFORM_SDK_VERSION has not been updated yet, and the codename
+ // is not rel. This happens for most of the internal branch's life
+ // while the branch has been cut but is still under active development.
+ // - PLATFORM_SDK_VERSION has been set, but the codename is still not
+ // REL. This happens briefly during the release process. During this
+ // state the code to add --current-version is commented out, and then
+ // that commenting out is reverted after the codename is set to REL.
+ // On the master branch, the PLATFORM_SDK_VERSION always represents a
+ // prior version and the codename is always non-REL.
+ //
+ // We need to add one here to match metalava adding 1. Technically
+ // this means that in the state described in the second bullet point
+ // above, this number is 1 higher than it should be.
+ return ctx.Config().PlatformSdkVersion().FinalInt() + 1
}
}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 0591012..f08b64b 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -32,12 +32,7 @@
func init() {
registerBootclasspathFragmentBuildComponents(android.InitRegistrationContext)
- android.RegisterSdkMemberType(&bootclasspathFragmentMemberType{
- SdkMemberTypeBase: android.SdkMemberTypeBase{
- PropertyName: "bootclasspath_fragments",
- SupportsSdk: true,
- },
- })
+ android.RegisterSdkMemberType(BootclasspathFragmentSdkMemberType)
}
func registerBootclasspathFragmentBuildComponents(ctx android.RegistrationContext) {
@@ -46,6 +41,15 @@
ctx.RegisterModuleType("prebuilt_bootclasspath_fragment", prebuiltBootclasspathFragmentFactory)
}
+// BootclasspathFragmentSdkMemberType is the member type used to add bootclasspath_fragments to
+// the SDK snapshot. It is exported for use by apex.
+var BootclasspathFragmentSdkMemberType = &bootclasspathFragmentMemberType{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
+ PropertyName: "bootclasspath_fragments",
+ SupportsSdk: true,
+ },
+}
+
type bootclasspathFragmentContentDependencyTag struct {
blueprint.BaseDependencyTag
}
diff --git a/java/dexpreopt.go_v1 b/java/dexpreopt.go_v1
deleted file mode 100644
index 0adaf99..0000000
--- a/java/dexpreopt.go_v1
+++ /dev/null
@@ -1,404 +0,0 @@
-// Copyright 2018 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package java
-
-import (
- "path/filepath"
- "strings"
-
- "android/soong/android"
- "android/soong/dexpreopt"
-)
-
-type DexpreopterInterface interface {
- IsInstallable() bool // Structs that embed dexpreopter must implement this.
- dexpreoptDisabled(ctx android.BaseModuleContext) bool
- DexpreoptBuiltInstalledForApex() []dexpreopterInstall
- AndroidMkEntriesForApex() []android.AndroidMkEntries
-}
-
-type dexpreopterInstall struct {
- // A unique name to distinguish an output from others for the same java library module. Usually in
- // the form of `<arch>-<encoded-path>.odex/vdex/art`.
- name string
-
- // The name of the input java module.
- moduleName string
-
- // The path to the dexpreopt output on host.
- outputPathOnHost android.Path
-
- // The directory on the device for the output to install to.
- installDirOnDevice android.InstallPath
-
- // The basename (the last segment of the path) for the output to install as.
- installFileOnDevice string
-}
-
-// The full module name of the output in the makefile.
-func (install *dexpreopterInstall) FullModuleName() string {
- return install.moduleName + install.SubModuleName()
-}
-
-// The sub-module name of the output in the makefile (the name excluding the java module name).
-func (install *dexpreopterInstall) SubModuleName() string {
- return "-dexpreopt-" + install.name
-}
-
-// Returns Make entries for installing the file.
-//
-// This function uses a value receiver rather than a pointer receiver to ensure that the object is
-// safe to use in `android.AndroidMkExtraEntriesFunc`.
-func (install dexpreopterInstall) ToMakeEntries() android.AndroidMkEntries {
- return android.AndroidMkEntries{
- Class: "ETC",
- SubName: install.SubModuleName(),
- OutputFile: android.OptionalPathForPath(install.outputPathOnHost),
- ExtraEntries: []android.AndroidMkExtraEntriesFunc{
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.SetString("LOCAL_MODULE_PATH", install.installDirOnDevice.String())
- entries.SetString("LOCAL_INSTALLED_MODULE_STEM", install.installFileOnDevice)
- entries.SetString("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", "false")
- },
- },
- }
-}
-
-type dexpreopter struct {
- dexpreoptProperties DexpreoptProperties
-
- installPath android.InstallPath
- uncompressedDex bool
- isSDKLibrary bool
- isApp bool
- isTest bool
- isPresignedPrebuilt bool
- preventInstall bool
-
- manifestFile android.Path
- statusFile android.WritablePath
- enforceUsesLibs bool
- classLoaderContexts dexpreopt.ClassLoaderContextMap
-
- // See the `dexpreopt` function for details.
- builtInstalled string
- builtInstalledForApex []dexpreopterInstall
-
- // The config is used for two purposes:
- // - Passing dexpreopt information about libraries from Soong to Make. This is needed when
- // a <uses-library> is defined in Android.bp, but used in Android.mk (see dex_preopt_config_merger.py).
- // Note that dexpreopt.config might be needed even if dexpreopt is disabled for the library itself.
- // - Dexpreopt post-processing (using dexpreopt artifacts from a prebuilt system image to incrementally
- // dexpreopt another partition).
- configPath android.WritablePath
-}
-
-type DexpreoptProperties struct {
- Dex_preopt struct {
- // If false, prevent dexpreopting. Defaults to true.
- Enabled *bool
-
- // If true, generate an app image (.art file) for this module.
- App_image *bool
-
- // If true, use a checked-in profile to guide optimization. Defaults to false unless
- // a matching profile is set or a profile is found in PRODUCT_DEX_PREOPT_PROFILE_DIR
- // that matches the name of this module, in which case it is defaulted to true.
- Profile_guided *bool
-
- // If set, provides the path to profile relative to the Android.bp file. If not set,
- // defaults to searching for a file that matches the name of this module in the default
- // profile location set by PRODUCT_DEX_PREOPT_PROFILE_DIR, or empty if not found.
- Profile *string `android:"path"`
- }
-}
-
-func init() {
- dexpreopt.DexpreoptRunningInSoong = true
-}
-
-func isApexVariant(ctx android.BaseModuleContext) bool {
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- return !apexInfo.IsForPlatform()
-}
-
-func forPrebuiltApex(ctx android.BaseModuleContext) bool {
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- return apexInfo.ForPrebuiltApex
-}
-
-func moduleName(ctx android.BaseModuleContext) string {
- // Remove the "prebuilt_" prefix if the module is from a prebuilt because the prefix is not
- // expected by dexpreopter.
- return android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName())
-}
-
-func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
- if !ctx.Device() {
- return true
- }
-
- if d.isTest {
- return true
- }
-
- if !BoolDefault(d.dexpreoptProperties.Dex_preopt.Enabled, true) {
- return true
- }
-
- // If the module is from a prebuilt APEX, it shouldn't be installable, but it can still be
- // dexpreopted.
- if !ctx.Module().(DexpreopterInterface).IsInstallable() && !forPrebuiltApex(ctx) {
- return true
- }
-
- if !android.IsModulePreferred(ctx.Module()) {
- return true
- }
-
- global := dexpreopt.GetGlobalConfig(ctx)
-
- if global.DisablePreopt {
- return true
- }
-
- if inList(moduleName(ctx), global.DisablePreoptModules) {
- return true
- }
-
- isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx))
- if isApexVariant(ctx) {
- // Don't preopt APEX variant module unless the module is an APEX system server jar and we are
- // building the entire system image.
- if !isApexSystemServerJar || ctx.Config().UnbundledBuild() {
- return true
- }
- } else {
- // Don't preopt the platform variant of an APEX system server jar to avoid conflicts.
- if isApexSystemServerJar {
- return true
- }
- }
-
- // TODO: contains no java code
-
- return false
-}
-
-func dexpreoptToolDepsMutator(ctx android.BottomUpMutatorContext) {
- if d, ok := ctx.Module().(DexpreopterInterface); !ok || d.dexpreoptDisabled(ctx) {
- return
- }
- dexpreopt.RegisterToolDeps(ctx)
-}
-
-func (d *dexpreopter) odexOnSystemOther(ctx android.ModuleContext, installPath android.InstallPath) bool {
- return dexpreopt.OdexOnSystemOtherByName(moduleName(ctx), android.InstallPathToOnDevicePath(ctx, installPath), dexpreopt.GetGlobalConfig(ctx))
-}
-
-// Returns the install path of the dex jar of a module.
-//
-// Do not rely on `ApexInfo.ApexVariationName` because it can be something like "apex1000", rather
-// than the `name` in the path `/apex/<name>` as suggested in its comment.
-//
-// This function is on a best-effort basis. It cannot handle the case where an APEX jar is not a
-// system server jar, which is fine because we currently only preopt system server jars for APEXes.
-func (d *dexpreopter) getInstallPath(
- ctx android.ModuleContext, defaultInstallPath android.InstallPath) android.InstallPath {
- global := dexpreopt.GetGlobalConfig(ctx)
- if global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx)) {
- dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, moduleName(ctx))
- return android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexLocation, "/"))
- }
- if !d.dexpreoptDisabled(ctx) && isApexVariant(ctx) &&
- filepath.Base(defaultInstallPath.PartitionDir()) != "apex" {
- ctx.ModuleErrorf("unable to get the install path of the dex jar for dexpreopt")
- }
- return defaultInstallPath
-}
-
-func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.WritablePath) {
- global := dexpreopt.GetGlobalConfig(ctx)
-
- // TODO(b/148690468): The check on d.installPath is to bail out in cases where
- // the dexpreopter struct hasn't been fully initialized before we're called,
- // e.g. in aar.go. This keeps the behaviour that dexpreopting is effectively
- // disabled, even if installable is true.
- if d.installPath.Base() == "." {
- return
- }
-
- dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
-
- providesUsesLib := moduleName(ctx)
- if ulib, ok := ctx.Module().(ProvidesUsesLib); ok {
- name := ulib.ProvidesUsesLib()
- if name != nil {
- providesUsesLib = *name
- }
- }
-
- // If it is test, make config files regardless of its dexpreopt setting.
- // The config files are required for apps defined in make which depend on the lib.
- if d.isTest && d.dexpreoptDisabled(ctx) {
- return
- }
-
- isSystemServerJar := global.AllSystemServerJars(ctx).ContainsJar(moduleName(ctx))
-
- bootImage := defaultBootImageConfig(ctx)
- dexFiles, dexLocations := bcpForDexpreopt(ctx, global.PreoptWithUpdatableBcp)
-
- targets := ctx.MultiTargets()
- if len(targets) == 0 {
- // assume this is a java library, dexpreopt for all arches for now
- for _, target := range ctx.Config().Targets[android.Android] {
- if target.NativeBridge == android.NativeBridgeDisabled {
- targets = append(targets, target)
- }
- }
- if isSystemServerJar && !d.isSDKLibrary {
- // If the module is not an SDK library and it's a system server jar, only preopt the primary arch.
- targets = targets[:1]
- }
- }
-
- var archs []android.ArchType
- var images android.Paths
- var imagesDeps []android.OutputPaths
- for _, target := range targets {
- archs = append(archs, target.Arch.ArchType)
- variant := bootImage.getVariant(target)
- images = append(images, variant.imagePathOnHost)
- imagesDeps = append(imagesDeps, variant.imagesDeps)
- }
- // The image locations for all Android variants are identical.
- hostImageLocations, deviceImageLocations := bootImage.getAnyAndroidVariant().imageLocations()
-
- var profileClassListing android.OptionalPath
- var profileBootListing android.OptionalPath
- profileIsTextListing := false
- if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) {
- // If dex_preopt.profile_guided is not set, default it based on the existence of the
- // dexprepot.profile option or the profile class listing.
- if String(d.dexpreoptProperties.Dex_preopt.Profile) != "" {
- profileClassListing = android.OptionalPathForPath(
- android.PathForModuleSrc(ctx, String(d.dexpreoptProperties.Dex_preopt.Profile)))
- profileBootListing = android.ExistentPathForSource(ctx,
- ctx.ModuleDir(), String(d.dexpreoptProperties.Dex_preopt.Profile)+"-boot")
- profileIsTextListing = true
- } else if global.ProfileDir != "" {
- profileClassListing = android.ExistentPathForSource(ctx,
- global.ProfileDir, moduleName(ctx)+".prof")
- }
- }
-
- // Full dexpreopt config, used to create dexpreopt build rules.
- dexpreoptConfig := &dexpreopt.ModuleConfig{
- Name: moduleName(ctx),
- DexLocation: dexLocation,
- BuildPath: android.PathForModuleOut(ctx, "dexpreopt", moduleName(ctx)+".jar").OutputPath,
- DexPath: dexJarFile,
- ManifestPath: android.OptionalPathForPath(d.manifestFile),
- UncompressedDex: d.uncompressedDex,
- HasApkLibraries: false,
- PreoptFlags: nil,
-
- ProfileClassListing: profileClassListing,
- ProfileIsTextListing: profileIsTextListing,
- ProfileBootListing: profileBootListing,
-
- EnforceUsesLibrariesStatusFile: dexpreopt.UsesLibrariesStatusFile(ctx),
- EnforceUsesLibraries: d.enforceUsesLibs,
- ProvidesUsesLibrary: providesUsesLib,
- ClassLoaderContexts: d.classLoaderContexts,
-
- Archs: archs,
- DexPreoptImagesDeps: imagesDeps,
- DexPreoptImageLocationsOnHost: hostImageLocations,
- DexPreoptImageLocationsOnDevice: deviceImageLocations,
-
- PreoptBootClassPathDexFiles: dexFiles.Paths(),
- PreoptBootClassPathDexLocations: dexLocations,
-
- PreoptExtractedApk: false,
-
- NoCreateAppImage: !BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, true),
- ForceCreateAppImage: BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, false),
-
- PresignedPrebuilt: d.isPresignedPrebuilt,
- }
-
- d.configPath = android.PathForModuleOut(ctx, "dexpreopt", "dexpreopt.config")
- dexpreopt.WriteModuleConfig(ctx, dexpreoptConfig, d.configPath)
-
- if d.dexpreoptDisabled(ctx) {
- return
- }
-
- globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
-
- dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(ctx, globalSoong, global, dexpreoptConfig)
- if err != nil {
- ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error())
- return
- }
-
- dexpreoptRule.Build("dexpreopt", "dexpreopt")
-
- isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx))
-
- for _, install := range dexpreoptRule.Installs() {
- // Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT.
- installDir := strings.TrimPrefix(filepath.Dir(install.To), "/")
- installBase := filepath.Base(install.To)
- arch := filepath.Base(installDir)
- installPath := android.PathForModuleInPartitionInstall(ctx, "", installDir)
-
- if isApexSystemServerJar {
- // APEX variants of java libraries are hidden from Make, so their dexpreopt
- // outputs need special handling. Currently, for APEX variants of java
- // libraries, only those in the system server classpath are handled here.
- // Preopting of boot classpath jars in the ART APEX are handled in
- // java/dexpreopt_bootjars.go, and other APEX jars are not preopted.
- // The installs will be handled by Make as sub-modules of the java library.
- d.builtInstalledForApex = append(d.builtInstalledForApex, dexpreopterInstall{
- name: arch + "-" + installBase,
- moduleName: moduleName(ctx),
- outputPathOnHost: install.From,
- installDirOnDevice: installPath,
- installFileOnDevice: installBase,
- })
- } else if !d.preventInstall {
- ctx.InstallFile(installPath, installBase, install.From)
- }
- }
-
- if !isApexSystemServerJar {
- d.builtInstalled = dexpreoptRule.Installs().String()
- }
-}
-
-func (d *dexpreopter) DexpreoptBuiltInstalledForApex() []dexpreopterInstall {
- return d.builtInstalledForApex
-}
-
-func (d *dexpreopter) AndroidMkEntriesForApex() []android.AndroidMkEntries {
- var entries []android.AndroidMkEntries
- for _, install := range d.builtInstalledForApex {
- entries = append(entries, install.ToMakeEntries())
- }
- return entries
-}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 7c4da3e..b4cd07a 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -785,24 +785,26 @@
}
defaultProfile := "frameworks/base/config/boot-image-profile.txt"
+ extraProfile := "frameworks/base/config/boot-image-profile-extra.txt"
rule := android.NewRuleBuilder(pctx, ctx)
- var bootImageProfile android.Path
- if len(global.BootImageProfiles) > 1 {
- combinedBootImageProfile := image.dir.Join(ctx, "boot-image-profile.txt")
- rule.Command().Text("cat").Inputs(global.BootImageProfiles).Text(">").Output(combinedBootImageProfile)
- bootImageProfile = combinedBootImageProfile
- } else if len(global.BootImageProfiles) == 1 {
- bootImageProfile = global.BootImageProfiles[0]
+ var profiles android.Paths
+ if len(global.BootImageProfiles) > 0 {
+ profiles = append(profiles, global.BootImageProfiles...)
} else if path := android.ExistentPathForSource(ctx, defaultProfile); path.Valid() {
- bootImageProfile = path.Path()
+ profiles = append(profiles, path.Path())
} else {
// No profile (not even a default one, which is the case on some branches
// like master-art-host that don't have frameworks/base).
// Return nil and continue without profile.
return nil
}
+ if path := android.ExistentPathForSource(ctx, extraProfile); path.Valid() {
+ profiles = append(profiles, path.Path())
+ }
+ bootImageProfile := image.dir.Join(ctx, "boot-image-profile.txt")
+ rule.Command().Text("cat").Inputs(profiles).Text(">").Output(bootImageProfile)
profile := image.dir.Join(ctx, "boot.prof")
diff --git a/java/dexpreopt_bootjars.go_v1 b/java/dexpreopt_bootjars.go_v1
deleted file mode 100644
index 07a357b..0000000
--- a/java/dexpreopt_bootjars.go_v1
+++ /dev/null
@@ -1,952 +0,0 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package java
-
-import (
- "path/filepath"
- "strings"
-
- "android/soong/android"
- "android/soong/dexpreopt"
-
- "github.com/google/blueprint/proptools"
-)
-
-// =================================================================================================
-// WIP - see http://b/177892522 for details
-//
-// The build support for boot images is currently being migrated away from singleton to modules so
-// the documentation may not be strictly accurate. Rather than update the documentation at every
-// step which will create a lot of churn the changes that have been made will be listed here and the
-// documentation will be updated once it is closer to the final result.
-//
-// Changes:
-// 1) dex_bootjars is now a singleton module and not a plain singleton.
-// 2) Boot images are now represented by the boot_image module type.
-// 3) The art boot image is called "art-boot-image", the framework boot image is called
-// "framework-boot-image".
-// 4) They are defined in art/build/boot/Android.bp and frameworks/base/boot/Android.bp
-// respectively.
-// 5) Each boot_image retrieves the appropriate boot image configuration from the map returned by
-// genBootImageConfigs() using the image_name specified in the boot_image module.
-// =================================================================================================
-
-// This comment describes:
-// 1. ART boot images in general (their types, structure, file layout, etc.)
-// 2. build system support for boot images
-//
-// 1. ART boot images
-// ------------------
-//
-// A boot image in ART is a set of files that contain AOT-compiled native code and a heap snapshot
-// of AOT-initialized classes for the bootclasspath Java libraries. A boot image is compiled from a
-// set of DEX jars by the dex2oat compiler. A boot image is used for two purposes: 1) it is
-// installed on device and loaded at runtime, and 2) other Java libraries and apps are compiled
-// against it (compilation may take place either on host, known as "dexpreopt", or on device, known
-// as "dexopt").
-//
-// A boot image is not a single file, but a collection of interrelated files. Each boot image has a
-// number of components that correspond to the Java libraries that constitute it. For each component
-// there are multiple files:
-// - *.oat or *.odex file with native code (architecture-specific, one per instruction set)
-// - *.art file with pre-initialized Java classes (architecture-specific, one per instruction set)
-// - *.vdex file with verification metadata for the DEX bytecode (architecture independent)
-//
-// *.vdex files for the boot images do not contain the DEX bytecode itself, because the
-// bootclasspath DEX files are stored on disk in uncompressed and aligned form. Consequently a boot
-// image is not self-contained and cannot be used without its DEX files. To simplify the management
-// of boot image files, ART uses a certain naming scheme and associates the following metadata with
-// each boot image:
-// - A stem, which is a symbolic name that is prepended to boot image file names.
-// - A location (on-device path to the boot image files).
-// - A list of boot image locations (on-device paths to dependency boot images).
-// - A set of DEX locations (on-device paths to the DEX files, one location for one DEX file used
-// to compile the boot image).
-//
-// There are two kinds of boot images:
-// - primary boot images
-// - boot image extensions
-//
-// 1.1. Primary boot images
-// ------------------------
-//
-// A primary boot image is compiled for a core subset of bootclasspath Java libraries. It does not
-// depend on any other images, and other boot images may depend on it.
-//
-// For example, assuming that the stem is "boot", the location is /apex/com.android.art/javalib/,
-// the set of core bootclasspath libraries is A B C, and the boot image is compiled for ARM targets
-// (32 and 64 bits), it will have three components with the following files:
-// - /apex/com.android.art/javalib/{arm,arm64}/boot.{art,oat,vdex}
-// - /apex/com.android.art/javalib/{arm,arm64}/boot-B.{art,oat,vdex}
-// - /apex/com.android.art/javalib/{arm,arm64}/boot-C.{art,oat,vdex}
-//
-// The files of the first component are special: they do not have the component name appended after
-// the stem. This naming convention dates back to the times when the boot image was not split into
-// components, and there were just boot.oat and boot.art. The decision to split was motivated by
-// licensing reasons for one of the bootclasspath libraries.
-//
-// As of November 2020 the only primary boot image in Android is the image in the ART APEX
-// com.android.art. The primary ART boot image contains the Core libraries that are part of the ART
-// module. When the ART module gets updated, the primary boot image will be updated with it, and all
-// dependent images will get invalidated (the checksum of the primary image stored in dependent
-// images will not match), unless they are updated in sync with the ART module.
-//
-// 1.2. Boot image extensions
-// --------------------------
-//
-// A boot image extension is compiled for a subset of bootclasspath Java libraries (in particular,
-// this subset does not include the Core bootclasspath libraries that go into the primary boot
-// image). A boot image extension depends on the primary boot image and optionally some other boot
-// image extensions. Other images may depend on it. In other words, boot image extensions can form
-// acyclic dependency graphs.
-//
-// The motivation for boot image extensions comes from the Mainline project. Consider a situation
-// when the list of bootclasspath libraries is A B C, and both A and B are parts of the Android
-// platform, but C is part of an updatable APEX com.android.C. When the APEX is updated, the Java
-// code for C might have changed compared to the code that was used to compile the boot image.
-// Consequently, the whole boot image is obsolete and invalidated (even though the code for A and B
-// that does not depend on C is up to date). To avoid this, the original monolithic boot image is
-// split in two parts: the primary boot image that contains A B, and the boot image extension that
-// contains C and depends on the primary boot image (extends it).
-//
-// For example, assuming that the stem is "boot", the location is /system/framework, the set of
-// bootclasspath libraries is D E (where D is part of the platform and is located in
-// /system/framework, and E is part of a non-updatable APEX com.android.E and is located in
-// /apex/com.android.E/javalib), and the boot image is compiled for ARM targets (32 and 64 bits),
-// it will have two components with the following files:
-// - /system/framework/{arm,arm64}/boot-D.{art,oat,vdex}
-// - /system/framework/{arm,arm64}/boot-E.{art,oat,vdex}
-//
-// As of November 2020 the only boot image extension in Android is the Framework boot image
-// extension. It extends the primary ART boot image and contains Framework libraries and other
-// bootclasspath libraries from the platform and non-updatable APEXes that are not included in the
-// ART image. The Framework boot image extension is updated together with the platform. In the
-// future other boot image extensions may be added for some updatable modules.
-//
-//
-// 2. Build system support for boot images
-// ---------------------------------------
-//
-// The primary ART boot image needs to be compiled with one dex2oat invocation that depends on DEX
-// jars for the core libraries. Framework boot image extension needs to be compiled with one dex2oat
-// invocation that depends on the primary ART boot image and all bootclasspath DEX jars except the
-// core libraries as they are already part of the primary ART boot image.
-//
-// 2.1. Libraries that go in the boot images
-// -----------------------------------------
-//
-// The contents of each boot image are determined by the PRODUCT variables. The primary ART APEX
-// boot image contains libraries listed in the ART_APEX_JARS variable in the AOSP makefiles. The
-// Framework boot image extension contains libraries specified in the PRODUCT_BOOT_JARS and
-// PRODUCT_BOOT_JARS_EXTRA variables. The AOSP makefiles specify some common Framework libraries,
-// but more product-specific libraries can be added in the product makefiles.
-//
-// Each component of the PRODUCT_BOOT_JARS and PRODUCT_BOOT_JARS_EXTRA variables is a
-// colon-separated pair <apex>:<library>, where <apex> is the variant name of a non-updatable APEX,
-// "platform" if the library is a part of the platform in the system partition, or "system_ext" if
-// it's in the system_ext partition.
-//
-// In these variables APEXes are identified by their "variant names", i.e. the names they get
-// mounted as in /apex on device. In Soong modules that is the name set in the "apex_name"
-// properties, which default to the "name" values. For example, many APEXes have both
-// com.android.xxx and com.google.android.xxx modules in Soong, but take the same place
-// /apex/com.android.xxx at runtime. In these cases the variant name is always com.android.xxx,
-// regardless which APEX goes into the product. See also android.ApexInfo.ApexVariationName and
-// apex.apexBundleProperties.Apex_name.
-//
-// A related variable PRODUCT_APEX_BOOT_JARS contains bootclasspath libraries that are in APEXes.
-// They are not included in the boot image. The only exception here are ART jars and core-icu4j.jar
-// that have been historically part of the boot image and are now in apexes; they are in boot images
-// and core-icu4j.jar is generally treated as being part of PRODUCT_BOOT_JARS.
-//
-// One exception to the above rules are "coverage" builds (a special build flavor which requires
-// setting environment variable EMMA_INSTRUMENT_FRAMEWORK=true). In coverage builds the Java code in
-// boot image libraries is instrumented, which means that the instrumentation library (jacocoagent)
-// needs to be added to the list of bootclasspath DEX jars.
-//
-// In general, there is a requirement that the source code for a boot image library must be
-// available at build time (e.g. it cannot be a stub that has a separate implementation library).
-//
-// 2.2. Static configs
-// -------------------
-//
-// Because boot images are used to dexpreopt other Java modules, the paths to boot image files must
-// be known by the time dexpreopt build rules for the dependent modules are generated. Boot image
-// configs are constructed very early during the build, before build rule generation. The configs
-// provide predefined paths to boot image files (these paths depend only on static build
-// configuration, such as PRODUCT variables, and use hard-coded directory names).
-//
-// 2.3. Singleton
-// --------------
-//
-// Build rules for the boot images are generated with a Soong singleton. Because a singleton has no
-// dependencies on other modules, it has to find the modules for the DEX jars using VisitAllModules.
-// Soong loops through all modules and compares each module against a list of bootclasspath library
-// names. Then it generates build rules that copy DEX jars from their intermediate module-specific
-// locations to the hard-coded locations predefined in the boot image configs.
-//
-// It would be possible to use a module with proper dependencies instead, but that would require
-// changes in the way Soong generates variables for Make: a singleton can use one MakeVars() method
-// that writes variables to out/soong/make_vars-*.mk, which is included early by the main makefile,
-// but module(s) would have to use out/soong/Android-*.mk which has a group of LOCAL_* variables
-// for each module, and is included later.
-//
-// 2.4. Install rules
-// ------------------
-//
-// The primary boot image and the Framework extension are installed in different ways. The primary
-// boot image is part of the ART APEX: it is copied into the APEX intermediate files, packaged
-// together with other APEX contents, extracted and mounted on device. The Framework boot image
-// extension is installed by the rules defined in makefiles (make/core/dex_preopt_libart.mk). Soong
-// writes out a few DEXPREOPT_IMAGE_* variables for Make; these variables contain boot image names,
-// paths and so on.
-//
-
-var artApexNames = []string{
- "com.android.art",
- "com.android.art.debug",
- "com.android.art.testing",
- "com.google.android.art",
- "com.google.android.art.debug",
- "com.google.android.art.testing",
-}
-
-func init() {
- RegisterDexpreoptBootJarsComponents(android.InitRegistrationContext)
-}
-
-// Target-independent description of a boot image.
-type bootImageConfig struct {
- // If this image is an extension, the image that it extends.
- extends *bootImageConfig
-
- // Image name (used in directory names and ninja rule names).
- name string
-
- // Basename of the image: the resulting filenames are <stem>[-<jar>].{art,oat,vdex}.
- stem string
-
- // Output directory for the image files.
- dir android.OutputPath
-
- // Output directory for the image files with debug symbols.
- symbolsDir android.OutputPath
-
- // Subdirectory where the image files are installed.
- installDirOnHost string
-
- // Subdirectory where the image files on device are installed.
- installDirOnDevice string
-
- // Install path of the boot image profile if it needs to be installed in the APEX, or empty if not
- // needed.
- profileInstallPathInApex string
-
- // A list of (location, jar) pairs for the Java modules in this image.
- modules android.ConfiguredJarList
-
- // File paths to jars.
- dexPaths android.WritablePaths // for this image
- dexPathsDeps android.WritablePaths // for the dependency images and in this image
-
- // Map from module name (without prebuilt_ prefix) to the predefined build path.
- dexPathsByModule map[string]android.WritablePath
-
- // File path to a zip archive with all image files (or nil, if not needed).
- zip android.WritablePath
-
- // Rules which should be used in make to install the outputs.
- profileInstalls android.RuleBuilderInstalls
-
- // Path to the license metadata file for the module that built the profile.
- profileLicenseMetadataFile android.OptionalPath
-
- // Path to the image profile file on host (or empty, if profile is not generated).
- profilePathOnHost android.Path
-
- // Target-dependent fields.
- variants []*bootImageVariant
-
- // Path of the preloaded classes file.
- preloadedClassesFile string
-}
-
-// Target-dependent description of a boot image.
-type bootImageVariant struct {
- *bootImageConfig
-
- // Target for which the image is generated.
- target android.Target
-
- // The "locations" of jars.
- dexLocations []string // for this image
- dexLocationsDeps []string // for the dependency images and in this image
-
- // Paths to image files.
- imagePathOnHost android.OutputPath // first image file path on host
- imagePathOnDevice string // first image file path on device
-
- // All the files that constitute this image variant, i.e. .art, .oat and .vdex files.
- imagesDeps android.OutputPaths
-
- // The path to the primary image variant's imagePathOnHost field, where primary image variant
- // means the image variant that this extends.
- //
- // This is only set for a variant of an image that extends another image.
- primaryImages android.OutputPath
-
- // The paths to the primary image variant's imagesDeps field, where primary image variant
- // means the image variant that this extends.
- //
- // This is only set for a variant of an image that extends another image.
- primaryImagesDeps android.Paths
-
- // Rules which should be used in make to install the outputs on host.
- installs android.RuleBuilderInstalls
- vdexInstalls android.RuleBuilderInstalls
- unstrippedInstalls android.RuleBuilderInstalls
-
- // Rules which should be used in make to install the outputs on device.
- deviceInstalls android.RuleBuilderInstalls
-
- // Path to the license metadata file for the module that built the image.
- licenseMetadataFile android.OptionalPath
-}
-
-// Get target-specific boot image variant for the given boot image config and target.
-func (image bootImageConfig) getVariant(target android.Target) *bootImageVariant {
- for _, variant := range image.variants {
- if variant.target.Os == target.Os && variant.target.Arch.ArchType == target.Arch.ArchType {
- return variant
- }
- }
- return nil
-}
-
-// Return any (the first) variant which is for the device (as opposed to for the host).
-func (image bootImageConfig) getAnyAndroidVariant() *bootImageVariant {
- for _, variant := range image.variants {
- if variant.target.Os == android.Android {
- return variant
- }
- }
- return nil
-}
-
-// Return the name of a boot image module given a boot image config and a component (module) index.
-// A module name is a combination of the Java library name, and the boot image stem (that is stored
-// in the config).
-func (image bootImageConfig) moduleName(ctx android.PathContext, idx int) string {
- // The first module of the primary boot image is special: its module name has only the stem, but
- // not the library name. All other module names are of the form <stem>-<library name>
- m := image.modules.Jar(idx)
- name := image.stem
- if idx != 0 || image.extends != nil {
- name += "-" + android.ModuleStem(m)
- }
- return name
-}
-
-// Return the name of the first boot image module, or stem if the list of modules is empty.
-func (image bootImageConfig) firstModuleNameOrStem(ctx android.PathContext) string {
- if image.modules.Len() > 0 {
- return image.moduleName(ctx, 0)
- } else {
- return image.stem
- }
-}
-
-// Return filenames for the given boot image component, given the output directory and a list of
-// extensions.
-func (image bootImageConfig) moduleFiles(ctx android.PathContext, dir android.OutputPath, exts ...string) android.OutputPaths {
- ret := make(android.OutputPaths, 0, image.modules.Len()*len(exts))
- for i := 0; i < image.modules.Len(); i++ {
- name := image.moduleName(ctx, i)
- for _, ext := range exts {
- ret = append(ret, dir.Join(ctx, name+ext))
- }
- }
- return ret
-}
-
-// apexVariants returns a list of all *bootImageVariant that could be included in an apex.
-func (image *bootImageConfig) apexVariants() []*bootImageVariant {
- variants := []*bootImageVariant{}
- for _, variant := range image.variants {
- // We also generate boot images for host (for testing), but we don't need those in the apex.
- // TODO(b/177892522) - consider changing this to check Os.OsClass = android.Device
- if variant.target.Os == android.Android {
- variants = append(variants, variant)
- }
- }
- return variants
-}
-
-// Returns true if the boot image should be installed in the APEX.
-func (image *bootImageConfig) shouldInstallInApex() bool {
- return strings.HasPrefix(image.installDirOnDevice, "apex/")
-}
-
-// Return boot image locations (as a list of symbolic paths).
-//
-// The image "location" is a symbolic path that, with multiarchitecture support, doesn't really
-// exist on the device. Typically it is /apex/com.android.art/javalib/boot.art and should be the
-// same for all supported architectures on the device. The concrete architecture specific files
-// actually end up in architecture-specific sub-directory such as arm, arm64, x86, or x86_64.
-//
-// For example a physical file /apex/com.android.art/javalib/x86/boot.art has "image location"
-// /apex/com.android.art/javalib/boot.art (which is not an actual file).
-//
-// For a primary boot image the list of locations has a single element.
-//
-// For a boot image extension the list of locations contains a location for all dependency images
-// (including the primary image) and the location of the extension itself. For example, for the
-// Framework boot image extension that depends on the primary ART boot image the list contains two
-// elements.
-//
-// The location is passed as an argument to the ART tools like dex2oat instead of the real path.
-// ART tools will then reconstruct the architecture-specific real path.
-//
-func (image *bootImageVariant) imageLocations() (imageLocationsOnHost []string, imageLocationsOnDevice []string) {
- if image.extends != nil {
- imageLocationsOnHost, imageLocationsOnDevice = image.extends.getVariant(image.target).imageLocations()
- }
- return append(imageLocationsOnHost, dexpreopt.PathToLocation(image.imagePathOnHost, image.target.Arch.ArchType)),
- append(imageLocationsOnDevice, dexpreopt.PathStringToLocation(image.imagePathOnDevice, image.target.Arch.ArchType))
-}
-
-func dexpreoptBootJarsFactory() android.SingletonModule {
- m := &dexpreoptBootJars{}
- android.InitAndroidModule(m)
- return m
-}
-
-func RegisterDexpreoptBootJarsComponents(ctx android.RegistrationContext) {
- ctx.RegisterSingletonModuleType("dex_bootjars", dexpreoptBootJarsFactory)
-}
-
-func SkipDexpreoptBootJars(ctx android.PathContext) bool {
- return dexpreopt.GetGlobalConfig(ctx).DisablePreoptBootImages
-}
-
-// Singleton module for generating boot image build rules.
-type dexpreoptBootJars struct {
- android.SingletonModuleBase
-
- // Default boot image config (currently always the Framework boot image extension). It should be
- // noted that JIT-Zygote builds use ART APEX image instead of the Framework boot image extension,
- // but the switch is handled not here, but in the makefiles (triggered with
- // DEXPREOPT_USE_ART_IMAGE=true).
- defaultBootImage *bootImageConfig
-
- // Build path to a config file that Soong writes for Make (to be used in makefiles that install
- // the default boot image).
- dexpreoptConfigForMake android.WritablePath
-}
-
-// Provide paths to boot images for use by modules that depend upon them.
-//
-// The build rules are created in GenerateSingletonBuildActions().
-func (d *dexpreoptBootJars) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- // Placeholder for now.
-}
-
-// Generate build rules for boot images.
-func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonContext) {
- if SkipDexpreoptBootJars(ctx) {
- return
- }
- if dexpreopt.GetCachedGlobalSoongConfig(ctx) == nil {
- // No module has enabled dexpreopting, so we assume there will be no boot image to make.
- return
- }
-
- d.dexpreoptConfigForMake = android.PathForOutput(ctx, ctx.Config().DeviceName(), "dexpreopt.config")
- writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake)
-
- global := dexpreopt.GetGlobalConfig(ctx)
- if !shouldBuildBootImages(ctx.Config(), global) {
- return
- }
-
- defaultImageConfig := defaultBootImageConfig(ctx)
- d.defaultBootImage = defaultImageConfig
-}
-
-// shouldBuildBootImages determines whether boot images should be built.
-func shouldBuildBootImages(config android.Config, global *dexpreopt.GlobalConfig) bool {
- // Skip recompiling the boot image for the second sanitization phase. We'll get separate paths
- // and invalidate first-stage artifacts which are crucial to SANITIZE_LITE builds.
- // Note: this is technically incorrect. Compiled code contains stack checks which may depend
- // on ASAN settings.
- if len(config.SanitizeDevice()) == 1 && config.SanitizeDevice()[0] == "address" && global.SanitizeLite {
- return false
- }
- return true
-}
-
-// copyBootJarsToPredefinedLocations generates commands that will copy boot jars to predefined
-// paths in the global config.
-func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, srcBootDexJarsByModule bootDexJarByModule, dstBootJarsByModule map[string]android.WritablePath) {
- // Create the super set of module names.
- names := []string{}
- names = append(names, android.SortedStringKeys(srcBootDexJarsByModule)...)
- names = append(names, android.SortedStringKeys(dstBootJarsByModule)...)
- names = android.SortedUniqueStrings(names)
- for _, name := range names {
- src := srcBootDexJarsByModule[name]
- dst := dstBootJarsByModule[name]
-
- if src == nil {
- // A dex boot jar should be provided by the source java module. It needs to be installable or
- // have compile_dex=true - cf. assignments to java.Module.dexJarFile.
- //
- // However, the source java module may be either replaced or overridden (using prefer:true) by
- // a prebuilt java module with the same name. In that case the dex boot jar needs to be
- // provided by the corresponding prebuilt APEX module. That APEX is the one that refers
- // through a exported_(boot|systemserver)classpath_fragments property to a
- // prebuilt_(boot|systemserver)classpath_fragment module, which in turn lists the prebuilt
- // java module in the contents property. If that chain is broken then this dependency will
- // fail.
- if !ctx.Config().AllowMissingDependencies() {
- ctx.ModuleErrorf("module %s does not provide a dex boot jar (see comment next to this message in Soong for details)", name)
- } else {
- ctx.AddMissingDependencies([]string{name})
- }
- } else if dst == nil {
- ctx.ModuleErrorf("module %s is not part of the boot configuration", name)
- } else {
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Input: src,
- Output: dst,
- })
- }
- }
-}
-
-// buildBootImageVariantsForAndroidOs generates rules to build the boot image variants for the
-// android.Android OsType and returns a map from the architectures to the paths of the generated
-// boot image files.
-//
-// The paths are returned because they are needed elsewhere in Soong, e.g. for populating an APEX.
-func buildBootImageVariantsForAndroidOs(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) bootImageFilesByArch {
- return buildBootImageForOsType(ctx, image, profile, android.Android)
-}
-
-// buildBootImageVariantsForBuildOs generates rules to build the boot image variants for the
-// config.BuildOS OsType, i.e. the type of OS on which the build is being running.
-//
-// The files need to be generated into their predefined location because they are used from there
-// both within Soong and outside, e.g. for ART based host side testing and also for use by some
-// cloud based tools. However, they are not needed by callers of this function and so the paths do
-// not need to be returned from this func, unlike the buildBootImageVariantsForAndroidOs func.
-func buildBootImageVariantsForBuildOs(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) {
- buildBootImageForOsType(ctx, image, profile, ctx.Config().BuildOS)
-}
-
-// buildBootImageForOsType takes a bootImageConfig, a profile file and an android.OsType
-// boot image files are required for and it creates rules to build the boot image
-// files for all the required architectures for them.
-//
-// It returns a map from android.ArchType to the predefined paths of the boot image files.
-func buildBootImageForOsType(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath, requiredOsType android.OsType) bootImageFilesByArch {
- filesByArch := bootImageFilesByArch{}
- for _, variant := range image.variants {
- if variant.target.Os == requiredOsType {
- buildBootImageVariant(ctx, variant, profile)
- filesByArch[variant.target.Arch.ArchType] = variant.imagesDeps.Paths()
- }
- }
-
- return filesByArch
-}
-
-// buildBootImageZipInPredefinedLocation generates a zip file containing all the boot image files.
-//
-// The supplied filesByArch is nil when the boot image files have not been generated. Otherwise, it
-// is a map from android.ArchType to the predefined locations.
-func buildBootImageZipInPredefinedLocation(ctx android.ModuleContext, image *bootImageConfig, filesByArch bootImageFilesByArch) {
- if filesByArch == nil {
- return
- }
-
- // Compute the list of files from all the architectures.
- zipFiles := android.Paths{}
- for _, archType := range android.ArchTypeList() {
- zipFiles = append(zipFiles, filesByArch[archType]...)
- }
-
- rule := android.NewRuleBuilder(pctx, ctx)
- rule.Command().
- BuiltTool("soong_zip").
- FlagWithOutput("-o ", image.zip).
- FlagWithArg("-C ", image.dir.Join(ctx, android.Android.String()).String()).
- FlagWithInputList("-f ", zipFiles, " -f ")
-
- rule.Build("zip_"+image.name, "zip "+image.name+" image")
-}
-
-// Generate boot image build rules for a specific target.
-func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) {
-
- globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
- global := dexpreopt.GetGlobalConfig(ctx)
-
- arch := image.target.Arch.ArchType
- os := image.target.Os.String() // We need to distinguish host-x86 and device-x86.
- symbolsDir := image.symbolsDir.Join(ctx, os, image.installDirOnHost, arch.String())
- symbolsFile := symbolsDir.Join(ctx, image.stem+".oat")
- outputDir := image.dir.Join(ctx, os, image.installDirOnHost, arch.String())
- outputPath := outputDir.Join(ctx, image.stem+".oat")
- oatLocation := dexpreopt.PathToLocation(outputPath, arch)
- imagePath := outputPath.ReplaceExtension(ctx, "art")
-
- rule := android.NewRuleBuilder(pctx, ctx)
-
- rule.Command().Text("mkdir").Flag("-p").Flag(symbolsDir.String())
- rule.Command().Text("rm").Flag("-f").
- Flag(symbolsDir.Join(ctx, "*.art").String()).
- Flag(symbolsDir.Join(ctx, "*.oat").String()).
- Flag(symbolsDir.Join(ctx, "*.invocation").String())
- rule.Command().Text("rm").Flag("-f").
- Flag(outputDir.Join(ctx, "*.art").String()).
- Flag(outputDir.Join(ctx, "*.oat").String()).
- Flag(outputDir.Join(ctx, "*.invocation").String())
-
- cmd := rule.Command()
-
- extraFlags := ctx.Config().Getenv("ART_BOOT_IMAGE_EXTRA_ARGS")
- if extraFlags == "" {
- // Use ANDROID_LOG_TAGS to suppress most logging by default...
- cmd.Text(`ANDROID_LOG_TAGS="*:e"`)
- } else {
- // ...unless the boot image is generated specifically for testing, then allow all logging.
- cmd.Text(`ANDROID_LOG_TAGS="*:v"`)
- }
-
- invocationPath := outputPath.ReplaceExtension(ctx, "invocation")
-
- cmd.Tool(globalSoong.Dex2oat).
- Flag("--avoid-storing-invocation").
- FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath).
- Flag("--runtime-arg").FlagWithArg("-Xms", global.Dex2oatImageXms).
- Flag("--runtime-arg").FlagWithArg("-Xmx", global.Dex2oatImageXmx)
-
- if profile != nil {
- cmd.FlagWithInput("--profile-file=", profile)
- }
-
- dirtyImageFile := "frameworks/base/config/dirty-image-objects"
- dirtyImagePath := android.ExistentPathForSource(ctx, dirtyImageFile)
- if dirtyImagePath.Valid() {
- cmd.FlagWithInput("--dirty-image-objects=", dirtyImagePath.Path())
- }
-
- if image.extends != nil {
- // It is a boot image extension, so it needs the boot image it depends on (in this case the
- // primary ART APEX image).
- artImage := image.primaryImages
- cmd.
- Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
- Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", image.dexLocationsDeps, ":").
- // Add the path to the first file in the boot image with the arch specific directory removed,
- // dex2oat will reconstruct the path to the actual file when it needs it. As the actual path
- // to the file cannot be passed to the command make sure to add the actual path as an Implicit
- // dependency to ensure that it is built before the command runs.
- FlagWithArg("--boot-image=", dexpreopt.PathToLocation(artImage, arch)).Implicit(artImage).
- // Similarly, the dex2oat tool will automatically find the paths to other files in the base
- // boot image so make sure to add them as implicit dependencies to ensure that they are built
- // before this command is run.
- Implicits(image.primaryImagesDeps)
- } else {
- // It is a primary image, so it needs a base address.
- cmd.FlagWithArg("--base=", ctx.Config().LibartImgDeviceBaseAddress())
- }
-
- // We always expect a preloaded classes file to be available. However, if we cannot find it, it's
- // OK to not pass the flag to dex2oat.
- preloadedClassesPath := android.ExistentPathForSource(ctx, image.preloadedClassesFile)
- if preloadedClassesPath.Valid() {
- cmd.FlagWithInput("--preloaded-classes=", preloadedClassesPath.Path())
- }
-
- cmd.
- FlagForEachInput("--dex-file=", image.dexPaths.Paths()).
- FlagForEachArg("--dex-location=", image.dexLocations).
- Flag("--generate-debug-info").
- Flag("--generate-build-id").
- Flag("--image-format=lz4hc").
- FlagWithArg("--oat-symbols=", symbolsFile.String()).
- Flag("--strip").
- FlagWithArg("--oat-file=", outputPath.String()).
- FlagWithArg("--oat-location=", oatLocation).
- FlagWithArg("--image=", imagePath.String()).
- FlagWithArg("--instruction-set=", arch.String()).
- FlagWithArg("--android-root=", global.EmptyDirectory).
- FlagWithArg("--no-inline-from=", "core-oj.jar").
- Flag("--force-determinism").
- Flag("--abort-on-hard-verifier-error")
-
- // 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 {
- cmd.FlagWithArg("--instruction-set-variant=", global.CpuVariant[arch])
- cmd.FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch])
- }
-
- if global.BootFlags != "" {
- cmd.Flag(global.BootFlags)
- }
-
- if extraFlags != "" {
- cmd.Flag(extraFlags)
- }
-
- cmd.Textf(`|| ( echo %s ; false )`, proptools.ShellEscape(failureMessage))
-
- installDir := filepath.Join("/", image.installDirOnHost, arch.String())
-
- var vdexInstalls android.RuleBuilderInstalls
- var unstrippedInstalls android.RuleBuilderInstalls
- var deviceInstalls android.RuleBuilderInstalls
-
- for _, artOrOat := range image.moduleFiles(ctx, outputDir, ".art", ".oat") {
- cmd.ImplicitOutput(artOrOat)
-
- // Install the .oat and .art files
- rule.Install(artOrOat, filepath.Join(installDir, artOrOat.Base()))
- }
-
- for _, vdex := range image.moduleFiles(ctx, outputDir, ".vdex") {
- cmd.ImplicitOutput(vdex)
-
- // Note that the vdex files are identical between architectures.
- // Make rules will create symlinks to share them between architectures.
- vdexInstalls = append(vdexInstalls,
- android.RuleBuilderInstall{vdex, filepath.Join(installDir, vdex.Base())})
- }
-
- for _, unstrippedOat := range image.moduleFiles(ctx, symbolsDir, ".oat") {
- cmd.ImplicitOutput(unstrippedOat)
-
- // Install the unstripped oat files. The Make rules will put these in $(TARGET_OUT_UNSTRIPPED)
- unstrippedInstalls = append(unstrippedInstalls,
- android.RuleBuilderInstall{unstrippedOat, filepath.Join(installDir, unstrippedOat.Base())})
- }
-
- if image.installDirOnHost != image.installDirOnDevice && !image.shouldInstallInApex() && !ctx.Config().UnbundledBuild() {
- installDirOnDevice := filepath.Join("/", image.installDirOnDevice, arch.String())
- for _, file := range image.moduleFiles(ctx, outputDir, ".art", ".oat", ".vdex") {
- deviceInstalls = append(deviceInstalls,
- android.RuleBuilderInstall{file, filepath.Join(installDirOnDevice, file.Base())})
- }
- }
-
- rule.Build(image.name+"JarsDexpreopt_"+image.target.String(), "dexpreopt "+image.name+" jars "+arch.String())
-
- // save output and installed files for makevars
- image.installs = rule.Installs()
- image.vdexInstalls = vdexInstalls
- image.unstrippedInstalls = unstrippedInstalls
- image.deviceInstalls = deviceInstalls
- image.licenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile())
-}
-
-const failureMessage = `ERROR: Dex2oat failed to compile a boot image.
-It is likely that the boot classpath is inconsistent.
-Rebuild with ART_BOOT_IMAGE_EXTRA_ARGS="--runtime-arg -verbose:verifier" to see verification errors.`
-
-func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) android.WritablePath {
- globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
- global := dexpreopt.GetGlobalConfig(ctx)
-
- if global.DisableGenerateProfile {
- return nil
- }
-
- defaultProfile := "frameworks/base/config/boot-image-profile.txt"
-
- rule := android.NewRuleBuilder(pctx, ctx)
-
- var bootImageProfile android.Path
- if len(global.BootImageProfiles) > 1 {
- combinedBootImageProfile := image.dir.Join(ctx, "boot-image-profile.txt")
- rule.Command().Text("cat").Inputs(global.BootImageProfiles).Text(">").Output(combinedBootImageProfile)
- bootImageProfile = combinedBootImageProfile
- } else if len(global.BootImageProfiles) == 1 {
- bootImageProfile = global.BootImageProfiles[0]
- } else if path := android.ExistentPathForSource(ctx, defaultProfile); path.Valid() {
- bootImageProfile = path.Path()
- } else {
- // No profile (not even a default one, which is the case on some branches
- // like master-art-host that don't have frameworks/base).
- // Return nil and continue without profile.
- return nil
- }
-
- profile := image.dir.Join(ctx, "boot.prof")
-
- rule.Command().
- Text(`ANDROID_LOG_TAGS="*:e"`).
- Tool(globalSoong.Profman).
- Flag("--output-profile-type=boot").
- FlagWithInput("--create-profile-from=", bootImageProfile).
- FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
- FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps).
- FlagWithOutput("--reference-profile-file=", profile)
-
- if image == defaultBootImageConfig(ctx) {
- rule.Install(profile, "/system/etc/boot-image.prof")
- image.profileInstalls = append(image.profileInstalls, rule.Installs()...)
- image.profileLicenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile())
- }
-
- rule.Build("bootJarsProfile", "profile boot jars")
-
- image.profilePathOnHost = profile
-
- return profile
-}
-
-// bootFrameworkProfileRule generates the rule to create the boot framework profile and
-// returns a path to the generated file.
-func bootFrameworkProfileRule(ctx android.ModuleContext, image *bootImageConfig) android.WritablePath {
- globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
- global := dexpreopt.GetGlobalConfig(ctx)
-
- if global.DisableGenerateProfile || ctx.Config().UnbundledBuild() {
- return nil
- }
-
- defaultProfile := "frameworks/base/config/boot-profile.txt"
- bootFrameworkProfile := android.PathForSource(ctx, defaultProfile)
-
- profile := image.dir.Join(ctx, "boot.bprof")
-
- rule := android.NewRuleBuilder(pctx, ctx)
- rule.Command().
- Text(`ANDROID_LOG_TAGS="*:e"`).
- Tool(globalSoong.Profman).
- Flag("--output-profile-type=bprof").
- FlagWithInput("--create-profile-from=", bootFrameworkProfile).
- FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
- FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps).
- FlagWithOutput("--reference-profile-file=", profile)
-
- rule.Install(profile, "/system/etc/boot-image.bprof")
- rule.Build("bootFrameworkProfile", "profile boot framework jars")
- image.profileInstalls = append(image.profileInstalls, rule.Installs()...)
- image.profileLicenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile())
-
- return profile
-}
-
-func dumpOatRules(ctx android.ModuleContext, image *bootImageConfig) {
- var allPhonies android.Paths
- for _, image := range image.variants {
- arch := image.target.Arch.ArchType
- suffix := arch.String()
- // Host and target might both use x86 arch. We need to ensure the names are unique.
- if image.target.Os.Class == android.Host {
- suffix = "host-" + suffix
- }
- // Create a rule to call oatdump.
- output := android.PathForOutput(ctx, "boot."+suffix+".oatdump.txt")
- rule := android.NewRuleBuilder(pctx, ctx)
- imageLocationsOnHost, _ := image.imageLocations()
- rule.Command().
- BuiltTool("oatdump").
- FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
- FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocationsDeps, ":").
- FlagWithArg("--image=", strings.Join(imageLocationsOnHost, ":")).Implicits(image.imagesDeps.Paths()).
- FlagWithOutput("--output=", output).
- FlagWithArg("--instruction-set=", arch.String())
- rule.Build("dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
-
- // Create a phony rule that depends on the output file and prints the path.
- phony := android.PathForPhony(ctx, "dump-oat-boot-"+suffix)
- rule = android.NewRuleBuilder(pctx, ctx)
- rule.Command().
- Implicit(output).
- ImplicitOutput(phony).
- Text("echo").FlagWithArg("Output in ", output.String())
- rule.Build("phony-dump-oat-boot-"+suffix, "dump oat boot "+arch.String())
-
- allPhonies = append(allPhonies, phony)
- }
-
- phony := android.PathForPhony(ctx, "dump-oat-boot")
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Phony,
- Output: phony,
- Inputs: allPhonies,
- Description: "dump-oat-boot",
- })
-}
-
-func writeGlobalConfigForMake(ctx android.SingletonContext, path android.WritablePath) {
- data := dexpreopt.GetGlobalConfigRawData(ctx)
-
- android.WriteFileRule(ctx, path, string(data))
-}
-
-// Define Make variables for boot image names, paths, etc. These variables are used in makefiles
-// (make/core/dex_preopt_libart.mk) to generate install rules that copy boot image files to the
-// correct output directories.
-func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) {
- if d.dexpreoptConfigForMake != nil {
- ctx.Strict("DEX_PREOPT_CONFIG_FOR_MAKE", d.dexpreoptConfigForMake.String())
- ctx.Strict("DEX_PREOPT_SOONG_CONFIG_FOR_MAKE", android.PathForOutput(ctx, "dexpreopt_soong.config").String())
- }
-
- image := d.defaultBootImage
- if image == nil {
- return
- }
-
- ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String())
- if image.profileLicenseMetadataFile.Valid() {
- ctx.Strict("DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA", image.profileLicenseMetadataFile.String())
- }
-
- global := dexpreopt.GetGlobalConfig(ctx)
- dexPaths, dexLocations := bcpForDexpreopt(ctx, global.PreoptWithUpdatableBcp)
- ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(dexPaths.Strings(), " "))
- ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(dexLocations, " "))
-
- for _, variant := range image.variants {
- suffix := ""
- if variant.target.Os.Class == android.Host {
- suffix = "_host"
- }
- sfx := suffix + "_" + variant.target.Arch.ArchType.String()
- ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+sfx, variant.vdexInstalls.String())
- ctx.Strict("DEXPREOPT_IMAGE_"+sfx, variant.imagePathOnHost.String())
- ctx.Strict("DEXPREOPT_IMAGE_DEPS_"+sfx, strings.Join(variant.imagesDeps.Strings(), " "))
- ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, variant.installs.String())
- ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, variant.unstrippedInstalls.String())
- if variant.licenseMetadataFile.Valid() {
- ctx.Strict("DEXPREOPT_IMAGE_LICENSE_METADATA_"+sfx, variant.licenseMetadataFile.String())
- }
- }
- imageLocationsOnHost, imageLocationsOnDevice := image.getAnyAndroidVariant().imageLocations()
- ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_ON_HOST", strings.Join(imageLocationsOnHost, ":"))
- ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICE", strings.Join(imageLocationsOnDevice, ":"))
- ctx.Strict("DEXPREOPT_IMAGE_ZIP", image.zip.String())
-
- // There used to be multiple images for JIT-Zygote mode, not there's only one.
- ctx.Strict("DEXPREOPT_IMAGE_NAMES", image.name)
-}
diff --git a/java/dexpreopt_config.go_v1 b/java/dexpreopt_config.go_v1
deleted file mode 100644
index d71e2bb..0000000
--- a/java/dexpreopt_config.go_v1
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2019 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package java
-
-import (
- "path/filepath"
- "strings"
-
- "android/soong/android"
- "android/soong/dexpreopt"
-)
-
-// dexpreoptTargets returns the list of targets that are relevant to dexpreopting, which excludes architectures
-// supported through native bridge.
-func dexpreoptTargets(ctx android.PathContext) []android.Target {
- var targets []android.Target
- for _, target := range ctx.Config().Targets[android.Android] {
- if target.NativeBridge == android.NativeBridgeDisabled {
- targets = append(targets, target)
- }
- }
- // We may also need the images on host in order to run host-based tests.
- for _, target := range ctx.Config().Targets[ctx.Config().BuildOS] {
- targets = append(targets, target)
- }
-
- return targets
-}
-
-var (
- bootImageConfigKey = android.NewOnceKey("bootImageConfig")
- bootImageConfigRawKey = android.NewOnceKey("bootImageConfigRaw")
- artBootImageName = "art"
- frameworkBootImageName = "boot"
-)
-
-func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig {
- return ctx.Config().Once(bootImageConfigRawKey, func() interface{} {
- global := dexpreopt.GetGlobalConfig(ctx)
-
- artModules := global.ArtApexJars
- frameworkModules := global.BootJars.RemoveList(artModules)
-
- // ART config for the primary boot image in the ART apex.
- // It includes the Core Libraries.
- artCfg := bootImageConfig{
- name: artBootImageName,
- stem: "boot",
- installDirOnHost: "apex/art_boot_images/javalib",
- installDirOnDevice: "system/framework",
- profileInstallPathInApex: "etc/boot-image.prof",
- modules: artModules,
- preloadedClassesFile: "art/build/boot/preloaded-classes",
- }
-
- // 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",
- installDirOnHost: frameworkSubdir,
- installDirOnDevice: frameworkSubdir,
- modules: frameworkModules,
- preloadedClassesFile: "frameworks/base/config/preloaded-classes",
- }
-
- return map[string]*bootImageConfig{
- artBootImageName: &artCfg,
- frameworkBootImageName: &frameworkCfg,
- }
- }).(map[string]*bootImageConfig)
-}
-
-// Construct the global boot image configs.
-func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig {
- return ctx.Config().Once(bootImageConfigKey, func() interface{} {
- targets := dexpreoptTargets(ctx)
- deviceDir := android.PathForOutput(ctx, ctx.Config().DeviceName())
-
- configs := genBootImageConfigRaw(ctx)
- artCfg := configs[artBootImageName]
- frameworkCfg := configs[frameworkBootImageName]
-
- // common to all configs
- for _, c := range configs {
- c.dir = deviceDir.Join(ctx, "dex_"+c.name+"jars")
- c.symbolsDir = deviceDir.Join(ctx, "dex_"+c.name+"jars_unstripped")
-
- // expands to <stem>.art for primary image and <stem>-<1st module>.art for extension
- imageName := c.firstModuleNameOrStem(ctx) + ".art"
-
- // The path to bootclasspath dex files needs to be known at module
- // GenerateAndroidBuildAction time, before the bootclasspath modules have been compiled.
- // Set up known paths for them, the singleton rules will copy them there.
- // TODO(b/143682396): use module dependencies instead
- inputDir := deviceDir.Join(ctx, "dex_"+c.name+"jars_input")
- c.dexPaths = c.modules.BuildPaths(ctx, inputDir)
- c.dexPathsByModule = c.modules.BuildPathsByModule(ctx, inputDir)
- c.dexPathsDeps = c.dexPaths
-
- // Create target-specific variants.
- for _, target := range targets {
- arch := target.Arch.ArchType
- imageDir := c.dir.Join(ctx, target.Os.String(), c.installDirOnHost, arch.String())
- variant := &bootImageVariant{
- bootImageConfig: c,
- target: target,
- imagePathOnHost: imageDir.Join(ctx, imageName),
- imagePathOnDevice: filepath.Join("/", c.installDirOnDevice, arch.String(), imageName),
- imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"),
- dexLocations: c.modules.DevicePaths(ctx.Config(), target.Os),
- }
- variant.dexLocationsDeps = variant.dexLocations
- c.variants = append(c.variants, variant)
- }
-
- c.zip = c.dir.Join(ctx, c.name+".zip")
- }
-
- // specific to the framework config
- frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...)
- for i := range targets {
- frameworkCfg.variants[i].primaryImages = artCfg.variants[i].imagePathOnHost
- frameworkCfg.variants[i].primaryImagesDeps = artCfg.variants[i].imagesDeps.Paths()
- frameworkCfg.variants[i].dexLocationsDeps = append(artCfg.variants[i].dexLocations, frameworkCfg.variants[i].dexLocationsDeps...)
- }
-
- return configs
- }).(map[string]*bootImageConfig)
-}
-
-func defaultBootImageConfig(ctx android.PathContext) *bootImageConfig {
- return genBootImageConfigs(ctx)[frameworkBootImageName]
-}
-
-// 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.
-type apexBootConfig struct {
- // A list of apex boot jars.
- modules android.ConfiguredJarList
-
- // A list of predefined build paths to apex boot jars. They are configured very early,
- // before the modules for these jars are processed and the actual paths are generated, and
- // later on a singleton adds commands to copy actual jars to the predefined paths.
- dexPaths android.WritablePaths
-
- // Map from module name (without prebuilt_ prefix) to the predefined build path.
- dexPathsByModule map[string]android.WritablePath
-
- // A list of dex locations (a.k.a. on-device paths) to the boot jars.
- dexLocations []string
-}
-
-var updatableBootConfigKey = android.NewOnceKey("apexBootConfig")
-
-// Returns apex boot config.
-func GetApexBootConfig(ctx android.PathContext) apexBootConfig {
- return ctx.Config().Once(updatableBootConfigKey, func() interface{} {
- apexBootJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars
-
- dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "apex_bootjars")
- dexPaths := apexBootJars.BuildPaths(ctx, dir)
- dexPathsByModuleName := apexBootJars.BuildPathsByModule(ctx, dir)
-
- dexLocations := apexBootJars.DevicePaths(ctx.Config(), android.Android)
-
- return apexBootConfig{apexBootJars, dexPaths, dexPathsByModuleName, dexLocations}
- }).(apexBootConfig)
-}
-
-// Returns a list of paths and a list of locations for the boot jars used in dexpreopt (to be
-// passed in -Xbootclasspath and -Xbootclasspath-locations arguments for dex2oat).
-func bcpForDexpreopt(ctx android.PathContext, withUpdatable bool) (android.WritablePaths, []string) {
- // Non-updatable boot jars (they are used both in the boot image and in dexpreopt).
- bootImage := defaultBootImageConfig(ctx)
- dexPaths := bootImage.dexPathsDeps
- // The dex locations for all Android variants are identical.
- dexLocations := bootImage.getAnyAndroidVariant().dexLocationsDeps
-
- if withUpdatable {
- // Apex boot jars (they are used only in dexpreopt, but not in the boot image).
- apexBootConfig := GetApexBootConfig(ctx)
- dexPaths = append(dexPaths, apexBootConfig.dexPaths...)
- dexLocations = append(dexLocations, apexBootConfig.dexLocations...)
- }
-
- return dexPaths, dexLocations
-}
-
-var defaultBootclasspathKey = android.NewOnceKey("defaultBootclasspath")
-
-var copyOf = android.CopyOf
-
-func init() {
- android.RegisterMakeVarsProvider(pctx, dexpreoptConfigMakevars)
-}
-
-func dexpreoptConfigMakevars(ctx android.MakeVarsContext) {
- ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules.CopyOfApexJarPairs(), ":"))
-}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 023d619..9663922 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -256,6 +256,10 @@
return j.SdkVersion(ctx)
}
+func (j *Javadoc) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
+ return j.SdkVersion(ctx)
+}
+
func (j *Javadoc) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
return j.SdkVersion(ctx)
}
diff --git a/java/fuzz.go b/java/fuzz.go
index b306991..d0f369f 100644
--- a/java/fuzz.go
+++ b/java/fuzz.go
@@ -171,6 +171,10 @@
return
}
+ if javaFuzzModule.Target().HostCross {
+ return
+ }
+
fuzzModuleValidator := fuzz.FuzzModule{
javaFuzzModule.ModuleBase,
javaFuzzModule.DefaultableModuleBase,
diff --git a/java/java.go b/java/java.go
index 2897fd7..dae69dc 100644
--- a/java/java.go
+++ b/java/java.go
@@ -118,6 +118,16 @@
copyEverythingToSnapshot,
}
+ snapshotRequiresImplementationJar = func(ctx android.SdkMemberContext) bool {
+ // In the S build the build will break if updatable-media does not provide a full implementation
+ // jar. That issue was fixed in Tiramisu by b/229932396.
+ if ctx.IsTargetBuildBeforeTiramisu() && ctx.Name() == "updatable-media" {
+ return true
+ }
+
+ return false
+ }
+
// Supports adding java boot libraries to module_exports and sdk.
//
// The build has some implicit dependencies (via the boot jars configuration) on a number of
@@ -135,13 +145,21 @@
SupportsSdk: true,
},
func(ctx android.SdkMemberContext, j *Library) android.Path {
+ if snapshotRequiresImplementationJar(ctx) {
+ return exportImplementationClassesJar(ctx, j)
+ }
+
// Java boot libs are only provided in the SDK to provide access to their dex implementation
// jar for use by dexpreopting and boot jars package check. They do not need to provide an
// actual implementation jar but the java_import will need a file that exists so just copy an
// empty file. Any attempt to use that file as a jar will cause a build error.
return ctx.SnapshotBuilder().EmptyFile()
},
- func(osPrefix, name string) string {
+ func(ctx android.SdkMemberContext, osPrefix, name string) string {
+ if snapshotRequiresImplementationJar(ctx) {
+ return sdkSnapshotFilePathForJar(ctx, osPrefix, name)
+ }
+
// Create a special name for the implementation jar to try and provide some useful information
// to a developer that attempts to compile against this.
// TODO(b/175714559): Provide a proper error message in Soong not ninja.
@@ -164,6 +182,9 @@
android.SdkMemberTypeBase{
PropertyName: "java_systemserver_libs",
SupportsSdk: true,
+
+ // This was only added in Tiramisu.
+ SupportedBuildReleaseSpecification: "Tiramisu+",
},
func(ctx android.SdkMemberContext, j *Library) android.Path {
// Java systemserver libs are only provided in the SDK to provide access to their dex
@@ -172,7 +193,7 @@
// file. Any attempt to use that file as a jar will cause a build error.
return ctx.SnapshotBuilder().EmptyFile()
},
- func(osPrefix, name string) string {
+ func(_ android.SdkMemberContext, osPrefix, name string) string {
// Create a special name for the implementation jar to try and provide some useful information
// to a developer that attempts to compile against this.
// TODO(b/175714559): Provide a proper error message in Soong not ninja.
@@ -510,6 +531,20 @@
}
}
+func (v javaVersion) StringForKotlinc() string {
+ // $ ./external/kotlinc/bin/kotlinc -jvm-target foo
+ // error: unknown JVM target version: foo
+ // Supported versions: 1.6, 1.8, 9, 10, 11, 12, 13, 14, 15, 16, 17
+ switch v {
+ case JAVA_VERSION_7:
+ return "1.6"
+ case JAVA_VERSION_9:
+ return "9"
+ default:
+ return v.String()
+ }
+}
+
// Returns true if javac targeting this version uses system modules instead of a bootclasspath.
func (v javaVersion) usesJavaModules() bool {
return v >= 9
@@ -655,7 +690,7 @@
)
// path to the jar file of a java library. Relative to <sdk_root>/<api_dir>
-func sdkSnapshotFilePathForJar(osPrefix, name string) string {
+func sdkSnapshotFilePathForJar(_ android.SdkMemberContext, osPrefix, name string) string {
return sdkSnapshotFilePathForMember(osPrefix, name, jarFileSuffix)
}
@@ -672,7 +707,7 @@
// Function to compute the snapshot relative path to which the named library's
// jar should be copied.
- snapshotPathGetter func(osPrefix, name string) string
+ snapshotPathGetter func(ctx android.SdkMemberContext, osPrefix, name string) string
// True if only the jar should be copied to the snapshot, false if the jar plus any additional
// files like aidl files should also be copied.
@@ -730,7 +765,7 @@
exportedJar := p.JarToExport
if exportedJar != nil {
// Delegate the creation of the snapshot relative path to the member type.
- snapshotRelativeJavaLibPath := memberType.snapshotPathGetter(p.OsPrefix(), ctx.Name())
+ snapshotRelativeJavaLibPath := memberType.snapshotPathGetter(ctx, p.OsPrefix(), ctx.Name())
// Copy the exported jar to the snapshot.
builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
@@ -1196,7 +1231,7 @@
exportedJar := p.JarToExport
if exportedJar != nil {
- snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), ctx.Name())
+ snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(ctx, p.OsPrefix(), ctx.Name())
builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
@@ -1442,6 +1477,10 @@
// specified.
Min_sdk_version *string
+ // The max sdk version placeholder used to replace maxSdkVersion attributes on permission
+ // and uses-permission tags in manifest_fixer.
+ Replace_max_sdk_version_placeholder *string
+
Installable *bool
// If not empty, classes are restricted to the specified packages and their sub-packages.
@@ -1521,6 +1560,13 @@
return j.SdkVersion(ctx)
}
+func (j *Import) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
+ if j.properties.Replace_max_sdk_version_placeholder != nil {
+ return android.SdkSpecFrom(ctx, *j.properties.Replace_max_sdk_version_placeholder)
+ }
+ return android.SdkSpecFrom(ctx, "")
+}
+
func (j *Import) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
return j.SdkVersion(ctx)
}
diff --git a/java/kotlin.go b/java/kotlin.go
index 903c624..9bff5ea 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -119,9 +119,8 @@
"srcJarDir": android.PathForModuleOut(ctx, "kotlinc", "srcJars").String(),
"kotlinBuildFile": android.PathForModuleOut(ctx, "kotlinc-build.xml").String(),
"emptyDir": android.PathForModuleOut(ctx, "kotlinc", "empty").String(),
- // http://b/69160377 kotlinc only supports -jvm-target 1.6 and 1.8
- "kotlinJvmTarget": "1.8",
- "name": kotlinName,
+ "kotlinJvmTarget": flags.javaVersion.StringForKotlinc(),
+ "name": kotlinName,
},
})
}
diff --git a/java/lint.go b/java/lint.go
index 22c9ec4..e276345 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -17,6 +17,7 @@
import (
"fmt"
"sort"
+ "strconv"
"strings"
"github.com/google/blueprint/proptools"
@@ -75,9 +76,9 @@
extraLintCheckJars android.Paths
test bool
library bool
- minSdkVersion android.ApiLevel
- targetSdkVersion android.ApiLevel
- compileSdkVersion android.ApiLevel
+ minSdkVersion int
+ targetSdkVersion int
+ compileSdkVersion int
compileSdkKind android.SdkKind
javaLanguageLevel string
kotlinLanguageLevel string
@@ -299,8 +300,8 @@
Text(`echo "<?xml version='1.0' encoding='utf-8'?>" &&`).
Text(`echo "<manifest xmlns:android='http://schemas.android.com/apk/res/android'" &&`).
Text(`echo " android:versionCode='1' android:versionName='1' >" &&`).
- Textf(`echo " <uses-sdk android:minSdkVersion='%s' android:targetSdkVersion='%s'/>" &&`,
- l.minSdkVersion.String(), l.targetSdkVersion.String()).
+ Textf(`echo " <uses-sdk android:minSdkVersion='%d' android:targetSdkVersion='%d'/>" &&`,
+ l.minSdkVersion, l.targetSdkVersion).
Text(`echo "</manifest>"`).
Text(") >").Output(manifestPath)
@@ -325,7 +326,7 @@
return
}
- if l.minSdkVersion.CompareTo(l.compileSdkVersion) == -1 {
+ if l.minSdkVersion != l.compileSdkVersion {
l.extraMainlineLintErrors = append(l.extraMainlineLintErrors, updatabilityChecks...)
_, filtered := android.FilterList(l.properties.Lint.Warning_checks, updatabilityChecks)
if len(filtered) != 0 {
@@ -427,7 +428,7 @@
FlagWithOutput("--html ", html).
FlagWithOutput("--text ", text).
FlagWithOutput("--xml ", xml).
- FlagWithArg("--compile-sdk-version ", l.compileSdkVersion.String()).
+ FlagWithArg("--compile-sdk-version ", strconv.Itoa(l.compileSdkVersion)).
FlagWithArg("--java-language-level ", l.javaLanguageLevel).
FlagWithArg("--kotlin-language-level ", l.kotlinLanguageLevel).
FlagWithArg("--url ", fmt.Sprintf(".=.,%s=out", android.PathForOutput(ctx).String())).
diff --git a/java/rro.go b/java/rro.go
index be84aff..7952c2c 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -173,6 +173,10 @@
return r.SdkVersion(ctx)
}
+func (r *RuntimeResourceOverlay) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
+ return android.SdkSpecFrom(ctx, "")
+}
+
func (r *RuntimeResourceOverlay) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
return r.SdkVersion(ctx)
}
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index fa61ea6..a2cd261 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -24,12 +24,7 @@
func init() {
registerSystemserverClasspathBuildComponents(android.InitRegistrationContext)
- android.RegisterSdkMemberType(&systemServerClasspathFragmentMemberType{
- SdkMemberTypeBase: android.SdkMemberTypeBase{
- PropertyName: "systemserverclasspath_fragments",
- SupportsSdk: true,
- },
- })
+ android.RegisterSdkMemberType(SystemServerClasspathFragmentSdkMemberType)
}
func registerSystemserverClasspathBuildComponents(ctx android.RegistrationContext) {
@@ -38,6 +33,17 @@
ctx.RegisterModuleType("prebuilt_systemserverclasspath_fragment", prebuiltSystemServerClasspathModuleFactory)
}
+var SystemServerClasspathFragmentSdkMemberType = &systemServerClasspathFragmentMemberType{
+ SdkMemberTypeBase: android.SdkMemberTypeBase{
+ PropertyName: "systemserverclasspath_fragments",
+ SupportsSdk: true,
+
+ // Support for adding systemserverclasspath_fragments to the sdk snapshot was only added in
+ // Tiramisu.
+ SupportedBuildReleaseSpecification: "Tiramisu+",
+ },
+}
+
type platformSystemServerClasspathModule struct {
android.ModuleBase
diff --git a/rust/bindgen.go b/rust/bindgen.go
index b4626a0..72cc894 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -41,10 +41,25 @@
//TODO(b/160803703) Use a prebuilt bindgen instead of the built bindgen.
_ = pctx.HostBinToolVariable("bindgenCmd", "bindgen")
+ _ = pctx.VariableFunc("bindgenHostPrebuiltTag", func(ctx android.PackageVarContext) string {
+ if ctx.Config().UseHostMusl() {
+ // This is a hack to use the glibc bindgen binary until we have a musl version checked in.
+ return "linux-x86"
+ } else {
+ return "${config.HostPrebuiltTag}"
+ }
+ })
+ _ = pctx.VariableFunc("bindgenClangLibdir", func(ctx android.PackageVarContext) string {
+ if ctx.Config().UseHostMusl() {
+ return "musl/lib64/"
+ } else {
+ return "lib64/"
+ }
+ })
_ = pctx.SourcePathVariable("bindgenClang",
- "${cc_config.ClangBase}/${config.HostPrebuiltTag}/${bindgenClangVersion}/bin/clang")
+ "${cc_config.ClangBase}/${bindgenHostPrebuiltTag}/${bindgenClangVersion}/bin/clang")
_ = pctx.SourcePathVariable("bindgenLibClang",
- "${cc_config.ClangBase}/${config.HostPrebuiltTag}/${bindgenClangVersion}/lib64/")
+ "${cc_config.ClangBase}/${bindgenHostPrebuiltTag}/${bindgenClangVersion}/${bindgenClangLibdir}")
//TODO(ivanlozano) Switch this to RuleBuilder
bindgen = pctx.AndroidStaticRule("bindgen",
@@ -224,6 +239,11 @@
cflags = append(cflags, "-x c")
}
+ // LLVM_NEXT may contain flags that bindgen doesn't recognise. Turn off unknown flags warning.
+ if ctx.Config().IsEnvTrue("LLVM_NEXT") {
+ cflags = append(cflags, "-Wno-unknown-warning-option")
+ }
+
outputFile := android.PathForModuleOut(ctx, b.BaseSourceProvider.getStem(ctx)+".rs")
var cmd, cmdDesc string
diff --git a/rust/compiler.go b/rust/compiler.go
index bcd58c8..bf6a488 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -371,8 +371,9 @@
if !Bool(compiler.Properties.No_stdlibs) {
for _, stdlib := range config.Stdlibs {
- // If we're building for the build host, use the prebuilt stdlibs
- if ctx.Target().Os == android.Linux || ctx.Target().Os == android.Darwin {
+ // If we're building for the build host, use the prebuilt stdlibs, unless the host
+ // is linux_bionic which doesn't have prebuilts.
+ if ctx.Host() && !ctx.Target().HostCross && ctx.Target().Os != android.LinuxBionic {
stdlib = "prebuilt_" + stdlib
}
deps.Stdlibs = append(deps.Stdlibs, stdlib)
diff --git a/rust/config/Android.bp b/rust/config/Android.bp
index 7757c79..ba40cb0 100644
--- a/rust/config/Android.bp
+++ b/rust/config/Android.bp
@@ -11,6 +11,7 @@
],
srcs: [
"arm_device.go",
+ "arm_linux_host.go",
"arm64_device.go",
"global.go",
"lints.go",
diff --git a/rust/config/arm_linux_host.go b/rust/config/arm_linux_host.go
new file mode 100644
index 0000000..22bdaee
--- /dev/null
+++ b/rust/config/arm_linux_host.go
@@ -0,0 +1,147 @@
+// 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 config
+
+import (
+ "strings"
+
+ "android/soong/android"
+)
+
+var (
+ linuxArmRustflags = []string{}
+ linuxArmLinkflags = []string{}
+ linuxArm64Rustflags = []string{}
+ linuxArm64Linkflags = []string{}
+)
+
+func init() {
+ registerToolchainFactory(android.LinuxMusl, android.Arm64, linuxMuslArm64ToolchainFactory)
+ registerToolchainFactory(android.LinuxMusl, android.Arm, linuxMuslArmToolchainFactory)
+
+ pctx.StaticVariable("LinuxToolchainArmRustFlags", strings.Join(linuxArmRustflags, " "))
+ pctx.StaticVariable("LinuxToolchainArmLinkFlags", strings.Join(linuxArmLinkflags, " "))
+ pctx.StaticVariable("LinuxToolchainArm64RustFlags", strings.Join(linuxArm64Rustflags, " "))
+ pctx.StaticVariable("LinuxToolchainArm64LinkFlags", strings.Join(linuxArm64Linkflags, " "))
+}
+
+// Base 64-bit linux rust toolchain
+type toolchainLinuxArm64 struct {
+ toolchain64Bit
+}
+
+func (toolchainLinuxArm64) Supported() bool {
+ return true
+}
+
+func (toolchainLinuxArm64) Bionic() bool {
+ return false
+}
+
+func (t *toolchainLinuxArm64) Name() string {
+ return "arm64"
+}
+
+func (t *toolchainLinuxArm64) ToolchainLinkFlags() string {
+ // Prepend the lld flags from cc_config so we stay in sync with cc
+ return "${cc_config.LinuxLldflags} ${cc_config.LinuxArm64Lldflags} " +
+ "${config.LinuxToolchainLinkFlags} ${config.LinuxToolchainArm64LinkFlags}"
+}
+
+func (t *toolchainLinuxArm64) ToolchainRustFlags() string {
+ return "${config.LinuxToolchainRustFlags} ${config.LinuxToolchainArm64RustFlags}"
+}
+
+// Specialization of the 64-bit linux rust toolchain for musl. Adds the musl rust triple and
+// linker flags to avoid using the host sysroot.
+type toolchainLinuxMuslArm64 struct {
+ toolchainLinuxArm64
+}
+
+func (t *toolchainLinuxMuslArm64) RustTriple() string {
+ return "aarch64-unknown-linux-musl"
+}
+
+func (t *toolchainLinuxMuslArm64) ToolchainLinkFlags() string {
+ return t.toolchainLinuxArm64.ToolchainLinkFlags() + " " + "${config.LinuxMuslToolchainLinkFlags}"
+}
+
+func (t *toolchainLinuxMuslArm64) ToolchainRustFlags() string {
+ return t.toolchainLinuxArm64.ToolchainRustFlags() + " " + "${config.LinuxMuslToolchainRustFlags}"
+}
+
+func linuxMuslArm64ToolchainFactory(arch android.Arch) Toolchain {
+ return toolchainLinuxMuslArm64Singleton
+}
+
+// Base 32-bit linux rust toolchain
+type toolchainLinuxArm struct {
+ toolchain32Bit
+}
+
+func (toolchainLinuxArm) Supported() bool {
+ return true
+}
+
+func (toolchainLinuxArm) Bionic() bool {
+ return false
+}
+
+func (t *toolchainLinuxArm) Name() string {
+ return "arm"
+}
+
+func (toolchainLinuxArm) LibclangRuntimeLibraryArch() string {
+ return "arm"
+}
+
+func (toolchainLinuxArm64) LibclangRuntimeLibraryArch() string {
+ return "arm64"
+}
+
+func (t *toolchainLinuxArm) ToolchainLinkFlags() string {
+ // Prepend the lld flags from cc_config so we stay in sync with cc
+ return "${cc_config.LinuxLldflags} ${cc_config.LinuxArmLldflags} " +
+ "${config.LinuxToolchainLinkFlags} ${config.LinuxToolchainArmLinkFlags}"
+}
+
+func (t *toolchainLinuxArm) ToolchainRustFlags() string {
+ return "${config.LinuxToolchainRustFlags} ${config.LinuxToolchainArmRustFlags}"
+}
+
+// Specialization of the 32-bit linux rust toolchain for musl. Adds the musl rust triple and
+// linker flags to avoid using the host sysroot.
+type toolchainLinuxMuslArm struct {
+ toolchainLinuxArm
+}
+
+func (t *toolchainLinuxMuslArm) RustTriple() string {
+ return "arm-unknown-linux-musleabihf"
+}
+
+func (t *toolchainLinuxMuslArm) ToolchainLinkFlags() string {
+ return t.toolchainLinuxArm.ToolchainLinkFlags() + " " + "${config.LinuxMuslToolchainLinkFlags}"
+}
+
+func (t *toolchainLinuxMuslArm) ToolchainRustFlags() string {
+ return t.toolchainLinuxArm.ToolchainRustFlags() + " " + "${config.LinuxMuslToolchainRustFlags}"
+}
+
+func linuxMuslArmToolchainFactory(arch android.Arch) Toolchain {
+ return toolchainLinuxMuslArmSingleton
+}
+
+var toolchainLinuxMuslArm64Singleton Toolchain = &toolchainLinuxMuslArm64{}
+var toolchainLinuxMuslArmSingleton Toolchain = &toolchainLinuxMuslArm{}
diff --git a/rust/config/global.go b/rust/config/global.go
index e9751fd..9e48344 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.61.0.p2"
+ RustDefaultVersion = "1.62.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2021"
Stdlibs = []string{
@@ -78,7 +78,13 @@
func init() {
pctx.SourcePathVariable("RustDefaultBase", RustDefaultBase)
- pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
+ pctx.VariableConfigMethod("HostPrebuiltTag", func(config android.Config) string {
+ if config.UseHostMusl() {
+ return "linux-musl-x86"
+ } else {
+ return config.PrebuiltOS()
+ }
+ })
pctx.VariableFunc("RustBase", func(ctx android.PackageVarContext) string {
if override := ctx.Config().Getenv("RUST_PREBUILTS_BASE"); override != "" {
diff --git a/rust/fuzz.go b/rust/fuzz.go
index 55921ba..586095c 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -153,7 +153,7 @@
sharedLibraries := fuzz.CollectAllSharedDependencies(ctx, module, cc.UnstrippedOutputFile, cc.IsValidSharedDependency)
// Package shared libraries
- files = append(files, cc.GetSharedLibsToZip(sharedLibraries, rustModule, &s.FuzzPackager, archString, &sharedLibraryInstalled)...)
+ files = append(files, cc.GetSharedLibsToZip(sharedLibraries, rustModule, &s.FuzzPackager, archString, "lib", &sharedLibraryInstalled)...)
archDirs[archOs], ok = s.BuildZipFile(ctx, module, fuzzModule.fuzzPackagedModule, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
if !ok {
diff --git a/rust/sanitize.go b/rust/sanitize.go
index 536fcbd..a3c5cb5 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -174,7 +174,7 @@
}
// Enable Memtag for all components in the include paths (for Aarch64 only)
- if ctx.Arch().ArchType == android.Arm64 {
+ if ctx.Arch().ArchType == android.Arm64 && ctx.Os().Bionic() {
if ctx.Config().MemtagHeapSyncEnabledForPath(ctx.ModuleDir()) {
if s.Memtag_heap == nil {
s.Memtag_heap = proptools.BoolPtr(true)
@@ -200,7 +200,7 @@
}
// HWASan requires AArch64 hardware feature (top-byte-ignore).
- if ctx.Arch().ArchType != android.Arm64 {
+ if ctx.Arch().ArchType != android.Arm64 || !ctx.Os().Bionic() {
s.Hwaddress = nil
}
@@ -215,7 +215,7 @@
}
// Memtag_heap is only implemented on AArch64.
- if ctx.Arch().ArchType != android.Arm64 {
+ if ctx.Arch().ArchType != android.Arm64 || !ctx.Os().Bionic() {
s.Memtag_heap = nil
}
@@ -234,7 +234,7 @@
}
if Bool(sanitize.Properties.Sanitize.Fuzzer) {
flags.RustFlags = append(flags.RustFlags, fuzzerFlags...)
- if ctx.Arch().ArchType == android.Arm64 {
+ if ctx.Arch().ArchType == android.Arm64 && ctx.Os().Bionic() {
flags.RustFlags = append(flags.RustFlags, hwasanFlags...)
} else {
flags.RustFlags = append(flags.RustFlags, asanFlags...)
@@ -282,13 +282,13 @@
var deps []string
if mod.IsSanitizerEnabled(cc.Asan) ||
- (mod.IsSanitizerEnabled(cc.Fuzzer) && mctx.Arch().ArchType != android.Arm64) {
+ (mod.IsSanitizerEnabled(cc.Fuzzer) && (mctx.Arch().ArchType != android.Arm64 || !mctx.Os().Bionic())) {
variations = append(variations,
blueprint.Variation{Mutator: "link", Variation: "shared"})
depTag = cc.SharedDepTag()
deps = []string{config.LibclangRuntimeLibrary(mod.toolchain(mctx), "asan")}
} else if mod.IsSanitizerEnabled(cc.Hwasan) ||
- (mod.IsSanitizerEnabled(cc.Fuzzer) && mctx.Arch().ArchType == android.Arm64) {
+ (mod.IsSanitizerEnabled(cc.Fuzzer) && mctx.Arch().ArchType == android.Arm64 && mctx.Os().Bionic()) {
// TODO(b/204776996): HWASan for static Rust binaries isn't supported yet.
if binary, ok := mod.compiler.(binaryInterface); ok {
if binary.staticallyLinked() {
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 4773579..814bd57 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -84,6 +84,16 @@
],
}
+python_test_host {
+ name: "jsonmodify_test",
+ main: "jsonmodify_test.py",
+ srcs: [
+ "jsonmodify_test.py",
+ "jsonmodify.py",
+ ],
+ test_suites: ["general-tests"],
+}
+
python_binary_host {
name: "test_config_fixer",
main: "test_config_fixer.py",
@@ -193,3 +203,9 @@
name: "list_image",
src: "list_image.sh",
}
+
+filegroup {
+ name: "rustfmt.toml",
+ srcs: ["rustfmt.toml"],
+ visibility: ["//visibility:public"],
+}
diff --git a/scripts/jsonmodify.py b/scripts/jsonmodify.py
index ba1109e..8bd8d45 100755
--- a/scripts/jsonmodify.py
+++ b/scripts/jsonmodify.py
@@ -59,6 +59,13 @@
cur[key] = val
+class ReplaceIfEqual(str):
+ def apply(self, obj, old_val, new_val):
+ cur, key = follow_path(obj, self)
+ if cur and cur[key] == int(old_val):
+ cur[key] = new_val
+
+
class Remove(str):
def apply(self, obj):
cur, key = follow_path(obj, self)
@@ -75,6 +82,14 @@
raise ValueError(self + " should be a array.")
cur[key].extend(args)
+# A JSONDecoder that supports line comments start with //
+class JSONWithCommentsDecoder(json.JSONDecoder):
+ def __init__(self, **kw):
+ super().__init__(**kw)
+
+ def decode(self, s: str):
+ s = '\n'.join(l for l in s.split('\n') if not l.lstrip(' ').startswith('//'))
+ return super().decode(s)
def main():
parser = argparse.ArgumentParser()
@@ -91,6 +106,11 @@
help='replace value of the key specified by path. If path doesn\'t exist, no op.',
metavar=('path', 'value'),
nargs=2, dest='patch', action='append')
+ parser.add_argument("-se", "--replace-if-equal", type=ReplaceIfEqual,
+ help='replace value of the key specified by path to new_value if it\'s equal to old_value.' +
+ 'If path doesn\'t exist or the value is not equal to old_value, no op.',
+ metavar=('path', 'old_value', 'new_value'),
+ nargs=3, dest='patch', action='append')
parser.add_argument("-r", "--remove", type=Remove,
help='remove the key specified by path. If path doesn\'t exist, no op.',
metavar='path',
@@ -103,9 +123,9 @@
if args.input:
with open(args.input) as f:
- obj = json.load(f, object_pairs_hook=collections.OrderedDict)
+ obj = json.load(f, object_pairs_hook=collections.OrderedDict, cls=JSONWithCommentsDecoder)
else:
- obj = json.load(sys.stdin, object_pairs_hook=collections.OrderedDict)
+ obj = json.load(sys.stdin, object_pairs_hook=collections.OrderedDict, cls=JSONWithCommentsDecoder)
for p in args.patch:
p[0].apply(obj, *p[1:])
diff --git a/scripts/jsonmodify_test.py b/scripts/jsonmodify_test.py
new file mode 100644
index 0000000..6f0291d
--- /dev/null
+++ b/scripts/jsonmodify_test.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2022 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.
+#
+"""Tests for jsonmodify."""
+
+import json
+import jsonmodify
+import unittest
+
+
+class JsonmodifyTest(unittest.TestCase):
+
+ def test_set_value(self):
+ obj = json.loads('{"field1": 111}')
+ field1 = jsonmodify.SetValue("field1")
+ field1.apply(obj, 222)
+ field2 = jsonmodify.SetValue("field2")
+ field2.apply(obj, 333)
+ expected = json.loads('{"field1": 222, "field2": 333}')
+ self.assertEqual(obj, expected)
+
+ def test_replace(self):
+ obj = json.loads('{"field1": 111}')
+ field1 = jsonmodify.Replace("field1")
+ field1.apply(obj, 222)
+ field2 = jsonmodify.Replace("field2")
+ field2.apply(obj, 333)
+ expected = json.loads('{"field1": 222}')
+ self.assertEqual(obj, expected)
+
+ def test_replace_if_equal(self):
+ obj = json.loads('{"field1": 111, "field2": 222}')
+ field1 = jsonmodify.ReplaceIfEqual("field1")
+ field1.apply(obj, 111, 333)
+ field2 = jsonmodify.ReplaceIfEqual("field2")
+ field2.apply(obj, 444, 555)
+ field3 = jsonmodify.ReplaceIfEqual("field3")
+ field3.apply(obj, 666, 777)
+ expected = json.loads('{"field1": 333, "field2": 222}')
+ self.assertEqual(obj, expected)
+
+ def test_remove(self):
+ obj = json.loads('{"field1": 111, "field2": 222}')
+ field2 = jsonmodify.Remove("field2")
+ field2.apply(obj)
+ field3 = jsonmodify.Remove("field3")
+ field3.apply(obj)
+ expected = json.loads('{"field1": 111}')
+ self.assertEqual(obj, expected)
+
+ def test_append_list(self):
+ obj = json.loads('{"field1": [111]}')
+ field1 = jsonmodify.AppendList("field1")
+ field1.apply(obj, 222, 333)
+ field2 = jsonmodify.AppendList("field2")
+ field2.apply(obj, 444, 555, 666)
+ expected = json.loads('{"field1": [111, 222, 333], "field2": [444, 555, 666]}')
+ self.assertEqual(obj, expected)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index 2d3103b..2da29ee 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -39,6 +39,8 @@
parser = argparse.ArgumentParser()
parser.add_argument('--minSdkVersion', default='', dest='min_sdk_version',
help='specify minSdkVersion used by the build system')
+ parser.add_argument('--replaceMaxSdkVersionPlaceholder', default='', dest='max_sdk_version',
+ help='specify maxSdkVersion used by the build system')
parser.add_argument('--targetSdkVersion', default='', dest='target_sdk_version',
help='specify targetSdkVersion used by the build system')
parser.add_argument('--raise-min-sdk-version', dest='raise_min_sdk_version', action='store_true',
@@ -342,6 +344,24 @@
attr.value = 'true'
application.setAttributeNode(attr)
+def set_max_sdk_version(doc, max_sdk_version):
+ """Replace the maxSdkVersion attribute value for permission and
+ uses-permission tags if the value was originally set to 'current'.
+ Used for cts test cases where the maxSdkVersion should equal to
+ Build.SDK_INT.
+
+ Args:
+ doc: The XML document. May be modified by this function.
+ max_sdk_version: The requested maxSdkVersion attribute.
+ """
+ manifest = parse_manifest(doc)
+ for tag in ['permission', 'uses-permission']:
+ children = get_children_with_tag(manifest, tag)
+ for child in children:
+ max_attr = child.getAttributeNodeNS(android_ns, 'maxSdkVersion')
+ if max_attr and max_attr.value == 'current':
+ max_attr.value = max_sdk_version
+
def main():
"""Program entry point."""
try:
@@ -354,6 +374,9 @@
if args.raise_min_sdk_version:
raise_min_sdk_version(doc, args.min_sdk_version, args.target_sdk_version, args.library)
+ if args.max_sdk_version:
+ set_max_sdk_version(doc, args.max_sdk_version)
+
if args.uses_libraries:
add_uses_libraries(doc, args.uses_libraries, True)
diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py
index 199b279..dad104a 100755
--- a/scripts/manifest_fixer_test.py
+++ b/scripts/manifest_fixer_test.py
@@ -571,5 +571,77 @@
output = self.run_test(manifest_input)
self.assert_xml_equal(output, manifest_input)
+
+class SetMaxSdkVersionTest(unittest.TestCase):
+ """Unit tests for set_max_sdk_version function."""
+
+ def assert_xml_equal(self, output, expected):
+ self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+
+ def run_test(self, input_manifest, max_sdk_version):
+ doc = minidom.parseString(input_manifest)
+ manifest_fixer.set_max_sdk_version(doc, max_sdk_version)
+ output = io.StringIO()
+ manifest_fixer.write_xml(output, doc)
+ return output.getvalue()
+
+ manifest_tmpl = (
+ '<?xml version="1.0" encoding="utf-8"?>\n'
+ '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
+ '%s'
+ '</manifest>\n')
+
+ def permission(self, max=None):
+ if max is None:
+ return ' <permission/>'
+ return ' <permission android:maxSdkVersion="%s"/>\n' % max
+
+ def uses_permission(self, max=None):
+ if max is None:
+ return ' <uses-permission/>'
+ return ' <uses-permission android:maxSdkVersion="%s"/>\n' % max
+
+ def test_permission_no_max_sdk_version(self):
+ """Tests if permission has no maxSdkVersion attribute"""
+ manifest_input = self.manifest_tmpl % self.permission()
+ expected = self.manifest_tmpl % self.permission()
+ output = self.run_test(manifest_input, '9000')
+ self.assert_xml_equal(output, expected)
+
+ def test_permission_max_sdk_version_changed(self):
+ """Tests if permission maxSdkVersion attribute is set to current"""
+ manifest_input = self.manifest_tmpl % self.permission('current')
+ expected = self.manifest_tmpl % self.permission(9000)
+ output = self.run_test(manifest_input, '9000')
+ self.assert_xml_equal(output, expected)
+
+ def test_permission_max_sdk_version_not_changed(self):
+ """Tests if permission maxSdkVersion attribute is not set to current"""
+ manifest_input = self.manifest_tmpl % self.permission(30)
+ expected = self.manifest_tmpl % self.permission(30)
+ output = self.run_test(manifest_input, '9000')
+ self.assert_xml_equal(output, expected)
+
+ def test_uses_permission_no_max_sdk_version(self):
+ """Tests if uses-permission has no maxSdkVersion attribute"""
+ manifest_input = self.manifest_tmpl % self.uses_permission()
+ expected = self.manifest_tmpl % self.uses_permission()
+ output = self.run_test(manifest_input, '9000')
+ self.assert_xml_equal(output, expected)
+
+ def test_uses_permission_max_sdk_version_changed(self):
+ """Tests if uses-permission maxSdkVersion attribute is set to current"""
+ manifest_input = self.manifest_tmpl % self.uses_permission('current')
+ expected = self.manifest_tmpl % self.uses_permission(9000)
+ output = self.run_test(manifest_input, '9000')
+ self.assert_xml_equal(output, expected)
+
+ def test_uses_permission_max_sdk_version_not_changed(self):
+ """Tests if uses-permission maxSdkVersion attribute is not set to current"""
+ manifest_input = self.manifest_tmpl % self.uses_permission(30)
+ expected = self.manifest_tmpl % self.uses_permission(30)
+ output = self.run_test(manifest_input, '9000')
+ self.assert_xml_equal(output, expected)
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 93ad172..13ddbe7 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -190,7 +190,7 @@
android.AssertStringDoesContain(t, "boot jars package check", command, expectedCommandArgs)
}
-func TestSnapshotWithBootClasspathFragment_Contents(t *testing.T) {
+func testSnapshotWithBootClasspathFragment_Contents(t *testing.T, sdk string, copyRules string) {
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
java.PrepareForTestWithJavaDefaultModules,
@@ -202,19 +202,7 @@
// Add a platform_bootclasspath that depends on the fragment.
fixtureAddPlatformBootclasspathForBootclasspathFragment("myapex", "mybootclasspathfragment"),
- android.FixtureWithRootAndroidBp(`
- sdk {
- name: "mysdk",
- bootclasspath_fragments: ["mybootclasspathfragment"],
- java_sdk_libs: [
- // This is not strictly needed as it should be automatically added to the sdk_snapshot as
- // a java_sdk_libs module because it is used in the mybootclasspathfragment's
- // api.stub_libs property. However, it is specified here to ensure that duplicates are
- // correctly deduped.
- "mysdklibrary",
- ],
- }
-
+ android.FixtureWithRootAndroidBp(sdk+`
apex {
name: "myapex",
key: "myapex.key",
@@ -373,24 +361,7 @@
},
}
`),
- checkAllCopyRules(`
-.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv
-.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv
-.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/index.csv -> hiddenapi/index.csv
-.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv
-.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv
-.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv
-.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar
-.intermediates/myothersdklibrary.stubs/android_common/javac/myothersdklibrary.stubs.jar -> sdk_library/public/myothersdklibrary-stubs.jar
-.intermediates/myothersdklibrary.stubs.source/android_common/metalava/myothersdklibrary.stubs.source_api.txt -> sdk_library/public/myothersdklibrary.txt
-.intermediates/myothersdklibrary.stubs.source/android_common/metalava/myothersdklibrary.stubs.source_removed.txt -> sdk_library/public/myothersdklibrary-removed.txt
-.intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
-.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
-.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
-.intermediates/mycoreplatform.stubs/android_common/javac/mycoreplatform.stubs.jar -> sdk_library/public/mycoreplatform-stubs.jar
-.intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_api.txt -> sdk_library/public/mycoreplatform.txt
-.intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_removed.txt -> sdk_library/public/mycoreplatform-removed.txt
-`),
+ checkAllCopyRules(copyRules),
snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot),
snapshotTestChecker(checkSnapshotWithoutSource, func(t *testing.T, result *android.TestResult) {
module := result.ModuleForTests("platform-bootclasspath", "android_common")
@@ -427,6 +398,89 @@
)
}
+func TestSnapshotWithBootClasspathFragment_Contents(t *testing.T) {
+ t.Run("added-directly", func(t *testing.T) {
+ testSnapshotWithBootClasspathFragment_Contents(t, `
+ sdk {
+ name: "mysdk",
+ bootclasspath_fragments: ["mybootclasspathfragment"],
+ java_sdk_libs: [
+ // This is not strictly needed as it should be automatically added to the sdk_snapshot as
+ // a java_sdk_libs module because it is used in the mybootclasspathfragment's
+ // api.stub_libs property. However, it is specified here to ensure that duplicates are
+ // correctly deduped.
+ "mysdklibrary",
+ ],
+ }
+ `, `
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/index.csv -> hiddenapi/index.csv
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv
+.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv
+.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar
+.intermediates/myothersdklibrary.stubs/android_common/javac/myothersdklibrary.stubs.jar -> sdk_library/public/myothersdklibrary-stubs.jar
+.intermediates/myothersdklibrary.stubs.source/android_common/metalava/myothersdklibrary.stubs.source_api.txt -> sdk_library/public/myothersdklibrary.txt
+.intermediates/myothersdklibrary.stubs.source/android_common/metalava/myothersdklibrary.stubs.source_removed.txt -> sdk_library/public/myothersdklibrary-removed.txt
+.intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
+.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
+.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
+.intermediates/mycoreplatform.stubs/android_common/javac/mycoreplatform.stubs.jar -> sdk_library/public/mycoreplatform-stubs.jar
+.intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_api.txt -> sdk_library/public/mycoreplatform.txt
+.intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_removed.txt -> sdk_library/public/mycoreplatform-removed.txt
+`)
+ })
+
+ copyBootclasspathFragmentFromApexVariantRules := `
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/index.csv -> hiddenapi/index.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv
+.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar
+.intermediates/myothersdklibrary.stubs/android_common/javac/myothersdklibrary.stubs.jar -> sdk_library/public/myothersdklibrary-stubs.jar
+.intermediates/myothersdklibrary.stubs.source/android_common/metalava/myothersdklibrary.stubs.source_api.txt -> sdk_library/public/myothersdklibrary.txt
+.intermediates/myothersdklibrary.stubs.source/android_common/metalava/myothersdklibrary.stubs.source_removed.txt -> sdk_library/public/myothersdklibrary-removed.txt
+.intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
+.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
+.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
+.intermediates/mycoreplatform.stubs/android_common/javac/mycoreplatform.stubs.jar -> sdk_library/public/mycoreplatform-stubs.jar
+.intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_api.txt -> sdk_library/public/mycoreplatform.txt
+.intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_removed.txt -> sdk_library/public/mycoreplatform-removed.txt
+`
+ t.Run("added-via-apex", func(t *testing.T) {
+ testSnapshotWithBootClasspathFragment_Contents(t, `
+ sdk {
+ name: "mysdk",
+ apexes: ["myapex"],
+ }
+ `, copyBootclasspathFragmentFromApexVariantRules)
+ })
+
+ t.Run("added-directly-and-indirectly", func(t *testing.T) {
+ testSnapshotWithBootClasspathFragment_Contents(t, `
+ sdk {
+ name: "mysdk",
+ apexes: ["myapex"],
+ // This is not strictly needed as it should be automatically added to the sdk_snapshot as
+ // a bootclasspath_fragments module because it is used in the myapex's
+ // bootclasspath_fragments property. However, it is specified here to ensure that duplicates
+ // are correctly deduped.
+ bootclasspath_fragments: ["mybootclasspathfragment"],
+ java_sdk_libs: [
+ // This is not strictly needed as it should be automatically added to the sdk_snapshot as
+ // a java_sdk_libs module because it is used in the mybootclasspathfragment's
+ // api.stub_libs property. However, it is specified here to ensure that duplicates are
+ // correctly deduped.
+ "mysdklibrary",
+ ],
+ }
+ `, copyBootclasspathFragmentFromApexVariantRules)
+ })
+}
+
// TestSnapshotWithBootClasspathFragment_Fragments makes sure that the fragments property of a
// bootclasspath_fragment is correctly output to the sdk snapshot.
func TestSnapshotWithBootClasspathFragment_Fragments(t *testing.T) {
diff --git a/sdk/build_release.go b/sdk/build_release.go
index 4c2277e..0494a28 100644
--- a/sdk/build_release.go
+++ b/sdk/build_release.go
@@ -24,18 +24,22 @@
// buildRelease represents the version of a build system used to create a specific release.
//
-// The name of the release, is the same as the code for the dessert release, e.g. S, T, etc.
+// The name of the release, is the same as the code for the dessert release, e.g. S, Tiramisu, etc.
type buildRelease struct {
- // The name of the release, e.g. S, T, etc.
+ // The name of the release, e.g. S, Tiramisu, etc.
name string
// The index of this structure within the buildReleases list.
ordinal int
}
+func (br *buildRelease) EarlierThan(other *buildRelease) bool {
+ return br.ordinal < other.ordinal
+}
+
// String returns the name of the build release.
-func (s *buildRelease) String() string {
- return s.name
+func (br *buildRelease) String() string {
+ return br.name
}
// buildReleaseSet represents a set of buildRelease objects.
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index d25138f..57c171f 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -15,6 +15,7 @@
package sdk
import (
+ "fmt"
"testing"
"android/soong/android"
@@ -257,8 +258,8 @@
android.FixtureAddFile("aidl", nil),
android.FixtureAddFile("resource.txt", nil),
).RunTestWithBp(t, `
- module_exports {
- name: "myexports",
+ sdk {
+ name: "mysdk",
java_boot_libs: ["myjavalib"],
}
@@ -278,7 +279,7 @@
}
`)
- CheckSnapshot(t, result, "myexports", "",
+ CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -292,11 +293,65 @@
}
`),
checkAllCopyRules(`
-.intermediates/myexports/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/myjavalib.jar
+.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/myjavalib.jar
`),
)
}
+func TestSnapshotWithJavaBootLibrary_UpdatableMedia(t *testing.T) {
+ runTest := func(t *testing.T, targetBuildRelease, expectedJarPath, expectedCopyRule string) {
+ result := android.GroupFixturePreparers(
+ prepareForSdkTestWithJava,
+ android.FixtureMergeEnv(map[string]string{
+ "SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": targetBuildRelease,
+ }),
+ ).RunTestWithBp(t, `
+ sdk {
+ name: "mysdk",
+ java_boot_libs: ["updatable-media"],
+ }
+
+ java_library {
+ name: "updatable-media",
+ srcs: ["Test.java"],
+ system_modules: "none",
+ sdk_version: "none",
+ compile_dex: true,
+ permitted_packages: ["pkg.media"],
+ apex_available: ["com.android.media"],
+ }
+ `)
+
+ CheckSnapshot(t, result, "mysdk", "",
+ checkAndroidBpContents(fmt.Sprintf(`
+// This is auto-generated. DO NOT EDIT.
+
+java_import {
+ name: "updatable-media",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["com.android.media"],
+ jars: ["%s"],
+ permitted_packages: ["pkg.media"],
+}
+`, expectedJarPath)),
+ checkAllCopyRules(expectedCopyRule),
+ )
+ }
+
+ t.Run("updatable-media in S", func(t *testing.T) {
+ runTest(t, "S", "java/updatable-media.jar", `
+.intermediates/updatable-media/android_common/package-check/updatable-media.jar -> java/updatable-media.jar
+`)
+ })
+
+ t.Run("updatable-media in T", func(t *testing.T) {
+ runTest(t, "Tiramisu", "java_boot_libs/snapshot/jars/are/invalid/updatable-media.jar", `
+.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/updatable-media.jar
+`)
+ })
+}
+
func TestSnapshotWithJavaSystemserverLibrary(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
diff --git a/sdk/systemserverclasspath_fragment_sdk_test.go b/sdk/systemserverclasspath_fragment_sdk_test.go
index 01692a3..1ac405d 100644
--- a/sdk/systemserverclasspath_fragment_sdk_test.go
+++ b/sdk/systemserverclasspath_fragment_sdk_test.go
@@ -22,28 +22,21 @@
"android/soong/java"
)
-func TestSnapshotWithSystemServerClasspathFragment(t *testing.T) {
+func testSnapshotWithSystemServerClasspathFragment(t *testing.T, sdk string, targetBuildRelease string, expectedSdkSnapshot string) {
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
java.PrepareForTestWithJavaDefaultModules,
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("mysdklibrary"),
dexpreopt.FixtureSetApexSystemServerJars("myapex:mylib", "myapex:mysdklibrary"),
+ android.FixtureModifyEnv(func(env map[string]string) {
+ if targetBuildRelease != "latest" {
+ env["SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE"] = targetBuildRelease
+ }
+ }),
prepareForSdkTestWithApex,
- android.FixtureWithRootAndroidBp(`
- sdk {
- name: "mysdk",
- systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
- java_sdk_libs: [
- // This is not strictly needed as it should be automatically added to the sdk_snapshot as
- // a java_sdk_libs module because it is used in the mysystemserverclasspathfragment's
- // contents property. However, it is specified here to ensure that duplicates are
- // correctly deduped.
- "mysdklibrary",
- ],
- }
-
+ android.FixtureWithRootAndroidBp(sdk+`
apex {
name: "myapex",
key: "myapex.key",
@@ -83,7 +76,27 @@
).RunTest(t)
CheckSnapshot(t, result, "mysdk", "",
- checkAndroidBpContents(`
+ checkAndroidBpContents(expectedSdkSnapshot),
+ )
+}
+
+func TestSnapshotWithSystemServerClasspathFragment(t *testing.T) {
+
+ commonSdk := `
+sdk {
+ name: "mysdk",
+ systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
+ java_sdk_libs: [
+ // This is not strictly needed as it should be automatically added to the sdk_snapshot as
+ // a java_sdk_libs module because it is used in the mysystemserverclasspathfragment's
+ // contents property. However, it is specified here to ensure that duplicates are
+ // correctly deduped.
+ "mysdklibrary",
+ ],
+}
+ `
+
+ expectedLatestSnapshot := `
// This is auto-generated. DO NOT EDIT.
java_sdk_library_import {
@@ -120,6 +133,80 @@
"mysdklibrary",
],
}
-`),
- )
+`
+
+ t.Run("target-s", func(t *testing.T) {
+ testSnapshotWithSystemServerClasspathFragment(t, commonSdk, "S", `
+// This is auto-generated. DO NOT EDIT.
+
+java_sdk_library_import {
+ name: "mysdklibrary",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["myapex"],
+ shared_library: false,
+ public: {
+ jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
+ stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
+ current_api: "sdk_library/public/mysdklibrary.txt",
+ removed_api: "sdk_library/public/mysdklibrary-removed.txt",
+ sdk_version: "current",
+ },
+}
+`)
+ })
+
+ t.Run("target-t", func(t *testing.T) {
+ testSnapshotWithSystemServerClasspathFragment(t, commonSdk, "Tiramisu", `
+// This is auto-generated. DO NOT EDIT.
+
+java_sdk_library_import {
+ name: "mysdklibrary",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["myapex"],
+ shared_library: false,
+ public: {
+ jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
+ stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
+ current_api: "sdk_library/public/mysdklibrary.txt",
+ removed_api: "sdk_library/public/mysdklibrary-removed.txt",
+ sdk_version: "current",
+ },
+}
+
+java_import {
+ name: "mylib",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["myapex"],
+ jars: ["java_systemserver_libs/snapshot/jars/are/invalid/mylib.jar"],
+ permitted_packages: ["mylib"],
+}
+
+prebuilt_systemserverclasspath_fragment {
+ name: "mysystemserverclasspathfragment",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["myapex"],
+ contents: [
+ "mylib",
+ "mysdklibrary",
+ ],
+}
+`)
+ })
+
+ t.Run("added-directly", func(t *testing.T) {
+ testSnapshotWithSystemServerClasspathFragment(t, commonSdk, `latest`, expectedLatestSnapshot)
+ })
+
+ t.Run("added-via-apex", func(t *testing.T) {
+ testSnapshotWithSystemServerClasspathFragment(t, `
+ sdk {
+ name: "mysdk",
+ apexes: ["myapex"],
+ }
+ `, `latest`, expectedLatestSnapshot)
+ })
}
diff --git a/sdk/update.go b/sdk/update.go
index 457828b..995da74 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -239,7 +239,7 @@
// Finally, the member type slices are concatenated together to form a single slice. The order in
// which they are concatenated is the order in which the member types were registered in the
// android.SdkMemberTypesRegistry.
-func (s *sdk) groupMemberVariantsByMemberThenType(ctx android.ModuleContext, memberVariantDeps []sdkMemberVariantDep) []*sdkMember {
+func (s *sdk) groupMemberVariantsByMemberThenType(ctx android.ModuleContext, targetBuildRelease *buildRelease, memberVariantDeps []sdkMemberVariantDep) []*sdkMember {
byType := make(map[android.SdkMemberType][]*sdkMember)
byName := make(map[string]*sdkMember)
@@ -268,13 +268,39 @@
}
var members []*sdkMember
for _, memberListProperty := range s.memberTypeListProperties() {
- membersOfType := byType[memberListProperty.memberType]
+ memberType := memberListProperty.memberType
+
+ if !isMemberTypeSupportedByTargetBuildRelease(memberType, targetBuildRelease) {
+ continue
+ }
+
+ membersOfType := byType[memberType]
members = append(members, membersOfType...)
}
return members
}
+// isMemberTypeSupportedByTargetBuildRelease returns true if the member type is supported by the
+// target build release.
+func isMemberTypeSupportedByTargetBuildRelease(memberType android.SdkMemberType, targetBuildRelease *buildRelease) bool {
+ supportedByTargetBuildRelease := true
+ supportedBuildReleases := memberType.SupportedBuildReleases()
+ if supportedBuildReleases == "" {
+ supportedBuildReleases = "S+"
+ }
+
+ set, err := parseBuildReleaseSet(supportedBuildReleases)
+ if err != nil {
+ panic(fmt.Errorf("member type %s has invalid supported build releases %q: %s",
+ memberType.SdkPropertyName(), supportedBuildReleases, err))
+ }
+ if !set.contains(targetBuildRelease) {
+ supportedByTargetBuildRelease = false
+ }
+ return supportedByTargetBuildRelease
+}
+
func appendUniqueVariants(variants []android.SdkAware, newVariant android.SdkAware) []android.SdkAware {
for _, v := range variants {
if v == newVariant {
@@ -401,12 +427,15 @@
// Group the variants for each member module together and then group the members of each member
// type together.
- members := s.groupMemberVariantsByMemberThenType(ctx, memberVariantDeps)
+ members := s.groupMemberVariantsByMemberThenType(ctx, targetBuildRelease, memberVariantDeps)
// Create the prebuilt modules for each of the member modules.
traits := s.gatherTraits()
for _, member := range members {
memberType := member.memberType
+ if !memberType.ArePrebuiltsRequired() {
+ continue
+ }
name := member.name
requiredTraits := traits[name]
@@ -1293,6 +1322,119 @@
}
}
+// TODO(187910671): BEGIN - Remove once modules do not have an APEX and default variant.
+// variantCoordinate contains the coordinates used to identify a variant of an SDK member.
+type variantCoordinate struct {
+ // osType identifies the OS target of a variant.
+ osType android.OsType
+ // archId identifies the architecture and whether it is for the native bridge.
+ archId archId
+ // image is the image variant name.
+ image string
+ // linkType is the link type name.
+ linkType string
+}
+
+func getVariantCoordinate(ctx *memberContext, variant android.Module) variantCoordinate {
+ linkType := ""
+ if len(ctx.MemberType().SupportedLinkages()) > 0 {
+ linkType = getLinkType(variant)
+ }
+ return variantCoordinate{
+ osType: variant.Target().Os,
+ archId: archIdFromTarget(variant.Target()),
+ image: variant.ImageVariation().Variation,
+ linkType: linkType,
+ }
+}
+
+// selectApexVariantsWhereAvailable filters the input list of variants by selecting the APEX
+// specific variant for a specific variantCoordinate when there is both an APEX and default variant.
+//
+// There is a long-standing issue where a module that is added to an APEX has both an APEX and
+// default/platform variant created even when the module does not require a platform variant. As a
+// result an indirect dependency onto a module via the APEX will use the APEX variant, whereas a
+// direct dependency onto the module will use the default/platform variant. That would result in a
+// failure while attempting to optimize the properties for a member as it would have two variants
+// when only one was expected.
+//
+// This function mitigates that problem by detecting when there are two variants that differ only
+// by apex variant, where one is the default/platform variant and one is the APEX variant. In that
+// case it picks the APEX variant. It picks the APEX variant because that is the behavior that would
+// be expected
+func selectApexVariantsWhereAvailable(ctx *memberContext, variants []android.SdkAware) []android.SdkAware {
+ moduleCtx := ctx.sdkMemberContext
+
+ // Group the variants by coordinates.
+ variantsByCoord := make(map[variantCoordinate][]android.SdkAware)
+ for _, variant := range variants {
+ coord := getVariantCoordinate(ctx, variant)
+ variantsByCoord[coord] = append(variantsByCoord[coord], variant)
+ }
+
+ toDiscard := make(map[android.SdkAware]struct{})
+ for coord, list := range variantsByCoord {
+ count := len(list)
+ if count == 1 {
+ continue
+ }
+
+ variantsByApex := make(map[string]android.SdkAware)
+ conflictDetected := false
+ for _, variant := range list {
+ apexInfo := moduleCtx.OtherModuleProvider(variant, android.ApexInfoProvider).(android.ApexInfo)
+ apexVariationName := apexInfo.ApexVariationName
+ // If there are two variants for a specific APEX variation then there is conflict.
+ if _, ok := variantsByApex[apexVariationName]; ok {
+ conflictDetected = true
+ break
+ }
+ variantsByApex[apexVariationName] = variant
+ }
+
+ // If there are more than 2 apex variations or one of the apex variations is not the
+ // default/platform variation then there is a conflict.
+ if len(variantsByApex) != 2 {
+ conflictDetected = true
+ } else if _, ok := variantsByApex[""]; !ok {
+ conflictDetected = true
+ }
+
+ // If there are no conflicts then add the default/platform variation to the list to remove.
+ if !conflictDetected {
+ toDiscard[variantsByApex[""]] = struct{}{}
+ continue
+ }
+
+ // There are duplicate variants at this coordinate and they are not the default and APEX variant
+ // so fail.
+ variantDescriptions := []string{}
+ for _, m := range list {
+ variantDescriptions = append(variantDescriptions, fmt.Sprintf(" %s", m.String()))
+ }
+
+ moduleCtx.ModuleErrorf("multiple conflicting variants detected for OsType{%s}, %s, Image{%s}, Link{%s}\n%s",
+ coord.osType, coord.archId.String(), coord.image, coord.linkType,
+ strings.Join(variantDescriptions, "\n"))
+ }
+
+ // If there are any variants to discard then remove them from the list of variants, while
+ // preserving the order.
+ if len(toDiscard) > 0 {
+ filtered := []android.SdkAware{}
+ for _, variant := range variants {
+ if _, ok := toDiscard[variant]; !ok {
+ filtered = append(filtered, variant)
+ }
+ }
+ variants = filtered
+ }
+
+ return variants
+}
+
+// TODO(187910671): END - Remove once modules do not have an APEX and default variant.
+
type baseInfo struct {
Properties android.SdkMemberProperties
}
@@ -1348,7 +1490,14 @@
if commonVariants, ok := variantsByArchId[commonArchId]; ok {
if len(osTypeVariants) != 1 {
- panic(fmt.Errorf("Expected to only have 1 variant when arch type is common but found %d", len(osTypeVariants)))
+ variants := []string{}
+ for _, m := range osTypeVariants {
+ variants = append(variants, fmt.Sprintf(" %s", m.String()))
+ }
+ panic(fmt.Errorf("expected to only have 1 variant of %q when arch type is common but found %d\n%s",
+ ctx.Name(),
+ len(osTypeVariants),
+ strings.Join(variants, "\n")))
}
// A common arch type only has one variant and its properties should be treated
@@ -1823,12 +1972,19 @@
return m.requiredTraits.Contains(trait)
}
+func (m *memberContext) IsTargetBuildBeforeTiramisu() bool {
+ return m.builder.targetBuildRelease.EarlierThan(buildReleaseT)
+}
+
+var _ android.SdkMemberContext = (*memberContext)(nil)
+
func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModule *bpModule) {
memberType := member.memberType
// Do not add the prefer property if the member snapshot module is a source module type.
- config := ctx.sdkMemberContext.Config()
+ moduleCtx := ctx.sdkMemberContext
+ config := moduleCtx.Config()
if !memberType.UsesSourceModuleTypeInSnapshot() {
// Set the prefer based on the environment variable. This is a temporary work around to allow a
// snapshot to be created that sets prefer: true.
@@ -1853,9 +2009,10 @@
}
}
+ variants := selectApexVariantsWhereAvailable(ctx, member.variants)
+
// Group the variants by os type.
variantsByOsType := make(map[android.OsType][]android.Module)
- variants := member.Variants()
for _, variant := range variants {
osType := variant.Target().Os
variantsByOsType[osType] = append(variantsByOsType[osType], variant)
@@ -1901,7 +2058,7 @@
}
// Extract properties which are common across all architectures and os types.
- extractCommonProperties(ctx.sdkMemberContext, commonValueExtractor, commonProperties, osSpecificPropertiesContainers)
+ extractCommonProperties(moduleCtx, commonValueExtractor, commonProperties, osSpecificPropertiesContainers)
// Add the common properties to the module.
addSdkMemberPropertiesToSet(ctx, commonProperties, bpModule)
diff --git a/tests/lib.sh b/tests/lib.sh
index 0c78cdf..69ad201 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -116,6 +116,7 @@
function create_mock_bazel {
copy_directory build/bazel
+ copy_directory build/bazel_common_rules
symlink_directory prebuilts/bazel
symlink_directory prebuilts/clang
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index 3dc87f5..cfcf804 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -34,15 +34,16 @@
deps: [
"blueprint",
"blueprint-bootstrap",
+ "blueprint-microfactory",
+ "soong-finder",
+ "soong-remoteexec",
+ "soong-shared",
"soong-ui-build-paths",
"soong-ui-logger",
"soong-ui-metrics",
"soong-ui-status",
"soong-ui-terminal",
"soong-ui-tracer",
- "soong-shared",
- "soong-finder",
- "blueprint-microfactory",
],
srcs: [
"bazel.go",
diff --git a/ui/build/config.go b/ui/build/config.go
index 8874209..cbf1986 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -156,10 +156,15 @@
// experiments system to control Soong features dynamically.
func fetchEnvConfig(ctx Context, config *configImpl, envConfigName string) error {
configName := envConfigName + "." + jsonSuffix
- expConfigFetcher := &smpb.ExpConfigFetcher{}
+ expConfigFetcher := &smpb.ExpConfigFetcher{Filename: &configName}
defer func() {
ctx.Metrics.ExpConfigFetcher(expConfigFetcher)
}()
+ if !config.GoogleProdCredsExist() {
+ status := smpb.ExpConfigFetcher_MISSING_GCERT
+ expConfigFetcher.Status = &status
+ return nil
+ }
s, err := os.Stat(configFetcher)
if err != nil {
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index 82fc15f..6231e52 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -21,6 +21,7 @@
"runtime"
"strings"
+ "android/soong/remoteexec"
"android/soong/ui/metrics"
)
@@ -54,11 +55,12 @@
func getRBEVars(ctx Context, config Config) map[string]string {
vars := map[string]string{
- "RBE_log_dir": config.rbeProxyLogsDir(),
- "RBE_re_proxy": config.rbeReproxy(),
- "RBE_exec_root": config.rbeExecRoot(),
- "RBE_output_dir": config.rbeProxyLogsDir(),
+ "RBE_log_dir": config.rbeProxyLogsDir(),
+ "RBE_re_proxy": config.rbeReproxy(),
+ "RBE_exec_root": config.rbeExecRoot(),
+ "RBE_output_dir": config.rbeProxyLogsDir(),
"RBE_proxy_log_dir": config.rbeProxyLogsDir(),
+ "RBE_platform": "container-image=" + remoteexec.DefaultImage,
}
if config.StartRBE() {
name, err := config.rbeSockAddr(absPath(ctx, config.TempDir()))
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index 4bc713b..2dd8299 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -220,9 +220,10 @@
type ExpConfigFetcher_ConfigStatus int32
const (
- ExpConfigFetcher_NO_CONFIG ExpConfigFetcher_ConfigStatus = 0
- ExpConfigFetcher_CONFIG ExpConfigFetcher_ConfigStatus = 1
- ExpConfigFetcher_ERROR ExpConfigFetcher_ConfigStatus = 2
+ ExpConfigFetcher_NO_CONFIG ExpConfigFetcher_ConfigStatus = 0
+ ExpConfigFetcher_CONFIG ExpConfigFetcher_ConfigStatus = 1
+ ExpConfigFetcher_ERROR ExpConfigFetcher_ConfigStatus = 2
+ ExpConfigFetcher_MISSING_GCERT ExpConfigFetcher_ConfigStatus = 3
)
// Enum value maps for ExpConfigFetcher_ConfigStatus.
@@ -231,11 +232,13 @@
0: "NO_CONFIG",
1: "CONFIG",
2: "ERROR",
+ 3: "MISSING_GCERT",
}
ExpConfigFetcher_ConfigStatus_value = map[string]int32{
- "NO_CONFIG": 0,
- "CONFIG": 1,
- "ERROR": 2,
+ "NO_CONFIG": 0,
+ "CONFIG": 1,
+ "ERROR": 2,
+ "MISSING_GCERT": 3,
}
)
@@ -1578,7 +1581,7 @@
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, 0xc8, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66,
+ 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,
@@ -1587,22 +1590,23 @@
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, 0x34, 0x0a, 0x0c, 0x43, 0x6f, 0x6e,
+ 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, 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,
+ 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,
}
var (
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index 51dd523..4f8fe7f 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -251,6 +251,7 @@
NO_CONFIG = 0;
CONFIG = 1;
ERROR = 2;
+ MISSING_GCERT = 3;
}
// The result of the call to expconfigfetcher
// NO_CONFIG - Not part of experiment