Merge "Support testing for resource shrinking"
diff --git a/.gitignore b/.gitignore
index 45884c4..5d2bc0d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,5 @@
/.idea
*.iml
+*.ipr
+*.iws
+
diff --git a/OWNERS b/OWNERS
index 730db7a..e18eea1 100644
--- a/OWNERS
+++ b/OWNERS
@@ -14,6 +14,7 @@
eakammer@google.com
jobredeaux@google.com
joeo@google.com
+juu@google.com
lamontjones@google.com
spandandas@google.com
tradical@google.com
diff --git a/README.md b/README.md
index 87d6948..18cf7b2 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,33 @@
# Soong
-Soong is the replacement for the old Android make-based build system. It
-replaces Android.mk files with Android.bp files, which are JSON-like simple
-declarative descriptions of modules to build.
+Soong is one of the build systems used in Android. There are altogether three:
+* The legacy Make-based build system that is controlled by files called
+ `Android.mk`.
+* Soong, which is controlled by files called `Android.bp`.
+* The upcoming Bazel-based build system that is controlled by files called
+ `BUILD.bazel`.
+
+`Android.bp` file are JSON-like declarative descriptions of "modules" to build;
+a "module" is the basic unit of building that Soong understands, similarly to
+how "target" is the basic unit of building for Bazel (and Make, although the
+two kinds of "targets" are very different)
See [Simple Build
Configuration](https://source.android.com/compatibility/tests/development/blueprints)
on source.android.com to read how Soong is configured for testing.
+### Contributing
+
+Code reviews are handled through the usual code review system of Android,
+available [here](https://android-review.googlesource.com/dashboard/self).
+
+For simple changes (fixing typos, obvious optimizations, etc.), sending a code
+review request is enough. For more substantial changes, file a bug in our
+[bug tracker](https://issuetracker.google.com/issues/new?component=381517) or
+or write us at android-building@googlegroups.com .
+
+For Googlers, see our [internal documentation](http://go/soong).
+
## Android.bp file format
By design, Android.bp files are very simple. There are no conditionals or
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index f2b05dd..5658503 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -33,6 +33,10 @@
// all modules in this package (not recursively) default to bp2build_available: false.
// allows modules to opt-in.
Bp2BuildDefaultFalse
+
+ // all modules in this package and subpackages default to bp2build_available: false.
+ // allows modules to opt-in.
+ Bp2BuildDefaultFalseRecursively
)
var (
@@ -45,10 +49,15 @@
"art/runtime": Bp2BuildDefaultTrueRecursively,
"art/tools": Bp2BuildDefaultTrue,
"bionic": Bp2BuildDefaultTrueRecursively,
+ "bootable/recovery/applypatch": Bp2BuildDefaultTrue,
+ "bootable/recovery/minadbd": Bp2BuildDefaultTrue,
+ "bootable/recovery/minui": Bp2BuildDefaultTrue,
+ "bootable/recovery/recovery_utils": Bp2BuildDefaultTrue,
"bootable/recovery/tools/recovery_l10n": Bp2BuildDefaultTrue,
"build/bazel": Bp2BuildDefaultTrueRecursively,
"build/make/target/product/security": Bp2BuildDefaultTrue,
+ "build/make/tools/releasetools": Bp2BuildDefaultTrue,
"build/make/tools/signapk": Bp2BuildDefaultTrue,
"build/make/tools/zipalign": Bp2BuildDefaultTrueRecursively,
"build/soong": Bp2BuildDefaultTrue,
@@ -60,6 +69,9 @@
"build/soong/scripts": Bp2BuildDefaultTrueRecursively,
"cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively,
+
+ "dalvik/tools/dexdeps": Bp2BuildDefaultTrueRecursively,
+
"development/apps/DevelopmentSettings": Bp2BuildDefaultTrue,
"development/apps/Fallback": Bp2BuildDefaultTrue,
"development/apps/WidgetPreview": Bp2BuildDefaultTrue,
@@ -99,13 +111,15 @@
"external/aac": Bp2BuildDefaultTrueRecursively,
"external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
- "external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively,
"external/auto": Bp2BuildDefaultTrue,
+ "external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively,
"external/auto/common": Bp2BuildDefaultTrueRecursively,
"external/auto/service": Bp2BuildDefaultTrueRecursively,
"external/boringssl": Bp2BuildDefaultTrueRecursively,
"external/bouncycastle": Bp2BuildDefaultTrue,
"external/brotli": Bp2BuildDefaultTrue,
+ "external/bsdiff": Bp2BuildDefaultTrueRecursively,
+ "external/bzip2": Bp2BuildDefaultTrueRecursively,
"external/conscrypt": Bp2BuildDefaultTrue,
"external/e2fsprogs": Bp2BuildDefaultTrueRecursively,
"external/eigen": Bp2BuildDefaultTrueRecursively,
@@ -124,16 +138,19 @@
"external/icu/icu4j": Bp2BuildDefaultFalse, // java rules incomplete
"external/jacoco": Bp2BuildDefaultTrueRecursively,
"external/jarjar": Bp2BuildDefaultTrueRecursively,
- "external/javassist": Bp2BuildDefaultTrueRecursively,
"external/javaparser": Bp2BuildDefaultTrueRecursively,
"external/javapoet": Bp2BuildDefaultTrueRecursively,
+ "external/javassist": Bp2BuildDefaultTrueRecursively,
"external/jemalloc_new": Bp2BuildDefaultTrueRecursively,
"external/jsoncpp": Bp2BuildDefaultTrueRecursively,
"external/junit": Bp2BuildDefaultTrueRecursively,
+ "external/libaom": Bp2BuildDefaultTrueRecursively,
"external/libavc": Bp2BuildDefaultTrueRecursively,
"external/libcap": Bp2BuildDefaultTrueRecursively,
"external/libcxx": Bp2BuildDefaultTrueRecursively,
"external/libcxxabi": Bp2BuildDefaultTrueRecursively,
+ "external/libdivsufsort": Bp2BuildDefaultTrueRecursively,
+ "external/libdrm": Bp2BuildDefaultTrue,
"external/libevent": Bp2BuildDefaultTrueRecursively,
"external/libgav1": Bp2BuildDefaultTrueRecursively,
"external/libhevc": Bp2BuildDefaultTrueRecursively,
@@ -143,11 +160,13 @@
"external/libvpx": Bp2BuildDefaultTrueRecursively,
"external/libyuv": Bp2BuildDefaultTrueRecursively,
"external/lz4/lib": Bp2BuildDefaultTrue,
+ "external/lz4/programs": Bp2BuildDefaultTrue,
"external/lzma/C": Bp2BuildDefaultTrueRecursively,
"external/mdnsresponder": Bp2BuildDefaultTrueRecursively,
"external/minijail": Bp2BuildDefaultTrueRecursively,
- "external/openscreen": Bp2BuildDefaultTrueRecursively,
"external/objenesis": Bp2BuildDefaultTrueRecursively,
+ "external/openscreen": Bp2BuildDefaultTrueRecursively,
+ "external/ow2-asm": Bp2BuildDefaultTrueRecursively,
"external/pcre": Bp2BuildDefaultTrueRecursively,
"external/protobuf": Bp2BuildDefaultTrueRecursively,
"external/python/six": Bp2BuildDefaultTrueRecursively,
@@ -161,37 +180,42 @@
"external/zopfli": Bp2BuildDefaultTrueRecursively,
"external/zstd": Bp2BuildDefaultTrueRecursively,
- "frameworks/av": Bp2BuildDefaultTrue,
+ "frameworks/av": Bp2BuildDefaultTrue,
+ "frameworks/av/media/codec2/components/aom": Bp2BuildDefaultTrueRecursively,
"frameworks/av/media/codecs": Bp2BuildDefaultTrueRecursively,
"frameworks/av/media/liberror": Bp2BuildDefaultTrueRecursively,
- "frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively,
"frameworks/av/media/module/minijail": Bp2BuildDefaultTrueRecursively,
+ "frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively,
"frameworks/base/libs/androidfw": Bp2BuildDefaultTrue,
"frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue,
"frameworks/base/services/tests/servicestests/aidl": Bp2BuildDefaultTrue,
"frameworks/base/startop/apps/test": Bp2BuildDefaultTrue,
"frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively,
"frameworks/base/tools/aapt2": Bp2BuildDefaultTrue,
+ "frameworks/base/tools/streaming_proto": Bp2BuildDefaultTrueRecursively,
"frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively,
"frameworks/native/libs/arect": Bp2BuildDefaultTrueRecursively,
+ "frameworks/native/libs/gui": Bp2BuildDefaultTrue,
"frameworks/native/libs/math": Bp2BuildDefaultTrueRecursively,
"frameworks/native/libs/nativebase": Bp2BuildDefaultTrueRecursively,
+ "frameworks/native/libs/vr": Bp2BuildDefaultTrueRecursively,
"frameworks/native/opengl/tests/gl2_cameraeye": Bp2BuildDefaultTrue,
"frameworks/native/opengl/tests/gl2_java": Bp2BuildDefaultTrue,
"frameworks/native/opengl/tests/testLatency": Bp2BuildDefaultTrue,
"frameworks/native/opengl/tests/testPauseResume": Bp2BuildDefaultTrue,
"frameworks/native/opengl/tests/testViewport": Bp2BuildDefaultTrue,
- "frameworks/proto_logging/stats/stats_log_api_gen": Bp2BuildDefaultTrueRecursively,
+ "frameworks/native/services/batteryservice": Bp2BuildDefaultTrue,
+ "frameworks/proto_logging/stats": Bp2BuildDefaultTrueRecursively,
"hardware/interfaces": Bp2BuildDefaultTrue,
"hardware/interfaces/common/aidl": Bp2BuildDefaultTrue,
"hardware/interfaces/configstore/1.0": Bp2BuildDefaultTrue,
"hardware/interfaces/configstore/1.1": Bp2BuildDefaultTrue,
"hardware/interfaces/configstore/utils": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/allocator/aidl": Bp2BuildDefaultTrue,
"hardware/interfaces/graphics/allocator/2.0": Bp2BuildDefaultTrue,
"hardware/interfaces/graphics/allocator/3.0": Bp2BuildDefaultTrue,
"hardware/interfaces/graphics/allocator/4.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/graphics/allocator/aidl": Bp2BuildDefaultTrue,
"hardware/interfaces/graphics/bufferqueue/1.0": Bp2BuildDefaultTrue,
"hardware/interfaces/graphics/bufferqueue/2.0": Bp2BuildDefaultTrue,
"hardware/interfaces/graphics/common/1.0": Bp2BuildDefaultTrue,
@@ -202,6 +226,14 @@
"hardware/interfaces/graphics/mapper/2.1": Bp2BuildDefaultTrue,
"hardware/interfaces/graphics/mapper/3.0": Bp2BuildDefaultTrue,
"hardware/interfaces/graphics/mapper/4.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/health/1.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/health/1.0/default": Bp2BuildDefaultTrue,
+ "hardware/interfaces/health/2.0": Bp2BuildDefaultTrue,
+ "hardware/interfaces/health/2.0/default": Bp2BuildDefaultTrue,
+ "hardware/interfaces/health/2.0/utils": Bp2BuildDefaultTrueRecursively,
+ "hardware/interfaces/health/2.1": Bp2BuildDefaultTrue,
+ "hardware/interfaces/health/aidl": Bp2BuildDefaultTrue,
+ "hardware/interfaces/health/utils": Bp2BuildDefaultTrueRecursively,
"hardware/interfaces/media/1.0": Bp2BuildDefaultTrue,
"hardware/interfaces/media/bufferpool/2.0": Bp2BuildDefaultTrue,
"hardware/interfaces/media/c2/1.0": Bp2BuildDefaultTrue,
@@ -221,6 +253,7 @@
"packages/apps/Protips": Bp2BuildDefaultTrue,
"packages/apps/SafetyRegulatoryInfo": Bp2BuildDefaultTrue,
"packages/apps/WallpaperPicker": Bp2BuildDefaultTrue,
+ "packages/modules/NeuralNetworks/driver/cache": Bp2BuildDefaultTrueRecursively,
"packages/modules/StatsD/lib/libstatssocket": Bp2BuildDefaultTrueRecursively,
"packages/modules/adb": Bp2BuildDefaultTrue,
"packages/modules/adb/apex": Bp2BuildDefaultTrue,
@@ -231,7 +264,6 @@
"packages/modules/adb/proto": Bp2BuildDefaultTrueRecursively,
"packages/modules/adb/tls": Bp2BuildDefaultTrueRecursively,
"packages/providers/MediaProvider/tools/dialogs": Bp2BuildDefaultFalse, // TODO(b/242834374)
- "packages/modules/NeuralNetworks/driver/cache": Bp2BuildDefaultTrueRecursively,
"packages/screensavers/Basic": Bp2BuildDefaultTrue,
"packages/services/Car/tests/SampleRearViewCamera": Bp2BuildDefaultFalse, // TODO(b/242834321)
@@ -244,6 +276,9 @@
"prebuilts/tools": Bp2BuildDefaultTrue,
"prebuilts/tools/common/m2": Bp2BuildDefaultTrue,
+ "sdk/dumpeventlog": Bp2BuildDefaultTrue,
+ "sdk/eventanalyzer": Bp2BuildDefaultTrue,
+
"system/apex": Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures
"system/apex/apexer": Bp2BuildDefaultTrue,
"system/apex/libs": Bp2BuildDefaultTrueRecursively,
@@ -251,6 +286,8 @@
"system/apex/tools": Bp2BuildDefaultTrueRecursively,
"system/core/debuggerd": Bp2BuildDefaultTrueRecursively,
"system/core/diagnose_usb": Bp2BuildDefaultTrueRecursively,
+ "system/core/healthd": Bp2BuildDefaultTrue,
+ "system/core/healthd/testdata": Bp2BuildDefaultTrue,
"system/core/libasyncio": Bp2BuildDefaultTrue,
"system/core/libcrypto_utils": Bp2BuildDefaultTrueRecursively,
"system/core/libcutils": Bp2BuildDefaultTrueRecursively,
@@ -258,12 +295,15 @@
"system/core/libprocessgroup": Bp2BuildDefaultTrue,
"system/core/libprocessgroup/cgrouprc": Bp2BuildDefaultTrue,
"system/core/libprocessgroup/cgrouprc_format": Bp2BuildDefaultTrue,
+ "system/core/libsuspend": Bp2BuildDefaultTrue,
"system/core/libsystem": Bp2BuildDefaultTrueRecursively,
"system/core/libsysutils": Bp2BuildDefaultTrueRecursively,
"system/core/libutils": Bp2BuildDefaultTrueRecursively,
"system/core/libvndksupport": Bp2BuildDefaultTrueRecursively,
+ "system/core/mkbootfs": Bp2BuildDefaultTrueRecursively,
"system/core/property_service/libpropertyinfoparser": Bp2BuildDefaultTrueRecursively,
"system/core/property_service/libpropertyinfoserializer": Bp2BuildDefaultTrueRecursively,
+ "system/extras/toolchain-extras": Bp2BuildDefaultTrue,
"system/incremental_delivery/incfs": Bp2BuildDefaultTrue,
"system/libartpalette": Bp2BuildDefaultTrueRecursively,
"system/libbase": Bp2BuildDefaultTrueRecursively,
@@ -294,11 +334,10 @@
"system/timezone/apex": Bp2BuildDefaultTrueRecursively,
"system/timezone/output_data": Bp2BuildDefaultTrueRecursively,
"system/tools/aidl/build/tests_bp2build": Bp2BuildDefaultTrue,
+ "system/tools/mkbootimg": Bp2BuildDefaultTrueRecursively,
"system/tools/sysprop": Bp2BuildDefaultTrue,
"system/unwinding/libunwindstack": Bp2BuildDefaultTrueRecursively,
- "frameworks/proto_logging/stats": Bp2BuildDefaultTrueRecursively,
-
"tools/apksig": Bp2BuildDefaultTrue,
"tools/platform-compat/java/android/compat": Bp2BuildDefaultTrueRecursively,
"tools/tradefederation/prebuilts/filegroups": Bp2BuildDefaultTrueRecursively,
@@ -309,6 +348,7 @@
".":/*recursive = */ false,
"build/bazel":/* recursive = */ true,
+ "build/make/core":/* recursive = */ false,
"build/bazel_common_rules":/* recursive = */ true,
// build/make/tools/signapk BUILD file is generated, so build/make/tools is not recursive.
"build/make/tools":/* recursive = */ false,
@@ -334,9 +374,12 @@
"packages/apps/Music":/* recursive = */ true,
"packages/apps/QuickSearchBox":/* recursive = */ true,
+ "prebuilts/abi-dumps/platform":/* recursive = */ true,
+ "prebuilts/abi-dumps/ndk":/* recursive = */ true,
"prebuilts/bazel":/* recursive = */ true,
"prebuilts/bundletool":/* recursive = */ true,
"prebuilts/clang/host/linux-x86":/* recursive = */ false,
+ "prebuilts/clang-tools":/* recursive = */ true,
"prebuilts/gcc":/* recursive = */ true,
"prebuilts/build-tools":/* recursive = */ true,
"prebuilts/jdk/jdk11":/* recursive = */ false,
@@ -344,6 +387,8 @@
"prebuilts/sdk":/* recursive = */ false,
"prebuilts/sdk/tools":/* recursive = */ false,
"prebuilts/r8":/* recursive = */ false,
+
+ "tools/asuite/atest/":/* recursive = */ true,
}
Bp2buildModuleAlwaysConvertList = []string{
@@ -354,8 +399,10 @@
"code_coverage.policy.other",
"codec2_soft_exports",
"codecs_g711dec",
+ "com.android.media.swcodec",
"com.android.media.swcodec-androidManifest",
"com.android.media.swcodec-ld.config.txt",
+ "com.android.media.swcodec-mediaswcodec.32rc",
"com.android.media.swcodec-mediaswcodec.rc",
"com.android.media.swcodec.certificate",
"com.android.media.swcodec.key",
@@ -364,8 +411,10 @@
"com.android.neuralnetworks.certificate",
"com.android.neuralnetworks.key",
"flatbuffer_headers",
+ "framework-connectivity-protos",
"gemmlowp_headers",
"gl_headers",
+ "ipconnectivity-proto-src",
"libaidlcommonsupport",
"libandroid_runtime_lazy",
"libandroid_runtime_vm_headers",
@@ -377,14 +426,11 @@
"libbinder_headers_platform_shared",
"libbinderthreadstateutils",
"libbluetooth-types-header",
- "libbufferhub_headers",
"libcodec2",
"libcodec2_headers",
"libcodec2_internal",
"libdmabufheap",
- "libdvr_headers",
"libgsm",
- "libgui_bufferqueue_sources",
"libgrallocusage",
"libgralloctypes",
"libnativewindow",
@@ -397,7 +443,6 @@
"libneuralnetworks_headers",
"libneuralnetworks_packageinfo",
"libopus",
- "libpdx_headers",
"libprocpartition",
"libruy_static",
"libandroidio",
@@ -423,7 +468,6 @@
"libtextclassifier_hash_static",
"libtflite_kernel_utils",
"libtinyxml2",
- "libgui_aidl",
"libui",
"libui-types",
"libui_headers",
@@ -446,17 +490,19 @@
"philox_random",
"philox_random_headers",
"server_configurable_flags",
+ "service-permission-streaming-proto-sources",
"statslog_neuralnetworks.cpp",
"statslog_neuralnetworks.h",
"tensorflow_headers",
- "libgui_headers",
"libstagefright_bufferpool@2.0",
"libstagefright_bufferpool@2.0.1",
"libSurfaceFlingerProp",
+ // prebuilts
+ "prebuilt_stats-log-api-gen",
+
// fastboot
- "bootimg_headers",
"fastboot",
"libfastboot",
"liblp",
@@ -489,6 +535,7 @@
//system/extras/verity/fec
"fec",
+ "boot_signer",
//packages/apps/Car/libs/car-ui-lib/car-ui-androidx
// genrule dependencies for java_imports
@@ -537,9 +584,6 @@
//system/core/libkeyutils
"libkeyutils",
- //bootable/recovery/minadbd
- "libminadbd_headers",
-
//bootable/recovery/otautil
"libotautil",
@@ -567,7 +611,6 @@
"libcodec2_hidl_plugin_stub",
"libcodec2_hidl_plugin",
"libstagefright_bufferqueue_helper_novndk",
- "libgui_bufferqueue_static",
"libGLESv2",
"libEGL",
"libcodec2_vndk",
@@ -576,19 +619,55 @@
"libEGL_getProcAddress",
"libEGL_blobCache",
- "protoc-gen-cppstream",
+ "mediaswcodec",
+ "libmedia_headers",
+ "libmedia_codecserviceregistrant",
+ "libsfplugin_ccodec_utils",
+ "libcodec2_soft_aacenc",
+ "libcodec2_soft_amrnbdec",
+ "libcodec2_soft_amrnbenc",
+ "libcodec2_soft_amrwbdec",
+ "libcodec2_soft_amrwbenc",
+ "libcodec2_soft_hevcdec",
+ "libcodec2_soft_hevcenc",
+ "libcodec2_soft_g711alawdec",
+ "libcodec2_soft_g711mlawdec",
+ "libcodec2_soft_mpeg2dec",
+ "libcodec2_soft_h263dec",
+ "libcodec2_soft_h263enc",
+ "libcodec2_soft_mpeg4dec",
+ "libcodec2_soft_mpeg4enc",
+ "libcodec2_soft_mp3dec",
+ "libcodec2_soft_vorbisdec",
+ "libcodec2_soft_opusdec",
+ "libcodec2_soft_opusenc",
+ "libcodec2_soft_vp8dec",
+ "libcodec2_soft_vp9dec",
+ "libcodec2_soft_av1dec_gav1",
+ "libcodec2_soft_vp8enc",
+ "libcodec2_soft_vp9enc",
+ "libcodec2_soft_rawdec",
+ "libcodec2_soft_flacdec",
+ "libcodec2_soft_flacenc",
+ "libcodec2_soft_gsmdec",
+ "libcodec2_soft_avcdec",
+ "libcodec2_soft_avcenc",
+ "libcodec2_soft_aacdec",
+ "libcodec2_soft_common",
+
+ // kotlin srcs in java libs
+ "CtsPkgInstallerConstants",
+ "kotlinx_atomicfu",
}
Bp2buildModuleTypeAlwaysConvertList = []string{
"aidl_interface_headers",
- "api_domain",
"license",
"linker_config",
"java_import",
"java_import_host",
- "ndk_headers",
- "ndk_library",
"sysprop_library",
+ "bpf",
}
// Add the names of modules that bp2build should never convert, if it is
@@ -599,6 +678,23 @@
// the "prebuilt_" prefix to the name, so that it's differentiable from
// the source versions within Soong's module graph.
Bp2buildModuleDoNotConvertList = []string{
+ // TODO(b/250876486): Created cc_aidl_library doesn't have static libs from parent cc module
+ "libgui_window_info_static",
+ "libgui", // Depends on unconverted libgui_window_info_static
+ "libdisplay", // Depends on uncovnerted libgui
+ // Depends on unconverted libdisplay
+ "libdvr_static.google",
+ "libdvr.google",
+ "libvrsensor",
+ "dvr_api-test",
+ // Depends on unconverted libandroid, libgui
+ "dvr_buffer_queue-test",
+ "dvr_display-test",
+ // Depends on unconverted libchrome
+ "pdx_benchmarks",
+ "buffer_hub_queue-test",
+ "buffer_hub_queue_producer-test",
+
// cc bugs
"libactivitymanager_aidl", // TODO(b/207426160): Unsupported use of aidl sources (via Dactivity_manager_procstate_aidl) in a cc_library
@@ -633,7 +729,6 @@
// aar support
"prebuilt_car-ui-androidx-core-common", // TODO(b/224773339), genrule dependency creates an .aar, not a .jar
- "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
// ERROR: The dependencies for the following 1 jar(s) are not complete.
// 1.bazel-out/android_target-fastbuild/bin/prebuilts/tools/common/m2/_aar/robolectric-monitor-1.0.2-alpha1/classes_and_libs_merged.jar
@@ -713,6 +808,12 @@
// depends on //external/okio:okio-lib, which uses kotlin
"wire-runtime",
+ // depends on adbd_system_api_recovery, which is a unconverted `phony` module type
+ "minadbd",
+
+ // depends on android.hardware.health-V2.0-java
+ "android.hardware.health-translate-java",
+
// cc_test related.
// Failing host cc_tests
"memunreachable_unit_test",
@@ -875,6 +976,7 @@
"libdlext_test_norelro",
"libdlext_test_recursive",
"libdlext_test_zip",
+ "libdvrcommon_test",
"libfortify1-new-tests-clang",
"libfortify1-new-tests-clang",
"libfortify1-tests-clang",
@@ -1173,6 +1275,33 @@
"launcherprotosnano",
"datastallprotosnano",
"devicepolicyprotosnano",
+ "ota_metadata_proto_java",
+ "merge_ota",
+
+ // releasetools
+ "releasetools_fsverity_metadata_generator",
+ "verity_utils",
+ "check_ota_package_signature",
+ "check_target_files_vintf",
+ "releasetools_check_target_files_vintf",
+ "releasetools_verity_utils",
+ "build_image",
+ "ota_from_target_files",
+ "releasetools_ota_from_target_files",
+ "releasetools_build_image",
+ "add_img_to_target_files",
+ "releasetools_add_img_to_target_files",
+ "fsverity_metadata_generator",
+ "sign_target_files_apks",
+
+ // depends on the support of yacc file
+ "libapplypatch",
+ "libapplypatch_modes",
+ "applypatch",
+
+ // TODO(b/254476335): disable the following due to this bug
+ "libapexinfo",
+ "libapexinfo_tests",
}
Bp2buildCcLibraryStaticOnlyList = []string{}
@@ -1218,26 +1347,16 @@
"prebuilt_kotlin-stdlib-jdk8",
"prebuilt_kotlin-test",
// TODO(b/217750501) exclude_files property not supported
- "prebuilt_platform-robolectric-4.4-prebuilt",
"prebuilt_platform-robolectric-4.5.1-prebuilt",
"prebuilt_currysrc_org.eclipse",
-
- // TODO(b/247782695 and/or b/242847534) Fix mixed build between unconverted gensrcs and converted filegroup
- "libstats_atom_enum_protos",
- "data_stall_event_proto",
- "device_policy_proto",
- "dns_resolver_proto",
- "launcher_proto",
- "network_stack_proto",
- "srcs_bluetooth_protos",
- "srcs_bluetooth_leaudio_protos",
- "style_proto",
- "tethering_proto",
- "text_classifier_proto",
- "libstats_atom_message_protos",
}
- ProdMixedBuildsEnabledList = []string{
- "com.android.adbd",
- }
+ // Bazel prod-mode allowlist. Modules in this list are built by Bazel
+ // in either prod mode or staging mode.
+ ProdMixedBuildsEnabledList = []string{"com.android.tzdata"}
+
+ // Staging-mode allowlist. Modules in this list are only built
+ // by Bazel with --bazel-mode-staging. This list should contain modules
+ // which will soon be added to the prod allowlist.
+ StagingMixedBuildsEnabledList = []string{"com.android.tzdata"}
)
diff --git a/android/android_test.go b/android/android_test.go
index fb82e37..64ceedc 100644
--- a/android/android_test.go
+++ b/android/android_test.go
@@ -15,10 +15,32 @@
package android
import (
+ "io/ioutil"
"os"
"testing"
)
+var buildDir string
+
+func setUp() {
+ var err error
+ buildDir, err = ioutil.TempDir("", "android_test")
+ if err != nil {
+ panic(err)
+ }
+}
+
+func tearDown() {
+ os.RemoveAll(buildDir)
+}
+
func TestMain(m *testing.M) {
- os.Exit(m.Run())
+ run := func() int {
+ setUp()
+ defer tearDown()
+
+ return m.Run()
+ }
+
+ os.Exit(run())
}
diff --git a/android/api_domain.go b/android/api_domain.go
index 8ff4752..3265148 100644
--- a/android/api_domain.go
+++ b/android/api_domain.go
@@ -67,17 +67,14 @@
m := &apiDomain{}
m.AddProperties(&m.properties)
InitAndroidArchModule(m, DeviceSupported, MultilibBoth)
- InitBazelModule(m)
return m
}
+// Do not create any dependency edges in Soong for now to skip visibility checks for some systemapi libraries.
+// Currently, all api_domain modules reside in build/orchestrator/apis/Android.bp
+// However, cc libraries like libsigchain (com.android.art) restrict their visibility to art/*
+// When the api_domain module types are collocated with their contributions, this dependency edge can be restored
func (a *apiDomain) DepsMutator(ctx BottomUpMutatorContext) {
- for _, cc := range a.properties.Cc_api_contributions {
- // Use FarVariationDependencies since the variants of api_domain is a subset of the variants of the dependency cc module
- // Creating a dependency on the first variant is ok since this is a no-op in Soong
- // The primary function of this dependency is to create a connected graph in the corresponding bp2build workspace
- ctx.AddFarVariationDependencies([]blueprint.Variation{}, nil, cc)
- }
}
// API domain does not have any builld actions yet
@@ -108,7 +105,9 @@
Cc_api_contributions bazel.LabelListAttribute
}
-func (a *apiDomain) ConvertWithBp2build(ctx TopDownMutatorContext) {
+var _ ApiProvider = (*apiDomain)(nil)
+
+func (a *apiDomain) ConvertWithApiBp2build(ctx TopDownMutatorContext) {
props := bazel.BazelTargetModuleProperties{
Rule_class: "api_domain",
Bzl_load_location: "//build/bazel/rules/apis:api_domain.bzl",
diff --git a/android/arch.go b/android/arch.go
index 9bc9d89..6acf9cf 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -16,6 +16,7 @@
import (
"encoding"
+ "encoding/json"
"fmt"
"reflect"
"runtime"
@@ -147,10 +148,11 @@
var (
archTypeList []ArchType
- Arm = newArch("arm", "lib32")
- Arm64 = newArch("arm64", "lib64")
- X86 = newArch("x86", "lib32")
- X86_64 = newArch("x86_64", "lib64")
+ Arm = newArch("arm", "lib32")
+ Arm64 = newArch("arm64", "lib64")
+ Riscv64 = newArch("riscv64", "lib64")
+ X86 = newArch("x86", "lib32")
+ X86_64 = newArch("x86_64", "lib64")
Common = ArchType{
Name: COMMON_VARIANT,
@@ -318,7 +320,7 @@
Windows = newOsType("windows", Host, true, X86, X86_64)
// Android is the OS for target devices that run all of Android, including the Linux kernel
// and the Bionic libc runtime.
- Android = newOsType("android", Device, false, Arm, Arm64, X86, X86_64)
+ Android = newOsType("android", Device, false, Arm, Arm64, Riscv64, X86, X86_64)
// CommonOS is a pseudo OSType for a common OS variant, which is OsType agnostic and which
// has dependencies on all the OS variants.
@@ -1680,20 +1682,18 @@
// archConfig describes a built-in configuration.
type archConfig struct {
- arch string
- archVariant string
- cpuVariant string
- abi []string
+ Arch string `json:"arch"`
+ ArchVariant string `json:"arch_variant"`
+ CpuVariant string `json:"cpu_variant"`
+ Abi []string `json:"abis"`
}
-// getNdkAbisConfig returns the list of archConfigs that are used for bulding
-// the API stubs and static libraries that are included in the NDK. These are
-// built *without Neon*, because non-Neon is still supported and building these
-// with Neon will break those users.
+// getNdkAbisConfig returns the list of archConfigs that are used for building
+// the API stubs and static libraries that are included in the NDK.
func getNdkAbisConfig() []archConfig {
return []archConfig{
{"arm64", "armv8-a-branchprot", "", []string{"arm64-v8a"}},
- {"arm", "armv7-a", "", []string{"armeabi-v7a"}},
+ {"arm", "armv7-a-neon", "", []string{"armeabi-v7a"}},
{"x86_64", "", "", []string{"x86_64"}},
{"x86", "", "", []string{"x86"}},
}
@@ -1714,8 +1714,8 @@
var ret []Target
for _, config := range archConfigs {
- arch, err := decodeArch(Android, config.arch, &config.archVariant,
- &config.cpuVariant, config.abi)
+ arch, err := decodeArch(Android, config.Arch, &config.ArchVariant,
+ &config.CpuVariant, config.Abi)
if err != nil {
return nil, err
}
@@ -2285,6 +2285,14 @@
return starlark_fmt.PrintDict(valDict, 0)
}
+func printArchConfigList(arches []archConfig) string {
+ jsonOut, err := json.MarshalIndent(arches, "", starlark_fmt.Indention(1))
+ if err != nil {
+ panic(fmt.Errorf("Error converting arch configs %#v to json: %q", arches, err))
+ }
+ return fmt.Sprintf("json.decode('''%s''')", string(jsonOut))
+}
+
func StarlarkArchConfigurations() string {
return fmt.Sprintf(`
_arch_to_variants = %s
@@ -2295,13 +2303,21 @@
_android_arch_feature_for_arch_variant = %s
+_aml_arches = %s
+
+_ndk_arches = %s
+
arch_to_variants = _arch_to_variants
arch_to_cpu_variants = _arch_to_cpu_variants
arch_to_features = _arch_to_features
android_arch_feature_for_arch_variants = _android_arch_feature_for_arch_variant
+aml_arches = _aml_arches
+ndk_arches = _ndk_arches
`, printArchTypeStarlarkDict(archVariants),
printArchTypeStarlarkDict(cpuVariants),
printArchTypeStarlarkDict(archFeatures),
printArchTypeNestedStarlarkDict(androidArchFeatureMap),
+ printArchConfigList(getAmlAbisConfig()),
+ printArchConfigList(getNdkAbisConfig()),
)
}
diff --git a/android/arch_test.go b/android/arch_test.go
index 6814f8a..46c018a 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -596,6 +596,7 @@
arm64: {
a: ["arm64"],
},
+ riscv64: { a: ["riscv64"] },
x86: { a: ["x86"] },
x86_64: { a: ["x86_64"] },
},
diff --git a/android/bazel.go b/android/bazel.go
index dd1de7b..3731dfe 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -134,6 +134,11 @@
SetBaseModuleType(baseModuleType string)
}
+// ApiProvider is implemented by modules that contribute to an API surface
+type ApiProvider interface {
+ ConvertWithApiBp2build(ctx TopDownMutatorContext)
+}
+
// MixedBuildBuildable is an interface that module types should implement in order
// to be "handled by Bazel" in a mixed build.
type MixedBuildBuildable interface {
@@ -336,16 +341,19 @@
// Exact dir match
return true
}
+ var i int
// Check if subtree match
- for prefix, recursive := range a.keepExistingBuildFile {
- if recursive {
- if strings.HasPrefix(dir, prefix+"/") {
- return true
- }
+ for {
+ j := strings.Index(dir[i:], "/")
+ if j == -1 {
+ return false //default
+ }
+ prefix := dir[0 : i+j]
+ i = i + j + 1 // skip the "/"
+ if recursive, ok := a.keepExistingBuildFile[prefix]; ok && recursive {
+ return true
}
}
- // Default
- return false
}
var bp2BuildAllowListKey = NewOnceKey("Bp2BuildAllowlist")
@@ -375,6 +383,9 @@
// mixedBuildPossible returns true if a module is ready to be replaced by a
// converted or handcrafted Bazel target.
func mixedBuildPossible(ctx BaseModuleContext) bool {
+ if !ctx.Config().IsMixedBuildsEnabled() {
+ return false
+ }
if ctx.Os() == Windows {
// Windows toolchains are not currently supported.
return false
@@ -415,6 +426,13 @@
return false
}
+ // In api_bp2build mode, all soong modules that can provide API contributions should be converted
+ // This is irrespective of its presence/absence in bp2build allowlists
+ if ctx.Config().BuildMode == ApiBp2build {
+ _, providesApis := module.(ApiProvider)
+ return providesApis
+ }
+
propValue := b.bazelProperties.Bazel_module.Bp2build_available
packagePath := ctx.OtherModuleDir(module)
@@ -477,21 +495,27 @@
// Check if the package path has an exact match in the config.
if config[packagePath] == allowlists.Bp2BuildDefaultTrue || config[packagePath] == allowlists.Bp2BuildDefaultTrueRecursively {
return true, packagePath
- } else if config[packagePath] == allowlists.Bp2BuildDefaultFalse {
+ } else if config[packagePath] == allowlists.Bp2BuildDefaultFalse || config[packagePath] == allowlists.Bp2BuildDefaultFalseRecursively {
return false, packagePath
}
// If not, check for the config recursively.
- packagePrefix := ""
- // e.g. for x/y/z, iterate over x, x/y, then x/y/z, taking the final value from the allowlist.
- for _, part := range strings.Split(packagePath, "/") {
- packagePrefix += part
- if config[packagePrefix] == allowlists.Bp2BuildDefaultTrueRecursively {
+ packagePrefix := packagePath
+
+ // e.g. for x/y/z, iterate over x/y, then x, taking the most-specific value from the allowlist.
+ for strings.Contains(packagePrefix, "/") {
+ dirIndex := strings.LastIndex(packagePrefix, "/")
+ packagePrefix = packagePrefix[:dirIndex]
+ switch value := config[packagePrefix]; value {
+ case allowlists.Bp2BuildDefaultTrueRecursively:
// package contains this prefix and this prefix should convert all modules
return true, packagePrefix
+ case allowlists.Bp2BuildDefaultFalseRecursively:
+ //package contains this prefix and this prefix should NOT convert any modules
+ return false, packagePrefix
}
// Continue to the next part of the package dir.
- packagePrefix += "/"
+
}
return false, packagePath
@@ -510,6 +534,17 @@
bModule.ConvertWithBp2build(ctx)
}
+func registerApiBp2buildConversionMutator(ctx RegisterMutatorsContext) {
+ ctx.TopDown("apiBp2build_conversion", convertWithApiBp2build).Parallel()
+}
+
+// Generate API contribution targets if the Soong module provides APIs
+func convertWithApiBp2build(ctx TopDownMutatorContext) {
+ if m, ok := ctx.Module().(ApiProvider); ok {
+ m.ConvertWithApiBp2build(ctx)
+ }
+}
+
// GetMainClassInManifest scans the manifest file specified in filepath and returns
// the value of attribute Main-Class in the manifest file if it exists, or returns error.
// WARNING: this is for bp2build converters of java_* modules only.
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index 3e490dd..acb81a4 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -81,7 +81,7 @@
// all request-relevant information about a target and returns a string containing
// this information.
// The function should have the following properties:
- // - `target` is the only parameter to this function (a configured target).
+ // - The arguments are `target` (a configured target) and `id_string` (the label + configuration).
// - The return value must be a string.
// - The function body should not be indented outside of its own scope.
StarlarkFunctionBody() string
@@ -104,9 +104,16 @@
configKey configKey
}
+func makeCqueryKey(label string, cqueryRequest cqueryRequest, cfgKey configKey) cqueryKey {
+ if strings.HasPrefix(label, "//") {
+ // Normalize Bazel labels to specify main repository explicitly.
+ label = "@" + label
+ }
+ return cqueryKey{label, cqueryRequest, cfgKey}
+}
+
func (c cqueryKey) String() string {
return fmt.Sprintf("cquery(%s,%s,%s)", c.label, c.requestType.Name(), c.configKey)
-
}
// BazelContext is a context object useful for interacting with Bazel during
@@ -135,13 +142,17 @@
GetPythonBinary(label string, cfgKey configKey) (string, error)
// Returns the results of the GetApexInfo query (including output files)
- GetApexInfo(label string, cfgkey configKey) (cquery.ApexCqueryInfo, error)
+ GetApexInfo(label string, cfgkey configKey) (cquery.ApexInfo, error)
+
+ // Returns the results of the GetCcUnstrippedInfo query
+ GetCcUnstrippedInfo(label string, cfgkey configKey) (cquery.CcUnstrippedInfo, error)
// ** end Cquery Results Retrieval Functions
// Issues commands to Bazel to receive results for all cquery requests
- // queued in the BazelContext.
- InvokeBazel(config Config) error
+ // queued in the BazelContext. The ctx argument is optional and is only
+ // used for performance data collection
+ InvokeBazel(config Config, ctx *Context) error
// Returns true if Bazel handling is enabled for the module with the given name.
// Note that this only implies "bazel mixed build" allowlisting. The caller
@@ -160,16 +171,18 @@
}
type bazelRunner interface {
- issueBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand, extraFlags ...string) (string, string, error)
+ createBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand, extraFlags ...string) *exec.Cmd
+ issueBazelCommand(bazelCmd *exec.Cmd) (output string, errorMessage string, error error)
}
type bazelPaths struct {
- homeDir string
- bazelPath string
- outputBase string
- workspaceDir string
- soongOutDir string
- metricsDir string
+ homeDir string
+ bazelPath string
+ outputBase string
+ workspaceDir string
+ soongOutDir string
+ metricsDir string
+ bazelDepsFile string
}
// A context object which tracks queued requests that need to be made to Bazel,
@@ -214,7 +227,8 @@
LabelToOutputFiles map[string][]string
LabelToCcInfo map[string]cquery.CcInfo
LabelToPythonBinary map[string]string
- LabelToApexInfo map[string]cquery.ApexCqueryInfo
+ LabelToApexInfo map[string]cquery.ApexInfo
+ LabelToCcBinary map[string]cquery.CcUnstrippedInfo
}
func (m MockBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
@@ -236,11 +250,17 @@
return result, nil
}
-func (n MockBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexCqueryInfo, error) {
- panic("unimplemented")
+func (m MockBazelContext) GetApexInfo(label string, _ configKey) (cquery.ApexInfo, error) {
+ result, _ := m.LabelToApexInfo[label]
+ return result, nil
}
-func (m MockBazelContext) InvokeBazel(_ Config) error {
+func (m MockBazelContext) GetCcUnstrippedInfo(label string, _ configKey) (cquery.CcUnstrippedInfo, error) {
+ result, _ := m.LabelToCcBinary[label]
+ return result, nil
+}
+
+func (m MockBazelContext) InvokeBazel(_ Config, ctx *Context) error {
panic("unimplemented")
}
@@ -261,23 +281,24 @@
var _ BazelContext = MockBazelContext{}
func (bazelCtx *bazelContext) QueueBazelRequest(label string, requestType cqueryRequest, cfgKey configKey) {
- key := cqueryKey{label, requestType, cfgKey}
+ key := makeCqueryKey(label, requestType, cfgKey)
bazelCtx.requestMutex.Lock()
defer bazelCtx.requestMutex.Unlock()
bazelCtx.requests[key] = true
}
func (bazelCtx *bazelContext) GetOutputFiles(label string, cfgKey configKey) ([]string, error) {
- key := cqueryKey{label, cquery.GetOutputFiles, cfgKey}
+ key := makeCqueryKey(label, cquery.GetOutputFiles, cfgKey)
if rawString, ok := bazelCtx.results[key]; ok {
bazelOutput := strings.TrimSpace(rawString)
+
return cquery.GetOutputFiles.ParseResult(bazelOutput), nil
}
return nil, fmt.Errorf("no bazel response found for %v", key)
}
func (bazelCtx *bazelContext) GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, error) {
- key := cqueryKey{label, cquery.GetCcInfo, cfgKey}
+ key := makeCqueryKey(label, cquery.GetCcInfo, cfgKey)
if rawString, ok := bazelCtx.results[key]; ok {
bazelOutput := strings.TrimSpace(rawString)
return cquery.GetCcInfo.ParseResult(bazelOutput)
@@ -286,7 +307,7 @@
}
func (bazelCtx *bazelContext) GetPythonBinary(label string, cfgKey configKey) (string, error) {
- key := cqueryKey{label, cquery.GetPythonBinary, cfgKey}
+ key := makeCqueryKey(label, cquery.GetPythonBinary, cfgKey)
if rawString, ok := bazelCtx.results[key]; ok {
bazelOutput := strings.TrimSpace(rawString)
return cquery.GetPythonBinary.ParseResult(bazelOutput), nil
@@ -294,12 +315,20 @@
return "", fmt.Errorf("no bazel response found for %v", key)
}
-func (bazelCtx *bazelContext) GetApexInfo(label string, cfgKey configKey) (cquery.ApexCqueryInfo, error) {
- key := cqueryKey{label, cquery.GetApexInfo, cfgKey}
+func (bazelCtx *bazelContext) GetApexInfo(label string, cfgKey configKey) (cquery.ApexInfo, error) {
+ key := makeCqueryKey(label, cquery.GetApexInfo, cfgKey)
if rawString, ok := bazelCtx.results[key]; ok {
- return cquery.GetApexInfo.ParseResult(strings.TrimSpace(rawString)), nil
+ return cquery.GetApexInfo.ParseResult(strings.TrimSpace(rawString))
}
- return cquery.ApexCqueryInfo{}, fmt.Errorf("no bazel response found for %v", key)
+ return cquery.ApexInfo{}, fmt.Errorf("no bazel response found for %v", key)
+}
+
+func (bazelCtx *bazelContext) GetCcUnstrippedInfo(label string, cfgKey configKey) (cquery.CcUnstrippedInfo, error) {
+ key := makeCqueryKey(label, cquery.GetCcUnstrippedInfo, cfgKey)
+ if rawString, ok := bazelCtx.results[key]; ok {
+ return cquery.GetCcUnstrippedInfo.ParseResult(strings.TrimSpace(rawString))
+ }
+ return cquery.CcUnstrippedInfo{}, fmt.Errorf("no bazel response for %s", key)
}
func (n noopBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
@@ -318,11 +347,16 @@
panic("unimplemented")
}
-func (n noopBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexCqueryInfo, error) {
+func (n noopBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexInfo, error) {
panic("unimplemented")
}
-func (n noopBazelContext) InvokeBazel(_ Config) error {
+func (n noopBazelContext) GetCcUnstrippedInfo(_ string, _ configKey) (cquery.CcUnstrippedInfo, error) {
+ //TODO implement me
+ panic("implement me")
+}
+
+func (n noopBazelContext) InvokeBazel(_ Config, ctx *Context) error {
panic("unimplemented")
}
@@ -354,6 +388,15 @@
for _, enabledProdModule := range allowlists.ProdMixedBuildsEnabledList {
enabledModules[enabledProdModule] = true
}
+ case BazelStagingMode:
+ modulesDefaultToBazel = false
+ // Staging mode includes all prod modules plus all staging modules.
+ for _, enabledProdModule := range allowlists.ProdMixedBuildsEnabledList {
+ enabledModules[enabledProdModule] = true
+ }
+ for _, enabledStagingMode := range allowlists.StagingMixedBuildsEnabledList {
+ enabledModules[enabledStagingMode] = true
+ }
case BazelDevMode:
modulesDefaultToBazel = true
@@ -415,6 +458,11 @@
} else {
missingEnvVars = append(missingEnvVars, "BAZEL_METRICS_DIR")
}
+ if len(c.Getenv("BAZEL_DEPS_FILE")) > 1 {
+ p.bazelDepsFile = c.Getenv("BAZEL_DEPS_FILE")
+ } else {
+ missingEnvVars = append(missingEnvVars, "BAZEL_DEPS_FILE")
+ }
if len(missingEnvVars) > 0 {
return nil, errors.New(fmt.Sprintf("missing required env vars to use bazel: %s", missingEnvVars))
} else {
@@ -452,16 +500,30 @@
type mockBazelRunner struct {
bazelCommandResults map[bazelCommand]string
- commands []bazelCommand
- extraFlags []string
+ // use *exec.Cmd as a key to get the bazelCommand, the map will be used in issueBazelCommand()
+ // Register createBazelCommand() invocations. Later, an
+ // issueBazelCommand() invocation can be mapped to the *exec.Cmd instance
+ // and then to the expected result via bazelCommandResults
+ tokens map[*exec.Cmd]bazelCommand
+ commands []bazelCommand
+ extraFlags []string
}
-func (r *mockBazelRunner) issueBazelCommand(_ *bazelPaths, _ bazel.RunName,
- command bazelCommand, extraFlags ...string) (string, string, error) {
+func (r *mockBazelRunner) createBazelCommand(paths *bazelPaths, runName bazel.RunName,
+ command bazelCommand, extraFlags ...string) *exec.Cmd {
r.commands = append(r.commands, command)
r.extraFlags = append(r.extraFlags, strings.Join(extraFlags, " "))
- if ret, ok := r.bazelCommandResults[command]; ok {
- return ret, "", nil
+ cmd := &exec.Cmd{}
+ if r.tokens == nil {
+ r.tokens = make(map[*exec.Cmd]bazelCommand)
+ }
+ r.tokens[cmd] = command
+ return cmd
+}
+
+func (r *mockBazelRunner) issueBazelCommand(bazelCmd *exec.Cmd) (string, string, error) {
+ if command, ok := r.tokens[bazelCmd]; ok {
+ return r.bazelCommandResults[command], "", nil
}
return "", "", nil
}
@@ -472,8 +534,20 @@
// Returns (stdout, stderr, error). The first and second return values are strings
// containing the stdout and stderr of the run command, and an error is returned if
// the invocation returned an error code.
-func (r *builtinBazelRunner) issueBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand,
- extraFlags ...string) (string, string, error) {
+
+func (r *builtinBazelRunner) issueBazelCommand(bazelCmd *exec.Cmd) (string, string, error) {
+ stderr := &bytes.Buffer{}
+ bazelCmd.Stderr = stderr
+ if output, err := bazelCmd.Output(); err != nil {
+ return "", string(stderr.Bytes()),
+ fmt.Errorf("bazel command failed. command: [%s], env: [%s], error [%s]", bazelCmd, bazelCmd.Env, stderr)
+ } else {
+ return string(output), string(stderr.Bytes()), nil
+ }
+}
+
+func (r *builtinBazelRunner) createBazelCommand(paths *bazelPaths, runName bazel.RunName, command bazelCommand,
+ extraFlags ...string) *exec.Cmd {
cmdFlags := []string{
"--output_base=" + absolutePath(paths.outputBase),
command.command,
@@ -488,9 +562,7 @@
//
// 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"),
-
// 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"),
@@ -500,7 +572,9 @@
// Suppress noise
"--ui_event_filters=-INFO",
- "--noshow_progress"}
+ "--noshow_progress",
+ "--norun_validations",
+ }
cmdFlags = append(cmdFlags, extraFlags...)
bazelCmd := exec.Command(paths.bazelPath, cmdFlags...)
@@ -509,7 +583,7 @@
"HOME=" + paths.homeDir,
pwdPrefix(),
"BUILD_DIR=" + absolutePath(paths.soongOutDir),
- // Make OUT_DIR absolute here so tools/bazel.sh uses the correct
+ // Make OUT_DIR absolute here so build/bazel/bin/bazel uses the correct
// OUT_DIR at <root>/out, instead of <root>/out/soong/workspace/out.
"OUT_DIR=" + absolutePath(paths.outDir()),
// Disables local host detection of gcc; toolchain information is defined
@@ -517,15 +591,14 @@
"BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1",
}
bazelCmd.Env = append(os.Environ(), extraEnv...)
- stderr := &bytes.Buffer{}
- bazelCmd.Stderr = stderr
- if output, err := bazelCmd.Output(); err != nil {
- return "", string(stderr.Bytes()),
- fmt.Errorf("bazel command failed. command: [%s], env: [%s], error [%s]", bazelCmd, bazelCmd.Env, stderr)
- } else {
- return string(output), string(stderr.Bytes()), nil
- }
+ return bazelCmd
+}
+
+func printableCqueryCommand(bazelCmd *exec.Cmd) string {
+ outputString := strings.Join(bazelCmd.Env, " ") + " \"" + strings.Join(bazelCmd.Args, "\" \"") + "\""
+ return outputString
+
}
func (context *bazelContext) mainBzlFileContents() []byte {
@@ -670,12 +743,12 @@
}
`
functionDefFormatString := `
-def %s(target):
+def %s(target, id_string):
%s
`
mainSwitchSectionFormatString := `
if id_string in %s:
- return id_string + ">>" + %s(target)
+ return id_string + ">>" + %s(target, id_string)
`
for requestType := range requestTypeToCqueryIdEntries {
@@ -755,6 +828,10 @@
def format(target):
id_string = str(target.label) + "|" + get_arch(target)
+ # TODO(b/248106697): Remove once Bazel is updated to always normalize labels.
+ if id_string.startswith("//"):
+ id_string = "@" + id_string
+
# Main switch section
%s
# This target was not requested via cquery, and thus must be a dependency
@@ -789,52 +866,80 @@
return filepath.Dir(p.soongOutDir)
}
+const buildrootLabel = "@soong_injection//mixed_builds:buildroot"
+
+var (
+ cqueryCmd = bazelCommand{"cquery", fmt.Sprintf("deps(%s, 2)", buildrootLabel)}
+ aqueryCmd = bazelCommand{"aquery", fmt.Sprintf("deps(%s)", buildrootLabel)}
+ buildCmd = bazelCommand{"build", "@soong_injection//mixed_builds:phonyroot"}
+)
+
// Issues commands to Bazel to receive results for all cquery requests
// queued in the BazelContext.
-func (context *bazelContext) InvokeBazel(config Config) error {
+func (context *bazelContext) InvokeBazel(config Config, ctx *Context) error {
+ if ctx != nil {
+ ctx.EventHandler.Begin("bazel")
+ defer ctx.EventHandler.End("bazel")
+ }
+
+ if metricsDir := context.paths.BazelMetricsDir(); metricsDir != "" {
+ if err := os.MkdirAll(metricsDir, 0777); err != nil {
+ return err
+ }
+ }
context.results = make(map[cqueryKey]string)
+ if err := context.runCquery(ctx); err != nil {
+ return err
+ }
+ if err := context.runAquery(config, ctx); err != nil {
+ return err
+ }
+ if err := context.generateBazelSymlinks(ctx); err != nil {
+ return err
+ }
- var err error
+ // Clear requests.
+ context.requests = map[cqueryKey]bool{}
+ return nil
+}
+func (context *bazelContext) runCquery(ctx *Context) error {
+ if ctx != nil {
+ ctx.EventHandler.Begin("cquery")
+ defer ctx.EventHandler.End("cquery")
+ }
soongInjectionPath := absolutePath(context.paths.injectedFilesDir())
mixedBuildsPath := filepath.Join(soongInjectionPath, "mixed_builds")
if _, err := os.Stat(mixedBuildsPath); os.IsNotExist(err) {
err = os.MkdirAll(mixedBuildsPath, 0777)
- }
- if err != nil {
- return err
- }
- if metricsDir := context.paths.BazelMetricsDir(); metricsDir != "" {
- err = os.MkdirAll(metricsDir, 0777)
if err != nil {
return err
}
}
- if err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil {
+ if err := ioutil.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil {
return err
}
- if err = ioutil.WriteFile(filepath.Join(mixedBuildsPath, "main.bzl"), context.mainBzlFileContents(), 0666); err != nil {
+ if err := ioutil.WriteFile(filepath.Join(mixedBuildsPath, "main.bzl"), context.mainBzlFileContents(), 0666); err != nil {
return err
}
- if err = ioutil.WriteFile(filepath.Join(mixedBuildsPath, "BUILD.bazel"), context.mainBuildFileContents(), 0666); 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")
- if err = ioutil.WriteFile(absolutePath(cqueryFileRelpath), context.cqueryStarlarkFileContents(), 0666); err != nil {
+ if err := ioutil.WriteFile(absolutePath(cqueryFileRelpath), context.cqueryStarlarkFileContents(), 0666); err != nil {
return err
}
- 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,
+ cqueryCommandWithFlag := context.createBazelCommand(context.paths, bazel.CqueryBuildRootRunName, cqueryCmd,
"--output=starlark", "--starlark:file="+absolutePath(cqueryFileRelpath))
- if err != nil {
+ cqueryOutput, cqueryErrorMessage, cqueryErr := context.issueBazelCommand(cqueryCommandWithFlag)
+ if cqueryErr != nil {
+ return cqueryErr
+ }
+ cqueryCommandPrint := fmt.Sprintf("cquery command line:\n %s \n\n\n", printableCqueryCommand(cqueryCommandWithFlag))
+ if err := ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"), []byte(cqueryCommandPrint+cqueryOutput), 0666); err != nil {
return err
}
- if err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"), []byte(cqueryOutput), 0666); err != nil {
- return err
- }
-
cqueryResults := map[string]string{}
for _, outputLine := range strings.Split(cqueryOutput, "\n") {
if strings.Contains(outputLine, ">>") {
@@ -847,19 +952,32 @@
context.results[val] = cqueryResult
} else {
return fmt.Errorf("missing result for bazel target %s. query output: [%s], cquery err: [%s]",
- getCqueryId(val), cqueryOutput, cqueryErr)
+ getCqueryId(val), cqueryOutput, cqueryErrorMessage)
}
}
+ return nil
+}
+func (context *bazelContext) runAquery(config Config, ctx *Context) error {
+ if ctx != nil {
+ ctx.EventHandler.Begin("aquery")
+ defer ctx.EventHandler.End("aquery")
+ }
// Issue an aquery command to retrieve action information about the bazel build tree.
//
// 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"}
+ extraFlags := []string{"--output=proto", "--include_file_write_contents"}
if Bool(config.productVariables.ClangCoverage) {
extraFlags = append(extraFlags, "--collect_code_coverage")
paths := make([]string, 0, 2)
if p := config.productVariables.NativeCoveragePaths; len(p) > 0 {
+ for i, _ := range p {
+ // TODO(b/259404593) convert path wildcard to regex values
+ if p[i] == "*" {
+ p[i] = ".*"
+ }
+ }
paths = append(paths, JoinWithPrefixAndSeparator(p, "+", ","))
}
if p := config.productVariables.NativeCoverageExcludePaths; len(p) > 0 {
@@ -869,26 +987,25 @@
extraFlags = append(extraFlags, "--instrumentation_filter="+strings.Join(paths, ","))
}
}
- 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))
- }
+ aqueryOutput, _, err := context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.AqueryBuildRootRunName, aqueryCmd,
+ extraFlags...))
if err != nil {
return err
}
+ context.buildStatements, context.depsets, err = bazel.AqueryBuildStatements([]byte(aqueryOutput))
+ return err
+}
+func (context *bazelContext) generateBazelSymlinks(ctx *Context) error {
+ if ctx != nil {
+ ctx.EventHandler.Begin("symlinks")
+ defer ctx.EventHandler.End("symlinks")
+ }
// 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.
- buildCmd := bazelCommand{"build", "@soong_injection//mixed_builds:phonyroot"}
- if _, _, err = context.issueBazelCommand(context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd); err != nil {
- return err
- }
-
- // Clear requests.
- context.requests = map[cqueryKey]bool{}
- return nil
+ _, _, err := context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd))
+ return err
}
func (context *bazelContext) BuildStatementsToRegister() []bazel.BuildStatement {
@@ -933,18 +1050,26 @@
for _, depset := range ctx.Config().BazelContext.AqueryDepsets() {
var outputs []Path
+ var orderOnlies []Path
for _, depsetDepHash := range depset.TransitiveDepSetHashes {
otherDepsetName := bazelDepsetName(depsetDepHash)
outputs = append(outputs, PathForPhony(ctx, otherDepsetName))
}
for _, artifactPath := range depset.DirectArtifacts {
- outputs = append(outputs, PathForBazelOut(ctx, artifactPath))
+ pathInBazelOut := PathForBazelOut(ctx, artifactPath)
+ if artifactPath == "bazel-out/volatile-status.txt" {
+ // See https://bazel.build/docs/user-manual#workspace-status
+ orderOnlies = append(orderOnlies, pathInBazelOut)
+ } else {
+ outputs = append(outputs, pathInBazelOut)
+ }
}
thisDepsetName := bazelDepsetName(depset.ContentHash)
ctx.Build(pctx, BuildParams{
Rule: blueprint.Phony,
Outputs: []WritablePath{PathForPhony(ctx, thisDepsetName)},
Implicits: outputs,
+ OrderOnly: orderOnlies,
})
}
@@ -1011,7 +1136,7 @@
// Remove old outputs, as some actions might not rerun if the outputs are detected.
if len(buildStatement.OutputPaths) > 0 {
- cmd.Text("rm -f")
+ cmd.Text("rm -rf") // -r because outputs can be Bazel dir/tree artifacts.
for _, outputPath := range buildStatement.OutputPaths {
cmd.Text(fmt.Sprintf("'%s'", outputPath))
}
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index ec2541b..bc16cb5 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -1,6 +1,7 @@
package android
import (
+ "encoding/json"
"os"
"path/filepath"
"reflect"
@@ -8,18 +9,21 @@
"testing"
"android/soong/bazel/cquery"
+ analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
+
+ "google.golang.org/protobuf/proto"
)
var testConfig = TestConfig("out", nil, "", nil)
func TestRequestResultsAfterInvokeBazel(t *testing.T) {
- label := "//foo:bar"
+ label := "@//foo:bar"
cfg := configKey{"arm64_armv8-a", Android}
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
- bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: `//foo:bar|arm64_armv8-a|android>>out/foo/bar.txt`,
+ bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: `@//foo:bar|arm64_armv8-a|android>>out/foo/bar.txt`,
})
bazelContext.QueueBazelRequest(label, cquery.GetOutputFiles, cfg)
- err := bazelContext.InvokeBazel(testConfig)
+ err := bazelContext.InvokeBazel(testConfig, nil)
if err != nil {
t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
}
@@ -33,7 +37,7 @@
func TestInvokeBazelWritesBazelFiles(t *testing.T) {
bazelContext, baseDir := testBazelContext(t, map[bazelCommand]string{})
- err := bazelContext.InvokeBazel(testConfig)
+ err := bazelContext.InvokeBazel(testConfig, nil)
if err != nil {
t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
}
@@ -65,52 +69,56 @@
var testCases = []testCase{
{`
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [1],
- "primaryOutputId": 1
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 2] }],
- "pathFragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+ "target_Id": 1,
+ "action_Key": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [1],
+ "output_Ids": [1],
+ "primary_output_id": 1
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1, 2] }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" }]
}`,
- "cd 'test/exec_root' && rm -f 'one' && touch foo",
+ "cd 'test/exec_root' && rm -rf 'one' && touch foo",
}, {`
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 10 },
- { "id": 2, "pathFragmentId": 20 }],
- "actions": [{
- "targetId": 100,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["bogus", "command"],
- "outputIds": [1, 2],
- "primaryOutputId": 1
- }],
- "pathFragments": [
- { "id": 10, "label": "one", "parentId": 30 },
- { "id": 20, "label": "one.d", "parentId": 30 },
- { "id": 30, "label": "parent" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 10 },
+ { "id": 2, "path_fragment_id": 20 }],
+ "actions": [{
+ "target_Id": 100,
+ "action_Key": "x",
+ "mnemonic": "x",
+ "arguments": ["bogus", "command"],
+ "output_Ids": [1, 2],
+ "primary_output_id": 1
+ }],
+ "path_fragments": [
+ { "id": 10, "label": "one", "parent_id": 30 },
+ { "id": 20, "label": "one.d", "parent_id": 30 },
+ { "id": 30, "label": "parent" }]
}`,
- `cd 'test/exec_root' && rm -f 'parent/one' && bogus command && sed -i'' -E 's@(^|\s|")bazel-out/@\1test/bazel_out/@g' 'parent/one.d'`,
+ `cd 'test/exec_root' && rm -rf 'parent/one' && bogus command && sed -i'' -E 's@(^|\s|")bazel-out/@\1test/bazel_out/@g' 'parent/one.d'`,
},
}
for i, testCase := range testCases {
+ data, err := JsonToActionGraphContainer(testCase.input)
+ if err != nil {
+ t.Error(err)
+ }
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
- bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: testCase.input})
+ bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}: string(data)})
- err := bazelContext.InvokeBazel(testConfig)
+ err = bazelContext.InvokeBazel(testConfig, nil)
if err != nil {
t.Fatalf("testCase #%d: did not expect error invoking Bazel, but got %s", i+1, err)
}
@@ -147,6 +155,10 @@
testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=-bar1`)
+ testConfig.productVariables.NativeCoveragePaths = []string{"*"}
+ testConfig.productVariables.NativeCoverageExcludePaths = nil
+ verifyExtraFlags(t, testConfig, `--collect_code_coverage --instrumentation_filter=+.*`)
+
testConfig.productVariables.ClangCoverage = boolPtr(false)
actual := verifyExtraFlags(t, testConfig, ``)
if strings.Contains(actual, "--collect_code_coverage") ||
@@ -158,7 +170,7 @@
func verifyExtraFlags(t *testing.T, config Config, expected string) string {
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
- err := bazelContext.InvokeBazel(config)
+ err := bazelContext.InvokeBazel(config, nil)
if err != nil {
t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
}
@@ -185,7 +197,7 @@
}
aqueryCommand := bazelCommand{command: "aquery", expression: "deps(@soong_injection//mixed_builds:buildroot)"}
if _, exists := bazelCommandResults[aqueryCommand]; !exists {
- bazelCommandResults[aqueryCommand] = "{}\n"
+ bazelCommandResults[aqueryCommand] = ""
}
runner := &mockBazelRunner{bazelCommandResults: bazelCommandResults}
return &bazelContext{
@@ -194,3 +206,14 @@
requests: map[cqueryKey]bool{},
}, p.soongOutDir
}
+
+// Transform the json format to ActionGraphContainer
+func JsonToActionGraphContainer(inputString string) ([]byte, error) {
+ var aqueryProtoResult analysis_v2_proto.ActionGraphContainer
+ err := json.Unmarshal([]byte(inputString), &aqueryProtoResult)
+ if err != nil {
+ return []byte(""), err
+ }
+ data, _ := proto.Marshal(&aqueryProtoResult)
+ return data, err
+}
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 9c50098..b2ea22f 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -534,3 +534,55 @@
}
return outs
}
+
+// BazelStringOrLabelFromProp splits a Soong module property that can be
+// either a string literal, path (with android:path tag) or a module reference
+// into separate bazel string or label attributes. Bazel treats string and label
+// attributes as distinct types, so this function categorizes a string property
+// into either one of them.
+//
+// e.g. apex.private_key = "foo.pem" can either refer to:
+//
+// 1. "foo.pem" in the current directory -> file target
+// 2. "foo.pem" module -> rule target
+// 3. "foo.pem" file in a different directory, prefixed by a product variable handled
+// in a bazel macro. -> string literal
+//
+// For the first two cases, they are defined using the label attribute. For the third case,
+// it's defined with the string attribute.
+func BazelStringOrLabelFromProp(
+ ctx TopDownMutatorContext,
+ propToDistinguish *string) (bazel.LabelAttribute, bazel.StringAttribute) {
+
+ var labelAttr bazel.LabelAttribute
+ var strAttr bazel.StringAttribute
+
+ if propToDistinguish == nil {
+ // nil pointer
+ return labelAttr, strAttr
+ }
+
+ prop := String(propToDistinguish)
+ if SrcIsModule(prop) != "" {
+ // If it's a module (SrcIsModule will return the module name), set the
+ // resolved label to the label attribute.
+ labelAttr.SetValue(BazelLabelForModuleDepSingle(ctx, prop))
+ } else {
+ // Not a module name. This could be a string literal or a file target in
+ // the current dir. Check if the path exists:
+ path := ExistentPathForSource(ctx, ctx.ModuleDir(), prop)
+
+ if path.Valid() && parentDir(path.String()) == ctx.ModuleDir() {
+ // If it exists and the path is relative to the current dir, resolve the bazel label
+ // for the _file target_ and set it to the label attribute.
+ //
+ // Resolution is necessary because this could be a file in a subpackage.
+ labelAttr.SetValue(BazelLabelForModuleSrcSingle(ctx, prop))
+ } else {
+ // Otherwise, treat it as a string literal and assign to the string attribute.
+ strAttr.Value = propToDistinguish
+ }
+ }
+
+ return labelAttr, strAttr
+}
diff --git a/android/bazel_test.go b/android/bazel_test.go
index dbe6067..7b38b6a 100644
--- a/android/bazel_test.go
+++ b/android/bazel_test.go
@@ -71,6 +71,20 @@
},
packageDir: "a",
},
+ {
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultFalseRecursively,
+ "a/b": allowlists.Bp2BuildDefaultTrue,
+ },
+ packageDir: "a/b",
+ },
+ {
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultFalseRecursively,
+ "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
+ },
+ packageDir: "a/b/c",
+ },
}
for _, test := range testCases {
@@ -133,6 +147,20 @@
},
packageDir: "a",
},
+ {
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultFalseRecursively,
+ "a/b": allowlists.Bp2BuildDefaultTrue,
+ },
+ packageDir: "a/b/c",
+ },
+ {
+ prefixes: allowlists.Bp2BuildConfig{
+ "a": allowlists.Bp2BuildDefaultTrueRecursively,
+ "a/b": allowlists.Bp2BuildDefaultFalseRecursively,
+ },
+ packageDir: "a/b/c",
+ },
}
for _, test := range testCases {
@@ -395,3 +423,21 @@
}
}
}
+
+func TestShouldKeepExistingBuildFileForDir(t *testing.T) {
+ allowlist := NewBp2BuildAllowlist()
+ // entry "a/b2/c2" is moot because of its parent "a/b2"
+ allowlist.SetKeepExistingBuildFile(map[string]bool{"a": false, "a/b1": false, "a/b2": true, "a/b1/c1": true, "a/b2/c2": false})
+ truths := []string{"a", "a/b1", "a/b2", "a/b1/c1", "a/b2/c", "a/b2/c2", "a/b2/c2/d"}
+ falsities := []string{"a1", "a/b", "a/b1/c"}
+ for _, dir := range truths {
+ if !allowlist.ShouldKeepExistingBuildFileForDir(dir) {
+ t.Errorf("%s expected TRUE but was FALSE", dir)
+ }
+ }
+ for _, dir := range falsities {
+ if allowlist.ShouldKeepExistingBuildFileForDir(dir) {
+ t.Errorf("%s expected FALSE but was TRUE", dir)
+ }
+ }
+}
diff --git a/android/config.go b/android/config.go
index ee432a2..f430b72 100644
--- a/android/config.go
+++ b/android/config.go
@@ -75,6 +75,9 @@
// Don't use bazel at all during module analysis.
AnalysisNoBazel SoongBuildMode = iota
+ // Symlink fores mode: merge two directory trees into a symlink forest
+ SymlinkForest
+
// Bp2build mode: Generate BUILD files from blueprint files and exit.
Bp2build
@@ -83,6 +86,9 @@
// express build semantics.
GenerateQueryView
+ // Generate BUILD files for API contributions to API surfaces
+ ApiBp2build
+
// Create a JSON representation of the module graph and exit.
GenerateModuleGraph
@@ -94,6 +100,11 @@
// allowlisted on an experimental basis.
BazelDevMode
+ // Use bazel during analysis of a few allowlisted build modules. The allowlist
+ // is considered "staging, as these are modules being prepared to be released
+ // into prod mode shortly after.
+ BazelStagingMode
+
// Use bazel during analysis of build modules from an allowlist carefully
// curated by the build team to be proven stable.
BazelProdMode
@@ -124,6 +135,11 @@
return []bootstrap.PrimaryBuilderInvocation{}
}
+// RunningInsideUnitTest returns true if this code is being run as part of a Soong unit test.
+func (c Config) RunningInsideUnitTest() bool {
+ return c.config.TestProductVariables != nil
+}
+
// A DeviceConfig object represents the configuration for a particular device
// being built. For now there will only be one of these, but in the future there
// may be multiple devices being built.
@@ -520,7 +536,40 @@
// Returns true if "Bazel builds" is enabled. In this mode, part of build
// analysis is handled by Bazel.
func (c *config) IsMixedBuildsEnabled() bool {
- return c.BuildMode == BazelProdMode || c.BuildMode == BazelDevMode
+ globalMixedBuildsSupport := c.Once(OnceKey{"globalMixedBuildsSupport"}, func() interface{} {
+ if c.productVariables.DeviceArch != nil && *c.productVariables.DeviceArch == "riscv64" {
+ fmt.Fprintln(os.Stderr, "unsupported device arch 'riscv64' for Bazel: falling back to non-mixed build")
+ return false
+ }
+ if c.IsEnvTrue("GLOBAL_THINLTO") {
+ fmt.Fprintln(os.Stderr, "unsupported env var GLOBAL_THINLTO for Bazel: falling back to non-mixed build")
+ return false
+ }
+ if c.IsEnvTrue("CLANG_COVERAGE") {
+ fmt.Fprintln(os.Stderr, "unsupported env var CLANG_COVERAGE for Bazel: falling back to non-mixed build")
+ return false
+ }
+ if len(c.productVariables.SanitizeHost) > 0 {
+ fmt.Fprintln(os.Stderr, "unsupported product var SanitizeHost for Bazel: falling back to non-mixed build")
+ return false
+ }
+ if len(c.productVariables.SanitizeDevice) > 0 {
+ fmt.Fprintln(os.Stderr, "unsupported product var SanitizeDevice for Bazel: falling back to non-mixed build")
+ return false
+ }
+ if len(c.productVariables.SanitizeDeviceDiag) > 0 {
+ fmt.Fprintln(os.Stderr, "unsupported product var SanitizeDeviceDiag for Bazel: falling back to non-mixed build")
+ return false
+ }
+ if len(c.productVariables.SanitizeDeviceArch) > 0 {
+ fmt.Fprintln(os.Stderr, "unsupported product var SanitizeDeviceArch for Bazel: falling back to non-mixed build")
+ return false
+ }
+ return true
+ }).(bool)
+
+ bazelModeEnabled := c.BuildMode == BazelProdMode || c.BuildMode == BazelDevMode || c.BuildMode == BazelStagingMode
+ return globalMixedBuildsSupport && bazelModeEnabled
}
func (c *config) SetAllowMissingDependencies() {
@@ -1093,7 +1142,7 @@
return c.config.productVariables.WithDexpreopt
}
-func (c *config) FrameworksBaseDirExists(ctx PathContext) bool {
+func (c *config) FrameworksBaseDirExists(ctx PathGlobContext) bool {
return ExistentPathForSource(ctx, "frameworks", "base", "Android.bp").Valid()
}
@@ -1256,10 +1305,6 @@
return coverage
}
-func (c *deviceConfig) AfdoAdditionalProfileDirs() []string {
- return c.config.productVariables.AfdoAdditionalProfileDirs
-}
-
func (c *deviceConfig) PgoAdditionalProfileDirs() []string {
return c.config.productVariables.PgoAdditionalProfileDirs
}
diff --git a/android/config_bp2build.go b/android/config_bp2build.go
index d6b2bcf..2beeb51 100644
--- a/android/config_bp2build.go
+++ b/android/config_bp2build.go
@@ -69,6 +69,7 @@
ret = append(ret, ev.exportedStringListDictVars.asBazel(config, stringVars, stringListVars, cfgDepVars)...)
// Note: ExportedVariableReferenceDictVars collections can only contain references to other variables and must be printed last
ret = append(ret, ev.exportedVariableReferenceDictVars.asBazel(config, stringVars, stringListVars, cfgDepVars)...)
+ ret = append(ret, ev.exportedConfigDependingVars.asBazel(config, stringVars, stringListVars, cfgDepVars)...)
return ret
}
@@ -141,6 +142,33 @@
m[k] = v
}
+func (m ExportedConfigDependingVariables) asBazel(config Config,
+ stringVars ExportedStringVariables, stringListVars ExportedStringListVariables, cfgDepVars ExportedConfigDependingVariables) []bazelConstant {
+ ret := make([]bazelConstant, 0, len(m))
+ for variable, unevaluatedVar := range m {
+ evalFunc := reflect.ValueOf(unevaluatedVar)
+ validateVariableMethod(variable, evalFunc)
+ evaluatedResult := evalFunc.Call([]reflect.Value{reflect.ValueOf(config)})
+ evaluatedValue := evaluatedResult[0].Interface().(string)
+ expandedVars, err := expandVar(config, evaluatedValue, stringVars, stringListVars, cfgDepVars)
+ if err != nil {
+ panic(fmt.Errorf("error expanding config variable %s: %s", variable, err))
+ }
+ if len(expandedVars) > 1 {
+ ret = append(ret, bazelConstant{
+ variableName: variable,
+ internalDefinition: starlark_fmt.PrintStringList(expandedVars, 0),
+ })
+ } else {
+ ret = append(ret, bazelConstant{
+ variableName: variable,
+ internalDefinition: fmt.Sprintf(`"%s"`, validateCharacters(expandedVars[0])),
+ })
+ }
+ }
+ return ret
+}
+
// Ensure that string s has no invalid characters to be generated into the bzl file.
func validateCharacters(s string) string {
for _, c := range []string{`\n`, `"`, `\`} {
diff --git a/android/defs.go b/android/defs.go
index 2a28e98..9ae360e 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -25,7 +25,8 @@
)
var (
- pctx = NewPackageContext("android/soong/android")
+ pctx = NewPackageContext("android/soong/android")
+ exportedVars = NewExportedVariables(pctx)
cpPreserveSymlinks = pctx.VariableConfigMethod("cpPreserveSymlinks",
Config.CpPreserveSymlinksFlags)
@@ -128,6 +129,13 @@
pctx.VariableFunc("RBEWrapper", func(ctx PackageVarContext) string {
return ctx.Config().RBEWrapper()
})
+
+ exportedVars.ExportStringList("NeverAllowNotInIncludeDir", neverallowNotInIncludeDir)
+ exportedVars.ExportStringList("NeverAllowNoUseIncludeDir", neverallowNoUseIncludeDir)
+}
+
+func BazelCcToolchainVars(config Config) string {
+ return BazelToolchainVars(config, exportedVars)
}
var (
diff --git a/android/filegroup.go b/android/filegroup.go
index 6b11172..d21d146 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -122,16 +122,18 @@
if fg.ShouldConvertToProtoLibrary(ctx) {
// TODO(b/246997908): we can remove this tag if we could figure out a
// solution for this bug.
- tags := []string{"manual"}
attrs := &ProtoAttrs{
Srcs: srcs,
Strip_import_prefix: fg.properties.Path,
- Tags: tags,
}
+ tags := []string{"manual"}
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
- CommonAttributes{Name: fg.Name() + convertedProtoLibrarySuffix},
+ CommonAttributes{
+ Name: fg.Name() + convertedProtoLibrarySuffix,
+ Tags: bazel.MakeStringListAttribute(tags),
+ },
attrs)
}
@@ -234,7 +236,8 @@
}
func (fg *fileGroup) IsMixedBuildSupported(ctx BaseModuleContext) bool {
- return true
+ // TODO(b/247782695), TODO(b/242847534) Fix mixed builds for filegroups
+ return false
}
func (fg *fileGroup) ProcessBazelQueryResponse(ctx ModuleContext) {
diff --git a/android/filegroup_test.go b/android/filegroup_test.go
index a7ea805..8292d5e 100644
--- a/android/filegroup_test.go
+++ b/android/filegroup_test.go
@@ -6,6 +6,8 @@
)
func TestFileGroupWithPathProp(t *testing.T) {
+ // TODO(b/247782695), TODO(b/242847534) Fix mixed builds for filegroups
+ t.Skip("Re-enable once filegroups are corrected for mixed builds")
outBaseDir := "outputbase"
pathPrefix := outBaseDir + "/execroot/__main__"
expectedOutputfile := filepath.Join(pathPrefix, "a/b/c/d/test.aidl")
diff --git a/android/fixture.go b/android/fixture.go
index f33e718..3f01f5a 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -658,7 +658,7 @@
func createFixture(t *testing.T, buildDir string, preparers []*simpleFixturePreparer) Fixture {
config := TestConfig(buildDir, nil, "", nil)
- ctx := NewTestContext(config)
+ ctx := newTestContextForFixture(config)
fixture := &fixture{
preparers: preparers,
t: t,
@@ -790,6 +790,16 @@
}
}
+ // Create and set the Context's NameInterface. It needs to be created here as it depends on the
+ // configuration that has been prepared for this fixture.
+ resolver := NewNameResolver(ctx.config)
+
+ // Set the NameInterface in the main Context.
+ ctx.SetNameInterface(resolver)
+
+ // Set the NameResolver in the TestContext.
+ ctx.NameResolver = resolver
+
ctx.Register()
var ninjaDeps []string
extraNinjaDeps, errs := ctx.ParseBlueprintsFiles("ignored")
diff --git a/android/gen_notice.go b/android/gen_notice.go
index 008aac5..28fddbc 100644
--- a/android/gen_notice.go
+++ b/android/gen_notice.go
@@ -61,6 +61,9 @@
if mod == nil {
continue
}
+ if !mod.Enabled() { // don't depend on variants without build rules
+ continue
+ }
modules = append(modules, mod)
}
}
diff --git a/android/license.go b/android/license.go
index cde5e6e..ab8431a 100644
--- a/android/license.go
+++ b/android/license.go
@@ -15,10 +15,12 @@
package android
import (
- "android/soong/bazel"
"fmt"
- "github.com/google/blueprint"
"os"
+
+ "github.com/google/blueprint"
+
+ "android/soong/bazel"
)
type licenseKindDependencyTag struct {
@@ -101,6 +103,14 @@
}
func (m *licenseModule) DepsMutator(ctx BottomUpMutatorContext) {
+ for i, license := range m.properties.License_kinds {
+ for j := i + 1; j < len(m.properties.License_kinds); j++ {
+ if license == m.properties.License_kinds[j] {
+ ctx.ModuleErrorf("Duplicated license kind: %q", license)
+ break
+ }
+ }
+ }
ctx.AddVariationDependencies(nil, licenseKindTag, m.properties.License_kinds...)
}
diff --git a/android/license_metadata.go b/android/license_metadata.go
index 4ee5bf7..18b63d3 100644
--- a/android/license_metadata.go
+++ b/android/license_metadata.go
@@ -98,6 +98,11 @@
var orderOnlyDeps Paths
var args []string
+ if n := ctx.ModuleName(); n != "" {
+ args = append(args,
+ "-mn "+proptools.NinjaAndShellEscape(n))
+ }
+
if t := ctx.ModuleType(); t != "" {
args = append(args,
"-mt "+proptools.NinjaAndShellEscape(t))
diff --git a/android/license_test.go b/android/license_test.go
index 7222cd7..89e7f06 100644
--- a/android/license_test.go
+++ b/android/license_test.go
@@ -90,6 +90,36 @@
},
},
{
+ name: "must not duplicate license_kind",
+ fs: map[string][]byte{
+ "top/Android.bp": []byte(`
+ license_kind {
+ name: "top_by_exception_only",
+ conditions: ["by_exception_only"],
+ visibility: ["//visibility:private"],
+ }
+
+ license_kind {
+ name: "top_by_exception_only_2",
+ conditions: ["by_exception_only"],
+ visibility: ["//visibility:private"],
+ }
+
+ license {
+ name: "top_proprietary",
+ license_kinds: [
+ "top_by_exception_only",
+ "top_by_exception_only_2",
+ "top_by_exception_only"
+ ],
+ visibility: ["//visibility:public"],
+ }`),
+ },
+ expectedErrors: []string{
+ `top/Android.bp:14:5: module "top_proprietary": Duplicated license kind: "top_by_exception_only"`,
+ },
+ },
+ {
name: "license_kind module must exist",
fs: map[string][]byte{
"top/Android.bp": []byte(`
diff --git a/android/licenses.go b/android/licenses.go
index c47b3e6..c6b3243 100644
--- a/android/licenses.go
+++ b/android/licenses.go
@@ -340,4 +340,5 @@
ctx.Strict("COMPLIANCENOTICE_SHIPPEDLIBS", ctx.Config().HostToolPath(ctx, "compliancenotice_shippedlibs").String())
ctx.Strict("COMPLIANCE_LISTSHARE", ctx.Config().HostToolPath(ctx, "compliance_listshare").String())
ctx.Strict("COMPLIANCE_CHECKSHARE", ctx.Config().HostToolPath(ctx, "compliance_checkshare").String())
+ ctx.Strict("COMPLIANCE_SBOM", ctx.Config().HostToolPath(ctx, "compliance_sbom").String())
}
diff --git a/android/makevars.go b/android/makevars.go
index a74185a..0800190 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -35,7 +35,7 @@
ctx.Strict("MIN_SUPPORTED_SDK_VERSION", ctx.Config().MinSupportedSdkVersion().String())
}
-///////////////////////////////////////////////////////////////////////////////
+// /////////////////////////////////////////////////////////////////////////////
// BaseMakeVarsContext contains the common functions for other packages to use
// to declare make variables
@@ -173,13 +173,14 @@
MakeVars(ctx MakeVarsModuleContext)
}
-///////////////////////////////////////////////////////////////////////////////
+// /////////////////////////////////////////////////////////////////////////////
func makeVarsSingletonFunc() Singleton {
return &makeVarsSingleton{}
}
type makeVarsSingleton struct {
+ varsForTesting []makeVarsVariable
installsForTesting []byte
}
@@ -320,7 +321,11 @@
ctx.Errorf(err.Error())
}
- s.installsForTesting = installsBytes
+ // Only save state for tests when testing.
+ if ctx.Config().RunningInsideUnitTest() {
+ s.varsForTesting = vars
+ s.installsForTesting = installsBytes
+ }
}
func (s *makeVarsSingleton) writeVars(vars []makeVarsVariable) []byte {
@@ -466,7 +471,7 @@
fmt.Fprintf(buf, " %s", dep.String())
}
fmt.Fprintln(buf)
- fmt.Fprintln(buf, "\t@echo \"Install $@\"")
+ fmt.Fprintln(buf, "\t@echo \"Install: $@\"")
fmt.Fprintf(buf, "\trm -f $@ && cp -f %s $< $@\n", preserveSymlinksFlag)
if install.executable {
fmt.Fprintf(buf, "\tchmod +x $@\n")
@@ -510,7 +515,7 @@
fromStr = symlink.absFrom
}
- fmt.Fprintln(buf, "\t@echo \"Symlink $@\"")
+ fmt.Fprintln(buf, "\t@echo \"Symlink: $@\"")
fmt.Fprintf(buf, "\trm -f $@ && ln -sfn %s $@", fromStr)
fmt.Fprintln(buf)
fmt.Fprintln(buf)
diff --git a/android/metrics.go b/android/metrics.go
index ecda026..3d41a1d 100644
--- a/android/metrics.go
+++ b/android/metrics.go
@@ -62,7 +62,7 @@
})
}
-func collectMetrics(config Config, eventHandler metrics.EventHandler) *soong_metrics_proto.SoongBuildMetrics {
+func collectMetrics(config Config, eventHandler *metrics.EventHandler) *soong_metrics_proto.SoongBuildMetrics {
metrics := &soong_metrics_proto.SoongBuildMetrics{}
soongMetrics, ok := readSoongMetrics(config)
@@ -107,7 +107,7 @@
return metrics
}
-func WriteMetrics(config Config, eventHandler metrics.EventHandler, metricsFile string) error {
+func WriteMetrics(config Config, eventHandler *metrics.EventHandler, metricsFile string) error {
metrics := collectMetrics(config, eventHandler)
buf, err := proto.Marshal(metrics)
diff --git a/android/module.go b/android/module.go
index 1617259..681f724 100644
--- a/android/module.go
+++ b/android/module.go
@@ -915,10 +915,21 @@
type CommonAttributes struct {
// Soong nameProperties -> Bazel name
Name string
+
// Data mapped from: Required
Data bazel.LabelListAttribute
+ // SkipData is neither a Soong nor Bazel target attribute
+ // If true, this will not fill the data attribute automatically
+ // This is useful for Soong modules that have 1:many Bazel targets
+ // Some of the generated Bazel targets might not have a data attribute
+ SkipData *bool
+
Tags bazel.StringListAttribute
+
+ Applicable_licenses bazel.LabelListAttribute
+
+ Testonly *bool
}
// constraintAttributes represents Bazel attributes pertaining to build constraints,
@@ -1231,16 +1242,20 @@
}
}
+ attrs.Applicable_licenses = bazel.MakeLabelListAttribute(BazelLabelForModuleDeps(ctx, mod.commonProperties.Licenses))
+
// The required property can contain the module itself. This causes a cycle
// when generated as the 'data' label list attribute in Bazel. Remove it if
// it exists. See b/247985196.
_, requiredWithoutCycles := RemoveFromList(ctx.ModuleName(), mod.commonProperties.Required)
+ requiredWithoutCycles = FirstUniqueStrings(requiredWithoutCycles)
required := depsToLabelList(requiredWithoutCycles)
archVariantProps := mod.GetArchVariantProperties(ctx, &commonProperties{})
for axis, configToProps := range archVariantProps {
for config, _props := range configToProps {
if archProps, ok := _props.(*commonProperties); ok {
_, requiredWithoutCycles := RemoveFromList(ctx.ModuleName(), archProps.Required)
+ requiredWithoutCycles = FirstUniqueStrings(requiredWithoutCycles)
required.SetSelectValue(axis, config, depsToLabelList(requiredWithoutCycles).Value)
if !neitherHostNorDevice {
if archProps.Enabled != nil {
@@ -1301,7 +1316,12 @@
platformEnabledAttribute.Add(&l)
}
- attrs.Data.Append(required)
+ if !proptools.Bool(attrs.SkipData) {
+ attrs.Data.Append(required)
+ }
+ // SkipData is not an attribute of any Bazel target
+ // Set this to nil so that it does not appear in the generated build file
+ attrs.SkipData = nil
moduleEnableConstraints := bazel.LabelListAttribute{}
moduleEnableConstraints.Append(platformEnabledAttribute)
@@ -1519,7 +1539,7 @@
return FirstUniqueStrings(m.commonProperties.BazelConversionStatus.UnconvertedDeps)
}
-// GetMissingBp2buildDeps eturns the list of module names that were not found in Android.bp files.
+// GetMissingBp2buildDeps returns the list of module names that were not found in Android.bp files.
func (m *ModuleBase) GetMissingBp2buildDeps() []string {
return FirstUniqueStrings(m.commonProperties.BazelConversionStatus.MissingDeps)
}
@@ -2033,7 +2053,7 @@
}
func (m *ModuleBase) InstallInVendor() bool {
- return Bool(m.commonProperties.Vendor)
+ return Bool(m.commonProperties.Vendor) || Bool(m.commonProperties.Soc_specific) || Bool(m.commonProperties.Proprietary)
}
func (m *ModuleBase) InstallInRoot() bool {
@@ -3542,10 +3562,29 @@
reportPathError(ctx, err)
return nil
}
+ if len(paths) == 0 {
+ type addMissingDependenciesIntf interface {
+ AddMissingDependencies([]string)
+ OtherModuleName(blueprint.Module) string
+ }
+ if mctx, ok := ctx.(addMissingDependenciesIntf); ok && ctx.Config().AllowMissingDependencies() {
+ mctx.AddMissingDependencies([]string{mctx.OtherModuleName(module)})
+ } else {
+ ReportPathErrorf(ctx, "failed to get output files from module %q", pathContextName(ctx, module))
+ }
+ // Return a fake output file to avoid nil dereferences of Path objects later.
+ // This should never get used for an actual build as the error or missing
+ // dependency has already been reported.
+ p, err := pathForSource(ctx, filepath.Join("missing_output_file", pathContextName(ctx, module)))
+ if err != nil {
+ reportPathError(ctx, err)
+ return nil
+ }
+ return p
+ }
if len(paths) > 1 {
ReportPathErrorf(ctx, "got multiple output files from module %q, expected exactly one",
pathContextName(ctx, module))
- return nil
}
return paths[0]
}
@@ -3557,18 +3596,12 @@
return nil, fmt.Errorf("failed to get output file from module %q: %s",
pathContextName(ctx, module), err.Error())
}
- if len(paths) == 0 {
- return nil, fmt.Errorf("failed to get output files from module %q", pathContextName(ctx, module))
- }
return paths, nil
} else if sourceFileProducer, ok := module.(SourceFileProducer); ok {
if tag != "" {
return nil, fmt.Errorf("module %q is a SourceFileProducer, not an OutputFileProducer, and so does not support tag %q", pathContextName(ctx, module), tag)
}
paths := sourceFileProducer.Srcs()
- if len(paths) == 0 {
- return nil, fmt.Errorf("failed to get output files from module %q", pathContextName(ctx, module))
- }
return paths, nil
} else {
return nil, fmt.Errorf("module %q is not an OutputFileProducer", pathContextName(ctx, module))
diff --git a/android/module_test.go b/android/module_test.go
index 0580bef..1ca7422 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -15,6 +15,7 @@
package android
import (
+ "github.com/google/blueprint"
"path/filepath"
"runtime"
"testing"
@@ -978,3 +979,88 @@
})
}
}
+
+type fakeBlueprintModule struct{}
+
+func (fakeBlueprintModule) Name() string { return "foo" }
+
+func (fakeBlueprintModule) GenerateBuildActions(blueprint.ModuleContext) {}
+
+type sourceProducerTestModule struct {
+ fakeBlueprintModule
+ source Path
+}
+
+func (s sourceProducerTestModule) Srcs() Paths { return Paths{s.source} }
+
+type outputFileProducerTestModule struct {
+ fakeBlueprintModule
+ output map[string]Path
+ error map[string]error
+}
+
+func (o outputFileProducerTestModule) OutputFiles(tag string) (Paths, error) {
+ return PathsIfNonNil(o.output[tag]), o.error[tag]
+}
+
+type pathContextAddMissingDependenciesWrapper struct {
+ PathContext
+ missingDeps []string
+}
+
+func (p *pathContextAddMissingDependenciesWrapper) AddMissingDependencies(deps []string) {
+ p.missingDeps = append(p.missingDeps, deps...)
+}
+func (p *pathContextAddMissingDependenciesWrapper) OtherModuleName(module blueprint.Module) string {
+ return module.Name()
+}
+
+func TestOutputFileForModule(t *testing.T) {
+ testcases := []struct {
+ name string
+ module blueprint.Module
+ tag string
+ env map[string]string
+ config func(*config)
+ expected string
+ missingDeps []string
+ }{
+ {
+ name: "SourceFileProducer",
+ module: &sourceProducerTestModule{source: PathForTesting("foo.txt")},
+ expected: "foo.txt",
+ },
+ {
+ name: "OutputFileProducer",
+ module: &outputFileProducerTestModule{output: map[string]Path{"": PathForTesting("foo.txt")}},
+ expected: "foo.txt",
+ },
+ {
+ name: "OutputFileProducer_tag",
+ module: &outputFileProducerTestModule{output: map[string]Path{"foo": PathForTesting("foo.txt")}},
+ tag: "foo",
+ expected: "foo.txt",
+ },
+ {
+ name: "OutputFileProducer_AllowMissingDependencies",
+ config: func(config *config) {
+ config.TestProductVariables.Allow_missing_dependencies = boolPtr(true)
+ },
+ module: &outputFileProducerTestModule{},
+ missingDeps: []string{"foo"},
+ expected: "missing_output_file/foo",
+ },
+ }
+ for _, tt := range testcases {
+ config := TestConfig(buildDir, tt.env, "", nil)
+ if tt.config != nil {
+ tt.config(config.config)
+ }
+ ctx := &pathContextAddMissingDependenciesWrapper{
+ PathContext: PathContextForTesting(config),
+ }
+ got := OutputFileForModule(ctx, tt.module, tt.tag)
+ AssertPathRelativeToTopEquals(t, "expected source path", tt.expected, got)
+ AssertArrayString(t, "expected missing deps", tt.missingDeps, ctx.missingDeps)
+ }
+}
diff --git a/android/mutator.go b/android/mutator.go
index 9e4aa59..83d4e66 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -31,22 +31,33 @@
// RegisterMutatorsForBazelConversion is a alternate registration pipeline for bp2build. Exported for testing.
func RegisterMutatorsForBazelConversion(ctx *Context, preArchMutators []RegisterMutatorFunc) {
+ bp2buildMutators := append(preArchMutators, registerBp2buildConversionMutator)
+ registerMutatorsForBazelConversion(ctx, bp2buildMutators)
+}
+
+// RegisterMutatorsForApiBazelConversion is an alternate registration pipeline for api_bp2build
+// This pipeline restricts generation of Bazel targets to Soong modules that contribute APIs
+func RegisterMutatorsForApiBazelConversion(ctx *Context, preArchMutators []RegisterMutatorFunc) {
+ bp2buildMutators := append(preArchMutators, registerApiBp2buildConversionMutator)
+ registerMutatorsForBazelConversion(ctx, bp2buildMutators)
+}
+
+func registerMutatorsForBazelConversion(ctx *Context, bp2buildMutators []RegisterMutatorFunc) {
mctx := ®isterMutatorsContext{
bazelConversionMode: true,
}
- bp2buildMutators := append([]RegisterMutatorFunc{
+ allMutators := append([]RegisterMutatorFunc{
RegisterNamespaceMutator,
RegisterDefaultsPreArchMutators,
// TODO(b/165114590): this is required to resolve deps that are only prebuilts, but we should
// evaluate the impact on conversion.
RegisterPrebuiltsPreArchMutators,
},
- preArchMutators...)
- bp2buildMutators = append(bp2buildMutators, registerBp2buildConversionMutator)
+ bp2buildMutators...)
// Register bp2build mutators
- for _, f := range bp2buildMutators {
+ for _, f := range allMutators {
f(mctx)
}
diff --git a/android/namespace.go b/android/namespace.go
index a3ff761..b43ffdf 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -91,7 +91,27 @@
namespaceExportFilter func(*Namespace) bool
}
-func NewNameResolver(namespaceExportFilter func(*Namespace) bool) *NameResolver {
+// NameResolverConfig provides the subset of the Config interface needed by the
+// NewNameResolver function.
+type NameResolverConfig interface {
+ // ExportedNamespaces is the list of namespaces that Soong must export to
+ // make.
+ ExportedNamespaces() []string
+}
+
+func NewNameResolver(config NameResolverConfig) *NameResolver {
+ namespacePathsToExport := make(map[string]bool)
+
+ for _, namespaceName := range config.ExportedNamespaces() {
+ namespacePathsToExport[namespaceName] = true
+ }
+
+ namespacePathsToExport["."] = true // always export the root namespace
+
+ namespaceExportFilter := func(namespace *Namespace) bool {
+ return namespacePathsToExport[namespace.Path]
+ }
+
r := &NameResolver{
namespacesByDir: sync.Map{},
namespaceExportFilter: namespaceExportFilter,
diff --git a/android/namespace_test.go b/android/namespace_test.go
index 87d1320..7a387a0 100644
--- a/android/namespace_test.go
+++ b/android/namespace_test.go
@@ -602,6 +602,36 @@
// RunTest will report any errors
}
+func TestNamespace_Exports(t *testing.T) {
+ result := GroupFixturePreparers(
+ prepareForTestWithNamespace,
+ FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+ variables.NamespacesToExport = []string{"dir1"}
+ }),
+ dirBpToPreparer(map[string]string{
+ "dir1": `
+ soong_namespace {
+ }
+ test_module {
+ name: "a",
+ }
+ `,
+ "dir2": `
+ soong_namespace {
+ }
+ test_module {
+ name: "b",
+ }
+ `,
+ }),
+ ).RunTest(t)
+
+ aModule := result.Module("a", "")
+ AssertBoolEquals(t, "a exported", true, aModule.ExportedToMake())
+ bModule := result.Module("b", "")
+ AssertBoolEquals(t, "b not exported", false, bModule.ExportedToMake())
+}
+
// some utils to support the tests
var prepareForTestWithNamespace = GroupFixturePreparers(
diff --git a/android/neverallow.go b/android/neverallow.go
index 00078a0..ad9880a 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -58,6 +58,8 @@
AddNeverAllowRules(createMakefileGoalRules()...)
AddNeverAllowRules(createInitFirstStageRules()...)
AddNeverAllowRules(createProhibitFrameworkAccessRules()...)
+ AddNeverAllowRules(createBp2BuildRule())
+ AddNeverAllowRules(createCcStubsRule())
}
// Add a NeverAllow rule to the set of rules to apply.
@@ -65,8 +67,16 @@
neverallows = append(neverallows, rules...)
}
-func createIncludeDirsRules() []Rule {
- notInIncludeDir := []string{
+func createBp2BuildRule() Rule {
+ return NeverAllow().
+ With("bazel_module.bp2build_available", "true").
+ NotIn("soong_tests"). // only used in tests
+ Because("setting bp2build_available in Android.bp is not " +
+ "supported for custom conversion, use allowlists.go instead.")
+}
+
+var (
+ neverallowNotInIncludeDir = []string{
"art",
"art/libnativebridge",
"art/libnativeloader",
@@ -82,7 +92,7 @@
"external/vixl",
"external/wycheproof",
}
- noUseIncludeDir := []string{
+ neverallowNoUseIncludeDir = []string{
"frameworks/av/apex",
"frameworks/av/tools",
"frameworks/native/cmds",
@@ -94,10 +104,12 @@
"system/libfmq",
"system/libvintf",
}
+)
- rules := make([]Rule, 0, len(notInIncludeDir)+len(noUseIncludeDir))
+func createIncludeDirsRules() []Rule {
+ rules := make([]Rule, 0, len(neverallowNotInIncludeDir)+len(neverallowNoUseIncludeDir))
- for _, path := range notInIncludeDir {
+ for _, path := range neverallowNotInIncludeDir {
rule :=
NeverAllow().
WithMatcher("include_dirs", StartsWith(path+"/")).
@@ -107,7 +119,7 @@
rules = append(rules, rule)
}
- for _, path := range noUseIncludeDir {
+ for _, path := range neverallowNoUseIncludeDir {
rule := NeverAllow().In(path+"/").WithMatcher("include_dirs", isSetMatcherInstance).
Because("include_dirs is deprecated, all usages of them in '" + path + "' have been migrated" +
" to use alternate mechanisms and so can no longer be used.")
@@ -154,6 +166,7 @@
"development/build",
"external/guava",
"external/robolectric-shadows",
+ "external/robolectric",
"frameworks/layoutlib",
}
@@ -202,6 +215,17 @@
}
}
+func createCcStubsRule() Rule {
+ ccStubsImplementationInstallableProjectsAllowedList := []string{
+ "packages/modules/Virtualization/vm_payload",
+ }
+
+ return NeverAllow().
+ NotIn(ccStubsImplementationInstallableProjectsAllowedList...).
+ WithMatcher("stubs.implementation_installable", isSetMatcherInstance).
+ Because("implementation_installable can only be used in allowed projects.")
+}
+
func createUncompressDexRules() []Rule {
return []Rule{
NeverAllow().
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 4772799..5f5f9a1 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -367,6 +367,22 @@
"framework can't be used when building against SDK",
},
},
+ // Test for the rule restricting use of implementation_installable
+ {
+ name: `"implementation_installable" outside allowed list`,
+ fs: map[string][]byte{
+ "Android.bp": []byte(`
+ cc_library {
+ name: "outside_allowed_list",
+ stubs: {
+ implementation_installable: true,
+ },
+ }`),
+ },
+ expectedErrors: []string{
+ `module "outside_allowed_list": violates neverallow`,
+ },
+ },
}
var prepareForNeverAllowTest = GroupFixturePreparers(
@@ -419,6 +435,10 @@
Platform struct {
Shared_libs []string
}
+
+ Stubs struct {
+ Implementation_installable *bool
+ }
}
type mockCcLibraryModule struct {
diff --git a/android/ninja_deps_test.go b/android/ninja_deps_test.go
index 947c257..d6afcc0 100644
--- a/android/ninja_deps_test.go
+++ b/android/ninja_deps_test.go
@@ -18,21 +18,6 @@
"testing"
)
-func init() {
- // This variable uses ExistentPathForSource on a PackageVarContext, which is a PathContext
- // that is not a PathGlobContext. That requires the deps to be stored in the Config.
- pctx.VariableFunc("test_ninja_deps_variable", func(ctx PackageVarContext) string {
- // Using ExistentPathForSource to look for a file that does not exist in a directory that
- // does exist (test_ninja_deps) from a PackageVarContext adds a dependency from build.ninja
- // to the directory.
- if ExistentPathForSource(ctx, "test_ninja_deps/does_not_exist").Valid() {
- return "true"
- } else {
- return "false"
- }
- })
-}
-
func testNinjaDepsSingletonFactory() Singleton {
return testNinjaDepsSingleton{}
}
@@ -40,33 +25,19 @@
type testNinjaDepsSingleton struct{}
func (testNinjaDepsSingleton) GenerateBuildActions(ctx SingletonContext) {
- // Reference the test_ninja_deps_variable in a build statement so Blueprint is forced to
- // evaluate it.
- ctx.Build(pctx, BuildParams{
- Rule: Cp,
- Input: PathForTesting("foo"),
- Output: PathForOutput(ctx, "test_ninja_deps_out"),
- Args: map[string]string{
- "cpFlags": "${test_ninja_deps_variable}",
- },
- })
+ ctx.Config().addNinjaFileDeps("foo")
}
func TestNinjaDeps(t *testing.T) {
- fs := MockFS{
- "test_ninja_deps/exists": nil,
- }
-
result := GroupFixturePreparers(
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterSingletonType("test_ninja_deps_singleton", testNinjaDepsSingletonFactory)
ctx.RegisterSingletonType("ninja_deps_singleton", ninjaDepsSingletonFactory)
}),
- fs.AddToFixture(),
).RunTest(t)
// Verify that the ninja file has a dependency on the test_ninja_deps directory.
- if g, w := result.NinjaDeps, "test_ninja_deps"; !InList(w, g) {
+ if g, w := result.NinjaDeps, "foo"; !InList(w, g) {
t.Errorf("expected %q in %q", w, g)
}
}
diff --git a/android/package_ctx.go b/android/package_ctx.go
index f354db8..c348c82 100644
--- a/android/package_ctx.go
+++ b/android/package_ctx.go
@@ -48,7 +48,7 @@
var _ PathContext = &configErrorWrapper{}
var _ errorfContext = &configErrorWrapper{}
-var _ PackageVarContext = &configErrorWrapper{}
+var _ PackageVarContext = &variableFuncContextWrapper{}
var _ PackagePoolContext = &configErrorWrapper{}
var _ PackageRuleContext = &configErrorWrapper{}
@@ -62,21 +62,33 @@
e.config.addNinjaFileDeps(deps...)
}
-type PackageVarContext interface {
+type variableFuncContextWrapper struct {
+ configErrorWrapper
+ blueprint.VariableFuncContext
+}
+
+type PackagePoolContext interface {
PathContext
errorfContext
}
-type PackagePoolContext PackageVarContext
-type PackageRuleContext PackageVarContext
+type PackageRuleContext PackagePoolContext
+
+type PackageVarContext interface {
+ PackagePoolContext
+ PathGlobContext
+}
// VariableFunc wraps blueprint.PackageContext.VariableFunc, converting the interface{} config
// argument to a PackageVarContext.
func (p PackageContext) VariableFunc(name string,
f func(PackageVarContext) string) blueprint.Variable {
- return p.PackageContext.VariableFunc(name, func(config interface{}) (string, error) {
- ctx := &configErrorWrapper{p, config.(Config), nil}
+ return p.PackageContext.VariableFunc(name, func(bpctx blueprint.VariableFuncContext, config interface{}) (string, error) {
+ ctx := &variableFuncContextWrapper{
+ configErrorWrapper: configErrorWrapper{p, config.(Config), nil},
+ VariableFuncContext: bpctx,
+ }
ret := f(ctx)
if len(ctx.errors) > 0 {
return "", ctx.errors[0]
diff --git a/android/paths.go b/android/paths.go
index 27f4bf5..a6a54fa 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -39,6 +39,7 @@
}
type PathGlobContext interface {
+ PathContext
GlobWithDeps(globPattern string, excludes []string) ([]string, error)
}
@@ -56,7 +57,6 @@
// EarlyModulePathContext is a subset of EarlyModuleContext methods required by the
// Path methods. These path methods can be called before any mutators have run.
type EarlyModulePathContext interface {
- PathContext
PathGlobContext
ModuleDir() string
@@ -375,7 +375,7 @@
// ExistentPathsForSources returns a list of Paths rooted from SrcDir, *not* rooted from the
// module's local source directory, that are found in the tree. If any are not found, they are
// omitted from the list, and dependencies are added so that we're re-run when they are added.
-func ExistentPathsForSources(ctx PathContext, paths []string) Paths {
+func ExistentPathsForSources(ctx PathGlobContext, paths []string) Paths {
ret := make(Paths, 0, len(paths))
for _, path := range paths {
p := ExistentPathForSource(ctx, path)
@@ -1087,21 +1087,12 @@
// existsWithDependencies returns true if the path exists, and adds appropriate dependencies to rerun if the
// path does not exist.
-func existsWithDependencies(ctx PathContext, path SourcePath) (exists bool, err error) {
+func existsWithDependencies(ctx PathGlobContext, path SourcePath) (exists bool, err error) {
var files []string
- if gctx, ok := ctx.(PathGlobContext); ok {
- // Use glob to produce proper dependencies, even though we only want
- // a single file.
- files, err = gctx.GlobWithDeps(path.String(), nil)
- } else {
- var result pathtools.GlobResult
- // We cannot add build statements in this context, so we fall back to
- // AddNinjaFileDeps
- result, err = ctx.Config().fs.Glob(path.String(), nil, pathtools.FollowSymlinks)
- ctx.AddNinjaFileDeps(result.Deps...)
- files = result.Matches
- }
+ // Use glob to produce proper dependencies, even though we only want
+ // a single file.
+ files, err = ctx.GlobWithDeps(path.String(), nil)
if err != nil {
return false, fmt.Errorf("glob: %s", err.Error())
@@ -1124,7 +1115,7 @@
}
if modCtx, ok := ctx.(ModuleMissingDepsPathContext); ok && ctx.Config().AllowMissingDependencies() {
- exists, err := existsWithDependencies(ctx, path)
+ exists, err := existsWithDependencies(modCtx, path)
if err != nil {
reportPathError(ctx, err)
}
@@ -1139,11 +1130,26 @@
return path
}
+// MaybeExistentPathForSource joins the provided path components and validates that the result
+// neither escapes the source dir nor is in the out dir.
+// It does not validate whether the path exists.
+func MaybeExistentPathForSource(ctx PathContext, pathComponents ...string) SourcePath {
+ path, err := pathForSource(ctx, pathComponents...)
+ if err != nil {
+ reportPathError(ctx, err)
+ }
+
+ if pathtools.IsGlob(path.String()) {
+ ReportPathErrorf(ctx, "path may not contain a glob: %s", path.String())
+ }
+ return path
+}
+
// ExistentPathForSource returns an OptionalPath with the SourcePath, rooted from SrcDir, *not*
// rooted from the module's local source directory, if the path exists, or an empty OptionalPath if
// it doesn't exist. Dependencies are added so that the ninja file will be regenerated if the state
// of the path changes.
-func ExistentPathForSource(ctx PathContext, pathComponents ...string) OptionalPath {
+func ExistentPathForSource(ctx PathGlobContext, pathComponents ...string) OptionalPath {
path, err := pathForSource(ctx, pathComponents...)
if err != nil {
reportPathError(ctx, err)
@@ -1638,6 +1644,10 @@
}
}
+func (p InstallPath) Partition() string {
+ return p.partition
+}
+
// Join creates a new InstallPath with paths... joined with the current path. The
// provided paths... may not use '..' to escape from the current path.
func (p InstallPath) Join(ctx PathContext, paths ...string) InstallPath {
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 4e4fa42..9b5c0e9 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -56,7 +56,9 @@
var _ ExcludeFromVisibilityEnforcementTag = PrebuiltDepTag
var _ ExcludeFromApexContentsTag = PrebuiltDepTag
-type PrebuiltProperties struct {
+// UserSuppliedPrebuiltProperties contains the prebuilt properties that can be specified in an
+// Android.bp file.
+type UserSuppliedPrebuiltProperties struct {
// When prefer is set to true the prebuilt will be used instead of any source module with
// a matching name.
Prefer *bool `android:"arch_variant"`
@@ -70,6 +72,16 @@
// If specified then the prefer property is ignored in favor of the value of the Soong config
// variable.
Use_source_config_var *ConfigVarProperties
+}
+
+// CopyUserSuppliedPropertiesFromPrebuilt copies the user supplied prebuilt properties from the
+// prebuilt properties.
+func (u *UserSuppliedPrebuiltProperties) CopyUserSuppliedPropertiesFromPrebuilt(p *Prebuilt) {
+ *u = p.properties.UserSuppliedPrebuiltProperties
+}
+
+type PrebuiltProperties struct {
+ UserSuppliedPrebuiltProperties
SourceExists bool `blueprint:"mutated"`
UsePrebuilt bool `blueprint:"mutated"`
diff --git a/android/proto.go b/android/proto.go
index 3cac9a1..8204f77 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -164,7 +164,6 @@
Srcs bazel.LabelListAttribute
Strip_import_prefix *string
Deps bazel.LabelListAttribute
- Tags []string
}
// For each package in the include_dirs property a proto_library target should
diff --git a/android/register.go b/android/register.go
index d4ce5f1..6c69cc5 100644
--- a/android/register.go
+++ b/android/register.go
@@ -180,6 +180,16 @@
RegisterMutatorsForBazelConversion(ctx, bp2buildPreArchMutators)
}
+// RegisterForApiBazelConversion is similar to RegisterForBazelConversion except that
+// it only generates API targets in the generated workspace
+func (ctx *Context) RegisterForApiBazelConversion() {
+ for _, t := range moduleTypes {
+ t.register(ctx)
+ }
+
+ RegisterMutatorsForApiBazelConversion(ctx, bp2buildPreArchMutators)
+}
+
// Register the pipeline of singletons, module types, and mutators for
// generating build.ninja and other files for Kati, from Android.bp files.
func (ctx *Context) Register() {
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index 7d21b75..1519f60 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -642,9 +642,13 @@
// Extracts an interface from values containing the properties to apply based on config.
// If config does not match a value with a non-nil property set, the default value will be returned.
func (s *stringVariable) PropertiesToApply(config SoongConfig, values reflect.Value) (interface{}, error) {
+ configValue := config.String(s.variable)
+ if configValue != "" && !InList(configValue, s.values) {
+ return nil, fmt.Errorf("Soong config property %q must be one of %v, found %q", s.variable, s.values, configValue)
+ }
for j, v := range s.values {
f := values.Field(j)
- if config.String(s.variable) == v && !f.Elem().IsNil() {
+ if configValue == v && !f.Elem().IsNil() {
return f.Interface(), nil
}
}
@@ -861,3 +865,13 @@
}
var emptyInterfaceType = reflect.TypeOf(emptyInterfaceStruct{}).Field(0).Type
+
+// InList checks if the string belongs to the list
+func InList(s string, list []string) bool {
+ for _, s2 := range list {
+ if s2 == s {
+ return true
+ }
+ }
+ return false
+}
diff --git a/android/soongconfig/modules_test.go b/android/soongconfig/modules_test.go
index a7800e8..d5d87ef 100644
--- a/android/soongconfig/modules_test.go
+++ b/android/soongconfig/modules_test.go
@@ -303,6 +303,10 @@
Bool_var interface{}
}
+type stringSoongConfigVars struct {
+ String_var interface{}
+}
+
func Test_PropertiesToApply(t *testing.T) {
mt, _ := newModuleType(&ModuleTypeProperties{
Module_type: "foo",
@@ -365,6 +369,51 @@
}
}
+func Test_PropertiesToApply_String_Error(t *testing.T) {
+ mt, _ := newModuleType(&ModuleTypeProperties{
+ Module_type: "foo",
+ Config_namespace: "bar",
+ Variables: []string{"string_var"},
+ Properties: []string{"a", "b"},
+ })
+ mt.Variables = append(mt.Variables, &stringVariable{
+ baseVariable: baseVariable{
+ variable: "string_var",
+ },
+ values: []string{"a", "b", "c"},
+ })
+ stringVarPositive := &properties{
+ A: proptools.StringPtr("A"),
+ B: true,
+ }
+ conditionsDefault := &properties{
+ A: proptools.StringPtr("default"),
+ B: false,
+ }
+ actualProps := &struct {
+ Soong_config_variables stringSoongConfigVars
+ }{
+ Soong_config_variables: stringSoongConfigVars{
+ String_var: &boolVarProps{
+ A: stringVarPositive.A,
+ B: stringVarPositive.B,
+ Conditions_default: conditionsDefault,
+ },
+ },
+ }
+ props := reflect.ValueOf(actualProps)
+
+ _, err := PropertiesToApply(mt, props, Config(map[string]string{
+ "string_var": "x",
+ }))
+ expected := `Soong config property "string_var" must be one of [a b c], found "x"`
+ if err == nil {
+ t.Fatalf("Expected an error, got nil")
+ } else if err.Error() != expected {
+ t.Fatalf("Error message was not correct, expected %q, got %q", expected, err.Error())
+ }
+}
+
func Test_Bp2BuildSoongConfigDefinitions(t *testing.T) {
testCases := []struct {
desc string
diff --git a/android/test_config.go b/android/test_config.go
index 0f88d51..70c319a 100644
--- a/android/test_config.go
+++ b/android/test_config.go
@@ -62,6 +62,7 @@
TestAllowNonExistentPaths: true,
BazelContext: noopBazelContext{},
+ BuildMode: BazelProdMode,
mixedBuildDisabledModules: make(map[string]struct{}),
mixedBuildEnabledModules: make(map[string]struct{}),
}
@@ -91,6 +92,9 @@
},
}
+ // Make the CommonOS OsType available for all products.
+ config.Targets[CommonOS] = []Target{commonTargetMap[CommonOS.Name]}
+
if runtime.GOOS == "darwin" {
config.Targets[config.BuildOS] = config.Targets[config.BuildOS][:1]
}
diff --git a/android/testing.go b/android/testing.go
index 7b74c89..8fcf440 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -30,19 +30,11 @@
"github.com/google/blueprint/proptools"
)
-func NewTestContext(config Config) *TestContext {
- namespaceExportFilter := func(namespace *Namespace) bool {
- return true
- }
-
- nameResolver := NewNameResolver(namespaceExportFilter)
+func newTestContextForFixture(config Config) *TestContext {
ctx := &TestContext{
- Context: &Context{blueprint.NewContext(), config},
- NameResolver: nameResolver,
+ Context: &Context{blueprint.NewContext(), config},
}
- ctx.SetNameInterface(nameResolver)
-
ctx.postDeps = append(ctx.postDeps, registerPathDepsMutator)
ctx.SetFs(ctx.config.fs)
@@ -53,6 +45,16 @@
return ctx
}
+func NewTestContext(config Config) *TestContext {
+ ctx := newTestContextForFixture(config)
+
+ nameResolver := NewNameResolver(config)
+ ctx.NameResolver = nameResolver
+ ctx.SetNameInterface(nameResolver)
+
+ return ctx
+}
+
var PrepareForTestWithArchMutator = GroupFixturePreparers(
// Configure architecture targets in the fixture config.
FixtureModifyConfig(modifyTestConfigToSupportArchMutator),
@@ -461,6 +463,12 @@
RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch)
}
+// RegisterForApiBazelConversion prepares a test context for API bp2build conversion.
+func (ctx *TestContext) RegisterForApiBazelConversion() {
+ ctx.config.BuildMode = ApiBp2build
+ RegisterMutatorsForApiBazelConversion(ctx.Context, ctx.bp2buildPreArch)
+}
+
func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
// This function adapts the old style ParseFileList calls that are spread throughout the tests
// to the new style that takes a config.
@@ -667,6 +675,46 @@
return parseMkRules(t, ctx.config, nodes)
}
+// MakeVarVariable provides access to make vars that will be written by the makeVarsSingleton
+type MakeVarVariable interface {
+ // Name is the name of the variable.
+ Name() string
+
+ // Value is the value of the variable.
+ Value() string
+}
+
+func (v makeVarsVariable) Name() string {
+ return v.name
+}
+
+func (v makeVarsVariable) Value() string {
+ return v.value
+}
+
+// PrepareForTestAccessingMakeVars sets up the test so that MakeVarsForTesting will work.
+var PrepareForTestAccessingMakeVars = GroupFixturePreparers(
+ PrepareForTestWithAndroidMk,
+ PrepareForTestWithMakevars,
+)
+
+// MakeVarsForTesting returns a filtered list of MakeVarVariable objects that represent the
+// variables that will be written out.
+//
+// It is necessary to use PrepareForTestAccessingMakeVars in tests that want to call this function.
+// Along with any other preparers needed to add the make vars.
+func (ctx *TestContext) MakeVarsForTesting(filter func(variable MakeVarVariable) bool) []MakeVarVariable {
+ vars := ctx.SingletonForTests("makevars").Singleton().(*makeVarsSingleton).varsForTesting
+ result := make([]MakeVarVariable, 0, len(vars))
+ for _, v := range vars {
+ if filter(v) {
+ result = append(result, v)
+ }
+ }
+
+ return result
+}
+
func (ctx *TestContext) Config() Config {
return ctx.config
}
@@ -1074,6 +1122,7 @@
}
func AndroidMkEntriesForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) []AndroidMkEntries {
+ t.Helper()
var p AndroidMkEntriesProvider
var ok bool
if p, ok = mod.(AndroidMkEntriesProvider); !ok {
@@ -1088,6 +1137,7 @@
}
func AndroidMkDataForTest(t *testing.T, ctx *TestContext, mod blueprint.Module) AndroidMkData {
+ t.Helper()
var p AndroidMkDataProvider
var ok bool
if p, ok = mod.(AndroidMkDataProvider); !ok {
diff --git a/android/variable.go b/android/variable.go
index 37ecab5..28f22c9 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -336,8 +336,7 @@
NamespacesToExport []string `json:",omitempty"`
- AfdoAdditionalProfileDirs []string `json:",omitempty"`
- PgoAdditionalProfileDirs []string `json:",omitempty"`
+ PgoAdditionalProfileDirs []string `json:",omitempty"`
VndkUseCoreVariant *bool `json:",omitempty"`
VndkSnapshotBuildArtifacts *bool `json:",omitempty"`
diff --git a/apex/apex.go b/apex/apex.go
index 2e54e7e..b1b4e47 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -17,13 +17,14 @@
package apex
import (
- "android/soong/bazel/cquery"
"fmt"
"path/filepath"
"regexp"
"sort"
"strings"
+ "android/soong/bazel/cquery"
+
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/proptools"
@@ -47,7 +48,7 @@
func registerApexBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("apex", BundleFactory)
- ctx.RegisterModuleType("apex_test", testApexBundleFactory)
+ ctx.RegisterModuleType("apex_test", TestApexBundleFactory)
ctx.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
ctx.RegisterModuleType("apex_defaults", defaultsFactory)
ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
@@ -224,7 +225,7 @@
// List of JNI libraries that are embedded inside this APEX.
Jni_libs []string
- // List of rust dyn libraries
+ // List of rust dyn libraries that are embedded inside this APEX.
Rust_dyn_libs []string
// List of native executables that are embedded inside this APEX.
@@ -235,6 +236,41 @@
// List of filesystem images that are embedded inside this APEX bundle.
Filesystems []string
+
+ // List of native libraries to exclude from this APEX.
+ Exclude_native_shared_libs []string
+
+ // List of JNI libraries to exclude from this APEX.
+ Exclude_jni_libs []string
+
+ // List of rust dyn libraries to exclude from this APEX.
+ Exclude_rust_dyn_libs []string
+
+ // List of native executables to exclude from this APEX.
+ Exclude_binaries []string
+
+ // List of native tests to exclude from this APEX.
+ Exclude_tests []string
+
+ // List of filesystem images to exclude from this APEX bundle.
+ Exclude_filesystems []string
+}
+
+// Merge combines another ApexNativeDependencies into this one
+func (a *ApexNativeDependencies) Merge(b ApexNativeDependencies) {
+ a.Native_shared_libs = append(a.Native_shared_libs, b.Native_shared_libs...)
+ a.Jni_libs = append(a.Jni_libs, b.Jni_libs...)
+ a.Rust_dyn_libs = append(a.Rust_dyn_libs, b.Rust_dyn_libs...)
+ a.Binaries = append(a.Binaries, b.Binaries...)
+ a.Tests = append(a.Tests, b.Tests...)
+ a.Filesystems = append(a.Filesystems, b.Filesystems...)
+
+ a.Exclude_native_shared_libs = append(a.Exclude_native_shared_libs, b.Exclude_native_shared_libs...)
+ a.Exclude_jni_libs = append(a.Exclude_jni_libs, b.Exclude_jni_libs...)
+ a.Exclude_rust_dyn_libs = append(a.Exclude_rust_dyn_libs, b.Exclude_rust_dyn_libs...)
+ a.Exclude_binaries = append(a.Exclude_binaries, b.Exclude_binaries...)
+ a.Exclude_tests = append(a.Exclude_tests, b.Exclude_tests...)
+ a.Exclude_filesystems = append(a.Exclude_filesystems, b.Exclude_filesystems...)
}
type apexMultilibProperties struct {
@@ -286,6 +322,9 @@
Arm64 struct {
ApexNativeDependencies
}
+ Riscv64 struct {
+ ApexNativeDependencies
+ }
X86 struct {
ApexNativeDependencies
}
@@ -416,9 +455,6 @@
// Processed file_contexts files
fileContexts android.WritablePath
- // Path to notice file in html.gz format.
- htmlGzNotice android.WritablePath
-
// The built APEX file. This is the main product.
// Could be .apex or .capex
outputFile android.WritablePath
@@ -671,12 +707,18 @@
// Use *FarVariation* to be able to depend on modules having conflicting variations with
// this module. This is required since arch variant of an APEX bundle is 'common' but it is
// 'arm' or 'arm64' for native shared libs.
- ctx.AddFarVariationDependencies(binVariations, executableTag, nativeModules.Binaries...)
- ctx.AddFarVariationDependencies(binVariations, testTag, nativeModules.Tests...)
- ctx.AddFarVariationDependencies(libVariations, jniLibTag, nativeModules.Jni_libs...)
- ctx.AddFarVariationDependencies(libVariations, sharedLibTag, nativeModules.Native_shared_libs...)
- ctx.AddFarVariationDependencies(rustLibVariations, sharedLibTag, nativeModules.Rust_dyn_libs...)
- ctx.AddFarVariationDependencies(target.Variations(), fsTag, nativeModules.Filesystems...)
+ ctx.AddFarVariationDependencies(binVariations, executableTag,
+ android.RemoveListFromList(nativeModules.Binaries, nativeModules.Exclude_binaries)...)
+ ctx.AddFarVariationDependencies(binVariations, testTag,
+ android.RemoveListFromList(nativeModules.Tests, nativeModules.Exclude_tests)...)
+ ctx.AddFarVariationDependencies(libVariations, jniLibTag,
+ android.RemoveListFromList(nativeModules.Jni_libs, nativeModules.Exclude_jni_libs)...)
+ ctx.AddFarVariationDependencies(libVariations, sharedLibTag,
+ android.RemoveListFromList(nativeModules.Native_shared_libs, nativeModules.Exclude_native_shared_libs)...)
+ ctx.AddFarVariationDependencies(rustLibVariations, sharedLibTag,
+ android.RemoveListFromList(nativeModules.Rust_dyn_libs, nativeModules.Exclude_rust_dyn_libs)...)
+ ctx.AddFarVariationDependencies(target.Variations(), fsTag,
+ android.RemoveListFromList(nativeModules.Filesystems, nativeModules.Exclude_filesystems)...)
}
func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
@@ -744,12 +786,12 @@
continue
}
- var depsList []ApexNativeDependencies
+ var deps ApexNativeDependencies
// Add native modules targeting both ABIs. When multilib.* is omitted for
// native_shared_libs/jni_libs/tests, it implies multilib.both
- depsList = append(depsList, a.properties.Multilib.Both)
- depsList = append(depsList, ApexNativeDependencies{
+ deps.Merge(a.properties.Multilib.Both)
+ deps.Merge(ApexNativeDependencies{
Native_shared_libs: a.properties.Native_shared_libs,
Tests: a.properties.Tests,
Jni_libs: a.properties.Jni_libs,
@@ -760,8 +802,8 @@
// binaries, it implies multilib.first
isPrimaryAbi := i == 0
if isPrimaryAbi {
- depsList = append(depsList, a.properties.Multilib.First)
- depsList = append(depsList, ApexNativeDependencies{
+ deps.Merge(a.properties.Multilib.First)
+ deps.Merge(ApexNativeDependencies{
Native_shared_libs: nil,
Tests: nil,
Jni_libs: nil,
@@ -772,32 +814,32 @@
// Add native modules targeting either 32-bit or 64-bit ABI
switch target.Arch.ArchType.Multilib {
case "lib32":
- depsList = append(depsList, a.properties.Multilib.Lib32)
- depsList = append(depsList, a.properties.Multilib.Prefer32)
+ deps.Merge(a.properties.Multilib.Lib32)
+ deps.Merge(a.properties.Multilib.Prefer32)
case "lib64":
- depsList = append(depsList, a.properties.Multilib.Lib64)
+ deps.Merge(a.properties.Multilib.Lib64)
if !has32BitTarget {
- depsList = append(depsList, a.properties.Multilib.Prefer32)
+ deps.Merge(a.properties.Multilib.Prefer32)
}
}
// Add native modules targeting a specific arch variant
switch target.Arch.ArchType {
case android.Arm:
- depsList = append(depsList, a.archProperties.Arch.Arm.ApexNativeDependencies)
+ deps.Merge(a.archProperties.Arch.Arm.ApexNativeDependencies)
case android.Arm64:
- depsList = append(depsList, a.archProperties.Arch.Arm64.ApexNativeDependencies)
+ deps.Merge(a.archProperties.Arch.Arm64.ApexNativeDependencies)
+ case android.Riscv64:
+ deps.Merge(a.archProperties.Arch.Riscv64.ApexNativeDependencies)
case android.X86:
- depsList = append(depsList, a.archProperties.Arch.X86.ApexNativeDependencies)
+ deps.Merge(a.archProperties.Arch.X86.ApexNativeDependencies)
case android.X86_64:
- depsList = append(depsList, a.archProperties.Arch.X86_64.ApexNativeDependencies)
+ deps.Merge(a.archProperties.Arch.X86_64.ApexNativeDependencies)
default:
panic(fmt.Errorf("unsupported arch %v\n", ctx.Arch().ArchType))
}
- for _, d := range depsList {
- addDependenciesForNativeModules(ctx, d, target, imageVariation)
- }
+ addDependenciesForNativeModules(ctx, deps, target, imageVariation)
ctx.AddFarVariationDependencies([]blueprint.Variation{
{Mutator: "os", Variation: target.OsVariation()},
{Mutator: "arch", Variation: target.ArchVariation()},
@@ -1559,7 +1601,7 @@
dirInApex = filepath.Join(dirInApex, "bionic")
}
- fileToCopy := ccMod.OutputFile().Path()
+ fileToCopy := android.OutputFileForModule(ctx, ccMod, "")
androidMkModuleName := ccMod.BaseModuleName() + ccMod.Properties.SubName
return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, ccMod)
}
@@ -1570,7 +1612,7 @@
dirInApex = filepath.Join(dirInApex, cc.Target().NativeBridgeRelativePath)
}
dirInApex = filepath.Join(dirInApex, cc.RelativeInstallPath())
- fileToCopy := cc.OutputFile().Path()
+ fileToCopy := android.OutputFileForModule(ctx, cc, "")
androidMkModuleName := cc.BaseModuleName() + cc.Properties.SubName
af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, cc)
af.symlinks = cc.Symlinks()
@@ -1583,7 +1625,7 @@
if rustm.Target().NativeBridge == android.NativeBridgeEnabled {
dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath)
}
- fileToCopy := rustm.OutputFile().Path()
+ fileToCopy := android.OutputFileForModule(ctx, rustm, "")
androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName
af := newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeExecutable, rustm)
return af
@@ -1602,7 +1644,7 @@
if rustm.Target().NativeBridge == android.NativeBridgeEnabled {
dirInApex = filepath.Join(dirInApex, rustm.Target().NativeBridgeRelativePath)
}
- fileToCopy := rustm.OutputFile().Path()
+ fileToCopy := android.OutputFileForModule(ctx, rustm, "")
androidMkModuleName := rustm.BaseModuleName() + rustm.Properties.SubName
return newApexFile(ctx, fileToCopy, androidMkModuleName, dirInApex, nativeSharedLib, rustm)
}
@@ -1848,24 +1890,22 @@
a.outputFile = a.outputApexFile
a.setCompression(ctx)
- a.publicKeyFile = android.PathForBazelOut(ctx, outputs.BundleKeyPair[0])
- a.privateKeyFile = android.PathForBazelOut(ctx, outputs.BundleKeyPair[1])
- a.containerCertificateFile = android.PathForBazelOut(ctx, outputs.ContainerKeyPair[0])
- a.containerPrivateKeyFile = android.PathForBazelOut(ctx, outputs.ContainerKeyPair[1])
+ // TODO(b/257829940): These are used by the apex_keys_text singleton; would probably be a clearer
+ // interface if these were set in a provider rather than the module itself
+ a.publicKeyFile = android.PathForBazelOut(ctx, outputs.BundleKeyInfo[0])
+ a.privateKeyFile = android.PathForBazelOut(ctx, outputs.BundleKeyInfo[1])
+ a.containerCertificateFile = android.PathForBazelOut(ctx, outputs.ContainerKeyInfo[0])
+ a.containerPrivateKeyFile = android.PathForBazelOut(ctx, outputs.ContainerKeyInfo[1])
+
apexType := a.properties.ApexType
switch apexType {
case imageApex:
- // TODO(asmundak): Bazel does not create these files yet.
- // b/190817312
- a.htmlGzNotice = android.PathForBazelOut(ctx, "NOTICE.html.gz")
- // b/239081457
- a.bundleModuleFile = android.PathForBazelOut(ctx, a.Name()+apexType.suffix()+"-base.zip")
- // b/239081455
- a.nativeApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, a.Name()+"_using.txt"))
- // b/239081456
- a.nativeApisBackedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, a.Name()+"_backing.txt"))
- // b/239084755
- a.javaApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, a.Name()+"_using.xml"))
+ a.bundleModuleFile = android.PathForBazelOut(ctx, outputs.BundleFile)
+ a.nativeApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.SymbolsUsedByApex))
+ a.nativeApisBackedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.BackingLibs))
+ // TODO(b/239084755): Generate the java api using.xml file from Bazel.
+ a.javaApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.JavaSymbolsUsedByApex))
+ a.installedFilesFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.InstalledFiles))
installSuffix := imageApexSuffix
if a.isCompressed {
installSuffix = imageCapexSuffix
@@ -2261,7 +2301,7 @@
//
// Always include if we are a host-apex however since those won't have any
// system libraries.
- if !am.DirectlyInAnyApex() {
+ if ch.IsStubsImplementationRequired() && !am.DirectlyInAnyApex() {
// we need a module name for Make
name := ch.ImplementationModuleNameForMake(ctx) + ch.Properties.SubName
if !android.InList(name, a.requiredDeps) {
@@ -2462,7 +2502,8 @@
filesToAdd = append(filesToAdd, *af)
}
- if pathInApex := bootclasspathFragmentInfo.ProfileInstallPathInApex(); pathInApex != "" {
+ pathInApex := bootclasspathFragmentInfo.ProfileInstallPathInApex()
+ if pathInApex != "" && !java.SkipDexpreoptBootJars(ctx) {
pathOnHost := bootclasspathFragmentInfo.ProfilePathOnHost()
tempPath := android.PathForModuleOut(ctx, "boot_image_profile", pathInApex)
@@ -2558,7 +2599,7 @@
// apex_test is an APEX for testing. The difference from the ordinary apex module type is that
// certain compatibility checks such as apex_available are not done for apex_test.
-func testApexBundleFactory() android.Module {
+func TestApexBundleFactory() android.Module {
bundle := newApexBundle()
bundle.testApex = true
return bundle
@@ -2587,6 +2628,7 @@
module.AddProperties(
&apexBundleProperties{},
&apexTargetBundleProperties{},
+ &apexArchBundleProperties{},
&overridableProperties{},
)
@@ -2659,9 +2701,14 @@
}
// Certificate
- if overridableProperties.Certificate != nil {
+ if overridableProperties.Certificate == nil {
+ // If overridableProperties.Certificate is nil, clear this out as
+ // well with zeroed structs, so the override_apex does not use the
+ // base apex's certificate.
attrs.Certificate = bazel.LabelAttribute{}
- attrs.Certificate.SetValue(android.BazelLabelForModuleDepSingle(ctx, *overridableProperties.Certificate))
+ attrs.Certificate_name = bazel.StringAttribute{}
+ } else {
+ attrs.Certificate, attrs.Certificate_name = android.BazelStringOrLabelFromProp(ctx, overridableProperties.Certificate)
}
// Prebuilts
@@ -2726,16 +2773,18 @@
// Only override the minSdkVersion value on Apexes which already specify
// a min_sdk_version (it's optional for non-updatable apexes), and that its
// min_sdk_version value is lower than the one to override with.
- overrideMinSdkValue := ctx.DeviceConfig().ApexGlobalMinSdkVersionOverride()
- overrideApiLevel := minSdkVersionFromValue(ctx, overrideMinSdkValue)
- originalMinApiLevel := minSdkVersionFromValue(ctx, proptools.String(a.properties.Min_sdk_version))
- isMinSdkSet := a.properties.Min_sdk_version != nil
- isOverrideValueHigher := overrideApiLevel.CompareTo(originalMinApiLevel) > 0
- if overrideMinSdkValue != "" && isMinSdkSet && isOverrideValueHigher {
- return overrideMinSdkValue
+ minApiLevel := minSdkVersionFromValue(ctx, proptools.String(a.properties.Min_sdk_version))
+ if minApiLevel.IsNone() {
+ return ""
}
- return proptools.String(a.properties.Min_sdk_version)
+ overrideMinSdkValue := ctx.DeviceConfig().ApexGlobalMinSdkVersionOverride()
+ overrideApiLevel := minSdkVersionFromValue(ctx, overrideMinSdkValue)
+ if !overrideApiLevel.IsNone() && overrideApiLevel.CompareTo(minApiLevel) > 0 {
+ minApiLevel = overrideApiLevel
+ }
+
+ return minApiLevel.String()
}
// Returns apex's min_sdk_version SdkSpec, honoring overrides
@@ -3335,7 +3384,8 @@
Android_manifest bazel.LabelAttribute
File_contexts bazel.LabelAttribute
Key bazel.LabelAttribute
- Certificate bazel.LabelAttribute
+ Certificate bazel.LabelAttribute // used when the certificate prop is a module
+ Certificate_name bazel.StringAttribute // used when the certificate prop is a string
Min_sdk_version *string
Updatable bazel.BoolAttribute
Installable bazel.BoolAttribute
@@ -3346,6 +3396,7 @@
Compressible bazel.BoolAttribute
Package_name *string
Logging_parent *string
+ Tests bazel.LabelListAttribute
}
type convertedNativeSharedLibs struct {
@@ -3355,13 +3406,19 @@
// ConvertWithBp2build performs bp2build conversion of an apex
func (a *apexBundle) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- // We do not convert apex_test modules at this time
- if ctx.ModuleType() != "apex" {
+ // We only convert apex and apex_test modules at this time
+ if ctx.ModuleType() != "apex" && ctx.ModuleType() != "apex_test" {
return
}
attrs, props := convertWithBp2build(a, ctx)
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: a.Name()}, &attrs)
+ commonAttrs := android.CommonAttributes{
+ Name: a.Name(),
+ }
+ if a.testApex {
+ commonAttrs.Testonly = proptools.BoolPtr(a.testApex)
+ }
+ ctx.CreateBazelTargetModule(props, commonAttrs, &attrs)
}
func convertWithBp2build(a *apexBundle, ctx android.TopDownMutatorContext) (bazelApexBundleAttributes, bazel.BazelTargetModuleProperties) {
@@ -3397,16 +3454,19 @@
keyLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *a.overridableProperties.Key))
}
- var certificateLabelAttribute bazel.LabelAttribute
- if a.overridableProperties.Certificate != nil {
- certificateLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *a.overridableProperties.Certificate))
- }
+ // Certificate
+ certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableProperties.Certificate)
nativeSharedLibs := &convertedNativeSharedLibs{
Native_shared_libs_32: bazel.LabelListAttribute{},
Native_shared_libs_64: bazel.LabelListAttribute{},
}
- compileMultilib := "both"
+
+ // https://cs.android.com/android/platform/superproject/+/master:build/soong/android/arch.go;l=698;drc=f05b0d35d2fbe51be9961ce8ce8031f840295c68
+ // https://cs.android.com/android/platform/superproject/+/master:build/soong/apex/apex.go;l=2549;drc=ec731a83e3e2d80a1254e32fd4ad7ef85e262669
+ // In Soong, decodeMultilib, used to get multilib, return "first" if defaultMultilib is set to "common".
+ // Since apex sets defaultMultilib to be "common", equivalent compileMultilib in bp2build for apex should be "first"
+ compileMultilib := "first"
if a.CompileMultilib() != nil {
compileMultilib = *a.CompileMultilib()
}
@@ -3425,6 +3485,12 @@
binaries := android.BazelLabelForModuleDeps(ctx, a.properties.ApexNativeDependencies.Binaries)
binariesLabelListAttribute := bazel.MakeLabelListAttribute(binaries)
+ var testsAttrs bazel.LabelListAttribute
+ if a.testApex && len(a.properties.ApexNativeDependencies.Tests) > 0 {
+ tests := android.BazelLabelForModuleDeps(ctx, a.properties.ApexNativeDependencies.Tests)
+ testsAttrs = bazel.MakeLabelListAttribute(tests)
+ }
+
var updatableAttribute bazel.BoolAttribute
if a.properties.Updatable != nil {
updatableAttribute.Value = a.properties.Updatable
@@ -3456,7 +3522,8 @@
File_contexts: fileContextsLabelAttribute,
Min_sdk_version: minSdkVersion,
Key: keyLabelAttribute,
- Certificate: certificateLabelAttribute,
+ Certificate: certificate,
+ Certificate_name: certificateName,
Updatable: updatableAttribute,
Installable: installableAttribute,
Native_shared_libs_32: nativeSharedLibs.Native_shared_libs_32,
@@ -3466,6 +3533,7 @@
Compressible: compressibleAttribute,
Package_name: packageName,
Logging_parent: loggingParent,
+ Tests: testsAttrs,
}
props := bazel.BazelTargetModuleProperties{
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 7ae9ed7..883c3c8 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -16,7 +16,6 @@
import (
"fmt"
- "os"
"path"
"path/filepath"
"reflect"
@@ -30,6 +29,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/bazel/cquery"
"android/soong/bpf"
"android/soong/cc"
"android/soong/dexpreopt"
@@ -2191,6 +2191,38 @@
`)
}
+func TestApexMinSdkVersion_MinApiForArch(t *testing.T) {
+ // Tests that an apex dependency with min_sdk_version higher than the
+ // min_sdk_version of the apex is allowed as long as the dependency's
+ // min_sdk_version is less than or equal to the api level that the
+ // architecture was introduced in. In this case, arm64 didn't exist
+ // until api level 21, so the arm64 code will never need to run on
+ // an api level 20 device, even if other architectures of the apex
+ // will.
+ testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ min_sdk_version: "20",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ srcs: ["mylib.cpp"],
+ apex_available: ["myapex"],
+ min_sdk_version: "21",
+ stl: "none",
+ }
+ `)
+}
+
func TestJavaStableSdkVersion(t *testing.T) {
testCases := []struct {
name string
@@ -4098,6 +4130,76 @@
ensureNotContains(t, androidMk, "LOCAL_MODULE := mylib.com.android.myapex\n")
}
+func TestCompileMultilibProp(t *testing.T) {
+ testCases := []struct {
+ compileMultiLibProp string
+ containedLibs []string
+ notContainedLibs []string
+ }{
+ {
+ containedLibs: []string{
+ "image.apex/lib64/mylib.so",
+ "image.apex/lib/mylib.so",
+ },
+ compileMultiLibProp: `compile_multilib: "both",`,
+ },
+ {
+ containedLibs: []string{"image.apex/lib64/mylib.so"},
+ notContainedLibs: []string{"image.apex/lib/mylib.so"},
+ compileMultiLibProp: `compile_multilib: "first",`,
+ },
+ {
+ containedLibs: []string{"image.apex/lib64/mylib.so"},
+ notContainedLibs: []string{"image.apex/lib/mylib.so"},
+ // compile_multilib, when unset, should result to the same output as when compile_multilib is "first"
+ },
+ {
+ containedLibs: []string{"image.apex/lib64/mylib.so"},
+ notContainedLibs: []string{"image.apex/lib/mylib.so"},
+ compileMultiLibProp: `compile_multilib: "64",`,
+ },
+ {
+ containedLibs: []string{"image.apex/lib/mylib.so"},
+ notContainedLibs: []string{"image.apex/lib64/mylib.so"},
+ compileMultiLibProp: `compile_multilib: "32",`,
+ },
+ }
+ for _, testCase := range testCases {
+ ctx := testApex(t, fmt.Sprintf(`
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ %s
+ native_shared_libs: ["mylib"],
+ updatable: false,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ apex_available: [
+ "//apex_available:platform",
+ "myapex",
+ ],
+ }
+ `, testCase.compileMultiLibProp),
+ )
+ module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+ apexRule := module.Rule("apexRule")
+ copyCmds := apexRule.Args["copy_commands"]
+ for _, containedLib := range testCase.containedLibs {
+ ensureContains(t, copyCmds, containedLib)
+ }
+ for _, notContainedLib := range testCase.notContainedLibs {
+ ensureNotContains(t, copyCmds, notContainedLib)
+ }
+ }
+}
+
func TestNonTestApex(t *testing.T) {
ctx := testApex(t, `
apex {
@@ -4297,12 +4399,15 @@
name: "myapex",
key: "myapex.key",
updatable: false,
+ native_shared_libs: ["mylib.generic"],
arch: {
arm64: {
native_shared_libs: ["mylib.arm64"],
+ exclude_native_shared_libs: ["mylib.generic"],
},
x86_64: {
native_shared_libs: ["mylib.x64"],
+ exclude_native_shared_libs: ["mylib.generic"],
},
}
}
@@ -4314,6 +4419,18 @@
}
cc_library {
+ name: "mylib.generic",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ // TODO: remove //apex_available:platform
+ apex_available: [
+ "//apex_available:platform",
+ "myapex",
+ ],
+ }
+
+ cc_library {
name: "mylib.arm64",
srcs: ["mylib.cpp"],
system_shared_libs: [],
@@ -4343,6 +4460,7 @@
// Ensure that apex variant is created for the direct dep
ensureListContains(t, ctx.ModuleVariantsForTests("mylib.arm64"), "android_arm64_armv8-a_shared_apex10000")
+ ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib.generic"), "android_arm64_armv8-a_shared_apex10000")
ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib.x64"), "android_arm64_armv8-a_shared_apex10000")
// Ensure that both direct and indirect deps are copied into apex
@@ -7235,12 +7353,13 @@
ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
s := mod.Rule("apexRule").Args["copy_commands"]
copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
- if len(copyCmds) != 3 {
- t.Fatalf("Expected 3 commands, got %d in:\n%s", len(copyCmds), s)
+ if len(copyCmds) != 4 {
+ t.Fatalf("Expected 4 commands, got %d in:\n%s", len(copyCmds), s)
}
ensureMatches(t, copyCmds[0], "^rm -rf .*/app/AppSet@TEST.BUILD_ID$")
ensureMatches(t, copyCmds[1], "^mkdir -p .*/app/AppSet@TEST.BUILD_ID$")
- ensureMatches(t, copyCmds[2], "^unzip .*-d .*/app/AppSet@TEST.BUILD_ID .*/AppSet.zip$")
+ ensureMatches(t, copyCmds[2], "^cp -f .*/app/AppSet@TEST.BUILD_ID/AppSet.apk$")
+ ensureMatches(t, copyCmds[3], "^unzip .*-d .*/app/AppSet@TEST.BUILD_ID .*/AppSet.zip$")
// Ensure that canned_fs_config has an entry for the app set zip file
generateFsRule := mod.Rule("generateFsConfig")
@@ -8294,6 +8413,30 @@
}
}
+func TestApexSet_NativeBridge(t *testing.T) {
+ ctx := testApex(t, `
+ apex_set {
+ name: "myapex",
+ set: "myapex.apks",
+ filename: "foo_v2.apex",
+ overrides: ["foo"],
+ }
+ `,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.Targets[android.Android] = []android.Target{
+ {Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "", Abi: []string{"x86_64"}}},
+ {Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeEnabled},
+ }
+ }),
+ )
+
+ m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
+
+ // Check extract_apks tool parameters. No native bridge arch expected
+ extractedApex := m.Output("extracted/myapex.apks")
+ android.AssertStringEquals(t, "abis", "X86_64", extractedApex.Args["abis"])
+}
+
func TestNoStaticLinkingToStubsLib(t *testing.T) {
testApexError(t, `.*required by "mylib" is a native library providing stub.*`, `
apex {
@@ -9627,6 +9770,94 @@
android.AssertBoolEquals(t, "core variant should link against source libc", true, hasDep(libfooCoreVariant, libcCoreVariant))
}
-func TestMain(m *testing.M) {
- os.Exit(m.Run())
+func TestApexImageInMixedBuilds(t *testing.T) {
+ bp := `
+apex_key{
+ name: "foo_key",
+}
+apex {
+ name: "foo",
+ key: "foo_key",
+ updatable: true,
+ min_sdk_version: "31",
+ file_contexts: ":myapex-file_contexts",
+ bazel_module: { label: "//:foo" },
+}`
+
+ outputBaseDir := "out/bazel"
+ result := android.GroupFixturePreparers(
+ prepareForApexTest,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: outputBaseDir,
+ LabelToApexInfo: map[string]cquery.ApexInfo{
+ "//:foo": cquery.ApexInfo{
+ SignedOutput: "signed_out.apex",
+ UnsignedOutput: "unsigned_out.apex",
+ BundleKeyInfo: []string{"public_key", "private_key"},
+ ContainerKeyInfo: []string{"container_cert", "container_private"},
+ SymbolsUsedByApex: "foo_using.txt",
+ JavaSymbolsUsedByApex: "foo_using.xml",
+ BundleFile: "apex_bundle.zip",
+ InstalledFiles: "installed-files.txt",
+
+ // unused
+ PackageName: "pkg_name",
+ ProvidesLibs: []string{"a", "b"},
+ RequiresLibs: []string{"c", "d"},
+ },
+ },
+ }
+ }),
+ ).RunTestWithBp(t, bp)
+
+ m := result.ModuleForTests("foo", "android_common_foo_image").Module()
+ ab, ok := m.(*apexBundle)
+ if !ok {
+ t.Fatalf("Expected module to be an apexBundle, was not")
+ }
+
+ if w, g := "out/bazel/execroot/__main__/public_key", ab.publicKeyFile.String(); w != g {
+ t.Errorf("Expected public key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/private_key", ab.privateKeyFile.String(); w != g {
+ t.Errorf("Expected private key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/container_cert", ab.containerCertificateFile.String(); w != g {
+ t.Errorf("Expected public container key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/container_private", ab.containerPrivateKeyFile.String(); w != g {
+ t.Errorf("Expected private container key %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/signed_out.apex", ab.outputFile.String(); w != g {
+ t.Errorf("Expected output file %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/foo_using.txt", ab.nativeApisUsedByModuleFile.String(); w != g {
+ t.Errorf("Expected output file %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/foo_using.xml", ab.javaApisUsedByModuleFile.String(); w != g {
+ t.Errorf("Expected output file %q, got %q", w, g)
+ }
+
+ if w, g := "out/bazel/execroot/__main__/installed-files.txt", ab.installedFilesFile.String(); w != g {
+ t.Errorf("Expected installed-files.txt %q, got %q", w, g)
+ }
+
+ mkData := android.AndroidMkDataForTest(t, result.TestContext, m)
+ var builder strings.Builder
+ mkData.Custom(&builder, "foo", "BAZEL_TARGET_", "", mkData)
+
+ data := builder.String()
+ if w := "ALL_MODULES.$(my_register_name).BUNDLE := out/bazel/execroot/__main__/apex_bundle.zip"; !strings.Contains(data, w) {
+ t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
+ }
+ if w := "$(call dist-for-goals,checkbuild,out/bazel/execroot/__main__/installed-files.txt:foo-installed-files.txt)"; !strings.Contains(data, w) {
+ t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
+ }
}
diff --git a/apex/builder.go b/apex/builder.go
index cb09e35..9e368b6 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -459,8 +459,13 @@
pathOnDevice := filepath.Join("/system", fi.path())
copyCommands = append(copyCommands, "ln -sfn "+pathOnDevice+" "+destPath)
} else {
+ // Copy the file into APEX
+ copyCommands = append(copyCommands, "cp -f "+fi.builtFile.String()+" "+destPath)
+
var installedPath android.InstallPath
if fi.class == appSet {
+ // In case of AppSet, we need to copy additional APKs as well. They
+ // are zipped. So we need to unzip them.
copyCommands = append(copyCommands,
fmt.Sprintf("unzip -qDD -d %s %s", destPathDir,
fi.module.(*java.AndroidAppSet).PackedAdditionalOutputs().String()))
@@ -469,7 +474,6 @@
fi.stem(), fi.builtFile, fi.module.(*java.AndroidAppSet).PackedAdditionalOutputs())
}
} else {
- copyCommands = append(copyCommands, "cp -f "+fi.builtFile.String()+" "+destPath)
if installSymbolFiles {
installedPath = ctx.InstallFile(pathWhenActivated.Join(ctx, fi.installDir), fi.stem(), fi.builtFile)
}
@@ -646,9 +650,9 @@
}
// Create a NOTICE file, and embed it as an asset file in the APEX.
- a.htmlGzNotice = android.PathForModuleOut(ctx, "NOTICE.html.gz")
+ htmlGzNotice := android.PathForModuleOut(ctx, "NOTICE.html.gz")
android.BuildNoticeHtmlOutputFromLicenseMetadata(
- ctx, a.htmlGzNotice, "", "",
+ ctx, htmlGzNotice, "", "",
[]string{
android.PathForModuleInstall(ctx).String() + "/",
android.PathForModuleInPartitionInstall(ctx, "apex").String() + "/",
@@ -656,7 +660,7 @@
noticeAssetPath := android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
builder := android.NewRuleBuilder(pctx, ctx)
builder.Command().Text("cp").
- Input(a.htmlGzNotice).
+ Input(htmlGzNotice).
Output(noticeAssetPath)
builder.Build("notice_dir", "Building notice dir")
implicitInputs = append(implicitInputs, noticeAssetPath)
@@ -918,10 +922,16 @@
installedSymlinks = append(installedSymlinks,
ctx.InstallAbsoluteSymlink(installDir, fi.stem(), pathOnDevice))
} else {
- target := ctx.InstallFile(installDir, fi.stem(), fi.builtFile)
- for _, sym := range fi.symlinks {
- installedSymlinks = append(installedSymlinks,
- ctx.InstallSymlink(installDir, sym, target))
+ if fi.class == appSet {
+ as := fi.module.(*java.AndroidAppSet)
+ ctx.InstallFileWithExtraFilesZip(installDir, as.BaseModuleName()+".apk",
+ as.OutputFile(), as.PackedAdditionalOutputs())
+ } else {
+ target := ctx.InstallFile(installDir, fi.stem(), fi.builtFile)
+ for _, sym := range fi.symlinks {
+ installedSymlinks = append(installedSymlinks,
+ ctx.InstallSymlink(installDir, sym, target))
+ }
}
}
}
@@ -1086,6 +1096,9 @@
executablePaths = append(executablePaths, filepath.Join(f.installDir, s))
}
} else if f.class == appSet {
+ // base APK
+ readOnlyPaths = append(readOnlyPaths, pathInApex)
+ // Additional APKs
appSetDirs = append(appSetDirs, f.installDir)
appSetFiles[f.installDir] = f.module.(*java.AndroidAppSet).PackedAdditionalOutputs()
} else {
diff --git a/apex/key.go b/apex/key.go
index d449589..0a7e80f 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -44,8 +44,6 @@
publicKeyFile android.Path
privateKeyFile android.Path
-
- keyName string
}
type apexKeyProperties struct {
@@ -102,7 +100,6 @@
m.publicKeyFile.String(), pubKeyName, m.privateKeyFile, privKeyName)
return
}
- m.keyName = pubKeyName
}
// //////////////////////////////////////////////////////////////////////
@@ -203,8 +200,11 @@
// For Bazel / bp2build
type bazelApexKeyAttributes struct {
- Public_key bazel.LabelAttribute
- Private_key bazel.LabelAttribute
+ Public_key bazel.LabelAttribute
+ Public_key_name bazel.StringAttribute
+
+ Private_key bazel.LabelAttribute
+ Private_key_name bazel.StringAttribute
}
// ConvertWithBp2build performs conversion apexKey for bp2build
@@ -213,19 +213,18 @@
}
func apexKeyBp2BuildInternal(ctx android.TopDownMutatorContext, module *apexKey) {
- var privateKeyLabelAttribute bazel.LabelAttribute
- if module.properties.Private_key != nil {
- privateKeyLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *module.properties.Private_key))
- }
+ privateKeyLabelAttribute, privateKeyNameAttribute :=
+ android.BazelStringOrLabelFromProp(ctx, module.properties.Private_key)
- var publicKeyLabelAttribute bazel.LabelAttribute
- if module.properties.Public_key != nil {
- publicKeyLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *module.properties.Public_key))
- }
+ publicKeyLabelAttribute, publicKeyNameAttribute :=
+ android.BazelStringOrLabelFromProp(ctx, module.properties.Public_key)
attrs := &bazelApexKeyAttributes{
- Private_key: privateKeyLabelAttribute,
- Public_key: publicKeyLabelAttribute,
+ Private_key: privateKeyLabelAttribute,
+ Private_key_name: privateKeyNameAttribute,
+
+ Public_key: publicKeyLabelAttribute,
+ Public_key_name: publicKeyNameAttribute,
}
props := bazel.BazelTargetModuleProperties{
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 25ae5bf..6fdd50a 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -24,6 +24,7 @@
"android/soong/android"
"android/soong/java"
"android/soong/provenance"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -500,6 +501,9 @@
Arm64 struct {
Src *string `android:"path"`
}
+ Riscv64 struct {
+ Src *string `android:"path"`
+ }
X86 struct {
Src *string `android:"path"`
}
@@ -527,6 +531,12 @@
src = String(p.Arch.Arm.Src)
case android.Arm64:
src = String(p.Arch.Arm64.Src)
+ case android.Riscv64:
+ src = String(p.Arch.Riscv64.Src)
+ // HACK: fall back to arm64 prebuilts, the riscv64 ones don't exist yet.
+ if src == "" {
+ src = String(p.Arch.Arm64.Src)
+ }
case android.X86:
src = String(p.Arch.X86.Src)
case android.X86_64:
@@ -537,7 +547,11 @@
}
if src == "" {
- ctx.OtherModuleErrorf(prebuilt, "prebuilt_apex does not support %q", multiTargets[0].Arch.String())
+ if ctx.Config().AllowMissingDependencies() {
+ ctx.AddMissingDependencies([]string{ctx.OtherModuleName(prebuilt)})
+ } else {
+ ctx.OtherModuleErrorf(prebuilt, "prebuilt_apex does not support %q", multiTargets[0].Arch.String())
+ }
// Drop through to return an empty string as the src (instead of nil) to avoid the prebuilt
// logic from reporting a more general, less useful message.
}
@@ -818,6 +832,8 @@
}
apexSet := android.SingleSourcePathFromSupplier(ctx, srcsSupplier, "set")
p.extractedApex = android.PathForModuleOut(ctx, "extracted", apexSet.Base())
+ // Filter out NativeBridge archs (b/260115309)
+ abis := java.SupportedAbis(ctx, true)
ctx.Build(pctx,
android.BuildParams{
Rule: extractMatchingApex,
@@ -825,7 +841,7 @@
Inputs: android.Paths{apexSet},
Output: p.extractedApex,
Args: map[string]string{
- "abis": strings.Join(java.SupportedAbis(ctx), ","),
+ "abis": strings.Join(abis, ","),
"allow-prereleased": strconv.FormatBool(proptools.Bool(p.properties.Prerelease)),
"sdk-version": ctx.Config().PlatformSdkVersion().String(),
},
diff --git a/bazel/Android.bp b/bazel/Android.bp
index 9e7edc7..d11c78b 100644
--- a/bazel/Android.bp
+++ b/bazel/Android.bp
@@ -20,6 +20,7 @@
"soong_build",
],
deps: [
+ "bazel_analysis_v2_proto",
"blueprint",
],
}
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 05f6ed4..bc823b3 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -17,7 +17,6 @@
import (
"crypto/sha256"
"encoding/base64"
- "encoding/json"
"fmt"
"path/filepath"
"reflect"
@@ -25,6 +24,8 @@
"strings"
"github.com/google/blueprint/proptools"
+ "google.golang.org/protobuf/proto"
+ analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
)
type artifactId int
@@ -312,11 +313,79 @@
// BuildStatements are one-to-one with actions in the given action graph, and AqueryDepsets
// are one-to-one with Bazel's depSetOfFiles objects.
func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, []AqueryDepset, error) {
- var aqueryResult actionGraphContainer
- err := json.Unmarshal(aqueryJsonProto, &aqueryResult)
+ aqueryProto := &analysis_v2_proto.ActionGraphContainer{}
+ err := proto.Unmarshal(aqueryJsonProto, aqueryProto)
if err != nil {
return nil, nil, err
}
+ aqueryResult := actionGraphContainer{}
+
+ for _, protoArtifact := range aqueryProto.Artifacts {
+ aqueryResult.Artifacts = append(aqueryResult.Artifacts, artifact{artifactId(protoArtifact.Id),
+ pathFragmentId(protoArtifact.PathFragmentId)})
+ }
+
+ for _, protoAction := range aqueryProto.Actions {
+ var environmentVariable []KeyValuePair
+ var inputDepSetIds []depsetId
+ var outputIds []artifactId
+ var substitutions []KeyValuePair
+
+ for _, protoEnvironmentVariable := range protoAction.EnvironmentVariables {
+ environmentVariable = append(environmentVariable, KeyValuePair{
+ protoEnvironmentVariable.Key, protoEnvironmentVariable.Value,
+ })
+ }
+ for _, protoInputDepSetIds := range protoAction.InputDepSetIds {
+ inputDepSetIds = append(inputDepSetIds, depsetId(protoInputDepSetIds))
+ }
+ for _, protoOutputIds := range protoAction.OutputIds {
+ outputIds = append(outputIds, artifactId(protoOutputIds))
+ }
+ for _, protoSubstitutions := range protoAction.Substitutions {
+ substitutions = append(substitutions, KeyValuePair{
+ protoSubstitutions.Key, protoSubstitutions.Value,
+ })
+ }
+
+ aqueryResult.Actions = append(aqueryResult.Actions,
+ action{
+ Arguments: protoAction.Arguments,
+ EnvironmentVariables: environmentVariable,
+ InputDepSetIds: inputDepSetIds,
+ Mnemonic: protoAction.Mnemonic,
+ OutputIds: outputIds,
+ TemplateContent: protoAction.TemplateContent,
+ Substitutions: substitutions,
+ FileContents: protoAction.FileContents})
+ }
+
+ for _, protoDepSetOfFiles := range aqueryProto.DepSetOfFiles {
+ var directArtifactIds []artifactId
+ var transitiveDepSetIds []depsetId
+
+ for _, protoDirectArtifactIds := range protoDepSetOfFiles.DirectArtifactIds {
+ directArtifactIds = append(directArtifactIds, artifactId(protoDirectArtifactIds))
+ }
+ for _, protoTransitiveDepSetIds := range protoDepSetOfFiles.TransitiveDepSetIds {
+ transitiveDepSetIds = append(transitiveDepSetIds, depsetId(protoTransitiveDepSetIds))
+ }
+ aqueryResult.DepSetOfFiles = append(aqueryResult.DepSetOfFiles,
+ depSetOfFiles{
+ Id: depsetId(protoDepSetOfFiles.Id),
+ DirectArtifactIds: directArtifactIds,
+ TransitiveDepSetIds: transitiveDepSetIds})
+
+ }
+
+ for _, protoPathFragments := range aqueryProto.PathFragments {
+ aqueryResult.PathFragments = append(aqueryResult.PathFragments,
+ pathFragment{
+ Id: pathFragmentId(protoPathFragments.Id),
+ Label: protoPathFragments.Label,
+ ParentId: pathFragmentId(protoPathFragments.ParentId)})
+
+ }
aqueryHandler, err := newAqueryHandler(aqueryResult)
if err != nil {
return nil, nil, err
diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go
index 5810364..2eacafa 100644
--- a/bazel/aquery_test.go
+++ b/bazel/aquery_test.go
@@ -15,118 +15,128 @@
package bazel
import (
+ "encoding/json"
"fmt"
"reflect"
"sort"
"testing"
+
+ "google.golang.org/protobuf/proto"
+ analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
)
func TestAqueryMultiArchGenrule(t *testing.T) {
// 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 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "ab53f6ecbdc2ee8cb8812613b63205464f1f5083f6dca87081a0a398c0f1ecf7",
- "mnemonic": "Genrule",
- "configurationId": 1,
- "arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py arm ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-arm.S"],
- "environmentVariables": [{
- "key": "PATH",
- "value": "/bin:/usr/bin:/usr/local/bin"
- }],
- "inputDepSetIds": [1],
- "outputIds": [4],
- "primaryOutputId": 4
- }, {
- "targetId": 2,
- "actionKey": "9f4309ce165dac458498cb92811c18b0b7919782cc37b82a42d2141b8cc90826",
- "mnemonic": "Genrule",
- "configurationId": 1,
- "arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py x86 ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-x86.S"],
- "environmentVariables": [{
- "key": "PATH",
- "value": "/bin:/usr/bin:/usr/local/bin"
- }],
- "inputDepSetIds": [2],
- "outputIds": [5],
- "primaryOutputId": 5
- }, {
- "targetId": 3,
- "actionKey": "50d6c586103ebeed3a218195540bcc30d329464eae36377eb82f8ce7c36ac342",
- "mnemonic": "Genrule",
- "configurationId": 1,
- "arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py x86_64 ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-x86_64.S"],
- "environmentVariables": [{
- "key": "PATH",
- "value": "/bin:/usr/bin:/usr/local/bin"
- }],
- "inputDepSetIds": [3],
- "outputIds": [6],
- "primaryOutputId": 6
- }, {
- "targetId": 4,
- "actionKey": "f30cbe442f5216f4223cf16a39112cad4ec56f31f49290d85cff587e48647ffa",
- "mnemonic": "Genrule",
- "configurationId": 1,
- "arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py arm64 ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-arm64.S"],
- "environmentVariables": [{
- "key": "PATH",
- "value": "/bin:/usr/bin:/usr/local/bin"
- }],
- "inputDepSetIds": [4],
- "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] }],
- "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 }]
-}`
- actualbuildStatements, actualDepsets, _ := AqueryBuildStatements([]byte(inputString))
+ "Artifacts": [
+ { "Id": 1, "path_fragment_id": 1 },
+ { "Id": 2, "path_fragment_id": 6 },
+ { "Id": 3, "path_fragment_id": 8 },
+ { "Id": 4, "path_fragment_id": 12 },
+ { "Id": 5, "path_fragment_id": 19 },
+ { "Id": 6, "path_fragment_id": 20 },
+ { "Id": 7, "path_fragment_id": 21 }],
+ "Actions": [{
+ "target_id": 1,
+ "action_key": "ab53f6ecbdc2ee8cb8812613b63205464f1f5083f6dca87081a0a398c0f1ecf7",
+ "Mnemonic": "Genrule",
+ "configuration_id": 1,
+ "Arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py arm ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-arm.S"],
+ "environment_variables": [{
+ "Key": "PATH",
+ "Value": "/bin:/usr/bin:/usr/local/bin"
+ }],
+ "input_dep_set_ids": [1],
+ "output_ids": [4],
+ "primary_output_id": 4
+ }, {
+ "target_id": 2,
+ "action_key": "9f4309ce165dac458498cb92811c18b0b7919782cc37b82a42d2141b8cc90826",
+ "Mnemonic": "Genrule",
+ "configuration_id": 1,
+ "Arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py x86 ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-x86.S"],
+ "environment_variables": [{
+ "Key": "PATH",
+ "Value": "/bin:/usr/bin:/usr/local/bin"
+ }],
+ "input_dep_set_ids": [2],
+ "output_ids": [5],
+ "primary_output_id": 5
+ }, {
+ "target_id": 3,
+ "action_key": "50d6c586103ebeed3a218195540bcc30d329464eae36377eb82f8ce7c36ac342",
+ "Mnemonic": "Genrule",
+ "configuration_id": 1,
+ "Arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py x86_64 ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-x86_64.S"],
+ "environment_variables": [{
+ "Key": "PATH",
+ "Value": "/bin:/usr/bin:/usr/local/bin"
+ }],
+ "input_dep_set_ids": [3],
+ "output_ids": [6],
+ "primary_output_id": 6
+ }, {
+ "target_id": 4,
+ "action_key": "f30cbe442f5216f4223cf16a39112cad4ec56f31f49290d85cff587e48647ffa",
+ "Mnemonic": "Genrule",
+ "configuration_id": 1,
+ "Arguments": ["/bin/bash", "-c", "source ../bazel_tools/tools/genrule/genrule-setup.sh; ../sourceroot/bionic/libc/tools/gensyscalls.py arm64 ../sourceroot/bionic/libc/SYSCALLS.TXT \u003e bazel-out/sourceroot/k8-fastbuild/bin/bionic/libc/syscalls-arm64.S"],
+ "environment_variables": [{
+ "Key": "PATH",
+ "Value": "/bin:/usr/bin:/usr/local/bin"
+ }],
+ "input_dep_set_ids": [4],
+ "output_ids": [7],
+ "primary_output_id": 7
+ }],
+ "Targets": [
+ { "Id": 1, "Label": "@sourceroot//bionic/libc:syscalls-arm", "rule_class_id": 1 },
+ { "Id": 2, "Label": "@sourceroot//bionic/libc:syscalls-x86", "rule_class_id": 1 },
+ { "Id": 3, "Label": "@sourceroot//bionic/libc:syscalls-x86_64", "rule_class_id": 1 },
+ { "Id": 4, "Label": "@sourceroot//bionic/libc:syscalls-arm64", "rule_class_id": 1 }],
+ "dep_set_of_files": [
+ { "Id": 1, "direct_artifact_ids": [1, 2, 3] },
+ { "Id": 2, "direct_artifact_ids": [1, 2, 3] },
+ { "Id": 3, "direct_artifact_ids": [1, 2, 3] },
+ { "Id": 4, "direct_artifact_ids": [1, 2, 3] }],
+ "Configuration": [{
+ "Id": 1,
+ "Mnemonic": "k8-fastbuild",
+ "platform_name": "k8",
+ "Checksum": "485c362832c178e367d972177f68e69e0981e51e67ef1c160944473db53fe046"
+ }],
+ "rule_classes": [{ "Id": 1, "Name": "genrule"}],
+ "path_fragments": [
+ { "Id": 5, "Label": ".." },
+ { "Id": 4, "Label": "sourceroot", "parent_id": 5 },
+ { "Id": 3, "Label": "bionic", "parent_id": 4 },
+ { "Id": 2, "Label": "libc", "parent_id": 3 },
+ { "Id": 1, "Label": "SYSCALLS.TXT", "parent_id": 2 },
+ { "Id": 7, "Label": "tools", "parent_id": 2 },
+ { "Id": 6, "Label": "gensyscalls.py", "parent_id": 7 },
+ { "Id": 11, "Label": "bazel_tools", "parent_id": 5 },
+ { "Id": 10, "Label": "tools", "parent_id": 11 },
+ { "Id": 9, "Label": "genrule", "parent_id": 10 },
+ { "Id": 8, "Label": "genrule-setup.sh", "parent_id": 9 },
+ { "Id": 18, "Label": "bazel-out" },
+ { "Id": 17, "Label": "sourceroot", "parent_id": 18 },
+ { "Id": 16, "Label": "k8-fastbuild", "parent_id": 17 },
+ { "Id": 15, "Label": "bin", "parent_id": 16 },
+ { "Id": 14, "Label": "bionic", "parent_id": 15 },
+ { "Id": 13, "Label": "libc", "parent_id": 14 },
+ { "Id": 12, "Label": "syscalls-arm.S", "parent_id": 13 },
+ { "Id": 19, "Label": "syscalls-x86.S", "parent_id": 13 },
+ { "Id": 20, "Label": "syscalls-x86_64.S", "parent_id": 13 },
+ { "Id": 21, "Label": "syscalls-arm64.S", "parent_id": 13 }]
+}
+`
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actualbuildStatements, actualDepsets, _ := AqueryBuildStatements(data)
var expectedBuildStatements []BuildStatement
for _, arch := range []string{"arm", "arm64", "x86", "x86_64"} {
expectedBuildStatements = append(expectedBuildStatements,
@@ -161,130 +171,155 @@
func TestInvalidOutputId(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [3],
- "primaryOutputId": 3
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 2] }],
- "pathFragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [1],
+ "output_ids": [3],
+ "primary_output_id": 3
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1, 2] }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, "undefined outputId 3")
}
func TestInvalidInputDepsetIdFromAction(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [2],
- "outputIds": [1],
- "primaryOutputId": 1
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 2] }],
- "pathFragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [2],
+ "output_ids": [1],
+ "primary_output_id": 1
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1, 2] }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, "undefined input depsetId 2")
}
func TestInvalidInputDepsetIdFromDepset(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [1],
- "primaryOutputId": 1
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 2], "transitiveDepSetIds": [42] }],
- "pathFragments": [
- { "id": 1, "label": "one"},
- { "id": 2, "label": "two" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [1],
+ "output_ids": [1],
+ "primary_output_id": 1
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1, 2], "transitive_dep_set_ids": [42] }],
+ "path_fragments": [
+ { "id": 1, "label": "one"},
+ { "id": 2, "label": "two" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, "undefined input depsetId 42 (referenced by depsetId 1)")
}
func TestInvalidInputArtifactId(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [1],
- "primaryOutputId": 1
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 3] }],
- "pathFragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [1],
+ "output_ids": [1],
+ "primary_output_id": 1
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1, 3] }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, "undefined input artifactId 3")
}
func TestInvalidPathFragmentId(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [1],
- "primaryOutputId": 1
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 2] }],
- "pathFragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two", "parentId": 3 }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [1],
+ "output_ids": [1],
+ "primary_output_id": 1
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1, 2] }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two", "parent_id": 3 }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, "undefined path fragment id 3")
}
@@ -292,27 +327,32 @@
const inputString = `
{
"artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 },
- { "id": 3, "pathFragmentId": 3 }],
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 },
+ { "id": 3, "path_fragment_id": 3 }],
"actions": [{
- "targetId": 1,
- "actionKey": "x",
+ "target_Id": 1,
+ "action_Key": "x",
"mnemonic": "x",
"arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [2, 3],
- "primaryOutputId": 2
+ "input_dep_set_ids": [1],
+ "output_ids": [2, 3],
+ "primary_output_id": 2
}],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1, 2, 3] }],
- "pathFragments": [
+ "dep_set_of_files": [
+ { "id": 1, "direct_Artifact_Ids": [1, 2, 3] }],
+ "path_fragments": [
{ "id": 1, "label": "one" },
{ "id": 2, "label": "two" },
{ "id": 3, "label": "two.d" }]
}`
- actual, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -332,32 +372,37 @@
func TestMultipleDepfiles(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 },
- { "id": 3, "pathFragmentId": 3 },
- { "id": 4, "pathFragmentId": 4 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [2,3,4],
- "primaryOutputId": 2
- }],
- "depSetOfFiles": [{
- "id": 1,
- "directArtifactIds": [1, 2, 3, 4]
- }],
- "pathFragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two" },
- { "id": 3, "label": "two.d" },
- { "id": 4, "label": "other.d" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 },
+ { "id": 3, "path_fragment_id": 3 },
+ { "id": 4, "path_fragment_id": 4 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "x",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [1],
+ "output_ids": [2,3,4],
+ "primary_output_id": 2
+ }],
+ "dep_set_of_files": [{
+ "id": 1,
+ "direct_artifact_ids": [1, 2, 3, 4]
+ }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "two" },
+ { "id": 3, "label": "two.d" },
+ { "id": 4, "label": "other.d" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, `found multiple potential depfiles "two.d", "other.d"`)
}
@@ -366,74 +411,79 @@
// 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 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "3b826d17fadbbbcd8313e456b90ec47c078c438088891dd45b4adbcd8889dc50",
- "mnemonic": "Action",
- "configurationId": 1,
- "arguments": ["/bin/bash", "-c", "touch bazel-out/sourceroot/k8-fastbuild/bin/testpkg/test_out"],
- "inputDepSetIds": [1],
- "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 }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 7 },
+ { "id": 3, "path_fragment_id": 8 },
+ { "id": 4, "path_fragment_id": 9 },
+ { "id": 5, "path_fragment_id": 10 },
+ { "id": 6, "path_fragment_id": 11 },
+ { "id": 7, "path_fragment_id": 12 },
+ { "id": 8, "path_fragment_id": 13 },
+ { "id": 9, "path_fragment_id": 14 },
+ { "id": 10, "path_fragment_id": 15 },
+ { "id": 11, "path_fragment_id": 16 },
+ { "id": 12, "path_fragment_id": 17 },
+ { "id": 13, "path_fragment_id": 18 },
+ { "id": 14, "path_fragment_id": 19 },
+ { "id": 15, "path_fragment_id": 20 },
+ { "id": 16, "path_fragment_id": 21 },
+ { "id": 17, "path_fragment_id": 22 },
+ { "id": 18, "path_fragment_id": 23 },
+ { "id": 19, "path_fragment_id": 24 },
+ { "id": 20, "path_fragment_id": 25 },
+ { "id": 21, "path_fragment_id": 26 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "3b826d17fadbbbcd8313e456b90ec47c078c438088891dd45b4adbcd8889dc50",
+ "mnemonic": "Action",
+ "configuration_id": 1,
+ "arguments": ["/bin/bash", "-c", "touch bazel-out/sourceroot/k8-fastbuild/bin/testpkg/test_out"],
+ "input_dep_set_ids": [1],
+ "output_ids": [21],
+ "primary_output_id": 21
+ }],
+ "dep_set_of_files": [
+ { "id": 3, "direct_artifact_ids": [1, 2, 3, 4, 5] },
+ { "id": 4, "direct_artifact_ids": [6, 7, 8, 9, 10] },
+ { "id": 2, "transitive_dep_set_ids": [3, 4], "direct_artifact_ids": [11, 12, 13, 14, 15] },
+ { "id": 5, "direct_artifact_ids": [16, 17, 18, 19] },
+ { "id": 1, "transitive_dep_set_ids": [2, 5], "direct_artifact_ids": [20] }],
+ "path_fragments": [
+ { "id": 6, "label": "bazel-out" },
+ { "id": 5, "label": "sourceroot", "parent_id": 6 },
+ { "id": 4, "label": "k8-fastbuild", "parent_id": 5 },
+ { "id": 3, "label": "bin", "parent_id": 4 },
+ { "id": 2, "label": "testpkg", "parent_id": 3 },
+ { "id": 1, "label": "test_1", "parent_id": 2 },
+ { "id": 7, "label": "test_2", "parent_id": 2 },
+ { "id": 8, "label": "test_3", "parent_id": 2 },
+ { "id": 9, "label": "test_4", "parent_id": 2 },
+ { "id": 10, "label": "test_5", "parent_id": 2 },
+ { "id": 11, "label": "test_6", "parent_id": 2 },
+ { "id": 12, "label": "test_7", "parent_id": 2 },
+ { "id": 13, "label": "test_8", "parent_id": 2 },
+ { "id": 14, "label": "test_9", "parent_id": 2 },
+ { "id": 15, "label": "test_10", "parent_id": 2 },
+ { "id": 16, "label": "test_11", "parent_id": 2 },
+ { "id": 17, "label": "test_12", "parent_id": 2 },
+ { "id": 18, "label": "test_13", "parent_id": 2 },
+ { "id": 19, "label": "test_14", "parent_id": 2 },
+ { "id": 20, "label": "test_15", "parent_id": 2 },
+ { "id": 21, "label": "test_16", "parent_id": 2 },
+ { "id": 22, "label": "test_17", "parent_id": 2 },
+ { "id": 23, "label": "test_18", "parent_id": 2 },
+ { "id": 24, "label": "test_19", "parent_id": 2 },
+ { "id": 25, "label": "test_root", "parent_id": 2 },
+ { "id": 26,"label": "test_out", "parent_id": 2 }]
}`
- actualbuildStatements, actualDepsets, _ := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actualbuildStatements, actualDepsets, _ := AqueryBuildStatements(data)
expectedBuildStatements := []BuildStatement{
{
@@ -463,27 +513,32 @@
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] }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "SymlinkTree",
+ "configuration_id": 1,
+ "input_dep_set_ids": [1],
+ "output_ids": [2],
+ "primary_output_id": 2,
+ "execution_platform": "//build/bazel/platforms:linux_x86_64"
+ }],
+ "path_fragments": [
+ { "id": 1, "label": "foo.manifest" },
+ { "id": 2, "label": "foo.runfiles/MANIFEST" }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1] }]
}
`
- actual, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -499,37 +554,42 @@
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]
- }, {
- "id": 2222,
- "directArtifactIds": [3]
- }],
- "actions": [{
- "targetId": 100,
- "actionKey": "x",
- "inputDepSetIds": [1111, 2222],
- "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": ".."}
- ]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 10 },
+ { "id": 2, "path_fragment_id": 20 },
+ { "id": 3, "path_fragment_id": 30 },
+ { "id": 4, "path_fragment_id": 40 }],
+ "dep_set_of_files": [{
+ "id": 1111,
+ "direct_artifact_ids": [3 , 4]
+ }, {
+ "id": 2222,
+ "direct_artifact_ids": [3]
+ }],
+ "actions": [{
+ "target_id": 100,
+ "action_key": "x",
+ "input_dep_set_ids": [1111, 2222],
+ "mnemonic": "x",
+ "arguments": ["bogus", "command"],
+ "output_ids": [2],
+ "primary_output_id": 1
+ }],
+ "path_fragments": [
+ { "id": 10, "label": "input" },
+ { "id": 20, "label": "output" },
+ { "id": 30, "label": "dep1", "parent_id": 50 },
+ { "id": 40, "label": "dep2", "parent_id": 60 },
+ { "id": 50, "label": "bazel_tools", "parent_id": 60 },
+ { "id": 60, "label": ".."}
+ ]
}`
- actualBuildStatements, actualDepsets, _ := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actualBuildStatements, actualDepsets, _ := AqueryBuildStatements(data)
if len(actualDepsets) != 2 {
t.Errorf("expected 1 depset but found %#v", actualDepsets)
return
@@ -567,43 +627,47 @@
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] }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "Middleman",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [1],
- "outputIds": [3],
- "primaryOutputId": 3
- }, {
- "targetId": 2,
- "actionKey": "y",
- "mnemonic": "Main action",
- "arguments": ["touch", "foo"],
- "inputDepSetIds": [2],
- "outputIds": [6],
- "primaryOutputId": 6
- }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 },
+ { "id": 3, "path_fragment_id": 3 },
+ { "id": 4, "path_fragment_id": 4 },
+ { "id": 5, "path_fragment_id": 5 },
+ { "id": 6, "path_fragment_id": 6 }],
+ "path_fragments": [
+ { "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" }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1, 2] },
+ { "id": 2, "direct_artifact_ids": [3, 4, 5] }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "Middleman",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [1],
+ "output_ids": [3],
+ "primary_output_id": 3
+ }, {
+ "target_id": 2,
+ "action_key": "y",
+ "mnemonic": "Main action",
+ "arguments": ["touch", "foo"],
+ "input_dep_set_ids": [2],
+ "output_ids": [6],
+ "primary_output_id": 6
+ }]
}`
-
- actualBuildStatements, actualDepsets, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actualBuildStatements, actualDepsets, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -675,28 +739,32 @@
func TestSimpleSymlink(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 3 },
- { "id": 2, "pathFragmentId": 5 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "Symlink",
- "inputDepSetIds": [1],
- "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 }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 3 },
+ { "id": 2, "path_fragment_id": 5 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "Symlink",
+ "input_dep_set_ids": [1],
+ "output_ids": [2],
+ "primary_output_id": 2
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1] }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "file_subdir", "parent_id": 1 },
+ { "id": 3, "label": "file", "parent_id": 2 },
+ { "id": 4, "label": "symlink_subdir", "parent_id": 1 },
+ { "id": 5, "label": "symlink", "parent_id": 4 }]
}`
-
- actual, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
@@ -719,29 +787,33 @@
func TestSymlinkQuotesPaths(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 3 },
- { "id": 2, "pathFragmentId": 5 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "SolibSymlink",
- "inputDepSetIds": [1],
- "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 }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 3 },
+ { "id": 2, "path_fragment_id": 5 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "SolibSymlink",
+ "input_dep_set_ids": [1],
+ "output_ids": [2],
+ "primary_output_id": 2
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1] }],
+ "path_fragments": [
+ { "id": 1, "label": "one" },
+ { "id": 2, "label": "file subdir", "parent_id": 1 },
+ { "id": 3, "label": "file", "parent_id": 2 },
+ { "id": 4, "label": "symlink subdir", "parent_id": 1 },
+ { "id": 5, "label": "symlink", "parent_id": 4 }]
}`
- actual, _, err := AqueryBuildStatements([]byte(inputString))
-
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -763,82 +835,95 @@
func TestSymlinkMultipleInputs(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 },
- { "id": 3, "pathFragmentId": 3 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "Symlink",
- "inputDepSetIds": [1],
- "outputIds": [3],
- "primaryOutputId": 3
- }],
- "depSetOfFiles": [{ "id": 1, "directArtifactIds": [1,2] }],
- "pathFragments": [
- { "id": 1, "label": "file" },
- { "id": 2, "label": "other_file" },
- { "id": 3, "label": "symlink" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 2, "path_fragment_id": 2 },
+ { "id": 3, "path_fragment_id": 3 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "Symlink",
+ "input_dep_set_ids": [1],
+ "output_ids": [3],
+ "primary_output_id": 3
+ }],
+ "dep_set_of_files": [{ "id": 1, "direct_artifact_ids": [1,2] }],
+ "path_fragments": [
+ { "id": 1, "label": "file" },
+ { "id": 2, "label": "other_file" },
+ { "id": 3, "label": "symlink" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, `Expect 1 input and 1 output to symlink action, got: input ["file" "other_file"], output ["symlink"]`)
}
func TestSymlinkMultipleOutputs(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 },
- { "id": 2, "pathFragmentId": 2 },
- { "id": 3, "pathFragmentId": 3 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "Symlink",
- "inputDepSetIds": [1],
- "outputIds": [2,3],
- "primaryOutputId": 2
- }],
- "depSetOfFiles": [
- { "id": 1, "directArtifactIds": [1] }],
- "pathFragments": [
- { "id": 1, "label": "file" },
- { "id": 2, "label": "symlink" },
- { "id": 3, "label": "other_symlink" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 },
+ { "id": 3, "path_fragment_id": 3 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "Symlink",
+ "input_dep_set_ids": [1],
+ "output_ids": [2,3],
+ "primary_output_id": 2
+ }],
+ "dep_set_of_files": [
+ { "id": 1, "direct_artifact_ids": [1] }],
+ "path_fragments": [
+ { "id": 1, "label": "file" },
+ { "id": 2, "label": "symlink" },
+ { "id": 3, "label": "other_symlink" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
- assertError(t, err, `Expect 1 input and 1 output to symlink action, got: input ["file"], output ["symlink" "other_symlink"]`)
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
+ assertError(t, err, "undefined outputId 2")
}
func TestTemplateExpandActionSubstitutions(t *testing.T) {
const inputString = `
{
- "artifacts": [{
- "id": 1,
- "pathFragmentId": 1
- }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "TemplateExpand",
- "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" }]
- }],
- "pathFragments": [
- { "id": 1, "label": "template_file" }]
+ "artifacts": [{
+ "id": 1,
+ "path_fragment_id": 1
+ }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "TemplateExpand",
+ "configuration_id": 1,
+ "output_ids": [1],
+ "primary_output_id": 1,
+ "execution_platform": "//build/bazel/platforms:linux_x86_64",
+ "template_content": "Test template substitutions: %token1%, %python_binary%",
+ "substitutions": [
+ { "key": "%token1%", "value": "abcd" },
+ { "key": "%python_binary%", "value": "python3" }]
+ }],
+ "path_fragments": [
+ { "id": 1, "label": "template_file" }]
}`
- actual, _, err := AqueryBuildStatements([]byte(inputString))
-
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -857,48 +942,58 @@
func TestTemplateExpandActionNoOutput(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "TemplateExpand",
- "configurationId": 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" }]
- }],
- "pathFragments": [
- { "id": 1, "label": "template_file" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "TemplateExpand",
+ "configuration_id": 1,
+ "primary_output_id": 1,
+ "execution_platform": "//build/bazel/platforms:linux_x86_64",
+ "templateContent": "Test template substitutions: %token1%, %python_binary%",
+ "substitutions": [
+ { "key": "%token1%", "value": "abcd" },
+ { "key": "%python_binary%", "value": "python3" }]
+ }],
+ "path_fragments": [
+ { "id": 1, "label": "template_file" }]
}`
- _, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ _, _, err = AqueryBuildStatements(data)
assertError(t, err, `Expect 1 output to template expand action, got: output []`)
}
func TestFileWrite(t *testing.T) {
const inputString = `
{
- "artifacts": [
- { "id": 1, "pathFragmentId": 1 }],
- "actions": [{
- "targetId": 1,
- "actionKey": "x",
- "mnemonic": "FileWrite",
- "configurationId": 1,
- "outputIds": [1],
- "primaryOutputId": 1,
- "executionPlatform": "//build/bazel/platforms:linux_x86_64",
- "fileContents": "file data\n"
- }],
- "pathFragments": [
- { "id": 1, "label": "foo.manifest" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "FileWrite",
+ "configuration_id": 1,
+ "output_ids": [1],
+ "primary_output_id": 1,
+ "execution_platform": "//build/bazel/platforms:linux_x86_64",
+ "file_contents": "file data\n"
+ }],
+ "path_fragments": [
+ { "id": 1, "label": "foo.manifest" }]
}
`
- actual, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -914,23 +1009,28 @@
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" }]
+ "artifacts": [
+ { "id": 1, "path_fragment_id": 1 }],
+ "actions": [{
+ "target_id": 1,
+ "action_key": "x",
+ "mnemonic": "SourceSymlinkManifest",
+ "configuration_id": 1,
+ "output_ids": [1],
+ "primary_output_id": 1,
+ "execution_platform": "//build/bazel/platforms:linux_x86_64",
+ "file_contents": "symlink target\n"
+ }],
+ "path_fragments": [
+ { "id": 1, "label": "foo.manifest" }]
}
`
- actual, _, err := AqueryBuildStatements([]byte(inputString))
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actual, _, err := AqueryBuildStatements(data)
if err != nil {
t.Errorf("Unexpected error %q", err)
}
@@ -1011,3 +1111,14 @@
sort.Strings(sorted)
return sorted
}
+
+// Transform the json format to ActionGraphContainer
+func JsonToActionGraphContainer(inputString string) ([]byte, error) {
+ var aqueryProtoResult analysis_v2_proto.ActionGraphContainer
+ err := json.Unmarshal([]byte(inputString), &aqueryProtoResult)
+ if err != nil {
+ return []byte(""), err
+ }
+ data, _ := proto.Marshal(&aqueryProtoResult)
+ return data, err
+}
diff --git a/bazel/configurability.go b/bazel/configurability.go
index b6bbd67..3f4cc73 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -23,10 +23,11 @@
const (
// ArchType names in arch.go
- archArm = "arm"
- archArm64 = "arm64"
- archX86 = "x86"
- archX86_64 = "x86_64"
+ archArm = "arm"
+ archArm64 = "arm64"
+ archRiscv64 = "riscv64"
+ archX86 = "x86"
+ archX86_64 = "x86_64"
// OsType names in arch.go
OsAndroid = "android"
@@ -39,6 +40,7 @@
// Targets in arch.go
osArchAndroidArm = "android_arm"
osArchAndroidArm64 = "android_arm64"
+ osArchAndroidRiscv64 = "android_riscv64"
osArchAndroidX86 = "android_x86"
osArchAndroidX86_64 = "android_x86_64"
osArchDarwinArm64 = "darwin_arm64"
@@ -99,6 +101,7 @@
"arm64": {
"dotprod",
},
+ "riscv64": {},
"x86": {
"ssse3",
"sse4",
@@ -164,6 +167,7 @@
platformOsArchMap = map[string]string{
osArchAndroidArm: "//build/bazel/platforms/os_arch:android_arm",
osArchAndroidArm64: "//build/bazel/platforms/os_arch:android_arm64",
+ osArchAndroidRiscv64: "//build/bazel/platforms/os_arch:android_riscv64",
osArchAndroidX86: "//build/bazel/platforms/os_arch:android_x86",
osArchAndroidX86_64: "//build/bazel/platforms/os_arch:android_x86_64",
osArchDarwinArm64: "//build/bazel/platforms/os_arch:darwin_arm64",
@@ -187,7 +191,7 @@
// TODO(cparsons): Source from arch.go; this task is nontrivial, as it currently results
// in a cyclic dependency.
osToArchMap = map[string][]string{
- OsAndroid: {archArm, archArm64, archX86, archX86_64},
+ OsAndroid: {archArm, archArm64, archRiscv64, archX86, archX86_64},
osLinux: {archX86, archX86_64},
osLinuxMusl: {archX86, archX86_64},
osDarwin: {archArm64, archX86_64},
@@ -199,6 +203,11 @@
osAndInApexMap = map[string]string{
AndroidAndInApex: "//build/bazel/rules/apex:android-in_apex",
AndroidAndNonApex: "//build/bazel/rules/apex:android-non_apex",
+ osDarwin: "//build/bazel/platforms/os:darwin",
+ osLinux: "//build/bazel/platforms/os:linux",
+ osLinuxMusl: "//build/bazel/platforms/os:linux_musl",
+ osLinuxBionic: "//build/bazel/platforms/os:linux_bionic",
+ osWindows: "//build/bazel/platforms/os:windows",
ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
}
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index 3b06f85..e4830d3 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -7,10 +7,11 @@
)
var (
- GetOutputFiles = &getOutputFilesRequestType{}
- GetPythonBinary = &getPythonBinaryRequestType{}
- GetCcInfo = &getCcInfoType{}
- GetApexInfo = &getApexInfoType{}
+ GetOutputFiles = &getOutputFilesRequestType{}
+ GetPythonBinary = &getPythonBinaryRequestType{}
+ GetCcInfo = &getCcInfoType{}
+ GetApexInfo = &getApexInfoType{}
+ GetCcUnstrippedInfo = &getCcUnstippedInfoType{}
)
type CcInfo struct {
@@ -29,7 +30,9 @@
// be a subset of OutputFiles. (or shared libraries, this will be equal to OutputFiles,
// but general cc_library will also have dynamic libraries in output files).
RootDynamicLibraries []string
+ TidyFiles []string
TocFile string
+ UnstrippedOutput string
}
type getOutputFilesRequestType struct{}
@@ -47,7 +50,7 @@
// all request-relevant information about a target and returns a string containing
// this information.
// The function should have the following properties:
-// - `target` is the only parameter to this function (a configured target).
+// - The arguments are `target` (a configured target) and `id_string` (the label + configuration).
// - The return value must be a string.
// - The function body should not be indented outside of its own scope.
func (g getOutputFilesRequestType) StarlarkFunctionBody() string {
@@ -72,7 +75,7 @@
// all request-relevant information about a target and returns a string containing
// this information.
// The function should have the following properties:
-// - `target` is the only parameter to this function (a configured target).
+// - The arguments are `target` (a configured target) and `id_string` (the label + configuration).
// - The return value must be a string.
// - The function body should not be indented outside of its own scope.
func (g getPythonBinaryRequestType) StarlarkFunctionBody() string {
@@ -99,13 +102,16 @@
// all request-relevant information about a target and returns a string containing
// this information.
// The function should have the following properties:
-// - `target` is the only parameter to this function (a configured target).
+// - The arguments are `target` (a configured target) and `id_string` (the label + configuration).
// - The return value must be a string.
// - The function body should not be indented outside of its own scope.
func (g getCcInfoType) StarlarkFunctionBody() string {
return `
outputFiles = [f.path for f in target.files.to_list()]
-cc_info = providers(target)["CcInfo"]
+p = providers(target)
+cc_info = p.get("CcInfo")
+if not cc_info:
+ fail("%s did not provide CcInfo" % id_string)
includes = cc_info.compilation_context.includes.to_list()
system_includes = cc_info.compilation_context.system_includes.to_list()
@@ -117,8 +123,8 @@
linker_inputs = cc_info.linking_context.linker_inputs.to_list()
static_info_tag = "//build/bazel/rules/cc:cc_library_static.bzl%CcStaticLibraryInfo"
-if static_info_tag in providers(target):
- static_info = providers(target)[static_info_tag]
+if static_info_tag in p:
+ static_info = p[static_info_tag]
ccObjectFiles = [f.path for f in static_info.objects]
rootStaticArchives = [static_info.root_static_archive.path]
else:
@@ -135,12 +141,17 @@
rootSharedLibraries = []
shared_info_tag = "//build/bazel/rules/cc:cc_library_shared.bzl%CcSharedLibraryOutputInfo"
+unstripped_tag = "//build/bazel/rules/cc:stripped_cc_common.bzl%CcUnstrippedInfo"
+unstripped = ""
-if shared_info_tag in providers(target):
- shared_info = providers(target)[shared_info_tag]
+if shared_info_tag in p:
+ shared_info = p[shared_info_tag]
path = shared_info.output_file.path
sharedLibraries.append(path)
rootSharedLibraries += [path]
+ unstripped = path
+ if unstripped_tag in p:
+ unstripped = p[unstripped_tag].unstripped.path
else:
for linker_input in linker_inputs:
for library in linker_input.libraries:
@@ -152,12 +163,17 @@
toc_file = ""
toc_file_tag = "//build/bazel/rules/cc:generate_toc.bzl%CcTocInfo"
-if toc_file_tag in providers(target):
- toc_file = providers(target)[toc_file_tag].toc.path
+if toc_file_tag in p:
+ toc_file = p[toc_file_tag].toc.path
else:
# NOTE: It's OK if there's no ToC, as Soong just uses it for optimization
pass
+tidy_files = []
+clang_tidy_info = p.get("//build/bazel/rules/cc:clang_tidy.bzl%ClangTidyInfo")
+if clang_tidy_info:
+ tidy_files = [v.path for v in clang_tidy_info.tidy_files.to_list()]
+
return json_encode({
"OutputFiles": outputFiles,
"CcObjectFiles": ccObjectFiles,
@@ -168,7 +184,9 @@
"Headers": headers,
"RootStaticArchives": rootStaticArchives,
"RootDynamicLibraries": rootSharedLibraries,
- "TocFile": toc_file
+ "TidyFiles": tidy_files,
+ "TocFile": toc_file,
+ "UnstrippedOutput": unstripped,
})`
}
@@ -178,10 +196,10 @@
// Starlark given in StarlarkFunctionBody.
func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) {
var ccInfo CcInfo
- decoder := json.NewDecoder(strings.NewReader(rawString))
- decoder.DisallowUnknownFields() //useful to detect typos, e.g. in unit tests
- err := decoder.Decode(&ccInfo)
- return ccInfo, err
+ if err := parseJson(rawString, &ccInfo); err != nil {
+ return ccInfo, err
+ }
+ return ccInfo, nil
}
// Query Bazel for the artifacts generated by the apex modules.
@@ -197,41 +215,91 @@
// The returned string is the body of a Starlark function which obtains
// all request-relevant information about a target and returns a string containing
// this information. The function should have the following properties:
-// - `target` is the only parameter to this function (a configured target).
+// - The arguments are `target` (a configured target) and `id_string` (the label + configuration).
// - The return value must be a string.
// - The function body should not be indented outside of its own scope.
func (g getApexInfoType) StarlarkFunctionBody() string {
- return `info = providers(target)["//build/bazel/rules/apex:apex.bzl%ApexInfo"]
+ return `
+info = providers(target).get("//build/bazel/rules/apex:apex.bzl%ApexInfo")
+if not info:
+ fail("%s did not provide ApexInfo" % id_string)
+bundle_key_info = info.bundle_key_info
+container_key_info = info.container_key_info
return json_encode({
"signed_output": info.signed_output.path,
"unsigned_output": info.unsigned_output.path,
"provides_native_libs": [str(lib) for lib in info.provides_native_libs],
"requires_native_libs": [str(lib) for lib in info.requires_native_libs],
- "bundle_key_pair": [f.path for f in info.bundle_key_pair],
- "container_key_pair": [f.path for f in info.container_key_pair]
+ "bundle_key_info": [bundle_key_info.public_key.path, bundle_key_info.private_key.path],
+ "container_key_info": [container_key_info.pem.path, container_key_info.pk8.path, container_key_info.key_name],
+ "package_name": info.package_name,
+ "symbols_used_by_apex": info.symbols_used_by_apex.path,
+ "java_symbols_used_by_apex": info.java_symbols_used_by_apex.path,
+ "backing_libs": info.backing_libs.path,
+ "bundle_file": info.base_with_config_zip.path,
+ "installed_files": info.installed_files.path,
})`
}
-type ApexCqueryInfo struct {
- SignedOutput string `json:"signed_output"`
- UnsignedOutput string `json:"unsigned_output"`
- ProvidesLibs []string `json:"provides_native_libs"`
- RequiresLibs []string `json:"requires_native_libs"`
- BundleKeyPair []string `json:"bundle_key_pair"`
- ContainerKeyPair []string `json:"container_key_pair"`
+type ApexInfo struct {
+ SignedOutput string `json:"signed_output"`
+ UnsignedOutput string `json:"unsigned_output"`
+ ProvidesLibs []string `json:"provides_native_libs"`
+ RequiresLibs []string `json:"requires_native_libs"`
+ BundleKeyInfo []string `json:"bundle_key_info"`
+ ContainerKeyInfo []string `json:"container_key_info"`
+ PackageName string `json:"package_name"`
+ SymbolsUsedByApex string `json:"symbols_used_by_apex"`
+ JavaSymbolsUsedByApex string `json:"java_symbols_used_by_apex"`
+ BackingLibs string `json:"backing_libs"`
+ BundleFile string `json:"bundle_file"`
+ InstalledFiles string `json:"installed_files"`
}
// ParseResult returns a value obtained by parsing the result of the request's Starlark function.
// The given rawString must correspond to the string output which was created by evaluating the
// Starlark given in StarlarkFunctionBody.
-func (g getApexInfoType) ParseResult(rawString string) ApexCqueryInfo {
- var info ApexCqueryInfo
- decoder := json.NewDecoder(strings.NewReader(rawString))
- decoder.DisallowUnknownFields() //useful to detect typos, e.g. in unit tests
- if err := decoder.Decode(&info); err != nil {
- panic(fmt.Errorf("cannot parse cquery result '%s': %s", rawString, err))
- }
- return info
+func (g getApexInfoType) ParseResult(rawString string) (ApexInfo, error) {
+ var info ApexInfo
+ err := parseJson(rawString, &info)
+ return info, err
+}
+
+// getCcUnstrippedInfoType implements cqueryRequest interface. It handles the
+// interaction with `bazel cquery` to retrieve CcUnstrippedInfo provided
+// by the` cc_binary` and `cc_shared_library` rules.
+type getCcUnstippedInfoType struct{}
+
+func (g getCcUnstippedInfoType) Name() string {
+ return "getCcUnstrippedInfo"
+}
+
+func (g getCcUnstippedInfoType) StarlarkFunctionBody() string {
+ return `unstripped_tag = "//build/bazel/rules/cc:stripped_cc_common.bzl%CcUnstrippedInfo"
+p = providers(target)
+output_path = target.files.to_list()[0].path
+unstripped = output_path
+if unstripped_tag in p:
+ unstripped = p[unstripped_tag].unstripped.files.to_list()[0].path
+return json_encode({
+ "OutputFile": output_path,
+ "UnstrippedOutput": unstripped,
+})
+`
+}
+
+// ParseResult returns a value obtained by parsing the result of the request's Starlark function.
+// The given rawString must correspond to the string output which was created by evaluating the
+// Starlark given in StarlarkFunctionBody.
+func (g getCcUnstippedInfoType) ParseResult(rawString string) (CcUnstrippedInfo, error) {
+ var info CcUnstrippedInfo
+ err := parseJson(rawString, &info)
+ return info, err
+}
+
+type CcUnstrippedInfo struct {
+ OutputFile string
+ UnstrippedOutput string
}
// splitOrEmpty is a modification of strings.Split() that returns an empty list
@@ -243,3 +311,15 @@
return strings.Split(s, sep)
}
}
+
+// parseJson decodes json string into the fields of the receiver.
+// Unknown attribute name causes panic.
+func parseJson(jsonString string, info interface{}) error {
+ decoder := json.NewDecoder(strings.NewReader(jsonString))
+ decoder.DisallowUnknownFields() //useful to detect typos, e.g. in unit tests
+ err := decoder.Decode(info)
+ if err != nil {
+ return fmt.Errorf("cannot parse cquery result '%s': %s", jsonString, err)
+ }
+ return nil
+}
diff --git a/bazel/cquery/request_type_test.go b/bazel/cquery/request_type_test.go
index afe478b..1d30535 100644
--- a/bazel/cquery/request_type_test.go
+++ b/bazel/cquery/request_type_test.go
@@ -3,10 +3,12 @@
import (
"encoding/json"
"reflect"
+ "strings"
"testing"
)
func TestGetOutputFilesParseResults(t *testing.T) {
+ t.Parallel()
testCases := []struct {
description string
input string
@@ -29,14 +31,17 @@
},
}
for _, tc := range testCases {
- actualOutput := GetOutputFiles.ParseResult(tc.input)
- if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
- t.Errorf("%q: expected %#v != actual %#v", tc.description, tc.expectedOutput, actualOutput)
- }
+ t.Run(tc.description, func(t *testing.T) {
+ actualOutput := GetOutputFiles.ParseResult(tc.input)
+ if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
+ t.Errorf("expected %#v != actual %#v", tc.expectedOutput, actualOutput)
+ }
+ })
}
}
func TestGetPythonBinaryParseResults(t *testing.T) {
+ t.Parallel()
testCases := []struct {
description string
input string
@@ -54,14 +59,17 @@
},
}
for _, tc := range testCases {
- actualOutput := GetPythonBinary.ParseResult(tc.input)
- if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
- t.Errorf("%q: expected %#v != actual %#v", tc.description, tc.expectedOutput, actualOutput)
- }
+ t.Run(tc.description, func(t *testing.T) {
+ actualOutput := GetPythonBinary.ParseResult(tc.input)
+ if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
+ t.Errorf("expected %#v != actual %#v", tc.expectedOutput, actualOutput)
+ }
+ })
}
}
func TestGetCcInfoParseResults(t *testing.T) {
+ t.Parallel()
testCases := []struct {
description string
inputCcInfo CcInfo
@@ -73,24 +81,6 @@
expectedOutput: CcInfo{},
},
{
- description: "only output",
- inputCcInfo: CcInfo{
- OutputFiles: []string{"test", "test3"},
- },
- expectedOutput: CcInfo{
- OutputFiles: []string{"test", "test3"},
- },
- },
- {
- description: "only ToC",
- inputCcInfo: CcInfo{
- TocFile: "test",
- },
- expectedOutput: CcInfo{
- TocFile: "test",
- },
- },
- {
description: "all items set",
inputCcInfo: CcInfo{
OutputFiles: []string{"out1", "out2"},
@@ -119,49 +109,196 @@
},
}
for _, tc := range testCases {
- jsonInput, _ := json.Marshal(tc.inputCcInfo)
- actualOutput, err := GetCcInfo.ParseResult(string(jsonInput))
- if err != nil {
- t.Errorf("%q:\n test case get error: %q", tc.description, err)
- } else if err == nil && !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
- t.Errorf("%q:\n expected %#v\n!= actual %#v", tc.description, tc.expectedOutput, actualOutput)
- }
+ t.Run(tc.description, func(t *testing.T) {
+ jsonInput, _ := json.Marshal(tc.inputCcInfo)
+ actualOutput, err := GetCcInfo.ParseResult(string(jsonInput))
+ if err != nil {
+ t.Errorf("error parsing result: %q", err)
+ } else if err == nil && !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
+ t.Errorf("expected %#v\n!= actual %#v", tc.expectedOutput, actualOutput)
+ }
+ })
+ }
+}
+
+func TestGetCcInfoParseResultsError(t *testing.T) {
+ t.Parallel()
+ testCases := []struct {
+ description string
+ input string
+ expectedError string
+ }{
+ {
+ description: "not json",
+ input: ``,
+ expectedError: `cannot parse cquery result '': EOF`,
+ },
+ {
+ description: "invalid field",
+ input: `{
+ "toc_file": "dir/file.so.toc"
+}`,
+ expectedError: `json: unknown field "toc_file"`,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.description, func(t *testing.T) {
+ _, err := GetCcInfo.ParseResult(tc.input)
+ if !strings.Contains(err.Error(), tc.expectedError) {
+ t.Errorf("expected string %q in error message, got %q", tc.expectedError, err)
+ }
+ })
}
}
func TestGetApexInfoParseResults(t *testing.T) {
+ t.Parallel()
testCases := []struct {
description string
input string
- expectedOutput ApexCqueryInfo
+ expectedOutput ApexInfo
}{
{
description: "no result",
input: "{}",
- expectedOutput: ApexCqueryInfo{},
+ expectedOutput: ApexInfo{},
},
{
description: "one result",
- input: `{"signed_output":"my.apex",` +
- `"unsigned_output":"my.apex.unsigned",` +
- `"requires_native_libs":["//bionic/libc:libc","//bionic/libdl:libdl"],` +
- `"bundle_key_pair":["foo.pem","foo.privkey"],` +
- `"container_key_pair":["foo.x509.pem", "foo.pk8"],` +
- `"provides_native_libs":[]}`,
- expectedOutput: ApexCqueryInfo{
- SignedOutput: "my.apex",
- UnsignedOutput: "my.apex.unsigned",
- RequiresLibs: []string{"//bionic/libc:libc", "//bionic/libdl:libdl"},
- ProvidesLibs: []string{},
- BundleKeyPair: []string{"foo.pem", "foo.privkey"},
- ContainerKeyPair: []string{"foo.x509.pem", "foo.pk8"},
+ input: `{
+ "signed_output":"my.apex",
+ "unsigned_output":"my.apex.unsigned",
+ "requires_native_libs":["//bionic/libc:libc","//bionic/libdl:libdl"],
+ "bundle_key_info":["foo.pem", "foo.privkey"],
+ "container_key_info":["foo.x509.pem", "foo.pk8", "foo"],
+ "package_name":"package.name",
+ "symbols_used_by_apex": "path/to/my.apex_using.txt",
+ "backing_libs":"path/to/backing.txt",
+ "bundle_file": "dir/bundlefile.zip",
+ "installed_files":"path/to/installed-files.txt",
+ "provides_native_libs":[]
+}`,
+ expectedOutput: ApexInfo{
+ SignedOutput: "my.apex",
+ UnsignedOutput: "my.apex.unsigned",
+ RequiresLibs: []string{"//bionic/libc:libc", "//bionic/libdl:libdl"},
+ ProvidesLibs: []string{},
+ BundleKeyInfo: []string{"foo.pem", "foo.privkey"},
+ ContainerKeyInfo: []string{"foo.x509.pem", "foo.pk8", "foo"},
+ PackageName: "package.name",
+ SymbolsUsedByApex: "path/to/my.apex_using.txt",
+ BackingLibs: "path/to/backing.txt",
+ BundleFile: "dir/bundlefile.zip",
+ InstalledFiles: "path/to/installed-files.txt",
},
},
}
for _, tc := range testCases {
- actualOutput := GetApexInfo.ParseResult(tc.input)
- if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
- t.Errorf("%q: expected %#v != actual %#v", tc.description, tc.expectedOutput, actualOutput)
- }
+ t.Run(tc.description, func(t *testing.T) {
+ actualOutput, err := GetApexInfo.ParseResult(tc.input)
+ if err != nil {
+ t.Errorf("Unexpected error %q", err)
+ }
+ if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
+ t.Errorf("expected %#v != actual %#v", tc.expectedOutput, actualOutput)
+ }
+ })
+ }
+}
+
+func TestGetApexInfoParseResultsError(t *testing.T) {
+ t.Parallel()
+ testCases := []struct {
+ description string
+ input string
+ expectedError string
+ }{
+ {
+ description: "not json",
+ input: ``,
+ expectedError: `cannot parse cquery result '': EOF`,
+ },
+ {
+ description: "invalid field",
+ input: `{
+ "fake_field": "path/to/file"
+}`,
+ expectedError: `json: unknown field "fake_field"`,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.description, func(t *testing.T) {
+ _, err := GetApexInfo.ParseResult(tc.input)
+ if !strings.Contains(err.Error(), tc.expectedError) {
+ t.Errorf("expected string %q in error message, got %q", tc.expectedError, err)
+ }
+ })
+ }
+}
+
+func TestGetCcUnstrippedParseResults(t *testing.T) {
+ t.Parallel()
+ testCases := []struct {
+ description string
+ input string
+ expectedOutput CcUnstrippedInfo
+ }{
+ {
+ description: "no result",
+ input: "{}",
+ expectedOutput: CcUnstrippedInfo{},
+ },
+ {
+ description: "one result",
+ input: `{"OutputFile":"myapp", "UnstrippedOutput":"myapp_unstripped"}`,
+ expectedOutput: CcUnstrippedInfo{
+ OutputFile: "myapp",
+ UnstrippedOutput: "myapp_unstripped",
+ },
+ },
+ }
+ for _, tc := range testCases {
+ t.Run(tc.description, func(t *testing.T) {
+ actualOutput, err := GetCcUnstrippedInfo.ParseResult(tc.input)
+ if err != nil {
+ t.Errorf("Unexpected error %q", err)
+ }
+ if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
+ t.Errorf("expected %#v != actual %#v", tc.expectedOutput, actualOutput)
+ }
+ })
+ }
+}
+
+func TestGetCcUnstrippedParseResultsErrors(t *testing.T) {
+ t.Parallel()
+ testCases := []struct {
+ description string
+ input string
+ expectedError string
+ }{
+ {
+ description: "not json",
+ input: ``,
+ expectedError: `cannot parse cquery result '': EOF`,
+ },
+ {
+ description: "invalid field",
+ input: `{
+ "fake_field": "path/to/file"
+}`,
+ expectedError: `json: unknown field "fake_field"`,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.description, func(t *testing.T) {
+ _, err := GetCcUnstrippedInfo.ParseResult(tc.input)
+ if !strings.Contains(err.Error(), tc.expectedError) {
+ t.Errorf("expected string %q in error message, got %q", tc.expectedError, err)
+ }
+ })
}
}
diff --git a/bazel/properties.go b/bazel/properties.go
index c329e41..ee9609a 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -73,6 +73,17 @@
}
}
+// MakeLabelListFromTargetNames creates a LabelList from unqualified target names
+// This is a utiltity function for bp2build converters of Soong modules that have 1:many generated targets
+func MakeLabelListFromTargetNames(targetNames []string) LabelList {
+ labels := []Label{}
+ for _, name := range targetNames {
+ label := Label{Label: ":" + name}
+ labels = append(labels, label)
+ }
+ return MakeLabelList(labels)
+}
+
func (ll *LabelList) Equals(other LabelList) bool {
if len(ll.Includes) != len(other.Includes) || len(ll.Excludes) != len(other.Excludes) {
return false
@@ -832,6 +843,26 @@
// ResolveExcludes handles excludes across the various axes, ensuring that items are removed from
// the base value and included in default values as appropriate.
func (lla *LabelListAttribute) ResolveExcludes() {
+ // If there are OsAndInApexAxis, we need to use
+ // * includes from the OS & in APEX Axis for non-Android configs for libraries that need to be
+ // included in non-Android OSes
+ // * excludes from the OS Axis for non-Android configs, to exclude libraries that should _not_
+ // be included in the non-Android OSes
+ if _, ok := lla.ConfigurableValues[OsAndInApexAxis]; ok {
+ inApexLabels := lla.ConfigurableValues[OsAndInApexAxis][ConditionsDefaultConfigKey]
+ for config, labels := range lla.ConfigurableValues[OsConfigurationAxis] {
+ // OsAndroid has already handled its excludes.
+ // We only need to copy the excludes from other arches, so if there are none, skip it.
+ if config == OsAndroid || len(labels.Excludes) == 0 {
+ continue
+ }
+ lla.ConfigurableValues[OsAndInApexAxis][config] = LabelList{
+ Includes: inApexLabels.Includes,
+ Excludes: labels.Excludes,
+ }
+ }
+ }
+
for axis, configToLabels := range lla.ConfigurableValues {
baseLabels := lla.Value.deepCopy()
for config, val := range configToLabels {
@@ -1178,6 +1209,11 @@
ConfigurableValues configurableStringLists
}
+// IsEmpty returns true if the attribute has no values under any configuration.
+func (sla StringListAttribute) IsEmpty() bool {
+ return len(sla.Value) == 0 && !sla.HasConfigurableValues()
+}
+
type configurableStringLists map[ConfigurationAxis]stringListSelectValues
func (csl configurableStringLists) Append(other configurableStringLists) {
diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go
index e112be3..2b35521 100644
--- a/bp2build/android_app_conversion_test.go
+++ b/bp2build/android_app_conversion_test.go
@@ -27,6 +27,7 @@
}
func registerAndroidAppModuleTypes(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
}
func TestMinimalAndroidApp(t *testing.T) {
@@ -76,6 +77,7 @@
manifest: "manifest/AndroidManifest.xml",
static_libs: ["static_lib_dep"],
java_version: "7",
+ certificate: "foocert",
}
`,
ExpectedBazelTargets: []string{
@@ -86,9 +88,10 @@
"resa/res.png",
"resb/res.png",
]`,
- "custom_package": `"com.google"`,
- "deps": `[":static_lib_dep"]`,
- "javacopts": `["-source 1.7 -target 1.7"]`,
+ "custom_package": `"com.google"`,
+ "deps": `[":static_lib_dep"]`,
+ "javacopts": `["-source 1.7 -target 1.7"]`,
+ "certificate_name": `"foocert"`,
}),
}})
}
@@ -130,3 +133,70 @@
}),
}})
}
+
+func TestAndroidAppCertIsModule(t *testing.T) {
+ runAndroidAppTestCase(t, Bp2buildTestCase{
+ Description: "Android app - cert is module",
+ ModuleTypeUnderTest: "android_app",
+ ModuleTypeUnderTestFactory: java.AndroidAppFactory,
+ Filesystem: map[string]string{},
+ Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
+android_app {
+ name: "TestApp",
+ certificate: ":foocert",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("android_binary", "TestApp", AttrNameToString{
+ "certificate": `":foocert"`,
+ "manifest": `"AndroidManifest.xml"`,
+ "resource_files": `[]`,
+ }),
+ }})
+}
+
+func TestAndroidAppCertIsSrcFile(t *testing.T) {
+ runAndroidAppTestCase(t, Bp2buildTestCase{
+ Description: "Android app - cert is src file",
+ ModuleTypeUnderTest: "android_app",
+ ModuleTypeUnderTestFactory: java.AndroidAppFactory,
+ Filesystem: map[string]string{
+ "foocert": "",
+ },
+ Blueprint: `
+android_app {
+ name: "TestApp",
+ certificate: "foocert",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("android_binary", "TestApp", AttrNameToString{
+ "certificate": `"foocert"`,
+ "manifest": `"AndroidManifest.xml"`,
+ "resource_files": `[]`,
+ }),
+ }})
+}
+
+func TestAndroidAppCertIsNotSrcOrModule(t *testing.T) {
+ runAndroidAppTestCase(t, Bp2buildTestCase{
+ Description: "Android app - cert is not src or module",
+ ModuleTypeUnderTest: "android_app",
+ ModuleTypeUnderTestFactory: java.AndroidAppFactory,
+ Filesystem: map[string]string{
+ // deliberate empty
+ },
+ Blueprint: `
+android_app {
+ name: "TestApp",
+ certificate: "foocert",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("android_binary", "TestApp", AttrNameToString{
+ "certificate_name": `"foocert"`,
+ "manifest": `"AndroidManifest.xml"`,
+ "resource_files": `[]`,
+ }),
+ }})
+}
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
index b0a2966..b6061e4 100644
--- a/bp2build/apex_conversion_test.go
+++ b/bp2build/apex_conversion_test.go
@@ -22,6 +22,7 @@
"android/soong/java"
"android/soong/sh"
+ "fmt"
"testing"
)
@@ -41,6 +42,7 @@
ctx.RegisterModuleType("android_app_certificate", java.AndroidAppCertificateFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("prebuilt_etc", etc.PrebuiltEtcFactory)
+ ctx.RegisterModuleType("cc_test", cc.TestFactory)
}
func runOverrideApexTestCase(t *testing.T, tc Bp2buildTestCase) {
@@ -120,7 +122,7 @@
file_contexts: ":com.android.apogee-file_contexts",
min_sdk_version: "29",
key: "com.android.apogee.key",
- certificate: "com.android.apogee.certificate",
+ certificate: ":com.android.apogee.certificate",
updatable: false,
installable: false,
compressible: false,
@@ -153,10 +155,17 @@
"key": `":com.android.apogee.key"`,
"manifest": `"apogee_manifest.json"`,
"min_sdk_version": `"29"`,
- "native_shared_libs_32": `[
- ":native_shared_lib_1",
- ":native_shared_lib_2",
- ]`,
+ "native_shared_libs_32": `select({
+ "//build/bazel/platforms/arch:arm": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_2",
+ ],
+ "//build/bazel/platforms/arch:x86": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_2",
+ ],
+ "//conditions:default": [],
+ })`,
"native_shared_libs_64": `select({
"//build/bazel/platforms/arch:arm64": [
":native_shared_lib_1",
@@ -273,27 +282,30 @@
}
`,
},
- Blueprint: createMultilibBlueprint("both"),
+ Blueprint: createMultilibBlueprint(`compile_multilib: "both",`),
ExpectedBazelTargets: []string{
MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
"native_shared_libs_32": `[
- ":native_shared_lib_1",
- ":native_shared_lib_3",
+ ":unnested_native_shared_lib",
+ ":native_shared_lib_for_both",
+ ":native_shared_lib_for_lib32",
] + select({
- "//build/bazel/platforms/arch:arm": [":native_shared_lib_2"],
- "//build/bazel/platforms/arch:x86": [":native_shared_lib_2"],
+ "//build/bazel/platforms/arch:arm": [":native_shared_lib_for_first"],
+ "//build/bazel/platforms/arch:x86": [":native_shared_lib_for_first"],
"//conditions:default": [],
})`,
"native_shared_libs_64": `select({
"//build/bazel/platforms/arch:arm64": [
- ":native_shared_lib_1",
- ":native_shared_lib_4",
- ":native_shared_lib_2",
+ ":unnested_native_shared_lib",
+ ":native_shared_lib_for_both",
+ ":native_shared_lib_for_lib64",
+ ":native_shared_lib_for_first",
],
"//build/bazel/platforms/arch:x86_64": [
- ":native_shared_lib_1",
- ":native_shared_lib_4",
- ":native_shared_lib_2",
+ ":unnested_native_shared_lib",
+ ":native_shared_lib_for_both",
+ ":native_shared_lib_for_lib64",
+ ":native_shared_lib_for_first",
],
"//conditions:default": [],
})`,
@@ -303,53 +315,69 @@
}})
}
-func TestApexBundleCompileMultilibFirst(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - example with compile_multilib=first",
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}
-`,
- },
- Blueprint: createMultilibBlueprint("first"),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
- "native_shared_libs_32": `select({
+func TestApexBundleCompileMultilibFirstAndDefaultValue(t *testing.T) {
+ expectedBazelTargets := []string{
+ MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
+ "native_shared_libs_32": `select({
"//build/bazel/platforms/arch:arm": [
- ":native_shared_lib_1",
- ":native_shared_lib_3",
- ":native_shared_lib_2",
+ ":unnested_native_shared_lib",
+ ":native_shared_lib_for_both",
+ ":native_shared_lib_for_lib32",
+ ":native_shared_lib_for_first",
],
"//build/bazel/platforms/arch:x86": [
- ":native_shared_lib_1",
- ":native_shared_lib_3",
- ":native_shared_lib_2",
+ ":unnested_native_shared_lib",
+ ":native_shared_lib_for_both",
+ ":native_shared_lib_for_lib32",
+ ":native_shared_lib_for_first",
],
"//conditions:default": [],
})`,
- "native_shared_libs_64": `select({
+ "native_shared_libs_64": `select({
"//build/bazel/platforms/arch:arm64": [
- ":native_shared_lib_1",
- ":native_shared_lib_4",
- ":native_shared_lib_2",
+ ":unnested_native_shared_lib",
+ ":native_shared_lib_for_both",
+ ":native_shared_lib_for_lib64",
+ ":native_shared_lib_for_first",
],
"//build/bazel/platforms/arch:x86_64": [
- ":native_shared_lib_1",
- ":native_shared_lib_4",
- ":native_shared_lib_2",
+ ":unnested_native_shared_lib",
+ ":native_shared_lib_for_both",
+ ":native_shared_lib_for_lib64",
+ ":native_shared_lib_for_first",
],
"//conditions:default": [],
})`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- }),
- }})
+ "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
+ "manifest": `"apex_manifest.json"`,
+ }),
+ }
+
+ // "first" is the default value of compile_multilib prop so `compile_multilib_: "first"` and unset compile_multilib
+ // should result to the same bp2build output
+ compileMultiLibPropValues := []string{`compile_multilib: "first",`, ""}
+ for _, compileMultiLibProp := range compileMultiLibPropValues {
+ descriptionSuffix := compileMultiLibProp
+ if descriptionSuffix == "" {
+ descriptionSuffix = "compile_multilib unset"
+ }
+ runApexTestCase(t, Bp2buildTestCase{
+ Description: "apex - example with " + compileMultiLibProp,
+ ModuleTypeUnderTest: "apex",
+ ModuleTypeUnderTestFactory: apex.BundleFactory,
+ Filesystem: map[string]string{
+ "system/sepolicy/apex/Android.bp": `
+ filegroup {
+ name: "com.android.apogee-file_contexts",
+ srcs: [ "apogee-file_contexts", ],
+ bazel_module: { bp2build_available: false },
+ }
+ `,
+ },
+ Blueprint: createMultilibBlueprint(compileMultiLibProp),
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ }
}
func TestApexBundleCompileMultilib32(t *testing.T) {
@@ -366,15 +394,16 @@
}
`,
},
- Blueprint: createMultilibBlueprint("32"),
+ Blueprint: createMultilibBlueprint(`compile_multilib: "32",`),
ExpectedBazelTargets: []string{
MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
"native_shared_libs_32": `[
- ":native_shared_lib_1",
- ":native_shared_lib_3",
+ ":unnested_native_shared_lib",
+ ":native_shared_lib_for_both",
+ ":native_shared_lib_for_lib32",
] + select({
- "//build/bazel/platforms/arch:arm": [":native_shared_lib_2"],
- "//build/bazel/platforms/arch:x86": [":native_shared_lib_2"],
+ "//build/bazel/platforms/arch:arm": [":native_shared_lib_for_first"],
+ "//build/bazel/platforms/arch:x86": [":native_shared_lib_for_first"],
"//conditions:default": [],
})`,
"file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
@@ -397,19 +426,21 @@
}
`,
},
- Blueprint: createMultilibBlueprint("64"),
+ Blueprint: createMultilibBlueprint(`compile_multilib: "64",`),
ExpectedBazelTargets: []string{
MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
"native_shared_libs_64": `select({
"//build/bazel/platforms/arch:arm64": [
- ":native_shared_lib_1",
- ":native_shared_lib_4",
- ":native_shared_lib_2",
+ ":unnested_native_shared_lib",
+ ":native_shared_lib_for_both",
+ ":native_shared_lib_for_lib64",
+ ":native_shared_lib_for_first",
],
"//build/bazel/platforms/arch:x86_64": [
- ":native_shared_lib_1",
- ":native_shared_lib_4",
- ":native_shared_lib_2",
+ ":unnested_native_shared_lib",
+ ":native_shared_lib_for_both",
+ ":native_shared_lib_for_lib64",
+ ":native_shared_lib_for_first",
],
"//conditions:default": [],
})`,
@@ -419,6 +450,62 @@
}})
}
+func createMultilibBlueprint(compile_multilib string) string {
+ return fmt.Sprintf(`
+cc_library {
+ name: "native_shared_lib_for_both",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "native_shared_lib_for_first",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "native_shared_lib_for_lib32",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "native_shared_lib_for_lib64",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "unnested_native_shared_lib",
+ bazel_module: { bp2build_available: false },
+}
+
+apex {
+ name: "com.android.apogee",
+ %s
+ native_shared_libs: ["unnested_native_shared_lib"],
+ multilib: {
+ both: {
+ native_shared_libs: [
+ "native_shared_lib_for_both",
+ ],
+ },
+ first: {
+ native_shared_libs: [
+ "native_shared_lib_for_first",
+ ],
+ },
+ lib32: {
+ native_shared_libs: [
+ "native_shared_lib_for_lib32",
+ ],
+ },
+ lib64: {
+ native_shared_libs: [
+ "native_shared_lib_for_lib64",
+ ],
+ },
+ },
+}`, compile_multilib)
+}
+
func TestApexBundleDefaultPropertyValues(t *testing.T) {
runApexTestCase(t, Bp2buildTestCase{
Description: "apex - default property values",
@@ -474,56 +561,6 @@
}})
}
-func createMultilibBlueprint(compile_multilib string) string {
- return `
-cc_library {
- name: "native_shared_lib_1",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "native_shared_lib_2",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "native_shared_lib_3",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "native_shared_lib_4",
- bazel_module: { bp2build_available: false },
-}
-
-apex {
- name: "com.android.apogee",
- compile_multilib: "` + compile_multilib + `",
- multilib: {
- both: {
- native_shared_libs: [
- "native_shared_lib_1",
- ],
- },
- first: {
- native_shared_libs: [
- "native_shared_lib_2",
- ],
- },
- lib32: {
- native_shared_libs: [
- "native_shared_lib_3",
- ],
- },
- lib64: {
- native_shared_libs: [
- "native_shared_lib_4",
- ],
- },
- },
-}`
-}
-
func TestBp2BuildOverrideApex(t *testing.T) {
runOverrideApexTestCase(t, Bp2buildTestCase{
Description: "override_apex",
@@ -582,7 +619,7 @@
file_contexts: ":com.android.apogee-file_contexts",
min_sdk_version: "29",
key: "com.android.apogee.key",
- certificate: "com.android.apogee.certificate",
+ certificate: ":com.android.apogee.certificate",
updatable: false,
installable: false,
compressible: false,
@@ -618,7 +655,7 @@
name: "com.google.android.apogee",
base: ":com.android.apogee",
key: "com.google.android.apogee.key",
- certificate: "com.google.android.apogee.certificate",
+ certificate: ":com.google.android.apogee.certificate",
prebuilts: [],
compressible: true,
}
@@ -636,10 +673,17 @@
"key": `":com.google.android.apogee.key"`,
"manifest": `"apogee_manifest.json"`,
"min_sdk_version": `"29"`,
- "native_shared_libs_32": `[
- ":native_shared_lib_1",
- ":native_shared_lib_2",
- ]`,
+ "native_shared_libs_32": `select({
+ "//build/bazel/platforms/arch:arm": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_2",
+ ],
+ "//build/bazel/platforms/arch:x86": [
+ ":native_shared_lib_1",
+ ":native_shared_lib_2",
+ ],
+ "//conditions:default": [],
+ })`,
"native_shared_libs_64": `select({
"//build/bazel/platforms/arch:arm64": [
":native_shared_lib_1",
@@ -1016,3 +1060,218 @@
}),
}})
}
+
+func TestBp2BuildOverrideApex_CertificateNil(t *testing.T) {
+ runOverrideApexTestCase(t, Bp2buildTestCase{
+ Description: "override_apex - don't set default certificate",
+ ModuleTypeUnderTest: "override_apex",
+ ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+ Filesystem: map[string]string{},
+ Blueprint: `
+android_app_certificate {
+ name: "com.android.apogee.certificate",
+ certificate: "com.android.apogee",
+ bazel_module: { bp2build_available: false },
+}
+
+filegroup {
+ name: "com.android.apogee-file_contexts",
+ srcs: [
+ "com.android.apogee-file_contexts",
+ ],
+ bazel_module: { bp2build_available: false },
+}
+
+apex {
+ name: "com.android.apogee",
+ manifest: "apogee_manifest.json",
+ file_contexts: ":com.android.apogee-file_contexts",
+ certificate: ":com.android.apogee.certificate",
+ bazel_module: { bp2build_available: false },
+}
+
+override_apex {
+ name: "com.google.android.apogee",
+ base: ":com.android.apogee",
+ // certificate is deliberately omitted, and not converted to bazel,
+ // because the overridden apex shouldn't be using the base apex's cert.
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
+ "file_contexts": `":com.android.apogee-file_contexts"`,
+ "manifest": `"apogee_manifest.json"`,
+ }),
+ }})
+}
+
+func TestApexCertificateIsModule(t *testing.T) {
+ runApexTestCase(t, Bp2buildTestCase{
+ Description: "apex - certificate is module",
+ ModuleTypeUnderTest: "apex",
+ ModuleTypeUnderTestFactory: apex.BundleFactory,
+ Filesystem: map[string]string{},
+ Blueprint: `
+android_app_certificate {
+ name: "com.android.apogee.certificate",
+ certificate: "com.android.apogee",
+ bazel_module: { bp2build_available: false },
+}
+
+apex {
+ name: "com.android.apogee",
+ manifest: "apogee_manifest.json",
+ file_contexts: ":com.android.apogee-file_contexts",
+ certificate: ":com.android.apogee.certificate",
+}
+` + simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee-file_contexts"),
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
+ "certificate": `":com.android.apogee.certificate"`,
+ "file_contexts": `":com.android.apogee-file_contexts"`,
+ "manifest": `"apogee_manifest.json"`,
+ }),
+ }})
+}
+
+func TestApexCertificateIsSrc(t *testing.T) {
+ runApexTestCase(t, Bp2buildTestCase{
+ Description: "apex - certificate is src",
+ ModuleTypeUnderTest: "apex",
+ ModuleTypeUnderTestFactory: apex.BundleFactory,
+ Filesystem: map[string]string{},
+ Blueprint: `
+apex {
+ name: "com.android.apogee",
+ manifest: "apogee_manifest.json",
+ file_contexts: ":com.android.apogee-file_contexts",
+ certificate: "com.android.apogee.certificate",
+}
+` + simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee-file_contexts"),
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
+ "certificate_name": `"com.android.apogee.certificate"`,
+ "file_contexts": `":com.android.apogee-file_contexts"`,
+ "manifest": `"apogee_manifest.json"`,
+ }),
+ }})
+}
+
+func TestBp2BuildOverrideApex_CertificateIsModule(t *testing.T) {
+ runOverrideApexTestCase(t, Bp2buildTestCase{
+ Description: "override_apex - certificate is module",
+ ModuleTypeUnderTest: "override_apex",
+ ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+ Filesystem: map[string]string{},
+ Blueprint: `
+android_app_certificate {
+ name: "com.android.apogee.certificate",
+ certificate: "com.android.apogee",
+ bazel_module: { bp2build_available: false },
+}
+
+filegroup {
+ name: "com.android.apogee-file_contexts",
+ srcs: [
+ "com.android.apogee-file_contexts",
+ ],
+ bazel_module: { bp2build_available: false },
+}
+
+apex {
+ name: "com.android.apogee",
+ manifest: "apogee_manifest.json",
+ file_contexts: ":com.android.apogee-file_contexts",
+ certificate: ":com.android.apogee.certificate",
+ bazel_module: { bp2build_available: false },
+}
+
+android_app_certificate {
+ name: "com.google.android.apogee.certificate",
+ certificate: "com.google.android.apogee",
+ bazel_module: { bp2build_available: false },
+}
+
+override_apex {
+ name: "com.google.android.apogee",
+ base: ":com.android.apogee",
+ certificate: ":com.google.android.apogee.certificate",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
+ "file_contexts": `":com.android.apogee-file_contexts"`,
+ "certificate": `":com.google.android.apogee.certificate"`,
+ "manifest": `"apogee_manifest.json"`,
+ }),
+ }})
+}
+
+func TestBp2BuildOverrideApex_CertificateIsSrc(t *testing.T) {
+ runOverrideApexTestCase(t, Bp2buildTestCase{
+ Description: "override_apex - certificate is src",
+ ModuleTypeUnderTest: "override_apex",
+ ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+ Filesystem: map[string]string{},
+ Blueprint: `
+android_app_certificate {
+ name: "com.android.apogee.certificate",
+ certificate: "com.android.apogee",
+ bazel_module: { bp2build_available: false },
+}
+
+filegroup {
+ name: "com.android.apogee-file_contexts",
+ srcs: [
+ "com.android.apogee-file_contexts",
+ ],
+ bazel_module: { bp2build_available: false },
+}
+
+apex {
+ name: "com.android.apogee",
+ manifest: "apogee_manifest.json",
+ file_contexts: ":com.android.apogee-file_contexts",
+ certificate: ":com.android.apogee.certificate",
+ bazel_module: { bp2build_available: false },
+}
+
+override_apex {
+ name: "com.google.android.apogee",
+ base: ":com.android.apogee",
+ certificate: "com.google.android.apogee.certificate",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
+ "file_contexts": `":com.android.apogee-file_contexts"`,
+ "certificate_name": `"com.google.android.apogee.certificate"`,
+ "manifest": `"apogee_manifest.json"`,
+ }),
+ }})
+}
+
+func TestApexTestBundleSimple(t *testing.T) {
+ runApexTestCase(t, Bp2buildTestCase{
+ Description: "apex_test - simple",
+ ModuleTypeUnderTest: "apex_test",
+ ModuleTypeUnderTestFactory: apex.TestApexBundleFactory,
+ Filesystem: map[string]string{},
+ Blueprint: `
+cc_test { name: "cc_test_1", bazel_module: { bp2build_available: false } }
+
+apex_test {
+ name: "test_com.android.apogee",
+ file_contexts: "file_contexts_file",
+ tests: ["cc_test_1"],
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("apex", "test_com.android.apogee", AttrNameToString{
+ "file_contexts": `"file_contexts_file"`,
+ "manifest": `"apex_manifest.json"`,
+ "testonly": `True`,
+ "tests": `[":cc_test_1"]`,
+ }),
+ }})
+}
diff --git a/bp2build/apex_key_conversion_test.go b/bp2build/apex_key_conversion_test.go
index 15bccf7..f9a68c9 100644
--- a/bp2build/apex_key_conversion_test.go
+++ b/bp2build/apex_key_conversion_test.go
@@ -27,14 +27,18 @@
}
func registerApexKeyModuleTypes(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
}
-func TestApexKeySimple(t *testing.T) {
+func TestApexKeySimple_KeysAreSrcFilesInSameDir(t *testing.T) {
runApexKeyTestCase(t, Bp2buildTestCase{
- Description: "apex key - simple example",
+ Description: "apex key - keys are src files, use key attributes",
ModuleTypeUnderTest: "apex_key",
ModuleTypeUnderTestFactory: apex.ApexKeyFactory,
- Filesystem: map[string]string{},
+ Filesystem: map[string]string{
+ "com.android.apogee.avbpubkey": "",
+ "com.android.apogee.pem": "",
+ },
Blueprint: `
apex_key {
name: "com.android.apogee.key",
@@ -48,3 +52,46 @@
}),
}})
}
+
+func TestApexKeySimple_KeysAreSrcFilesNotInDir(t *testing.T) {
+ runApexKeyTestCase(t, Bp2buildTestCase{
+ Description: "apex key - keys are not src or module, use key_name attributes",
+ ModuleTypeUnderTest: "apex_key",
+ ModuleTypeUnderTestFactory: apex.ApexKeyFactory,
+ Filesystem: map[string]string{
+ // deliberately left empty
+ },
+ Blueprint: `
+apex_key {
+ name: "com.android.apogee.key",
+ public_key: "com.android.apogee.avbpubkey",
+ private_key: "com.android.apogee.pem",
+}
+`,
+ ExpectedBazelTargets: []string{MakeBazelTargetNoRestrictions("apex_key", "com.android.apogee.key", AttrNameToString{
+ "private_key_name": `"com.android.apogee.pem"`,
+ "public_key_name": `"com.android.apogee.avbpubkey"`,
+ }),
+ }})
+}
+
+func TestApexKey_KeysAreModules(t *testing.T) {
+ runApexKeyTestCase(t, Bp2buildTestCase{
+ Description: "apex key - keys are modules, use key attributes",
+ ModuleTypeUnderTest: "apex_key",
+ ModuleTypeUnderTestFactory: apex.ApexKeyFactory,
+ Filesystem: map[string]string{},
+ Blueprint: `
+apex_key {
+ name: "com.android.apogee.key",
+ public_key: ":com.android.apogee.avbpubkey",
+ private_key: ":com.android.apogee.pem",
+}
+` + simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee.avbpubkey") +
+ simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee.pem"),
+ ExpectedBazelTargets: []string{MakeBazelTargetNoRestrictions("apex_key", "com.android.apogee.key", AttrNameToString{
+ "private_key": `":com.android.apogee.pem"`,
+ "public_key": `":com.android.apogee.avbpubkey"`,
+ }),
+ }})
+}
diff --git a/bp2build/api_domain_conversion_test.go b/bp2build/api_domain_conversion_test.go
index fc9d1d5..224008f 100644
--- a/bp2build/api_domain_conversion_test.go
+++ b/bp2build/api_domain_conversion_test.go
@@ -60,7 +60,7 @@
"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
},
)
- RunBp2BuildTestCase(t, registerApiDomainModuleTypes, Bp2buildTestCase{
+ RunApiBp2BuildTestCase(t, registerApiDomainModuleTypes, Bp2buildTestCase{
Blueprint: bp,
ExpectedBazelTargets: []string{expectedBazelTarget},
Filesystem: fs,
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
index 0e3d2a5..a75a84e 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -26,7 +26,7 @@
// Codegen is the backend of bp2build. The code generator is responsible for
// writing .bzl files that are equivalent to Android.bp files that are capable
// of being built with Bazel.
-func Codegen(ctx *CodegenContext) CodegenMetrics {
+func Codegen(ctx *CodegenContext) *CodegenMetrics {
// This directory stores BUILD files that could be eventually checked-in.
bp2buildDir := android.PathForOutput(ctx, "bp2build")
if err := android.RemoveAllOutputDir(bp2buildDir); err != nil {
@@ -48,7 +48,7 @@
soongInjectionDir := android.PathForOutput(ctx, bazel.SoongInjectionDirName)
writeFiles(ctx, soongInjectionDir, CreateSoongInjectionFiles(ctx.Config(), res.metrics))
- return res.metrics
+ return &res.metrics
}
// Get the output directory and create it if it doesn't exist.
diff --git a/bp2build/bpf_conversion_test.go b/bp2build/bpf_conversion_test.go
new file mode 100644
index 0000000..1259f9e
--- /dev/null
+++ b/bp2build/bpf_conversion_test.go
@@ -0,0 +1,65 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bp2build
+
+import (
+ "android/soong/android"
+ "android/soong/bpf"
+
+ "testing"
+)
+
+func runBpfTestCase(t *testing.T, tc Bp2buildTestCase) {
+ t.Helper()
+ (&tc).ModuleTypeUnderTest = "bpf"
+ (&tc).ModuleTypeUnderTestFactory = bpf.BpfFactory
+ RunBp2BuildTestCase(t, registerBpfModuleTypes, tc)
+}
+
+func registerBpfModuleTypes(ctx android.RegistrationContext) {}
+
+func TestBpfSupportedAttrs(t *testing.T) {
+ runBpfTestCase(t, Bp2buildTestCase{
+ Description: "Bpf module only converts supported attributes",
+ Filesystem: map[string]string{},
+ Blueprint: `
+bpf {
+ name: "bpfTestOut.o",
+ srcs: ["bpfTestSrcOne.c",
+ "bpfTestSrcTwo.c"],
+ btf: true,
+ cflags: ["-bpfCflagOne",
+ "-bpfCflagTwo"],
+ include_dirs: ["ia/ib/ic"],
+ sub_dir: "sa/ab",
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("bpf", "bpfTestOut.o", AttrNameToString{
+ "absolute_includes": `["ia/ib/ic"]`,
+ "btf": `True`,
+ "copts": `[
+ "-bpfCflagOne",
+ "-bpfCflagTwo",
+ ]`,
+ "srcs": `[
+ "bpfTestSrcOne.c",
+ "bpfTestSrcTwo.c",
+ ]`,
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 36c3a48..5ab54e3 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -28,7 +28,6 @@
"android/soong/android"
"android/soong/bazel"
"android/soong/starlark_fmt"
-
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -137,7 +136,7 @@
type CodegenContext struct {
config android.Config
- context android.Context
+ context *android.Context
mode CodegenMode
additionalDeps []string
unconvertedDepMode unconvertedDepsMode
@@ -163,6 +162,9 @@
// This mode is used for discovering and introspecting the existing Soong
// module graph.
QueryView
+
+ // ApiBp2build - generate BUILD files for API contribution targets
+ ApiBp2build
)
type unconvertedDepsMode int
@@ -181,6 +183,8 @@
return "Bp2Build"
case QueryView:
return "QueryView"
+ case ApiBp2build:
+ return "ApiBp2build"
default:
return fmt.Sprintf("%d", mode)
}
@@ -199,12 +203,12 @@
return ctx.additionalDeps
}
-func (ctx *CodegenContext) Config() android.Config { return ctx.config }
-func (ctx *CodegenContext) Context() android.Context { return ctx.context }
+func (ctx *CodegenContext) Config() android.Config { return ctx.config }
+func (ctx *CodegenContext) Context() *android.Context { return ctx.context }
// NewCodegenContext creates a wrapper context that conforms to PathContext for
// writing BUILD files in the output directory.
-func NewCodegenContext(config android.Config, context android.Context, mode CodegenMode) *CodegenContext {
+func NewCodegenContext(config android.Config, context *android.Context, mode CodegenMode) *CodegenContext {
var unconvertedDeps unconvertedDepsMode
if config.IsEnvTrue("BP2BUILD_ERROR_UNCONVERTED") {
unconvertedDeps = errorModulesUnconvertedDeps
@@ -240,12 +244,7 @@
buildFileToTargets := make(map[string]BazelTargets)
// Simple metrics tracking for bp2build
- metrics := CodegenMetrics{
- ruleClassCount: make(map[string]uint64),
- convertedModulePathMap: make(map[string]string),
- convertedModuleTypeCount: make(map[string]uint64),
- totalModuleTypeCount: make(map[string]uint64),
- }
+ metrics := CreateCodegenMetrics()
dirs := make(map[string]bool)
@@ -327,6 +326,10 @@
errs = append(errs, err)
}
targets = append(targets, t)
+ case ApiBp2build:
+ if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() {
+ targets, errs = generateBazelTargets(bpCtx, aModule)
+ }
default:
errs = append(errs, fmt.Errorf("Unknown code-generation mode: %s", ctx.Mode()))
return
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index d29eb9c..c40c45a 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -209,7 +209,7 @@
_, errs = ctx.PrepareBuildActions(config)
android.FailIfErrored(t, errs)
- codegenCtx := NewCodegenContext(config, *ctx.Context, QueryView)
+ codegenCtx := NewCodegenContext(config, ctx.Context, QueryView)
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
android.FailIfErrored(t, err)
if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
@@ -369,6 +369,7 @@
x86_64: { arch_paths: ["x86_64.txt"] },
arm: { arch_paths: ["arm.txt"] },
arm64: { arch_paths: ["arm64.txt"] },
+ riscv64: { arch_paths: ["riscv64.txt"] },
},
target: {
linux: { arch_paths: ["linux.txt"] },
@@ -401,6 +402,10 @@
"arm64.txt",
"lib64.txt",
],
+ "//build/bazel/platforms/arch:riscv64": [
+ "riscv64.txt",
+ "lib64.txt",
+ ],
"//build/bazel/platforms/arch:x86": [
"x86.txt",
"lib32.txt",
@@ -525,7 +530,7 @@
return
}
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
android.FailIfErrored(t, err)
@@ -898,7 +903,7 @@
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
android.FailIfErrored(t, err)
if actualCount := len(bazelTargets); actualCount != testCase.expectedBazelTargetCount {
@@ -1151,7 +1156,7 @@
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
android.FailIfErrored(t, err)
if actualCount := len(bazelTargets); actualCount != testCase.expectedCount {
@@ -1258,7 +1263,7 @@
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
// For each directory, test that the expected number of generated targets is correct.
for dir, expectedCount := range testCase.expectedCount {
@@ -1393,7 +1398,7 @@
if testCase.Dir != "" {
checkDir = testCase.Dir
}
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
bazelTargets, err := generateBazelTargetsForDir(codegenCtx, checkDir)
android.FailIfErrored(t, err)
bazelTargets.sort()
@@ -1821,3 +1826,54 @@
})
}
}
+
+func TestLicensesAttrConversion(t *testing.T) {
+ RunBp2BuildTestCase(t,
+ func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("license", android.LicenseFactory)
+ },
+ Bp2buildTestCase{
+ Description: "Test that licenses: attribute is converted",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ Blueprint: `
+license {
+ name: "my_license",
+}
+filegroup {
+ name: "my_filegroup",
+ licenses: ["my_license"],
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "my_filegroup", AttrNameToString{
+ "applicable_licenses": `[":my_license"]`,
+ }),
+ MakeBazelTargetNoRestrictions("android_license", "my_license", AttrNameToString{}),
+ },
+ })
+}
+
+func TestGenerateApiBazelTargets(t *testing.T) {
+ bp := `
+ custom {
+ name: "foo",
+ api: "foo.txt",
+ }
+ `
+ expectedBazelTarget := MakeBazelTarget(
+ "custom_api_contribution",
+ "foo",
+ AttrNameToString{
+ "api": `"foo.txt"`,
+ },
+ )
+ registerCustomModule := func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
+ }
+ RunApiBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
+ Blueprint: bp,
+ ExpectedBazelTargets: []string{expectedBazelTarget},
+ Description: "Generating API contribution Bazel targets for custom module",
+ })
+}
diff --git a/bp2build/bzl_conversion_test.go b/bp2build/bzl_conversion_test.go
index 28d2c75..a8e557d 100644
--- a/bp2build/bzl_conversion_test.go
+++ b/bp2build/bzl_conversion_test.go
@@ -85,6 +85,7 @@
"soong_module_name": attr.string(mandatory = True),
"soong_module_variant": attr.string(),
"soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
+ "api": attr.string(),
"arch_paths": attr.string_list(),
"arch_paths_exclude": attr.string_list(),
# bazel_module start
@@ -119,6 +120,7 @@
"soong_module_name": attr.string(mandatory = True),
"soong_module_variant": attr.string(),
"soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
+ "api": attr.string(),
"arch_paths": attr.string_list(),
"arch_paths_exclude": attr.string_list(),
"bool_prop": attr.bool(),
@@ -149,6 +151,7 @@
"soong_module_name": attr.string(mandatory = True),
"soong_module_variant": attr.string(),
"soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
+ "api": attr.string(),
"arch_paths": attr.string_list(),
"arch_paths_exclude": attr.string_list(),
"bool_prop": attr.bool(),
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index c23779e..8aa2c3e 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -201,26 +201,65 @@
})
}
-func TestCcBinaryVersionScript(t *testing.T) {
+func TestCcBinaryVersionScriptAndDynamicList(t *testing.T) {
runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: `version script`,
+ description: `version script and dynamic list`,
blueprint: `
{rule_name} {
name: "foo",
include_build_directory: false,
version_script: "vs",
+ dynamic_list: "dynamic.list",
}
`,
targets: []testBazelTarget{
{"cc_binary", "foo", AttrNameToString{
- "additional_linker_inputs": `["vs"]`,
- "linkopts": `["-Wl,--version-script,$(location vs)"]`,
+ "additional_linker_inputs": `[
+ "vs",
+ "dynamic.list",
+ ]`,
+ "linkopts": `[
+ "-Wl,--version-script,$(location vs)",
+ "-Wl,--dynamic-list,$(location dynamic.list)",
+ ]`,
},
},
},
})
}
+func TestCcBinaryLdflagsSplitBySpaceExceptSoongAdded(t *testing.T) {
+ runCcBinaryTests(t, ccBinaryBp2buildTestCase{
+ description: "ldflags are split by spaces except for the ones added by soong (version script and dynamic list)",
+ blueprint: `
+{rule_name} {
+ name: "foo",
+ ldflags: [
+ "--nospace_flag",
+ "-z spaceflag",
+ ],
+ version_script: "version_script",
+ dynamic_list: "dynamic.list",
+ include_build_directory: false,
+}
+`,
+ targets: []testBazelTarget{
+ {"cc_binary", "foo", AttrNameToString{
+ "additional_linker_inputs": `[
+ "version_script",
+ "dynamic.list",
+ ]`,
+ "linkopts": `[
+ "--nospace_flag",
+ "-z",
+ "spaceflag",
+ "-Wl,--version-script,$(location version_script)",
+ "-Wl,--dynamic-list,$(location dynamic.list)",
+ ]`,
+ }}},
+ })
+}
+
func TestCcBinarySplitSrcsByLang(t *testing.T) {
runCcHostBinaryTestCase(t, ccBinaryBp2buildTestCase{
description: "split srcs by lang",
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 1b8e9b4..edb0c43 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -870,9 +870,9 @@
})}})
}
-func TestCcLibraryNonConfiguredVersionScript(t *testing.T) {
+func TestCcLibraryNonConfiguredVersionScriptAndDynamicList(t *testing.T) {
runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library non-configured version script",
+ Description: "cc_library non-configured version script and dynamic list",
ModuleTypeUnderTest: "cc_library",
ModuleTypeUnderTestFactory: cc.LibraryFactory,
Dir: "foo/bar",
@@ -882,6 +882,7 @@
name: "a",
srcs: ["a.cpp"],
version_script: "v.map",
+ dynamic_list: "dynamic.list",
bazel_module: { bp2build_available: true },
include_build_directory: false,
}
@@ -889,17 +890,23 @@
},
Blueprint: soongCcLibraryPreamble,
ExpectedBazelTargets: makeCcLibraryTargets("a", AttrNameToString{
- "additional_linker_inputs": `["v.map"]`,
- "linkopts": `["-Wl,--version-script,$(location v.map)"]`,
- "srcs": `["a.cpp"]`,
+ "additional_linker_inputs": `[
+ "v.map",
+ "dynamic.list",
+ ]`,
+ "linkopts": `[
+ "-Wl,--version-script,$(location v.map)",
+ "-Wl,--dynamic-list,$(location dynamic.list)",
+ ]`,
+ "srcs": `["a.cpp"]`,
}),
},
)
}
-func TestCcLibraryConfiguredVersionScript(t *testing.T) {
+func TestCcLibraryConfiguredVersionScriptAndDynamicList(t *testing.T) {
runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library configured version script",
+ Description: "cc_library configured version script and dynamic list",
ModuleTypeUnderTest: "cc_library",
ModuleTypeUnderTestFactory: cc.LibraryFactory,
Dir: "foo/bar",
@@ -911,9 +918,11 @@
arch: {
arm: {
version_script: "arm.map",
+ dynamic_list: "dynamic_arm.list",
},
arm64: {
version_script: "arm64.map",
+ dynamic_list: "dynamic_arm64.list",
},
},
@@ -925,13 +934,25 @@
Blueprint: soongCcLibraryPreamble,
ExpectedBazelTargets: makeCcLibraryTargets("a", AttrNameToString{
"additional_linker_inputs": `select({
- "//build/bazel/platforms/arch:arm": ["arm.map"],
- "//build/bazel/platforms/arch:arm64": ["arm64.map"],
+ "//build/bazel/platforms/arch:arm": [
+ "arm.map",
+ "dynamic_arm.list",
+ ],
+ "//build/bazel/platforms/arch:arm64": [
+ "arm64.map",
+ "dynamic_arm64.list",
+ ],
"//conditions:default": [],
})`,
"linkopts": `select({
- "//build/bazel/platforms/arch:arm": ["-Wl,--version-script,$(location arm.map)"],
- "//build/bazel/platforms/arch:arm64": ["-Wl,--version-script,$(location arm64.map)"],
+ "//build/bazel/platforms/arch:arm": [
+ "-Wl,--version-script,$(location arm.map)",
+ "-Wl,--dynamic-list,$(location dynamic_arm.list)",
+ ],
+ "//build/bazel/platforms/arch:arm64": [
+ "-Wl,--version-script,$(location arm64.map)",
+ "-Wl,--dynamic-list,$(location dynamic_arm64.list)",
+ ],
"//conditions:default": [],
})`,
"srcs": `["a.cpp"]`,
@@ -940,6 +961,46 @@
)
}
+func TestCcLibraryLdflagsSplitBySpaceExceptSoongAdded(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "ldflags are split by spaces except for the ones added by soong (version script and dynamic list)",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Filesystem: map[string]string{
+ "version_script": "",
+ "dynamic.list": "",
+ },
+ Blueprint: `
+cc_library {
+ name: "foo",
+ ldflags: [
+ "--nospace_flag",
+ "-z spaceflag",
+ ],
+ version_script: "version_script",
+ dynamic_list: "dynamic.list",
+ include_build_directory: false,
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "additional_linker_inputs": `[
+ "version_script",
+ "dynamic.list",
+ ]`,
+ "linkopts": `[
+ "--nospace_flag",
+ "-z",
+ "spaceflag",
+ "-Wl,--version-script,$(location version_script)",
+ "-Wl,--dynamic-list,$(location dynamic.list)",
+ ]`,
+ }),
+ },
+ })
+}
+
func TestCcLibrarySharedLibs(t *testing.T) {
runCcLibraryTestCase(t, Bp2buildTestCase{
Description: "cc_library shared_libs",
@@ -1348,6 +1409,7 @@
"strip": true,
"inject_bssl_hash": true,
"has_stubs": true,
+ "stubs_symbol_file": true,
"use_version_lib": true,
}
@@ -2649,7 +2711,8 @@
func TestCcLibraryStubs(t *testing.T) {
expectedBazelTargets := makeCcLibraryTargets("a", AttrNameToString{
- "has_stubs": `True`,
+ "has_stubs": `True`,
+ "stubs_symbol_file": `"a.map.txt"`,
})
expectedBazelTargets = append(expectedBazelTargets, makeCcStubSuiteTargets("a", AttrNameToString{
"soname": `"a.so"`,
@@ -2682,6 +2745,205 @@
)
}
+func TestCcApiContributionsWithHdrs(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libfoo",
+ stubs: { symbol_file: "libfoo.map.txt", versions: ["28", "29", "current"] },
+ llndk: { symbol_file: "libfoo.map.txt", override_export_include_dirs: ["dir2"]},
+ export_include_dirs: ["dir1"],
+ }
+ `
+ expectedBazelTargets := []string{
+ MakeBazelTarget(
+ "cc_api_library_headers",
+ "libfoo.systemapi.headers",
+ AttrNameToString{
+ "export_includes": `["dir1"]`,
+ }),
+ MakeBazelTarget(
+ "cc_api_library_headers",
+ "libfoo.vendorapi.headers",
+ AttrNameToString{
+ "export_includes": `["dir2"]`,
+ }),
+ MakeBazelTarget(
+ "cc_api_contribution",
+ "libfoo.contribution",
+ AttrNameToString{
+ "api": `"libfoo.map.txt"`,
+ "library_name": `"libfoo"`,
+ "api_surfaces": `[
+ "systemapi",
+ "vendorapi",
+ ]`,
+ "hdrs": `[
+ ":libfoo.systemapi.headers",
+ ":libfoo.vendorapi.headers",
+ ]`,
+ }),
+ }
+ RunApiBp2BuildTestCase(t, cc.RegisterLibraryBuildComponents, Bp2buildTestCase{
+ Blueprint: bp,
+ Description: "cc API contributions to systemapi and vendorapi",
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+}
+
+func TestCcApiSurfaceCombinations(t *testing.T) {
+ testCases := []struct {
+ bp string
+ expectedApi string
+ expectedApiSurfaces string
+ description string
+ }{
+ {
+ bp: `
+ cc_library {
+ name: "a",
+ stubs: {symbol_file: "a.map.txt"},
+ }`,
+ expectedApi: `"a.map.txt"`,
+ expectedApiSurfaces: `["systemapi"]`,
+ description: "Library that contributes to systemapi",
+ },
+ {
+ bp: `
+ cc_library {
+ name: "a",
+ llndk: {symbol_file: "a.map.txt"},
+ }`,
+ expectedApi: `"a.map.txt"`,
+ expectedApiSurfaces: `["vendorapi"]`,
+ description: "Library that contributes to vendorapi",
+ },
+ {
+ bp: `
+ cc_library {
+ name: "a",
+ llndk: {symbol_file: "a.map.txt"},
+ stubs: {symbol_file: "a.map.txt"},
+ }`,
+ expectedApi: `"a.map.txt"`,
+ expectedApiSurfaces: `[
+ "systemapi",
+ "vendorapi",
+ ]`,
+ description: "Library that contributes to systemapi and vendorapi",
+ },
+ }
+ for _, testCase := range testCases {
+ expectedBazelTargets := []string{
+ MakeBazelTarget(
+ "cc_api_contribution",
+ "a.contribution",
+ AttrNameToString{
+ "library_name": `"a"`,
+ "hdrs": `[]`,
+ "api": testCase.expectedApi,
+ "api_surfaces": testCase.expectedApiSurfaces,
+ },
+ ),
+ }
+ RunApiBp2BuildTestCase(t, cc.RegisterLibraryBuildComponents, Bp2buildTestCase{
+ Blueprint: testCase.bp,
+ Description: testCase.description,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ }
+}
+
+// llndk struct property in Soong provides users with several options to configure the exported include dirs
+// Test the generated bazel targets for the different configurations
+func TestCcVendorApiHeaders(t *testing.T) {
+ testCases := []struct {
+ bp string
+ expectedIncludes string
+ expectedSystemIncludes string
+ description string
+ }{
+ {
+ bp: `
+ cc_library {
+ name: "a",
+ export_include_dirs: ["include"],
+ export_system_include_dirs: ["base_system_include"],
+ llndk: {
+ symbol_file: "a.map.txt",
+ export_headers_as_system: true,
+ },
+ }
+ `,
+ expectedIncludes: "",
+ expectedSystemIncludes: `[
+ "base_system_include",
+ "include",
+ ]`,
+ description: "Headers are exported as system to API surface",
+ },
+ {
+ bp: `
+ cc_library {
+ name: "a",
+ export_include_dirs: ["include"],
+ export_system_include_dirs: ["base_system_include"],
+ llndk: {
+ symbol_file: "a.map.txt",
+ override_export_include_dirs: ["llndk_include"],
+ },
+ }
+ `,
+ expectedIncludes: `["llndk_include"]`,
+ expectedSystemIncludes: `["base_system_include"]`,
+ description: "Non-system Headers are ovverriden before export to API surface",
+ },
+ {
+ bp: `
+ cc_library {
+ name: "a",
+ export_include_dirs: ["include"],
+ export_system_include_dirs: ["base_system_include"],
+ llndk: {
+ symbol_file: "a.map.txt",
+ override_export_include_dirs: ["llndk_include"],
+ export_headers_as_system: true,
+ },
+ }
+ `,
+ expectedIncludes: "", // includes are set to nil
+ expectedSystemIncludes: `[
+ "base_system_include",
+ "llndk_include",
+ ]`,
+ description: "System Headers are extended before export to API surface",
+ },
+ }
+ for _, testCase := range testCases {
+ attrs := AttrNameToString{}
+ if testCase.expectedIncludes != "" {
+ attrs["export_includes"] = testCase.expectedIncludes
+ }
+ if testCase.expectedSystemIncludes != "" {
+ attrs["export_system_includes"] = testCase.expectedSystemIncludes
+ }
+
+ expectedBazelTargets := []string{
+ MakeBazelTarget("cc_api_library_headers", "a.vendorapi.headers", attrs),
+ // Create a target for cc_api_contribution target
+ MakeBazelTarget("cc_api_contribution", "a.contribution", AttrNameToString{
+ "api": `"a.map.txt"`,
+ "api_surfaces": `["vendorapi"]`,
+ "hdrs": `[":a.vendorapi.headers"]`,
+ "library_name": `"a"`,
+ }),
+ }
+ RunApiBp2BuildTestCase(t, cc.RegisterLibraryBuildComponents, Bp2buildTestCase{
+ Blueprint: testCase.bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ }
+}
+
func TestCcLibraryStubsAcrossConfigsDuplicatesRemoved(t *testing.T) {
runCcLibraryTestCase(t, Bp2buildTestCase{
Description: "stub target generation of the same lib across configs should not result in duplicates",
@@ -2716,6 +2978,63 @@
})
}
+func TestCcLibraryExcludesLibsHost(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Filesystem: map[string]string{
+ "bar.map.txt": "",
+ },
+ Blueprint: simpleModuleDoNotConvertBp2build("cc_library", "bazlib") + `
+cc_library {
+ name: "quxlib",
+ stubs: { symbol_file: "bar.map.txt", versions: ["current"] },
+ bazel_module: { bp2build_available: false },
+}
+cc_library {
+ name: "barlib",
+ stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] },
+ bazel_module: { bp2build_available: false },
+}
+cc_library {
+ name: "foolib",
+ shared_libs: ["barlib", "quxlib"],
+ target: {
+ host: {
+ shared_libs: ["bazlib"],
+ exclude_shared_libs: ["barlib"],
+ },
+ },
+ include_build_directory: false,
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: makeCcLibraryTargets("foolib", AttrNameToString{
+ "implementation_dynamic_deps": `select({
+ "//build/bazel/platforms/os:darwin": [":bazlib"],
+ "//build/bazel/platforms/os:linux": [":bazlib"],
+ "//build/bazel/platforms/os:linux_bionic": [":bazlib"],
+ "//build/bazel/platforms/os:linux_musl": [":bazlib"],
+ "//build/bazel/platforms/os:windows": [":bazlib"],
+ "//conditions:default": [],
+ }) + select({
+ "//build/bazel/platforms/os:darwin": [":quxlib"],
+ "//build/bazel/platforms/os:linux": [":quxlib"],
+ "//build/bazel/platforms/os:linux_bionic": [":quxlib"],
+ "//build/bazel/platforms/os:linux_musl": [":quxlib"],
+ "//build/bazel/platforms/os:windows": [":quxlib"],
+ "//build/bazel/rules/apex:android-in_apex": [
+ ":barlib_stub_libs_current",
+ ":quxlib_stub_libs_current",
+ ],
+ "//conditions:default": [
+ ":barlib",
+ ":quxlib",
+ ],
+ })`,
+ }),
+ })
+}
+
func TestCcLibraryEscapeLdflags(t *testing.T) {
runCcLibraryTestCase(t, Bp2buildTestCase{
ModuleTypeUnderTest: "cc_library",
@@ -3248,3 +3567,81 @@
},
})
}
+
+func TestCcLibraryWithTidy(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library uses tidy properties",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ srcs: ["foo.cpp"],
+ tidy: true,
+ tidy_checks: ["check1", "check2"],
+ tidy_checks_as_errors: ["check1error", "check2error"],
+ tidy_disabled_srcs: ["bar.cpp"],
+ tidy_timeout_srcs: ["baz.cpp"],
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "local_includes": `["."]`,
+ "srcs": `["foo.cpp"]`,
+ "tidy": `True`,
+ "tidy_checks": `[
+ "check1",
+ "check2",
+ ]`,
+ "tidy_checks_as_errors": `[
+ "check1error",
+ "check2error",
+ ]`,
+ "tidy_disabled_srcs": `["bar.cpp"]`,
+ "tidy_timeout_srcs": `["baz.cpp"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryHeaderAbiChecker(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library with header abi checker",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `cc_library {
+ name: "foo",
+ header_abi_checker: {
+ enabled: true,
+ symbol_file: "a.map.txt",
+ exclude_symbol_versions: [
+ "29",
+ "30",
+ ],
+ exclude_symbol_tags: [
+ "tag1",
+ "tag2",
+ ],
+ check_all_apis: true,
+ diff_flags: ["-allow-adding-removing-weak-symbols"],
+ },
+ include_build_directory: false,
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "abi_checker_enabled": `True`,
+ "abi_checker_symbol_file": `"a.map.txt"`,
+ "abi_checker_exclude_symbol_versions": `[
+ "29",
+ "30",
+ ]`,
+ "abi_checker_exclude_symbol_tags": `[
+ "tag1",
+ "tag2",
+ ]`,
+ "abi_checker_check_all_apis": `True`,
+ "abi_checker_diff_flags": `["-allow-adding-removing-weak-symbols"]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 5fa7cac..7d9db6f 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -123,6 +123,69 @@
})
}
+func TestCcApiHeaders(t *testing.T) {
+ fs := map[string]string{
+ "bar/Android.bp": `cc_library_headers { name: "bar_headers", }`,
+ }
+ bp := `
+ cc_library_headers {
+ name: "foo_headers",
+ export_include_dirs: ["dir1", "dir2"],
+ export_header_lib_headers: ["bar_headers"],
+
+ arch: {
+ arm: {
+ export_include_dirs: ["dir_arm"],
+ },
+ x86: {
+ export_include_dirs: ["dir_x86"],
+ },
+ },
+
+ target: {
+ android: {
+ export_include_dirs: ["dir1", "dir_android"],
+ },
+ windows: {
+ export_include_dirs: ["dir_windows"],
+ },
+ }
+ }
+ `
+ expectedBazelTargets := []string{
+ MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.arm", AttrNameToString{
+ "export_includes": `["dir_arm"]`,
+ "arch": `"arm"`,
+ }),
+ MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.x86", AttrNameToString{
+ "export_includes": `["dir_x86"]`,
+ "arch": `"x86"`,
+ }),
+ MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution.androidos", AttrNameToString{
+ "export_includes": `["dir_android"]`, // common includes are deduped
+ }),
+ // Windows headers are not exported
+ MakeBazelTarget("cc_api_library_headers", "foo_headers.contribution", AttrNameToString{
+ "export_includes": `[
+ "dir1",
+ "dir2",
+ ]`,
+ "deps": `[
+ "//bar:bar_headers.contribution",
+ ":foo_headers.contribution.arm",
+ ":foo_headers.contribution.x86",
+ ":foo_headers.contribution.androidos",
+ ]`,
+ }),
+ }
+ RunApiBp2BuildTestCase(t, cc.RegisterLibraryHeadersBuildComponents, Bp2buildTestCase{
+ Blueprint: bp,
+ Description: "Header library contributions to API surfaces",
+ ExpectedBazelTargets: expectedBazelTargets,
+ Filesystem: fs,
+ })
+}
+
func TestCcLibraryHeadersOsSpecificHeader(t *testing.T) {
runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
Description: "cc_library_headers test with os-specific header_libs props",
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index b1a9240..7e1d111 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -338,22 +338,66 @@
})
}
-func TestCcLibrarySharedVersionScript(t *testing.T) {
+func TestCcLibrarySharedVersionScriptAndDynamicList(t *testing.T) {
runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared version script",
+ Description: "cc_library_shared version script and dynamic list",
Filesystem: map[string]string{
"version_script": "",
+ "dynamic.list": "",
},
Blueprint: soongCcLibrarySharedPreamble + `
cc_library_shared {
name: "foo_shared",
version_script: "version_script",
+ dynamic_list: "dynamic.list",
include_build_directory: false,
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{
- "additional_linker_inputs": `["version_script"]`,
- "linkopts": `["-Wl,--version-script,$(location version_script)"]`,
+ "additional_linker_inputs": `[
+ "version_script",
+ "dynamic.list",
+ ]`,
+ "linkopts": `[
+ "-Wl,--version-script,$(location version_script)",
+ "-Wl,--dynamic-list,$(location dynamic.list)",
+ ]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryLdflagsSplitBySpaceSoongAdded(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "ldflags are split by spaces except for the ones added by soong (version script and dynamic list)",
+ Filesystem: map[string]string{
+ "version_script": "",
+ "dynamic.list": "",
+ },
+ Blueprint: `
+cc_library_shared {
+ name: "foo",
+ ldflags: [
+ "--nospace_flag",
+ "-z spaceflag",
+ ],
+ version_script: "version_script",
+ dynamic_list: "dynamic.list",
+ include_build_directory: false,
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "additional_linker_inputs": `[
+ "version_script",
+ "dynamic.list",
+ ]`,
+ "linkopts": `[
+ "--nospace_flag",
+ "-z",
+ "spaceflag",
+ "-Wl,--version-script,$(location version_script)",
+ "-Wl,--dynamic-list,$(location dynamic.list)",
+ ]`,
}),
},
})
@@ -499,7 +543,8 @@
]`,
}),
MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
- "has_stubs": `True`,
+ "has_stubs": `True`,
+ "stubs_symbol_file": `"a.map.txt"`,
}),
},
})
@@ -801,3 +846,43 @@
},
})
}
+
+func TestCcLibrarySharedHeaderAbiChecker(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_shared with header abi checker",
+ Blueprint: `cc_library_shared {
+ name: "foo",
+ header_abi_checker: {
+ enabled: true,
+ symbol_file: "a.map.txt",
+ exclude_symbol_versions: [
+ "29",
+ "30",
+ ],
+ exclude_symbol_tags: [
+ "tag1",
+ "tag2",
+ ],
+ check_all_apis: true,
+ diff_flags: ["-allow-adding-removing-weak-symbols"],
+ },
+ include_build_directory: false,
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "abi_checker_enabled": `True`,
+ "abi_checker_symbol_file": `"a.map.txt"`,
+ "abi_checker_exclude_symbol_versions": `[
+ "29",
+ "30",
+ ]`,
+ "abi_checker_exclude_symbol_tags": `[
+ "tag1",
+ "tag2",
+ ]`,
+ "abi_checker_check_all_apis": `True`,
+ "abi_checker_diff_flags": `["-allow-adding-removing-weak-symbols"]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index e3ea9a0..b47d1f1 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -836,6 +836,10 @@
"not-for-lib32.c",
"for-lib64.c",
],
+ "//build/bazel/platforms/arch:riscv64": [
+ "not-for-lib32.c",
+ "for-lib64.c",
+ ],
"//build/bazel/platforms/arch:x86": [
"not-for-lib64.c",
"for-lib32.c",
@@ -867,6 +871,7 @@
"for-lib64.c": "",
"not-for-arm.c": "",
"not-for-arm64.c": "",
+ "not-for-riscv64.c": "",
"not-for-x86.c": "",
"not-for-x86_64.c": "",
"not-for-lib32.c": "",
@@ -881,6 +886,7 @@
arch: {
arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
arm64: { srcs: ["for-arm64.c"], exclude_srcs: ["not-for-arm64.c"] },
+ riscv64: { srcs: ["for-riscv64.c"], exclude_srcs: ["not-for-riscv64.c"] },
x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] },
x86_64: { srcs: ["for-x86_64.c"], exclude_srcs: ["not-for-x86_64.c"] },
},
@@ -896,6 +902,7 @@
"//build/bazel/platforms/arch:arm": [
"not-for-arm64.c",
"not-for-lib64.c",
+ "not-for-riscv64.c",
"not-for-x86.c",
"not-for-x86_64.c",
"for-arm.c",
@@ -904,15 +911,26 @@
"//build/bazel/platforms/arch:arm64": [
"not-for-arm.c",
"not-for-lib32.c",
+ "not-for-riscv64.c",
"not-for-x86.c",
"not-for-x86_64.c",
"for-arm64.c",
"for-lib64.c",
],
+ "//build/bazel/platforms/arch:riscv64": [
+ "not-for-arm.c",
+ "not-for-arm64.c",
+ "not-for-lib32.c",
+ "not-for-x86.c",
+ "not-for-x86_64.c",
+ "for-riscv64.c",
+ "for-lib64.c",
+ ],
"//build/bazel/platforms/arch:x86": [
"not-for-arm.c",
"not-for-arm64.c",
"not-for-lib64.c",
+ "not-for-riscv64.c",
"not-for-x86_64.c",
"for-x86.c",
"for-lib32.c",
@@ -921,6 +939,7 @@
"not-for-arm.c",
"not-for-arm64.c",
"not-for-lib32.c",
+ "not-for-riscv64.c",
"not-for-x86.c",
"for-x86_64.c",
"for-lib64.c",
@@ -930,6 +949,7 @@
"not-for-arm64.c",
"not-for-lib32.c",
"not-for-lib64.c",
+ "not-for-riscv64.c",
"not-for-x86.c",
"not-for-x86_64.c",
],
diff --git a/bp2build/cc_prebuilt_binary_conversion_test.go b/bp2build/cc_prebuilt_binary_conversion_test.go
new file mode 100644
index 0000000..0e8048c
--- /dev/null
+++ b/bp2build/cc_prebuilt_binary_conversion_test.go
@@ -0,0 +1,125 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package bp2build
+
+import (
+ "fmt"
+ "testing"
+
+ "android/soong/cc"
+)
+
+func runCcPrebuiltBinaryTestCase(t *testing.T, testCase Bp2buildTestCase) {
+ t.Helper()
+ description := fmt.Sprintf("cc_prebuilt_binary: %s", testCase.Description)
+ testCase.ModuleTypeUnderTest = "cc_prebuilt_binary"
+ testCase.ModuleTypeUnderTestFactory = cc.PrebuiltBinaryFactory
+ testCase.Description = description
+ t.Run(description, func(t *testing.T) {
+ t.Helper()
+ RunBp2BuildTestCaseSimple(t, testCase)
+ })
+}
+
+func TestPrebuiltBinary(t *testing.T) {
+ runCcPrebuiltBinaryTestCase(t,
+ Bp2buildTestCase{
+ Description: "simple",
+ Filesystem: map[string]string{
+ "bin": "",
+ },
+ Blueprint: `
+cc_prebuilt_binary {
+ name: "bintest",
+ srcs: ["bin"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_binary", "bintest", AttrNameToString{
+ "src": `"bin"`,
+ })},
+ })
+}
+
+func TestPrebuiltBinaryWithStrip(t *testing.T) {
+ runCcPrebuiltBinaryTestCase(t,
+ Bp2buildTestCase{
+ Description: "with strip",
+ Filesystem: map[string]string{
+ "bin": "",
+ },
+ Blueprint: `
+cc_prebuilt_binary {
+ name: "bintest",
+ srcs: ["bin"],
+ strip: { all: true },
+ bazel_module: { bp2build_available: true },
+}`, ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_binary", "bintest", AttrNameToString{
+ "src": `"bin"`,
+ "strip": `{
+ "all": True,
+ }`,
+ }),
+ },
+ })
+}
+
+func TestPrebuiltBinaryWithArchVariance(t *testing.T) {
+ runCcPrebuiltBinaryTestCase(t,
+ Bp2buildTestCase{
+ Description: "with arch variance",
+ Filesystem: map[string]string{
+ "bina": "",
+ "binb": "",
+ },
+ Blueprint: `
+cc_prebuilt_binary {
+ name: "bintest",
+ arch: {
+ arm64: { srcs: ["bina"], },
+ arm: { srcs: ["binb"], },
+ },
+ bazel_module: { bp2build_available: true },
+}`, ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_binary", "bintest", AttrNameToString{
+ "src": `select({
+ "//build/bazel/platforms/arch:arm": "binb",
+ "//build/bazel/platforms/arch:arm64": "bina",
+ "//conditions:default": None,
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPrebuiltBinaryMultipleSrcsFails(t *testing.T) {
+ runCcPrebuiltBinaryTestCase(t,
+ Bp2buildTestCase{
+ Description: "fails because multiple sources",
+ Filesystem: map[string]string{
+ "bina": "",
+ "binb": "",
+ },
+ Blueprint: `
+cc_prebuilt_binary {
+ name: "bintest",
+ srcs: ["bina", "binb"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedErr: fmt.Errorf("Expected at most one source file"),
+ })
+}
+
+// TODO: nosrcs test
diff --git a/bp2build/cc_prebuilt_library_conversion_test.go b/bp2build/cc_prebuilt_library_conversion_test.go
index dd217c3..47006ac 100644
--- a/bp2build/cc_prebuilt_library_conversion_test.go
+++ b/bp2build/cc_prebuilt_library_conversion_test.go
@@ -36,10 +36,10 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
"static_library": `"libf.so"`,
}),
- MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
"shared_library": `"libf.so"`,
}),
},
@@ -66,14 +66,14 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
"static_library": `select({
"//build/bazel/platforms/arch:arm": "libg.so",
"//build/bazel/platforms/arch:arm64": "libf.so",
"//conditions:default": None,
})`,
}),
- MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
"shared_library": `select({
"//build/bazel/platforms/arch:arm": "libg.so",
"//build/bazel/platforms/arch:arm64": "libf.so",
@@ -104,13 +104,13 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
"static_library": `"libf.so"`,
"export_includes": `["testdir/1/"]`,
"export_system_includes": `["testdir/2/"]`,
}),
// TODO(b/229374533): When fixed, update this test
- MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
"shared_library": `"libf.so"`,
}),
},
@@ -185,10 +185,10 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
"static_library": `"libf.so"`,
}),
- MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
"shared_library": `"libg.so"`,
}),
},
@@ -215,7 +215,7 @@
// bazel_module: { bp2build_available: true },
//}`,
// expectedBazelTargets: []string{
-// makeBazelTarget("prebuilt_library_shared", "libtest", attrNameToString{
+// makeBazelTarget("cc_prebuilt_library_shared", "libtest", attrNameToString{
// "shared_library": `"libf.so"`,
// }),
// },
@@ -242,7 +242,7 @@
// bazel_module: { bp2build_available: true },
//}`,
// expectedBazelTargets: []string{
-// makeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", attrNameToString{
+// makeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", attrNameToString{
// "static_library": `"libf.so"`,
// }),
// },
diff --git a/bp2build/cc_prebuilt_library_shared_test.go b/bp2build/cc_prebuilt_library_shared_test.go
index 541ce5e..58c0a70 100644
--- a/bp2build/cc_prebuilt_library_shared_test.go
+++ b/bp2build/cc_prebuilt_library_shared_test.go
@@ -23,7 +23,7 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
"shared_library": `"libf.so"`,
}),
},
@@ -50,7 +50,7 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
"shared_library": `select({
"//build/bazel/platforms/arch:arm": "libg.so",
"//build/bazel/platforms/arch:arm64": "libf.so",
diff --git a/bp2build/cc_prebuilt_library_static_test.go b/bp2build/cc_prebuilt_library_static_test.go
index 69a1b5e..6116b00 100644
--- a/bp2build/cc_prebuilt_library_static_test.go
+++ b/bp2build/cc_prebuilt_library_static_test.go
@@ -36,7 +36,7 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_static", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
"static_library": `"libf.so"`,
}),
},
@@ -63,7 +63,7 @@
bazel_module: { bp2build_available: true },
}`,
ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_library_static", "libtest", AttrNameToString{
+ MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
"static_library": `select({
"//build/bazel/platforms/arch:arm": "libg.so",
"//build/bazel/platforms/arch:arm64": "libf.so",
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 522c10e..6eb93bc 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -23,6 +23,9 @@
func CreateSoongInjectionFiles(cfg android.Config, metrics CodegenMetrics) []BazelFile {
var files []BazelFile
+ files = append(files, newFile("android", GeneratedBuildFileName, "")) // Creates a //cc_toolchain package.
+ files = append(files, newFile("android", "constants.bzl", android.BazelCcToolchainVars(cfg)))
+
files = append(files, newFile("cc_toolchain", GeneratedBuildFileName, "")) // Creates a //cc_toolchain package.
files = append(files, newFile("cc_toolchain", "constants.bzl", cc_config.BazelCcToolchainVars(cfg)))
@@ -32,7 +35,7 @@
files = append(files, newFile("apex_toolchain", GeneratedBuildFileName, "")) // Creates a //apex_toolchain package.
files = append(files, newFile("apex_toolchain", "constants.bzl", apex.BazelApexToolchainVars()))
- files = append(files, newFile("metrics", "converted_modules.txt", strings.Join(metrics.convertedModules, "\n")))
+ files = append(files, newFile("metrics", "converted_modules.txt", strings.Join(metrics.Serialize().ConvertedModules, "\n")))
convertedModulePathMap, err := json.MarshalIndent(metrics.convertedModulePathMap, "", "\t")
if err != nil {
@@ -55,10 +58,6 @@
return files
}
-func convertedModules(convertedModules []string) string {
- return strings.Join(convertedModules, "\n")
-}
-
func CreateBazelFiles(
cfg android.Config,
ruleShims map[string]RuleShim,
@@ -97,7 +96,7 @@
targets.sort()
var content string
- if mode == Bp2Build {
+ if mode == Bp2Build || mode == ApiBp2build {
content = `# READ THIS FIRST:
# This file was automatically generated by bp2build for the Bazel migration project.
# Feel free to edit or test it, but do *not* check it into your version control system.
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index b696a98..8de2f83 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -84,10 +84,18 @@
func TestCreateBazelFiles_Bp2Build_CreatesDefaultFiles(t *testing.T) {
testConfig := android.TestConfig("", make(map[string]string), "", make(map[string][]byte))
- files := CreateSoongInjectionFiles(testConfig, CodegenMetrics{})
+ files := CreateSoongInjectionFiles(testConfig, CreateCodegenMetrics())
expectedFilePaths := []bazelFilepath{
{
+ dir: "android",
+ basename: GeneratedBuildFileName,
+ },
+ {
+ dir: "android",
+ basename: "constants.bzl",
+ },
+ {
dir: "cc_toolchain",
basename: GeneratedBuildFileName,
},
diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go
index 160395b..3490881 100644
--- a/bp2build/genrule_conversion_test.go
+++ b/bp2build/genrule_conversion_test.go
@@ -15,12 +15,13 @@
package bp2build
import (
+ "fmt"
+ "testing"
+
"android/soong/android"
"android/soong/cc"
"android/soong/genrule"
"android/soong/java"
- "fmt"
- "testing"
)
func registerGenruleModuleTypes(ctx android.RegistrationContext) {
@@ -643,3 +644,50 @@
})
}
}
+
+func TestCcGenruleArchAndExcludeSrcs(t *testing.T) {
+ name := "cc_genrule with arch"
+ bp := `
+ cc_genrule {
+ name: "foo",
+ srcs: [
+ "foo1.in",
+ "foo2.in",
+ ],
+ exclude_srcs: ["foo2.in"],
+ arch: {
+ arm: {
+ srcs: [
+ "foo1_arch.in",
+ "foo2_arch.in",
+ ],
+ exclude_srcs: ["foo2_arch.in"],
+ },
+ },
+ cmd: "cat $(in) > $(out)",
+ bazel_module: { bp2build_available: true },
+ }`
+
+ expectedBazelAttrs := AttrNameToString{
+ "srcs": `["foo1.in"] + select({
+ "//build/bazel/platforms/arch:arm": ["foo1_arch.in"],
+ "//conditions:default": [],
+ })`,
+ "cmd": `"cat $(SRCS) > $(OUTS)"`,
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ }
+
+ expectedBazelTargets := []string{
+ MakeBazelTargetNoRestrictions("genrule", "foo", expectedBazelAttrs),
+ }
+
+ t.Run(name, func(t *testing.T) {
+ RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
+ Bp2buildTestCase{
+ ModuleTypeUnderTest: "cc_genrule",
+ ModuleTypeUnderTestFactory: cc.GenRuleFactory,
+ Blueprint: bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ })
+}
diff --git a/bp2build/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go
index 86f3d42..e8551e5 100644
--- a/bp2build/java_binary_host_conversion_test.go
+++ b/bp2build/java_binary_host_conversion_test.go
@@ -29,10 +29,11 @@
RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("cc_library_host_shared", cc.LibraryHostSharedFactory)
ctx.RegisterModuleType("java_library", java.LibraryFactory)
+ ctx.RegisterModuleType("java_import_host", java.ImportFactory)
}, tc)
}
-var fs = map[string]string{
+var testFs = map[string]string{
"test.mf": "Main-Class: com.android.test.MainClass",
"other/Android.bp": `cc_library_host_shared {
name: "jni-lib-1",
@@ -43,7 +44,7 @@
func TestJavaBinaryHost(t *testing.T) {
runJavaBinaryHostTestCase(t, Bp2buildTestCase{
Description: "java_binary_host with srcs, exclude_srcs, jni_libs, javacflags, and manifest.",
- Filesystem: fs,
+ Filesystem: testFs,
Blueprint: `java_binary_host {
name: "java-binary-host-1",
srcs: ["a.java", "b.java"],
@@ -76,7 +77,7 @@
func TestJavaBinaryHostRuntimeDeps(t *testing.T) {
runJavaBinaryHostTestCase(t, Bp2buildTestCase{
Description: "java_binary_host with srcs, exclude_srcs, jni_libs, javacflags, and manifest.",
- Filesystem: fs,
+ Filesystem: testFs,
Blueprint: `java_binary_host {
name: "java-binary-host-1",
static_libs: ["java-dep-1"],
@@ -102,3 +103,34 @@
},
})
}
+
+func TestJavaBinaryHostLibs(t *testing.T) {
+ runJavaBinaryHostTestCase(t, Bp2buildTestCase{
+ Description: "java_binary_host with srcs, libs.",
+ Filesystem: testFs,
+ Blueprint: `java_binary_host {
+ name: "java-binary-host-libs",
+ libs: ["java-lib-dep-1"],
+ manifest: "test.mf",
+ srcs: ["a.java"],
+}
+
+java_import_host{
+ name: "java-lib-dep-1",
+ jars: ["foo.jar"],
+ bazel_module: { bp2build_available: false },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("java_binary", "java-binary-host-libs", AttrNameToString{
+ "main_class": `"com.android.test.MainClass"`,
+ "srcs": `["a.java"]`,
+ "deps": `[":java-lib-dep-1-neverlink"]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/java_import_conversion_test.go b/bp2build/java_import_conversion_test.go
index 05d7142..ac7dfff 100644
--- a/bp2build/java_import_conversion_test.go
+++ b/bp2build/java_import_conversion_test.go
@@ -48,6 +48,10 @@
MakeBazelTarget("java_import", "example_import", AttrNameToString{
"jars": `["import.jar"]`,
}),
+ MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
+ "exports": `[":example_import"]`,
+ "neverlink": `True`,
+ }),
}})
}
@@ -81,5 +85,35 @@
"//conditions:default": [],
})`,
}),
+ MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
+ "exports": `[":example_import"]`,
+ "neverlink": `True`,
+ }),
+ }})
+}
+
+func TestJavaImportHost(t *testing.T) {
+ runJavaImportTestCase(t, Bp2buildTestCase{
+ Description: "Java import host- simple example",
+ ModuleTypeUnderTest: "java_import_host",
+ ModuleTypeUnderTestFactory: java.ImportFactory,
+ Filesystem: map[string]string{
+ "import.jar": "",
+ },
+ Blueprint: `
+java_import_host {
+ name: "example_import",
+ jars: ["import.jar"],
+ bazel_module: { bp2build_available: true },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("java_import", "example_import", AttrNameToString{
+ "jars": `["import.jar"]`,
+ }),
+ MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
+ "exports": `[":example_import"]`,
+ "neverlink": `True`,
+ }),
}})
}
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index 74e2dbd..e37fa62 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -53,11 +53,13 @@
ExpectedBazelTargets: []string{
MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
"srcs": `["a.java"]`,
- "deps": `[":java-lib-2"]`,
+ "deps": `[":java-lib-2-neverlink"]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
MakeBazelTarget("java_library", "java-lib-2", AttrNameToString{
"srcs": `["b.java"]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-2"),
},
})
}
@@ -87,11 +89,12 @@
MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
"srcs": `["a.java"]`,
"deps": `[
- ":java-lib-2",
+ ":java-lib-2-neverlink",
":java-lib-3",
]`,
"exports": `[":java-lib-3"]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
},
})
}
@@ -113,6 +116,7 @@
MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
"exports": `[":java-lib-2"]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
},
})
}
@@ -152,6 +156,7 @@
MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
"plugins": `[":java-plugin-1"]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
},
}, func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("java_plugin", java.PluginFactory)
@@ -170,6 +175,7 @@
"srcs": `["a.java"]`,
"javacopts": `["-source 11 -target 11"]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
},
})
}
@@ -193,6 +199,7 @@
]`,
"srcs": `["a.java"]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
},
})
}
@@ -212,6 +219,7 @@
"javacopts": `["-Xsuper-fast"]`,
"srcs": `["a.java"]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
},
})
}
@@ -232,6 +240,7 @@
"javacopts": `["-Xsuper-fast"]`,
"srcs": `["a.java"]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
},
})
}
@@ -265,6 +274,7 @@
":example_lib_logtags",
]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "example_lib"),
}})
}
@@ -286,6 +296,7 @@
"res/b.res",
]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
},
})
}
@@ -310,6 +321,7 @@
"res/dir1/b.res",
]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
},
})
}
@@ -330,6 +342,7 @@
"resource_strip_prefix": `"res"`,
"resources": `["res/a.res"]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
},
})
}
@@ -354,6 +367,7 @@
"res/dir1/b.res",
]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
},
})
}
@@ -406,6 +420,7 @@
"b.java",
]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "example_lib"),
}})
}
@@ -435,6 +450,7 @@
"exports": `[":example_lib_java_aidl_library"]`,
"srcs": `["a.java"]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "example_lib"),
},
}, func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
@@ -490,6 +506,7 @@
":random_other_files",
]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "example_lib"),
MakeBazelTargetNoRestrictions("filegroup", "random_other_files", AttrNameToString{
"srcs": `[
"a.java",
@@ -529,6 +546,7 @@
MakeBazelTarget("java_library", "foo", AttrNameToString{
"exports": `[":foo_java_aidl_library"]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "foo"),
},
}, func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
@@ -649,3 +667,46 @@
}),
}})
}
+
+func TestJavaLibraryKotlinSrcs(t *testing.T) {
+ runJavaLibraryTestCase(t, Bp2buildTestCase{
+ Description: "java_library with kotlin srcs",
+ Blueprint: `java_library {
+ name: "java-lib-1",
+ srcs: ["a.java", "b.java", "c.kt"],
+ bazel_module: { bp2build_available: true },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("kt_jvm_library", "java-lib-1", AttrNameToString{
+ "srcs": `[
+ "a.java",
+ "b.java",
+ "c.kt",
+ ]`,
+ }),
+ },
+ })
+}
+
+func TestJavaLibraryKotlinCommonSrcs(t *testing.T) {
+ runJavaLibraryTestCase(t, Bp2buildTestCase{
+ Description: "java_library with kotlin common_srcs",
+ Blueprint: `java_library {
+ name: "java-lib-1",
+ srcs: ["a.java", "b.java"],
+ common_srcs: ["c.kt"],
+ bazel_module: { bp2build_available: true },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("kt_jvm_library", "java-lib-1", AttrNameToString{
+ "srcs": `[
+ "a.java",
+ "b.java",
+ ]`,
+ "common_srcs": `["c.kt"]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/java_library_host_conversion_test.go b/bp2build/java_library_host_conversion_test.go
index edd8690..14854c0 100644
--- a/bp2build/java_library_host_conversion_test.go
+++ b/bp2build/java_library_host_conversion_test.go
@@ -48,7 +48,15 @@
ExpectedBazelTargets: []string{
MakeBazelTarget("java_library", "java-lib-host-1", AttrNameToString{
"srcs": `["a.java"]`,
- "deps": `[":java-lib-host-2"]`,
+ "deps": `[":java-lib-host-2-neverlink"]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTarget("java_library", "java-lib-host-1-neverlink", AttrNameToString{
+ "exports": `[":java-lib-host-1"]`,
+ "neverlink": `True`,
"target_compatible_with": `select({
"//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
"//conditions:default": [],
@@ -62,6 +70,14 @@
"//conditions:default": [],
})`,
}),
+ MakeBazelTarget("java_library", "java-lib-host-2-neverlink", AttrNameToString{
+ "exports": `[":java-lib-host-2"]`,
+ "neverlink": `True`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
},
})
}
diff --git a/bp2build/java_proto_conversion_test.go b/bp2build/java_proto_conversion_test.go
index df0df2f..d25b7c4 100644
--- a/bp2build/java_proto_conversion_test.go
+++ b/bp2build/java_proto_conversion_test.go
@@ -91,6 +91,7 @@
MakeBazelTarget("java_library", "java-protos", AttrNameToString{
"exports": fmt.Sprintf(`[":%s"]`, javaLibraryName),
}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-protos"),
},
})
}
@@ -119,6 +120,7 @@
"exports": `[":java-protos_java_proto_lite"]`,
"javacopts": `["-source 1.7 -target 1.7"]`,
}),
+ MakeNeverlinkDuplicateTarget("java_library", "java-protos"),
},
})
}
diff --git a/bp2build/metrics.go b/bp2build/metrics.go
index 0b45996..bd21629 100644
--- a/bp2build/metrics.go
+++ b/bp2build/metrics.go
@@ -9,25 +9,16 @@
"android/soong/android"
"android/soong/shared"
"android/soong/ui/metrics/bp2build_metrics_proto"
+ "google.golang.org/protobuf/proto"
"github.com/google/blueprint"
)
-// Simple metrics struct to collect information about a Blueprint to BUILD
+// CodegenMetrics represents information about the Blueprint-to-BUILD
// conversion process.
+// Use CreateCodegenMetrics() to get a properly initialized instance
type CodegenMetrics struct {
- // Total number of Soong modules converted to generated targets
- generatedModuleCount uint64
-
- // Total number of Soong modules converted to handcrafted targets
- handCraftedModuleCount uint64
-
- // Total number of unconverted Soong modules
- unconvertedModuleCount uint64
-
- // Counts of generated Bazel targets per Bazel rule class
- ruleClassCount map[string]uint64
-
+ serialized *bp2build_metrics_proto.Bp2BuildMetrics
// List of modules with unconverted deps
// NOTE: NOT in the .proto
moduleWithUnconvertedDepsMsgs []string
@@ -36,40 +27,32 @@
// NOTE: NOT in the .proto
moduleWithMissingDepsMsgs []string
- // List of converted modules
- convertedModules []string
-
// Map of converted modules and paths to call
+ // NOTE: NOT in the .proto
convertedModulePathMap map[string]string
+}
- // Counts of converted modules by module type.
- convertedModuleTypeCount map[string]uint64
-
- // Counts of total modules by module type.
- totalModuleTypeCount map[string]uint64
-
- Events []*bp2build_metrics_proto.Event
+func CreateCodegenMetrics() CodegenMetrics {
+ return CodegenMetrics{
+ serialized: &bp2build_metrics_proto.Bp2BuildMetrics{
+ RuleClassCount: make(map[string]uint64),
+ ConvertedModuleTypeCount: make(map[string]uint64),
+ TotalModuleTypeCount: make(map[string]uint64),
+ },
+ convertedModulePathMap: make(map[string]string),
+ }
}
// Serialize returns the protoized version of CodegenMetrics: bp2build_metrics_proto.Bp2BuildMetrics
-func (metrics *CodegenMetrics) Serialize() bp2build_metrics_proto.Bp2BuildMetrics {
- return bp2build_metrics_proto.Bp2BuildMetrics{
- GeneratedModuleCount: metrics.generatedModuleCount,
- HandCraftedModuleCount: metrics.handCraftedModuleCount,
- UnconvertedModuleCount: metrics.unconvertedModuleCount,
- RuleClassCount: metrics.ruleClassCount,
- ConvertedModules: metrics.convertedModules,
- ConvertedModuleTypeCount: metrics.convertedModuleTypeCount,
- TotalModuleTypeCount: metrics.totalModuleTypeCount,
- Events: metrics.Events,
- }
+func (metrics *CodegenMetrics) Serialize() *bp2build_metrics_proto.Bp2BuildMetrics {
+ return metrics.serialized
}
// Print the codegen metrics to stdout.
func (metrics *CodegenMetrics) Print() {
generatedTargetCount := uint64(0)
- for _, ruleClass := range android.SortedStringKeys(metrics.ruleClassCount) {
- count := metrics.ruleClassCount[ruleClass]
+ for _, ruleClass := range android.SortedStringKeys(metrics.serialized.RuleClassCount) {
+ count := metrics.serialized.RuleClassCount[ruleClass]
fmt.Printf("[bp2build] %s: %d targets\n", ruleClass, count)
generatedTargetCount += count
}
@@ -80,9 +63,9 @@
%d converted modules have missing deps:
%s
`,
- metrics.generatedModuleCount,
+ metrics.serialized.GeneratedModuleCount,
generatedTargetCount,
- metrics.handCraftedModuleCount,
+ metrics.serialized.HandCraftedModuleCount,
metrics.TotalModuleCount(),
len(metrics.moduleWithUnconvertedDepsMsgs),
strings.Join(metrics.moduleWithUnconvertedDepsMsgs, "\n\t"),
@@ -119,29 +102,67 @@
fail(err, "Error outputting %s", metricsFile)
}
if _, err := os.Stat(metricsFile); err != nil {
- fail(err, "MISSING BP2BUILD METRICS OUTPUT: Failed to `stat` %s", metricsFile)
+ if os.IsNotExist(err) {
+ fail(err, "MISSING BP2BUILD METRICS OUTPUT: %s", metricsFile)
+ } else {
+ fail(err, "FAILED TO `stat` BP2BUILD METRICS OUTPUT: %s", metricsFile)
+ }
+ }
+}
+
+// ReadCodegenMetrics loads CodegenMetrics from `dir`
+// returns a nil pointer if the file doesn't exist
+func ReadCodegenMetrics(dir string) *CodegenMetrics {
+ metricsFile := filepath.Join(dir, bp2buildMetricsFilename)
+ if _, err := os.Stat(metricsFile); err != nil {
+ if os.IsNotExist(err) {
+ return nil
+ } else {
+ fail(err, "FAILED TO `stat` BP2BUILD METRICS OUTPUT: %s", metricsFile)
+ panic("unreachable after fail")
+ }
+ }
+ if buf, err := os.ReadFile(metricsFile); err != nil {
+ fail(err, "FAILED TO READ BP2BUILD METRICS OUTPUT: %s", metricsFile)
+ panic("unreachable after fail")
+ } else {
+ bp2BuildMetrics := bp2build_metrics_proto.Bp2BuildMetrics{
+ RuleClassCount: make(map[string]uint64),
+ ConvertedModuleTypeCount: make(map[string]uint64),
+ TotalModuleTypeCount: make(map[string]uint64),
+ }
+ if err := proto.Unmarshal(buf, &bp2BuildMetrics); err != nil {
+ fail(err, "FAILED TO PARSE BP2BUILD METRICS OUTPUT: %s", metricsFile)
+ }
+ return &CodegenMetrics{
+ serialized: &bp2BuildMetrics,
+ convertedModulePathMap: make(map[string]string),
+ }
}
}
func (metrics *CodegenMetrics) IncrementRuleClassCount(ruleClass string) {
- metrics.ruleClassCount[ruleClass] += 1
+ metrics.serialized.RuleClassCount[ruleClass] += 1
}
+func (metrics *CodegenMetrics) AddEvent(event *bp2build_metrics_proto.Event) {
+ metrics.serialized.Events = append(metrics.serialized.Events, event)
+}
func (metrics *CodegenMetrics) AddUnconvertedModule(moduleType string) {
- metrics.unconvertedModuleCount += 1
- metrics.totalModuleTypeCount[moduleType] += 1
+ metrics.serialized.UnconvertedModuleCount += 1
+ metrics.serialized.TotalModuleTypeCount[moduleType] += 1
}
func (metrics *CodegenMetrics) TotalModuleCount() uint64 {
- return metrics.handCraftedModuleCount +
- metrics.generatedModuleCount +
- metrics.unconvertedModuleCount
+ return metrics.serialized.HandCraftedModuleCount +
+ metrics.serialized.GeneratedModuleCount +
+ metrics.serialized.UnconvertedModuleCount
}
// Dump serializes the metrics to the given filename
func (metrics *CodegenMetrics) dump(filename string) (err error) {
ser := metrics.Serialize()
- return shared.Save(&ser, filename)
+ return shared.Save(ser, filename)
}
type ConversionType int
@@ -154,14 +175,14 @@
func (metrics *CodegenMetrics) AddConvertedModule(m blueprint.Module, moduleType string, dir string, conversionType ConversionType) {
// Undo prebuilt_ module name prefix modifications
moduleName := android.RemoveOptionalPrebuiltPrefix(m.Name())
- metrics.convertedModules = append(metrics.convertedModules, moduleName)
+ metrics.serialized.ConvertedModules = append(metrics.serialized.ConvertedModules, moduleName)
metrics.convertedModulePathMap[moduleName] = "//" + dir
- metrics.convertedModuleTypeCount[moduleType] += 1
- metrics.totalModuleTypeCount[moduleType] += 1
+ metrics.serialized.ConvertedModuleTypeCount[moduleType] += 1
+ metrics.serialized.TotalModuleTypeCount[moduleType] += 1
if conversionType == Handcrafted {
- metrics.handCraftedModuleCount += 1
+ metrics.serialized.HandCraftedModuleCount += 1
} else if conversionType == Generated {
- metrics.generatedModuleCount += 1
+ metrics.serialized.GeneratedModuleCount += 1
}
}
diff --git a/bp2build/ndk_headers_conversion_test.go b/bp2build/ndk_headers_conversion_test.go
index c7cc6b2..9d0f1f2 100644
--- a/bp2build/ndk_headers_conversion_test.go
+++ b/bp2build/ndk_headers_conversion_test.go
@@ -79,7 +79,7 @@
"hdrs": testCase.expectedHdrs,
},
)
- RunBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
+ RunApiBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
Description: testCase.desc,
Blueprint: fmt.Sprintf(bpTemplate, testCase.srcs, testCase.excludeSrcs),
ExpectedBazelTargets: []string{expectedBazelTarget},
@@ -121,7 +121,7 @@
"include_dir": testCase.expectedIncludeDir,
},
)
- RunBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
+ RunApiBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
Description: testCase.desc,
Blueprint: fmt.Sprintf(bpTemplate, testCase.from),
ExpectedBazelTargets: []string{expectedBazelTarget},
@@ -156,7 +156,7 @@
]`,
},
)
- RunBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
+ RunApiBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
Blueprint: bp,
Filesystem: fs,
ExpectedBazelTargets: []string{expectedBazelTarget},
diff --git a/bp2build/ndk_library_conversion_test.go b/bp2build/ndk_library_conversion_test.go
index 244ce20..819ab25 100644
--- a/bp2build/ndk_library_conversion_test.go
+++ b/bp2build/ndk_library_conversion_test.go
@@ -37,7 +37,7 @@
"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
},
)
- RunBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
+ RunApiBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
Blueprint: bp,
ExpectedBazelTargets: []string{expectedBazelTarget},
})
@@ -69,7 +69,7 @@
"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
},
)
- RunBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
+ RunApiBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
Blueprint: bp,
Filesystem: fs,
ExpectedBazelTargets: []string{expectedBazelTarget},
diff --git a/bp2build/performance_test.go b/bp2build/performance_test.go
index c4bbae2..272ebf5 100644
--- a/bp2build/performance_test.go
+++ b/bp2build/performance_test.go
@@ -22,11 +22,12 @@
// run for longer, set -benchtime to a larger value.
import (
- "android/soong/android"
"fmt"
"math"
"strings"
"testing"
+
+ "android/soong/android"
)
const (
@@ -105,7 +106,7 @@
ctx := android.NewTestContext(config)
registerCustomModuleForBp2buildConversion(ctx)
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
return testConfig{
config,
ctx,
diff --git a/bp2build/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go
index e8b9bc4..1b538d0 100644
--- a/bp2build/python_binary_conversion_test.go
+++ b/bp2build/python_binary_conversion_test.go
@@ -4,6 +4,7 @@
"testing"
"android/soong/android"
+ "android/soong/genrule"
"android/soong/python"
)
@@ -12,6 +13,8 @@
RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("python_library", python.PythonLibraryFactory)
ctx.RegisterModuleType("python_library_host", python.PythonLibraryHostFactory)
+ ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
+ ctx.RegisterModuleType("python_defaults", python.DefaultsFactory)
}, tc)
}
@@ -165,3 +168,152 @@
},
})
}
+
+func TestPythonBinaryMainIsNotSpecified(t *testing.T) {
+ runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+ Description: "python_binary_host main label in same package",
+ ModuleTypeUnderTest: "python_binary_host",
+ ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+ Blueprint: `python_binary_host {
+ name: "foo",
+ bazel_module: { bp2build_available: true },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("py_binary", "foo", AttrNameToString{
+ "imports": `["."]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPythonBinaryMainIsLabel(t *testing.T) {
+ runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+ Description: "python_binary_host main label in same package",
+ ModuleTypeUnderTest: "python_binary_host",
+ ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+ Blueprint: `python_binary_host {
+ name: "foo",
+ main: ":a",
+ bazel_module: { bp2build_available: true },
+}
+
+genrule {
+ name: "a",
+ bazel_module: { bp2build_available: false },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("py_binary", "foo", AttrNameToString{
+ "main": `":a"`,
+ "imports": `["."]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPythonBinaryMainIsSubpackageFile(t *testing.T) {
+ runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+ Description: "python_binary_host main is subpackage file",
+ ModuleTypeUnderTest: "python_binary_host",
+ ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+ Filesystem: map[string]string{
+ "a/Android.bp": "",
+ "a/b.py": "",
+ },
+ Blueprint: `python_binary_host {
+ name: "foo",
+ main: "a/b.py",
+ bazel_module: { bp2build_available: true },
+}
+
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("py_binary", "foo", AttrNameToString{
+ "main": `"//a:b.py"`,
+ "imports": `["."]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPythonBinaryMainIsSubDirFile(t *testing.T) {
+ runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+ Description: "python_binary_host main is file in sub directory that is not Bazel package",
+ ModuleTypeUnderTest: "python_binary_host",
+ ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+ Filesystem: map[string]string{
+ "a/b.py": "",
+ },
+ Blueprint: `python_binary_host {
+ name: "foo",
+ main: "a/b.py",
+ bazel_module: { bp2build_available: true },
+}
+
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("py_binary", "foo", AttrNameToString{
+ "main": `"a/b.py"`,
+ "imports": `["."]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPythonBinaryDuplicatesInRequired(t *testing.T) {
+ runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
+ Description: "python_binary_host duplicates in required attribute of the module and its defaults",
+ ModuleTypeUnderTest: "python_binary_host",
+ ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
+ Blueprint: `python_binary_host {
+ name: "foo",
+ main: "a.py",
+ defaults: ["d"],
+ required: [
+ "r1",
+ ],
+ bazel_module: { bp2build_available: true },
+}
+
+python_defaults {
+ name: "d",
+ required: [
+ "r1",
+ "r2",
+ ],
+}` + simpleModuleDoNotConvertBp2build("genrule", "r1") +
+ simpleModuleDoNotConvertBp2build("genrule", "r2"),
+
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("py_binary", "foo", AttrNameToString{
+ "main": `"a.py"`,
+ "imports": `["."]`,
+ "data": `[
+ ":r1",
+ ":r2",
+ ]`,
+ "target_compatible_with": `select({
+ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go
index 023ec96..81ec7ee 100644
--- a/bp2build/symlink_forest.go
+++ b/bp2build/symlink_forest.go
@@ -15,13 +15,16 @@
package bp2build
import (
+ "errors"
"fmt"
+ "io/fs"
"io/ioutil"
"os"
"path/filepath"
"regexp"
+ "sync"
+ "sync/atomic"
- "android/soong/android"
"android/soong/shared"
)
@@ -31,14 +34,78 @@
// or a directory. If excluded is true, then that file/directory should be
// excluded from symlinking. Otherwise, the node is not excluded, but one of its
// descendants is (otherwise the node in question would not exist)
-type node struct {
+
+type instructionsNode struct {
name string
excluded bool // If false, this is just an intermediate node
- children map[string]*node
+ children map[string]*instructionsNode
+}
+
+type symlinkForestContext struct {
+ verbose bool
+ topdir string // $TOPDIR
+
+ // State
+ wg sync.WaitGroup
+ depCh chan string
+ okay atomic.Bool // Whether the forest was successfully constructed
+}
+
+// A simple thread pool to limit concurrency on system calls.
+// Necessary because Go spawns a new OS-level thread for each blocking system
+// call. This means that if syscalls are too slow and there are too many of
+// them, the hard limit on OS-level threads can be exhausted.
+type syscallPool struct {
+ shutdownCh []chan<- struct{}
+ workCh chan syscall
+}
+
+type syscall struct {
+ work func()
+ done chan<- struct{}
+}
+
+func createSyscallPool(count int) *syscallPool {
+ result := &syscallPool{
+ shutdownCh: make([]chan<- struct{}, count),
+ workCh: make(chan syscall),
+ }
+
+ for i := 0; i < count; i++ {
+ shutdownCh := make(chan struct{})
+ result.shutdownCh[i] = shutdownCh
+ go result.worker(shutdownCh)
+ }
+
+ return result
+}
+
+func (p *syscallPool) do(work func()) {
+ doneCh := make(chan struct{})
+ p.workCh <- syscall{work, doneCh}
+ <-doneCh
+}
+
+func (p *syscallPool) shutdown() {
+ for _, ch := range p.shutdownCh {
+ ch <- struct{}{} // Blocks until the value is received
+ }
+}
+
+func (p *syscallPool) worker(shutdownCh <-chan struct{}) {
+ for {
+ select {
+ case <-shutdownCh:
+ return
+ case work := <-p.workCh:
+ work.work()
+ work.done <- struct{}{}
+ }
+ }
}
// Ensures that the node for the given path exists in the tree and returns it.
-func ensureNodeExists(root *node, path string) *node {
+func ensureNodeExists(root *instructionsNode, path string) *instructionsNode {
if path == "" {
return root
}
@@ -56,15 +123,14 @@
if child, ok := dn.children[base]; ok {
return child
} else {
- dn.children[base] = &node{base, false, make(map[string]*node)}
+ dn.children[base] = &instructionsNode{base, false, make(map[string]*instructionsNode)}
return dn.children[base]
}
}
-// Turns a list of paths to be excluded into a tree made of "node" objects where
-// the specified paths are marked as excluded.
-func treeFromExcludePathList(paths []string) *node {
- result := &node{"", false, make(map[string]*node)}
+// Turns a list of paths to be excluded into a tree
+func instructionsFromExcludePathList(paths []string) *instructionsNode {
+ result := &instructionsNode{"", false, make(map[string]*instructionsNode)}
for _, p := range paths {
ensureNodeExists(result, p).excluded = true
@@ -179,17 +245,23 @@
// Recursively plants a symlink forest at forestDir. The symlink tree will
// contain every file in buildFilesDir and srcDir excluding the files in
-// exclude. Collects every directory encountered during the traversal of srcDir
-// into acc.
-func plantSymlinkForestRecursive(cfg android.Config, topdir string, forestDir string, buildFilesDir string, srcDir string, exclude *node, acc *[]string, okay *bool) {
- if exclude != nil && exclude.excluded {
+// instructions. Collects every directory encountered during the traversal of
+// srcDir .
+func plantSymlinkForestRecursive(context *symlinkForestContext, instructions *instructionsNode, forestDir string, buildFilesDir string, srcDir string) {
+ defer context.wg.Done()
+
+ if instructions != nil && instructions.excluded {
// This directory is not needed, bail out
return
}
- *acc = append(*acc, srcDir)
- srcDirMap := readdirToMap(shared.JoinPath(topdir, srcDir))
- buildFilesMap := readdirToMap(shared.JoinPath(topdir, buildFilesDir))
+ // We don't add buildFilesDir here because the bp2build files marker files is
+ // already a dependency which covers it. If we ever wanted to turn this into
+ // a generic symlink forest creation tool, we'd need to add it, too.
+ context.depCh <- srcDir
+
+ srcDirMap := readdirToMap(shared.JoinPath(context.topdir, srcDir))
+ buildFilesMap := readdirToMap(shared.JoinPath(context.topdir, buildFilesDir))
renamingBuildFile := false
if _, ok := srcDirMap["BUILD"]; ok {
@@ -202,16 +274,16 @@
}
}
- allEntries := make(map[string]bool)
+ allEntries := make(map[string]struct{})
for n := range srcDirMap {
- allEntries[n] = true
+ allEntries[n] = struct{}{}
}
for n := range buildFilesMap {
- allEntries[n] = true
+ allEntries[n] = struct{}{}
}
- err := os.MkdirAll(shared.JoinPath(topdir, forestDir), 0777)
+ err := os.MkdirAll(shared.JoinPath(context.topdir, forestDir), 0777)
if err != nil {
fmt.Fprintf(os.Stderr, "Cannot mkdir '%s': %s\n", forestDir, err)
os.Exit(1)
@@ -230,89 +302,152 @@
}
buildFilesChild := shared.JoinPath(buildFilesDir, f)
- // Descend in the exclusion tree, if there are any excludes left
- var excludeChild *node = nil
- if exclude != nil {
+ // Descend in the instruction tree if it exists
+ var instructionsChild *instructionsNode = nil
+ if instructions != nil {
if f == "BUILD.bazel" && renamingBuildFile {
- excludeChild = exclude.children["BUILD"]
+ instructionsChild = instructions.children["BUILD"]
} else {
- excludeChild = exclude.children[f]
+ instructionsChild = instructions.children[f]
}
}
srcChildEntry, sExists := srcDirMap[f]
buildFilesChildEntry, bExists := buildFilesMap[f]
- if excludeChild != nil && excludeChild.excluded {
+ if instructionsChild != nil && instructionsChild.excluded {
if bExists {
- symlinkIntoForest(topdir, forestChild, buildFilesChild)
+ symlinkIntoForest(context.topdir, forestChild, buildFilesChild)
}
continue
}
- sDir := false
- bDir := false
- if sExists {
- sDir = isDir(shared.JoinPath(topdir, srcChild), srcChildEntry)
- }
-
- if bExists {
- bDir = isDir(shared.JoinPath(topdir, buildFilesChild), buildFilesChildEntry)
- }
+ sDir := sExists && isDir(shared.JoinPath(context.topdir, srcChild), srcChildEntry)
+ bDir := bExists && isDir(shared.JoinPath(context.topdir, buildFilesChild), buildFilesChildEntry)
if !sExists {
- if bDir && excludeChild != nil {
+ if bDir && instructionsChild != nil {
// Not in the source tree, but we have to exclude something from under
// this subtree, so descend
- plantSymlinkForestRecursive(cfg, topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay)
+ context.wg.Add(1)
+ go plantSymlinkForestRecursive(context, instructionsChild, forestChild, buildFilesChild, srcChild)
} else {
// Not in the source tree, symlink BUILD file
- symlinkIntoForest(topdir, forestChild, buildFilesChild)
+ symlinkIntoForest(context.topdir, forestChild, buildFilesChild)
}
} else if !bExists {
- if sDir && excludeChild != nil {
+ if sDir && instructionsChild != nil {
// Not in the build file tree, but we have to exclude something from
// under this subtree, so descend
- plantSymlinkForestRecursive(cfg, topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay)
+ context.wg.Add(1)
+ go plantSymlinkForestRecursive(context, instructionsChild, forestChild, buildFilesChild, srcChild)
} else {
// Not in the build file tree, symlink source tree, carry on
- symlinkIntoForest(topdir, forestChild, srcChild)
+ symlinkIntoForest(context.topdir, forestChild, srcChild)
}
} else if sDir && bDir {
// Both are directories. Descend.
- plantSymlinkForestRecursive(cfg, topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay)
+ context.wg.Add(1)
+ go plantSymlinkForestRecursive(context, instructionsChild, forestChild, buildFilesChild, srcChild)
} else if !sDir && !bDir {
// Neither is a directory. Merge them.
- srcBuildFile := shared.JoinPath(topdir, srcChild)
- generatedBuildFile := shared.JoinPath(topdir, buildFilesChild)
- err = mergeBuildFiles(shared.JoinPath(topdir, forestChild), srcBuildFile, generatedBuildFile, cfg.IsEnvTrue("BP2BUILD_VERBOSE"))
+ srcBuildFile := shared.JoinPath(context.topdir, srcChild)
+ generatedBuildFile := shared.JoinPath(context.topdir, buildFilesChild)
+ // The Android.bp file that codegen used to produce `buildFilesChild` is
+ // already a dependency, we can ignore `buildFilesChild`.
+ context.depCh <- srcChild
+ err = mergeBuildFiles(shared.JoinPath(context.topdir, forestChild), srcBuildFile, generatedBuildFile, context.verbose)
if err != nil {
fmt.Fprintf(os.Stderr, "Error merging %s and %s: %s",
srcBuildFile, generatedBuildFile, err)
- *okay = false
+ context.okay.Store(false)
}
} else {
// Both exist and one is a file. This is an error.
fmt.Fprintf(os.Stderr,
"Conflict in workspace symlink tree creation: both '%s' and '%s' exist and exactly one is a directory\n",
srcChild, buildFilesChild)
- *okay = false
+ context.okay.Store(false)
}
}
}
+func removeParallelRecursive(pool *syscallPool, path string, fi os.FileInfo, wg *sync.WaitGroup) {
+ defer wg.Done()
+
+ if fi.IsDir() {
+ children := readdirToMap(path)
+ childrenWg := &sync.WaitGroup{}
+ childrenWg.Add(len(children))
+
+ for child, childFi := range children {
+ go removeParallelRecursive(pool, shared.JoinPath(path, child), childFi, childrenWg)
+ }
+
+ childrenWg.Wait()
+ }
+
+ pool.do(func() {
+ if err := os.Remove(path); err != nil {
+ fmt.Fprintf(os.Stderr, "Cannot unlink '%s': %s\n", path, err)
+ os.Exit(1)
+ }
+ })
+}
+
+func removeParallel(path string) {
+ fi, err := os.Lstat(path)
+ if err != nil {
+ if errors.Is(err, fs.ErrNotExist) {
+ return
+ }
+
+ fmt.Fprintf(os.Stderr, "Cannot lstat '%s': %s\n", path, err)
+ os.Exit(1)
+ }
+
+ wg := &sync.WaitGroup{}
+ wg.Add(1)
+
+ // Random guess as to the best number of syscalls to run in parallel
+ pool := createSyscallPool(100)
+ removeParallelRecursive(pool, path, fi, wg)
+ pool.shutdown()
+
+ wg.Wait()
+}
+
// Creates a symlink forest by merging the directory tree at "buildFiles" and
// "srcDir" while excluding paths listed in "exclude". Returns the set of paths
// under srcDir on which readdir() had to be called to produce the symlink
// forest.
-func PlantSymlinkForest(cfg android.Config, topdir string, forest string, buildFiles string, srcDir string, exclude []string) []string {
+func PlantSymlinkForest(verbose bool, topdir string, forest string, buildFiles string, exclude []string) []string {
+ context := &symlinkForestContext{
+ verbose: verbose,
+ topdir: topdir,
+ depCh: make(chan string),
+ }
+
+ context.okay.Store(true)
+
+ removeParallel(shared.JoinPath(topdir, forest))
+
+ instructions := instructionsFromExcludePathList(exclude)
+ go func() {
+ context.wg.Add(1)
+ plantSymlinkForestRecursive(context, instructions, forest, buildFiles, ".")
+ context.wg.Wait()
+ close(context.depCh)
+ }()
+
deps := make([]string, 0)
- os.RemoveAll(shared.JoinPath(topdir, forest))
- excludeTree := treeFromExcludePathList(exclude)
- okay := true
- plantSymlinkForestRecursive(cfg, topdir, forest, buildFiles, srcDir, excludeTree, &deps, &okay)
- if !okay {
+ for dep := range context.depCh {
+ deps = append(deps, dep)
+ }
+
+ if !context.okay.Load() {
os.Exit(1)
}
+
return deps
}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index c2c1b19..4e63d19 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -24,6 +24,8 @@
"strings"
"testing"
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
"android/soong/android/allowlists"
"android/soong/bazel"
@@ -89,6 +91,24 @@
func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
t.Helper()
+ bp2buildSetup := func(ctx *android.TestContext) {
+ registerModuleTypes(ctx)
+ ctx.RegisterForBazelConversion()
+ }
+ runBp2BuildTestCaseWithSetup(t, bp2buildSetup, tc)
+}
+
+func RunApiBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
+ t.Helper()
+ apiBp2BuildSetup := func(ctx *android.TestContext) {
+ registerModuleTypes(ctx)
+ ctx.RegisterForApiBazelConversion()
+ }
+ runBp2BuildTestCaseWithSetup(t, apiBp2BuildSetup, tc)
+}
+
+func runBp2BuildTestCaseWithSetup(t *testing.T, setup func(ctx *android.TestContext), tc Bp2buildTestCase) {
+ t.Helper()
dir := "."
filesystem := make(map[string][]byte)
toParse := []string{
@@ -103,7 +123,7 @@
config := android.TestConfig(buildDir, nil, tc.Blueprint, filesystem)
ctx := android.NewTestContext(config)
- registerModuleTypes(ctx)
+ setup(ctx)
ctx.RegisterModuleType(tc.ModuleTypeUnderTest, tc.ModuleTypeUnderTestFactory)
// A default configuration for tests to not have to specify bp2build_available on top level targets.
@@ -118,7 +138,6 @@
})
}
ctx.RegisterBp2BuildConfig(bp2buildConfig)
- ctx.RegisterForBazelConversion()
_, parseErrs := ctx.ParseFileList(dir, toParse)
if errored(t, tc, parseErrs) {
@@ -138,7 +157,7 @@
if tc.Dir != "" {
checkDir = tc.Dir
}
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build)
codegenCtx.unconvertedDepMode = tc.UnconvertedDepsMode
bazelTargets, errs := generateBazelTargetsForDir(codegenCtx, checkDir)
if tc.ExpectedErr != nil {
@@ -198,6 +217,8 @@
// Prop used to indicate this conversion should be 1 module -> multiple targets
One_to_many_prop *bool
+
+ Api *string // File describing the APIs of this module
}
type customModule struct {
@@ -320,6 +341,7 @@
String_ptr_prop *string
String_list_prop []string
Arch_paths bazel.LabelListAttribute
+ Api bazel.LabelAttribute
}
func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
@@ -364,6 +386,23 @@
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
}
+var _ android.ApiProvider = (*customModule)(nil)
+
+func (c *customModule) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "custom_api_contribution",
+ }
+ apiAttribute := bazel.MakeLabelAttribute(
+ android.BazelLabelForModuleSrcSingle(ctx, proptools.String(c.props.Api)).Label,
+ )
+ attrs := &customBazelModuleAttributes{
+ Api: *apiAttribute,
+ }
+ ctx.CreateBazelTargetModule(props,
+ android.CommonAttributes{Name: c.Name()},
+ attrs)
+}
+
// A bp2build mutator that uses load statements and creates a 1:M mapping from
// module to target.
func customBp2buildOneToMany(ctx android.TopDownMutatorContext, m *customModule) {
@@ -493,3 +532,10 @@
}
return MakeBazelTarget("cc_stub_suite", name+"_stub_libs", stubSuiteAttrs)
}
+
+func MakeNeverlinkDuplicateTarget(moduleType string, name string) string {
+ return MakeBazelTarget(moduleType, name+"-neverlink", AttrNameToString{
+ "neverlink": `True`,
+ "exports": `[":` + name + `"]`,
+ })
+}
diff --git a/bpf/bpf.go b/bpf/bpf.go
index e89cc4e..a840fa3 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -18,9 +18,13 @@
"fmt"
"io"
"path/filepath"
+ "runtime"
"strings"
"android/soong/android"
+ "android/soong/bazel"
+ "android/soong/bazel/cquery"
+ "android/soong/cc"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -29,6 +33,7 @@
func init() {
registerBpfBuildComponents(android.InitRegistrationContext)
pctx.Import("android/soong/cc/config")
+ pctx.StaticVariable("relPwd", cc.PwdPrefix())
}
var (
@@ -38,7 +43,7 @@
blueprint.RuleParams{
Depfile: "${out}.d",
Deps: blueprint.DepsGCC,
- Command: "$ccCmd --target=bpf -c $cFlags -MD -MF ${out}.d -o $out $in",
+ Command: "$relPwd $ccCmd --target=bpf -c $cFlags -MD -MF ${out}.d -o $out $in",
CommandDeps: []string{"$ccCmd"},
},
"ccCmd", "cFlags")
@@ -93,6 +98,7 @@
type bpf struct {
android.ModuleBase
+ android.BazelModuleBase
properties BpfProperties
@@ -161,6 +167,9 @@
if proptools.Bool(bpf.properties.Btf) {
cflags = append(cflags, "-g")
+ if runtime.GOOS != "darwin" {
+ cflags = append(cflags, "-fdebug-prefix-map=/proc/self/cwd=")
+ }
}
srcs := android.PathsForModuleSrc(ctx, bpf.properties.Srcs)
@@ -237,6 +246,35 @@
}
}
+var _ android.MixedBuildBuildable = (*bpf)(nil)
+
+func (bpf *bpf) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
+ return true
+}
+
+func (bpf *bpf) QueueBazelCall(ctx android.BaseModuleContext) {
+ bazelCtx := ctx.Config().BazelContext
+ bazelCtx.QueueBazelRequest(
+ bpf.GetBazelLabel(ctx, bpf),
+ cquery.GetOutputFiles,
+ android.GetConfigKey(ctx))
+}
+
+func (bpf *bpf) ProcessBazelQueryResponse(ctx android.ModuleContext) {
+ bazelCtx := ctx.Config().BazelContext
+ objPaths, err := bazelCtx.GetOutputFiles(bpf.GetBazelLabel(ctx, bpf), android.GetConfigKey(ctx))
+ if err != nil {
+ ctx.ModuleErrorf(err.Error())
+ return
+ }
+
+ bazelOuts := android.Paths{}
+ for _, p := range objPaths {
+ bazelOuts = append(bazelOuts, android.PathForBazelOut(ctx, p))
+ }
+ bpf.objs = bazelOuts
+}
+
// Implements OutputFileFileProducer interface so that the obj output can be used in the data property
// of other modules.
func (bpf *bpf) OutputFiles(tag string) (android.Paths, error) {
@@ -260,5 +298,39 @@
module.AddProperties(&module.properties)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitBazelModule(module)
return module
}
+
+type bazelBpfAttributes struct {
+ Srcs bazel.LabelListAttribute
+ Copts bazel.StringListAttribute
+ Absolute_includes bazel.StringListAttribute
+ Btf *bool
+ // TODO(b/249528391): Add support for sub_dir
+}
+
+// bpf bp2build converter
+func (b *bpf) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ if ctx.ModuleType() != "bpf" {
+ return
+ }
+
+ srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, b.properties.Srcs))
+ copts := bazel.MakeStringListAttribute(b.properties.Cflags)
+ absolute_includes := bazel.MakeStringListAttribute(b.properties.Include_dirs)
+ btf := b.properties.Btf
+
+ attrs := bazelBpfAttributes{
+ Srcs: srcs,
+ Copts: copts,
+ Absolute_includes: absolute_includes,
+ Btf: btf,
+ }
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "bpf",
+ Bzl_load_location: "//build/bazel/rules/bpf:bpf.bzl",
+ }
+
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: b.Name()}, &attrs)
+}
diff --git a/bpf/bpf_test.go b/bpf/bpf_test.go
index 6e39096..a2010ff 100644
--- a/bpf/bpf_test.go
+++ b/bpf/bpf_test.go
@@ -71,3 +71,26 @@
`\QAndroid.bp:2:3: module "bpf_invalid_name.o" variant "android_common": invalid character '_' in source name\E`)).
RunTestWithBp(t, bp)
}
+
+func TestBpfWithBazel(t *testing.T) {
+ bp := `
+ bpf {
+ name: "bpf.o",
+ srcs: ["bpf.c"],
+ bazel_module: { label: "//bpf" },
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ prepareForBpfTest, android.FixtureModifyConfig(func(config android.Config) {
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: "outputbase",
+ LabelToOutputFiles: map[string][]string{
+ "//bpf": []string{"bpf.o"}}}
+ })).RunTestWithBp(t, bp)
+
+ output := result.Module("bpf.o", "android_common").(*bpf)
+
+ expectedOutputFiles := []string{"outputbase/execroot/__main__/bpf.o"}
+ android.AssertDeepEquals(t, "output files", expectedOutputFiles, output.objs.Strings())
+}
diff --git a/build_test.bash b/build_test.bash
index 8b91e2c..eda4beb 100755
--- a/build_test.bash
+++ b/build_test.bash
@@ -29,6 +29,9 @@
linux_bionic
mainline_sdk
ndk
+
+ # New architecture bringup, fails without ALLOW_MISSING_DEPENDENCIES=true
+ aosp_riscv64
)
# To track how long we took to startup. %N isn't supported on Darwin, but
@@ -45,8 +48,10 @@
case $(uname) in
Linux)
- export LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so
- export SEGFAULT_USE_ALTSTACK=1
+ if [[ -f /lib/x86_64-linux-gnu/libSegFault.so ]]; then
+ export LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so
+ export SEGFAULT_USE_ALTSTACK=1
+ fi
ulimit -a
;;
esac
@@ -59,7 +64,7 @@
echo
echo "Running Bazel smoke test..."
-STANDALONE_BAZEL=true "${TOP}/tools/bazel" --batch --max_idle_secs=1 info
+STANDALONE_BAZEL=true "${TOP}/build/bazel/bin/bazel" --batch --max_idle_secs=1 help
echo
echo "Running Soong test..."
diff --git a/cc/afdo.go b/cc/afdo.go
index fb66bbe..d36f4af 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -36,7 +36,7 @@
func getAfdoProfileProjects(config android.DeviceConfig) []string {
return config.OnceStringSlice(afdoProfileProjectsConfigKey, func() []string {
- return append(globalAfdoProfileProjects, config.AfdoAdditionalProfileDirs()...)
+ return globalAfdoProfileProjects
})
}
diff --git a/cc/androidmk.go b/cc/androidmk.go
index a9ba1a9..aaf21e9 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -227,27 +227,17 @@
}
}
-func (library *libraryDecorator) getAbiDiffsForAndroidMkDeps() []string {
- if library.static() {
- return nil
- }
- var abiDiffs []string
- if library.sAbiDiff.Valid() {
- abiDiffs = append(abiDiffs, library.sAbiDiff.String())
- }
- if library.prevSAbiDiff.Valid() {
- abiDiffs = append(abiDiffs, library.prevSAbiDiff.String())
- }
- return abiDiffs
-}
-
func (library *libraryDecorator) androidMkEntriesWriteAdditionalDependenciesForSourceAbiDiff(entries *android.AndroidMkEntries) {
- entries.AddStrings("LOCAL_ADDITIONAL_DEPENDENCIES", library.getAbiDiffsForAndroidMkDeps()...)
+ if !library.static() {
+ entries.AddPaths("LOCAL_ADDITIONAL_DEPENDENCIES", library.sAbiDiff)
+ }
}
// TODO(ccross): remove this once apex/androidmk.go is converted to AndroidMkEntries
func (library *libraryDecorator) androidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Writer) {
- fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES +=", strings.Join(library.getAbiDiffsForAndroidMkDeps(), " "))
+ if !library.static() {
+ fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES +=", strings.Join(library.sAbiDiff.Strings(), " "))
+ }
}
func (library *libraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
@@ -546,7 +536,7 @@
entries.SubName += c.baseProperties.Androidmk_suffix
- entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.ExtraEntries = append(entries.ExtraEntries, func(_ android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
c.libraryDecorator.androidMkWriteExportedFlags(entries)
if c.shared() || c.static() {
@@ -567,6 +557,10 @@
if c.tocFile.Valid() {
entries.SetString("LOCAL_SOONG_TOC", c.tocFile.String())
}
+
+ if c.shared() && len(c.Properties.Overrides) > 0 {
+ entries.SetString("LOCAL_OVERRIDES_MODULES", strings.Join(makeOverrideModuleNames(ctx, c.Properties.Overrides), " "))
+ }
}
if !c.shared() { // static or header
diff --git a/cc/api_level.go b/cc/api_level.go
index fd145a9..fdff5cb 100644
--- a/cc/api_level.go
+++ b/cc/api_level.go
@@ -20,7 +20,7 @@
"android/soong/android"
)
-func minApiForArch(ctx android.BaseModuleContext,
+func minApiForArch(ctx android.EarlyModuleContext,
arch android.ArchType) android.ApiLevel {
switch arch {
@@ -28,6 +28,8 @@
return ctx.Config().MinSupportedSdkVersion()
case android.Arm64, android.X86_64:
return android.FirstLp64Version
+ case android.Riscv64:
+ return android.FutureApiLevel
default:
panic(fmt.Errorf("Unknown arch %q", arch))
}
diff --git a/cc/binary.go b/cc/binary.go
index 3351fd7..c2868e7 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -540,6 +540,12 @@
return binary.toolPath
}
+func (binary *binaryDecorator) overriddenModules() []string {
+ return binary.Properties.Overrides
+}
+
+var _ overridable = (*binaryDecorator)(nil)
+
func init() {
pctx.HostBinToolVariable("verifyHostBionicCmd", "host_bionic_verify")
}
@@ -571,25 +577,20 @@
func (handler *ccBinaryBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(label, cquery.GetOutputFiles, android.GetConfigKey(ctx))
+ bazelCtx.QueueBazelRequest(label, cquery.GetCcUnstrippedInfo, android.GetConfigKey(ctx))
}
func (handler *ccBinaryBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
bazelCtx := ctx.Config().BazelContext
- filePaths, err := bazelCtx.GetOutputFiles(label, android.GetConfigKey(ctx))
+ info, err := bazelCtx.GetCcUnstrippedInfo(label, android.GetConfigKey(ctx))
if err != nil {
ctx.ModuleErrorf(err.Error())
return
}
- if len(filePaths) != 1 {
- ctx.ModuleErrorf("expected exactly one output file for '%s', but got %s", label, filePaths)
- return
- }
- outputFilePath := android.PathForBazelOut(ctx, filePaths[0])
+ outputFilePath := android.PathForBazelOut(ctx, info.OutputFile)
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
- // TODO(b/220164721): We need to decide if we should return the stripped as the unstripped.
- handler.module.linker.(*binaryDecorator).unstrippedOutputFile = outputFilePath
+ handler.module.linker.(*binaryDecorator).unstrippedOutputFile = android.PathForBazelOut(ctx, info.UnstrippedOutput)
}
func binaryBp2buildAttrs(ctx android.TopDownMutatorContext, m *Module) binaryAttributes {
@@ -645,6 +646,8 @@
sdkAttributes: bp2BuildParseSdkAttributes(m),
}
+ m.convertTidyAttributes(ctx, &attrs.tidyAttributes)
+
return attrs
}
@@ -697,4 +700,6 @@
Features bazel.StringListAttribute
sdkAttributes
+
+ tidyAttributes
}
diff --git a/cc/binary_test.go b/cc/binary_test.go
index cba5974..db6fb3a 100644
--- a/cc/binary_test.go
+++ b/cc/binary_test.go
@@ -15,6 +15,7 @@
package cc
import (
+ "android/soong/bazel/cquery"
"testing"
"android/soong/android"
@@ -30,8 +31,11 @@
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.BazelContext = android.MockBazelContext{
OutputBaseDir: "outputbase",
- LabelToOutputFiles: map[string][]string{
- "//foo/bar:bar": []string{"foo"},
+ LabelToCcBinary: map[string]cquery.CcUnstrippedInfo{
+ "//foo/bar:bar": cquery.CcUnstrippedInfo{
+ OutputFile: "foo",
+ UnstrippedOutput: "foo.unstripped",
+ },
},
}
ctx := testCcWithConfig(t, config)
@@ -46,7 +50,7 @@
android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
unStrippedFilePath := binMod.(*Module).UnstrippedOutputFile()
- expectedUnStrippedFile := "outputbase/execroot/__main__/foo"
+ expectedUnStrippedFile := "outputbase/execroot/__main__/foo.unstripped"
android.AssertStringEquals(t, "Unstripped output file", expectedUnStrippedFile, unStrippedFilePath.String())
}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 9b85ec4..6caa854 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -66,6 +66,40 @@
Native_coverage bazel.BoolAttribute
sdkAttributes
+
+ tidyAttributes
+}
+
+type tidyAttributes struct {
+ Tidy *bool
+ Tidy_flags []string
+ Tidy_checks []string
+ Tidy_checks_as_errors []string
+ Tidy_disabled_srcs bazel.LabelListAttribute
+ Tidy_timeout_srcs bazel.LabelListAttribute
+}
+
+func (m *Module) convertTidyAttributes(ctx android.BaseMutatorContext, moduleAttrs *tidyAttributes) {
+ for _, f := range m.features {
+ if tidy, ok := f.(*tidyFeature); ok {
+ moduleAttrs.Tidy = tidy.Properties.Tidy
+ moduleAttrs.Tidy_flags = tidy.Properties.Tidy_flags
+ moduleAttrs.Tidy_checks = tidy.Properties.Tidy_checks
+ moduleAttrs.Tidy_checks_as_errors = tidy.Properties.Tidy_checks_as_errors
+ }
+
+ }
+ archVariantProps := m.GetArchVariantProperties(ctx, &BaseCompilerProperties{})
+ for axis, configToProps := range archVariantProps {
+ for config, _props := range configToProps {
+ if archProps, ok := _props.(*BaseCompilerProperties); ok {
+ archDisabledSrcs := android.BazelLabelForModuleSrc(ctx, archProps.Tidy_disabled_srcs)
+ moduleAttrs.Tidy_disabled_srcs.SetSelectValue(axis, config, archDisabledSrcs)
+ archTimeoutSrcs := android.BazelLabelForModuleSrc(ctx, archProps.Tidy_timeout_srcs)
+ moduleAttrs.Tidy_timeout_srcs.SetSelectValue(axis, config, archTimeoutSrcs)
+ }
+ }
+ }
}
// groupSrcsByExtension partitions `srcs` into groups based on file extension.
@@ -169,12 +203,20 @@
}
}
+func bp2BuildPropParseHelper(ctx android.ArchVariantContext, module *Module, propsType interface{}, parseFunc func(axis bazel.ConfigurationAxis, config string, props interface{})) {
+ for axis, configToProps := range module.GetArchVariantProperties(ctx, propsType) {
+ for config, props := range configToProps {
+ parseFunc(axis, config, props)
+ }
+ }
+}
+
// Parses properties common to static and shared libraries. Also used for prebuilt libraries.
func bp2buildParseStaticOrSharedProps(ctx android.BazelConversionPathContext, module *Module, lib *libraryDecorator, isStatic bool) staticOrSharedAttributes {
attrs := staticOrSharedAttributes{}
setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) {
- attrs.Copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, true, filterOutStdFlag))
+ attrs.Copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag))
attrs.Srcs.SetSelectValue(axis, config, android.BazelLabelForModuleSrc(ctx, props.Srcs))
attrs.System_dynamic_deps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, props.System_shared_libs))
@@ -227,32 +269,30 @@
Enabled bazel.BoolAttribute
}
+func parseSrc(ctx android.BazelConversionPathContext, srcLabelAttribute *bazel.LabelAttribute, axis bazel.ConfigurationAxis, config string, srcs []string) {
+ srcFileError := func() {
+ ctx.ModuleErrorf("parseSrc: Expected at most one source file for %s %s\n", axis, config)
+ }
+ if len(srcs) > 1 {
+ srcFileError()
+ return
+ } else if len(srcs) == 0 {
+ return
+ }
+ if srcLabelAttribute.SelectValue(axis, config) != nil {
+ srcFileError()
+ return
+ }
+ srcLabelAttribute.SetSelectValue(axis, config, android.BazelLabelForModuleSrcSingle(ctx, srcs[0]))
+}
+
// NOTE: Used outside of Soong repo project, in the clangprebuilts.go bootstrap_go_package
func Bp2BuildParsePrebuiltLibraryProps(ctx android.BazelConversionPathContext, module *Module, isStatic bool) prebuiltAttributes {
- manySourceFileError := func(axis bazel.ConfigurationAxis, config string) {
- ctx.ModuleErrorf("Bp2BuildParsePrebuiltLibraryProps: Expected at most one source file for %s %s\n", axis, config)
- }
+
var srcLabelAttribute bazel.LabelAttribute
-
- parseSrcs := func(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis, config string, srcs []string) {
- if len(srcs) > 1 {
- manySourceFileError(axis, config)
- return
- } else if len(srcs) == 0 {
- return
- }
- if srcLabelAttribute.SelectValue(axis, config) != nil {
- manySourceFileError(axis, config)
- return
- }
-
- src := android.BazelLabelForModuleSrcSingle(ctx, srcs[0])
- srcLabelAttribute.SetSelectValue(axis, config, src)
- }
-
bp2BuildPropParseHelper(ctx, module, &prebuiltLinkerProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
if prebuiltLinkerProperties, ok := props.(*prebuiltLinkerProperties); ok {
- parseSrcs(ctx, axis, config, prebuiltLinkerProperties.Srcs)
+ parseSrc(ctx, &srcLabelAttribute, axis, config, prebuiltLinkerProperties.Srcs)
}
})
@@ -261,7 +301,7 @@
if props.Enabled != nil {
enabledLabelAttribute.SetSelectValue(axis, config, props.Enabled)
}
- parseSrcs(ctx, axis, config, props.Srcs)
+ parseSrc(ctx, &srcLabelAttribute, axis, config, props.Srcs)
}
if isStatic {
@@ -284,11 +324,16 @@
}
}
-func bp2BuildPropParseHelper(ctx android.ArchVariantContext, module *Module, propsType interface{}, parseFunc func(axis bazel.ConfigurationAxis, config string, props interface{})) {
- for axis, configToProps := range module.GetArchVariantProperties(ctx, propsType) {
- for config, props := range configToProps {
- parseFunc(axis, config, props)
+func bp2BuildParsePrebuiltBinaryProps(ctx android.BazelConversionPathContext, module *Module) prebuiltAttributes {
+ var srcLabelAttribute bazel.LabelAttribute
+ bp2BuildPropParseHelper(ctx, module, &prebuiltLinkerProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
+ if props, ok := props.(*prebuiltLinkerProperties); ok {
+ parseSrc(ctx, &srcLabelAttribute, axis, config, props.Srcs)
}
+ })
+
+ return prebuiltAttributes{
+ Src: srcLabelAttribute,
}
}
@@ -365,7 +410,7 @@
return false
}
-func parseCommandLineFlags(soongFlags []string, noCoptsTokenization bool, filterOut ...filterOutFn) []string {
+func parseCommandLineFlags(soongFlags []string, filterOut ...filterOutFn) []string {
var result []string
for _, flag := range soongFlags {
skipFlag := false
@@ -380,15 +425,7 @@
// Soong's cflags can contain spaces, like `-include header.h`. For
// Bazel's copts, split them up to be compatible with the
// no_copts_tokenization feature.
- if noCoptsTokenization {
- result = append(result, strings.Split(flag, " ")...)
- } else {
- // Soong's Version Script and Dynamic List Properties are added as flags
- // to Bazel's linkopts using "($location label)" syntax.
- // Splitting on spaces would separate this into two different flags
- // "($ location" and "label)"
- result = append(result, flag)
- }
+ result = append(result, strings.Split(flag, " ")...)
}
return result
}
@@ -422,10 +459,10 @@
// overridden. In Bazel we always allow overriding, via flags; however, this can cause
// incompatibilities, so we remove "-std=" flags from Cflag properties while leaving it in other
// cases.
- ca.copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, true, filterOutStdFlag, filterOutClangUnknownCflags))
- ca.asFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Asflags, true, nil))
- ca.conlyFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Conlyflags, true, filterOutClangUnknownCflags))
- ca.cppFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Cppflags, true, filterOutClangUnknownCflags))
+ ca.copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag, filterOutClangUnknownCflags))
+ ca.asFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Asflags, nil))
+ ca.conlyFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Conlyflags, filterOutClangUnknownCflags))
+ ca.cppFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Cppflags, filterOutClangUnknownCflags))
ca.rtti.SetSelectValue(axis, config, props.Rtti)
}
@@ -1031,19 +1068,26 @@
axisFeatures = append(axisFeatures, "-static_flag")
}
}
+
+ // This must happen before the addition of flags for Version Script and
+ // Dynamic List, as these flags must be split on spaces and those must not
+ linkerFlags = parseCommandLineFlags(linkerFlags, filterOutClangUnknownCflags)
+
+ additionalLinkerInputs := bazel.LabelList{}
if props.Version_script != nil {
label := android.BazelLabelForModuleSrcSingle(ctx, *props.Version_script)
- la.additionalLinkerInputs.SetSelectValue(axis, config, bazel.LabelList{Includes: []bazel.Label{label}})
+ additionalLinkerInputs.Add(&label)
linkerFlags = append(linkerFlags, fmt.Sprintf("-Wl,--version-script,$(location %s)", label.Label))
}
if props.Dynamic_list != nil {
label := android.BazelLabelForModuleSrcSingle(ctx, *props.Dynamic_list)
- la.additionalLinkerInputs.SetSelectValue(axis, config, bazel.LabelList{Includes: []bazel.Label{label}})
+ additionalLinkerInputs.Add(&label)
linkerFlags = append(linkerFlags, fmt.Sprintf("-Wl,--dynamic-list,$(location %s)", label.Label))
}
- la.linkopts.SetSelectValue(axis, config, parseCommandLineFlags(linkerFlags, false, filterOutClangUnknownCflags))
+ la.additionalLinkerInputs.SetSelectValue(axis, config, additionalLinkerInputs)
+ la.linkopts.SetSelectValue(axis, config, linkerFlags)
la.useLibcrt.SetSelectValue(axis, config, props.libCrt())
// it's very unlikely for nocrt to be arch variant, so bp2build doesn't support it.
diff --git a/cc/builder.go b/cc/builder.go
index cb21b1f..0629406 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -292,12 +292,6 @@
},
"extraFlags", "referenceDump", "libName", "arch", "errorMessage")
- // Rule to unzip a reference abi dump.
- unzipRefSAbiDump = pctx.AndroidStaticRule("unzipRefSAbiDump",
- blueprint.RuleParams{
- Command: "gunzip -c $in > $out",
- })
-
// Rule to zip files.
zip = pctx.AndroidStaticRule("zip",
blueprint.RuleParams{
@@ -672,11 +666,16 @@
tidyCmd := "${config.ClangBin}/clang-tidy"
rule := clangTidy
+ reducedCFlags := moduleFlags
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_CLANG_TIDY") {
rule = clangTidyRE
+ // b/248371171, work around RBE input processor problem
+ // some cflags rejected by input processor, but usually
+ // do not affect included files or clang-tidy
+ reducedCFlags = config.TidyReduceCFlags(reducedCFlags)
}
- sharedCFlags := shareFlags("cFlags", moduleFlags)
+ sharedCFlags := shareFlags("cFlags", reducedCFlags)
srcRelPath := srcFile.Rel()
// Add the .tidy rule
@@ -906,63 +905,17 @@
return android.OptionalPathForPath(outputFile)
}
-// unzipRefDump registers a build statement to unzip a reference abi dump.
-func unzipRefDump(ctx android.ModuleContext, zippedRefDump android.Path, baseName string) android.Path {
- outputFile := android.PathForModuleOut(ctx, baseName+"_ref.lsdump")
- ctx.Build(pctx, android.BuildParams{
- Rule: unzipRefSAbiDump,
- Description: "gunzip" + outputFile.Base(),
- Output: outputFile,
- Input: zippedRefDump,
- })
- return outputFile
-}
-
-// sourceAbiDiff registers a build statement to compare linked sAbi dump files (.lsdump).
-func sourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path,
- baseName, exportedHeaderFlags string, diffFlags []string, prevVersion int,
- checkAllApis, isLlndk, isNdk, isVndkExt, previousVersionDiff bool) android.OptionalPath {
+func transformAbiDumpToAbiDiff(ctx android.ModuleContext, inputDump, referenceDump android.Path,
+ baseName, nameExt string, extraFlags []string, errorMessage string) android.Path {
var outputFile android.ModuleOutPath
- if previousVersionDiff {
- outputFile = android.PathForModuleOut(ctx, baseName+"."+strconv.Itoa(prevVersion)+".abidiff")
+ if nameExt != "" {
+ outputFile = android.PathForModuleOut(ctx, baseName+"."+nameExt+".abidiff")
} else {
outputFile = android.PathForModuleOut(ctx, baseName+".abidiff")
}
libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
- var extraFlags []string
- if checkAllApis {
- extraFlags = append(extraFlags, "-check-all-apis")
- } else {
- extraFlags = append(extraFlags,
- "-allow-unreferenced-changes",
- "-allow-unreferenced-elf-symbol-changes")
- }
-
- var errorMessage string
- // When error occurs in previous version ABI diff, Developers can't just update ABI
- // reference but need to follow instructions to ensure ABI backward compatibility.
- if previousVersionDiff {
- // TODO(b/241496591): Remove -advice-only after b/239792343 and b/239790286 are reolved.
- extraFlags = append(extraFlags, "-advice-only")
- errorMessage = "error: Please follow development/vndk/tools/header-checker/README.md to ensure the ABI compatibility between your source code and version " + strconv.Itoa(prevVersion) + "."
- sourceVersion := prevVersion + 1
- extraFlags = append(extraFlags, "-target-version", strconv.Itoa(sourceVersion))
- } else {
- errorMessage = "error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l " + libName
- extraFlags = append(extraFlags, "-target-version", "current")
- }
-
- if isLlndk || isNdk {
- extraFlags = append(extraFlags, "-consider-opaque-types-different")
- }
- if isVndkExt || previousVersionDiff {
- extraFlags = append(extraFlags, "-allow-extensions")
- }
- // TODO(b/232891473): Simplify the above logic with diffFlags.
- extraFlags = append(extraFlags, diffFlags...)
-
ctx.Build(pctx, android.BuildParams{
Rule: sAbiDiff,
Description: "header-abi-diff " + outputFile.Base(),
@@ -977,7 +930,7 @@
"errorMessage": errorMessage,
},
})
- return android.OptionalPathForPath(outputFile)
+ return outputFile
}
// Generate a rule for extracting a table of contents from a shared library (.so)
@@ -1135,7 +1088,3 @@
},
})
}
-
-func mingwCmd(toolchain config.Toolchain, cmd string) string {
- return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd)
-}
diff --git a/cc/cc.go b/cc/cc.go
index 1c845f6..2ff5bba 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -616,6 +616,10 @@
XrefCcFiles() android.Paths
}
+type overridable interface {
+ overriddenModules() []string
+}
+
type libraryDependencyKind int
const (
@@ -1201,6 +1205,8 @@
return c
}
+// UseVndk() returns true if this module is built against VNDK.
+// This means the vendor and product variants of a module.
func (c *Module) UseVndk() bool {
return c.Properties.VndkVersion != ""
}
@@ -1294,6 +1300,9 @@
return false
}
+// IsVndk() returns true if this module has a vndk variant.
+// Note that IsVndk() returns true for all variants of vndk-enabled libraries. Not only vendor variant,
+// but also platform and product variants of vndk-enabled libraries return true for IsVndk().
func (c *Module) IsVndk() bool {
if vndkdep := c.vndkdep; vndkdep != nil {
return vndkdep.isVndk()
@@ -1372,6 +1381,13 @@
return false
}
+func (c *Module) IsStubsImplementationRequired() bool {
+ if lib := c.library; lib != nil {
+ return lib.isStubsImplementationRequired()
+ }
+ return false
+}
+
// If this is a stubs library, ImplementationModuleName returns the name of the module that contains
// the implementation. If it is an implementation library it returns its own name.
func (c *Module) ImplementationModuleName(ctx android.BaseModuleContext) string {
@@ -1849,6 +1865,11 @@
func (c *Module) ProcessBazelQueryResponse(ctx android.ModuleContext) {
bazelModuleLabel := c.getBazelModuleLabel(ctx)
+ bazelCtx := ctx.Config().BazelContext
+ if ccInfo, err := bazelCtx.GetCcInfo(bazelModuleLabel, android.GetConfigKey(ctx)); err == nil {
+ c.tidyFiles = android.PathsForBazelOut(ctx, ccInfo.TidyFiles)
+ }
+
c.bazelHandler.ProcessBazelQueryResponse(ctx, bazelModuleLabel)
c.Properties.SubName = GetSubnameProperty(ctx, c)
@@ -2293,28 +2314,23 @@
return nonvariantLibs, variantLibs
}
-func updateDepsWithApiImports(deps Deps, apiImports multitree.ApiImportInfo) Deps {
- for idx, lib := range deps.SharedLibs {
- deps.SharedLibs[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
+func rewriteLibsForApiImports(c LinkableInterface, libs []string, replaceList map[string]string, config android.Config) ([]string, []string) {
+ nonVariantLibs := []string{}
+ variantLibs := []string{}
+
+ for _, lib := range libs {
+ replaceLibName := GetReplaceModuleName(lib, replaceList)
+ if replaceLibName == lib {
+ // Do not handle any libs which are not in API imports
+ nonVariantLibs = append(nonVariantLibs, replaceLibName)
+ } else if c.UseSdk() && inList(replaceLibName, *getNDKKnownLibs(config)) {
+ variantLibs = append(variantLibs, replaceLibName)
+ } else {
+ nonVariantLibs = append(nonVariantLibs, replaceLibName)
+ }
}
- for idx, lib := range deps.LateSharedLibs {
- deps.LateSharedLibs[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
- }
-
- for idx, lib := range deps.RuntimeLibs {
- deps.RuntimeLibs[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
- }
-
- for idx, lib := range deps.SystemSharedLibs {
- deps.SystemSharedLibs[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
- }
-
- for idx, lib := range deps.ReexportSharedLibHeaders {
- deps.ReexportSharedLibHeaders[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
- }
-
- return deps
+ return nonVariantLibs, variantLibs
}
func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
@@ -2331,9 +2347,18 @@
ctx.ctx = ctx
deps := c.deps(ctx)
-
apiImportInfo := GetApiImports(c, actx)
- deps = updateDepsWithApiImports(deps, apiImportInfo)
+
+ apiNdkLibs := []string{}
+ apiLateNdkLibs := []string{}
+
+ if ctx.Os() == android.Android && c.Target().NativeBridge != android.NativeBridgeEnabled {
+ deps.SharedLibs, apiNdkLibs = rewriteLibsForApiImports(c, deps.SharedLibs, apiImportInfo.SharedLibs, ctx.Config())
+ deps.LateSharedLibs, apiLateNdkLibs = rewriteLibsForApiImports(c, deps.LateSharedLibs, apiImportInfo.SharedLibs, ctx.Config())
+ deps.SystemSharedLibs, _ = rewriteLibsForApiImports(c, deps.SystemSharedLibs, apiImportInfo.SharedLibs, ctx.Config())
+ deps.ReexportHeaderLibHeaders, _ = rewriteLibsForApiImports(c, deps.ReexportHeaderLibHeaders, apiImportInfo.SharedLibs, ctx.Config())
+ deps.ReexportSharedLibHeaders, _ = rewriteLibsForApiImports(c, deps.ReexportSharedLibHeaders, apiImportInfo.SharedLibs, ctx.Config())
+ }
c.Properties.AndroidMkSystemSharedLibs = deps.SystemSharedLibs
@@ -2358,7 +2383,9 @@
}
// Check header lib replacement from API surface first, and then check again with VSDK
- lib = GetReplaceModuleName(lib, apiImportInfo.HeaderLibs)
+ if ctx.Os() == android.Android && c.Target().NativeBridge != android.NativeBridgeEnabled {
+ lib = GetReplaceModuleName(lib, apiImportInfo.HeaderLibs)
+ }
lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).HeaderLibs)
if c.isNDKStubLibrary() {
@@ -2517,12 +2544,20 @@
{Mutator: "version", Variation: version},
{Mutator: "link", Variation: "shared"},
}, ndkStubDepTag, variantNdkLibs...)
+ actx.AddVariationDependencies([]blueprint.Variation{
+ {Mutator: "version", Variation: version},
+ {Mutator: "link", Variation: "shared"},
+ }, ndkStubDepTag, apiNdkLibs...)
ndkLateStubDepTag := libraryDependencyTag{Kind: sharedLibraryDependency, Order: lateLibraryDependency, ndk: true, makeSuffix: "." + version}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "version", Variation: version},
{Mutator: "link", Variation: "shared"},
}, ndkLateStubDepTag, variantLateNdkLibs...)
+ actx.AddVariationDependencies([]blueprint.Variation{
+ {Mutator: "version", Variation: version},
+ {Mutator: "link", Variation: "shared"},
+ }, ndkLateStubDepTag, apiLateNdkLibs...)
if vndkdep := c.vndkdep; vndkdep != nil {
if vndkdep.isVndkExt() {
@@ -2532,6 +2567,8 @@
}, vndkExtDepTag, GetReplaceModuleName(vndkdep.getVndkExtendsModuleName(), GetSnapshot(c, &snapshotInfo, actx).SharedLibs))
}
}
+
+ updateImportedLibraryDependency(ctx)
}
func BeginMutator(ctx android.BottomUpMutatorContext) {
@@ -2574,6 +2611,10 @@
}
return
}
+ // TODO(b/244244438) : Remove this once all variants are implemented
+ if ccFrom, ok := from.(*Module); ok && ccFrom.isImportedApiLibrary() {
+ return
+ }
if from.SdkVersion() == "" {
// Platform code can link to anything
return
@@ -2600,6 +2641,10 @@
// the NDK.
return
}
+ if c.isImportedApiLibrary() {
+ // Imported library from the API surface is a stub library built against interface definition.
+ return
+ }
}
if strings.HasPrefix(ctx.ModuleName(), "libclang_rt.") && to.Module().Name() == "libc++" {
@@ -3330,6 +3375,11 @@
return android.Paths{c.outputFile.Path()}, nil
}
return android.Paths{}, nil
+ case "unstripped":
+ if c.linker != nil {
+ return android.PathsIfNonNil(c.linker.unstrippedOutputFilePath()), nil
+ }
+ return nil, nil
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
@@ -3617,6 +3667,16 @@
return err
}
+ // A dependency only needs to support a min_sdk_version at least
+ // as high as the api level that the architecture was introduced in.
+ // This allows introducing new architectures in the platform that
+ // need to be included in apexes that normally require an older
+ // min_sdk_version.
+ minApiForArch := minApiForArch(ctx, c.Target().Arch.ArchType)
+ if sdkVersion.LessThan(minApiForArch) {
+ sdkVersion = minApiForArch
+ }
+
if ver.GreaterThan(sdkVersion) {
return fmt.Errorf("newer SDK(%v)", ver)
}
@@ -3637,6 +3697,13 @@
return c.UseVndk() && c.IsVndk()
}
+func (c *Module) overriddenModules() []string {
+ if o, ok := c.linker.(overridable); ok {
+ return o.overriddenModules()
+ }
+ return nil
+}
+
var _ snapshot.RelativeInstallPath = (*Module)(nil)
type moduleType int
@@ -3698,7 +3765,9 @@
prebuilt := c.IsPrebuilt()
switch c.typ() {
case binary:
- if !prebuilt {
+ if prebuilt {
+ prebuiltBinaryBp2Build(ctx, c)
+ } else {
binaryBp2build(ctx, c)
}
case testBin:
@@ -3729,6 +3798,24 @@
} else {
sharedOrStaticLibraryBp2Build(ctx, c, false)
}
+ }
+}
+
+var _ android.ApiProvider = (*Module)(nil)
+
+func (c *Module) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
+ if c.IsPrebuilt() {
+ return
+ }
+ switch c.typ() {
+ case fullLibrary:
+ apiContributionBp2Build(ctx, c)
+ case sharedLibrary:
+ apiContributionBp2Build(ctx, c)
+ case headerLibrary:
+ // Aggressively generate api targets for all header modules
+ // This is necessary since the header module does not know if it is a dep of API surface stub library
+ apiLibraryHeadersBp2Build(ctx, c)
case ndkLibrary:
ndkLibraryBp2build(ctx, c)
}
@@ -3821,6 +3908,15 @@
}
}
+func (c *Module) Partition() string {
+ if p, ok := c.installer.(interface {
+ getPartition() string
+ }); ok {
+ return p.getPartition()
+ }
+ return ""
+}
+
var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault
var BoolPtr = proptools.BoolPtr
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 01ac133..6a22bd0 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -3260,6 +3260,102 @@
}
}
+func pathsToBase(paths android.Paths) []string {
+ var ret []string
+ for _, p := range paths {
+ ret = append(ret, p.Base())
+ }
+ return ret
+}
+
+func TestStaticLibArchiveArgs(t *testing.T) {
+ ctx := testCc(t, `
+ cc_library_static {
+ name: "foo",
+ srcs: ["foo.c"],
+ }
+
+ cc_library_static {
+ name: "bar",
+ srcs: ["bar.c"],
+ }
+
+ cc_library_shared {
+ name: "qux",
+ srcs: ["qux.c"],
+ }
+
+ cc_library_static {
+ name: "baz",
+ srcs: ["baz.c"],
+ static_libs: ["foo"],
+ shared_libs: ["qux"],
+ whole_static_libs: ["bar"],
+ }`)
+
+ variant := "android_arm64_armv8-a_static"
+ arRule := ctx.ModuleForTests("baz", variant).Rule("ar")
+
+ // For static libraries, the object files of a whole static dep are included in the archive
+ // directly
+ if g, w := pathsToBase(arRule.Inputs), []string{"bar.o", "baz.o"}; !reflect.DeepEqual(w, g) {
+ t.Errorf("Expected input objects %q, got %q", w, g)
+ }
+
+ // non whole static dependencies are not linked into the archive
+ if len(arRule.Implicits) > 0 {
+ t.Errorf("Expected 0 additional deps, got %q", arRule.Implicits)
+ }
+}
+
+func TestSharedLibLinkingArgs(t *testing.T) {
+ ctx := testCc(t, `
+ cc_library_static {
+ name: "foo",
+ srcs: ["foo.c"],
+ }
+
+ cc_library_static {
+ name: "bar",
+ srcs: ["bar.c"],
+ }
+
+ cc_library_shared {
+ name: "qux",
+ srcs: ["qux.c"],
+ }
+
+ cc_library_shared {
+ name: "baz",
+ srcs: ["baz.c"],
+ static_libs: ["foo"],
+ shared_libs: ["qux"],
+ whole_static_libs: ["bar"],
+ }`)
+
+ variant := "android_arm64_armv8-a_shared"
+ linkRule := ctx.ModuleForTests("baz", variant).Rule("ld")
+ libFlags := linkRule.Args["libFlags"]
+ // When dynamically linking, we expect static dependencies to be found on the command line
+ if expected := "foo.a"; !strings.Contains(libFlags, expected) {
+ t.Errorf("Static lib %q was not found in %q", expected, libFlags)
+ }
+ // When dynamically linking, we expect whole static dependencies to be found on the command line
+ if expected := "bar.a"; !strings.Contains(libFlags, expected) {
+ t.Errorf("Static lib %q was not found in %q", expected, libFlags)
+ }
+
+ // When dynamically linking, we expect shared dependencies to be found on the command line
+ if expected := "qux.so"; !strings.Contains(libFlags, expected) {
+ t.Errorf("Shared lib %q was not found in %q", expected, libFlags)
+ }
+
+ // We should only have the objects from the shared library srcs, not the whole static dependencies
+ if g, w := pathsToBase(linkRule.Inputs), []string{"baz.o"}; !reflect.DeepEqual(w, g) {
+ t.Errorf("Expected input objects %q, got %q", w, g)
+ }
+}
+
func TestStaticExecutable(t *testing.T) {
ctx := testCc(t, `
cc_binary {
@@ -3543,14 +3639,6 @@
defaults: ["defaults"],
}`)
- pathsToBase := func(paths android.Paths) []string {
- var ret []string
- for _, p := range paths {
- ret = append(ret, p.Base())
- }
- return ret
- }
-
shared := ctx.ModuleForTests("libshared", "android_arm64_armv8-a_shared").Rule("ld")
if g, w := pathsToBase(shared.Inputs), []string{"foo.o", "baz.o"}; !reflect.DeepEqual(w, g) {
t.Errorf("libshared ld rule wanted %q, got %q", w, g)
diff --git a/cc/config/Android.bp b/cc/config/Android.bp
index 64a121e..fdc94ad 100644
--- a/cc/config/Android.bp
+++ b/cc/config/Android.bp
@@ -21,6 +21,7 @@
"arm_device.go",
"arm64_device.go",
+ "riscv64_device.go",
"x86_device.go",
"x86_64_device.go",
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 66087e6..d7f9618 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -74,7 +74,7 @@
"-mcpu=kryo",
},
"kryo385": []string{
- // Use cortex-a53 because kryo385 is not supported in GCC/clang.
+ // Use cortex-a53 because kryo385 is not supported in clang.
"-mcpu=cortex-a53",
},
"exynos-m1": []string{
@@ -86,16 +86,7 @@
}
)
-const (
- arm64GccVersion = "4.9"
-)
-
func init() {
- pctx.StaticVariable("arm64GccVersion", arm64GccVersion)
-
- pctx.SourcePathVariable("Arm64GccRoot",
- "prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}")
-
exportedVars.ExportStringListStaticVariable("Arm64Ldflags", arm64Ldflags)
exportedVars.ExportStringListStaticVariable("Arm64Lldflags", arm64Lldflags)
@@ -164,24 +155,12 @@
return "arm64"
}
-func (t *toolchainArm64) GccRoot() string {
- return "${config.Arm64GccRoot}"
-}
-
-func (t *toolchainArm64) GccTriple() string {
- return "aarch64-linux-android"
-}
-
-func (t *toolchainArm64) GccVersion() string {
- return arm64GccVersion
-}
-
func (t *toolchainArm64) IncludeFlags() string {
return ""
}
func (t *toolchainArm64) ClangTriple() string {
- return t.GccTriple()
+ return "aarch64-linux-android"
}
func (t *toolchainArm64) Cflags() string {
diff --git a/cc/config/arm64_linux_host.go b/cc/config/arm64_linux_host.go
index 2d316e6..9f5124b 100644
--- a/cc/config/arm64_linux_host.go
+++ b/cc/config/arm64_linux_host.go
@@ -58,8 +58,8 @@
)
func init() {
- pctx.StaticVariable("LinuxBionicArm64Cflags", strings.Join(linuxCrossCflags, " "))
- pctx.StaticVariable("LinuxBionicArm64Ldflags", strings.Join(linuxCrossLdflags, " "))
+ exportedVars.ExportStringListStaticVariable("LinuxBionicArm64Cflags", linuxCrossCflags)
+ exportedVars.ExportStringListStaticVariable("LinuxBionicArm64Ldflags", linuxCrossLdflags)
}
// toolchain config for ARM64 Linux CrossHost. Almost everything is the same as the ARM64 Android
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index d702c61..981d1ea 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -79,7 +79,7 @@
"cortex-a7": []string{
"-mcpu=cortex-a7",
"-mfpu=neon-vfpv4",
- // Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+ // Fake an ARM compiler flag as these processors support LPAE which clang
// don't advertise.
// TODO This is a hack and we need to add it for each processor that supports LPAE until some
// better solution comes around. See Bug 27340895
@@ -91,7 +91,7 @@
"cortex-a15": []string{
"-mcpu=cortex-a15",
"-mfpu=neon-vfpv4",
- // Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+ // Fake an ARM compiler flag as these processors support LPAE which clang
// don't advertise.
// TODO This is a hack and we need to add it for each processor that supports LPAE until some
// better solution comes around. See Bug 27340895
@@ -100,7 +100,7 @@
"cortex-a53": []string{
"-mcpu=cortex-a53",
"-mfpu=neon-fp-armv8",
- // Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+ // Fake an ARM compiler flag as these processors support LPAE which clang
// don't advertise.
// TODO This is a hack and we need to add it for each processor that supports LPAE until some
// better solution comes around. See Bug 27340895
@@ -109,7 +109,7 @@
"cortex-a55": []string{
"-mcpu=cortex-a55",
"-mfpu=neon-fp-armv8",
- // Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+ // Fake an ARM compiler flag as these processors support LPAE which clang
// don't advertise.
// TODO This is a hack and we need to add it for each processor that supports LPAE until some
// better solution comes around. See Bug 27340895
@@ -118,7 +118,7 @@
"cortex-a75": []string{
"-mcpu=cortex-a55",
"-mfpu=neon-fp-armv8",
- // Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+ // Fake an ARM compiler flag as these processors support LPAE which clang
// don't advertise.
// TODO This is a hack and we need to add it for each processor that supports LPAE until some
// better solution comes around. See Bug 27340895
@@ -127,7 +127,7 @@
"cortex-a76": []string{
"-mcpu=cortex-a55",
"-mfpu=neon-fp-armv8",
- // Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+ // Fake an ARM compiler flag as these processors support LPAE which clang
// don't advertise.
// TODO This is a hack and we need to add it for each processor that supports LPAE until some
// better solution comes around. See Bug 27340895
@@ -136,7 +136,7 @@
"krait": []string{
"-mcpu=krait",
"-mfpu=neon-vfpv4",
- // Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+ // Fake an ARM compiler flag as these processors support LPAE which clang
// don't advertise.
// TODO This is a hack and we need to add it for each processor that supports LPAE until some
// better solution comes around. See Bug 27340895
@@ -147,16 +147,16 @@
// even though clang does.
"-mcpu=cortex-a53",
"-mfpu=neon-fp-armv8",
- // Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+ // Fake an ARM compiler flag as these processors support LPAE which clang
// don't advertise.
// TODO This is a hack and we need to add it for each processor that supports LPAE until some
// better solution comes around. See Bug 27340895
"-D__ARM_FEATURE_LPAE=1",
},
"kryo385": []string{
- // Use cortex-a53 because kryo385 is not supported in GCC/clang.
+ // Use cortex-a53 because kryo385 is not supported in clang.
"-mcpu=cortex-a53",
- // Fake an ARM compiler flag as these processors support LPAE which GCC/clang
+ // Fake an ARM compiler flag as these processors support LPAE which clang
// don't advertise.
// TODO This is a hack and we need to add it for each processor that supports LPAE until some
// better solution comes around. See Bug 27340895
@@ -166,17 +166,12 @@
)
const (
- name = "arm"
- armGccVersion = "4.9"
- gccTriple = "arm-linux-androideabi"
- clangTriple = "armv7a-linux-androideabi"
+ name = "arm"
+ ndkTriple = "arm-linux-androideabi"
+ clangTriple = "armv7a-linux-androideabi"
)
func init() {
- pctx.StaticVariable("armGccVersion", armGccVersion)
-
- pctx.SourcePathVariable("ArmGccRoot", "prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}")
-
// Just exported. Not created as a Ninja static variable.
exportedVars.ExportString("ArmClangTriple", clangTriple)
@@ -227,6 +222,7 @@
"": "${config.ArmGenericCflags}",
"cortex-a7": "${config.ArmCortexA7Cflags}",
"cortex-a8": "${config.ArmCortexA8Cflags}",
+ "cortex-a9": "${config.ArmGenericCflags}",
"cortex-a15": "${config.ArmCortexA15Cflags}",
"cortex-a53": "${config.ArmCortexA53Cflags}",
"cortex-a53.a57": "${config.ArmCortexA53Cflags}",
@@ -255,18 +251,6 @@
return name
}
-func (t *toolchainArm) GccRoot() string {
- return "${config.ArmGccRoot}"
-}
-
-func (t *toolchainArm) GccTriple() string {
- return gccTriple
-}
-
-func (t *toolchainArm) GccVersion() string {
- return armGccVersion
-}
-
func (t *toolchainArm) IncludeFlags() string {
return ""
}
@@ -278,7 +262,7 @@
func (t *toolchainArm) ndkTriple() string {
// Use current NDK include path, while ClangTriple is changed.
- return t.GccTriple()
+ return ndkTriple
}
func (t *toolchainArm) ToolchainCflags() string {
diff --git a/cc/config/darwin_host.go b/cc/config/darwin_host.go
index 01b1e63..2cabdc8 100644
--- a/cc/config/darwin_host.go
+++ b/cc/config/darwin_host.go
@@ -75,10 +75,6 @@
)
)
-const (
- darwinGccVersion = "4.2.1"
-)
-
func init() {
pctx.VariableFunc("macSdkRoot", func(ctx android.PackageVarContext) string {
return getMacTools(ctx).sdkRoot
@@ -100,12 +96,6 @@
return getMacTools(ctx).toolPath
})
- pctx.StaticVariable("DarwinGccVersion", darwinGccVersion)
- pctx.SourcePathVariable("DarwinGccRoot",
- "prebuilts/gcc/${HostPrebuiltTag}/host/i686-apple-darwin-${DarwinGccVersion}")
-
- pctx.StaticVariable("DarwinGccTriple", "i686-apple-darwin11")
-
pctx.StaticVariable("DarwinCflags", strings.Join(darwinCflags, " "))
pctx.StaticVariable("DarwinLdflags", strings.Join(darwinLdflags, " "))
pctx.StaticVariable("DarwinLldflags", strings.Join(darwinLdflags, " "))
@@ -196,30 +186,6 @@
return "x86_64"
}
-func (t *toolchainDarwinArm) GccRoot() string {
- panic("unimplemented")
-}
-
-func (t *toolchainDarwinArm) GccTriple() string {
- panic("unimplemented")
-}
-
-func (t *toolchainDarwinArm) GccVersion() string {
- panic("unimplemented")
-}
-
-func (t *toolchainDarwinX86) GccRoot() string {
- return "${config.DarwinGccRoot}"
-}
-
-func (t *toolchainDarwinX86) GccTriple() string {
- return "${config.DarwinGccTriple}"
-}
-
-func (t *toolchainDarwinX86) GccVersion() string {
- return darwinGccVersion
-}
-
func (t *toolchainDarwin) IncludeFlags() string {
return ""
}
diff --git a/cc/config/global.go b/cc/config/global.go
index bf80907..61151d1 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -76,9 +76,6 @@
// Help catch common 32/64-bit errors.
"-Werror=int-conversion",
- // Enable the new pass manager.
- "-fexperimental-new-pass-manager",
-
// Disable overly aggressive warning for macros defined with a leading underscore
// This happens in AndroidConfig.h, which is included nearly everywhere.
// TODO: can we remove this now?
@@ -91,9 +88,6 @@
// Warnings from clang-7.0
"-Wno-sign-compare",
- // Warnings from clang-8.0
- "-Wno-defaulted-function-deleted",
-
// Disable -Winconsistent-missing-override until we can clean up the existing
// codebase for it.
"-Wno-inconsistent-missing-override",
@@ -150,6 +144,11 @@
"-fdebug-info-for-profiling",
}
+ commonGlobalLldflags = []string{
+ "-fuse-ld=lld",
+ "-Wl,--icf=safe",
+ }
+
deviceGlobalCppflags = []string{
"-fvisibility-inlines-hidden",
}
@@ -167,13 +166,9 @@
"-Wl,--exclude-libs,libgcc_stripped.a",
"-Wl,--exclude-libs,libunwind_llvm.a",
"-Wl,--exclude-libs,libunwind.a",
- "-Wl,--icf=safe",
}
- deviceGlobalLldflags = append(deviceGlobalLdflags,
- []string{
- "-fuse-ld=lld",
- }...)
+ deviceGlobalLldflags = append(deviceGlobalLdflags, commonGlobalLldflags...)
hostGlobalCflags = []string{}
@@ -181,7 +176,7 @@
hostGlobalLdflags = []string{}
- hostGlobalLldflags = []string{"-fuse-ld=lld"}
+ hostGlobalLldflags = commonGlobalLldflags
commonGlobalCppflags = []string{
"-Wsign-promo",
@@ -227,7 +222,6 @@
// http://b/145211066
"-Wno-implicit-int-float-conversion",
// New warnings to be fixed after clang-r377782.
- "-Wno-sizeof-array-div", // http://b/148815709
"-Wno-tautological-overlap-compare", // http://b/148815696
// New warnings to be fixed after clang-r383902.
"-Wno-deprecated-copy", // http://b/153746672
@@ -245,12 +239,17 @@
// New warnings to be fixed after clang-r458507
"-Wno-error=unqualified-std-cast-call", // http://b/239662094
// New warnings to be fixed after clang-r468909
- "-Wno-error=array-parameter", // http://b/241941550
"-Wno-error=deprecated-builtins", // http://b/241601211
"-Wno-error=deprecated", // in external/googletest/googletest
+ // New warnings to be fixed after clang-r475365
+ "-Wno-error=single-bit-bitfield-constant-conversion", // http://b/243965903
+ "-Wno-error=incompatible-function-pointer-types", // http://b/257101299
+ "-Wno-error=enum-constexpr-conversion", // http://b/243964282
}
noOverrideExternalGlobalCflags = []string{
+ // http://b/148815709
+ "-Wno-sizeof-array-div",
// http://b/197240255
"-Wno-unused-but-set-variable",
"-Wno-unused-but-set-parameter",
@@ -258,6 +257,8 @@
"-Wno-bitwise-instead-of-logical",
// http://b/232926688
"-Wno-misleading-indentation",
+ // http://b/241941550
+ "-Wno-array-parameter",
}
// Extra cflags for external third-party projects to disable warnings that
@@ -295,10 +296,8 @@
}
llvmNextExtraCommonGlobalCflags = []string{
- // New warnings to be fixed after clang-r468909
- "-Wno-error=array-parameter", // http://b/241941550
- "-Wno-error=deprecated-builtins", // http://b/241601211
- "-Wno-error=deprecated", // in external/googletest/googletest
+ // New warnings to be fixed after clang-r475365
+ "-Wno-error=single-bit-bitfield-constant-conversion", // http://b/243965903
}
IllegalFlags = []string{
@@ -312,8 +311,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r468909"
- ClangDefaultShortVersion = "15.0.2"
+ ClangDefaultVersion = "clang-r475365"
+ ClangDefaultShortVersion = "16.0.1"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
@@ -354,6 +353,7 @@
// Default to zero initialization.
"-ftrivial-auto-var-init=zero",
"-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang",
+ "-Wno-unused-command-line-argument",
}...)
exportedVars.ExportStringList("CommonGlobalCflags", bazelCommonGlobalCflags)
@@ -364,14 +364,14 @@
// Automatically initialize any uninitialized stack variables.
// Prefer zero-init if multiple options are set.
if ctx.Config().IsEnvTrue("AUTO_ZERO_INITIALIZE") {
- flags = append(flags, "-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang")
+ flags = append(flags, "-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang -Wno-unused-command-line-argument")
} else if ctx.Config().IsEnvTrue("AUTO_PATTERN_INITIALIZE") {
flags = append(flags, "-ftrivial-auto-var-init=pattern")
} else if ctx.Config().IsEnvTrue("AUTO_UNINITIALIZE") {
flags = append(flags, "-ftrivial-auto-var-init=uninitialized")
} else {
// Default to zero initialization.
- flags = append(flags, "-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang")
+ flags = append(flags, "-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang -Wno-unused-command-line-argument")
}
// Workaround for ccache with clang.
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
new file mode 100644
index 0000000..67208b2
--- /dev/null
+++ b/cc/config/riscv64_device.go
@@ -0,0 +1,140 @@
+// 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 (
+ "fmt"
+ "strings"
+
+ "android/soong/android"
+)
+
+var (
+ riscv64Cflags = []string{
+ // Help catch common 32/64-bit errors.
+ "-Werror=implicit-function-declaration",
+ "-fno-emulated-tls",
+ }
+
+ riscv64ArchVariantCflags = map[string][]string{}
+
+ riscv64Ldflags = []string{
+ "-Wl,--hash-style=gnu",
+ }
+
+ riscv64Lldflags = append(riscv64Ldflags,
+ "-Wl,-z,max-page-size=4096")
+
+ riscv64Cppflags = []string{}
+
+ riscv64CpuVariantCflags = map[string][]string{}
+)
+
+const ()
+
+func init() {
+
+ exportedVars.ExportStringListStaticVariable("Riscv64Ldflags", riscv64Ldflags)
+ exportedVars.ExportStringListStaticVariable("Riscv64Lldflags", riscv64Lldflags)
+
+ exportedVars.ExportStringListStaticVariable("Riscv64Cflags", riscv64Cflags)
+ exportedVars.ExportStringListStaticVariable("Riscv64Cppflags", riscv64Cppflags)
+
+ exportedVars.ExportVariableReferenceDict("Riscv64ArchVariantCflags", riscv64ArchVariantCflagsVar)
+ exportedVars.ExportVariableReferenceDict("Riscv64CpuVariantCflags", riscv64CpuVariantCflagsVar)
+ exportedVars.ExportVariableReferenceDict("Riscv64CpuVariantLdflags", riscv64CpuVariantLdflags)
+}
+
+var (
+ riscv64ArchVariantCflagsVar = map[string]string{}
+
+ riscv64CpuVariantCflagsVar = map[string]string{}
+
+ riscv64CpuVariantLdflags = map[string]string{}
+)
+
+type toolchainRiscv64 struct {
+ toolchainBionic
+ toolchain64Bit
+
+ ldflags string
+ lldflags string
+ toolchainCflags string
+}
+
+func (t *toolchainRiscv64) Name() string {
+ return "riscv64"
+}
+
+func (t *toolchainRiscv64) IncludeFlags() string {
+ return ""
+}
+
+func (t *toolchainRiscv64) ClangTriple() string {
+ return "riscv64-linux-android"
+}
+
+func (t *toolchainRiscv64) Cflags() string {
+ return "${config.Riscv64Cflags}"
+}
+
+func (t *toolchainRiscv64) Cppflags() string {
+ return "${config.Riscv64Cppflags}"
+}
+
+func (t *toolchainRiscv64) Ldflags() string {
+ return t.ldflags
+}
+
+func (t *toolchainRiscv64) Lldflags() string {
+ return t.lldflags
+}
+
+func (t *toolchainRiscv64) ToolchainCflags() string {
+ return t.toolchainCflags
+}
+
+func (toolchainRiscv64) LibclangRuntimeLibraryArch() string {
+ return "riscv64"
+}
+
+func riscv64ToolchainFactory(arch android.Arch) Toolchain {
+ switch arch.ArchVariant {
+ case "":
+ default:
+ panic(fmt.Sprintf("Unknown Riscv64 architecture version: %q", arch.ArchVariant))
+ }
+
+ toolchainCflags := []string{riscv64ArchVariantCflagsVar[arch.ArchVariant]}
+ toolchainCflags = append(toolchainCflags,
+ variantOrDefault(riscv64CpuVariantCflagsVar, arch.CpuVariant))
+
+ extraLdflags := variantOrDefault(riscv64CpuVariantLdflags, arch.CpuVariant)
+ return &toolchainRiscv64{
+ ldflags: strings.Join([]string{
+ "${config.Riscv64Ldflags}",
+ extraLdflags,
+ }, " "),
+ lldflags: strings.Join([]string{
+ "${config.Riscv64Lldflags}",
+ extraLdflags,
+ }, " "),
+ toolchainCflags: strings.Join(toolchainCflags, " "),
+ }
+}
+
+func init() {
+ registerToolchainFactory(android.Android, android.Riscv64, riscv64ToolchainFactory)
+}
diff --git a/cc/config/tidy.go b/cc/config/tidy.go
index 23bda66..1180da4 100644
--- a/cc/config/tidy.go
+++ b/cc/config/tidy.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "regexp"
"strings"
)
@@ -54,20 +55,32 @@
// http://b/241819232
"-misc-const-correctness",
}
+
+ extraArgFlags = []string{
+ // We might be using the static analyzer through clang tidy.
+ // https://bugs.llvm.org/show_bug.cgi?id=32914
+ "-D__clang_analyzer__",
+
+ // A recent change in clang-tidy (r328258) enabled destructor inlining, which
+ // appears to cause a number of false positives. Until that's resolved, this turns
+ // off the effects of r328258.
+ // https://bugs.llvm.org/show_bug.cgi?id=37459
+ "-Xclang",
+ "-analyzer-config",
+ "-Xclang",
+ "c++-temp-dtor-inlining=false",
+ }
)
func init() {
- // Many clang-tidy checks like altera-*, llvm-*, modernize-*
- // are not designed for Android source code or creating too
- // many (false-positive) warnings. The global default tidy checks
- // should include only tested groups and exclude known noisy checks.
+ // The global default tidy checks should include clang-tidy
+ // default checks and tested groups, but exclude known noisy checks.
// See https://clang.llvm.org/extra/clang-tidy/checks/list.html
- pctx.VariableFunc("TidyDefaultGlobalChecks", func(ctx android.PackageVarContext) string {
- if override := ctx.Config().Getenv("DEFAULT_GLOBAL_TIDY_CHECKS"); override != "" {
+ exportedVars.ExportVariableConfigMethod("TidyDefaultGlobalChecks", func(config android.Config) string {
+ if override := config.Getenv("DEFAULT_GLOBAL_TIDY_CHECKS"); override != "" {
return override
}
checks := strings.Join([]string{
- "-*",
"android-*",
"bugprone-*",
"cert-*",
@@ -94,7 +107,7 @@
"-misc-non-private-member-variables-in-classes",
"-misc-unused-parameters",
"-performance-no-int-to-ptr",
- // the following groups are excluded by -*
+ // the following groups are not in clang-tidy default checks.
// -altera-*
// -cppcoreguidelines-*
// -darwin-*
@@ -108,49 +121,57 @@
// -readability-*
// -zircon-*
}, ",")
- // clang-analyzer-* checks are too slow to be in the default for WITH_TIDY=1.
- // nightly builds add CLANG_ANALYZER_CHECKS=1 to run those checks.
+ // clang-analyzer-* checks are slow for large files, but we have TIDY_TIMEOUT to
+ // limit clang-tidy runtime. We allow clang-tidy default clang-analyzer-* checks,
+ // and add it explicitly when CLANG_ANALYZER_CHECKS is set.
// The insecureAPI.DeprecatedOrUnsafeBufferHandling warning does not apply to Android.
- if ctx.Config().IsEnvTrue("CLANG_ANALYZER_CHECKS") {
+ if config.IsEnvTrue("CLANG_ANALYZER_CHECKS") {
checks += ",clang-analyzer-*,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling"
+ } else {
+ checks += ",-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling"
}
return checks
})
- // There are too many clang-tidy warnings in external and vendor projects.
- // Enable only some google checks for these projects.
- pctx.VariableFunc("TidyExternalVendorChecks", func(ctx android.PackageVarContext) string {
- if override := ctx.Config().Getenv("DEFAULT_EXTERNAL_VENDOR_TIDY_CHECKS"); override != "" {
+ // The external and vendor projects do not run clang-tidy unless TIDY_EXTERNAL_VENDOR is set.
+ // We do not add "-*" to the check list to avoid suppressing the check list in .clang-tidy config files.
+ // There are too many clang-tidy warnings in external and vendor projects, so we only
+ // enable some google checks for these projects. Users can add more checks locally with the
+ // "tidy_checks" list in .bp files, or the "Checks" list in .clang-tidy config files.
+ exportedVars.ExportVariableConfigMethod("TidyExternalVendorChecks", func(config android.Config) string {
+ if override := config.Getenv("DEFAULT_EXTERNAL_VENDOR_TIDY_CHECKS"); override != "" {
return override
}
return strings.Join([]string{
- "-*",
"clang-diagnostic-unused-command-line-argument",
"google-build-explicit-make-pair",
"google-build-namespaces",
"google-runtime-operator",
"google-upgrade-*",
+ "-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling",
}, ",")
})
- pctx.VariableFunc("TidyGlobalNoChecks", func(ctx android.PackageVarContext) string {
+ exportedVars.ExportVariableFuncVariable("TidyGlobalNoChecks", func() string {
return strings.Join(globalNoCheckList, ",")
})
- pctx.VariableFunc("TidyGlobalNoErrorChecks", func(ctx android.PackageVarContext) string {
+ exportedVars.ExportVariableFuncVariable("TidyGlobalNoErrorChecks", func() string {
return strings.Join(globalNoErrorCheckList, ",")
})
+ exportedVars.ExportStringListStaticVariable("TidyExtraArgFlags", extraArgFlags)
+
// To reduce duplicate warnings from the same header files,
// header-filter will contain only the module directory and
// those specified by DEFAULT_TIDY_HEADER_DIRS.
- pctx.VariableFunc("TidyDefaultHeaderDirs", func(ctx android.PackageVarContext) string {
- return ctx.Config().Getenv("DEFAULT_TIDY_HEADER_DIRS")
+ exportedVars.ExportVariableConfigMethod("TidyDefaultHeaderDirs", func(config android.Config) string {
+ return config.Getenv("DEFAULT_TIDY_HEADER_DIRS")
})
// Use WTIH_TIDY_FLAGS to pass extra global default clang-tidy flags.
- pctx.VariableFunc("TidyWithTidyFlags", func(ctx android.PackageVarContext) string {
- return ctx.Config().Getenv("WITH_TIDY_FLAGS")
+ exportedVars.ExportVariableConfigMethod("TidyWithTidyFlags", func(config android.Config) string {
+ return config.Getenv("WITH_TIDY_FLAGS")
})
}
@@ -201,11 +222,18 @@
return tidyDefault
}
-func NoClangTidyForDir(dir string) bool {
+func neverTidyForDir(dir string) bool {
+ // This function can be extended if tidy needs to be disabled for more directories.
+ return strings.HasPrefix(dir, "external/grpc-grpc")
+}
+
+func NoClangTidyForDir(allowExternalVendor bool, dir string) bool {
+ // Tidy can be disable for a module in dir, if the dir is "neverTidyForDir",
+ // or if it belongs to external|vendor and !allowExternalVendor.
// This function depends on TidyChecksForDir, which selects tidyExternalVendor
- // checks for external/vendor projects. For those projects we disable clang-tidy
- // by default, unless some modules enable clang-tidy with tidy:true.
- return TidyChecksForDir(dir) == tidyExternalVendor
+ // checks for external/vendor projects.
+ return neverTidyForDir(dir) ||
+ (!allowExternalVendor && TidyChecksForDir(dir) == tidyExternalVendor)
}
// Returns a globally disabled tidy checks, overriding locally selected checks.
@@ -224,6 +252,10 @@
return ""
}
+func TidyExtraArgFlags() []string {
+ return extraArgFlags
+}
+
func TidyFlagsForSrcFile(srcFile android.Path, flags string) string {
// Disable clang-analyzer-* checks globally for generated source files
// because some of them are too huge. Local .bp files can add wanted
@@ -237,3 +269,11 @@
}
return flags
}
+
+var (
+ removedCFlags = regexp.MustCompile(" -fsanitize=[^ ]*memtag-[^ ]* ")
+)
+
+func TidyReduceCFlags(flags string) string {
+ return removedCFlags.ReplaceAllString(flags, " ")
+}
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index d9eaf53..052832d 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -63,11 +63,6 @@
type Toolchain interface {
Name() string
- GccRoot() string
- GccTriple() string
- // GccVersion should return a real value, not a ninja reference
- GccVersion() string
-
IncludeFlags() string
ClangTriple() string
@@ -249,4 +244,8 @@
return LibclangRuntimeLibrary(t, "fuzzer")
}
+func LibFuzzerRuntimeInterceptors(t Toolchain) string {
+ return LibclangRuntimeLibrary(t, "fuzzer_interceptors")
+}
+
var inList = android.InList
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index aebda0b..e2b0f06 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -80,17 +80,7 @@
}
)
-const (
- x86_64GccVersion = "4.9"
-)
-
func init() {
-
- pctx.StaticVariable("x86_64GccVersion", x86_64GccVersion)
-
- pctx.SourcePathVariable("X86_64GccRoot",
- "prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86_64GccVersion}")
-
exportedVars.ExportStringListStaticVariable("X86_64ToolchainCflags", []string{"-m64"})
exportedVars.ExportStringListStaticVariable("X86_64ToolchainLdflags", []string{"-m64"})
@@ -128,24 +118,12 @@
return "x86_64"
}
-func (t *toolchainX86_64) GccRoot() string {
- return "${config.X86_64GccRoot}"
-}
-
-func (t *toolchainX86_64) GccTriple() string {
- return "x86_64-linux-android"
-}
-
-func (t *toolchainX86_64) GccVersion() string {
- return x86_64GccVersion
-}
-
func (t *toolchainX86_64) IncludeFlags() string {
return ""
}
func (t *toolchainX86_64) ClangTriple() string {
- return t.GccTriple()
+ return "x86_64-linux-android"
}
func (t *toolchainX86_64) ToolchainLdflags() string {
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index 421b083..3001ab4 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -88,16 +88,7 @@
}
)
-const (
- x86GccVersion = "4.9"
-)
-
func init() {
- pctx.StaticVariable("x86GccVersion", x86GccVersion)
-
- pctx.SourcePathVariable("X86GccRoot",
- "prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86GccVersion}")
-
exportedVars.ExportStringListStaticVariable("X86ToolchainCflags", []string{"-m32"})
exportedVars.ExportStringListStaticVariable("X86ToolchainLdflags", []string{"-m32"})
@@ -134,18 +125,6 @@
return "x86"
}
-func (t *toolchainX86) GccRoot() string {
- return "${config.X86GccRoot}"
-}
-
-func (t *toolchainX86) GccTriple() string {
- return "x86_64-linux-android"
-}
-
-func (t *toolchainX86) GccVersion() string {
- return x86GccVersion
-}
-
func (t *toolchainX86) IncludeFlags() string {
return ""
}
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index 976cc25..e006471 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -15,8 +15,6 @@
package config
import (
- "strings"
-
"android/soong/android"
)
@@ -66,13 +64,19 @@
"host_bionic_linker_script")
)
+const (
+ x86_64GccVersion = "4.9"
+)
+
func init() {
- pctx.StaticVariable("LinuxBionicCflags", strings.Join(linuxBionicCflags, " "))
- pctx.StaticVariable("LinuxBionicLdflags", strings.Join(linuxBionicLdflags, " "))
- pctx.StaticVariable("LinuxBionicLldflags", strings.Join(linuxBionicLdflags, " "))
+ exportedVars.ExportStringListStaticVariable("LinuxBionicCflags", linuxBionicCflags)
+ exportedVars.ExportStringListStaticVariable("LinuxBionicLdflags", linuxBionicLdflags)
+ exportedVars.ExportStringListStaticVariable("LinuxBionicLldflags", linuxBionicLdflags)
// Use the device gcc toolchain for now
- pctx.StaticVariable("LinuxBionicGccRoot", "${X86_64GccRoot}")
+ exportedVars.ExportStringStaticVariable("LinuxBionicGccVersion", x86_64GccVersion)
+ exportedVars.ExportSourcePathVariable("LinuxBionicGccRoot",
+ "prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${LinuxBionicGccVersion}")
}
type toolchainLinuxBionic struct {
@@ -84,18 +88,6 @@
return "x86_64"
}
-func (t *toolchainLinuxBionic) GccRoot() string {
- return "${config.LinuxBionicGccRoot}"
-}
-
-func (t *toolchainLinuxBionic) GccTriple() string {
- return "x86_64-linux-android"
-}
-
-func (t *toolchainLinuxBionic) GccVersion() string {
- return "4.9"
-}
-
func (t *toolchainLinuxBionic) IncludeFlags() string {
return ""
}
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 07b95e1..740405e 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -180,18 +180,6 @@
return "x86_64"
}
-func (t *toolchainLinux) GccRoot() string {
- return "${config.LinuxGccRoot}"
-}
-
-func (t *toolchainLinux) GccTriple() string {
- return "${config.LinuxGccTriple}"
-}
-
-func (t *toolchainLinux) GccVersion() string {
- return linuxGccVersion
-}
-
func (t *toolchainLinux) IncludeFlags() string {
return ""
}
diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go
index a33606f..561c500 100644
--- a/cc/config/x86_windows_host.go
+++ b/cc/config/x86_windows_host.go
@@ -175,24 +175,12 @@
return "x86_64"
}
-func (t *toolchainWindows) GccRoot() string {
- return "${config.WindowsGccRoot}"
-}
-
-func (t *toolchainWindows) GccTriple() string {
- return "${config.WindowsGccTriple}"
-}
-
func (t *toolchainWindows) ToolchainCflags() string {
- return "-B" + filepath.Join(t.GccRoot(), t.GccTriple(), "bin")
+ return "-B" + filepath.Join("${config.WindowsGccRoot}", "${config.WindowsGccTriple}", "bin")
}
func (t *toolchainWindows) ToolchainLdflags() string {
- return "-B" + filepath.Join(t.GccRoot(), t.GccTriple(), "bin")
-}
-
-func (t *toolchainWindows) GccVersion() string {
- return windowsGccVersion
+ return "-B" + filepath.Join("${config.WindowsGccRoot}", "${config.WindowsGccTriple}", "bin")
}
func (t *toolchainWindows) IncludeFlags() string {
diff --git a/cc/coverage.go b/cc/coverage.go
index d0902ea..a7356f8 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -108,6 +108,12 @@
if EnableContinuousCoverage(ctx) {
flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-mllvm", "-runtime-counter-relocation")
}
+
+ // http://b/248022906, http://b/247941801 enabling coverage and hwasan-globals
+ // instrumentation together causes duplicate-symbol errors for __llvm_profile_filename.
+ if c, ok := ctx.Module().(*Module); ok && c.sanitize.isSanitizerEnabled(Hwasan) {
+ flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-mllvm", "-hwasan-globals=0")
+ }
}
}
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 8a8c107..64bb7dd 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -103,6 +103,7 @@
*baseCompiler
fuzzPackagedModule fuzz.FuzzPackagedModule
installedSharedDeps []string
+ sharedLibraries android.Paths
}
func (fuzz *fuzzBinary) fuzzBinary() bool {
@@ -125,6 +126,14 @@
deps.HeaderLibs = append(deps.HeaderLibs, "libafl_headers")
} else {
deps.StaticLibs = append(deps.StaticLibs, config.LibFuzzerRuntimeLibrary(ctx.toolchain()))
+ // Fuzzers built with HWASAN should use the interceptors for better
+ // mutation based on signals in strcmp, memcpy, etc. This is only needed for
+ // fuzz targets, not generic HWASAN-ified binaries or libraries.
+ if module, ok := ctx.Module().(*Module); ok {
+ if module.IsSanitizerEnabled(Hwasan) {
+ deps.StaticLibs = append(deps.StaticLibs, config.LibFuzzerRuntimeInterceptors(ctx.toolchain()))
+ }
+ }
}
deps = fuzzBin.binaryDecorator.linkerDeps(ctx, deps)
@@ -136,17 +145,19 @@
// RunPaths on devices isn't instantiated by the base linker. `../lib` for
// installed fuzz targets (both host and device), and `./lib` for fuzz
// 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
-}
-
-func UnstrippedOutputFile(module android.Module) android.Path {
- if mod, ok := module.(LinkableInterface); ok {
- return mod.UnstrippedOutputFile()
+ // When running on device, fuzz targets with vendor: true set will be in
+ // fuzzer_name/vendor/fuzzer_name (note the extra 'vendor' and thus need to
+ // link with libraries in ../../lib/. Non-vendor binaries only need to look
+ // one level up, in ../lib/.
+ if ctx.inVendor() {
+ flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../../lib`)
+ } else {
+ flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
}
- panic("UnstrippedOutputFile called on non-LinkableInterface module: " + module.Name())
+
+ return flags
}
// IsValidSharedDependency takes a module and determines if it is a unique shared library
@@ -270,22 +281,9 @@
}
// Grab the list of required shared libraries.
- seen := make(map[string]bool)
- var sharedLibraries android.Paths
- ctx.WalkDeps(func(child, parent android.Module) bool {
- if seen[child.Name()] {
- return false
- }
- seen[child.Name()] = true
+ fuzzBin.sharedLibraries, _ = CollectAllSharedDependencies(ctx)
- if IsValidSharedDependency(child) {
- sharedLibraries = append(sharedLibraries, child.(*Module).UnstrippedOutputFile())
- return true
- }
- return false
- })
-
- for _, lib := range sharedLibraries {
+ for _, lib := range fuzzBin.sharedLibraries {
fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
sharedLibraryInstallLocation(
lib, ctx.Host(), installBase, ctx.Arch().ArchType.String()))
@@ -412,9 +410,6 @@
archDir := android.PathForIntermediates(ctx, intermediatePath, hostOrTargetString, archString)
archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
- // Grab the list of required shared libraries.
- sharedLibraries := fuzz.CollectAllSharedDependencies(ctx, module, UnstrippedOutputFile, IsValidSharedDependency)
-
var files []fuzz.FileToZip
builder := android.NewRuleBuilder(pctx, ctx)
@@ -422,10 +417,10 @@
files = s.PackageArtifacts(ctx, module, fpm, archDir, builder)
// Package shared libraries
- files = append(files, GetSharedLibsToZip(sharedLibraries, ccModule, &s.FuzzPackager, archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...)
+ files = append(files, GetSharedLibsToZip(fuzzModule.sharedLibraries, ccModule, &s.FuzzPackager, archString, sharedLibsInstallDirPrefix, &sharedLibraryInstalled)...)
// The executable.
- files = append(files, fuzz.FileToZip{ccModule.UnstrippedOutputFile(), ""})
+ files = append(files, fuzz.FileToZip{android.OutputFileForModule(ctx, ccModule, "unstripped"), ""})
archDirs[archOs], ok = s.BuildZipFile(ctx, module, fpm, files, builder, archDir, archString, hostOrTargetString, archOs, archDirs)
if !ok {
@@ -494,3 +489,49 @@
}
return files
}
+
+// CollectAllSharedDependencies search over the provided module's dependencies using
+// VisitDirectDeps and WalkDeps to enumerate all shared library dependencies.
+// VisitDirectDeps is used first to avoid incorrectly using the core libraries (sanitizer
+// runtimes, libc, libdl, etc.) from a dependency. This may cause issues when dependencies
+// have explicit sanitizer tags, as we may get a dependency on an unsanitized libc, etc.
+func CollectAllSharedDependencies(ctx android.ModuleContext) (android.Paths, []android.Module) {
+ seen := make(map[string]bool)
+ recursed := make(map[string]bool)
+ deps := []android.Module{}
+
+ var sharedLibraries android.Paths
+
+ // Enumerate the first level of dependencies, as we discard all non-library
+ // modules in the BFS loop below.
+ ctx.VisitDirectDeps(func(dep android.Module) {
+ if !IsValidSharedDependency(dep) {
+ return
+ }
+ if seen[ctx.OtherModuleName(dep)] {
+ return
+ }
+ seen[ctx.OtherModuleName(dep)] = true
+ deps = append(deps, dep)
+ sharedLibraries = append(sharedLibraries, android.OutputFileForModule(ctx, dep, "unstripped"))
+ })
+
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ if !IsValidSharedDependency(child) {
+ return false
+ }
+ if !seen[ctx.OtherModuleName(child)] {
+ seen[ctx.OtherModuleName(child)] = true
+ deps = append(deps, child)
+ sharedLibraries = append(sharedLibraries, android.OutputFileForModule(ctx, child, "unstripped"))
+ }
+
+ if recursed[ctx.OtherModuleName(child)] {
+ return false
+ }
+ recursed[ctx.OtherModuleName(child)] = true
+ return true
+ })
+
+ return sharedLibraries, deps
+}
diff --git a/cc/genrule_test.go b/cc/genrule_test.go
index f25f704..0d16e62 100644
--- a/cc/genrule_test.go
+++ b/cc/genrule_test.go
@@ -40,14 +40,13 @@
name: "gen",
tool_files: ["tool"],
cmd: "$(location tool) $(in) $(out)",
+ out: ["out_arm"],
arch: {
arm: {
srcs: ["foo"],
- out: ["out_arm"],
},
arm64: {
srcs: ["bar"],
- out: ["out_arm64"],
},
},
}
@@ -70,7 +69,7 @@
t.Errorf(`want arm inputs %v, got %v`, expected, gen.Implicits.Strings())
}
- gen = ctx.ModuleForTests("gen", "android_arm64_armv8-a").Output("out_arm64")
+ gen = ctx.ModuleForTests("gen", "android_arm64_armv8-a").Output("out_arm")
expected = []string{"bar"}
if !reflect.DeepEqual(expected, gen.Implicits.Strings()[:len(expected)]) {
t.Errorf(`want arm64 inputs %v, got %v`, expected, gen.Implicits.Strings())
diff --git a/cc/library.go b/cc/library.go
index 441eb79..1cad6b9 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -30,6 +30,7 @@
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
+ "github.com/google/blueprint/proptools"
)
// LibraryProperties is a collection of properties shared by cc library rules/cc.
@@ -70,6 +71,12 @@
// List versions to generate stubs libs for. The version name "current" is always
// implicitly added.
Versions []string
+
+ // Whether to not require the implementation of the library to be installed if a
+ // client of the stubs is installed. Defaults to true; set to false if the
+ // implementation is made available by some other means, e.g. in a Microdroid
+ // virtual machine.
+ Implementation_installable *bool
}
// set the name of the output
@@ -288,6 +295,16 @@
None bazel.BoolAttribute
}
+func stripAttrsFromLinkerAttrs(la *linkerAttributes) stripAttributes {
+ return stripAttributes{
+ Keep_symbols: la.stripKeepSymbols,
+ Keep_symbols_and_debug_frame: la.stripKeepSymbolsAndDebugFrame,
+ Keep_symbols_list: la.stripKeepSymbolsList,
+ All: la.stripAll,
+ None: la.stripNone,
+ }
+}
+
func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
// For some cc_library modules, their static variants are ready to be
// converted, but not their shared variants. For these modules, delegate to
@@ -394,19 +411,15 @@
Additional_linker_inputs: linkerAttrs.additionalLinkerInputs,
- Strip: stripAttributes{
- Keep_symbols: linkerAttrs.stripKeepSymbols,
- Keep_symbols_and_debug_frame: linkerAttrs.stripKeepSymbolsAndDebugFrame,
- Keep_symbols_list: linkerAttrs.stripKeepSymbolsList,
- All: linkerAttrs.stripAll,
- None: linkerAttrs.stripNone,
- },
- Features: baseAttributes.features,
+ Strip: stripAttrsFromLinkerAttrs(&linkerAttrs),
+ Features: baseAttributes.features,
+ bazelCcHeaderAbiCheckerAttributes: bp2buildParseAbiCheckerProps(ctx, m),
}
if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 {
hasStubs := true
sharedTargetAttrs.Has_stubs.SetValue(&hasStubs)
+ sharedTargetAttrs.Stubs_symbol_file = compilerAttrs.stubsSymbolFile
}
sharedTargetAttrs.Suffix = compilerAttrs.suffix
@@ -466,6 +479,147 @@
}
}
+func apiContributionBp2Build(ctx android.TopDownMutatorContext, module *Module) {
+ apiSurfaces := make([]string, 0)
+ apiHeaders := make([]string, 0)
+ // systemapi (non-null `stubs` property)
+ if module.HasStubsVariants() {
+ apiSurfaces = append(apiSurfaces, android.SystemApi.String())
+ apiIncludes := getSystemApiIncludes(ctx, module)
+ if !apiIncludes.isEmpty() {
+ createApiHeaderTarget(ctx, apiIncludes)
+ apiHeaders = append(apiHeaders, apiIncludes.name)
+ }
+ }
+ // vendorapi (non-null `llndk` property)
+ if module.HasLlndkStubs() {
+ apiSurfaces = append(apiSurfaces, android.VendorApi.String())
+ apiIncludes := getVendorApiIncludes(ctx, module)
+ if !apiIncludes.isEmpty() {
+ createApiHeaderTarget(ctx, apiIncludes)
+ apiHeaders = append(apiHeaders, apiIncludes.name)
+ }
+ }
+ // create a target only if this module contributes to an api surface
+ // TODO: Currently this does not distinguish systemapi-only headers and vendrorapi-only headers
+ // TODO: Update so that systemapi-only headers do not get exported to vendorapi (and vice-versa)
+ if len(apiSurfaces) > 0 {
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_api_contribution",
+ Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl",
+ }
+ attrs := &bazelCcApiContributionAttributes{
+ Library_name: module.Name(),
+ Api_surfaces: bazel.MakeStringListAttribute(apiSurfaces),
+ Api: apiLabelAttribute(ctx, module),
+ Hdrs: bazel.MakeLabelListAttribute(
+ bazel.MakeLabelListFromTargetNames(apiHeaders),
+ ),
+ }
+ ctx.CreateBazelTargetModule(
+ props,
+ android.CommonAttributes{
+ Name: android.ApiContributionTargetName(module.Name()),
+ SkipData: proptools.BoolPtr(true),
+ },
+ attrs,
+ )
+ }
+}
+
+// Native apis are versioned in a single .map.txt for all api surfaces
+// Pick any one of the .map.txt files
+func apiLabelAttribute(ctx android.TopDownMutatorContext, module *Module) bazel.LabelAttribute {
+ var apiFile *string
+ linker := module.linker.(*libraryDecorator)
+ if llndkApi := linker.Properties.Llndk.Symbol_file; llndkApi != nil {
+ apiFile = llndkApi
+ } else if systemApi := linker.Properties.Stubs.Symbol_file; systemApi != nil {
+ apiFile = systemApi
+ } else {
+ ctx.ModuleErrorf("API surface library does not have any API file")
+ }
+ apiLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(apiFile)).Label
+ return *bazel.MakeLabelAttribute(apiLabel)
+}
+
+// wrapper struct to flatten the arch and os specific export_include_dirs
+// flattening is necessary since we want to export apis of all arches even when we build for x86 (e.g.)
+type bazelCcApiLibraryHeadersAttributes struct {
+ bazelCcLibraryHeadersAttributes
+
+ Arch *string
+}
+
+func (a *bazelCcApiLibraryHeadersAttributes) isEmpty() bool {
+ return a.Export_includes.IsEmpty() &&
+ a.Export_system_includes.IsEmpty() &&
+ a.Deps.IsEmpty()
+}
+
+type apiIncludes struct {
+ name string // name of the Bazel target in the generated bp2build workspace
+ attrs bazelCcApiLibraryHeadersAttributes
+}
+
+func (includes *apiIncludes) isEmpty() bool {
+ return includes.attrs.isEmpty()
+}
+
+func (includes *apiIncludes) addDep(name string) {
+ l := bazel.Label{Label: ":" + name}
+ ll := bazel.MakeLabelList([]bazel.Label{l})
+ lla := bazel.MakeLabelListAttribute(ll)
+ includes.attrs.Deps.Append(lla)
+}
+
+func getSystemApiIncludes(ctx android.TopDownMutatorContext, c *Module) apiIncludes {
+ flagProps := c.library.(*libraryDecorator).flagExporter.Properties
+ linkProps := c.library.(*libraryDecorator).baseLinker.Properties
+ includes := android.FirstUniqueStrings(flagProps.Export_include_dirs)
+ systemIncludes := android.FirstUniqueStrings(flagProps.Export_system_include_dirs)
+ headerLibs := android.FirstUniqueStrings(linkProps.Export_header_lib_headers)
+ attrs := bazelCcLibraryHeadersAttributes{
+ Export_includes: bazel.MakeStringListAttribute(includes),
+ Export_system_includes: bazel.MakeStringListAttribute(systemIncludes),
+ Deps: bazel.MakeLabelListAttribute(apiHeaderLabels(ctx, headerLibs)),
+ }
+
+ return apiIncludes{
+ name: c.Name() + ".systemapi.headers",
+ attrs: bazelCcApiLibraryHeadersAttributes{
+ bazelCcLibraryHeadersAttributes: attrs,
+ },
+ }
+}
+
+func getVendorApiIncludes(ctx android.TopDownMutatorContext, c *Module) apiIncludes {
+ baseProps := c.library.(*libraryDecorator).flagExporter.Properties
+ llndkProps := c.library.(*libraryDecorator).Properties.Llndk
+ includes := baseProps.Export_include_dirs
+ systemIncludes := baseProps.Export_system_include_dirs
+ // LLNDK can override the base includes
+ if llndkIncludes := llndkProps.Override_export_include_dirs; llndkIncludes != nil {
+ includes = llndkIncludes
+ }
+ if proptools.Bool(llndkProps.Export_headers_as_system) {
+ systemIncludes = append(systemIncludes, includes...)
+ includes = nil
+ }
+
+ attrs := bazelCcLibraryHeadersAttributes{
+ Export_includes: bazel.MakeStringListAttribute(includes),
+ Export_system_includes: bazel.MakeStringListAttribute(systemIncludes),
+ Deps: bazel.MakeLabelListAttribute(apiHeaderLabels(ctx, llndkProps.Export_llndk_headers)),
+ }
+ return apiIncludes{
+ name: c.Name() + ".vendorapi.headers",
+ attrs: bazelCcApiLibraryHeadersAttributes{
+ bazelCcLibraryHeadersAttributes: attrs,
+ },
+ }
+}
+
// cc_library creates both static and/or shared libraries for a device and/or
// host. By default, a cc_library has a single variant that targets the device.
// Specifying `host_supported: true` also creates a library that targets the
@@ -650,10 +804,7 @@
sAbiOutputFile android.OptionalPath
// Source Abi Diff
- sAbiDiff android.OptionalPath
-
- // Source Abi Diff against previous SDK version
- prevSAbiDiff android.OptionalPath
+ sAbiDiff android.Paths
// Location of the static library in the sysroot. Empty if the library is
// not included in the NDK.
@@ -739,7 +890,7 @@
outputFilePath := android.PathForBazelOut(ctx, rootDynamicLibraries[0])
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
- handler.module.linker.(*libraryDecorator).unstrippedOutputFile = outputFilePath
+ handler.module.linker.(*libraryDecorator).unstrippedOutputFile = android.PathForBazelOut(ctx, ccInfo.UnstrippedOutput)
var tocFile android.OptionalPath
if len(ccInfo.TocFile) > 0 {
@@ -810,7 +961,7 @@
for _, path := range paths {
dir := path.String()
// Skip if dir is for generated headers
- if strings.HasPrefix(dir, android.PathForOutput(ctx).String()) {
+ if strings.HasPrefix(dir, ctx.Config().OutDir()) {
continue
}
@@ -1089,6 +1240,12 @@
} else {
flag = "--systemapi"
}
+ // b/184712170, unless the lib is an NDK library, exclude all public symbols from
+ // the stub so that it is mandated that all symbols are explicitly marked with
+ // either apex or systemapi.
+ if !ctx.Module().(*Module).IsNdk(ctx.Config()) {
+ flag = flag + " --no-ndk"
+ }
nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile,
android.ApiLevelOrPanic(ctx, library.MutatedProperties.StubsVersion), flag)
objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
@@ -1187,6 +1344,7 @@
buildStubs() bool
setBuildStubs(isLatest bool)
hasStubsVariants() bool
+ isStubsImplementationRequired() bool
setStubsVersion(string)
stubsVersion() string
@@ -1576,7 +1734,6 @@
objs.coverageFiles = append(objs.coverageFiles, deps.StaticLibObjs.coverageFiles...)
objs.coverageFiles = append(objs.coverageFiles, deps.WholeStaticLibObjs.coverageFiles...)
-
objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.StaticLibObjs.sAbiDumpFiles...)
objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.WholeStaticLibObjs.sAbiDumpFiles...)
@@ -1637,10 +1794,8 @@
return library.coverageOutputFile
}
-// pathForVndkRefAbiDump returns an OptionalPath representing the path of the
-// reference abi dump for the given module. This is not guaranteed to be valid.
-func pathForVndkRefAbiDump(ctx android.ModuleInstallPathContext, version, fileName string,
- isNdk, isVndk, isGzip bool) android.OptionalPath {
+func getRefAbiDumpFile(ctx android.ModuleInstallPathContext,
+ versionedDumpDir, fileName string) android.OptionalPath {
currentArchType := ctx.Arch().ArchType
primaryArchType := ctx.Config().DevicePrimaryArchType()
@@ -1649,73 +1804,34 @@
archName += "_" + primaryArchType.String()
}
+ return android.ExistentPathForSource(ctx, versionedDumpDir, archName, "source-based",
+ fileName+".lsdump")
+}
+
+func getRefAbiDumpDir(isNdk, isVndk bool) string {
var dirName string
if isNdk {
dirName = "ndk"
} else if isVndk {
dirName = "vndk"
} else {
- dirName = "platform" // opt-in libs
+ dirName = "platform"
}
-
- binderBitness := ctx.DeviceConfig().BinderBitness()
-
- var ext string
- if isGzip {
- ext = ".lsdump.gz"
- } else {
- ext = ".lsdump"
- }
-
- return android.ExistentPathForSource(ctx, "prebuilts", "abi-dumps", dirName,
- version, binderBitness, archName, "source-based",
- fileName+ext)
+ return filepath.Join("prebuilts", "abi-dumps", dirName)
}
-func getRefAbiDumpFile(ctx ModuleContext, vndkVersion, fileName string) android.Path {
- // The logic must be consistent with classifySourceAbiDump.
- isNdk := ctx.isNdk(ctx.Config())
- isVndk := ctx.useVndk() && ctx.isVndk()
-
- refAbiDumpTextFile := pathForVndkRefAbiDump(ctx, vndkVersion, fileName, isNdk, isVndk, false)
- refAbiDumpGzipFile := pathForVndkRefAbiDump(ctx, vndkVersion, fileName, isNdk, isVndk, true)
-
- if refAbiDumpTextFile.Valid() {
- if refAbiDumpGzipFile.Valid() {
- ctx.ModuleErrorf(
- "Two reference ABI dump files are found: %q and %q. Please delete the stale one.",
- refAbiDumpTextFile, refAbiDumpGzipFile)
- return nil
- }
- return refAbiDumpTextFile.Path()
- }
- if refAbiDumpGzipFile.Valid() {
- return unzipRefDump(ctx, refAbiDumpGzipFile.Path(), fileName)
- }
- return nil
-}
-
-func prevDumpRefVersion(ctx ModuleContext) int {
+func prevRefAbiDumpVersion(ctx ModuleContext, dumpDir string) int {
sdkVersionInt := ctx.Config().PlatformSdkVersion().FinalInt()
sdkVersionStr := ctx.Config().PlatformSdkVersion().String()
if ctx.Config().PlatformSdkFinal() {
return sdkVersionInt - 1
} else {
- var dirName string
-
- isNdk := ctx.isNdk(ctx.Config())
- if isNdk {
- dirName = "ndk"
- } else {
- dirName = "platform"
- }
-
// The platform SDK version can be upgraded before finalization while the corresponding abi dumps hasn't
// been generated. Thus the Cross-Version Check chooses PLATFORM_SDK_VERION - 1 as previous version.
// This situation could be identified by checking the existence of the PLATFORM_SDK_VERION dump directory.
- refDumpDir := android.ExistentPathForSource(ctx, "prebuilts", "abi-dumps", dirName, sdkVersionStr)
- if refDumpDir.Valid() {
+ versionedDumpDir := android.ExistentPathForSource(ctx, dumpDir, sdkVersionStr)
+ if versionedDumpDir.Valid() {
return sdkVersionInt
} else {
return sdkVersionInt - 1
@@ -1723,25 +1839,69 @@
}
}
+func currRefAbiDumpVersion(ctx ModuleContext, isVndk bool) string {
+ if isVndk {
+ // Each version of VNDK is independent, so follow the VNDK version which is the codename or PLATFORM_SDK_VERSION.
+ return ctx.Module().(*Module).VndkVersion()
+ } else if ctx.Config().PlatformSdkFinal() {
+ // After sdk finalization, the ABI of the latest API level must be consistent with the source code,
+ // so choose PLATFORM_SDK_VERSION as the current version.
+ return ctx.Config().PlatformSdkVersion().String()
+ } else {
+ return "current"
+ }
+}
+
+// sourceAbiDiff registers a build statement to compare linked sAbi dump files (.lsdump).
+func (library *libraryDecorator) sourceAbiDiff(ctx android.ModuleContext, referenceDump android.Path,
+ baseName, nameExt string, isLlndkOrNdk, allowExtensions bool,
+ sourceVersion, errorMessage string) {
+
+ sourceDump := library.sAbiOutputFile.Path()
+
+ extraFlags := []string{"-target-version", sourceVersion}
+ if Bool(library.Properties.Header_abi_checker.Check_all_apis) {
+ extraFlags = append(extraFlags, "-check-all-apis")
+ } else {
+ extraFlags = append(extraFlags,
+ "-allow-unreferenced-changes",
+ "-allow-unreferenced-elf-symbol-changes")
+ }
+ if isLlndkOrNdk {
+ extraFlags = append(extraFlags, "-consider-opaque-types-different")
+ }
+ if allowExtensions {
+ extraFlags = append(extraFlags, "-allow-extensions")
+ }
+ extraFlags = append(extraFlags, library.Properties.Header_abi_checker.Diff_flags...)
+
+ library.sAbiDiff = append(
+ library.sAbiDiff,
+ transformAbiDumpToAbiDiff(ctx, sourceDump, referenceDump,
+ baseName, nameExt, extraFlags, errorMessage))
+}
+
+func (library *libraryDecorator) crossVersionAbiDiff(ctx android.ModuleContext, referenceDump android.Path,
+ baseName string, isLlndkOrNdk bool, sourceVersion, prevVersion string) {
+
+ errorMessage := "error: Please follow https://android.googlesource.com/platform/development/+/master/vndk/tools/header-checker/README.md#configure-cross_version-abi-check to resolve the ABI difference between your source code and version " + prevVersion + "."
+
+ library.sourceAbiDiff(ctx, referenceDump, baseName, prevVersion,
+ isLlndkOrNdk, /* allowExtensions */ true, sourceVersion, errorMessage)
+}
+
+func (library *libraryDecorator) sameVersionAbiDiff(ctx android.ModuleContext, referenceDump android.Path,
+ baseName string, isLlndkOrNdk, allowExtensions bool) {
+
+ libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
+ errorMessage := "error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l " + libName
+
+ library.sourceAbiDiff(ctx, referenceDump, baseName, /* nameExt */ "",
+ isLlndkOrNdk, allowExtensions, "current", errorMessage)
+}
+
func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objects, fileName string, soFile android.Path) {
if library.sabi.shouldCreateSourceAbiDump() {
- var version string
- var prevVersion int
-
- if ctx.useVndk() {
- // For modules linking against vndk, follow its vndk version
- version = ctx.Module().(*Module).VndkVersion()
- } else {
- // After sdk finalizatoin, the ABI of the latest API level must be consistent with the source code
- // so the chosen reference dump is the PLATFORM_SDK_VERSION.
- if ctx.Config().PlatformSdkFinal() {
- version = ctx.Config().PlatformSdkVersion().String()
- } else {
- version = "current"
- }
- prevVersion = prevDumpRefVersion(ctx)
- }
-
exportIncludeDirs := library.flagExporter.exportedIncludes(ctx)
var SourceAbiFlags []string
for _, dir := range exportIncludeDirs.Strings() {
@@ -1758,26 +1918,31 @@
addLsdumpPath(classifySourceAbiDump(ctx) + ":" + library.sAbiOutputFile.String())
+ // The logic must be consistent with classifySourceAbiDump.
+ isVndk := ctx.useVndk() && ctx.isVndk()
+ isNdk := ctx.isNdk(ctx.Config())
+ isLlndk := ctx.isImplementationForLLNDKPublic()
+ dumpDir := getRefAbiDumpDir(isNdk, isVndk)
+ binderBitness := ctx.DeviceConfig().BinderBitness()
// If NDK or PLATFORM library, check against previous version ABI.
- if !ctx.useVndk() {
- prevRefAbiDumpFile := getRefAbiDumpFile(ctx, strconv.Itoa(prevVersion), fileName)
- if prevRefAbiDumpFile != nil {
- library.prevSAbiDiff = sourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
- prevRefAbiDumpFile, fileName, exportedHeaderFlags,
- library.Properties.Header_abi_checker.Diff_flags, prevVersion,
- Bool(library.Properties.Header_abi_checker.Check_all_apis),
- ctx.IsLlndk(), ctx.isNdk(ctx.Config()), ctx.IsVndkExt(), true)
+ if !isVndk {
+ prevVersionInt := prevRefAbiDumpVersion(ctx, dumpDir)
+ prevVersion := strconv.Itoa(prevVersionInt)
+ prevDumpDir := filepath.Join(dumpDir, prevVersion, binderBitness)
+ prevDumpFile := getRefAbiDumpFile(ctx, prevDumpDir, fileName)
+ if prevDumpFile.Valid() {
+ library.crossVersionAbiDiff(ctx, prevDumpFile.Path(),
+ fileName, isLlndk || isNdk,
+ strconv.Itoa(prevVersionInt+1), prevVersion)
}
}
-
- refAbiDumpFile := getRefAbiDumpFile(ctx, version, fileName)
- if refAbiDumpFile != nil {
- library.sAbiDiff = sourceAbiDiff(ctx, library.sAbiOutputFile.Path(),
- refAbiDumpFile, fileName, exportedHeaderFlags,
- library.Properties.Header_abi_checker.Diff_flags,
- /* unused if not previousVersionDiff */ 0,
- Bool(library.Properties.Header_abi_checker.Check_all_apis),
- ctx.IsLlndk(), ctx.isNdk(ctx.Config()), ctx.IsVndkExt(), false)
+ // Check against the current version.
+ currVersion := currRefAbiDumpVersion(ctx, isVndk)
+ currDumpDir := filepath.Join(dumpDir, currVersion, binderBitness)
+ currDumpFile := getRefAbiDumpFile(ctx, currDumpDir, fileName)
+ if currDumpFile.Valid() {
+ library.sameVersionAbiDiff(ctx, currDumpFile.Path(),
+ fileName, isLlndk || isNdk, ctx.IsVndkExt())
}
}
}
@@ -2145,6 +2310,10 @@
len(library.Properties.Stubs.Versions) > 0
}
+func (library *libraryDecorator) isStubsImplementationRequired() bool {
+ return BoolDefault(library.Properties.Stubs.Implementation_installable, true)
+}
+
func (library *libraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
if !library.hasStubsVariants() {
return nil
@@ -2227,10 +2396,20 @@
mod.ModuleBase.MakeUninstallable()
}
+func (library *libraryDecorator) getPartition() string {
+ return library.path.Partition()
+}
+
func (library *libraryDecorator) getAPIListCoverageXMLPath() android.ModuleOutPath {
return library.apiListCoverageXmlPath
}
+func (library *libraryDecorator) overriddenModules() []string {
+ return library.Properties.Overrides
+}
+
+var _ overridable = (*libraryDecorator)(nil)
+
var versioningMacroNamesListKey = android.NewOnceKey("versioningMacroNamesList")
// versioningMacroNamesList returns a singleton map, where keys are "version macro names",
@@ -2435,11 +2614,12 @@
m := mctx.Module().(*Module)
isLLNDK := m.IsLlndk()
isVendorPublicLibrary := m.IsVendorPublicLibrary()
+ isImportedApiLibrary := m.isImportedApiLibrary()
modules := mctx.CreateLocalVariations(variants...)
for i, m := range modules {
- if variants[i] != "" || isLLNDK || isVendorPublicLibrary {
+ if variants[i] != "" || isLLNDK || isVendorPublicLibrary || isImportedApiLibrary {
// A stubs or LLNDK stubs variant.
c := m.(*Module)
c.sanitize = nil
@@ -2582,6 +2762,29 @@
return outputFile
}
+func bp2buildParseAbiCheckerProps(ctx android.TopDownMutatorContext, module *Module) bazelCcHeaderAbiCheckerAttributes {
+ lib, ok := module.linker.(*libraryDecorator)
+ if !ok {
+ return bazelCcHeaderAbiCheckerAttributes{}
+ }
+
+ abiChecker := lib.Properties.Header_abi_checker
+
+ abiCheckerAttrs := bazelCcHeaderAbiCheckerAttributes{
+ Abi_checker_enabled: abiChecker.Enabled,
+ Abi_checker_exclude_symbol_versions: abiChecker.Exclude_symbol_versions,
+ Abi_checker_exclude_symbol_tags: abiChecker.Exclude_symbol_tags,
+ Abi_checker_check_all_apis: abiChecker.Check_all_apis,
+ Abi_checker_diff_flags: abiChecker.Diff_flags,
+ }
+ if abiChecker.Symbol_file != nil {
+ symbolFile := android.BazelLabelForModuleSrcSingle(ctx, *abiChecker.Symbol_file)
+ abiCheckerAttrs.Abi_checker_symbol_file = &symbolFile
+ }
+
+ return abiCheckerAttrs
+}
+
func sharedOrStaticLibraryBp2Build(ctx android.TopDownMutatorContext, module *Module, isStatic bool) {
baseAttributes := bp2BuildParseBaseProps(ctx, module)
compilerAttrs := baseAttributes.compilerAttributes
@@ -2629,6 +2832,8 @@
Runtime_deps: linkerAttrs.runtimeDeps,
}
+ module.convertTidyAttributes(ctx, &commonAttrs.tidyAttributes)
+
var attrs interface{}
if isStatic {
commonAttrs.Deps.Add(baseAttributes.protoDependency)
@@ -2681,21 +2886,18 @@
Absolute_includes: compilerAttrs.absoluteIncludes,
Additional_linker_inputs: linkerAttrs.additionalLinkerInputs,
- Strip: stripAttributes{
- Keep_symbols: linkerAttrs.stripKeepSymbols,
- Keep_symbols_and_debug_frame: linkerAttrs.stripKeepSymbolsAndDebugFrame,
- Keep_symbols_list: linkerAttrs.stripKeepSymbolsList,
- All: linkerAttrs.stripAll,
- None: linkerAttrs.stripNone,
- },
+ Strip: stripAttrsFromLinkerAttrs(&linkerAttrs),
Features: baseAttributes.features,
Suffix: compilerAttrs.suffix,
+
+ bazelCcHeaderAbiCheckerAttributes: bp2buildParseAbiCheckerProps(ctx, module),
}
if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 {
hasStubs := true
sharedLibAttrs.Has_stubs.SetValue(&hasStubs)
+ sharedLibAttrs.Stubs_symbol_file = compilerAttrs.stubsSymbolFile
}
attrs = sharedLibAttrs
}
@@ -2772,11 +2974,14 @@
Features bazel.StringListAttribute
- Has_stubs bazel.BoolAttribute
+ Has_stubs bazel.BoolAttribute
+ Stubs_symbol_file *string
Inject_bssl_hash bazel.BoolAttribute
Suffix bazel.StringAttribute
+
+ bazelCcHeaderAbiCheckerAttributes
}
type bazelCcStubSuiteAttributes struct {
@@ -2787,3 +2992,12 @@
Soname *string
Deps bazel.LabelListAttribute
}
+
+type bazelCcHeaderAbiCheckerAttributes struct {
+ Abi_checker_enabled *bool
+ Abi_checker_symbol_file *bazel.Label
+ Abi_checker_exclude_symbol_versions []string
+ Abi_checker_exclude_symbol_tags []string
+ Abi_checker_check_all_apis *bool
+ Abi_checker_diff_flags []string
+}
diff --git a/cc/library_headers.go b/cc/library_headers.go
index a683f58..1c4f354 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -15,6 +15,8 @@
package cc
import (
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
"android/soong/bazel"
"android/soong/bazel/cquery"
@@ -145,3 +147,118 @@
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
}
+
+// Append .contribution suffix to input labels
+func apiBazelTargets(ll bazel.LabelList) bazel.LabelList {
+ labels := make([]bazel.Label, 0)
+ for _, l := range ll.Includes {
+ labels = append(labels, bazel.Label{
+ Label: android.ApiContributionTargetName(l.Label),
+ })
+ }
+ return bazel.MakeLabelList(labels)
+}
+
+func apiLibraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) {
+ // cc_api_library_headers have a 1:1 mapping to arch/no-arch
+ // For API export, create a top-level arch-agnostic target and list the arch-specific targets as its deps
+
+ // arch-agnostic includes
+ apiIncludes := getSystemApiIncludes(ctx, module)
+ // arch and os specific includes
+ archApiIncludes, androidOsIncludes := archOsSpecificApiIncludes(ctx, module)
+ for _, arch := range allArches { // sorted iteration
+ archApiInclude := archApiIncludes[arch]
+ if !archApiInclude.isEmpty() {
+ createApiHeaderTarget(ctx, archApiInclude)
+ apiIncludes.addDep(archApiInclude.name)
+ }
+ }
+ // os==android includes
+ if !androidOsIncludes.isEmpty() {
+ createApiHeaderTarget(ctx, androidOsIncludes)
+ apiIncludes.addDep(androidOsIncludes.name)
+ }
+
+ if !apiIncludes.isEmpty() {
+ // override the name from <mod>.systemapi.headers --> <mod>.contribution
+ apiIncludes.name = android.ApiContributionTargetName(module.Name())
+ createApiHeaderTarget(ctx, apiIncludes)
+ }
+}
+
+func createApiHeaderTarget(ctx android.TopDownMutatorContext, includes apiIncludes) {
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_api_library_headers",
+ Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl",
+ }
+ ctx.CreateBazelTargetModule(
+ props,
+ android.CommonAttributes{
+ Name: includes.name,
+ SkipData: proptools.BoolPtr(true),
+ },
+ &includes.attrs,
+ )
+}
+
+var (
+ allArches = []string{"arm", "arm64", "x86", "x86_64"}
+)
+
+type archApiIncludes map[string]apiIncludes
+
+func archOsSpecificApiIncludes(ctx android.TopDownMutatorContext, module *Module) (archApiIncludes, apiIncludes) {
+ baseProps := bp2BuildParseBaseProps(ctx, module)
+ i := bp2BuildParseExportedIncludes(ctx, module, &baseProps.includes)
+ archRet := archApiIncludes{}
+ for _, arch := range allArches {
+ includes := i.Includes.SelectValue(
+ bazel.ArchConfigurationAxis,
+ arch)
+ systemIncludes := i.SystemIncludes.SelectValue(
+ bazel.ArchConfigurationAxis,
+ arch)
+ deps := baseProps.deps.SelectValue(
+ bazel.ArchConfigurationAxis,
+ arch)
+ attrs := bazelCcLibraryHeadersAttributes{
+ Export_includes: bazel.MakeStringListAttribute(includes),
+ Export_system_includes: bazel.MakeStringListAttribute(systemIncludes),
+ }
+ apiDeps := apiBazelTargets(deps)
+ if !apiDeps.IsEmpty() {
+ attrs.Deps = bazel.MakeLabelListAttribute(apiDeps)
+ }
+ apiIncludes := apiIncludes{
+ name: android.ApiContributionTargetName(module.Name()) + "." + arch,
+ attrs: bazelCcApiLibraryHeadersAttributes{
+ bazelCcLibraryHeadersAttributes: attrs,
+ Arch: proptools.StringPtr(arch),
+ },
+ }
+ archRet[arch] = apiIncludes
+ }
+
+ // apiIncludes for os == Android
+ androidOsDeps := baseProps.deps.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid)
+ androidOsAttrs := bazelCcLibraryHeadersAttributes{
+ Export_includes: bazel.MakeStringListAttribute(
+ i.Includes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid),
+ ),
+ Export_system_includes: bazel.MakeStringListAttribute(
+ i.SystemIncludes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid),
+ ),
+ }
+ androidOsApiDeps := apiBazelTargets(androidOsDeps)
+ if !androidOsApiDeps.IsEmpty() {
+ androidOsAttrs.Deps = bazel.MakeLabelListAttribute(androidOsApiDeps)
+ }
+ osRet := apiIncludes{
+ name: android.ApiContributionTargetName(module.Name()) + ".androidos",
+ attrs: bazelCcApiLibraryHeadersAttributes{
+ bazelCcLibraryHeadersAttributes: androidOsAttrs,
+ },
+ }
+ return archRet, osRet
+}
diff --git a/cc/library_stub.go b/cc/library_stub.go
index 2ebb6ef..22e61a7 100644
--- a/cc/library_stub.go
+++ b/cc/library_stub.go
@@ -15,10 +15,17 @@
package cc
import (
+ "regexp"
+ "strings"
+
"android/soong/android"
"android/soong/multitree"
)
+var (
+ ndkVariantRegex = regexp.MustCompile("ndk\\.([a-zA-Z0-9]+)")
+)
+
func init() {
RegisterLibraryStubBuildComponents(android.InitRegistrationContext)
}
@@ -26,10 +33,34 @@
func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("cc_api_library", CcApiLibraryFactory)
ctx.RegisterModuleType("cc_api_headers", CcApiHeadersFactory)
+ ctx.RegisterModuleType("cc_api_variant", CcApiVariantFactory)
+}
- // cc_api_stub_library shares a lot of ndk_library, and this will be refactored later
- ctx.RegisterModuleType("cc_api_stub_library", CcApiStubLibraryFactory)
- ctx.RegisterModuleType("cc_api_contribution", CcApiContributionFactory)
+func updateImportedLibraryDependency(ctx android.BottomUpMutatorContext) {
+ m, ok := ctx.Module().(*Module)
+ if !ok {
+ return
+ }
+
+ apiLibrary, ok := m.linker.(*apiLibraryDecorator)
+ if !ok {
+ return
+ }
+
+ if m.UseVndk() && apiLibrary.hasLLNDKStubs() {
+ // Add LLNDK variant dependency
+ if inList("llndk", apiLibrary.properties.Variants) {
+ variantName := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
+ ctx.AddDependency(m, nil, variantName)
+ }
+ } else if m.IsSdkVariant() {
+ // Add NDK variant dependencies
+ targetVariant := "ndk." + m.StubsVersion()
+ if inList(targetVariant, apiLibrary.properties.Variants) {
+ variantName := BuildApiVariantName(m.BaseModuleName(), targetVariant, "")
+ ctx.AddDependency(m, nil, variantName)
+ }
+ }
}
// 'cc_api_library' is a module type which is from the exported API surface
@@ -37,7 +68,8 @@
// offer a link to the module that generates shared library object from the
// map file.
type apiLibraryProperties struct {
- Src *string `android:"arch_variant"`
+ Src *string `android:"arch_variant"`
+ Variants []string
}
type apiLibraryDecorator struct {
@@ -59,11 +91,9 @@
module.compiler = nil
module.linker = apiLibraryDecorator
module.installer = nil
+ module.library = apiLibraryDecorator
module.AddProperties(&module.Properties, &apiLibraryDecorator.properties)
- // Mark module as stub, so APEX would not include this stub in the package.
- module.library.setBuildStubs(true)
-
// Prevent default system libs (libc, libm, and libdl) from being linked
if apiLibraryDecorator.baseLinker.Properties.System_shared_libs == nil {
apiLibraryDecorator.baseLinker.Properties.System_shared_libs = []string{}
@@ -81,25 +111,121 @@
return basename + multitree.GetApiImportSuffix()
}
+// Export include dirs without checking for existence.
+// The directories are not guaranteed to exist during Soong analysis.
+func (d *apiLibraryDecorator) exportIncludes(ctx ModuleContext) {
+ exporterProps := d.flagExporter.Properties
+ for _, dir := range exporterProps.Export_include_dirs {
+ d.dirs = append(d.dirs, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), dir))
+ }
+ // system headers
+ for _, dir := range exporterProps.Export_system_include_dirs {
+ d.systemDirs = append(d.systemDirs, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), dir))
+ }
+}
+
+func (d *apiLibraryDecorator) linkerInit(ctx BaseModuleContext) {
+ d.baseLinker.linkerInit(ctx)
+
+ if d.hasNDKStubs() {
+ // Set SDK version of module as current
+ ctx.Module().(*Module).Properties.Sdk_version = StringPtr("current")
+
+ // Add NDK stub as NDK known libs
+ name := ctx.ModuleName()
+
+ ndkKnownLibsLock.Lock()
+ ndkKnownLibs := getNDKKnownLibs(ctx.Config())
+ if !inList(name, *ndkKnownLibs) {
+ *ndkKnownLibs = append(*ndkKnownLibs, name)
+ }
+ ndkKnownLibsLock.Unlock()
+ }
+}
+
func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
- // Export headers as system include dirs if specified. Mostly for libc
- if Bool(d.libraryDecorator.Properties.Llndk.Export_headers_as_system) {
- d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs = append(
- d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
- d.libraryDecorator.flagExporter.Properties.Export_include_dirs...)
- d.libraryDecorator.flagExporter.Properties.Export_include_dirs = nil
+ m, _ := ctx.Module().(*Module)
+
+ var in android.Path
+
+ if src := String(d.properties.Src); src != "" {
+ in = android.PathForModuleSrc(ctx, src)
+ }
+
+ // LLNDK variant
+ if m.UseVndk() && d.hasLLNDKStubs() {
+ apiVariantModule := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
+
+ var mod android.Module
+
+ ctx.VisitDirectDeps(func(depMod android.Module) {
+ if depMod.Name() == apiVariantModule {
+ mod = depMod
+ }
+ })
+
+ if mod != nil {
+ variantMod, ok := mod.(*CcApiVariant)
+ if ok {
+ in = variantMod.Src()
+
+ // Copy LLDNK properties to cc_api_library module
+ d.libraryDecorator.flagExporter.Properties.Export_include_dirs = append(
+ d.libraryDecorator.flagExporter.Properties.Export_include_dirs,
+ variantMod.exportProperties.Export_headers...)
+
+ // Export headers as system include dirs if specified. Mostly for libc
+ if Bool(variantMod.exportProperties.Export_headers_as_system) {
+ d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs = append(
+ d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
+ d.libraryDecorator.flagExporter.Properties.Export_include_dirs...)
+ d.libraryDecorator.flagExporter.Properties.Export_include_dirs = nil
+ }
+ }
+ }
+ } else if m.IsSdkVariant() {
+ // NDK Variant
+ apiVariantModule := BuildApiVariantName(m.BaseModuleName(), "ndk", m.StubsVersion())
+
+ var mod android.Module
+
+ ctx.VisitDirectDeps(func(depMod android.Module) {
+ if depMod.Name() == apiVariantModule {
+ mod = depMod
+ }
+ })
+
+ if mod != nil {
+ variantMod, ok := mod.(*CcApiVariant)
+ if ok {
+ in = variantMod.Src()
+
+ // Copy NDK properties to cc_api_library module
+ d.libraryDecorator.flagExporter.Properties.Export_include_dirs = append(
+ d.libraryDecorator.flagExporter.Properties.Export_include_dirs,
+ variantMod.exportProperties.Export_headers...)
+ }
+ }
}
// Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
- d.libraryDecorator.flagExporter.exportIncludes(ctx)
+ d.exportIncludes(ctx)
d.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
d.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
d.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
d.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
d.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
- d.libraryDecorator.flagExporter.setProvider(ctx)
- in := android.PathForModuleSrc(ctx, *d.properties.Src)
+ if in == nil {
+ ctx.PropertyErrorf("src", "Unable to locate source property")
+ return nil
+ }
+
+ // Make the _compilation_ of rdeps have an order-only dep on cc_api_library.src (an .so file)
+ // The .so file itself has an order-only dependency on the headers contributed by this library.
+ // Creating this dependency ensures that the headers are assembled before compilation of rdeps begins.
+ d.libraryDecorator.reexportDeps(in)
+ d.libraryDecorator.flagExporter.setProvider(ctx)
d.unstrippedOutputFile = in
libName := d.libraryDecorator.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
@@ -123,6 +249,67 @@
return true
}
+func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
+ m, ok := ctx.Module().(*Module)
+
+ if !ok {
+ return nil
+ }
+
+ if d.hasLLNDKStubs() && m.UseVndk() {
+ // LLNDK libraries only need a single stubs variant.
+ return []string{android.FutureApiLevel.String()}
+ }
+
+ // TODO(b/244244438) Create more version information for NDK and APEX variations
+ // NDK variants
+
+ if m.IsSdkVariant() {
+ // TODO(b/249193999) Do not check if module has NDK stubs once all NDK cc_api_library contains ndk variant of cc_api_variant.
+ if d.hasNDKStubs() {
+ return d.getNdkVersions()
+ }
+ }
+
+ if m.MinSdkVersion() == "" {
+ return nil
+ }
+
+ firstVersion, err := nativeApiLevelFromUser(ctx,
+ m.MinSdkVersion())
+
+ if err != nil {
+ return nil
+ }
+
+ return ndkLibraryVersions(ctx, firstVersion)
+}
+
+func (d *apiLibraryDecorator) hasLLNDKStubs() bool {
+ return inList("llndk", d.properties.Variants)
+}
+
+func (d *apiLibraryDecorator) hasNDKStubs() bool {
+ for _, variant := range d.properties.Variants {
+ if ndkVariantRegex.MatchString(variant) {
+ return true
+ }
+ }
+ return false
+}
+
+func (d *apiLibraryDecorator) getNdkVersions() []string {
+ ndkVersions := []string{}
+
+ for _, variant := range d.properties.Variants {
+ if match := ndkVariantRegex.FindStringSubmatch(variant); len(match) == 2 {
+ ndkVersions = append(ndkVersions, match[1])
+ }
+ }
+
+ return ndkVersions
+}
+
// 'cc_api_headers' is similar with 'cc_api_library', but which replaces
// header libraries. The module will replace any dependencies to existing
// original header libraries.
@@ -145,9 +332,6 @@
module.linker = apiHeadersDecorator
module.installer = nil
- // Mark module as stub, so APEX would not include this stub in the package.
- module.library.setBuildStubs(true)
-
// Prevent default system libs (libc, libm, and libdl) from being linked
if apiHeadersDecorator.baseLinker.Properties.System_shared_libs == nil {
apiHeadersDecorator.baseLinker.Properties.System_shared_libs = []string{}
@@ -170,135 +354,92 @@
return true
}
-func CcApiStubLibraryFactory() android.Module {
- module, decorator := NewLibrary(android.DeviceSupported)
- apiStubDecorator := &apiStubDecorator{
- libraryDecorator: decorator,
- }
- apiStubDecorator.BuildOnlyShared()
+type ccApiexportProperties struct {
+ Src *string `android:"arch_variant"`
+ Variant *string
+ Version *string
+}
- module.compiler = apiStubDecorator
- module.linker = apiStubDecorator
- module.installer = nil
- module.library = apiStubDecorator
- module.Properties.HideFromMake = true // TODO: remove
+type variantExporterProperties struct {
+ // Header directory to export
+ Export_headers []string `android:"arch_variant"`
+
+ // Export all headers as system include
+ Export_headers_as_system *bool
+}
+
+type CcApiVariant struct {
+ android.ModuleBase
+
+ properties ccApiexportProperties
+ exportProperties variantExporterProperties
+
+ src android.Path
+}
+
+var _ android.Module = (*CcApiVariant)(nil)
+var _ android.ImageInterface = (*CcApiVariant)(nil)
+
+func CcApiVariantFactory() android.Module {
+ module := &CcApiVariant{}
+
+ module.AddProperties(&module.properties)
+ module.AddProperties(&module.exportProperties)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
- module.AddProperties(&module.Properties,
- &apiStubDecorator.properties,
- &apiStubDecorator.MutatedProperties,
- &apiStubDecorator.apiStubLibraryProperties)
return module
}
-type apiStubLiraryProperties struct {
- Imported_includes []string `android:"path"`
-}
+func (v *CcApiVariant) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ // No need to build
-type apiStubDecorator struct {
- *libraryDecorator
- properties libraryProperties
- apiStubLibraryProperties apiStubLiraryProperties
-}
-
-func (compiler *apiStubDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
- firstVersion := String(compiler.properties.First_version)
- return ndkLibraryVersions(ctx, android.ApiLevelOrPanic(ctx, firstVersion))
-}
-
-func (decorator *apiStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
- if decorator.stubsVersion() == "" {
- decorator.setStubsVersion("current")
- } // TODO: fix
- symbolFile := String(decorator.properties.Symbol_file)
- nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile,
- android.ApiLevelOrPanic(ctx, decorator.stubsVersion()),
- "")
- return compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
-}
-
-func (decorator *apiStubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
- decorator.reexportDirs(android.PathsForModuleSrc(ctx, decorator.apiStubLibraryProperties.Imported_includes)...)
- return decorator.libraryDecorator.link(ctx, flags, deps, objects)
-}
-
-func init() {
- pctx.HostBinToolVariable("gen_api_surface_build_files", "gen_api_surface_build_files")
-}
-
-type CcApiContribution struct {
- android.ModuleBase
- properties ccApiContributionProperties
-}
-
-type ccApiContributionProperties struct {
- Symbol_file *string `android:"path"`
- First_version *string
- Export_include_dir *string
-}
-
-func CcApiContributionFactory() android.Module {
- module := &CcApiContribution{}
- module.AddProperties(&module.properties)
- android.InitAndroidModule(module)
- return module
-}
-
-// Do some simple validations
-// Majority of the build rules will be created in the ctx of the api surface this module contributes to
-func (contrib *CcApiContribution) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- if contrib.properties.Symbol_file == nil {
- ctx.PropertyErrorf("symbol_file", "%v does not have symbol file", ctx.ModuleName())
+ if String(v.properties.Src) == "" {
+ ctx.PropertyErrorf("src", "src is a required property")
}
- if contrib.properties.First_version == nil {
- ctx.PropertyErrorf("first_version", "%v does not have first_version for stub variants", ctx.ModuleName())
+
+ // Skip the existence check of the stub prebuilt file.
+ // The file is not guaranteed to exist during Soong analysis.
+ // Build orchestrator will be responsible for creating a connected ninja graph.
+ v.src = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), String(v.properties.Src))
+}
+
+func (v *CcApiVariant) Name() string {
+ version := String(v.properties.Version)
+ return BuildApiVariantName(v.BaseModuleName(), *v.properties.Variant, version)
+}
+
+func (v *CcApiVariant) Src() android.Path {
+ return v.src
+}
+
+func BuildApiVariantName(baseName string, variant string, version string) string {
+ names := []string{baseName, variant}
+ if version != "" {
+ names = append(names, version)
}
+
+ return strings.Join(names[:], ".") + multitree.GetApiImportSuffix()
}
-// Path is out/soong/.export/ but will be different in final multi-tree layout
-func outPathApiSurface(ctx android.ModuleContext, myModuleName string, pathComponent string) android.OutputPath {
- return android.PathForOutput(ctx, ".export", ctx.ModuleName(), myModuleName, pathComponent)
+// Implement ImageInterface to generate image variants
+func (v *CcApiVariant) ImageMutatorBegin(ctx android.BaseModuleContext) {}
+func (v *CcApiVariant) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+ return String(v.properties.Variant) == "ndk"
}
+func (v *CcApiVariant) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
+func (v *CcApiVariant) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
+func (v *CcApiVariant) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
+func (v *CcApiVariant) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { return false }
+func (v *CcApiVariant) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+ var variations []string
+ platformVndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
-func (contrib *CcApiContribution) CopyFilesWithTag(apiSurfaceContext android.ModuleContext) map[string]android.Paths {
- // copy map.txt for now
- // hardlinks cannot be created since nsjail creates a different mountpoint for out/
- myDir := apiSurfaceContext.OtherModuleDir(contrib)
- genMapTxt := outPathApiSurface(apiSurfaceContext, contrib.Name(), String(contrib.properties.Symbol_file))
- apiSurfaceContext.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Description: "import map.txt file",
- Input: android.PathForSource(apiSurfaceContext, myDir, String(contrib.properties.Symbol_file)),
- Output: genMapTxt,
- })
-
- outputs := make(map[string]android.Paths)
- outputs["map"] = []android.Path{genMapTxt}
-
- if contrib.properties.Export_include_dir != nil {
- includeDir := android.PathForSource(apiSurfaceContext, myDir, String(contrib.properties.Export_include_dir))
- outputs["export_include_dir"] = []android.Path{includeDir}
+ if String(v.properties.Variant) == "llndk" {
+ variations = append(variations, VendorVariationPrefix+platformVndkVersion)
+ variations = append(variations, ProductVariationPrefix+platformVndkVersion)
}
- return outputs
+
+ return variations
}
-
-var _ multitree.ApiContribution = (*CcApiContribution)(nil)
-
-/*
-func (contrib *CcApiContribution) GenerateBuildFiles(apiSurfaceContext android.ModuleContext) android.Paths {
- genAndroidBp := outPathApiSurface(apiSurfaceContext, contrib.Name(), "Android.bp")
-
- // generate Android.bp
- apiSurfaceContext.Build(pctx, android.BuildParams{
- Rule: genApiSurfaceBuildFiles,
- Description: "generate API surface build files",
- Outputs: []android.WritablePath{genAndroidBp},
- Args: map[string]string{
- "name": contrib.Name() + "." + apiSurfaceContext.ModuleName(), //e.g. liblog.ndk
- "symbol_file": String(contrib.properties.Symbol_file),
- "first_version": String(contrib.properties.First_version),
- },
- })
- return []android.Path{genAndroidBp}
+func (v *CcApiVariant) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
}
-*/
diff --git a/cc/library_stub_test.go b/cc/library_stub_test.go
index cd06172..e372860 100644
--- a/cc/library_stub_test.go
+++ b/cc/library_stub_test.go
@@ -21,94 +21,10 @@
"testing"
"android/soong/android"
- "android/soong/multitree"
"github.com/google/blueprint"
)
-func TestCcApiStubLibraryOutputFiles(t *testing.T) {
- bp := `
- cc_api_stub_library {
- name: "foo",
- symbol_file: "foo.map.txt",
- first_version: "29",
- }
- `
- result := prepareForCcTest.RunTestWithBp(t, bp)
- outputs := result.ModuleForTests("foo", "android_arm64_armv8-a_shared").AllOutputs()
- expected_file_suffixes := []string{".c", "stub.map", ".o", ".so"}
- for _, expected_file_suffix := range expected_file_suffixes {
- android.AssertBoolEquals(t, expected_file_suffix+" file not found in output", true, android.SuffixInList(outputs, expected_file_suffix))
- }
-}
-
-func TestCcApiStubLibraryVariants(t *testing.T) {
- bp := `
- cc_api_stub_library {
- name: "foo",
- symbol_file: "foo.map.txt",
- first_version: "29",
- }
- `
- result := prepareForCcTest.RunTestWithBp(t, bp)
- variants := result.ModuleVariantsForTests("foo")
- expected_variants := []string{"29", "30", "S", "Tiramisu"} //TODO: make this test deterministic by using fixtures
- for _, expected_variant := range expected_variants {
- android.AssertBoolEquals(t, expected_variant+" variant not found in foo", true, android.SubstringInList(variants, expected_variant))
- }
-}
-
-func TestCcLibraryUsesCcApiStubLibrary(t *testing.T) {
- bp := `
- cc_api_stub_library {
- name: "foo",
- symbol_file: "foo.map.txt",
- first_version: "29",
- }
- cc_library {
- name: "foo_user",
- shared_libs: [
- "foo#29",
- ],
- }
-
- `
- prepareForCcTest.RunTestWithBp(t, bp)
-}
-
-func TestApiSurfaceOutputs(t *testing.T) {
- bp := `
- api_surface {
- name: "mysdk",
- contributions: [
- "foo",
- ],
- }
-
- cc_api_contribution {
- name: "foo",
- symbol_file: "foo.map.txt",
- first_version: "29",
- }
- `
- result := android.GroupFixturePreparers(
- prepareForCcTest,
- multitree.PrepareForTestWithApiSurface,
- ).RunTestWithBp(t, bp)
- mysdk := result.ModuleForTests("mysdk", "")
-
- actual_surface_inputs := mysdk.Rule("phony").BuildParams.Inputs.Strings()
- expected_file_suffixes := []string{"mysdk/foo/foo.map.txt"}
- for _, expected_file_suffix := range expected_file_suffixes {
- android.AssertBoolEquals(t, expected_file_suffix+" file not found in input", true, android.SuffixInList(actual_surface_inputs, expected_file_suffix))
- }
-
- // check args/inputs to rule
- /*api_surface_gen_rule_args := result.ModuleForTests("mysdk", "").Rule("genApiSurfaceBuildFiles").Args
- android.AssertStringEquals(t, "name", "foo.mysdk", api_surface_gen_rule_args["name"])
- android.AssertStringEquals(t, "symbol_file", "foo.map.txt", api_surface_gen_rule_args["symbol_file"])*/
-}
-
func hasDirectDependency(t *testing.T, ctx *android.TestResult, from android.Module, to android.Module) bool {
t.Helper()
var found bool
@@ -325,3 +241,269 @@
android.AssertBoolEquals(t, "original header should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeader))
android.AssertBoolEquals(t, "Header from API surface should not be used for original library", false, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport))
}
+
+func TestExportDirFromStubLibrary(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libfoo",
+ export_include_dirs: ["source_include_dir"],
+ export_system_include_dirs: ["source_system_include_dir"],
+ vendor_available: true,
+ }
+ cc_api_library {
+ name: "libfoo",
+ export_include_dirs: ["stub_include_dir"],
+ export_system_include_dirs: ["stub_system_include_dir"],
+ vendor_available: true,
+ src: "libfoo.so",
+ }
+ api_imports {
+ name: "api_imports",
+ shared_libs: [
+ "libfoo",
+ ],
+ header_libs: [],
+ }
+ // vendor binary
+ cc_binary {
+ name: "vendorbin",
+ vendor: true,
+ srcs: ["vendor.cc"],
+ shared_libs: ["libfoo"],
+ }
+ `
+ ctx := prepareForCcTest.RunTestWithBp(t, bp)
+ vendorCFlags := ctx.ModuleForTests("vendorbin", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
+ android.AssertStringDoesContain(t, "Vendor binary should compile using headers provided by stub", vendorCFlags, "-Istub_include_dir")
+ android.AssertStringDoesNotContain(t, "Vendor binary should not compile using headers of source", vendorCFlags, "-Isource_include_dir")
+ android.AssertStringDoesContain(t, "Vendor binary should compile using system headers provided by stub", vendorCFlags, "-isystem stub_system_include_dir")
+ android.AssertStringDoesNotContain(t, "Vendor binary should not compile using system headers of source", vendorCFlags, "-isystem source_system_include_dir")
+
+ vendorImplicits := ctx.ModuleForTests("vendorbin", "android_vendor.29_arm64_armv8-a").Rule("cc").OrderOnly.Strings()
+ // Building the stub.so file first assembles its .h files in multi-tree out.
+ // These header files are required for compiling the other API domain (vendor in this case)
+ android.AssertStringListContains(t, "Vendor binary compilation should have an implicit dep on the stub .so file", vendorImplicits, "libfoo.so")
+}
+
+func TestApiLibraryWithLlndkVariant(t *testing.T) {
+ bp := `
+ cc_binary {
+ name: "binfoo",
+ vendor: true,
+ srcs: ["binfoo.cc"],
+ shared_libs: ["libbar"],
+ }
+
+ cc_api_library {
+ name: "libbar",
+ // TODO(b/244244438) Remove src property once all variants are implemented.
+ src: "libbar.so",
+ vendor_available: true,
+ variants: [
+ "llndk",
+ ],
+ }
+
+ cc_api_variant {
+ name: "libbar",
+ variant: "llndk",
+ src: "libbar_llndk.so",
+ export_headers: ["libbar_llndk_include"]
+ }
+
+ api_imports {
+ name: "api_imports",
+ shared_libs: [
+ "libbar",
+ ],
+ header_libs: [],
+ }
+ `
+
+ ctx := prepareForCcTest.RunTestWithBp(t, bp)
+
+ binfoo := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Module()
+ libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
+ libbarApiVariant := ctx.ModuleForTests("libbar.llndk.apiimport", "android_vendor.29_arm64_armv8-a").Module()
+
+ android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, binfoo, libbarApiImport))
+ android.AssertBoolEquals(t, "Stub library variant from API surface should be linked", true, hasDirectDependency(t, ctx, libbarApiImport, libbarApiVariant))
+
+ binFooLibFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("ld").Args["libFlags"]
+ android.AssertStringDoesContain(t, "Vendor binary should be linked with LLNDK variant source", binFooLibFlags, "libbar_llndk.so")
+
+ binFooCFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
+ android.AssertStringDoesContain(t, "Vendor binary should include headers from the LLNDK variant source", binFooCFlags, "-Ilibbar_llndk_include")
+}
+
+func TestApiLibraryWithNdkVariant(t *testing.T) {
+ bp := `
+ cc_binary {
+ name: "binfoo",
+ sdk_version: "29",
+ srcs: ["binfoo.cc"],
+ shared_libs: ["libbar"],
+ stl: "c++_shared",
+ }
+
+ cc_binary {
+ name: "binbaz",
+ sdk_version: "30",
+ srcs: ["binbaz.cc"],
+ shared_libs: ["libbar"],
+ stl: "c++_shared",
+ }
+
+ cc_api_library {
+ name: "libbar",
+ // TODO(b/244244438) Remove src property once all variants are implemented.
+ src: "libbar.so",
+ variants: [
+ "ndk.29",
+ "ndk.30",
+ "ndk.current",
+ ],
+ }
+
+ cc_api_variant {
+ name: "libbar",
+ variant: "ndk",
+ version: "29",
+ src: "libbar_ndk_29.so",
+ export_headers: ["libbar_ndk_29_include"]
+ }
+
+ cc_api_variant {
+ name: "libbar",
+ variant: "ndk",
+ version: "30",
+ src: "libbar_ndk_30.so",
+ export_headers: ["libbar_ndk_30_include"]
+ }
+
+ cc_api_variant {
+ name: "libbar",
+ variant: "ndk",
+ version: "current",
+ src: "libbar_ndk_current.so",
+ export_headers: ["libbar_ndk_current_include"]
+ }
+
+ api_imports {
+ name: "api_imports",
+ shared_libs: [
+ "libbar",
+ ],
+ header_libs: [],
+ }
+ `
+
+ ctx := prepareForCcTest.RunTestWithBp(t, bp)
+
+ binfoo := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Module()
+ libbarApiImportv29 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_29").Module()
+ libbarApiVariantv29 := ctx.ModuleForTests("libbar.ndk.29.apiimport", "android_arm64_armv8-a_sdk").Module()
+ libbarApiImportv30 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_30").Module()
+ libbarApiVariantv30 := ctx.ModuleForTests("libbar.ndk.30.apiimport", "android_arm64_armv8-a_sdk").Module()
+
+ android.AssertBoolEquals(t, "Stub library from API surface should be linked with target version", true, hasDirectDependency(t, ctx, binfoo, libbarApiImportv29))
+ android.AssertBoolEquals(t, "Stub library variant from API surface should be linked with target version", true, hasDirectDependency(t, ctx, libbarApiImportv29, libbarApiVariantv29))
+ android.AssertBoolEquals(t, "Stub library from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, binfoo, libbarApiImportv30))
+ android.AssertBoolEquals(t, "Stub library variant from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, libbarApiImportv29, libbarApiVariantv30))
+
+ binbaz := ctx.ModuleForTests("binbaz", "android_arm64_armv8-a_sdk").Module()
+
+ android.AssertBoolEquals(t, "Stub library from API surface should be linked with target version", true, hasDirectDependency(t, ctx, binbaz, libbarApiImportv30))
+ android.AssertBoolEquals(t, "Stub library from API surface should not be linked with different version", false, hasDirectDependency(t, ctx, binbaz, libbarApiImportv29))
+
+ binFooLibFlags := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Rule("ld").Args["libFlags"]
+ android.AssertStringDoesContain(t, "Binary using sdk should be linked with NDK variant source", binFooLibFlags, "libbar_ndk_29.so")
+
+ binFooCFlags := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Rule("cc").Args["cFlags"]
+ android.AssertStringDoesContain(t, "Binary using sdk should include headers from the NDK variant source", binFooCFlags, "-Ilibbar_ndk_29_include")
+}
+
+func TestApiLibraryWithMultipleVariants(t *testing.T) {
+ bp := `
+ cc_binary {
+ name: "binfoo",
+ sdk_version: "29",
+ srcs: ["binfoo.cc"],
+ shared_libs: ["libbar"],
+ stl: "c++_shared",
+ }
+
+ cc_binary {
+ name: "binbaz",
+ vendor: true,
+ srcs: ["binbaz.cc"],
+ shared_libs: ["libbar"],
+ }
+
+ cc_api_library {
+ name: "libbar",
+ // TODO(b/244244438) Remove src property once all variants are implemented.
+ src: "libbar.so",
+ vendor_available: true,
+ variants: [
+ "llndk",
+ "ndk.29",
+ "ndk.30",
+ "ndk.current",
+ ],
+ }
+
+ cc_api_variant {
+ name: "libbar",
+ variant: "ndk",
+ version: "29",
+ src: "libbar_ndk_29.so",
+ export_headers: ["libbar_ndk_29_include"]
+ }
+
+ cc_api_variant {
+ name: "libbar",
+ variant: "ndk",
+ version: "30",
+ src: "libbar_ndk_30.so",
+ export_headers: ["libbar_ndk_30_include"]
+ }
+
+ cc_api_variant {
+ name: "libbar",
+ variant: "ndk",
+ version: "current",
+ src: "libbar_ndk_current.so",
+ export_headers: ["libbar_ndk_current_include"]
+ }
+
+ cc_api_variant {
+ name: "libbar",
+ variant: "llndk",
+ src: "libbar_llndk.so",
+ export_headers: ["libbar_llndk_include"]
+ }
+
+ api_imports {
+ name: "api_imports",
+ shared_libs: [
+ "libbar",
+ ],
+ header_libs: [],
+ }
+ `
+ ctx := prepareForCcTest.RunTestWithBp(t, bp)
+
+ binfoo := ctx.ModuleForTests("binfoo", "android_arm64_armv8-a_sdk").Module()
+ libbarApiImportv29 := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_sdk_shared_29").Module()
+ libbarApiImportLlndk := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
+
+ android.AssertBoolEquals(t, "Binary using SDK should be linked with API library from NDK variant", true, hasDirectDependency(t, ctx, binfoo, libbarApiImportv29))
+ android.AssertBoolEquals(t, "Binary using SDK should not be linked with API library from LLNDK variant", false, hasDirectDependency(t, ctx, binfoo, libbarApiImportLlndk))
+
+ binbaz := ctx.ModuleForTests("binbaz", "android_vendor.29_arm64_armv8-a").Module()
+
+ android.AssertBoolEquals(t, "Vendor binary should be linked with API library from LLNDK variant", true, hasDirectDependency(t, ctx, binbaz, libbarApiImportLlndk))
+ android.AssertBoolEquals(t, "Vendor binary should not be linked with API library from NDK variant", false, hasDirectDependency(t, ctx, binbaz, libbarApiImportv29))
+
+}
diff --git a/cc/library_test.go b/cc/library_test.go
index 6d5eda2..2bc9967 100644
--- a/cc/library_test.go
+++ b/cc/library_test.go
@@ -259,6 +259,7 @@
SystemIncludes: []string{"system_include"},
Headers: []string{"foo.h"},
RootDynamicLibraries: []string{"foo.so"},
+ UnstrippedOutput: "foo_unstripped.so",
},
"//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{
CcObjectFiles: []string{"foo.o"},
@@ -294,6 +295,7 @@
expectedOutputFiles = []string{"outputbase/execroot/__main__/foo.so"}
android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
+ android.AssertStringEquals(t, "unstripped shared library", "outputbase/execroot/__main__/foo_unstripped.so", sharedFoo.(*Module).linker.unstrippedOutputFilePath().String())
flagExporter = ctx.ModuleProvider(sharedFoo, FlagExporterInfoProvider).(FlagExporterInfo)
android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs)
android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs)
diff --git a/cc/linkable.go b/cc/linkable.go
index 2316d86..0522fc6 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -253,6 +253,9 @@
// VndkVersion returns the VNDK version string for this module.
VndkVersion() string
+
+ // Partition returns the partition string for this module.
+ Partition() string
}
var (
diff --git a/cc/lto.go b/cc/lto.go
index 581856b..1afa1dd 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -91,6 +91,11 @@
return flags
}
+ // TODO(b/254713216): LTO doesn't work on riscv64 yet.
+ if ctx.Arch().ArchType == android.Riscv64 {
+ return flags
+ }
+
if lto.LTO(ctx) {
var ltoCFlag string
var ltoLdFlag string
diff --git a/cc/makevars.go b/cc/makevars.go
index de8a8f2..c70d4a6 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -314,8 +314,6 @@
ctx.Strict(makePrefix+"LD", "${config.ClangBin}/lld")
ctx.Strict(makePrefix+"NDK_TRIPLE", config.NDKTriple(toolchain))
ctx.Strict(makePrefix+"TOOLS_PREFIX", "${config.ClangBin}/llvm-")
- // TODO: GCC version is obsolete now that GCC has been removed.
- ctx.Strict(makePrefix+"GCC_VERSION", toolchain.GccVersion())
}
if target.Os.Class == android.Host {
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 08e2a39..7354be9 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -173,7 +173,9 @@
}, attrs)
}
-func (h *headerModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+var _ android.ApiProvider = (*headerModule)(nil)
+
+func (h *headerModule) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
// Generate `cc_api_headers` target for Multi-tree API export
createCcApiHeadersTarget(ctx, h.properties.Srcs, h.properties.Exclude_srcs, h.properties.From)
}
@@ -192,7 +194,6 @@
module := &headerModule{}
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
- android.InitBazelModule(module)
return module
}
@@ -263,7 +264,9 @@
processHeadersWithVersioner(ctx, fromSrcPath, toOutputPath, srcFiles, installPaths)
}
-func (h *versionedHeaderModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+var _ android.ApiProvider = (*versionedHeaderModule)(nil)
+
+func (h *versionedHeaderModule) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
// Glob all .h files under `From`
includePattern := headerGlobPattern(proptools.String(h.properties.From))
// Generate `cc_api_headers` target for Multi-tree API export
@@ -319,7 +322,6 @@
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
- android.InitBazelModule(module)
return module
}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 06ded3f..2473ba2 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -307,6 +307,7 @@
impl, ok := dep.(*Module)
if !ok {
ctx.ModuleErrorf("Implementation for stub is not correct module type")
+ return nil
}
output := impl.UnstrippedOutputFile()
if output == nil {
@@ -395,14 +396,14 @@
}
func (this *stubDecorator) diffAbi(ctx ModuleContext) {
- missingPrebuiltError := fmt.Sprintf(
- "Did not find prebuilt ABI dump for %q. Generate with "+
- "//development/tools/ndk/update_ndk_abi.sh.", this.libraryName(ctx))
-
// Catch any ABI changes compared to the checked-in definition of this API
// level.
abiDiffPath := android.PathForModuleOut(ctx, "abidiff.timestamp")
prebuiltAbiDump := this.findPrebuiltAbiDump(ctx, this.apiLevel)
+ missingPrebuiltError := fmt.Sprintf(
+ "Did not find prebuilt ABI dump for %q (%q). Generate with "+
+ "//development/tools/ndk/update_ndk_abi.sh.", this.libraryName(ctx),
+ prebuiltAbiDump.InvalidReason())
if !prebuiltAbiDump.Valid() {
ctx.Build(pctx, android.BuildParams{
Rule: android.ErrorRule,
@@ -581,12 +582,12 @@
}
// Names of the cc_api_header targets in the bp2build workspace
-func (s *stubDecorator) apiHeaderLabels(ctx android.TopDownMutatorContext) bazel.LabelList {
+func apiHeaderLabels(ctx android.TopDownMutatorContext, hdrLibs []string) bazel.LabelList {
addSuffix := func(ctx android.BazelConversionPathContext, module blueprint.Module) string {
label := android.BazelModuleLabel(ctx, module)
return android.ApiContributionTargetName(label)
}
- return android.BazelLabelForModuleDepsWithFn(ctx, s.properties.Export_header_libs, addSuffix)
+ return android.BazelLabelForModuleDepsWithFn(ctx, hdrLibs, addSuffix)
}
func ndkLibraryBp2build(ctx android.TopDownMutatorContext, m *Module) {
@@ -604,7 +605,7 @@
apiLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(symbolFile)).Label
attrs.Api = *bazel.MakeLabelAttribute(apiLabel)
}
- apiHeaders := stubLibrary.apiHeaderLabels(ctx)
+ apiHeaders := apiHeaderLabels(ctx, stubLibrary.properties.Export_header_libs)
attrs.Hdrs = bazel.MakeLabelListAttribute(apiHeaders)
apiContributionTargetName := android.ApiContributionTargetName(ctx.ModuleName())
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: apiContributionTargetName}, attrs)
diff --git a/cc/ndkstubgen/__init__.py b/cc/ndkstubgen/__init__.py
index f893d41..efad70a 100755
--- a/cc/ndkstubgen/__init__.py
+++ b/cc/ndkstubgen/__init__.py
@@ -111,6 +111,11 @@
action='store_true',
dest='systemapi',
help='Use the SystemAPI variant.')
+ parser.add_argument(
+ '--no-ndk',
+ action='store_false',
+ dest='ndk',
+ help='Do not include NDK APIs.')
parser.add_argument('--api-map',
type=resolved_path,
@@ -147,7 +152,7 @@
verbosity = 2
logging.basicConfig(level=verbose_map[verbosity])
- filt = symbolfile.Filter(args.arch, api, args.llndk, args.apex, args.systemapi)
+ filt = symbolfile.Filter(args.arch, api, args.llndk, args.apex, args.systemapi, args.ndk)
with args.symbol_file.open() as symbol_file:
try:
versions = symbolfile.SymbolFileParser(symbol_file, api_map, filt).parse()
diff --git a/cc/ndkstubgen/test_ndkstubgen.py b/cc/ndkstubgen/test_ndkstubgen.py
index 450719b..1e0bdf3 100755
--- a/cc/ndkstubgen/test_ndkstubgen.py
+++ b/cc/ndkstubgen/test_ndkstubgen.py
@@ -424,6 +424,45 @@
""")
self.assertEqual(expected_version, version_file.getvalue())
+ def test_integration_with_nondk(self) -> None:
+ input_file = io.StringIO(textwrap.dedent("""\
+ VERSION_1 {
+ global:
+ foo;
+ bar; # apex
+ local:
+ *;
+ };
+ """))
+ f = copy(self.filter)
+ f.apex = True
+ f.ndk = False # ndk symbols should be excluded
+ parser = symbolfile.SymbolFileParser(input_file, {}, f)
+ versions = parser.parse()
+
+ src_file = io.StringIO()
+ version_file = io.StringIO()
+ symbol_list_file = io.StringIO()
+ f = copy(self.filter)
+ f.apex = True
+ f.ndk = False # ndk symbols should be excluded
+ generator = ndkstubgen.Generator(src_file,
+ version_file, symbol_list_file, f)
+ generator.write(versions)
+
+ expected_src = textwrap.dedent("""\
+ void bar() {}
+ """)
+ self.assertEqual(expected_src, src_file.getvalue())
+
+ expected_version = textwrap.dedent("""\
+ VERSION_1 {
+ global:
+ bar;
+ };
+ """)
+ self.assertEqual(expected_version, version_file.getvalue())
+
def test_empty_stub(self) -> None:
"""Tests that empty stubs can be generated.
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 867c36c..1842e5a 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -33,7 +33,7 @@
ctx.RegisterModuleType("cc_prebuilt_library_static", PrebuiltStaticLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_test_library_shared", PrebuiltSharedTestLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_object", prebuiltObjectFactory)
- ctx.RegisterModuleType("cc_prebuilt_binary", prebuiltBinaryFactory)
+ ctx.RegisterModuleType("cc_prebuilt_binary", PrebuiltBinaryFactory)
}
type prebuiltLinkerInterface interface {
@@ -358,12 +358,12 @@
// TODO(b/228623543): The below is not entirely true until the bug is fixed. For now, both targets are always generated
// Implements bp2build for cc_prebuilt_library modules. This will generate:
-// - Only a prebuilt_library_static if the shared.enabled property is set to false across all variants.
-// - Only a prebuilt_library_shared if the static.enabled property is set to false across all variants
-// - Both a prebuilt_library_static and prebuilt_library_shared if the aforementioned properties are not false across
+// - Only a cc_prebuilt_library_static if the shared.enabled property is set to false across all variants.
+// - Only a cc_prebuilt_library_shared if the static.enabled property is set to false across all variants
+// - Both a cc_prebuilt_library_static and cc_prebuilt_library_shared if the aforementioned properties are not false across
// all variants
//
-// In all cases, prebuilt_library_static target names will be appended with "_bp2build_cc_library_static".
+// In all cases, cc_prebuilt_library_static target names will be appended with "_bp2build_cc_library_static".
func prebuiltLibraryBp2Build(ctx android.TopDownMutatorContext, module *Module) {
prebuiltLibraryStaticBp2Build(ctx, module, true)
prebuiltLibrarySharedBp2Build(ctx, module)
@@ -380,8 +380,8 @@
}
props := bazel.BazelTargetModuleProperties{
- Rule_class: "prebuilt_library_static",
- Bzl_load_location: "//build/bazel/rules/cc:prebuilt_library_static.bzl",
+ Rule_class: "cc_prebuilt_library_static",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_library_static.bzl",
}
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
@@ -403,8 +403,8 @@
}
props := bazel.BazelTargetModuleProperties{
- Rule_class: "prebuilt_library_shared",
- Bzl_load_location: "//build/bazel/rules/cc:prebuilt_library_shared.bzl",
+ Rule_class: "cc_prebuilt_library_shared",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_library_shared.bzl",
}
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
@@ -668,15 +668,21 @@
}
// cc_prebuilt_binary installs a precompiled executable in srcs property in the
-// device's directory.
-func prebuiltBinaryFactory() android.Module {
+// device's directory, for both the host and device
+func PrebuiltBinaryFactory() android.Module {
module, _ := NewPrebuiltBinary(android.HostAndDeviceSupported)
return module.Init()
}
+type prebuiltBinaryBazelHandler struct {
+ module *Module
+ decorator *binaryDecorator
+}
+
func NewPrebuiltBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
- module, binary := newBinary(hod, false)
+ module, binary := newBinary(hod, true)
module.compiler = nil
+ module.bazelHandler = &prebuiltBinaryBazelHandler{module, binary}
prebuilt := &prebuiltBinaryLinker{
binaryDecorator: binary,
@@ -690,6 +696,53 @@
return module, binary
}
+var _ BazelHandler = (*prebuiltBinaryBazelHandler)(nil)
+
+func (h *prebuiltBinaryBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
+ bazelCtx := ctx.Config().BazelContext
+ bazelCtx.QueueBazelRequest(label, cquery.GetOutputFiles, android.GetConfigKey(ctx))
+}
+
+func (h *prebuiltBinaryBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
+ bazelCtx := ctx.Config().BazelContext
+ outputs, err := bazelCtx.GetOutputFiles(label, android.GetConfigKey(ctx))
+ if err != nil {
+ ctx.ModuleErrorf(err.Error())
+ return
+ }
+ if len(outputs) != 1 {
+ ctx.ModuleErrorf("Expected a single output for `%s`, but got:\n%v", label, outputs)
+ return
+ }
+ out := android.PathForBazelOut(ctx, outputs[0])
+ h.module.outputFile = android.OptionalPathForPath(out)
+ h.module.maybeUnhideFromMake()
+}
+
+type bazelPrebuiltBinaryAttributes struct {
+ Src bazel.LabelAttribute
+ Strip stripAttributes
+}
+
+func prebuiltBinaryBp2Build(ctx android.TopDownMutatorContext, module *Module) {
+ prebuiltAttrs := bp2BuildParsePrebuiltBinaryProps(ctx, module)
+
+ var la linkerAttributes
+ la.convertStripProps(ctx, module)
+ attrs := &bazelPrebuiltBinaryAttributes{
+ Src: prebuiltAttrs.Src,
+ Strip: stripAttrsFromLinkerAttrs(&la),
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_prebuilt_binary",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_binary.bzl",
+ }
+
+ name := android.RemoveOptionalPrebuiltPrefix(module.Name())
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
+}
+
type Sanitized struct {
None struct {
Srcs []string `android:"path,arch_variant"`
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index e959157..95fa99e 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -663,3 +663,47 @@
testFunc(t, disabledSourceStublibBp+prebuiltStublibBp+installedlibBp)
})
}
+
+func TestPrebuiltBinaryNoSrcsNoError(t *testing.T) {
+ const bp = `
+cc_prebuilt_binary {
+ name: "bintest",
+ srcs: [],
+}`
+ ctx := testPrebuilt(t, bp, map[string][]byte{})
+ mod := ctx.ModuleForTests("bintest", "android_arm64_armv8-a").Module().(*Module)
+ android.AssertBoolEquals(t, `expected no srcs to yield no output file`, false, mod.OutputFile().Valid())
+}
+
+func TestPrebuiltBinaryMultipleSrcs(t *testing.T) {
+ const bp = `
+cc_prebuilt_binary {
+ name: "bintest",
+ srcs: ["foo", "bar"],
+}`
+ testCcError(t, `Android.bp:4:6: module "bintest" variant "android_arm64_armv8-a": srcs: multiple prebuilt source files`, bp)
+}
+
+func TestPrebuiltBinaryWithBazel(t *testing.T) {
+ const bp = `
+cc_prebuilt_binary {
+ name: "bintest",
+ srcs: ["bin"],
+ bazel_module: { label: "//bin/foo:foo" },
+}`
+ const outBaseDir = "outputbase"
+ const expectedOut = outBaseDir + "/execroot/__main__/bin"
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
+ config.BazelContext = android.MockBazelContext{
+ OutputBaseDir: outBaseDir,
+ LabelToOutputFiles: map[string][]string{"//bin/foo:foo": []string{"bin"}},
+ }
+ ctx := testCcWithConfig(t, config)
+ bin := ctx.ModuleForTests("bintest", "android_arm64_armv8-a").Module().(*Module)
+ out := bin.OutputFile()
+ if !out.Valid() {
+ t.Error("Invalid output file")
+ return
+ }
+ android.AssertStringEquals(t, "output file", expectedOut, out.String())
+}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 436b149..d3fc221 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -511,6 +511,12 @@
s.Integer_overflow = nil
}
+ // TODO(b/254713216): CFI doesn't work for riscv64 yet because LTO doesn't work.
+ if ctx.Arch().ArchType == android.Riscv64 {
+ s.Cfi = nil
+ s.Diag.Cfi = nil
+ }
+
// Disable CFI for musl
if ctx.toolchain().Musl() {
s.Cfi = nil
@@ -613,6 +619,14 @@
return flags
}
+ // Currently unwinding through tagged frames for exceptions is broken, so disable memtag stack
+ // in that case, so we don't end up tagging those.
+ // TODO(b/174878242): Remove once https://r.android.com/2251926 is included in toolchain.
+ if android.InList("-fexceptions", flags.Local.CFlags) || android.InList("-fexceptions", flags.Global.CFlags) {
+ sanitize.Properties.Sanitize.Memtag_stack = nil
+ _, sanitize.Properties.Sanitizers = android.RemoveFromList("memtag-stack", sanitize.Properties.Sanitizers)
+ }
+
if Bool(sanitize.Properties.Sanitize.Address) {
if ctx.Arch().ArchType == android.Arm {
// Frame pointer based unwinder in ASan requires ARM frame setup.
@@ -881,8 +895,12 @@
switch t {
case Asan:
sanitize.Properties.Sanitize.Address = bPtr
+ // For ASAN variant, we need to disable Memtag_stack
+ sanitize.Properties.Sanitize.Memtag_stack = nil
case Hwasan:
sanitize.Properties.Sanitize.Hwaddress = bPtr
+ // For HWAsan variant, we need to disable Memtag_stack
+ sanitize.Properties.Sanitize.Memtag_stack = nil
case tsan:
sanitize.Properties.Sanitize.Thread = bPtr
case intOverflow:
@@ -895,6 +913,7 @@
sanitize.Properties.Sanitize.Memtag_heap = bPtr
case Memtag_stack:
sanitize.Properties.Sanitize.Memtag_stack = bPtr
+ // We do not need to disable ASAN or HWASan here, as there is no Memtag_stack variant.
case Fuzzer:
sanitize.Properties.Sanitize.Fuzzer = bPtr
default:
@@ -1379,6 +1398,7 @@
// Determine the runtime library required
runtimeLibrary := ""
+ alwaysStaticRuntime := false
var extraStaticDeps []string
toolchain := c.toolchain(mctx)
if Bool(c.sanitize.Properties.Sanitize.Address) {
@@ -1403,8 +1423,15 @@
Bool(c.sanitize.Properties.Sanitize.Undefined) ||
Bool(c.sanitize.Properties.Sanitize.All_undefined) {
runtimeLibrary = config.UndefinedBehaviorSanitizerRuntimeLibrary(toolchain)
- if c.staticBinary() {
+ if c.staticBinary() || toolchain.Musl() {
+ // Use a static runtime for static binaries.
+ // Also use a static runtime for musl to match
+ // what clang does for glibc. Otherwise dlopening
+ // libraries that depend on libclang_rt.ubsan_standalone.so
+ // fails with:
+ // Error relocating ...: initial-exec TLS resolves to dynamic definition
runtimeLibrary += ".static"
+ alwaysStaticRuntime = true
}
}
@@ -1448,7 +1475,7 @@
//
// Note that by adding dependency with {static|shared}DepTag, the lib is
// added to libFlags and LOCAL_SHARED_LIBRARIES by cc.Module
- if c.staticBinary() {
+ if c.staticBinary() || alwaysStaticRuntime {
addStaticDeps(runtimeLibrary)
addStaticDeps(extraStaticDeps...)
} else if !c.static() && !c.Header() {
diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go
index 48ac650..2393f3e 100644
--- a/cc/sanitize_test.go
+++ b/cc/sanitize_test.go
@@ -41,6 +41,7 @@
static_libs: [
"libstatic",
"libnoasan",
+ "libstatic_asan",
],
sanitize: {
address: true,
@@ -57,6 +58,7 @@
static_libs: [
"libstatic",
"libnoasan",
+ "libstatic_asan",
],
}
@@ -92,6 +94,15 @@
address: false,
}
}
+
+ cc_library_static {
+ name: "libstatic_asan",
+ host_supported: true,
+ sanitize: {
+ address: true,
+ }
+ }
+
`
result := android.GroupFixturePreparers(
@@ -125,6 +136,10 @@
// Static library that never uses asan.
libNoAsan := result.ModuleForTests("libnoasan", staticVariant)
+ // Static library that specifies asan
+ libStaticAsan := result.ModuleForTests("libstatic_asan", staticAsanVariant)
+ libStaticAsanNoAsanVariant := result.ModuleForTests("libstatic_asan", staticVariant)
+
// expectSharedLinkDep verifies that the from module links against the to module as a
// shared library.
expectSharedLinkDep := func(from, to android.TestingModule) {
@@ -176,6 +191,7 @@
expectStaticLinkDep(binWithAsan, libStaticAsanVariant)
expectStaticLinkDep(binWithAsan, libNoAsan)
+ expectStaticLinkDep(binWithAsan, libStaticAsan)
expectInstallDep(binWithAsan, libShared)
expectInstallDep(binWithAsan, libAsan)
@@ -190,6 +206,7 @@
expectStaticLinkDep(binNoAsan, libStaticNoAsanVariant)
expectStaticLinkDep(binNoAsan, libNoAsan)
+ expectStaticLinkDep(binNoAsan, libStaticAsanNoAsanVariant)
expectInstallDep(binNoAsan, libShared)
expectInstallDep(binNoAsan, libAsan)
diff --git a/cc/sdk.go b/cc/sdk.go
index a83e5ad..3e50c9f 100644
--- a/cc/sdk.go
+++ b/cc/sdk.go
@@ -31,6 +31,7 @@
switch m := ctx.Module().(type) {
case LinkableInterface:
+ ccModule, isCcModule := ctx.Module().(*Module)
if m.AlwaysSdk() {
if !m.UseSdk() && !m.SplitPerApiLevel() {
ctx.ModuleErrorf("UseSdk() must return true when AlwaysSdk is set, did the factory forget to set Sdk_version?")
@@ -58,11 +59,32 @@
modules[1].(*Module).Properties.PreventInstall = true
}
ctx.AliasVariation("")
+ } else if isCcModule && ccModule.isImportedApiLibrary() {
+ apiLibrary, _ := ccModule.linker.(*apiLibraryDecorator)
+ if apiLibrary.hasNDKStubs() && ccModule.canUseSdk() {
+ // Handle cc_api_library module with NDK stubs and variants only which can use SDK
+ modules := ctx.CreateVariations("", "sdk")
+ modules[1].(*Module).Properties.IsSdkVariant = true
+ if ctx.Config().UnbundledBuildApps() {
+ // For an unbundled apps build, hide the platform variant from Make.
+ modules[0].(*Module).Properties.HideFromMake = true
+ modules[0].(*Module).Properties.PreventInstall = true
+ } else {
+ // For a platform build, mark the SDK variant so that it gets a ".sdk" suffix when
+ // exposed to Make.
+ modules[1].(*Module).Properties.SdkAndPlatformVariantVisibleToMake = true
+ modules[1].(*Module).Properties.PreventInstall = true
+ }
+ } else {
+ ccModule.Properties.Sdk_version = nil
+ ctx.CreateVariations("")
+ ctx.AliasVariation("")
+ }
} else {
- if m, ok := ctx.Module().(*Module); ok {
+ if isCcModule {
// Clear the sdk_version property for modules that don't have an SDK variant so
// later code doesn't get confused by it.
- m.Properties.Sdk_version = nil
+ ccModule.Properties.Sdk_version = nil
}
ctx.CreateVariations("")
ctx.AliasVariation("")
@@ -78,5 +100,12 @@
}
case *snapshotModule:
ctx.CreateVariations("")
+ case *CcApiVariant:
+ ccApiVariant, _ := ctx.Module().(*CcApiVariant)
+ if String(ccApiVariant.properties.Variant) == "ndk" {
+ ctx.CreateVariations("sdk")
+ } else {
+ ctx.CreateVariations("")
+ }
}
}
diff --git a/cc/stl.go b/cc/stl.go
index 85a06da..6353a4a 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -139,6 +139,8 @@
return "libunwind"
}
+// Should be kept up to date with
+// https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/cc/stl.bzl;l=46;drc=21771b671ae08565033768a6d3d151c54f887fa2
func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps {
switch stl.Properties.SelectedStl {
case "libstdc++":
@@ -194,6 +196,8 @@
return deps
}
+// Should be kept up to date with
+// https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/cc/stl.bzl;l=94;drc=5bc8e39d2637927dc57dd0850210d43d348a1341
func (stl *stl) flags(ctx ModuleContext, flags Flags) Flags {
switch stl.Properties.SelectedStl {
case "libc++", "libc++_static":
diff --git a/cc/symbolfile/__init__.py b/cc/symbolfile/__init__.py
index 471a12f..94c8567 100644
--- a/cc/symbolfile/__init__.py
+++ b/cc/symbolfile/__init__.py
@@ -41,6 +41,7 @@
ALL_ARCHITECTURES = (
Arch('arm'),
Arch('arm64'),
+ Arch('riscv64'),
Arch('x86'),
Arch('x86_64'),
)
@@ -208,12 +209,14 @@
symbol should be omitted or not
"""
- def __init__(self, arch: Arch, api: int, llndk: bool = False, apex: bool = False, systemapi: bool = False):
+ def __init__(self, arch: Arch, api: int, llndk: bool = False, apex: bool = False, systemapi:
+ bool = False, ndk: bool = True):
self.arch = arch
self.api = api
self.llndk = llndk
self.apex = apex
self.systemapi = systemapi
+ self.ndk = ndk
def _should_omit_tags(self, tags: Tags) -> bool:
"""Returns True if the tagged object should be omitted.
@@ -253,8 +256,13 @@
def should_omit_symbol(self, symbol: Symbol) -> bool:
"""Returns True if the symbol should be omitted."""
- return self._should_omit_tags(symbol.tags)
+ if not symbol.tags.has_mode_tags and not self.ndk:
+ # Symbols that don't have mode tags are NDK. They are usually
+ # included, but have to be omitted if NDK symbols are explicitly
+ # filtered-out
+ return True
+ return self._should_omit_tags(symbol.tags)
def symbol_in_arch(tags: Tags, arch: Arch) -> bool:
"""Returns true if the symbol is present for the given architecture."""
diff --git a/cc/symbolfile/test_symbolfile.py b/cc/symbolfile/test_symbolfile.py
index e17a8d0..856b9d7 100644
--- a/cc/symbolfile/test_symbolfile.py
+++ b/cc/symbolfile/test_symbolfile.py
@@ -308,6 +308,20 @@
def assertInclude(self, f: Filter, s: Symbol) -> None:
self.assertFalse(f.should_omit_symbol(s))
+ def test_omit_ndk(self) -> None:
+ f_ndk = self.filter
+ f_nondk = copy(f_ndk)
+ f_nondk.ndk = False
+ f_nondk.apex = True
+
+ s_ndk = Symbol('foo', Tags())
+ s_nonndk = Symbol('foo', Tags.from_strs(['apex']))
+
+ self.assertInclude(f_ndk, s_ndk)
+ self.assertOmit(f_ndk, s_nonndk)
+ self.assertOmit(f_nondk, s_ndk)
+ self.assertInclude(f_nondk, s_nonndk)
+
def test_omit_llndk(self) -> None:
f_none = self.filter
f_llndk = copy(f_none)
diff --git a/cc/test.go b/cc/test.go
index 715c537..536210b 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -643,6 +643,8 @@
Gtest bool
Isolated bool
+
+ tidyAttributes
}
// testBinaryBp2build is the bp2build converter for cc_test modules. A cc_test's
@@ -676,6 +678,8 @@
}
}
+ m.convertTidyAttributes(ctx, &testBinaryAttrs.tidyAttributes)
+
for _, propIntf := range m.GetProperties() {
if testLinkerProps, ok := propIntf.(*TestLinkerProperties); ok {
testBinaryAttrs.Gtest = proptools.BoolDefault(testLinkerProps.Gtest, true)
diff --git a/cc/testing.go b/cc/testing.go
index e42b9fa..992069b 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -15,6 +15,7 @@
package cc
import (
+ "encoding/json"
"path/filepath"
"testing"
@@ -736,3 +737,22 @@
t.Errorf("expected %q ExcludeFromRecoverySnapshot to be %t", m.String(), expected)
}
}
+
+func checkOverrides(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, jsonPath string, expected []string) {
+ t.Helper()
+ out := singleton.MaybeOutput(jsonPath)
+ content := android.ContentFromFileRuleForTests(t, out)
+
+ var flags snapshotJsonFlags
+ if err := json.Unmarshal([]byte(content), &flags); err != nil {
+ t.Errorf("Error while unmarshalling json %q: %s", jsonPath, err.Error())
+ return
+ }
+
+ for _, moduleName := range expected {
+ if !android.InList(moduleName, flags.Overrides) {
+ t.Errorf("expected %q to be in %q: %q", moduleName, flags.Overrides, content)
+ return
+ }
+ }
+}
diff --git a/cc/tidy.go b/cc/tidy.go
index 082cf88..bbcaece 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -68,6 +68,7 @@
// Then, that old style usage will be obsolete and an error.
const NoWarningsAsErrorsInTidyFlags = true
+// keep this up to date with https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/cc/clang_tidy.bzl
func (tidy *tidyFeature) flags(ctx ModuleContext, flags Flags) Flags {
CheckBadTidyFlags(ctx, "tidy_flags", tidy.Properties.Tidy_flags)
CheckBadTidyChecks(ctx, "tidy_checks", tidy.Properties.Tidy_checks)
@@ -76,9 +77,13 @@
if tidy.Properties.Tidy != nil && !*tidy.Properties.Tidy {
return flags
}
- // Some projects like external/* and vendor/* have clang-tidy disabled by default.
- // They can enable clang-tidy explicitly with the "tidy:true" property.
- if config.NoClangTidyForDir(ctx.ModuleDir()) && !proptools.Bool(tidy.Properties.Tidy) {
+ // Some projects like external/* and vendor/* have clang-tidy disabled by default,
+ // unless they are enabled explicitly with the "tidy:true" property or
+ // when TIDY_EXTERNAL_VENDOR is set to true.
+ if !proptools.Bool(tidy.Properties.Tidy) &&
+ config.NoClangTidyForDir(
+ ctx.Config().IsEnvTrue("TIDY_EXTERNAL_VENDOR"),
+ ctx.ModuleDir()) {
return flags
}
// If not explicitly disabled, set flags.Tidy to generate .tidy rules.
@@ -131,19 +136,7 @@
flags.TidyFlags = append(flags.TidyFlags, "-extra-arg-before=-fno-caret-diagnostics")
}
- extraArgFlags := []string{
- // We might be using the static analyzer through clang tidy.
- // https://bugs.llvm.org/show_bug.cgi?id=32914
- "-D__clang_analyzer__",
-
- // A recent change in clang-tidy (r328258) enabled destructor inlining, which
- // appears to cause a number of false positives. Until that's resolved, this turns
- // off the effects of r328258.
- // https://bugs.llvm.org/show_bug.cgi?id=37459
- "-Xclang", "-analyzer-config", "-Xclang", "c++-temp-dtor-inlining=false",
- }
-
- for _, f := range extraArgFlags {
+ for _, f := range config.TidyExtraArgFlags() {
flags.TidyFlags = append(flags.TidyFlags, "-extra-arg-before="+f)
}
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 77e6f6f..2dcf26e 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -239,6 +239,9 @@
}
prop.RuntimeLibs = m.SnapshotRuntimeLibs()
prop.Required = m.RequiredModuleNames()
+ if o, ok := m.(overridable); ok {
+ prop.Overrides = o.overriddenModules()
+ }
for _, path := range m.InitRc() {
prop.InitRc = append(prop.InitRc, filepath.Join("configs", path.Base()))
}
diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go
index 2bb43ab..6a98778 100644
--- a/cc/vendor_snapshot_test.go
+++ b/cc/vendor_snapshot_test.go
@@ -42,6 +42,13 @@
}
cc_library {
+ name: "libvendor_override",
+ vendor: true,
+ nocrt: true,
+ overrides: ["libvendor"],
+ }
+
+ cc_library {
name: "libvendor_available",
vendor_available: true,
nocrt: true,
@@ -65,6 +72,13 @@
nocrt: true,
}
+ cc_binary {
+ name: "vendor_bin_override",
+ vendor: true,
+ nocrt: true,
+ overrides: ["vendor_bin"],
+ }
+
cc_prebuilt_library_static {
name: "libb",
vendor_available: true,
@@ -150,6 +164,8 @@
jsonFiles = append(jsonFiles,
filepath.Join(binaryDir, "vendor_bin.json"),
filepath.Join(binaryDir, "vendor_available_bin.json"))
+
+ checkOverrides(t, ctx, snapshotSingleton, filepath.Join(binaryDir, "vendor_bin_override.json"), []string{"vendor_bin"})
}
// For header libraries, all vendor:true and vendor_available modules are captured.
@@ -161,6 +177,8 @@
objectDir := filepath.Join(snapshotVariantPath, archDir, "object")
CheckSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json"))
+
+ checkOverrides(t, ctx, snapshotSingleton, filepath.Join(sharedDir, "libvendor_override.so.json"), []string{"libvendor"})
}
for _, jsonFile := range jsonFiles {
@@ -506,11 +524,13 @@
],
shared_libs: [
"libvendor",
+ "libvendor_override",
"libvendor_available",
"lib64",
],
binaries: [
"bin",
+ "bin_override",
],
},
arm: {
@@ -526,6 +546,7 @@
],
shared_libs: [
"libvendor",
+ "libvendor_override",
"libvendor_available",
"lib32",
],
@@ -577,6 +598,30 @@
},
}
+ vendor_snapshot_shared {
+ name: "libvendor_override",
+ version: "31",
+ target_arch: "arm64",
+ compile_multilib: "both",
+ vendor: true,
+ overrides: ["libvendor"],
+ shared_libs: [
+ "libvendor_without_snapshot",
+ "libvendor_available",
+ "libvndk",
+ ],
+ arch: {
+ arm64: {
+ src: "override/libvendor.so",
+ export_include_dirs: ["include/libvendor"],
+ },
+ arm: {
+ src: "override/libvendor.so",
+ export_include_dirs: ["include/libvendor"],
+ },
+ },
+ }
+
vendor_snapshot_static {
name: "lib32",
version: "31",
@@ -745,6 +790,21 @@
}
vendor_snapshot_binary {
+ name: "bin_override",
+ version: "31",
+ target_arch: "arm64",
+ compile_multilib: "64",
+ vendor: true,
+ overrides: ["bin"],
+ arch: {
+ arm64: {
+ src: "override/bin",
+ },
+ },
+ symlinks: ["binfoo", "binbar"],
+ }
+
+ vendor_snapshot_binary {
name: "bin32",
version: "31",
target_arch: "arm64",
@@ -793,6 +853,7 @@
"framework/symbol.txt": nil,
"vendor/Android.bp": []byte(vendorProprietaryBp),
"vendor/bin": nil,
+ "vendor/override/bin": nil,
"vendor/bin32": nil,
"vendor/bin.cpp": nil,
"vendor/client.cpp": nil,
@@ -806,6 +867,7 @@
"vendor/libvendor.a": nil,
"vendor/libvendor.cfi.a": nil,
"vendor/libvendor.so": nil,
+ "vendor/override/libvendor.so": nil,
"vendor/lib32.a": nil,
"vendor/lib32.so": nil,
"vendor/lib64.a": nil,
@@ -958,6 +1020,23 @@
if inList(binaryVariant, binVariants) {
t.Errorf("bin must not have variant %#v, but it does", sharedVariant)
}
+
+ // test overrides property
+ binOverrideModule := ctx.ModuleForTests("bin_override.vendor_binary.31.arm64", binaryVariant)
+ binOverrideModule.Output("bin")
+ binOverrideMkEntries := android.AndroidMkEntriesForTest(t, ctx, binOverrideModule.Module())
+ binOverrideEntry := binOverrideMkEntries[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
+ if !inList("bin", binOverrideEntry) {
+ t.Errorf("bin_override must override bin but was %q\n", binOverrideEntry)
+ }
+
+ libvendorOverrideModule := ctx.ModuleForTests("libvendor_override.vendor_shared.31.arm64", sharedVariant)
+ libvendorOverrideModule.Output("libvendor.so")
+ libvendorOverrideMkEntries := android.AndroidMkEntriesForTest(t, ctx, libvendorOverrideModule.Module())
+ libvendorOverrideEntry := libvendorOverrideMkEntries[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
+ if !inList("libvendor", libvendorOverrideEntry) {
+ t.Errorf("libvendor_override must override libvendor but was %q\n", libvendorOverrideEntry)
+ }
}
func TestVendorSnapshotSanitizer(t *testing.T) {
diff --git a/cmd/extract_apks/bundle_proto/Android.bp b/cmd/extract_apks/bundle_proto/Android.bp
new file mode 100644
index 0000000..e56c0fb
--- /dev/null
+++ b/cmd/extract_apks/bundle_proto/Android.bp
@@ -0,0 +1,13 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+python_library_host {
+ name: "config_proto",
+ srcs: [
+ "config.proto",
+ ],
+ proto: {
+ canonical_path_from_root: false,
+ },
+}
diff --git a/cmd/extract_apks/bundle_proto/config.proto b/cmd/extract_apks/bundle_proto/config.proto
index d6fac03..946bd9a 100644
--- a/cmd/extract_apks/bundle_proto/config.proto
+++ b/cmd/extract_apks/bundle_proto/config.proto
@@ -26,6 +26,9 @@
ASSET_ONLY = 2;
}
BundleType type = 8;
+
+ // Configuration for locales.
+ Locales locales = 9;
}
message Bundletool {
@@ -40,6 +43,48 @@
// the name of the modules, and using forward slash ("/") as a name separator.
// Examples: "res/raw/**", "assets/**/*.uncompressed", etc.
repeated string uncompressed_glob = 1;
+
+ enum AssetModuleCompression {
+ UNSPECIFIED = 0;
+ // Assets are left uncompressed in the generated asset module.
+ UNCOMPRESSED = 1;
+ // Assets are compressed in the generated asset module.
+ // This option can be overridden at a finer granularity by specifying
+ // files or folders to keep uncompressed in `uncompressed_glob`.
+ // This option should only be used if the app is able to handle compressed
+ // asset module content at runtime (some runtime APIs may misbehave).
+ COMPRESSED = 2;
+ }
+
+ // Default compression strategy for install-time asset modules.
+ // If the compression strategy indicates to compress a file and the same file
+ // matches one of the `uncompressed_glob` values, the `uncompressed_glob`
+ // takes precedence (the file is left uncompressed in the generated APK).
+ //
+ // If unspecified, asset module content is left uncompressed in the
+ // generated asset modules.
+ //
+ // Note: this flag only configures the compression strategy for install-time
+ // asset modules; the content of on-demand and fast-follow asset modules is
+ // always kept uncompressed.
+ AssetModuleCompression install_time_asset_module_default_compression = 2;
+
+ enum ApkCompressionAlgorithm {
+ // Default in the current version of bundletool is zlib deflate algorithm
+ // with compression level 9 for the application's resources and compression
+ // level 6 for other entries.
+ //
+ // This is a good trade-off between size of final APK and size of patches
+ // which are used to update the application from previous to next version.
+ DEFAULT_APK_COMPRESSION_ALGORITHM = 0;
+
+ // 7zip implementation of deflate algorithm which gives smaller APK size
+ // but size of patches required to update the application are larger.
+ P7ZIP = 1;
+ }
+
+ // Compression algorithm which is used to compress entries in final APKs.
+ ApkCompressionAlgorithm apk_compression_algorithm = 3;
}
// Resources to keep in the master split.
@@ -55,12 +100,40 @@
// This is for uncompressing native libraries on M+ devices (L+ devices on
// instant apps).
UncompressNativeLibraries uncompress_native_libraries = 2;
- // This is for uncompressing dex files on P+ devices.
+ // This is for uncompressing dex files.
UncompressDexFiles uncompress_dex_files = 3;
// Configuration for the generation of standalone APKs.
// If no StandaloneConfig is set, the configuration is inherited from
// splits_config.
StandaloneConfig standalone_config = 4;
+
+ // Optimizations that are applied to resources.
+ ResourceOptimizations resource_optimizations = 5;
+
+ // Configuration for archiving the app.
+ StoreArchive store_archive = 6;
+}
+
+message ResourceOptimizations {
+ // Whether to use sparse encoding for resource tables.
+ // Resources in sparse resource table are accessed using a binary search tree.
+ // This decreases APK size at the cost of resource retrieval performance.
+ SparseEncoding sparse_encoding = 1;
+
+ enum SparseEncoding {
+ // Previously 'ENFORCED'. This option is deprecated because of issues found
+ // in Android O up to Android Sv2 and causes segfaults in
+ // Resources#getIdentifier.
+ reserved 1;
+ reserved "ENFORCED";
+
+ // Disables sparse encoding.
+ UNSPECIFIED = 0;
+ // Generates special APKs for Android SDK +32 with sparse resource tables.
+ // Devices with Android SDK below 32 will still receive APKs with regular
+ // resource tables.
+ VARIANT_FOR_SDK_32 = 2;
+ }
}
message UncompressNativeLibraries {
@@ -68,7 +141,39 @@
}
message UncompressDexFiles {
+ // A new variant with uncompressed dex will be generated. The sdk targeting
+ // of the variant is determined by 'uncompressed_dex_target_sdk'.
bool enabled = 1;
+
+ // If 'enabled' field is set, this will determine the sdk targeting of the
+ // generated variant.
+ UncompressedDexTargetSdk uncompressed_dex_target_sdk = 2;
+
+ enum UncompressedDexTargetSdk {
+ // Q+ variant will be generated.
+ UNSPECIFIED = 0;
+ // S+ variant will be generated.
+ SDK_31 = 1;
+ }
+}
+
+message StoreArchive {
+ // Archive is an app state that allows an official app store to reclaim device
+ // storage and disable app functionality temporarily until the user interacts
+ // with the app again. Upon interaction the latest available version of the
+ // app will be restored while leaving user data unaffected.
+ // Enabled by default.
+ bool enabled = 1;
+}
+
+message Locales {
+ // Instructs bundletool to generate locale config and inject it into
+ // AndroidManifest.xml. A locale is marked as supported by the application if
+ // there is at least one resource value in this locale. Be very careful with
+ // this setting because if some of your libraries expose resources in some
+ // locales which are not actually supported by your application it will mark
+ // this locale as supported. Disabled by default.
+ bool inject_locale_config = 1;
}
// Optimization configuration used to generate Split APKs.
@@ -82,8 +187,28 @@
repeated SplitDimension split_dimension = 1;
// Whether 64 bit libraries should be stripped from Standalone APKs.
bool strip_64_bit_libraries = 2;
+ // Dex merging strategy that should be applied to produce Standalone APKs.
+ DexMergingStrategy dex_merging_strategy = 3;
+
+ enum DexMergingStrategy {
+ // Strategy that does dex merging for applications that have minimum SDK
+ // below 21 to ensure dex files from all modules are merged into one or
+ // mainDexList is applied when merging into one dex is not possible. For
+ // applications with minSdk >= 21 dex files from all modules are copied into
+ // standalone APK as is because Android supports multiple dex files natively
+ // starting from Android 5.0.
+ MERGE_IF_NEEDED = 0;
+ // Requires to copy dex files from all modules into standalone APK as is.
+ // If an application supports SDKs below 21 this strategy puts
+ // responsibility of providing dex files compatible with legacy multidex on
+ // application developers.
+ NEVER_MERGE = 1;
+ }
}
+// BEGIN-INTERNAL
+// LINT.IfChange
+// END-INTERNAL
message SplitDimension {
enum Value {
UNSPECIFIED_VALUE = 0;
@@ -92,8 +217,9 @@
LANGUAGE = 3;
TEXTURE_COMPRESSION_FORMAT = 4;
// BEGIN-INTERNAL
- GRAPHICS_API = 5;
+ GRAPHICS_API = 5 [deprecated = true];
// END-INTERNAL
+ DEVICE_TIER = 6;
}
Value value = 1;
@@ -105,11 +231,14 @@
// the targeting is encoded in the directory name (e.g: assets/foo#tcf_etc1)
SuffixStripping suffix_stripping = 3;
}
+// BEGIN-INTERNAL
+// LINT.ThenChange(//depot/google3/wireless/android/vending/developer/proto/storage/app/apk_bundle.proto)
+// END-INTERNAL
message SuffixStripping {
// If set to 'true', indicates that the targeting suffix should be removed
- // from assets paths for this dimension when splits (or asset slices) are
- // generated.
+ // from assets paths for this dimension when splits (e.g: "asset packs") or
+ // standalone/universal APKs are generated.
// This only applies to assets.
// For example a folder with path "assets/level1_textures#tcf_etc1"
// would be outputted to "assets/level1_textures". File contents are
@@ -117,9 +246,9 @@
bool enabled = 1;
// The default suffix to be used for the cases where separate slices can't
- // be generated for this dimension. In the case of standalone/universal APKs
- // generation, stripping the suffix can lead to file name collisions. This
- // default suffix defines the directories to retain. The others are
+ // be generated for this dimension - typically for standalone or universal
+ // APKs.
+ // This default suffix defines the directories to retain. The others are
// discarded: standalone/universal APKs will contain only directories
// targeted at this value for the dimension.
//
@@ -135,6 +264,15 @@
message ApexConfig {
// Configuration for processing of APKs embedded in an APEX image.
repeated ApexEmbeddedApkConfig apex_embedded_apk_config = 1;
+
+ // Explicit list of supported ABIs.
+ // Default: See ApexBundleValidator.REQUIRED_ONE_OF_ABI_SETS
+ repeated SupportedAbiSet supported_abi_set = 2;
+}
+
+// Represents a set of ABIs which must be supported by a single APEX image.
+message SupportedAbiSet {
+ repeated string abi = 1;
}
message ApexEmbeddedApkConfig {
diff --git a/cmd/extract_apks/main.go b/cmd/extract_apks/main.go
index c420567..82db634 100644
--- a/cmd/extract_apks/main.go
+++ b/cmd/extract_apks/main.go
@@ -132,21 +132,21 @@
*android_bundle_proto.ApkDescription
}
-func (m apkDescriptionMatcher) matches(config TargetConfig) bool {
- return m.ApkDescription == nil || (apkTargetingMatcher{m.Targeting}).matches(config)
+func (m apkDescriptionMatcher) matches(config TargetConfig, allAbisMustMatch bool) bool {
+ return m.ApkDescription == nil || (apkTargetingMatcher{m.Targeting}).matches(config, allAbisMustMatch)
}
type apkTargetingMatcher struct {
*android_bundle_proto.ApkTargeting
}
-func (m apkTargetingMatcher) matches(config TargetConfig) bool {
+func (m apkTargetingMatcher) matches(config TargetConfig, allAbisMustMatch bool) bool {
return m.ApkTargeting == nil ||
(abiTargetingMatcher{m.AbiTargeting}.matches(config) &&
languageTargetingMatcher{m.LanguageTargeting}.matches(config) &&
screenDensityTargetingMatcher{m.ScreenDensityTargeting}.matches(config) &&
sdkVersionTargetingMatcher{m.SdkVersionTargeting}.matches(config) &&
- multiAbiTargetingMatcher{m.MultiAbiTargeting}.matches(config))
+ multiAbiTargetingMatcher{m.MultiAbiTargeting}.matches(config, allAbisMustMatch))
}
type languageTargetingMatcher struct {
@@ -215,33 +215,27 @@
}
}
- m = append(multiAbiValue{}, m...)
- sort.Slice(m, sortAbis(m))
- other = append(multiAbiValue{}, other...)
- sort.Slice(other, sortAbis(other))
+ sortedM := append(multiAbiValue{}, m...)
+ sort.Slice(sortedM, sortAbis(sortedM))
+ sortedOther := append(multiAbiValue{}, other...)
+ sort.Slice(sortedOther, sortAbis(sortedOther))
- for i := 0; i < min(len(m), len(other)); i++ {
- if multiAbiPriorities[m[i].Alias] > multiAbiPriorities[other[i].Alias] {
+ for i := 0; i < min(len(sortedM), len(sortedOther)); i++ {
+ if multiAbiPriorities[sortedM[i].Alias] > multiAbiPriorities[sortedOther[i].Alias] {
return 1
}
- if multiAbiPriorities[m[i].Alias] < multiAbiPriorities[other[i].Alias] {
+ if multiAbiPriorities[sortedM[i].Alias] < multiAbiPriorities[sortedOther[i].Alias] {
return -1
}
}
- if len(m) == len(other) {
- return 0
- }
- if len(m) > len(other) {
- return 1
- }
- return -1
+ return len(sortedM) - len(sortedOther)
}
// this logic should match the logic in bundletool at
// https://github.com/google/bundletool/blob/ae0fc0162fd80d92ef8f4ef4527c066f0106942f/src/main/java/com/android/tools/build/bundletool/device/MultiAbiMatcher.java#L43
// (note link is the commit at time of writing; but logic should always match the latest)
-func (t multiAbiTargetingMatcher) matches(config TargetConfig) bool {
+func (t multiAbiTargetingMatcher) matches(config TargetConfig, allAbisMustMatch bool) bool {
if t.MultiAbiTargeting == nil {
return true
}
@@ -250,12 +244,19 @@
}
multiAbiIsValid := func(m multiAbiValue) bool {
+ numValid := 0
for _, abi := range m {
- if _, ok := config.abis[abi.Alias]; !ok {
- return false
+ if _, ok := config.abis[abi.Alias]; ok {
+ numValid += 1
}
}
- return true
+ if numValid == 0 {
+ return false
+ } else if numValid > 0 && !allAbisMustMatch {
+ return true
+ } else {
+ return numValid == len(m)
+ }
}
// ensure that the current value is valid for our config
@@ -264,6 +265,7 @@
for _, multiAbi := range multiAbiSet {
if multiAbiIsValid(multiAbi.GetAbi()) {
valueSetContainsViableAbi = true
+ break
}
}
@@ -362,13 +364,13 @@
*android_bundle_proto.VariantTargeting
}
-func (m variantTargetingMatcher) matches(config TargetConfig) bool {
+func (m variantTargetingMatcher) matches(config TargetConfig, allAbisMustMatch bool) bool {
if m.VariantTargeting == nil {
return true
}
return sdkVersionTargetingMatcher{m.SdkVersionTargeting}.matches(config) &&
abiTargetingMatcher{m.AbiTargeting}.matches(config) &&
- multiAbiTargetingMatcher{m.MultiAbiTargeting}.matches(config) &&
+ multiAbiTargetingMatcher{m.MultiAbiTargeting}.matches(config, allAbisMustMatch) &&
screenDensityTargetingMatcher{m.ScreenDensityTargeting}.matches(config) &&
textureCompressionFormatTargetingMatcher{m.TextureCompressionFormatTargeting}.matches(config)
}
@@ -380,30 +382,42 @@
// Return all entries matching target configuration
func selectApks(toc Toc, targetConfig TargetConfig) SelectionResult {
- var result SelectionResult
- for _, variant := range (*toc).GetVariant() {
- if !(variantTargetingMatcher{variant.GetTargeting()}.matches(targetConfig)) {
- continue
- }
- for _, as := range variant.GetApkSet() {
- if !(moduleMetadataMatcher{as.ModuleMetadata}.matches(targetConfig)) {
+ checkMatching := func(allAbisMustMatch bool) SelectionResult {
+ var result SelectionResult
+ for _, variant := range (*toc).GetVariant() {
+ if !(variantTargetingMatcher{variant.GetTargeting()}.matches(targetConfig, allAbisMustMatch)) {
continue
}
- for _, apkdesc := range as.GetApkDescription() {
- if (apkDescriptionMatcher{apkdesc}).matches(targetConfig) {
- result.entries = append(result.entries, apkdesc.GetPath())
- // TODO(asmundak): As it turns out, moduleName which we get from
- // the ModuleMetadata matches the module names of the generated
- // entry paths just by coincidence, only for the split APKs. We
- // need to discuss this with bundletool folks.
- result.moduleName = as.GetModuleMetadata().GetName()
+ for _, as := range variant.GetApkSet() {
+ if !(moduleMetadataMatcher{as.ModuleMetadata}.matches(targetConfig)) {
+ continue
+ }
+ for _, apkdesc := range as.GetApkDescription() {
+ if (apkDescriptionMatcher{apkdesc}).matches(targetConfig, allAbisMustMatch) {
+ result.entries = append(result.entries, apkdesc.GetPath())
+ // TODO(asmundak): As it turns out, moduleName which we get from
+ // the ModuleMetadata matches the module names of the generated
+ // entry paths just by coincidence, only for the split APKs. We
+ // need to discuss this with bundletool folks.
+ result.moduleName = as.GetModuleMetadata().GetName()
+ }
+ }
+ // we allow only a single module, so bail out here if we found one
+ if result.moduleName != "" {
+ return result
}
}
- // we allow only a single module, so bail out here if we found one
- if result.moduleName != "" {
- return result
- }
}
+ return result
+ }
+ result := checkMatching(true)
+ if result.moduleName == "" {
+ // if there are no matches where all of the ABIs are available in the
+ // TargetConfig, then search again with a looser requirement of at
+ // least one matching ABI
+ // NOTE(b/260130686): this logic diverges from the logic in bundletool
+ // https://github.com/google/bundletool/blob/ae0fc0162fd80d92ef8f4ef4527c066f0106942f/src/main/java/com/android/tools/build/bundletool/device/MultiAbiMatcher.java#L43
+ result = checkMatching(false)
}
return result
}
diff --git a/cmd/extract_apks/main_test.go b/cmd/extract_apks/main_test.go
index c1d712d..9f52877 100644
--- a/cmd/extract_apks/main_test.go
+++ b/cmd/extract_apks/main_test.go
@@ -744,7 +744,11 @@
bp.Abi_X86_64: 0,
},
},
- expected: SelectionResult{},
+ expected: SelectionResult{
+ "base",
+ []string{
+ "standalones/standalone-x86.x86_64.apex",
+ }},
},
{
name: "multi-variant multi-target cross-target",
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index 7cb8ab7..d8d5e5d 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -48,6 +48,10 @@
var outDir = flag.String("out", "", "path to store output directories (defaults to tmpdir under $OUT when empty)")
var alternateResultDir = flag.Bool("dist", false, "write select results to $DIST_DIR (or <out>/dist when empty)")
+var bazelMode = flag.Bool("bazel-mode", false, "use bazel for analysis of certain modules")
+var bazelModeStaging = flag.Bool("bazel-mode-staging", false, "use bazel for analysis of certain near-ready modules")
+var bazelModeDev = flag.Bool("bazel-mode-dev", false, "use bazel for analysis of a large number of modules (less stable)")
+
var onlyConfig = flag.Bool("only-config", false, "Only run product config (not Soong or Kati)")
var onlySoong = flag.Bool("only-soong", false, "Only run product config and Soong (not Kati)")
@@ -214,6 +218,31 @@
return value == "1" || value == "y" || value == "yes" || value == "on" || value == "true"
}
+func getBazelArg() string {
+ count := 0
+ str := ""
+ if *bazelMode {
+ count++
+ str = "--bazel-mode"
+ }
+ if *bazelModeStaging {
+ count++
+ str = "--bazel-mode-staging"
+ }
+ if *bazelModeDev {
+ count++
+ str = "--bazel-mode-dev"
+ }
+
+ if count > 1 {
+ // Can't set more than one
+ fmt.Errorf("Only one bazel mode is permitted to be set.")
+ os.Exit(1)
+ }
+
+ return str
+}
+
func main() {
stdio := terminal.StdioImpl{}
@@ -472,6 +501,11 @@
args = append(args, "--soong-only")
}
+ bazelStr := getBazelArg()
+ if bazelStr != "" {
+ args = append(args, bazelStr)
+ }
+
cmd := exec.Command(mpctx.SoongUi, args...)
cmd.Stdout = consoleLogWriter
cmd.Stderr = consoleLogWriter
diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go
index d4a57bf..ba0648d 100644
--- a/cmd/pom2bp/pom2bp.go
+++ b/cmd/pom2bp/pom2bp.go
@@ -150,6 +150,7 @@
var defaultMinSdkVersion string
var useVersion string
var staticDeps bool
+var writeCmd bool
var jetifier bool
func InList(s string, list []string) bool {
@@ -206,6 +207,10 @@
return p.Packaging == "jar"
}
+func (p Pom) IsApk() bool {
+ return p.Packaging == "apk"
+}
+
func (p Pom) IsHostModule() bool {
return hostModuleNames.IsHostModule(p.GroupId, p.ArtifactId)
}
@@ -243,6 +248,8 @@
func (p Pom) ImportModuleType() string {
if p.IsAar() {
return "android_library_import"
+ } else if p.IsApk() {
+ return "android_app_import"
} else if p.IsHostOnly() {
return "java_import_host"
} else {
@@ -253,6 +260,8 @@
func (p Pom) BazelImportTargetType() string {
if p.IsAar() {
return "aar_import"
+ } else if p.IsApk() {
+ return "apk_import"
} else {
return "java_import"
}
@@ -261,6 +270,8 @@
func (p Pom) ImportProperty() string {
if p.IsAar() {
return "aars"
+ } else if p.IsApk() {
+ return "apk"
} else {
return "jars"
}
@@ -269,6 +280,8 @@
func (p Pom) BazelImportProperty() string {
if p.IsAar() {
return "aar"
+ } else if p.IsApk() {
+ return "apk"
} else {
return "jars"
}
@@ -492,8 +505,12 @@
var bpTemplate = template.Must(template.New("bp").Parse(`
{{.ImportModuleType}} {
name: "{{.BpName}}",
+ {{- if .IsApk}}
+ {{.ImportProperty}}: "{{.ArtifactFile}}",
+ {{- else}}
{{.ImportProperty}}: ["{{.ArtifactFile}}"],
sdk_version: "{{.SdkVersion}}",
+ {{- end}}
{{- if .Jetifier}}
jetifier: true,
{{- end}}
@@ -534,8 +551,14 @@
],
{{- end}}
{{- else if not .IsHostOnly}}
+ {{- if not .IsApk}}
min_sdk_version: "{{.DefaultMinSdkVersion}}",
{{- end}}
+ {{- end}}
+ {{- if .IsApk}}
+ presigned: true
+ {{- end}}
+
}
`))
@@ -810,6 +833,9 @@
-use-version <version>
If the maven directory contains multiple versions of artifacts and their pom files,
-use-version can be used to only write Android.bp files for a specific version of those artifacts.
+ -write-cmd
+ Whether to write the command line arguments used to generate the build file as a comment at
+ the top of the build file itself.
-jetifier
Sets jetifier: true for all modules.
<dir>
@@ -837,6 +863,7 @@
flag.StringVar(&defaultMinSdkVersion, "default-min-sdk-version", "24", "Default min_sdk_version to use, if one is not available from AndroidManifest.xml. Default: 24")
flag.StringVar(&useVersion, "use-version", "", "Only read artifacts of a specific version")
flag.BoolVar(&staticDeps, "static-deps", false, "Statically include direct dependencies")
+ flag.BoolVar(&writeCmd, "write-cmd", true, "Write command line arguments as a comment")
flag.BoolVar(&jetifier, "jetifier", false, "Sets jetifier: true on all modules")
flag.StringVar(®en, "regen", "", "Rewrite specified file")
flag.BoolVar(&pom2build, "pom2build", false, "If true, will generate a Bazel BUILD file *instead* of a .bp file")
@@ -964,8 +991,13 @@
if pom2build {
commentString = "#"
}
- fmt.Fprintln(buf, commentString, "Automatically generated with:")
- fmt.Fprintln(buf, commentString, "pom2bp", strings.Join(proptools.ShellEscapeList(os.Args[1:]), " "))
+
+ fmt.Fprintln(buf, commentString, "This is a generated file. Do not modify directly.")
+
+ if writeCmd {
+ fmt.Fprintln(buf, commentString, "Automatically generated with:")
+ fmt.Fprintln(buf, commentString, "pom2bp", strings.Join(proptools.ShellEscapeList(os.Args[1:]), " "))
+ }
if prepend != "" {
contents, err := ioutil.ReadFile(prepend)
@@ -985,7 +1017,7 @@
for _, pom := range poms {
var err error
- if staticDeps {
+ if staticDeps && !pom.IsApk() {
err = depsTemplate.Execute(buf, pom)
} else {
err = template.Execute(buf, pom)
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 0b8cc88..3bc311b 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -15,6 +15,7 @@
package main
import (
+ "bytes"
"flag"
"fmt"
"io/ioutil"
@@ -24,6 +25,7 @@
"time"
"android/soong/android"
+ "android/soong/bazel"
"android/soong/bp2build"
"android/soong/shared"
"android/soong/ui/metrics/bp2build_metrics_proto"
@@ -48,11 +50,13 @@
delveListen string
delvePath string
- moduleGraphFile string
- moduleActionsFile string
- docFile string
- bazelQueryViewDir string
- bp2buildMarker string
+ moduleGraphFile string
+ moduleActionsFile string
+ docFile string
+ bazelQueryViewDir string
+ bazelApiBp2buildDir string
+ bp2buildMarker string
+ symlinkForestMarker string
cmdlineArgs bootstrap.Args
)
@@ -81,10 +85,13 @@
flag.StringVar(&moduleActionsFile, "module_actions_file", "", "JSON file to output inputs/outputs of actions of modules")
flag.StringVar(&docFile, "soong_docs", "", "build documentation file to output")
flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory relative to --top")
+ flag.StringVar(&bazelApiBp2buildDir, "bazel_api_bp2build_dir", "", "path to the bazel api_bp2build directory relative to --top")
flag.StringVar(&bp2buildMarker, "bp2build_marker", "", "If set, run bp2build, touch the specified marker file then exit")
+ flag.StringVar(&symlinkForestMarker, "symlink_forest_marker", "", "If set, create the bp2build symlink forest, touch the specified marker file, then exit")
flag.StringVar(&cmdlineArgs.OutFile, "o", "build.ninja", "the Ninja file to output")
flag.BoolVar(&cmdlineArgs.EmptyNinjaFile, "empty-ninja-file", false, "write out a 0-byte ninja file")
flag.BoolVar(&cmdlineArgs.BazelMode, "bazel-mode", false, "use bazel for analysis of certain modules")
+ flag.BoolVar(&cmdlineArgs.BazelModeStaging, "bazel-mode-staging", false, "use bazel for analysis of certain near-ready modules")
flag.BoolVar(&cmdlineArgs.BazelModeDev, "bazel-mode-dev", false, "use bazel for analysis of a large number of modules (less stable)")
// Flags that probably shouldn't be flags of soong_build but we haven't found
@@ -99,24 +106,11 @@
}
func newNameResolver(config android.Config) *android.NameResolver {
- namespacePathsToExport := make(map[string]bool)
-
- for _, namespaceName := range config.ExportedNamespaces() {
- namespacePathsToExport[namespaceName] = true
- }
-
- namespacePathsToExport["."] = true // always export the root namespace
-
- exportFilter := func(namespace *android.Namespace) bool {
- return namespacePathsToExport[namespace.Path]
- }
-
- return android.NewNameResolver(exportFilter)
+ return android.NewNameResolver(config)
}
func newContext(configuration android.Config) *android.Context {
ctx := android.NewContext(configuration)
- ctx.Register()
ctx.SetNameInterface(newNameResolver(configuration))
ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
return ctx
@@ -125,10 +119,14 @@
func newConfig(availableEnv map[string]string) android.Config {
var buildMode android.SoongBuildMode
- if bp2buildMarker != "" {
+ if symlinkForestMarker != "" {
+ buildMode = android.SymlinkForest
+ } else if bp2buildMarker != "" {
buildMode = android.Bp2build
} else if bazelQueryViewDir != "" {
buildMode = android.GenerateQueryView
+ } else if bazelApiBp2buildDir != "" {
+ buildMode = android.ApiBp2build
} else if moduleGraphFile != "" {
buildMode = android.GenerateModuleGraph
} else if docFile != "" {
@@ -137,6 +135,8 @@
buildMode = android.BazelDevMode
} else if cmdlineArgs.BazelMode {
buildMode = android.BazelProdMode
+ } else if cmdlineArgs.BazelModeStaging {
+ buildMode = android.BazelStagingMode
} else {
buildMode = android.AnalysisNoBazel
}
@@ -152,33 +152,37 @@
// Bazel-enabled mode. Attaches a mutator to queue Bazel requests, adds a
// BeforePrepareBuildActionsHook to invoke Bazel, and then uses Bazel metadata
// for modules that should be handled by Bazel.
-func runMixedModeBuild(configuration android.Config, ctx *android.Context, extraNinjaDeps []string) {
+func runMixedModeBuild(configuration android.Config, ctx *android.Context, extraNinjaDeps []string) string {
ctx.EventHandler.Begin("mixed_build")
defer ctx.EventHandler.End("mixed_build")
bazelHook := func() error {
- ctx.EventHandler.Begin("bazel")
- defer ctx.EventHandler.End("bazel")
- return configuration.BazelContext.InvokeBazel(configuration)
+ return configuration.BazelContext.InvokeBazel(configuration, ctx)
}
ctx.SetBeforePrepareBuildActionsHook(bazelHook)
-
ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs, bootstrap.DoEverything, ctx.Context, configuration)
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
+ bazelPaths, err := readBazelPaths(configuration)
+ if err != nil {
+ panic("Bazel deps file not found: " + err.Error())
+ }
+ ninjaDeps = append(ninjaDeps, bazelPaths...)
+
globListFiles := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration)
ninjaDeps = append(ninjaDeps, globListFiles...)
- writeDepFile(cmdlineArgs.OutFile, *ctx.EventHandler, ninjaDeps)
+ writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps)
+ return cmdlineArgs.OutFile
}
// Run the code-generation phase to convert BazelTargetModules to BUILD files.
func runQueryView(queryviewDir, queryviewMarker string, configuration android.Config, ctx *android.Context) {
ctx.EventHandler.Begin("queryview")
defer ctx.EventHandler.End("queryview")
- codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.QueryView)
+ codegenContext := bp2build.NewCodegenContext(configuration, ctx, bp2build.QueryView)
absoluteQueryViewDir := shared.JoinPath(topDir, queryviewDir)
- if err := createBazelQueryView(codegenContext, absoluteQueryViewDir); err != nil {
+ if err := createBazelWorkspace(codegenContext, absoluteQueryViewDir); err != nil {
fmt.Fprintf(os.Stderr, "%s", err)
os.Exit(1)
}
@@ -186,7 +190,101 @@
touch(shared.JoinPath(topDir, queryviewMarker))
}
-func writeMetrics(configuration android.Config, eventHandler metrics.EventHandler, metricsDir string) {
+// Run the code-generation phase to convert API contributions to BUILD files.
+// Return marker file for the new synthetic workspace
+func runApiBp2build(configuration android.Config, ctx *android.Context, extraNinjaDeps []string) string {
+ ctx.EventHandler.Begin("api_bp2build")
+ defer ctx.EventHandler.End("api_bp2build")
+ // Do not allow missing dependencies.
+ ctx.SetAllowMissingDependencies(false)
+ ctx.RegisterForApiBazelConversion()
+
+ // Register the Android.bp files in the tree
+ // Add them to the workspace's .d file
+ ctx.SetModuleListFile(cmdlineArgs.ModuleListFile)
+ if paths, err := ctx.ListModulePaths("."); err == nil {
+ extraNinjaDeps = append(extraNinjaDeps, paths...)
+ } else {
+ panic(err)
+ }
+
+ // Run the loading and analysis phase
+ ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs,
+ bootstrap.StopBeforePrepareBuildActions,
+ ctx.Context,
+ configuration)
+ ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
+
+ // Add the globbed dependencies
+ globs := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration)
+ ninjaDeps = append(ninjaDeps, globs...)
+
+ // Run codegen to generate BUILD files
+ codegenContext := bp2build.NewCodegenContext(configuration, ctx, bp2build.ApiBp2build)
+ absoluteApiBp2buildDir := shared.JoinPath(topDir, bazelApiBp2buildDir)
+ if err := createBazelWorkspace(codegenContext, absoluteApiBp2buildDir); err != nil {
+ fmt.Fprintf(os.Stderr, "%s", err)
+ os.Exit(1)
+ }
+ ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
+
+ // Create soong_injection repository
+ soongInjectionFiles := bp2build.CreateSoongInjectionFiles(configuration, bp2build.CreateCodegenMetrics())
+ absoluteSoongInjectionDir := shared.JoinPath(topDir, configuration.SoongOutDir(), bazel.SoongInjectionDirName)
+ for _, file := range soongInjectionFiles {
+ writeReadOnlyFile(absoluteSoongInjectionDir, file)
+ }
+
+ workspace := shared.JoinPath(configuration.SoongOutDir(), "api_bp2build")
+
+ excludes := bazelArtifacts()
+ // Exclude all src BUILD files
+ excludes = append(excludes, apiBuildFileExcludes()...)
+
+ // Android.bp files for api surfaces are mounted to out/, but out/ should not be a
+ // dep for api_bp2build.
+ // Otherwise api_bp2build will be run every single time
+ excludes = append(excludes, configuration.OutDir())
+
+ // Create the symlink forest
+ symlinkDeps := bp2build.PlantSymlinkForest(
+ configuration.IsEnvTrue("BP2BUILD_VERBOSE"),
+ topDir,
+ workspace,
+ bazelApiBp2buildDir,
+ excludes)
+ ninjaDeps = append(ninjaDeps, symlinkDeps...)
+
+ workspaceMarkerFile := workspace + ".marker"
+ writeDepFile(workspaceMarkerFile, ctx.EventHandler, ninjaDeps)
+ touch(shared.JoinPath(topDir, workspaceMarkerFile))
+ return workspaceMarkerFile
+}
+
+// With some exceptions, api_bp2build does not have any dependencies on the checked-in BUILD files
+// Exclude them from the generated workspace to prevent unrelated errors during the loading phase
+func apiBuildFileExcludes() []string {
+ ret := make([]string, 0)
+
+ srcs, err := getExistingBazelRelatedFiles(topDir)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error determining existing Bazel-related files: %s\n", err)
+ os.Exit(1)
+ }
+ for _, src := range srcs {
+ if src != "WORKSPACE" &&
+ src != "BUILD" &&
+ src != "BUILD.bazel" &&
+ !strings.HasPrefix(src, "build/bazel") &&
+ !strings.HasPrefix(src, "external/bazel-skylib") &&
+ !strings.HasPrefix(src, "prebuilts/clang") {
+ ret = append(ret, src)
+ }
+ }
+ return ret
+}
+
+func writeMetrics(configuration android.Config, eventHandler *metrics.EventHandler, metricsDir string) {
if len(metricsDir) < 1 {
fmt.Fprintf(os.Stderr, "\nMissing required env var for generating soong metrics: LOG_DIR\n")
os.Exit(1)
@@ -226,7 +324,7 @@
return bootstrap.GlobFileListFiles(globDir)
}
-func writeDepFile(outputFile string, eventHandler metrics.EventHandler, ninjaDeps []string) {
+func writeDepFile(outputFile string, eventHandler *metrics.EventHandler, ninjaDeps []string) {
eventHandler.Begin("ninja_deps")
defer eventHandler.End("ninja_deps")
depFile := shared.JoinPath(topDir, outputFile+".d")
@@ -240,58 +338,79 @@
// doChosenActivity runs Soong for a specific activity, like bp2build, queryview
// or the actual Soong build for the build.ninja file. Returns the top level
// output file of the specific activity.
-func doChosenActivity(ctx *android.Context, configuration android.Config, extraNinjaDeps []string) string {
- if configuration.BuildMode == android.Bp2build {
+func doChosenActivity(ctx *android.Context, configuration android.Config, extraNinjaDeps []string, metricsDir string) string {
+ if configuration.BuildMode == android.SymlinkForest {
+ return runSymlinkForestCreation(configuration, ctx, extraNinjaDeps, metricsDir)
+ } else if configuration.BuildMode == android.Bp2build {
// Run the alternate pipeline of bp2build mutators and singleton to convert
// Blueprint to BUILD files before everything else.
- runBp2Build(configuration, extraNinjaDeps)
- return bp2buildMarker
- } else if configuration.IsMixedBuildsEnabled() {
- runMixedModeBuild(configuration, ctx, extraNinjaDeps)
+ return runBp2Build(configuration, ctx, extraNinjaDeps, metricsDir)
+ } else if configuration.BuildMode == android.ApiBp2build {
+ outputFile := runApiBp2build(configuration, ctx, extraNinjaDeps)
+ writeMetrics(configuration, ctx.EventHandler, metricsDir)
+ return outputFile
} else {
- var stopBefore bootstrap.StopBefore
- if configuration.BuildMode == android.GenerateModuleGraph {
- stopBefore = bootstrap.StopBeforeWriteNinja
- } else if configuration.BuildMode == android.GenerateQueryView || configuration.BuildMode == android.GenerateDocFile {
- stopBefore = bootstrap.StopBeforePrepareBuildActions
+ ctx.Register()
+
+ var outputFile string
+ if configuration.IsMixedBuildsEnabled() {
+ outputFile = runMixedModeBuild(configuration, ctx, extraNinjaDeps)
} else {
- stopBefore = bootstrap.DoEverything
+ outputFile = runSoongOnlyBuild(configuration, ctx, extraNinjaDeps)
}
- ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs, stopBefore, ctx.Context, configuration)
- ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
+ writeMetrics(configuration, ctx.EventHandler, metricsDir)
- globListFiles := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration)
- ninjaDeps = append(ninjaDeps, globListFiles...)
+ return outputFile
+ }
+}
- // Convert the Soong module graph into Bazel BUILD files.
- if configuration.BuildMode == android.GenerateQueryView {
- queryviewMarkerFile := bazelQueryViewDir + ".marker"
- runQueryView(bazelQueryViewDir, queryviewMarkerFile, configuration, ctx)
- writeDepFile(queryviewMarkerFile, *ctx.EventHandler, ninjaDeps)
- return queryviewMarkerFile
- } else if configuration.BuildMode == android.GenerateModuleGraph {
- writeJsonModuleGraphAndActions(ctx, moduleGraphFile, moduleActionsFile)
- writeDepFile(moduleGraphFile, *ctx.EventHandler, ninjaDeps)
- return moduleGraphFile
- } else if configuration.BuildMode == android.GenerateDocFile {
- // TODO: we could make writeDocs() return the list of documentation files
- // written and add them to the .d file. Then soong_docs would be re-run
- // whenever one is deleted.
- if err := writeDocs(ctx, shared.JoinPath(topDir, docFile)); err != nil {
- fmt.Fprintf(os.Stderr, "error building Soong documentation: %s\n", err)
- os.Exit(1)
- }
- writeDepFile(docFile, *ctx.EventHandler, ninjaDeps)
- return docFile
- } else {
- // The actual output (build.ninja) was written in the RunBlueprint() call
- // above
- writeDepFile(cmdlineArgs.OutFile, *ctx.EventHandler, ninjaDeps)
- }
+// runSoongOnlyBuild runs the standard Soong build in a number of different modes.
+func runSoongOnlyBuild(configuration android.Config, ctx *android.Context, extraNinjaDeps []string) string {
+ ctx.EventHandler.Begin("soong_build")
+ defer ctx.EventHandler.End("soong_build")
+
+ var stopBefore bootstrap.StopBefore
+ if configuration.BuildMode == android.GenerateModuleGraph {
+ stopBefore = bootstrap.StopBeforeWriteNinja
+ } else if configuration.BuildMode == android.GenerateQueryView || configuration.BuildMode == android.GenerateDocFile {
+ stopBefore = bootstrap.StopBeforePrepareBuildActions
+ } else {
+ stopBefore = bootstrap.DoEverything
}
- return cmdlineArgs.OutFile
+ ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs, stopBefore, ctx.Context, configuration)
+ ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
+
+ globListFiles := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration)
+ ninjaDeps = append(ninjaDeps, globListFiles...)
+
+ // Convert the Soong module graph into Bazel BUILD files.
+ if configuration.BuildMode == android.GenerateQueryView {
+ queryviewMarkerFile := bazelQueryViewDir + ".marker"
+ runQueryView(bazelQueryViewDir, queryviewMarkerFile, configuration, ctx)
+ writeDepFile(queryviewMarkerFile, ctx.EventHandler, ninjaDeps)
+ return queryviewMarkerFile
+ } else if configuration.BuildMode == android.GenerateModuleGraph {
+ writeJsonModuleGraphAndActions(ctx, moduleGraphFile, moduleActionsFile)
+ writeDepFile(moduleGraphFile, ctx.EventHandler, ninjaDeps)
+ return moduleGraphFile
+ } else if configuration.BuildMode == android.GenerateDocFile {
+ // TODO: we could make writeDocs() return the list of documentation files
+ // written and add them to the .d file. Then soong_docs would be re-run
+ // whenever one is deleted.
+ if err := writeDocs(ctx, shared.JoinPath(topDir, docFile)); err != nil {
+ fmt.Fprintf(os.Stderr, "error building Soong documentation: %s\n", err)
+ os.Exit(1)
+ }
+ writeDepFile(docFile, ctx.EventHandler, ninjaDeps)
+ return docFile
+ } else {
+ // The actual output (build.ninja) was written in the RunBlueprint() call
+ // above
+ writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps)
+ return cmdlineArgs.OutFile
+ }
}
// soong_ui dumps the available environment variables to
@@ -351,12 +470,8 @@
logDir := availableEnv["LOG_DIR"]
ctx := newContext(configuration)
- ctx.EventHandler.Begin("soong_build")
- finalOutputFile := doChosenActivity(ctx, configuration, extraNinjaDeps)
-
- ctx.EventHandler.End("soong_build")
- writeMetrics(configuration, *ctx.EventHandler, logDir)
+ finalOutputFile := doChosenActivity(ctx, configuration, extraNinjaDeps, logDir)
writeUsedEnvironmentFile(configuration, finalOutputFile)
}
@@ -373,12 +488,19 @@
os.Exit(1)
}
- err = ioutil.WriteFile(path, data, 0666)
- if err != nil {
+ if preexistingData, err := os.ReadFile(path); err != nil {
+ if !os.IsNotExist(err) {
+ fmt.Fprintf(os.Stderr, "error reading used environment file '%s': %s\n", usedEnvFile, err)
+ os.Exit(1)
+ }
+ } else if bytes.Equal(preexistingData, data) {
+ // used environment file is unchanged
+ return
+ }
+ if err = os.WriteFile(path, data, 0666); err != nil {
fmt.Fprintf(os.Stderr, "error writing used environment file '%s': %s\n", usedEnvFile, err)
os.Exit(1)
}
-
// Touch the output file so that it's not older than the file we just
// wrote. We can't write the environment file earlier because one an access
// new environment variables while writing it.
@@ -457,6 +579,17 @@
// FIXME: 'frameworks/compile/slang' has a filegroup error due to an escaping issue
excludes = append(excludes, "frameworks/compile/slang")
+ // FIXME(b/260809113): 'prebuilts/clang/host/linux-x86/clang-dev' is a tool-generated symlink directory that contains a BUILD file.
+ // The bazel files finder code doesn't traverse into symlink dirs, and hence is not aware of this BUILD file and exclude it accordingly
+ // during symlink forest generation when checking against keepExistingBuildFiles allowlist.
+ //
+ // This is necessary because globs in //prebuilts/clang/host/linux-x86/BUILD
+ // currently assume no subpackages (keepExistingBuildFile is not recursive for that directory).
+ //
+ // This is a bandaid until we the symlink forest logic can intelligently exclude BUILD files found in source symlink dirs according
+ // to the keepExistingBuildFile allowlist.
+ excludes = append(excludes, "prebuilts/clang/host/linux-x86/clang-dev")
+
return excludes
}
@@ -476,86 +609,112 @@
return files, nil
}
+func bazelArtifacts() []string {
+ return []string{
+ "bazel-bin",
+ "bazel-genfiles",
+ "bazel-out",
+ "bazel-testlogs",
+ "bazel-" + filepath.Base(topDir),
+ }
+}
+
+// This could in theory easily be separated into a binary that generically
+// merges two directories into a symlink tree. The main obstacle is that this
+// function currently depends on both Bazel-specific knowledge (the existence
+// of bazel-* symlinks) and configuration (the set of BUILD.bazel files that
+// should and should not be kept)
+//
+// Ideally, bp2build would write a file that contains instructions to the
+// symlink tree creation binary. Then the latter would not need to depend on
+// the very heavy-weight machinery of soong_build .
+func runSymlinkForestCreation(configuration android.Config, ctx *android.Context, extraNinjaDeps []string, metricsDir string) string {
+ var ninjaDeps []string
+ ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
+
+ generatedRoot := shared.JoinPath(configuration.SoongOutDir(), "bp2build")
+ workspaceRoot := shared.JoinPath(configuration.SoongOutDir(), "workspace")
+
+ excludes := bazelArtifacts()
+
+ if outDir[0] != '/' {
+ excludes = append(excludes, outDir)
+ }
+
+ existingBazelRelatedFiles, err := getExistingBazelRelatedFiles(topDir)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error determining existing Bazel-related files: %s\n", err)
+ os.Exit(1)
+ }
+
+ pathsToIgnoredBuildFiles := getPathsToIgnoredBuildFiles(configuration.Bp2buildPackageConfig, topDir, existingBazelRelatedFiles, configuration.IsEnvTrue("BP2BUILD_VERBOSE"))
+ excludes = append(excludes, pathsToIgnoredBuildFiles...)
+ excludes = append(excludes, getTemporaryExcludes()...)
+
+ // PlantSymlinkForest() returns all the directories that were readdir()'ed.
+ // Such a directory SHOULD be added to `ninjaDeps` so that a child directory
+ // or file created/deleted under it would trigger an update of the symlink
+ // forest.
+ ctx.EventHandler.Do("symlink_forest", func() {
+ symlinkForestDeps := bp2build.PlantSymlinkForest(
+ configuration.IsEnvTrue("BP2BUILD_VERBOSE"), topDir, workspaceRoot, generatedRoot, excludes)
+ ninjaDeps = append(ninjaDeps, symlinkForestDeps...)
+ })
+
+ writeDepFile(symlinkForestMarker, ctx.EventHandler, ninjaDeps)
+ touch(shared.JoinPath(topDir, symlinkForestMarker))
+ codegenMetrics := bp2build.ReadCodegenMetrics(metricsDir)
+ if codegenMetrics == nil {
+ m := bp2build.CreateCodegenMetrics()
+ codegenMetrics = &m
+ } else {
+ //TODO (usta) we cannot determine if we loaded a stale file, i.e. from an unrelated prior
+ //invocation of codegen. We should simply use a separate .pb file
+ }
+ writeBp2BuildMetrics(codegenMetrics, ctx.EventHandler, metricsDir)
+
+ return symlinkForestMarker
+}
+
// Run Soong in the bp2build mode. This creates a standalone context that registers
// an alternate pipeline of mutators and singletons specifically for generating
// Bazel BUILD files instead of Ninja files.
-func runBp2Build(configuration android.Config, extraNinjaDeps []string) {
- eventHandler := metrics.EventHandler{}
- var metrics bp2build.CodegenMetrics
- eventHandler.Do("bp2build", func() {
-
- // Register an alternate set of singletons and mutators for bazel
- // conversion for Bazel conversion.
- bp2buildCtx := android.NewContext(configuration)
+func runBp2Build(configuration android.Config, ctx *android.Context, extraNinjaDeps []string, metricsDir string) string {
+ var codegenMetrics *bp2build.CodegenMetrics
+ ctx.EventHandler.Do("bp2build", func() {
// Propagate "allow misssing dependencies" bit. This is normally set in
- // newContext(), but we create bp2buildCtx without calling that method.
- bp2buildCtx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
- bp2buildCtx.SetNameInterface(newNameResolver(configuration))
- bp2buildCtx.RegisterForBazelConversion()
+ // newContext(), but we create ctx without calling that method.
+ ctx.SetAllowMissingDependencies(configuration.AllowMissingDependencies())
+ ctx.SetNameInterface(newNameResolver(configuration))
+ ctx.RegisterForBazelConversion()
+ ctx.SetModuleListFile(cmdlineArgs.ModuleListFile)
- // The bp2build process is a purely functional process that only depends on
- // Android.bp files. It must not depend on the values of per-build product
- // configurations or variables, since those will generate different BUILD
- // files based on how the user has configured their tree.
- bp2buildCtx.SetModuleListFile(cmdlineArgs.ModuleListFile)
- modulePaths, err := bp2buildCtx.ListModulePaths(".")
- if err != nil {
- panic(err)
- }
-
- extraNinjaDeps = append(extraNinjaDeps, modulePaths...)
+ var ninjaDeps []string
+ ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
// Run the loading and analysis pipeline to prepare the graph of regular
// Modules parsed from Android.bp files, and the BazelTargetModules mapped
// from the regular Modules.
- blueprintArgs := cmdlineArgs
- ninjaDeps := bootstrap.RunBlueprint(blueprintArgs, bootstrap.StopBeforePrepareBuildActions, bp2buildCtx.Context, configuration)
- ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
+ ctx.EventHandler.Do("bootstrap", func() {
+ blueprintArgs := cmdlineArgs
+ bootstrapDeps := bootstrap.RunBlueprint(blueprintArgs, bootstrap.StopBeforePrepareBuildActions, ctx.Context, configuration)
+ ninjaDeps = append(ninjaDeps, bootstrapDeps...)
+ })
- globListFiles := writeBuildGlobsNinjaFile(bp2buildCtx, configuration.SoongOutDir(), configuration)
+ globListFiles := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration)
ninjaDeps = append(ninjaDeps, globListFiles...)
// Run the code-generation phase to convert BazelTargetModules to BUILD files
- // and print conversion metrics to the user.
- codegenContext := bp2build.NewCodegenContext(configuration, *bp2buildCtx, bp2build.Bp2Build)
- metrics = bp2build.Codegen(codegenContext)
-
- generatedRoot := shared.JoinPath(configuration.SoongOutDir(), "bp2build")
- workspaceRoot := shared.JoinPath(configuration.SoongOutDir(), "workspace")
-
- excludes := []string{
- "bazel-bin",
- "bazel-genfiles",
- "bazel-out",
- "bazel-testlogs",
- "bazel-" + filepath.Base(topDir),
- }
-
- if outDir[0] != '/' {
- excludes = append(excludes, outDir)
- }
-
- existingBazelRelatedFiles, err := getExistingBazelRelatedFiles(topDir)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error determining existing Bazel-related files: %s\n", err)
- os.Exit(1)
- }
-
- pathsToIgnoredBuildFiles := getPathsToIgnoredBuildFiles(configuration.Bp2buildPackageConfig, topDir, existingBazelRelatedFiles, configuration.IsEnvTrue("BP2BUILD_VERBOSE"))
- excludes = append(excludes, pathsToIgnoredBuildFiles...)
-
- excludes = append(excludes, getTemporaryExcludes()...)
-
- symlinkForestDeps := bp2build.PlantSymlinkForest(
- configuration, topDir, workspaceRoot, generatedRoot, ".", excludes)
+ // and print conversion codegenMetrics to the user.
+ codegenContext := bp2build.NewCodegenContext(configuration, ctx, bp2build.Bp2Build)
+ ctx.EventHandler.Do("codegen", func() {
+ codegenMetrics = bp2build.Codegen(codegenContext)
+ })
ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
- ninjaDeps = append(ninjaDeps, symlinkForestDeps...)
- writeDepFile(bp2buildMarker, eventHandler, ninjaDeps)
-
- // Create an empty bp2build marker file.
+ writeDepFile(bp2buildMarker, ctx.EventHandler, ninjaDeps)
touch(shared.JoinPath(topDir, bp2buildMarker))
})
@@ -563,26 +722,35 @@
// for queryview, since that's a total repo-wide conversion and there's a
// 1:1 mapping for each module.
if configuration.IsEnvTrue("BP2BUILD_VERBOSE") {
- metrics.Print()
+ codegenMetrics.Print()
}
- writeBp2BuildMetrics(&metrics, configuration, eventHandler)
+ writeBp2BuildMetrics(codegenMetrics, ctx.EventHandler, metricsDir)
+ return bp2buildMarker
}
// Write Bp2Build metrics into $LOG_DIR
-func writeBp2BuildMetrics(codegenMetrics *bp2build.CodegenMetrics,
- configuration android.Config, eventHandler metrics.EventHandler) {
+func writeBp2BuildMetrics(codegenMetrics *bp2build.CodegenMetrics, eventHandler *metrics.EventHandler, metricsDir string) {
for _, event := range eventHandler.CompletedEvents() {
- codegenMetrics.Events = append(codegenMetrics.Events,
- &bp2build_metrics_proto.Event{
- Name: event.Id,
- StartTime: uint64(event.Start.UnixNano()),
- RealTime: event.RuntimeNanoseconds(),
- })
+ codegenMetrics.AddEvent(&bp2build_metrics_proto.Event{
+ Name: event.Id,
+ StartTime: uint64(event.Start.UnixNano()),
+ RealTime: event.RuntimeNanoseconds(),
+ })
}
- metricsDir := configuration.Getenv("LOG_DIR")
if len(metricsDir) < 1 {
fmt.Fprintf(os.Stderr, "\nMissing required env var for generating bp2build metrics: LOG_DIR\n")
os.Exit(1)
}
codegenMetrics.Write(metricsDir)
}
+
+func readBazelPaths(configuration android.Config) ([]string, error) {
+ depsPath := configuration.Getenv("BAZEL_DEPS_FILE")
+
+ data, err := os.ReadFile(depsPath)
+ if err != nil {
+ return nil, err
+ }
+ paths := strings.Split(strings.TrimSpace(string(data)), "\n")
+ return paths, nil
+}
diff --git a/cmd/soong_build/queryview.go b/cmd/soong_build/queryview.go
index 983dbf0..a876522 100644
--- a/cmd/soong_build/queryview.go
+++ b/cmd/soong_build/queryview.go
@@ -15,6 +15,7 @@
package main
import (
+ "io/fs"
"io/ioutil"
"os"
"path/filepath"
@@ -23,8 +24,9 @@
"android/soong/bp2build"
)
-func createBazelQueryView(ctx *bp2build.CodegenContext, bazelQueryViewDir string) error {
- os.RemoveAll(bazelQueryViewDir)
+// A helper function to generate a Read-only Bazel workspace in outDir
+func createBazelWorkspace(ctx *bp2build.CodegenContext, outDir string) error {
+ os.RemoveAll(outDir)
ruleShims := bp2build.CreateRuleShims(android.ModuleTypeFactories())
res, err := bp2build.GenerateBazelTargets(ctx, true)
@@ -33,9 +35,14 @@
}
filesToWrite := bp2build.CreateBazelFiles(ctx.Config(), ruleShims, res.BuildDirToTargets(),
- bp2build.QueryView)
+ ctx.Mode())
+ bazelRcFiles, err2 := CopyBazelRcFiles()
+ if err2 != nil {
+ return err2
+ }
+ filesToWrite = append(filesToWrite, bazelRcFiles...)
for _, f := range filesToWrite {
- if err := writeReadOnlyFile(bazelQueryViewDir, f); err != nil {
+ if err := writeReadOnlyFile(outDir, f); err != nil {
return err
}
}
@@ -43,6 +50,32 @@
return nil
}
+// CopyBazelRcFiles creates BazelFiles for all the bazelrc files under
+// build/bazel. They're needed because the rc files are still read when running
+// queryview, so they have to be in the queryview workspace.
+func CopyBazelRcFiles() ([]bp2build.BazelFile, error) {
+ result := make([]bp2build.BazelFile, 0)
+ err := filepath.WalkDir(filepath.Join(topDir, "build/bazel"), func(path string, info fs.DirEntry, err error) error {
+ if filepath.Ext(path) == ".bazelrc" {
+ contents, err := os.ReadFile(path)
+ if err != nil {
+ return err
+ }
+ path, err = filepath.Rel(topDir, path)
+ if err != nil {
+ return err
+ }
+ result = append(result, bp2build.BazelFile{
+ Dir: filepath.Dir(path),
+ Basename: filepath.Base(path),
+ Contents: string(contents),
+ })
+ }
+ return nil
+ })
+ return result, err
+}
+
// The auto-conversion directory should be read-only, sufficient for bazel query. The files
// are not intended to be edited by end users.
func writeReadOnlyFile(dir string, f bp2build.BazelFile) error {
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index b06e4fe..f7689b9 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -132,8 +132,13 @@
build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"),
build.OsEnvironment().IsEnvTrue("SOONG_UI_ANSI_OUTPUT"))
+ // Create and start a new metric record.
+ met := metrics.New()
+ met.SetBuildDateTime(buildStarted)
+ met.SetBuildCommand(os.Args)
+
// Attach a new logger instance to the terminal output.
- log := logger.New(output)
+ log := logger.NewWithMetrics(output, met)
defer log.Cleanup()
// Create a context to simplify the program termination process.
@@ -144,11 +149,6 @@
trace := tracer.New(log)
defer trace.Close()
- // Create and start a new metric record.
- met := metrics.New()
- met.SetBuildDateTime(buildStarted)
- met.SetBuildCommand(os.Args)
-
// Create a new Status instance, which manages action counts and event output channels.
stat := &status.Status{}
defer stat.Finish()
@@ -183,6 +183,7 @@
buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
+ bp2buildMetricsFile := filepath.Join(logsDir, c.logsPrefix+"bp2build_metrics.pb")
build.PrintOutDirWarning(buildCtx, config)
@@ -210,6 +211,7 @@
files := []string{
buildErrorFile, // build error strings
rbeMetricsFile, // high level metrics related to remote build execution.
+ bp2buildMetricsFile, // high level metrics related to bp2build.
soongMetricsFile, // high level metrics related to this build system.
config.BazelMetricsDir(), // directory that contains a set of bazel metrics.
}
@@ -281,7 +283,7 @@
if flags.NArg() != 1 {
flags.Usage()
- os.Exit(1)
+ ctx.Fatalf("Invalid usage")
}
varName := flags.Arg(0)
@@ -341,7 +343,7 @@
if flags.NArg() != 0 {
flags.Usage()
- os.Exit(1)
+ ctx.Fatalf("Invalid usage")
}
vars := strings.Fields(*varsStr)
@@ -502,7 +504,7 @@
fmt.Fprintln(writer, "!")
fmt.Fprintln(writer, "! Older versions are saved in verbose.log.#.gz files")
fmt.Fprintln(writer, "")
- ctx.Fatal("done")
+ ctx.Fatal("Invalid argument")
}
if _, ok := config.Environment().Get("ONE_SHOT_MAKEFILE"); ok {
@@ -513,7 +515,7 @@
fmt.Fprintln(writer, "!")
fmt.Fprintln(writer, "! Otherwise, either specify a module name with m, or use mma / MODULES-IN-...")
fmt.Fprintln(writer, "")
- ctx.Fatal("done")
+ ctx.Fatal("Invalid environment")
}
build.Build(ctx, config)
diff --git a/compliance/build_license_metadata/build_license_metadata.go b/compliance/build_license_metadata/build_license_metadata.go
index 53d2407..fb4b784 100644
--- a/compliance/build_license_metadata/build_license_metadata.go
+++ b/compliance/build_license_metadata/build_license_metadata.go
@@ -66,6 +66,7 @@
packageName := flags.String("p", "", "license package name")
moduleType := newMultiString(flags, "mt", "module type")
+ moduleName := flags.String("mn", "", "module name")
kinds := newMultiString(flags, "k", "license kinds")
moduleClass := newMultiString(flags, "mc", "module class")
conditions := newMultiString(flags, "c", "license conditions")
@@ -83,6 +84,7 @@
metadata := license_metadata_proto.LicenseMetadata{}
metadata.PackageName = proto.String(*packageName)
+ metadata.ModuleName = proto.String(*moduleName)
metadata.ModuleTypes = *moduleType
metadata.ModuleClasses = *moduleClass
metadata.IsContainer = proto.Bool(*isContainer)
diff --git a/compliance/license_metadata_proto/license_metadata.pb.go b/compliance/license_metadata_proto/license_metadata.pb.go
index 44dbc78..69aa377 100644
--- a/compliance/license_metadata_proto/license_metadata.pb.go
+++ b/compliance/license_metadata_proto/license_metadata.pb.go
@@ -14,8 +14,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.27.1
-// protoc v3.19.0
+// protoc-gen-go v1.28.0
+// protoc v3.12.4
// source: license_metadata.proto
package license_metadata_proto
@@ -40,7 +40,9 @@
unknownFields protoimpl.UnknownFields
// package_name identifies the source package. License texts are named relative to the package name.
- PackageName *string `protobuf:"bytes,1,opt,name=package_name,json=packageName" json:"package_name,omitempty"`
+ PackageName *string `protobuf:"bytes,1,opt,name=package_name,json=packageName" json:"package_name,omitempty"`
+ // module_name identifies the target
+ ModuleName *string `protobuf:"bytes,14,opt,name=module_name,json=moduleName" json:"module_name,omitempty"`
ModuleTypes []string `protobuf:"bytes,2,rep,name=module_types,json=moduleTypes" json:"module_types,omitempty"`
ModuleClasses []string `protobuf:"bytes,3,rep,name=module_classes,json=moduleClasses" json:"module_classes,omitempty"`
// projects identifies the git project(s) containing the associated source code.
@@ -104,6 +106,13 @@
return ""
}
+func (x *LicenseMetadata) GetModuleName() string {
+ if x != nil && x.ModuleName != nil {
+ return *x.ModuleName
+ }
+ return ""
+}
+
func (x *LicenseMetadata) GetModuleTypes() []string {
if x != nil {
return x.ModuleTypes
@@ -311,52 +320,54 @@
0x0a, 0x16, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x16, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
- 0x22, 0x8a, 0x04, 0x0a, 0x0f, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61,
+ 0x22, 0xab, 0x04, 0x0a, 0x0f, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61,
0x64, 0x61, 0x74, 0x61, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b,
- 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
- 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x6d,
- 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x6f,
- 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03,
- 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x65,
- 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x04, 0x20,
- 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x23, 0x0a,
- 0x0d, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x73, 0x18, 0x05,
- 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4b, 0x69, 0x6e,
- 0x64, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x63, 0x6f,
- 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x11,
- 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
- 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x65, 0x78,
- 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73,
- 0x65, 0x54, 0x65, 0x78, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x63, 0x6f, 0x6e,
- 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73,
- 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x75, 0x69,
- 0x6c, 0x74, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x12,
- 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x03,
- 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x12, 0x43, 0x0a,
- 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x0b, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x63, 0x65, 0x6e,
- 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x49, 0x6e, 0x73, 0x74,
- 0x61, 0x6c, 0x6c, 0x4d, 0x61, 0x70, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x4d,
- 0x61, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x0c, 0x20,
- 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3f, 0x0a, 0x04,
- 0x64, 0x65, 0x70, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x62, 0x75, 0x69,
- 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64,
- 0x61, 0x74, 0x61, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x44, 0x65, 0x70,
- 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x04, 0x64, 0x65, 0x70, 0x73, 0x22, 0x50, 0x0a,
- 0x0a, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x4d, 0x61, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x66,
- 0x72, 0x6f, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
- 0x66, 0x72, 0x6f, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e, 0x74,
- 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x50, 0x61, 0x74, 0x68, 0x22,
- 0x4b, 0x0a, 0x13, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x44, 0x65, 0x70, 0x65,
- 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x61, 0x6e,
- 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52,
- 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x31, 0x5a, 0x2f,
- 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x63, 0x6f,
- 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x2f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65,
- 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x61, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
+ 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f,
+ 0x64, 0x75, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x6f, 0x64, 0x75,
+ 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b,
+ 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6d,
+ 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20,
+ 0x03, 0x28, 0x09, 0x52, 0x0d, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x04,
+ 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x23,
+ 0x0a, 0x0d, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x73, 0x18,
+ 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4b, 0x69,
+ 0x6e, 0x64, 0x73, 0x12, 0x2d, 0x0a, 0x12, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x63,
+ 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52,
+ 0x11, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f,
+ 0x6e, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x65,
+ 0x78, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x69, 0x63, 0x65, 0x6e,
+ 0x73, 0x65, 0x54, 0x65, 0x78, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x63, 0x6f,
+ 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69,
+ 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x75,
+ 0x69, 0x6c, 0x74, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x62, 0x75, 0x69, 0x6c, 0x74,
+ 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x18, 0x0a, 0x20,
+ 0x03, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x12, 0x43,
+ 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x0b, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x63, 0x65,
+ 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x49, 0x6e, 0x73,
+ 0x74, 0x61, 0x6c, 0x6c, 0x4d, 0x61, 0x70, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c,
+ 0x4d, 0x61, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x0c,
+ 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3f, 0x0a,
+ 0x04, 0x64, 0x65, 0x70, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x62, 0x75,
+ 0x69, 0x6c, 0x64, 0x5f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x44, 0x65,
+ 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x04, 0x64, 0x65, 0x70, 0x73, 0x22, 0x50,
+ 0x0a, 0x0a, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x4d, 0x61, 0x70, 0x12, 0x1b, 0x0a, 0x09,
+ 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x08, 0x66, 0x72, 0x6f, 0x6d, 0x50, 0x61, 0x74, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x6e,
+ 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x50, 0x61, 0x74, 0x68,
+ 0x22, 0x4b, 0x0a, 0x13, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x44, 0x65, 0x70,
+ 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x61,
+ 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
+ 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x31, 0x5a,
+ 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x63,
+ 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x2f, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73,
+ 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
diff --git a/compliance/license_metadata_proto/license_metadata.proto b/compliance/license_metadata_proto/license_metadata.proto
index 1b4f34f..61f8126 100644
--- a/compliance/license_metadata_proto/license_metadata.proto
+++ b/compliance/license_metadata_proto/license_metadata.proto
@@ -21,6 +21,9 @@
// package_name identifies the source package. License texts are named relative to the package name.
optional string package_name = 1;
+ // module_name identifies the target
+ optional string module_name = 14;
+
repeated string module_types = 2;
repeated string module_classes = 3;
@@ -54,6 +57,9 @@
// deps lists the license metadata files depended on.
repeated AnnotatedDependency deps = 13;
+
+ // next id: 15
+
}
// InstallMap messages describe the mapping from an input filesystem file to the path to the file
diff --git a/compliance/project_metadata_proto/Android.bp b/compliance/project_metadata_proto/Android.bp
new file mode 100644
index 0000000..56e76e7
--- /dev/null
+++ b/compliance/project_metadata_proto/Android.bp
@@ -0,0 +1,27 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "project_metadata_proto",
+ pkgPath: "android/soong/compliance/project_metadata_proto",
+ srcs: ["project_metadata.pb.go"],
+ deps: [
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ ],
+}
diff --git a/compliance/project_metadata_proto/project_metadata.pb.go b/compliance/project_metadata_proto/project_metadata.pb.go
new file mode 100644
index 0000000..529159c
--- /dev/null
+++ b/compliance/project_metadata_proto/project_metadata.pb.go
@@ -0,0 +1,765 @@
+// 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.
+
+// A proto definition used to parse METADATA file in third party projects.
+
+// This proto will only contain fields and values used by android compliance.
+// It is not intended to be the formal definition of METADATA file.
+
+// See google3/third_party/metadata.proto if you need to add more stuff to
+// match upstream. Do not add new fields and values here. Add them upstream
+// when necessary, and copy them here.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.28.0
+// protoc v3.12.4
+// source: project_metadata.proto
+
+package project_metadata_proto
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// License type that identifies how the packages may be used. See
+// go/thirdpartylicenses for full explanation of each license type.
+type LicenseType int32
+
+const (
+ LicenseType_BY_EXCEPTION_ONLY LicenseType = 1
+ LicenseType_NOTICE LicenseType = 2
+ LicenseType_PERMISSIVE LicenseType = 3
+ LicenseType_RECIPROCAL LicenseType = 4
+ LicenseType_RESTRICTED_IF_STATICALLY_LINKED LicenseType = 5
+ LicenseType_RESTRICTED LicenseType = 6
+ LicenseType_UNENCUMBERED LicenseType = 7
+)
+
+// Enum value maps for LicenseType.
+var (
+ LicenseType_name = map[int32]string{
+ 1: "BY_EXCEPTION_ONLY",
+ 2: "NOTICE",
+ 3: "PERMISSIVE",
+ 4: "RECIPROCAL",
+ 5: "RESTRICTED_IF_STATICALLY_LINKED",
+ 6: "RESTRICTED",
+ 7: "UNENCUMBERED",
+ }
+ LicenseType_value = map[string]int32{
+ "BY_EXCEPTION_ONLY": 1,
+ "NOTICE": 2,
+ "PERMISSIVE": 3,
+ "RECIPROCAL": 4,
+ "RESTRICTED_IF_STATICALLY_LINKED": 5,
+ "RESTRICTED": 6,
+ "UNENCUMBERED": 7,
+ }
+)
+
+func (x LicenseType) Enum() *LicenseType {
+ p := new(LicenseType)
+ *p = x
+ return p
+}
+
+func (x LicenseType) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (LicenseType) Descriptor() protoreflect.EnumDescriptor {
+ return file_project_metadata_proto_enumTypes[0].Descriptor()
+}
+
+func (LicenseType) Type() protoreflect.EnumType {
+ return &file_project_metadata_proto_enumTypes[0]
+}
+
+func (x LicenseType) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *LicenseType) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = LicenseType(num)
+ return nil
+}
+
+// Deprecated: Use LicenseType.Descriptor instead.
+func (LicenseType) EnumDescriptor() ([]byte, []int) {
+ return file_project_metadata_proto_rawDescGZIP(), []int{0}
+}
+
+type URL_Type int32
+
+const (
+ // The homepage for the package. For example, "https://bazel.io/". This URL
+ // is optional, but encouraged to help disambiguate similarly named packages
+ // or to get more information about the package. This is especially helpful
+ // when no other URLs provide human readable resources (such as git:// or
+ // sso:// URLs).
+ URL_HOMEPAGE URL_Type = 1
+ // The URL of the archive containing the source code for the package, for
+ // example a zip or tgz file.
+ URL_ARCHIVE URL_Type = 2
+ // The URL of the upstream git repository this package is retrieved from.
+ // For example:
+ // - https://github.com/git/git.git
+ // - git://git.kernel.org/pub/scm/git/git.git
+ //
+ // Use of a git URL requires that the package "version" value must specify a
+ // specific git tag or revision.
+ URL_GIT URL_Type = 3
+ // The URL of the upstream SVN repository this package is retrieved from.
+ // For example:
+ // - http://llvm.org/svn/llvm-project/llvm/
+ //
+ // Use of an SVN URL requires that the package "version" value must specify
+ // a specific SVN tag or revision.
+ URL_SVN URL_Type = 7
+ // The URL of the upstream mercurial repository this package is retrieved
+ // from. For example:
+ // - https://mercurial-scm.org/repo/evolve
+ //
+ // Use of a mercurial URL requires that the package "version" value must
+ // specify a specific tag or revision.
+ URL_HG URL_Type = 8
+ // The URL of the upstream darcs repository this package is retrieved
+ // from. For example:
+ // - https://hub.darcs.net/hu.dwim/hu.dwim.util
+ //
+ // Use of a DARCS URL requires that the package "version" value must
+ // specify a specific tag or revision.
+ URL_DARCS URL_Type = 9
+ // The URL of the upstream piper location. This is primarily used when a
+ // package is being migrated into third_party from elsewhere in piper, or
+ // when a package is being newly developed in third_party. For newly
+ // developed packages, the PIPER URL should reference the package itself
+ // (e.g. "http://google3/third_party/my/package")
+ URL_PIPER URL_Type = 4
+ // A URL that does not fit any other type. This may also indicate that the
+ // source code was received via email or some other out-of-band way. This is
+ // most commonly used with commercial software received directly from the
+ // vendor. In the case of email, the URL value can be used to provide
+ // additional information about how it was received.
+ URL_OTHER URL_Type = 11
+ // The URL identifying where the local copy of the package source code can
+ // be found.
+ //
+ // Typically, the metadata files describing a package reside in the same
+ // directory as the source code for the package. In a few rare cases where
+ // they are separate, the LOCAL_SOURCE URL identifies where to find the
+ // source code. This only describes where to find the local copy of the
+ // source; there should always be an additional URL describing where the
+ // package was retrieved from.
+ //
+ // Examples:
+ // - http://google3/third_party/java_src/gerritcodereview/gerrit/
+ // - https://android.googlesource.com/platform/external/apache-http/
+ URL_LOCAL_SOURCE URL_Type = 6
+)
+
+// Enum value maps for URL_Type.
+var (
+ URL_Type_name = map[int32]string{
+ 1: "HOMEPAGE",
+ 2: "ARCHIVE",
+ 3: "GIT",
+ 7: "SVN",
+ 8: "HG",
+ 9: "DARCS",
+ 4: "PIPER",
+ 11: "OTHER",
+ 6: "LOCAL_SOURCE",
+ }
+ URL_Type_value = map[string]int32{
+ "HOMEPAGE": 1,
+ "ARCHIVE": 2,
+ "GIT": 3,
+ "SVN": 7,
+ "HG": 8,
+ "DARCS": 9,
+ "PIPER": 4,
+ "OTHER": 11,
+ "LOCAL_SOURCE": 6,
+ }
+)
+
+func (x URL_Type) Enum() *URL_Type {
+ p := new(URL_Type)
+ *p = x
+ return p
+}
+
+func (x URL_Type) String() string {
+ return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (URL_Type) Descriptor() protoreflect.EnumDescriptor {
+ return file_project_metadata_proto_enumTypes[1].Descriptor()
+}
+
+func (URL_Type) Type() protoreflect.EnumType {
+ return &file_project_metadata_proto_enumTypes[1]
+}
+
+func (x URL_Type) Number() protoreflect.EnumNumber {
+ return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Do not use.
+func (x *URL_Type) UnmarshalJSON(b []byte) error {
+ num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b)
+ if err != nil {
+ return err
+ }
+ *x = URL_Type(num)
+ return nil
+}
+
+// Deprecated: Use URL_Type.Descriptor instead.
+func (URL_Type) EnumDescriptor() ([]byte, []int) {
+ return file_project_metadata_proto_rawDescGZIP(), []int{2, 0}
+}
+
+type Metadata struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Name of this API/package.
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ // A short description (a few lines) of the package. It will be
+ // included on the summary page.
+ // Example: "Handles location lookups, throttling, batching, etc."
+ Description *string `protobuf:"bytes,3,opt,name=description" json:"description,omitempty"`
+ // Specifies additional data about third-party packages.
+ ThirdParty *ThirdParty `protobuf:"bytes,13,opt,name=third_party,json=thirdParty" json:"third_party,omitempty"`
+}
+
+func (x *Metadata) Reset() {
+ *x = Metadata{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_project_metadata_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Metadata) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Metadata) ProtoMessage() {}
+
+func (x *Metadata) ProtoReflect() protoreflect.Message {
+ mi := &file_project_metadata_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Metadata.ProtoReflect.Descriptor instead.
+func (*Metadata) Descriptor() ([]byte, []int) {
+ return file_project_metadata_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Metadata) GetName() string {
+ if x != nil && x.Name != nil {
+ return *x.Name
+ }
+ return ""
+}
+
+func (x *Metadata) GetDescription() string {
+ if x != nil && x.Description != nil {
+ return *x.Description
+ }
+ return ""
+}
+
+func (x *Metadata) GetThirdParty() *ThirdParty {
+ if x != nil {
+ return x.ThirdParty
+ }
+ return nil
+}
+
+type ThirdParty struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // URL(s) associated with the package.
+ //
+ // At a minimum, all packages must specify a URL which identifies where it
+ // came from, containing a type of: ARCHIVE, GIT, PIPER, or OTHER. Typically,
+ // a package should contain only a single URL from these types. Occasionally,
+ // a package may be broken across multiple archive files for whatever reason,
+ // in which case having multiple ARCHIVE URLs is okay. However, this should
+ // not be used to combine different logical packages that are versioned and
+ // possibly licensed differently.
+ Url []*URL `protobuf:"bytes,1,rep,name=url" json:"url,omitempty"`
+ // The package version. In order of preference, this should contain:
+ // - If the package comes from Git or another source control system,
+ // a specific tag or revision in source control, such as "r123" or
+ // "58e27d2". This MUST NOT be a mutable ref such as a branch name.
+ // - a released package version such as "1.0", "2.3-beta", etc.
+ // - the date the package was retrieved, formatted as "As of YYYY-MM-DD".
+ Version *string `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"`
+ // The date of the change in which the package was last upgraded from
+ // upstream.
+ // This should only identify package upgrades from upstream, not local
+ // modifications. This may identify the date of either the original or
+ // merged change.
+ //
+ // Note: this is NOT the date that this version of the package was released
+ // externally.
+ LastUpgradeDate *Date `protobuf:"bytes,10,opt,name=last_upgrade_date,json=lastUpgradeDate" json:"last_upgrade_date,omitempty"`
+ // License type that identifies how the package may be used. See
+ // go/thirdpartylicenses for instructions on selecting the appropriate type.
+ LicenseType *LicenseType `protobuf:"varint,4,opt,name=license_type,json=licenseType,enum=project_metadata.LicenseType" json:"license_type,omitempty"`
+ // Description of local changes that have been made to the package. This does
+ // not need to (and in most cases should not) attempt to include an exhaustive
+ // list of all changes, but may instead direct readers to review the local
+ // commit history, a collection of patch files, a separate README.md (or
+ // similar) document, etc.
+ // Note: Use of this field to store IDs of advisories fixed with a backported
+ // patch is deprecated, use "security.mitigated_security_patch" instead.
+ LocalModifications *string `protobuf:"bytes,6,opt,name=local_modifications,json=localModifications" json:"local_modifications,omitempty"`
+ // The URL for any public mirror created for compliance purposes.
+ // See go/thirdpartylicenses#reciprocal policy for more details.
+ ComplianceMirrorUrl *string `protobuf:"bytes,12,opt,name=compliance_mirror_url,json=complianceMirrorUrl" json:"compliance_mirror_url,omitempty"`
+ // The homepage for the package. This will eventually replace
+ // `url { type: HOMEPAGE }`
+ Homepage *string `protobuf:"bytes,14,opt,name=homepage" json:"homepage,omitempty"`
+}
+
+func (x *ThirdParty) Reset() {
+ *x = ThirdParty{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_project_metadata_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *ThirdParty) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ThirdParty) ProtoMessage() {}
+
+func (x *ThirdParty) ProtoReflect() protoreflect.Message {
+ mi := &file_project_metadata_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use ThirdParty.ProtoReflect.Descriptor instead.
+func (*ThirdParty) Descriptor() ([]byte, []int) {
+ return file_project_metadata_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *ThirdParty) GetUrl() []*URL {
+ if x != nil {
+ return x.Url
+ }
+ return nil
+}
+
+func (x *ThirdParty) GetVersion() string {
+ if x != nil && x.Version != nil {
+ return *x.Version
+ }
+ return ""
+}
+
+func (x *ThirdParty) GetLastUpgradeDate() *Date {
+ if x != nil {
+ return x.LastUpgradeDate
+ }
+ return nil
+}
+
+func (x *ThirdParty) GetLicenseType() LicenseType {
+ if x != nil && x.LicenseType != nil {
+ return *x.LicenseType
+ }
+ return LicenseType_BY_EXCEPTION_ONLY
+}
+
+func (x *ThirdParty) GetLocalModifications() string {
+ if x != nil && x.LocalModifications != nil {
+ return *x.LocalModifications
+ }
+ return ""
+}
+
+func (x *ThirdParty) GetComplianceMirrorUrl() string {
+ if x != nil && x.ComplianceMirrorUrl != nil {
+ return *x.ComplianceMirrorUrl
+ }
+ return ""
+}
+
+func (x *ThirdParty) GetHomepage() string {
+ if x != nil && x.Homepage != nil {
+ return *x.Homepage
+ }
+ return ""
+}
+
+// URL associated with a third-party package.
+type URL struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The type of resource this URL identifies.
+ Type *URL_Type `protobuf:"varint,1,opt,name=type,enum=project_metadata.URL_Type" json:"type,omitempty"`
+ // The actual URL value. URLs should be absolute and start with 'http://' or
+ // 'https://' (or occasionally 'git://' or 'ftp://' where appropriate).
+ Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
+}
+
+func (x *URL) Reset() {
+ *x = URL{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_project_metadata_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *URL) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*URL) ProtoMessage() {}
+
+func (x *URL) ProtoReflect() protoreflect.Message {
+ mi := &file_project_metadata_proto_msgTypes[2]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use URL.ProtoReflect.Descriptor instead.
+func (*URL) Descriptor() ([]byte, []int) {
+ return file_project_metadata_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *URL) GetType() URL_Type {
+ if x != nil && x.Type != nil {
+ return *x.Type
+ }
+ return URL_HOMEPAGE
+}
+
+func (x *URL) GetValue() string {
+ if x != nil && x.Value != nil {
+ return *x.Value
+ }
+ return ""
+}
+
+// Represents a whole or partial calendar date, such as a birthday. The time of
+// day and time zone are either specified elsewhere or are insignificant. The
+// date is relative to the Gregorian Calendar. This can represent one of the
+// following:
+//
+// - A full date, with non-zero year, month, and day values.
+// - A month and day, with a zero year (for example, an anniversary).
+// - A year on its own, with a zero month and a zero day.
+// - A year and month, with a zero day (for example, a credit card expiration
+// date).
+type Date struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Year of the date. Must be from 1 to 9999, or 0 to specify a date without
+ // a year.
+ Year *int32 `protobuf:"varint,1,opt,name=year" json:"year,omitempty"`
+ // Month of a year. Must be from 1 to 12, or 0 to specify a year without a
+ // month and day.
+ Month *int32 `protobuf:"varint,2,opt,name=month" json:"month,omitempty"`
+ // Day of a month. Must be from 1 to 31 and valid for the year and month, or 0
+ // to specify a year by itself or a year and month where the day isn't
+ // significant.
+ Day *int32 `protobuf:"varint,3,opt,name=day" json:"day,omitempty"`
+}
+
+func (x *Date) Reset() {
+ *x = Date{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_project_metadata_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Date) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Date) ProtoMessage() {}
+
+func (x *Date) ProtoReflect() protoreflect.Message {
+ mi := &file_project_metadata_proto_msgTypes[3]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Date.ProtoReflect.Descriptor instead.
+func (*Date) Descriptor() ([]byte, []int) {
+ return file_project_metadata_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *Date) GetYear() int32 {
+ if x != nil && x.Year != nil {
+ return *x.Year
+ }
+ return 0
+}
+
+func (x *Date) GetMonth() int32 {
+ if x != nil && x.Month != nil {
+ return *x.Month
+ }
+ return 0
+}
+
+func (x *Date) GetDay() int32 {
+ if x != nil && x.Day != nil {
+ return *x.Day
+ }
+ return 0
+}
+
+var File_project_metadata_proto protoreflect.FileDescriptor
+
+var file_project_metadata_proto_rawDesc = []byte{
+ 0x0a, 0x16, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61,
+ 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
+ 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x7f, 0x0a, 0x08, 0x4d, 0x65,
+ 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, 0x0b,
+ 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28,
+ 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x52,
+ 0x0a, 0x74, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x22, 0xd6, 0x02, 0x0a, 0x0a,
+ 0x54, 0x68, 0x69, 0x72, 0x64, 0x50, 0x61, 0x72, 0x74, 0x79, 0x12, 0x27, 0x0a, 0x03, 0x75, 0x72,
+ 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
+ 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x55, 0x52, 0x4c, 0x52, 0x03,
+ 0x75, 0x72, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x42, 0x0a,
+ 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x5f, 0x64, 0x61,
+ 0x74, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x6a, 0x65,
+ 0x63, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x65,
+ 0x52, 0x0f, 0x6c, 0x61, 0x73, 0x74, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x44, 0x61, 0x74,
+ 0x65, 0x12, 0x40, 0x0a, 0x0c, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70,
+ 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63,
+ 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4c, 0x69, 0x63, 0x65, 0x6e,
+ 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x54,
+ 0x79, 0x70, 0x65, 0x12, 0x2f, 0x0a, 0x13, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x6d, 0x6f, 0x64,
+ 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x12, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+ 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e,
+ 0x63, 0x65, 0x5f, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0c, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x13, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x4d,
+ 0x69, 0x72, 0x72, 0x6f, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x6d, 0x65,
+ 0x70, 0x61, 0x67, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x6d, 0x65,
+ 0x70, 0x61, 0x67, 0x65, 0x22, 0xbb, 0x01, 0x0a, 0x03, 0x55, 0x52, 0x4c, 0x12, 0x2e, 0x0a, 0x04,
+ 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f,
+ 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x55, 0x52,
+ 0x4c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05,
+ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
+ 0x75, 0x65, 0x22, 0x6e, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0c, 0x0a, 0x08, 0x48, 0x4f,
+ 0x4d, 0x45, 0x50, 0x41, 0x47, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x52, 0x43, 0x48,
+ 0x49, 0x56, 0x45, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x47, 0x49, 0x54, 0x10, 0x03, 0x12, 0x07,
+ 0x0a, 0x03, 0x53, 0x56, 0x4e, 0x10, 0x07, 0x12, 0x06, 0x0a, 0x02, 0x48, 0x47, 0x10, 0x08, 0x12,
+ 0x09, 0x0a, 0x05, 0x44, 0x41, 0x52, 0x43, 0x53, 0x10, 0x09, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x49,
+ 0x50, 0x45, 0x52, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x4f, 0x54, 0x48, 0x45, 0x52, 0x10, 0x0b,
+ 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x5f, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45,
+ 0x10, 0x06, 0x22, 0x42, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x79, 0x65,
+ 0x61, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x79, 0x65, 0x61, 0x72, 0x12, 0x14,
+ 0x0a, 0x05, 0x6d, 0x6f, 0x6e, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d,
+ 0x6f, 0x6e, 0x74, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x05, 0x52, 0x03, 0x64, 0x61, 0x79, 0x2a, 0x97, 0x01, 0x0a, 0x0b, 0x4c, 0x69, 0x63, 0x65, 0x6e,
+ 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x42, 0x59, 0x5f, 0x45, 0x58, 0x43,
+ 0x45, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4f, 0x4e, 0x4c, 0x59, 0x10, 0x01, 0x12, 0x0a, 0x0a,
+ 0x06, 0x4e, 0x4f, 0x54, 0x49, 0x43, 0x45, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x50, 0x45, 0x52,
+ 0x4d, 0x49, 0x53, 0x53, 0x49, 0x56, 0x45, 0x10, 0x03, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x43,
+ 0x49, 0x50, 0x52, 0x4f, 0x43, 0x41, 0x4c, 0x10, 0x04, 0x12, 0x23, 0x0a, 0x1f, 0x52, 0x45, 0x53,
+ 0x54, 0x52, 0x49, 0x43, 0x54, 0x45, 0x44, 0x5f, 0x49, 0x46, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x49,
+ 0x43, 0x41, 0x4c, 0x4c, 0x59, 0x5f, 0x4c, 0x49, 0x4e, 0x4b, 0x45, 0x44, 0x10, 0x05, 0x12, 0x0e,
+ 0x0a, 0x0a, 0x52, 0x45, 0x53, 0x54, 0x52, 0x49, 0x43, 0x54, 0x45, 0x44, 0x10, 0x06, 0x12, 0x10,
+ 0x0a, 0x0c, 0x55, 0x4e, 0x45, 0x4e, 0x43, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x45, 0x44, 0x10, 0x07,
+ 0x42, 0x31, 0x5a, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e,
+ 0x67, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x2f, 0x70, 0x72, 0x6f,
+ 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f,
+}
+
+var (
+ file_project_metadata_proto_rawDescOnce sync.Once
+ file_project_metadata_proto_rawDescData = file_project_metadata_proto_rawDesc
+)
+
+func file_project_metadata_proto_rawDescGZIP() []byte {
+ file_project_metadata_proto_rawDescOnce.Do(func() {
+ file_project_metadata_proto_rawDescData = protoimpl.X.CompressGZIP(file_project_metadata_proto_rawDescData)
+ })
+ return file_project_metadata_proto_rawDescData
+}
+
+var file_project_metadata_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
+var file_project_metadata_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
+var file_project_metadata_proto_goTypes = []interface{}{
+ (LicenseType)(0), // 0: project_metadata.LicenseType
+ (URL_Type)(0), // 1: project_metadata.URL.Type
+ (*Metadata)(nil), // 2: project_metadata.Metadata
+ (*ThirdParty)(nil), // 3: project_metadata.ThirdParty
+ (*URL)(nil), // 4: project_metadata.URL
+ (*Date)(nil), // 5: project_metadata.Date
+}
+var file_project_metadata_proto_depIdxs = []int32{
+ 3, // 0: project_metadata.Metadata.third_party:type_name -> project_metadata.ThirdParty
+ 4, // 1: project_metadata.ThirdParty.url:type_name -> project_metadata.URL
+ 5, // 2: project_metadata.ThirdParty.last_upgrade_date:type_name -> project_metadata.Date
+ 0, // 3: project_metadata.ThirdParty.license_type:type_name -> project_metadata.LicenseType
+ 1, // 4: project_metadata.URL.type:type_name -> project_metadata.URL.Type
+ 5, // [5:5] is the sub-list for method output_type
+ 5, // [5:5] is the sub-list for method input_type
+ 5, // [5:5] is the sub-list for extension type_name
+ 5, // [5:5] is the sub-list for extension extendee
+ 0, // [0:5] is the sub-list for field type_name
+}
+
+func init() { file_project_metadata_proto_init() }
+func file_project_metadata_proto_init() {
+ if File_project_metadata_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_project_metadata_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Metadata); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_project_metadata_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ThirdParty); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_project_metadata_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*URL); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_project_metadata_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Date); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_project_metadata_proto_rawDesc,
+ NumEnums: 2,
+ NumMessages: 4,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_project_metadata_proto_goTypes,
+ DependencyIndexes: file_project_metadata_proto_depIdxs,
+ EnumInfos: file_project_metadata_proto_enumTypes,
+ MessageInfos: file_project_metadata_proto_msgTypes,
+ }.Build()
+ File_project_metadata_proto = out.File
+ file_project_metadata_proto_rawDesc = nil
+ file_project_metadata_proto_goTypes = nil
+ file_project_metadata_proto_depIdxs = nil
+}
diff --git a/compliance/project_metadata_proto/project_metadata.proto b/compliance/project_metadata_proto/project_metadata.proto
new file mode 100644
index 0000000..94cc516
--- /dev/null
+++ b/compliance/project_metadata_proto/project_metadata.proto
@@ -0,0 +1,225 @@
+// 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.
+
+// A proto definition used to parse METADATA file in third party projects.
+
+// This proto will only contain fields and values used by android compliance.
+// It is not intended to be the formal definition of METADATA file.
+
+// See google3/third_party/metadata.proto if you need to add more stuff to
+// match upstream. Do not add new fields and values here. Add them upstream
+// when necessary, and copy them here.
+
+syntax = "proto2"; // As long as upstream is proto2...
+
+package project_metadata;
+option go_package = "android/soong/compliance/project_metadata_proto";
+
+// Definitions for project metadata. (go/thirdparty/metadata)
+
+// Special naming conventions:
+// Repeated fields should have singular names (instead of plural).
+
+message Metadata {
+ // Name of this API/package.
+ optional string name = 1;
+
+ // A short description (a few lines) of the package. It will be
+ // included on the summary page.
+ // Example: "Handles location lookups, throttling, batching, etc."
+ optional string description = 3;
+
+ // Specifies additional data about third-party packages.
+ optional ThirdParty third_party = 13;
+}
+
+message ThirdParty {
+ // The name and description for the package should be specified using the top
+ // level fields in MetaData above
+ //
+ // Description should only specify a short description (a few lines) of the
+ // packages. Instructions for maintainers or similar information should be
+ // specified in BUILD comments, a separate README.md file, etc.
+
+ // URL(s) associated with the package.
+ //
+ // At a minimum, all packages must specify a URL which identifies where it
+ // came from, containing a type of: ARCHIVE, GIT, PIPER, or OTHER. Typically,
+ // a package should contain only a single URL from these types. Occasionally,
+ // a package may be broken across multiple archive files for whatever reason,
+ // in which case having multiple ARCHIVE URLs is okay. However, this should
+ // not be used to combine different logical packages that are versioned and
+ // possibly licensed differently.
+ repeated URL url = 1;
+
+ // The package version. In order of preference, this should contain:
+ // - If the package comes from Git or another source control system,
+ // a specific tag or revision in source control, such as "r123" or
+ // "58e27d2". This MUST NOT be a mutable ref such as a branch name.
+ // - a released package version such as "1.0", "2.3-beta", etc.
+ // - the date the package was retrieved, formatted as "As of YYYY-MM-DD".
+ optional string version = 2;
+
+ // The date of the change in which the package was last upgraded from
+ // upstream.
+ // This should only identify package upgrades from upstream, not local
+ // modifications. This may identify the date of either the original or
+ // merged change.
+ //
+ // Note: this is NOT the date that this version of the package was released
+ // externally.
+ optional Date last_upgrade_date = 10;
+
+ // License type that identifies how the package may be used. See
+ // go/thirdpartylicenses for instructions on selecting the appropriate type.
+ optional LicenseType license_type = 4;
+
+ // Description of local changes that have been made to the package. This does
+ // not need to (and in most cases should not) attempt to include an exhaustive
+ // list of all changes, but may instead direct readers to review the local
+ // commit history, a collection of patch files, a separate README.md (or
+ // similar) document, etc.
+ // Note: Use of this field to store IDs of advisories fixed with a backported
+ // patch is deprecated, use "security.mitigated_security_patch" instead.
+ optional string local_modifications = 6;
+
+ // The URL for any public mirror created for compliance purposes.
+ // See go/thirdpartylicenses#reciprocal policy for more details.
+ optional string compliance_mirror_url = 12;
+
+ // The homepage for the package. This will eventually replace
+ // `url { type: HOMEPAGE }`
+ optional string homepage = 14;
+}
+
+// URL associated with a third-party package.
+message URL {
+ enum Type {
+ // The homepage for the package. For example, "https://bazel.io/". This URL
+ // is optional, but encouraged to help disambiguate similarly named packages
+ // or to get more information about the package. This is especially helpful
+ // when no other URLs provide human readable resources (such as git:// or
+ // sso:// URLs).
+ HOMEPAGE = 1;
+
+ // The URL of the archive containing the source code for the package, for
+ // example a zip or tgz file.
+ ARCHIVE = 2;
+
+ // The URL of the upstream git repository this package is retrieved from.
+ // For example:
+ // - https://github.com/git/git.git
+ // - git://git.kernel.org/pub/scm/git/git.git
+ //
+ // Use of a git URL requires that the package "version" value must specify a
+ // specific git tag or revision.
+ GIT = 3;
+
+ // The URL of the upstream SVN repository this package is retrieved from.
+ // For example:
+ // - http://llvm.org/svn/llvm-project/llvm/
+ //
+ // Use of an SVN URL requires that the package "version" value must specify
+ // a specific SVN tag or revision.
+ SVN = 7;
+
+ // The URL of the upstream mercurial repository this package is retrieved
+ // from. For example:
+ // - https://mercurial-scm.org/repo/evolve
+ //
+ // Use of a mercurial URL requires that the package "version" value must
+ // specify a specific tag or revision.
+ HG = 8;
+
+ // The URL of the upstream darcs repository this package is retrieved
+ // from. For example:
+ // - https://hub.darcs.net/hu.dwim/hu.dwim.util
+ //
+ // Use of a DARCS URL requires that the package "version" value must
+ // specify a specific tag or revision.
+ DARCS = 9;
+
+ // The URL of the upstream piper location. This is primarily used when a
+ // package is being migrated into third_party from elsewhere in piper, or
+ // when a package is being newly developed in third_party. For newly
+ // developed packages, the PIPER URL should reference the package itself
+ // (e.g. "http://google3/third_party/my/package")
+ PIPER = 4;
+
+ // A URL that does not fit any other type. This may also indicate that the
+ // source code was received via email or some other out-of-band way. This is
+ // most commonly used with commercial software received directly from the
+ // vendor. In the case of email, the URL value can be used to provide
+ // additional information about how it was received.
+ OTHER = 11;
+
+ // The URL identifying where the local copy of the package source code can
+ // be found.
+ //
+ // Typically, the metadata files describing a package reside in the same
+ // directory as the source code for the package. In a few rare cases where
+ // they are separate, the LOCAL_SOURCE URL identifies where to find the
+ // source code. This only describes where to find the local copy of the
+ // source; there should always be an additional URL describing where the
+ // package was retrieved from.
+ //
+ // Examples:
+ // - http://google3/third_party/java_src/gerritcodereview/gerrit/
+ // - https://android.googlesource.com/platform/external/apache-http/
+ LOCAL_SOURCE = 6;
+ }
+
+ // The type of resource this URL identifies.
+ optional Type type = 1;
+
+ // The actual URL value. URLs should be absolute and start with 'http://' or
+ // 'https://' (or occasionally 'git://' or 'ftp://' where appropriate).
+ optional string value = 2;
+}
+
+// License type that identifies how the packages may be used. See
+// go/thirdpartylicenses for full explanation of each license type.
+enum LicenseType {
+ BY_EXCEPTION_ONLY = 1;
+ NOTICE = 2;
+ PERMISSIVE = 3;
+ RECIPROCAL = 4;
+ RESTRICTED_IF_STATICALLY_LINKED = 5;
+ RESTRICTED = 6;
+ UNENCUMBERED = 7;
+}
+
+
+// Represents a whole or partial calendar date, such as a birthday. The time of
+// day and time zone are either specified elsewhere or are insignificant. The
+// date is relative to the Gregorian Calendar. This can represent one of the
+// following:
+//
+// * A full date, with non-zero year, month, and day values.
+// * A month and day, with a zero year (for example, an anniversary).
+// * A year on its own, with a zero month and a zero day.
+// * A year and month, with a zero day (for example, a credit card expiration
+// date).
+message Date {
+ // Year of the date. Must be from 1 to 9999, or 0 to specify a date without
+ // a year.
+ optional int32 year = 1;
+ // Month of a year. Must be from 1 to 12, or 0 to specify a year without a
+ // month and day.
+ optional int32 month = 2;
+ // Day of a month. Must be from 1 to 31 and valid for the year and month, or 0
+ // to specify a year by itself or a year and month where the day isn't
+ // significant.
+ optional int32 day = 3;
+}
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index eefda19..609a29c 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -96,6 +96,8 @@
// quickly silence build errors. This flag should be used with caution and only as a temporary
// measure, as it masks real errors and affects performance.
RelaxUsesLibraryCheck bool
+
+ EnableUffdGc bool // preopt with the assumption that userfaultfd GC will be used on device.
}
var allPlatformSystemServerJarsKey = android.NewOnceKey("allPlatformSystemServerJars")
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index fdfd22e..e3404a5 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -495,6 +495,10 @@
cmd.FlagWithInput("--profile-file=", profile)
}
+ if global.EnableUffdGc {
+ cmd.Flag("--runtime-arg").Flag("-Xgc:CMC")
+ }
+
rule.Install(odexPath, odexInstallPath)
rule.Install(vdexPath, vdexInstallPath)
}
diff --git a/docs/perf.md b/docs/perf.md
index 694dcf1..5b53c8d 100644
--- a/docs/perf.md
+++ b/docs/perf.md
@@ -42,16 +42,29 @@
```
If the elapsed time is much longer than the critical path then additional
-parallelism on the build machine will improve total build times. If there are
+parallelism on the build machine will improve total build times. If there are
long individual times listed in the critical path then improving build times
for those steps or adjusting dependencies so that those steps can run earlier
in the build graph will improve total build times.
### Soong
-Soong can be traced and profiled using the standard Go tools. It understands
-the `-cpuprofile`, `-trace`, and `-memprofile` command line arguments, but we
-don't currently have an easy way to enable them in the context of a full build.
+Soong proper (i.e., `soong_build` executable that processes the blueprint
+files) can be traced and profiled using the standard Go tools. It understands
+the `-trace`, `-cpuprofile`, and `-memprofile` command line arguments.
+Setting `SOONG_PROFILE_CPU` and/or `SOONG_PROFILE_MEM` environment variables
+for the build enables respective profiling, e.g., running
+
+```shell
+SOONG_PROFILE_CPU=/tmp/foo m ..._
+```
+
+saves CPU profile for each Soong invocation in /tmp/foo._step_ file, where
+_step_ is Soong execution step. The main step is `build`. The others as
+`bp2build_files`, `bp2build_workspace`, `modulegraph`, `queryview`,
+`api_bp2build`, `soong_docs` (not all of them necessarily run during the build).
+The profiles can be inspected with `go tool pprof` from the command line or
+with _Run>Open Profiler Snapshot_ in IntelliJ IDEA.
### Kati
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 362a8ef..baad58e 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -296,27 +296,37 @@
}
func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- if p.properties.Src == nil {
- ctx.PropertyErrorf("src", "missing prebuilt source file")
- return
- }
- p.sourceFilePath = android.PathForModuleSrc(ctx, proptools.String(p.properties.Src))
-
- // Determine the output file basename.
- // If Filename is set, use the name specified by the property.
- // If Filename_from_src is set, use the source file name.
- // Otherwise use the module name.
filename := proptools.String(p.properties.Filename)
filenameFromSrc := proptools.Bool(p.properties.Filename_from_src)
- if filename != "" {
- if filenameFromSrc {
- ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
- return
+ if p.properties.Src != nil {
+ p.sourceFilePath = android.PathForModuleSrc(ctx, proptools.String(p.properties.Src))
+
+ // Determine the output file basename.
+ // If Filename is set, use the name specified by the property.
+ // If Filename_from_src is set, use the source file name.
+ // Otherwise use the module name.
+ if filename != "" {
+ if filenameFromSrc {
+ ctx.PropertyErrorf("filename_from_src", "filename is set. filename_from_src can't be true")
+ return
+ }
+ } else if filenameFromSrc {
+ filename = p.sourceFilePath.Base()
+ } else {
+ filename = ctx.ModuleName()
}
- } else if filenameFromSrc {
- filename = p.sourceFilePath.Base()
+ } else if ctx.Config().AllowMissingDependencies() {
+ // If no srcs was set and AllowMissingDependencies is enabled then
+ // mark the module as missing dependencies and set a fake source path
+ // and file name.
+ ctx.AddMissingDependencies([]string{"MISSING_PREBUILT_SRC_FILE"})
+ p.sourceFilePath = android.PathForModuleSrc(ctx)
+ if filename == "" {
+ filename = ctx.ModuleName()
+ }
} else {
- filename = ctx.ModuleName()
+ ctx.PropertyErrorf("src", "missing prebuilt source file")
+ return
}
p.outputFilePath = android.PathForModuleOut(ctx, filename).OutputPath
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index cf1f6d7..a6477dd 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -195,6 +195,30 @@
}
}
+func TestPrebuiltEtcAllowMissingDependencies(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForPrebuiltEtcTest,
+ android.PrepareForTestDisallowNonExistentPaths,
+ android.FixtureModifyConfig(
+ func(config android.Config) {
+ config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
+ }),
+ ).RunTestWithBp(t, `
+ prebuilt_etc {
+ name: "foo.conf",
+ filename_from_src: true,
+ arch: {
+ x86: {
+ src: "x86.conf",
+ },
+ },
+ }
+ `)
+
+ android.AssertStringEquals(t, "expected error rule", "android/soong/android.Error",
+ result.ModuleForTests("foo.conf", "android_arm64_armv8-a").Output("foo.conf").Rule.String())
+}
+
func TestPrebuiltRootInstallDirPath(t *testing.T) {
result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
prebuilt_root {
diff --git a/filesystem/avb_add_hash_footer.go b/filesystem/avb_add_hash_footer.go
index af3bdbe..1ee0edc 100644
--- a/filesystem/avb_add_hash_footer.go
+++ b/filesystem/avb_add_hash_footer.go
@@ -23,10 +23,6 @@
"android/soong/android"
)
-func init() {
- android.RegisterModuleType("avb_add_hash_footer", avbAddHashFooterFactory)
-}
-
type avbAddHashFooter struct {
android.ModuleBase
@@ -36,6 +32,17 @@
installDir android.InstallPath
}
+type avbProp struct {
+ // Name of a property
+ Name *string
+
+ // Value of a property. Can't be used together with `file`.
+ Value *string
+
+ // File from which the value of the prop is read from. Can't be used together with `value`.
+ File *string `android:"path,arch_variant"`
+}
+
type avbAddHashFooterProperties struct {
// Source file of this image. Can reference a genrule type module with the ":module" syntax.
Src *string `android:"path,arch_variant"`
@@ -57,6 +64,9 @@
// The salt in hex. Required for reproducible builds.
Salt *string
+
+ // List of properties to add to the footer
+ Props []avbProp
}
// The AVB footer adds verification information to the image.
@@ -106,6 +116,10 @@
}
cmd.FlagWithArg("--salt ", proptools.String(a.properties.Salt))
+ for _, prop := range a.properties.Props {
+ addAvbProp(ctx, cmd, prop)
+ }
+
cmd.FlagWithOutput("--image ", a.output)
builder.Build("avbAddHashFooter", fmt.Sprintf("avbAddHashFooter %s", ctx.ModuleName()))
@@ -114,6 +128,32 @@
ctx.InstallFile(a.installDir, a.installFileName(), a.output)
}
+func addAvbProp(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, prop avbProp) {
+ name := proptools.String(prop.Name)
+ value := proptools.String(prop.Value)
+ file := proptools.String(prop.File)
+ if name == "" {
+ ctx.PropertyErrorf("name", "can't be empty")
+ return
+ }
+ if value == "" && file == "" {
+ ctx.PropertyErrorf("value", "either value or file should be set")
+ return
+ }
+ if value != "" && file != "" {
+ ctx.PropertyErrorf("value", "value and file can't be set at the same time")
+ return
+ }
+
+ if value != "" {
+ cmd.FlagWithArg("--prop ", proptools.ShellEscape(fmt.Sprintf("%s:%s", name, value)))
+ } else {
+ p := android.PathForModuleSrc(ctx, file)
+ cmd.Input(p)
+ cmd.FlagWithArg("--prop_from_file ", proptools.ShellEscape(fmt.Sprintf("%s:%s", name, cmd.PathForInput(p))))
+ }
+}
+
var _ android.AndroidMkEntriesProvider = (*avbAddHashFooter)(nil)
// Implements android.AndroidMkEntriesProvider
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 6e1e78a..1365d4a 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -34,6 +34,7 @@
func registerBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("android_filesystem", filesystemFactory)
ctx.RegisterModuleType("android_system_image", systemImageFactory)
+ ctx.RegisterModuleType("avb_add_hash_footer", avbAddHashFooterFactory)
}
type filesystem struct {
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index cda06d9..9bfcc3d 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -125,3 +125,37 @@
module := result.ModuleForTests("myfilesystem", "android_common").Module().(*systemImage)
android.AssertDeepEquals(t, "entries should have foo only", []string{"components/foo"}, module.entries)
}
+
+func TestAvbAddHashFooter(t *testing.T) {
+ result := fixture.RunTestWithBp(t, `
+ avb_add_hash_footer {
+ name: "myfooter",
+ src: "input.img",
+ filename: "output.img",
+ partition_name: "mypartition",
+ private_key: "mykey",
+ salt: "1111",
+ props: [
+ {
+ name: "prop1",
+ value: "value1",
+ },
+ {
+ name: "prop2",
+ file: "value_file",
+ },
+ ],
+ }
+ `)
+ cmd := result.ModuleForTests("myfooter", "android_arm64_armv8-a").Rule("avbAddHashFooter").RuleParams.Command
+ android.AssertStringDoesContain(t, "Can't find correct --partition_name argument",
+ cmd, "--partition_name mypartition")
+ android.AssertStringDoesContain(t, "Can't find correct --key argument",
+ cmd, "--key mykey")
+ android.AssertStringDoesContain(t, "Can't find --salt argument",
+ cmd, "--salt 1111")
+ android.AssertStringDoesContain(t, "Can't find --prop argument",
+ cmd, "--prop 'prop1:value1'")
+ android.AssertStringDoesContain(t, "Can't find --prop_from_file argument",
+ cmd, "--prop_from_file 'prop2:value_file'")
+}
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index c8cd21b..5e5769b 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -151,6 +151,8 @@
// If there's a Java fuzzer with JNI, a different version of Jazzer would
// need to be added to the fuzzer package than one without JNI
IsJni *bool `json:"is_jni,omitempty"`
+ // List of modules for monitoring coverage drops in directories (e.g. "libicu")
+ Target_modules []string `json:"target_modules,omitempty"`
}
type FuzzFrameworks struct {
@@ -379,42 +381,3 @@
sort.Strings(fuzzTargets)
ctx.Strict(targets, strings.Join(fuzzTargets, " "))
}
-
-// CollectAllSharedDependencies performs a breadth-first search over the provided module's
-// dependencies using `visitDirectDeps` to enumerate all shared library
-// dependencies. We require breadth-first expansion, as otherwise we may
-// incorrectly use the core libraries (sanitizer runtimes, libc, libdl, etc.)
-// from a dependency. This may cause issues when dependencies have explicit
-// sanitizer tags, as we may get a dependency on an unsanitized libc, etc.
-func CollectAllSharedDependencies(ctx android.SingletonContext, module android.Module, unstrippedOutputFile func(module android.Module) android.Path, isValidSharedDependency func(dependency android.Module) bool) android.Paths {
- var fringe []android.Module
-
- seen := make(map[string]bool)
-
- // Enumerate the first level of dependencies, as we discard all non-library
- // modules in the BFS loop below.
- ctx.VisitDirectDeps(module, func(dep android.Module) {
- if isValidSharedDependency(dep) {
- fringe = append(fringe, dep)
- }
- })
-
- var sharedLibraries android.Paths
-
- for i := 0; i < len(fringe); i++ {
- module := fringe[i]
- if seen[module.Name()] {
- continue
- }
- seen[module.Name()] = true
-
- sharedLibraries = append(sharedLibraries, unstrippedOutputFile(module))
- ctx.VisitDirectDeps(module, func(dep android.Module) {
- if isValidSharedDependency(dep) && !seen[dep.Name()] {
- fringe = append(fringe, dep)
- }
- })
- }
-
- return sharedLibraries
-}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index d4ed363..14895c9 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -875,7 +875,7 @@
type genRuleProperties struct {
// names of the output files that will be generated
- Out []string `android:"arch_variant"`
+ Out []string
}
type bazelGenruleAttributes struct {
@@ -893,11 +893,27 @@
tools_prop.Append(tool_files_prop)
tools := bazel.MakeLabelListAttribute(tools_prop)
- srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Srcs))
+ srcs := bazel.LabelListAttribute{}
+ srcs_labels := bazel.LabelList{}
+ // Only cc_genrule is arch specific
+ if ctx.ModuleType() == "cc_genrule" {
+ for axis, configToProps := range m.GetArchVariantProperties(ctx, &generatorProperties{}) {
+ for config, props := range configToProps {
+ if props, ok := props.(*generatorProperties); ok {
+ labels := android.BazelLabelForModuleSrcExcludes(ctx, props.Srcs, props.Exclude_srcs)
+ srcs_labels.Append(labels)
+ srcs.SetSelectValue(axis, config, labels)
+ }
+ }
+ }
+ } else {
+ srcs_labels = android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
+ srcs = bazel.MakeLabelListAttribute(srcs_labels)
+ }
var allReplacements bazel.LabelList
allReplacements.Append(tools.Value)
- allReplacements.Append(srcs.Value)
+ allReplacements.Append(bazel.FirstUniqueBazelLabelList(srcs_labels))
// Replace in and out variables with $< and $@
var cmd string
diff --git a/go.mod b/go.mod
index 8c1a9f0..7239f6d 100644
--- a/go.mod
+++ b/go.mod
@@ -1,19 +1,21 @@
module android/soong
-require google.golang.org/protobuf v0.0.0
+require (
+ google.golang.org/protobuf v0.0.0
+ github.com/google/blueprint v0.0.0
+ prebuilts/bazel/common/proto/analysis_v2 v0.0.0
+ prebuilts/bazel/common/proto/build v0.0.0 // indirect
+)
-require github.com/google/blueprint v0.0.0
-
-replace google.golang.org/protobuf v0.0.0 => ../../external/golang-protobuf
-
-replace github.com/google/blueprint v0.0.0 => ../blueprint
+replace (
+ google.golang.org/protobuf v0.0.0 => ../../external/golang-protobuf
+ github.com/google/blueprint v0.0.0 => ../blueprint
+ github.com/google/go-cmp v0.5.5 => ../../external/go-cmp
+ prebuilts/bazel/common/proto/analysis_v2 => ../../prebuilts/bazel/common/proto/analysis_v2
+ prebuilts/bazel/common/proto/build => ../../prebuilts/bazel/common/proto/build
+)
// Indirect deps from golang-protobuf
exclude github.com/golang/protobuf v1.5.0
-replace github.com/google/go-cmp v0.5.5 => ../../external/go-cmp
-
-// Indirect dep from go-cmp
-exclude golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
-
-go 1.18
+go 2.0
diff --git a/java/Android.bp b/java/Android.bp
index 1c3aed9..27a0a38 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -43,6 +43,7 @@
"dexpreopt_bootjars.go",
"dexpreopt_check.go",
"dexpreopt_config.go",
+ "dexpreopt_config_testing.go",
"droiddoc.go",
"droidstubs.go",
"fuzz.go",
@@ -87,8 +88,10 @@
"dex_test.go",
"dexpreopt_test.go",
"dexpreopt_bootjars_test.go",
+ "dexpreopt_config_test.go",
"droiddoc_test.go",
"droidstubs_test.go",
+ "fuzz_test.go",
"genrule_test.go",
"hiddenapi_singleton_test.go",
"jacoco_test.go",
diff --git a/java/aar.go b/java/aar.go
index 3aa95d4..0fdde03 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -440,7 +440,7 @@
switch depTag {
case instrumentationForTag:
// Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2.
- case libTag:
+ case sdkLibTag, libTag:
if exportPackage != nil {
sharedLibs = append(sharedLibs, exportPackage)
}
@@ -1046,7 +1046,8 @@
}
func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- commonAttrs, depLabels := a.convertLibraryAttrsBp2Build(ctx)
+ commonAttrs, bp2buildInfo := a.convertLibraryAttrsBp2Build(ctx)
+ depLabels := bp2buildInfo.DepLabels
deps := depLabels.Deps
if !commonAttrs.Srcs.IsEmpty() {
diff --git a/java/androidmk.go b/java/androidmk.go
index 75ac0e7..42b4ef1 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -17,6 +17,7 @@
import (
"fmt"
"io"
+ "strings"
"android/soong/android"
)
@@ -138,6 +139,7 @@
entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.AddStrings("LOCAL_COMPATIBILITY_SUITE", "null-suite")
androidMkWriteTestData(j.jniFilePaths, entries)
+ androidMkWriteTestData(android.Paths{j.implementationJarFile}, entries)
})
return entriesList
}
@@ -398,6 +400,19 @@
} else {
for _, jniLib := range app.jniLibs {
entries.AddStrings("LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), jniLib.name)
+ var partitionTag string
+
+ // Mimic the creation of partition_tag in build/make,
+ // which defaults to an empty string when the partition is system.
+ // Otherwise, capitalize with a leading _
+ if jniLib.partition == "system" {
+ partitionTag = ""
+ } else {
+ split := strings.Split(jniLib.partition, "/")
+ partitionTag = "_" + strings.ToUpper(split[len(split)-1])
+ }
+ entries.AddStrings("LOCAL_SOONG_JNI_LIBS_PARTITION_"+jniLib.target.Arch.ArchType.String(),
+ jniLib.name+":"+partitionTag)
}
}
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index 197da4f..1232cd1 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -19,6 +19,9 @@
"testing"
"android/soong/android"
+ "android/soong/cc"
+
+ "github.com/google/blueprint/proptools"
)
func TestRequired(t *testing.T) {
@@ -252,3 +255,149 @@
android.AssertDeepEquals(t, "overrides property", expected.overrides, actual)
}
}
+
+func TestJniPartition(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "libjni_system",
+ system_shared_libs: [],
+ sdk_version: "current",
+ stl: "none",
+ }
+
+ cc_library {
+ name: "libjni_system_ext",
+ system_shared_libs: [],
+ sdk_version: "current",
+ stl: "none",
+ system_ext_specific: true,
+ }
+
+ cc_library {
+ name: "libjni_odm",
+ system_shared_libs: [],
+ sdk_version: "current",
+ stl: "none",
+ device_specific: true,
+ }
+
+ cc_library {
+ name: "libjni_product",
+ system_shared_libs: [],
+ sdk_version: "current",
+ stl: "none",
+ product_specific: true,
+ }
+
+ cc_library {
+ name: "libjni_vendor",
+ system_shared_libs: [],
+ sdk_version: "current",
+ stl: "none",
+ soc_specific: true,
+ }
+
+ android_app {
+ name: "test_app_system_jni_system",
+ privileged: true,
+ platform_apis: true,
+ certificate: "platform",
+ jni_libs: ["libjni_system"],
+ }
+
+ android_app {
+ name: "test_app_system_jni_system_ext",
+ privileged: true,
+ platform_apis: true,
+ certificate: "platform",
+ jni_libs: ["libjni_system_ext"],
+ }
+
+ android_app {
+ name: "test_app_system_ext_jni_system",
+ privileged: true,
+ platform_apis: true,
+ certificate: "platform",
+ jni_libs: ["libjni_system"],
+ system_ext_specific: true
+ }
+
+ android_app {
+ name: "test_app_system_ext_jni_system_ext",
+ sdk_version: "core_platform",
+ jni_libs: ["libjni_system_ext"],
+ system_ext_specific: true
+ }
+
+ android_app {
+ name: "test_app_product_jni_product",
+ sdk_version: "core_platform",
+ jni_libs: ["libjni_product"],
+ product_specific: true
+ }
+
+ android_app {
+ name: "test_app_vendor_jni_odm",
+ sdk_version: "core_platform",
+ jni_libs: ["libjni_odm"],
+ soc_specific: true
+ }
+
+ android_app {
+ name: "test_app_odm_jni_vendor",
+ sdk_version: "core_platform",
+ jni_libs: ["libjni_vendor"],
+ device_specific: true
+ }
+ android_app {
+ name: "test_app_system_jni_multiple",
+ privileged: true,
+ platform_apis: true,
+ certificate: "platform",
+ jni_libs: ["libjni_system", "libjni_system_ext"],
+ }
+ android_app {
+ name: "test_app_vendor_jni_multiple",
+ sdk_version: "core_platform",
+ jni_libs: ["libjni_odm", "libjni_vendor"],
+ soc_specific: true
+ }
+ `
+ arch := "arm64"
+ ctx := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ cc.PrepareForTestWithCcDefaultModules,
+ android.PrepareForTestWithAndroidMk,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.TestProductVariables.DeviceArch = proptools.StringPtr(arch)
+ }),
+ ).
+ RunTestWithBp(t, bp)
+ testCases := []struct {
+ name string
+ partitionNames []string
+ partitionTags []string
+ }{
+ {"test_app_system_jni_system", []string{"libjni_system"}, []string{""}},
+ {"test_app_system_jni_system_ext", []string{"libjni_system_ext"}, []string{"_SYSTEM_EXT"}},
+ {"test_app_system_ext_jni_system", []string{"libjni_system"}, []string{""}},
+ {"test_app_system_ext_jni_system_ext", []string{"libjni_system_ext"}, []string{"_SYSTEM_EXT"}},
+ {"test_app_product_jni_product", []string{"libjni_product"}, []string{"_PRODUCT"}},
+ {"test_app_vendor_jni_odm", []string{"libjni_odm"}, []string{"_ODM"}},
+ {"test_app_odm_jni_vendor", []string{"libjni_vendor"}, []string{"_VENDOR"}},
+ {"test_app_system_jni_multiple", []string{"libjni_system", "libjni_system_ext"}, []string{"", "_SYSTEM_EXT"}},
+ {"test_app_vendor_jni_multiple", []string{"libjni_odm", "libjni_vendor"}, []string{"_ODM", "_VENDOR"}},
+ }
+
+ for _, test := range testCases {
+ t.Run(test.name, func(t *testing.T) {
+ mod := ctx.ModuleForTests(test.name, "android_common").Module()
+ entry := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)[0]
+ for i := range test.partitionNames {
+ actual := entry.EntryMap["LOCAL_SOONG_JNI_LIBS_PARTITION_"+arch][i]
+ expected := test.partitionNames[i] + ":" + test.partitionTags[i]
+ android.AssertStringEquals(t, "Expected and actual differ", expected, actual)
+ }
+ })
+ }
+}
diff --git a/java/app.go b/java/app.go
index 1955e2a..a822cbf 100755
--- a/java/app.go
+++ b/java/app.go
@@ -591,7 +591,7 @@
// Set a certificate to avoid panics later when accessing it.
mainCertificate = Certificate{
Key: android.PathForModuleOut(ctx, "missing.pk8"),
- Pem: android.PathForModuleOut(ctx, "missing.pem"),
+ Pem: android.PathForModuleOut(ctx, "missing.x509.pem"),
}
}
@@ -798,6 +798,7 @@
target: module.Target(),
coverageFile: dep.CoverageOutputFile(),
unstrippedFile: dep.UnstrippedOutputFile(),
+ partition: dep.Partition(),
})
} else {
ctx.ModuleErrorf("dependency %q missing output file", otherName)
@@ -1485,28 +1486,22 @@
*bazelAapt
Deps bazel.LabelListAttribute
Custom_package *string
- Certificate *bazel.Label
- Certificate_name *string
+ Certificate bazel.LabelAttribute
+ Certificate_name bazel.StringAttribute
}
// ConvertWithBp2build is used to convert android_app to Bazel.
func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- commonAttrs, depLabels := a.convertLibraryAttrsBp2Build(ctx)
+ commonAttrs, bp2BuildInfo := a.convertLibraryAttrsBp2Build(ctx)
+ depLabels := bp2BuildInfo.DepLabels
deps := depLabels.Deps
deps.Append(depLabels.StaticDeps)
aapt := a.convertAaptAttrsWithBp2Build(ctx)
- var certificate *bazel.Label
- certificateNamePtr := a.overridableAppProperties.Certificate
- certificateName := proptools.StringDefault(certificateNamePtr, "")
- certModule := android.SrcIsModule(certificateName)
- if certModule != "" {
- c := android.BazelLabelForModuleDepSingle(ctx, certificateName)
- certificate = &c
- certificateNamePtr = nil
- }
+ certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableAppProperties.Certificate)
+
attrs := &bazelAndroidAppAttributes{
commonAttrs,
aapt,
@@ -1514,7 +1509,7 @@
// TODO(b/209576404): handle package name override by product variable PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES
a.overridableAppProperties.Package_name,
certificate,
- certificateNamePtr,
+ certificateName,
}
props := bazel.BazelTargetModuleProperties{
diff --git a/java/app_import.go b/java/app_import.go
index 6e603c9..8c1e19c 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -500,7 +500,18 @@
type AndroidTestImport struct {
AndroidAppImport
- testProperties testProperties
+ testProperties struct {
+ // list of compatibility suites (for example "cts", "vts") that the module should be
+ // installed into.
+ Test_suites []string `android:"arch_variant"`
+
+ // list of files or filegroup modules that provide data that should be installed alongside
+ // the test
+ Data []string `android:"path"`
+
+ // Install the test into a folder named for the module in all test suites.
+ Per_testcase_directory *bool
+ }
testImportProperties androidTestImportProperties
diff --git a/java/app_set.go b/java/app_set.go
index 694b167..0f55b77 100644
--- a/java/app_set.go
+++ b/java/app_set.go
@@ -90,13 +90,15 @@
}
var TargetCpuAbi = map[string]string{
- "arm": "ARMEABI_V7A",
- "arm64": "ARM64_V8A",
- "x86": "X86",
- "x86_64": "X86_64",
+ "arm": "ARMEABI_V7A",
+ "arm64": "ARM64_V8A",
+ // TODO: use "RISCV64" when that is supported in bundles
+ "riscv64": "ARM64_V8A",
+ "x86": "X86",
+ "x86_64": "X86_64",
}
-func SupportedAbis(ctx android.ModuleContext) []string {
+func SupportedAbis(ctx android.ModuleContext, excludeNativeBridgeAbis bool) []string {
abiName := func(targetIdx int, deviceArch string) string {
if abi, found := TargetCpuAbi[deviceArch]; found {
return abi
@@ -107,6 +109,9 @@
var result []string
for i, target := range ctx.Config().Targets[android.Android] {
+ if target.NativeBridge == android.NativeBridgeEnabled && excludeNativeBridgeAbis {
+ continue
+ }
result = append(result, abiName(i, target.Arch.ArchType.String()))
}
return result
@@ -133,7 +138,7 @@
ImplicitOutputs: android.WritablePaths{as.packedOutput, as.apkcertsFile},
Inputs: android.Paths{as.prebuilt.SingleSourcePath(ctx)},
Args: map[string]string{
- "abis": strings.Join(SupportedAbis(ctx), ","),
+ "abis": strings.Join(SupportedAbis(ctx, false), ","),
"allow-prereleased": strconv.FormatBool(proptools.Bool(as.properties.Prerelease)),
"screen-densities": screenDensities,
"sdk-version": ctx.Config().PlatformSdkVersion().String(),
diff --git a/java/base.go b/java/base.go
index 23b4d46..5d24981 100644
--- a/java/base.go
+++ b/java/base.go
@@ -190,7 +190,7 @@
// constructing a new module.
type DeviceProperties struct {
// If not blank, set to the version of the sdk to compile against.
- // Defaults to private.
+ // Defaults to an empty string, which compiles the module against the private platform APIs.
// Values are of one of the following forms:
// 1) numerical API level, "current", "none", or "core_platform"
// 2) An SDK kind with an API level: "<sdk kind>_<API level>"
@@ -447,9 +447,11 @@
// installed file for hostdex copy
hostdexInstallFile android.InstallPath
- // list of .java files and srcjars that was passed to javac
- compiledJavaSrcs android.Paths
- compiledSrcJars android.Paths
+ // list of unique .java and .kt source files
+ uniqueSrcFiles android.Paths
+
+ // list of srcjars that was passed to javac
+ compiledSrcJars android.Paths
// manifest file to use instead of properties.Manifest
overrideManifest android.OptionalPath
@@ -530,7 +532,7 @@
// TODO(satayev): cover other types as well, e.g. imports
case *Library, *AndroidLibrary:
switch tag {
- case bootClasspathTag, libTag, staticLibTag, java9LibTag:
+ case bootClasspathTag, sdkLibTag, libTag, staticLibTag, java9LibTag:
j.checkSdkLinkType(ctx, module.(moduleWithSdkDep), tag.(dependencyTag))
}
}
@@ -591,6 +593,8 @@
return android.Paths{j.outputFile}, nil
case ".jar":
return android.Paths{j.implementationAndResourcesJar}, nil
+ case ".hjar":
+ return android.Paths{j.headerJarFile}, nil
case ".proguard_map":
if j.dexer.proguardDictionary.Valid() {
return android.Paths{j.dexer.proguardDictionary.Path()}, nil
@@ -864,7 +868,7 @@
flags = append(flags, genAidlIncludeFlags(ctx, aidlSrcs, includeDirs))
sdkVersion := (j.SdkVersion(ctx)).Kind
- defaultTrace := ((sdkVersion == android.SdkSystemServer) || (sdkVersion == android.SdkCore) || (sdkVersion == android.SdkCorePlatform))
+ defaultTrace := ((sdkVersion == android.SdkSystemServer) || (sdkVersion == android.SdkCore) || (sdkVersion == android.SdkCorePlatform) || (sdkVersion == android.SdkModule))
if proptools.BoolDefault(j.deviceProperties.Aidl.Generate_traces, defaultTrace) {
flags = append(flags, "-t")
}
@@ -893,7 +897,7 @@
epEnabled := j.properties.Errorprone.Enabled
if (ctx.Config().RunErrorProne() && epEnabled == nil) || Bool(epEnabled) {
- if config.ErrorProneClasspath == nil && ctx.Config().TestProductVariables == nil {
+ if config.ErrorProneClasspath == nil && !ctx.Config().RunningInsideUnitTest() {
ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
}
@@ -1078,15 +1082,26 @@
jarName := ctx.ModuleName() + ".jar"
- javaSrcFiles := srcFiles.FilterByExt(".java")
- var uniqueSrcFiles android.Paths
+ var uniqueJavaFiles android.Paths
set := make(map[string]bool)
- for _, v := range javaSrcFiles {
+ for _, v := range srcFiles.FilterByExt(".java") {
if _, found := set[v.String()]; !found {
set[v.String()] = true
- uniqueSrcFiles = append(uniqueSrcFiles, v)
+ uniqueJavaFiles = append(uniqueJavaFiles, v)
}
}
+ var uniqueKtFiles android.Paths
+ for _, v := range srcFiles.FilterByExt(".kt") {
+ if _, found := set[v.String()]; !found {
+ set[v.String()] = true
+ uniqueKtFiles = append(uniqueKtFiles, v)
+ }
+ }
+
+ var uniqueSrcFiles android.Paths
+ uniqueSrcFiles = append(uniqueSrcFiles, uniqueJavaFiles...)
+ uniqueSrcFiles = append(uniqueSrcFiles, uniqueKtFiles...)
+ j.uniqueSrcFiles = uniqueSrcFiles
// We don't currently run annotation processors in turbine, which means we can't use turbine
// generated header jars when an annotation processor that generates API is enabled. One
@@ -1094,7 +1109,7 @@
// is used to run all of the annotation processors.
disableTurbine := deps.disableTurbine
- // Collect .java files for AIDEGen
+ // Collect .java and .kt files for AIDEGen
j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, uniqueSrcFiles.Strings()...)
var kotlinJars android.Paths
@@ -1132,12 +1147,7 @@
flags.kotlincFlags += "$kotlincFlags"
}
- var kotlinSrcFiles android.Paths
- kotlinSrcFiles = append(kotlinSrcFiles, uniqueSrcFiles...)
- kotlinSrcFiles = append(kotlinSrcFiles, srcFiles.FilterByExt(".kt")...)
-
- // Collect .kt files for AIDEGen
- j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, srcFiles.FilterByExt(".kt").Strings()...)
+ // Collect common .kt files for AIDEGen
j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, kotlinCommonSrcFiles.Strings()...)
flags.classpath = append(flags.classpath, deps.kotlinStdlib...)
@@ -1150,7 +1160,7 @@
// Use kapt for annotation processing
kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar")
kaptResJar := android.PathForModuleOut(ctx, "kapt", "kapt-res.jar")
- kotlinKapt(ctx, kaptSrcJar, kaptResJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
+ kotlinKapt(ctx, kaptSrcJar, kaptResJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
srcJars = append(srcJars, kaptSrcJar)
kotlinJars = append(kotlinJars, kaptResJar)
// Disable annotation processing in javac, it's already been handled by kapt
@@ -1160,7 +1170,7 @@
kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
kotlinHeaderJar := android.PathForModuleOut(ctx, "kotlin_headers", jarName)
- kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, kotlinSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
+ kotlinCompile(ctx, kotlinJar, kotlinHeaderJar, uniqueSrcFiles, kotlinCommonSrcFiles, srcJars, flags)
if ctx.Failed() {
return
}
@@ -1185,8 +1195,6 @@
jars := append(android.Paths(nil), kotlinJars...)
- // Store the list of .java files that was passed to javac
- j.compiledJavaSrcs = uniqueSrcFiles
j.compiledSrcJars = srcJars
enableSharding := false
@@ -1201,12 +1209,12 @@
// with sharding enabled. See: b/77284273.
}
headerJarFileWithoutDepsOrJarjar, j.headerJarFile =
- j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinHeaderJars)
+ j.compileJavaHeader(ctx, uniqueJavaFiles, srcJars, deps, flags, jarName, kotlinHeaderJars)
if ctx.Failed() {
return
}
}
- if len(uniqueSrcFiles) > 0 || len(srcJars) > 0 {
+ if len(uniqueJavaFiles) > 0 || len(srcJars) > 0 {
hasErrorproneableFiles := false
for _, ext := range j.sourceExtensions {
if ext != ".proto" && ext != ".aidl" {
@@ -1231,7 +1239,7 @@
errorproneFlags := enableErrorproneFlags(flags)
errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
- transformJavaToClasses(ctx, errorprone, -1, uniqueSrcFiles, srcJars, errorproneFlags, nil,
+ transformJavaToClasses(ctx, errorprone, -1, uniqueJavaFiles, srcJars, errorproneFlags, nil,
"errorprone", "errorprone")
extraJarDeps = append(extraJarDeps, errorprone)
@@ -1243,8 +1251,8 @@
}
shardSize := int(*(j.properties.Javac_shard_size))
var shardSrcs []android.Paths
- if len(uniqueSrcFiles) > 0 {
- shardSrcs = android.ShardPaths(uniqueSrcFiles, shardSize)
+ if len(uniqueJavaFiles) > 0 {
+ shardSrcs = android.ShardPaths(uniqueJavaFiles, shardSize)
for idx, shardSrc := range shardSrcs {
classes := j.compileJavaClasses(ctx, jarName, idx, shardSrc,
nil, flags, extraJarDeps)
@@ -1257,7 +1265,7 @@
jars = append(jars, classes)
}
} else {
- classes := j.compileJavaClasses(ctx, jarName, -1, uniqueSrcFiles, srcJars, flags, extraJarDeps)
+ classes := j.compileJavaClasses(ctx, jarName, -1, uniqueJavaFiles, srcJars, flags, extraJarDeps)
jars = append(jars, classes)
}
if ctx.Failed() {
@@ -1955,7 +1963,7 @@
if dep, ok := module.(SdkLibraryDependency); ok {
switch tag {
- case libTag:
+ case sdkLibTag, libTag:
depHeaderJars := dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))
deps.classpath = append(deps.classpath, depHeaderJars...)
deps.dexClasspath = append(deps.dexClasspath, depHeaderJars...)
@@ -1975,7 +1983,7 @@
switch tag {
case bootClasspathTag:
deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars...)
- case libTag, instrumentationForTag:
+ case sdkLibTag, libTag, instrumentationForTag:
if _, ok := module.(*Plugin); ok {
ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a libs dependency", otherName)
}
@@ -2048,7 +2056,7 @@
}
} else if dep, ok := module.(android.SourceFileProducer); ok {
switch tag {
- case libTag:
+ case sdkLibTag, libTag:
checkProducesJars(ctx, dep)
deps.classpath = append(deps.classpath, dep.Srcs()...)
deps.dexClasspath = append(deps.classpath, dep.Srcs()...)
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index f5b5f99..3a28c59 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -264,7 +264,7 @@
//
// If it could not create the files then it will return nil. Otherwise, it will return a map from
// android.ArchType to the predefined paths of the boot image files.
- produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch
+ produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs
}
var _ commonBootclasspathFragment = (*BootclasspathFragmentModule)(nil)
@@ -583,23 +583,24 @@
// Perform hidden API processing.
hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments)
- var bootImageFilesByArch bootImageFilesByArch
+ var bootImageFiles bootImageOutputs
if imageConfig != nil {
// Delegate the production of the boot image files to a module type specific method.
common := ctx.Module().(commonBootclasspathFragment)
- bootImageFilesByArch = common.produceBootImageFiles(ctx, imageConfig)
+ bootImageFiles = common.produceBootImageFiles(ctx, imageConfig)
if shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
// Zip the boot image files up, if available. This will generate the zip file in a
// predefined location.
- buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFilesByArch)
+ buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFiles.byArch)
// Copy the dex jars of this fragment's content modules to their predefined locations.
copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule)
}
- for _, variant := range imageConfig.apexVariants() {
- arch := variant.target.Arch.ArchType.String()
+ for _, variant := range bootImageFiles.variants {
+ archType := variant.config.target.Arch.ArchType
+ arch := archType.String()
for _, install := range variant.deviceInstalls {
// Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT.
installDir := strings.TrimPrefix(filepath.Dir(install.To), "/")
@@ -620,7 +621,7 @@
// A prebuilt fragment cannot contribute to an apex.
if !android.IsModulePrebuilt(ctx.Module()) {
// Provide the apex content info.
- b.provideApexContentInfo(ctx, imageConfig, hiddenAPIOutput, bootImageFilesByArch)
+ b.provideApexContentInfo(ctx, imageConfig, hiddenAPIOutput, bootImageFiles)
}
} else {
// Versioned fragments are not needed by make.
@@ -663,7 +664,7 @@
// provideApexContentInfo creates, initializes and stores the apex content info for use by other
// modules.
-func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, hiddenAPIOutput *HiddenAPIOutput, bootImageFilesByArch bootImageFilesByArch) {
+func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, hiddenAPIOutput *HiddenAPIOutput, bootImageFiles bootImageOutputs) {
// Construct the apex content info from the config.
info := BootclasspathFragmentApexContentInfo{
// Populate the apex content info with paths to the dex jars.
@@ -674,14 +675,14 @@
info.modules = imageConfig.modules
global := dexpreopt.GetGlobalConfig(ctx)
if !global.DisableGenerateProfile {
- info.profilePathOnHost = imageConfig.profilePathOnHost
+ info.profilePathOnHost = bootImageFiles.profile
info.profileInstallPathInApex = imageConfig.profileInstallPathInApex
}
info.shouldInstallBootImageInApex = imageConfig.shouldInstallInApex()
}
- info.bootImageFilesByArch = bootImageFilesByArch
+ info.bootImageFilesByArch = bootImageFiles.byArch
// Make the apex content info available for other modules.
ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, info)
@@ -934,9 +935,9 @@
}
// produceBootImageFiles builds the boot image files from the source if it is required.
-func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch {
+func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs {
if SkipDexpreoptBootJars(ctx) {
- return nil
+ return bootImageOutputs{}
}
// Only generate the boot image if the configuration does not skip it.
@@ -948,21 +949,21 @@
//
// If it could not create the files then it will return nil. Otherwise, it will return a map from
// android.ArchType to the predefined paths of the boot image files.
-func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch {
+func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs {
global := dexpreopt.GetGlobalConfig(ctx)
if !shouldBuildBootImages(ctx.Config(), global) {
- return nil
+ return bootImageOutputs{}
}
// Bootclasspath fragment modules that are for the platform do not produce a boot image.
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
if apexInfo.IsForPlatform() {
- return nil
+ return bootImageOutputs{}
}
// Bootclasspath fragment modules that are versioned do not produce a boot image.
if android.IsModuleInVersionedSdk(ctx.Module()) {
- return nil
+ return bootImageOutputs{}
}
// Build a profile for the image config and then use that to build the boot image.
@@ -972,11 +973,11 @@
buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
// Build boot image files for the android variants.
- androidBootImageFilesByArch := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
+ bootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
// Return the boot image files for the android variants for inclusion in an APEX and to be zipped
// up for the dist.
- return androidBootImageFilesByArch
+ return bootImageFiles
}
func (b *BootclasspathFragmentModule) AndroidMkEntries() []android.AndroidMkEntries {
@@ -1277,14 +1278,14 @@
}
// produceBootImageFiles extracts the boot image files from the APEX if available.
-func (module *PrebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch {
+func (module *PrebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs {
if !shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
- return nil
+ return bootImageOutputs{}
}
di := android.FindDeapexerProviderForModule(ctx)
if di == nil {
- return nil // An error has been reported by FindDeapexerProviderForModule.
+ return bootImageOutputs{} // An error has been reported by FindDeapexerProviderForModule.
}
profile := (android.WritablePath)(nil)
@@ -1302,8 +1303,17 @@
// If the boot image files for the android variants are in the prebuilt apex, we must use those
// rather than building new ones because those boot image files are going to be used on device.
files := bootImageFilesByArch{}
+ bootImageFiles := bootImageOutputs{
+ byArch: files,
+ profile: profile,
+ }
for _, variant := range imageConfig.apexVariants() {
arch := variant.target.Arch.ArchType
+ bootImageFiles.variants = append(bootImageFiles.variants, bootImageVariantOutputs{
+ variant,
+ // No device installs needed when installed in APEX.
+ nil,
+ })
for _, toPath := range variant.imagesDeps {
apexRelativePath := apexRootRelativePathToBootImageFile(arch, toPath.Base())
// Get the path to the file that the deapexer extracted from the prebuilt apex file.
@@ -1321,11 +1331,11 @@
})
}
}
- return files
+ return bootImageFiles
} else {
if profile == nil {
ctx.ModuleErrorf("Unable to produce boot image files: neither boot image files nor profiles exists in the prebuilt apex")
- return nil
+ return bootImageOutputs{}
}
// Build boot image files for the android variants from the dex files provided by the contents
// of this module.
diff --git a/java/builder.go b/java/builder.go
index c0fadd4..b1b9a4a 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -83,9 +83,9 @@
_ = pctx.VariableFunc("kytheCuJavaSourceMax",
func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuJavaSourceMax() })
_ = pctx.SourcePathVariable("kytheVnames", "build/soong/vnames.json")
- // Run it with -add-opens=java.base/java.nio=ALL-UNNAMED to avoid JDK9's warning about
- // "Illegal reflective access by com.google.protobuf.Utf8$UnsafeProcessor ...
- // to field java.nio.Buffer.address"
+ // Run it with several --add-exports to allow the classes in the
+ // com.google.devtools.kythe.extractors.java.standalone package access the packages in the
+ // jdk.compiler compiler module. Long live Java modules.
kytheExtract = pctx.AndroidStaticRule("kythe",
blueprint.RuleParams{
Command: `${config.ZipSyncCmd} -d $srcJarDir ` +
@@ -97,7 +97,17 @@
`KYTHE_KZIP_ENCODING=${kytheCuEncoding} ` +
`KYTHE_JAVA_SOURCE_BATCH_SIZE=${kytheCuJavaSourceMax} ` +
`${config.SoongJavacWrapper} ${config.JavaCmd} ` +
+ // Avoid JDK9's warning about "Illegal reflective access by com.google.protobuf.Utf8$UnsafeProcessor ...
+ // to field java.nio.Buffer.address"
`--add-opens=java.base/java.nio=ALL-UNNAMED ` +
+ // Allow the classes in the com.google.devtools.kythe.extractors.java.standalone package
+ // access the packages in the jdk.compiler compiler module
+ `--add-opens=java.base/java.nio=ALL-UNNAMED ` +
+ `--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED ` +
+ `--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED ` +
+ `--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED ` +
+ `--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED ` +
+ `--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED ` +
`-jar ${config.JavaKytheExtractorJar} ` +
`${config.JavacHeapFlags} ${config.CommonJdkFlags} ` +
`$processorpath $processor $javacFlags $bootClasspath $classpath ` +
diff --git a/java/config/config.go b/java/config/config.go
index ea44aaa..49d88c4 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -43,6 +43,7 @@
InstrumentFrameworkModules = []string{
"framework",
"framework-minus-apex",
+ "ims-common",
"telephony-common",
"services",
"android.car",
@@ -83,7 +84,7 @@
// ErrorProne can use significantly more memory than javac alone, give it a higher heap
// size (b/221480398).
- exportedVars.ExportStringStaticVariable("ErrorProneHeapSize", "4096M")
+ exportedVars.ExportStringStaticVariable("ErrorProneHeapSize", "8192M")
exportedVars.ExportStringStaticVariable("ErrorProneHeapFlags", "-J-Xmx${ErrorProneHeapSize}")
// D8 invocations are shorter lived, so we restrict their JIT tiering relative to R8.
@@ -124,29 +125,19 @@
// This is set up and guaranteed by soong_ui
return ctx.Config().Getenv("ANDROID_JAVA_HOME")
})
- pctx.VariableFunc("Java11Home", func(ctx android.PackageVarContext) string {
- // This is set up and guaranteed by soong_ui
- return ctx.Config().Getenv("ANDROID_JAVA11_HOME")
- })
pctx.VariableFunc("JlinkVersion", func(ctx android.PackageVarContext) string {
if override := ctx.Config().Getenv("OVERRIDE_JLINK_VERSION_NUMBER"); override != "" {
return override
}
- switch ctx.Config().Getenv("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN") {
- case "true":
- return "17"
- default:
- return "11"
- }
+ return "17"
})
pctx.SourcePathVariable("JavaToolchain", "${JavaHome}/bin")
- pctx.SourcePathVariable("Java11Toolchain", "${Java11Home}/bin")
pctx.SourcePathVariableWithEnvOverride("JavacCmd",
"${JavaToolchain}/javac", "ALTERNATE_JAVAC")
pctx.SourcePathVariable("JavaCmd", "${JavaToolchain}/java")
pctx.SourcePathVariable("JarCmd", "${JavaToolchain}/jar")
- pctx.SourcePathVariable("JavadocCmd", "${Java11Toolchain}/javadoc")
+ pctx.SourcePathVariable("JavadocCmd", "${JavaToolchain}/javadoc")
pctx.SourcePathVariable("JlinkCmd", "${JavaToolchain}/jlink")
pctx.SourcePathVariable("JmodCmd", "${JavaToolchain}/jmod")
pctx.SourcePathVariable("JrtFsJar", "${JavaHome}/lib/jrt-fs.jar")
@@ -273,7 +264,7 @@
// JavadocCmd returns a SourcePath object with the path to the java command.
func JavadocCmd(ctx android.PathContext) android.SourcePath {
- return java11Tool(ctx, "javadoc")
+ return javaTool(ctx, "javadoc")
}
func javaTool(ctx android.PathContext, tool string) android.SourcePath {
@@ -287,17 +278,6 @@
}
-func java11Tool(ctx android.PathContext, tool string) android.SourcePath {
- type javaToolKey string
-
- key := android.NewCustomOnceKey(javaToolKey(tool))
-
- return ctx.Config().OnceSourcePath(key, func() android.SourcePath {
- return java11Toolchain(ctx).Join(ctx, tool)
- })
-
-}
-
var javaToolchainKey = android.NewOnceKey("javaToolchain")
func javaToolchain(ctx android.PathContext) android.SourcePath {
@@ -306,14 +286,6 @@
})
}
-var java11ToolchainKey = android.NewOnceKey("java11Toolchain")
-
-func java11Toolchain(ctx android.PathContext) android.SourcePath {
- return ctx.Config().OnceSourcePath(java11ToolchainKey, func() android.SourcePath {
- return java11Home(ctx).Join(ctx, "bin")
- })
-}
-
var javaHomeKey = android.NewOnceKey("javaHome")
func javaHome(ctx android.PathContext) android.SourcePath {
@@ -322,12 +294,3 @@
return android.PathForSource(ctx, ctx.Config().Getenv("ANDROID_JAVA_HOME"))
})
}
-
-var java11HomeKey = android.NewOnceKey("java11Home")
-
-func java11Home(ctx android.PathContext) android.SourcePath {
- return ctx.Config().OnceSourcePath(java11HomeKey, func() android.SourcePath {
- // This is set up and guaranteed by soong_ui
- return android.PathForSource(ctx, ctx.Config().Getenv("ANDROID_JAVA11_HOME"))
- })
-}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 0adaf99..77cbe9c 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -269,8 +269,10 @@
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.
+ if isSystemServerJar && moduleName(ctx) != "com.android.location.provider" {
+ // If the module is a system server jar, only preopt for the primary arch because the jar can
+ // only be loaded by system server. "com.android.location.provider" is a special case because
+ // it's also used by apps as a shared library.
targets = targets[:1]
}
}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 4e416fc..3effff6 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -228,6 +228,11 @@
}
// Target-independent description of a boot image.
+//
+// WARNING: All fields in this struct should be initialized in the genBootImageConfigs function.
+// Failure to do so can lead to data races if there is no synchronization enforced ordering between
+// the writer and the reader. Fields which break this rule are marked as deprecated and should be
+// removed and replaced with something else, e.g. providers.
type bootImageConfig struct {
// If this image is an extension, the image that it extends.
extends *bootImageConfig
@@ -268,14 +273,15 @@
zip android.WritablePath
// Rules which should be used in make to install the outputs.
+ //
+ // Deprecated: Not initialized correctly, see struct comment.
profileInstalls android.RuleBuilderInstalls
// Path to the license metadata file for the module that built the profile.
+ //
+ // Deprecated: Not initialized correctly, see struct comment.
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
@@ -284,6 +290,8 @@
}
// Target-dependent description of a boot image.
+//
+// WARNING: The warning comment on bootImageConfig applies here too.
type bootImageVariant struct {
*bootImageConfig
@@ -314,14 +322,23 @@
primaryImagesDeps android.Paths
// Rules which should be used in make to install the outputs on host.
- installs android.RuleBuilderInstalls
- vdexInstalls android.RuleBuilderInstalls
+ //
+ // Deprecated: Not initialized correctly, see struct comment.
+ installs android.RuleBuilderInstalls
+
+ // Rules which should be used in make to install the vdex outputs on host.
+ //
+ // Deprecated: Not initialized correctly, see struct comment.
+ vdexInstalls android.RuleBuilderInstalls
+
+ // Rules which should be used in make to install the unstripped outputs on host.
+ //
+ // Deprecated: Not initialized correctly, see struct comment.
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.
+ //
+ // Deprecated: Not initialized correctly, see struct comment.
licenseMetadataFile android.OptionalPath
}
@@ -548,7 +565,7 @@
// 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 {
+func buildBootImageVariantsForAndroidOs(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) bootImageOutputs {
return buildBootImageForOsType(ctx, image, profile, android.Android)
}
@@ -563,21 +580,38 @@
buildBootImageForOsType(ctx, image, profile, ctx.Config().BuildOS)
}
+// bootImageOutputs encapsulates information about boot images that were created/obtained by
+// commonBootclasspathFragment.produceBootImageFiles.
+type bootImageOutputs struct {
+ // Map from arch to the paths to the boot image files created/obtained for that arch.
+ byArch bootImageFilesByArch
+
+ variants []bootImageVariantOutputs
+
+ // The path to the profile file created/obtained for the boot image.
+ profile android.WritablePath
+}
+
// 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 {
+func buildBootImageForOsType(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath, requiredOsType android.OsType) bootImageOutputs {
filesByArch := bootImageFilesByArch{}
+ imageOutputs := bootImageOutputs{
+ byArch: filesByArch,
+ profile: profile,
+ }
for _, variant := range image.variants {
if variant.target.Os == requiredOsType {
- buildBootImageVariant(ctx, variant, profile)
+ variantOutputs := buildBootImageVariant(ctx, variant, profile)
+ imageOutputs.variants = append(imageOutputs.variants, variantOutputs)
filesByArch[variant.target.Arch.ArchType] = variant.imagesDeps.Paths()
}
}
- return filesByArch
+ return imageOutputs
}
// buildBootImageZipInPredefinedLocation generates a zip file containing all the boot image files.
@@ -605,8 +639,13 @@
rule.Build("zip_"+image.name, "zip "+image.name+" image")
}
+type bootImageVariantOutputs struct {
+ config *bootImageVariant
+ deviceInstalls android.RuleBuilderInstalls
+}
+
// Generate boot image build rules for a specific target.
-func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) {
+func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) bootImageVariantOutputs {
globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
@@ -713,6 +752,10 @@
cmd.FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch])
}
+ if global.EnableUffdGc {
+ cmd.Flag("--runtime-arg").Flag("-Xgc:CMC")
+ }
+
if global.BootFlags != "" {
cmd.Flag(global.BootFlags)
}
@@ -764,11 +807,20 @@
rule.Build(image.name+"JarsDexpreopt_"+image.target.String(), "dexpreopt "+image.name+" jars "+arch.String())
// save output and installed files for makevars
+ // TODO - these are always the same and so should be initialized in genBootImageConfigs
image.installs = rule.Installs()
image.vdexInstalls = vdexInstalls
image.unstrippedInstalls = unstrippedInstalls
- image.deviceInstalls = deviceInstalls
- image.licenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile())
+
+ // Only set the licenseMetadataFile from the active module.
+ if isActiveModule(ctx.Module()) {
+ image.licenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile())
+ }
+
+ return bootImageVariantOutputs{
+ image,
+ deviceInstalls,
+ }
}
const failureMessage = `ERROR: Dex2oat failed to compile a boot image.
@@ -824,8 +876,6 @@
rule.Build("bootJarsProfile", "profile boot jars")
- image.profilePathOnHost = profile
-
return profile
}
diff --git a/java/dexpreopt_config_test.go b/java/dexpreopt_config_test.go
new file mode 100644
index 0000000..b704d09
--- /dev/null
+++ b/java/dexpreopt_config_test.go
@@ -0,0 +1,35 @@
+// 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 java
+
+import (
+ "runtime"
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestBootImageConfig(t *testing.T) {
+ if runtime.GOOS != "linux" {
+ t.Skipf("Skipping as boot image config test is only supported on linux not %s", runtime.GOOS)
+ }
+
+ result := android.GroupFixturePreparers(
+ PrepareForBootImageConfigTest,
+ ).RunTest(t)
+
+ CheckArtBootImageConfig(t, result)
+ CheckFrameworkBootImageConfig(t, result)
+}
diff --git a/java/dexpreopt_config_testing.go b/java/dexpreopt_config_testing.go
new file mode 100644
index 0000000..1c236d8
--- /dev/null
+++ b/java/dexpreopt_config_testing.go
@@ -0,0 +1,768 @@
+// 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.
+
+// Testing support for dexpreopt config.
+//
+// The bootImageConfig/bootImageVariant structs returned by genBootImageConfigs are used in many
+// places in the build and are currently mutated in a number of those locations. This provides
+// comprehensive tests of the fields in those structs to ensure that they have been initialized
+// correctly and where relevant, mutated correctly.
+//
+// This is used in TestBootImageConfig to verify that the
+
+package java
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+
+ "android/soong/android"
+)
+
+// PrepareForBootImageConfigTest is the minimal set of preparers that are needed to be able to use
+// the Check*BootImageConfig methods define here.
+var PrepareForBootImageConfigTest = android.GroupFixturePreparers(
+ android.PrepareForTestWithArchMutator,
+ android.PrepareForTestAccessingMakeVars,
+ FixtureConfigureBootJars("com.android.art:core1", "com.android.art:core2", "platform:framework"),
+)
+
+// normalizedInstall represents a android.RuleBuilderInstall that has been normalized to remove
+// test specific parts of the From path.
+type normalizedInstall struct {
+ from string
+ to string
+}
+
+// normalizeInstalls converts a slice of android.RuleBuilderInstall into a slice of
+// normalizedInstall to allow them to be compared using android.AssertDeepEquals.
+func normalizeInstalls(installs android.RuleBuilderInstalls) []normalizedInstall {
+ var normalized []normalizedInstall
+ for _, install := range installs {
+ normalized = append(normalized, normalizedInstall{
+ from: install.From.RelativeToTop().String(),
+ to: install.To,
+ })
+ }
+ return normalized
+}
+
+// assertInstallsEqual normalized the android.RuleBuilderInstalls and compares against the expected
+// normalizedInstalls.
+func assertInstallsEqual(t *testing.T, message string, expected []normalizedInstall, actual android.RuleBuilderInstalls) {
+ t.Helper()
+ normalizedActual := normalizeInstalls(actual)
+ android.AssertDeepEquals(t, message, expected, normalizedActual)
+}
+
+// expectedConfig encapsulates the expected properties that will be set in a bootImageConfig
+//
+// Each field <x> in here is compared against the corresponding field <x> in bootImageConfig.
+type expectedConfig struct {
+ name string
+ stem string
+ dir string
+ symbolsDir string
+ installDirOnDevice string
+ installDirOnHost string
+ profileInstallPathInApex string
+ modules android.ConfiguredJarList
+ dexPaths []string
+ dexPathsDeps []string
+ zip string
+ variants []*expectedVariant
+
+ // Mutated fields
+ profileInstalls []normalizedInstall
+ profileLicenseMetadataFile string
+}
+
+// expectedVariant encapsulates the expected properties that will be set in a bootImageVariant
+//
+// Each field <x> in here is compared against the corresponding field <x> in bootImageVariant
+// except for archType which is compared against the target.Arch.ArchType field in bootImageVariant.
+type expectedVariant struct {
+ archType android.ArchType
+ dexLocations []string
+ dexLocationsDeps []string
+ imagePathOnHost string
+ imagePathOnDevice string
+ imagesDeps []string
+ primaryImages string
+ primaryImagesDeps []string
+
+ // Mutated fields
+ installs []normalizedInstall
+ vdexInstalls []normalizedInstall
+ unstrippedInstalls []normalizedInstall
+ licenseMetadataFile string
+}
+
+// CheckArtBootImageConfig checks the status of the fields of the bootImageConfig and
+// bootImageVariant structures that are returned from artBootImageConfig.
+//
+// This is before any fields are mutated.
+func CheckArtBootImageConfig(t *testing.T, result *android.TestResult) {
+ checkArtBootImageConfig(t, result, false, "")
+}
+
+// getArtImageConfig gets the ART bootImageConfig that was created during the test.
+func getArtImageConfig(result *android.TestResult) *bootImageConfig {
+ pathCtx := &android.TestPathContext{TestResult: result}
+ imageConfig := artBootImageConfig(pathCtx)
+ return imageConfig
+}
+
+// checkArtBootImageConfig checks the ART boot image.
+//
+// mutated is true if this is called after fields in the image have been mutated by the ART
+// bootclasspath_fragment and false otherwise.
+func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated bool, expectedLicenseMetadataFile string) {
+ imageConfig := getArtImageConfig(result)
+
+ expected := &expectedConfig{
+ name: "art",
+ stem: "boot",
+ dir: "out/soong/test_device/dex_artjars",
+ symbolsDir: "out/soong/test_device/dex_artjars_unstripped",
+ installDirOnDevice: "system/framework",
+ installDirOnHost: "apex/art_boot_images/javalib",
+ profileInstallPathInApex: "etc/boot-image.prof",
+ modules: android.CreateTestConfiguredJarList([]string{"com.android.art:core1", "com.android.art:core2"}),
+ dexPaths: []string{"out/soong/test_device/dex_artjars_input/core1.jar", "out/soong/test_device/dex_artjars_input/core2.jar"},
+ dexPathsDeps: []string{"out/soong/test_device/dex_artjars_input/core1.jar", "out/soong/test_device/dex_artjars_input/core2.jar"},
+ zip: "out/soong/test_device/dex_artjars/art.zip",
+ variants: []*expectedVariant{
+ {
+ archType: android.Arm64,
+ dexLocations: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
+ dexLocationsDeps: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
+ imagePathOnHost: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art",
+ imagePathOnDevice: "/system/framework/arm64/boot.art",
+ imagesDeps: []string{
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex",
+ },
+ installs: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art",
+ to: "/apex/art_boot_images/javalib/arm64/boot.art",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat",
+ to: "/apex/art_boot_images/javalib/arm64/boot.oat",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art",
+ to: "/apex/art_boot_images/javalib/arm64/boot-core2.art",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat",
+ to: "/apex/art_boot_images/javalib/arm64/boot-core2.oat",
+ },
+ },
+ vdexInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex",
+ to: "/apex/art_boot_images/javalib/arm64/boot.vdex",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex",
+ to: "/apex/art_boot_images/javalib/arm64/boot-core2.vdex",
+ },
+ },
+ unstrippedInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot.oat",
+ to: "/apex/art_boot_images/javalib/arm64/boot.oat",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat",
+ to: "/apex/art_boot_images/javalib/arm64/boot-core2.oat",
+ },
+ },
+ licenseMetadataFile: expectedLicenseMetadataFile,
+ },
+ {
+ archType: android.Arm,
+ dexLocations: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
+ dexLocationsDeps: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"},
+ imagePathOnHost: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art",
+ imagePathOnDevice: "/system/framework/arm/boot.art",
+ imagesDeps: []string{
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex",
+ },
+ installs: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art",
+ to: "/apex/art_boot_images/javalib/arm/boot.art",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat",
+ to: "/apex/art_boot_images/javalib/arm/boot.oat",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art",
+ to: "/apex/art_boot_images/javalib/arm/boot-core2.art",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat",
+ to: "/apex/art_boot_images/javalib/arm/boot-core2.oat",
+ },
+ },
+ vdexInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex",
+ to: "/apex/art_boot_images/javalib/arm/boot.vdex",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex",
+ to: "/apex/art_boot_images/javalib/arm/boot-core2.vdex",
+ },
+ },
+ unstrippedInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot.oat",
+ to: "/apex/art_boot_images/javalib/arm/boot.oat",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat",
+ to: "/apex/art_boot_images/javalib/arm/boot-core2.oat",
+ },
+ },
+ licenseMetadataFile: expectedLicenseMetadataFile,
+ },
+ {
+ archType: android.X86_64,
+ dexLocations: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
+ dexLocationsDeps: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
+ imagePathOnHost: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art",
+ imagePathOnDevice: "/system/framework/x86_64/boot.art",
+ imagesDeps: []string{
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex",
+ },
+ installs: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art",
+ to: "/apex/art_boot_images/javalib/x86_64/boot.art",
+ }, {
+ from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat",
+ to: "/apex/art_boot_images/javalib/x86_64/boot.oat",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art",
+ to: "/apex/art_boot_images/javalib/x86_64/boot-core2.art",
+ }, {
+ from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
+ to: "/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
+ },
+ },
+ vdexInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex",
+ to: "/apex/art_boot_images/javalib/x86_64/boot.vdex",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex",
+ to: "/apex/art_boot_images/javalib/x86_64/boot-core2.vdex",
+ },
+ },
+ unstrippedInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat",
+ to: "/apex/art_boot_images/javalib/x86_64/boot.oat",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
+ to: "/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
+ },
+ },
+ licenseMetadataFile: expectedLicenseMetadataFile,
+ },
+ {
+ archType: android.X86,
+ dexLocations: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
+ dexLocationsDeps: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"},
+ imagePathOnHost: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art",
+ imagePathOnDevice: "/system/framework/x86/boot.art",
+ imagesDeps: []string{
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex",
+ },
+ installs: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art",
+ to: "/apex/art_boot_images/javalib/x86/boot.art",
+ }, {
+ from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat",
+ to: "/apex/art_boot_images/javalib/x86/boot.oat",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art",
+ to: "/apex/art_boot_images/javalib/x86/boot-core2.art",
+ }, {
+ from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat",
+ to: "/apex/art_boot_images/javalib/x86/boot-core2.oat",
+ },
+ },
+ vdexInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex",
+ to: "/apex/art_boot_images/javalib/x86/boot.vdex",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex",
+ to: "/apex/art_boot_images/javalib/x86/boot-core2.vdex",
+ },
+ },
+ unstrippedInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat",
+ to: "/apex/art_boot_images/javalib/x86/boot.oat",
+ },
+ {
+ from: "out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat",
+ to: "/apex/art_boot_images/javalib/x86/boot-core2.oat",
+ },
+ },
+ licenseMetadataFile: expectedLicenseMetadataFile,
+ },
+ },
+ }
+
+ checkBootImageConfig(t, imageConfig, mutated, expected)
+}
+
+// getFrameworkImageConfig gets the framework bootImageConfig that was created during the test.
+func getFrameworkImageConfig(result *android.TestResult) *bootImageConfig {
+ pathCtx := &android.TestPathContext{TestResult: result}
+ imageConfig := defaultBootImageConfig(pathCtx)
+ return imageConfig
+}
+
+// CheckFrameworkBootImageConfig checks the status of the fields of the bootImageConfig and
+// bootImageVariant structures that are returned from defaultBootImageConfig.
+//
+// This is before any fields are mutated.
+func CheckFrameworkBootImageConfig(t *testing.T, result *android.TestResult) {
+ checkFrameworkBootImageConfig(t, result, false, "")
+}
+
+// checkFrameworkBootImageConfig checks the framework boot image.
+//
+// mutated is true if this is called after fields in the image have been mutated by the
+// platform_bootclasspath and false otherwise.
+func checkFrameworkBootImageConfig(t *testing.T, result *android.TestResult, mutated bool, expectedLicenseMetadataFile string) {
+ imageConfig := getFrameworkImageConfig(result)
+
+ expected := &expectedConfig{
+ name: "boot",
+ stem: "boot",
+ dir: "out/soong/test_device/dex_bootjars",
+ symbolsDir: "out/soong/test_device/dex_bootjars_unstripped",
+ installDirOnDevice: "system/framework",
+ installDirOnHost: "system/framework",
+ profileInstallPathInApex: "",
+ modules: android.CreateTestConfiguredJarList([]string{"platform:framework"}),
+ dexPaths: []string{"out/soong/test_device/dex_bootjars_input/framework.jar"},
+ dexPathsDeps: []string{"out/soong/test_device/dex_artjars_input/core1.jar", "out/soong/test_device/dex_artjars_input/core2.jar", "out/soong/test_device/dex_bootjars_input/framework.jar"},
+ zip: "out/soong/test_device/dex_bootjars/boot.zip",
+ variants: []*expectedVariant{
+ {
+ archType: android.Arm64,
+ dexLocations: []string{"/system/framework/framework.jar"},
+ dexLocationsDeps: []string{
+ "/apex/com.android.art/javalib/core1.jar",
+ "/apex/com.android.art/javalib/core2.jar",
+ "/system/framework/framework.jar",
+ },
+ imagePathOnHost: "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art",
+ imagePathOnDevice: "/system/framework/arm64/boot-framework.art",
+ imagesDeps: []string{
+ "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art",
+ "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.oat",
+ "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.vdex",
+ },
+ primaryImages: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art",
+ primaryImagesDeps: []string{
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex",
+ },
+ installs: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art",
+ to: "/system/framework/arm64/boot-framework.art",
+ },
+ {
+ from: "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.oat",
+ to: "/system/framework/arm64/boot-framework.oat",
+ },
+ },
+ vdexInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.vdex",
+ to: "/system/framework/arm64/boot-framework.vdex",
+ },
+ },
+ unstrippedInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_bootjars_unstripped/android/system/framework/arm64/boot-framework.oat",
+ to: "/system/framework/arm64/boot-framework.oat",
+ },
+ },
+ licenseMetadataFile: expectedLicenseMetadataFile,
+ },
+ {
+ archType: android.Arm,
+ dexLocations: []string{"/system/framework/framework.jar"},
+ dexLocationsDeps: []string{
+ "/apex/com.android.art/javalib/core1.jar",
+ "/apex/com.android.art/javalib/core2.jar",
+ "/system/framework/framework.jar",
+ },
+ imagePathOnHost: "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.art",
+ imagePathOnDevice: "/system/framework/arm/boot-framework.art",
+ imagesDeps: []string{
+ "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.art",
+ "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.oat",
+ "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.vdex",
+ },
+ primaryImages: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art",
+ primaryImagesDeps: []string{
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat",
+ "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex",
+ },
+ installs: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.art",
+ to: "/system/framework/arm/boot-framework.art",
+ },
+ {
+ from: "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.oat",
+ to: "/system/framework/arm/boot-framework.oat",
+ },
+ },
+ vdexInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.vdex",
+ to: "/system/framework/arm/boot-framework.vdex",
+ },
+ },
+ unstrippedInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_bootjars_unstripped/android/system/framework/arm/boot-framework.oat",
+ to: "/system/framework/arm/boot-framework.oat",
+ },
+ },
+ licenseMetadataFile: expectedLicenseMetadataFile,
+ },
+ {
+ archType: android.X86_64,
+ dexLocations: []string{"host/linux-x86/system/framework/framework.jar"},
+ dexLocationsDeps: []string{
+ "host/linux-x86/apex/com.android.art/javalib/core1.jar",
+ "host/linux-x86/apex/com.android.art/javalib/core2.jar",
+ "host/linux-x86/system/framework/framework.jar",
+ },
+ imagePathOnHost: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art",
+ imagePathOnDevice: "/system/framework/x86_64/boot-framework.art",
+ imagesDeps: []string{
+ "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art",
+ "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat",
+ "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex",
+ },
+ primaryImages: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art",
+ primaryImagesDeps: []string{
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex",
+ },
+ installs: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art",
+ to: "/system/framework/x86_64/boot-framework.art",
+ },
+ {
+ from: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat",
+ to: "/system/framework/x86_64/boot-framework.oat",
+ },
+ },
+ vdexInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex",
+ to: "/system/framework/x86_64/boot-framework.vdex",
+ },
+ },
+ unstrippedInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_bootjars_unstripped/linux_glibc/system/framework/x86_64/boot-framework.oat",
+ to: "/system/framework/x86_64/boot-framework.oat",
+ },
+ },
+ licenseMetadataFile: expectedLicenseMetadataFile,
+ },
+ {
+ archType: android.X86,
+ dexLocations: []string{"host/linux-x86/system/framework/framework.jar"},
+ dexLocationsDeps: []string{
+ "host/linux-x86/apex/com.android.art/javalib/core1.jar",
+ "host/linux-x86/apex/com.android.art/javalib/core2.jar",
+ "host/linux-x86/system/framework/framework.jar",
+ },
+ imagePathOnHost: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art",
+ imagePathOnDevice: "/system/framework/x86/boot-framework.art",
+ imagesDeps: []string{
+ "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art",
+ "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat",
+ "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex",
+ },
+ primaryImages: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art",
+ primaryImagesDeps: []string{
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat",
+ "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex",
+ },
+ installs: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art",
+ to: "/system/framework/x86/boot-framework.art",
+ },
+ {
+ from: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat",
+ to: "/system/framework/x86/boot-framework.oat",
+ },
+ },
+ vdexInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex",
+ to: "/system/framework/x86/boot-framework.vdex",
+ },
+ },
+ unstrippedInstalls: []normalizedInstall{
+ {
+ from: "out/soong/test_device/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot-framework.oat",
+ to: "/system/framework/x86/boot-framework.oat",
+ },
+ },
+ licenseMetadataFile: expectedLicenseMetadataFile,
+ },
+ },
+ profileInstalls: []normalizedInstall{
+ {from: "out/soong/test_device/dex_bootjars/boot.bprof", to: "/system/etc/boot-image.bprof"},
+ {from: "out/soong/test_device/dex_bootjars/boot.prof", to: "/system/etc/boot-image.prof"},
+ },
+ profileLicenseMetadataFile: expectedLicenseMetadataFile,
+ }
+
+ checkBootImageConfig(t, imageConfig, mutated, expected)
+}
+
+// clearMutatedFields clears fields in the expectedConfig that correspond to fields in the
+// bootImageConfig/bootImageVariant structs which are mutated outside the call to
+// genBootImageConfigs.
+//
+// This allows the resulting expectedConfig struct to be compared against the values of those boot
+// image structs immediately the call to genBootImageConfigs. If this is not called then the
+// expectedConfig struct will expect the boot image structs to have been mutated by the ART
+// bootclasspath_fragment and the platform_bootclasspath.
+func clearMutatedFields(expected *expectedConfig) {
+ expected.profileInstalls = nil
+ expected.profileLicenseMetadataFile = ""
+ for _, variant := range expected.variants {
+ variant.installs = nil
+ variant.vdexInstalls = nil
+ variant.unstrippedInstalls = nil
+ variant.licenseMetadataFile = ""
+ }
+}
+
+// checkBootImageConfig checks a boot image against the expected contents.
+//
+// If mutated is false then this will clear any mutated fields in the expected contents back to the
+// zero value so that they will match the unmodified values in the boot image.
+//
+// It runs the checks in an image specific subtest of the current test.
+func checkBootImageConfig(t *testing.T, imageConfig *bootImageConfig, mutated bool, expected *expectedConfig) {
+ if !mutated {
+ clearMutatedFields(expected)
+ }
+
+ t.Run(imageConfig.name, func(t *testing.T) {
+ nestedCheckBootImageConfig(t, imageConfig, expected)
+ })
+}
+
+// nestedCheckBootImageConfig does the work of comparing the image against the expected values and
+// is run in an image specific subtest.
+func nestedCheckBootImageConfig(t *testing.T, imageConfig *bootImageConfig, expected *expectedConfig) {
+ android.AssertStringEquals(t, "name", expected.name, imageConfig.name)
+ android.AssertStringEquals(t, "stem", expected.stem, imageConfig.stem)
+ android.AssertPathRelativeToTopEquals(t, "dir", expected.dir, imageConfig.dir)
+ android.AssertPathRelativeToTopEquals(t, "symbolsDir", expected.symbolsDir, imageConfig.symbolsDir)
+ android.AssertStringEquals(t, "installDirOnDevice", expected.installDirOnDevice, imageConfig.installDirOnDevice)
+ android.AssertStringEquals(t, "installDirOnHost", expected.installDirOnHost, imageConfig.installDirOnHost)
+ android.AssertStringEquals(t, "profileInstallPathInApex", expected.profileInstallPathInApex, imageConfig.profileInstallPathInApex)
+ android.AssertDeepEquals(t, "modules", expected.modules, imageConfig.modules)
+ android.AssertPathsRelativeToTopEquals(t, "dexPaths", expected.dexPaths, imageConfig.dexPaths.Paths())
+ android.AssertPathsRelativeToTopEquals(t, "dexPathsDeps", expected.dexPathsDeps, imageConfig.dexPathsDeps.Paths())
+ // dexPathsByModule is just a different representation of the other information in the config.
+ android.AssertPathRelativeToTopEquals(t, "zip", expected.zip, imageConfig.zip)
+ assertInstallsEqual(t, "profileInstalls", expected.profileInstalls, imageConfig.profileInstalls)
+ android.AssertStringEquals(t, "profileLicenseMetadataFile", expected.profileLicenseMetadataFile, imageConfig.profileLicenseMetadataFile.RelativeToTop().String())
+
+ android.AssertIntEquals(t, "variant count", 4, len(imageConfig.variants))
+ for i, variant := range imageConfig.variants {
+ expectedVariant := expected.variants[i]
+ t.Run(variant.target.Arch.ArchType.String(), func(t *testing.T) {
+ android.AssertDeepEquals(t, "archType", expectedVariant.archType, variant.target.Arch.ArchType)
+ android.AssertDeepEquals(t, "dexLocations", expectedVariant.dexLocations, variant.dexLocations)
+ android.AssertDeepEquals(t, "dexLocationsDeps", expectedVariant.dexLocationsDeps, variant.dexLocationsDeps)
+ android.AssertPathRelativeToTopEquals(t, "imagePathOnHost", expectedVariant.imagePathOnHost, variant.imagePathOnHost)
+ android.AssertStringEquals(t, "imagePathOnDevice", expectedVariant.imagePathOnDevice, variant.imagePathOnDevice)
+ android.AssertPathsRelativeToTopEquals(t, "imagesDeps", expectedVariant.imagesDeps, variant.imagesDeps.Paths())
+ android.AssertPathRelativeToTopEquals(t, "primaryImages", expectedVariant.primaryImages, variant.primaryImages)
+ android.AssertPathsRelativeToTopEquals(t, "primaryImagesDeps", expectedVariant.primaryImagesDeps, variant.primaryImagesDeps)
+ assertInstallsEqual(t, "installs", expectedVariant.installs, variant.installs)
+ assertInstallsEqual(t, "vdexInstalls", expectedVariant.vdexInstalls, variant.vdexInstalls)
+ assertInstallsEqual(t, "unstrippedInstalls", expectedVariant.unstrippedInstalls, variant.unstrippedInstalls)
+ android.AssertStringEquals(t, "licenseMetadataFile", expectedVariant.licenseMetadataFile, variant.licenseMetadataFile.RelativeToTop().String())
+ })
+ }
+}
+
+// CheckMutatedArtBootImageConfig checks the mutated fields in the bootImageConfig/Variant for ART.
+func CheckMutatedArtBootImageConfig(t *testing.T, result *android.TestResult, expectedLicenseMetadataFile string) {
+ checkArtBootImageConfig(t, result, true, expectedLicenseMetadataFile)
+
+ // Check the dexpreopt make vars. Do it in here as it depends on the expected license metadata
+ // file at the moment and it
+ checkDexpreoptMakeVars(t, result, expectedLicenseMetadataFile)
+}
+
+// CheckMutatedFrameworkBootImageConfig checks the mutated fields in the bootImageConfig/Variant for framework.
+func CheckMutatedFrameworkBootImageConfig(t *testing.T, result *android.TestResult, expectedLicenseMetadataFile string) {
+ checkFrameworkBootImageConfig(t, result, true, expectedLicenseMetadataFile)
+}
+
+// checkDexpreoptMakeVars checks the DEXPREOPT_ prefixed make vars produced by dexpreoptBootJars
+// singleton.
+func checkDexpreoptMakeVars(t *testing.T, result *android.TestResult, expectedLicenseMetadataFile string) {
+ vars := result.MakeVarsForTesting(func(variable android.MakeVarVariable) bool {
+ return strings.HasPrefix(variable.Name(), "DEXPREOPT_")
+ })
+
+ out := &strings.Builder{}
+ for _, v := range vars {
+ fmt.Fprintf(out, "%s=%s\n", v.Name(), android.StringRelativeToTop(result.Config, v.Value()))
+ }
+ format := `
+DEXPREOPT_BOOTCLASSPATH_DEX_FILES=out/soong/test_device/dex_artjars_input/core1.jar out/soong/test_device/dex_artjars_input/core2.jar out/soong/test_device/dex_bootjars_input/framework.jar
+DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS=/apex/com.android.art/javalib/core1.jar /apex/com.android.art/javalib/core2.jar /system/framework/framework.jar
+DEXPREOPT_BOOT_JARS_MODULES=platform:framework
+DEXPREOPT_GEN=out/host/linux-x86/bin/dexpreopt_gen
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art:/apex/art_boot_images/javalib/arm/boot.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art:/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm64=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art:/apex/art_boot_images/javalib/arm64/boot.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art:/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art:/apex/art_boot_images/javalib/x86/boot.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art:/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86_64=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art:/apex/art_boot_images/javalib/x86_64/boot.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art:/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_arm=out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.art:/system/framework/arm/boot-framework.art out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.oat:/system/framework/arm/boot-framework.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_arm64=out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art:/system/framework/arm64/boot-framework.art out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.oat:/system/framework/arm64/boot-framework.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_host_x86=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art:/system/framework/x86/boot-framework.art out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat:/system/framework/x86/boot-framework.oat
+DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_host_x86_64=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art:/system/framework/x86_64/boot-framework.art out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat:/system/framework/x86_64/boot-framework.oat
+DEXPREOPT_IMAGE_DEPS_art_arm=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex
+DEXPREOPT_IMAGE_DEPS_art_arm64=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex
+DEXPREOPT_IMAGE_DEPS_art_host_x86=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex
+DEXPREOPT_IMAGE_DEPS_art_host_x86_64=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex
+DEXPREOPT_IMAGE_DEPS_boot_arm=out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.art out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.oat out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.vdex
+DEXPREOPT_IMAGE_DEPS_boot_arm64=out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.oat out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.vdex
+DEXPREOPT_IMAGE_DEPS_boot_host_x86=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex
+DEXPREOPT_IMAGE_DEPS_boot_host_x86_64=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex
+DEXPREOPT_IMAGE_LICENSE_METADATA_art_arm=%[1]s
+DEXPREOPT_IMAGE_LICENSE_METADATA_art_arm64=%[1]s
+DEXPREOPT_IMAGE_LICENSE_METADATA_art_host_x86=%[1]s
+DEXPREOPT_IMAGE_LICENSE_METADATA_art_host_x86_64=%[1]s
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
+DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86_64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
+DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEart=/system/framework/boot.art
+DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEboot=/system/framework/boot.art:/system/framework/boot-framework.art
+DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTart=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/boot.art
+DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTboot=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/boot.art:out/soong/test_device/dex_bootjars/android/system/framework/boot-framework.art
+DEXPREOPT_IMAGE_NAMES=art boot
+DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED=out/soong/test_device/dex_bootjars/boot.bprof:/system/etc/boot-image.bprof out/soong/test_device/dex_bootjars/boot.prof:/system/etc/boot-image.prof
+DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm=out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm64=out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86=out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86_64=out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_arm=out/soong/test_device/dex_bootjars_unstripped/android/system/framework/arm/boot-framework.oat:/system/framework/arm/boot-framework.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_arm64=out/soong/test_device/dex_bootjars_unstripped/android/system/framework/arm64/boot-framework.oat:/system/framework/arm64/boot-framework.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_host_x86=out/soong/test_device/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot-framework.oat:/system/framework/x86/boot-framework.oat
+DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_host_x86_64=out/soong/test_device/dex_bootjars_unstripped/linux_glibc/system/framework/x86_64/boot-framework.oat:/system/framework/x86_64/boot-framework.oat
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex:/apex/art_boot_images/javalib/arm/boot.vdex out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex:/apex/art_boot_images/javalib/arm/boot-core2.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm64=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex:/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex:/apex/art_boot_images/javalib/arm64/boot-core2.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex:/apex/art_boot_images/javalib/x86/boot.vdex out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex:/apex/art_boot_images/javalib/x86/boot-core2.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86_64=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex:/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex:/apex/art_boot_images/javalib/x86_64/boot-core2.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_arm=out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.vdex:/system/framework/arm/boot-framework.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_arm64=out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.vdex:/system/framework/arm64/boot-framework.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_host_x86=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex:/system/framework/x86/boot-framework.vdex
+DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_host_x86_64=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex:/system/framework/x86_64/boot-framework.vdex
+DEXPREOPT_IMAGE_ZIP_art=out/soong/test_device/dex_artjars/art.zip
+DEXPREOPT_IMAGE_ZIP_boot=out/soong/test_device/dex_bootjars/boot.zip
+DEXPREOPT_IMAGE_art_arm=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art
+DEXPREOPT_IMAGE_art_arm64=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art
+DEXPREOPT_IMAGE_art_host_x86=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art
+DEXPREOPT_IMAGE_art_host_x86_64=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art
+DEXPREOPT_IMAGE_boot_arm=out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.art
+DEXPREOPT_IMAGE_boot_arm64=out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art
+DEXPREOPT_IMAGE_boot_host_x86=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art
+DEXPREOPT_IMAGE_boot_host_x86_64=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art
+`
+ expected := strings.TrimSpace(fmt.Sprintf(format, expectedLicenseMetadataFile))
+ actual := strings.TrimSpace(out.String())
+ android.AssertStringEquals(t, "vars", expected, actual)
+}
diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go
index 1c1070a..3d2c5c3 100644
--- a/java/dexpreopt_test.go
+++ b/java/dexpreopt_test.go
@@ -63,6 +63,7 @@
java_binary {
name: "foo",
srcs: ["a.java"],
+ main_class: "foo.bar.jb",
}`,
enabled: true,
},
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 15585f1..8a291ad 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -267,7 +267,7 @@
ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...)
ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules)
ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...)
- ctx.AddVariationDependencies(nil, libTag, sdkDep.classpath...)
+ ctx.AddVariationDependencies(nil, sdkLibTag, sdkDep.classpath...)
}
}
@@ -304,6 +304,9 @@
flags = append(flags, "-I"+src.String())
}
+ minSdkVersion := j.MinSdkVersion(ctx).ApiLevel.FinalOrFutureInt()
+ flags = append(flags, fmt.Sprintf("--min_sdk_version=%v", minSdkVersion))
+
return strings.Join(flags, " "), deps
}
@@ -367,7 +370,7 @@
} else {
panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName()))
}
- case libTag:
+ case libTag, sdkLibTag:
if dep, ok := module.(SdkLibraryDependency); ok {
deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...)
} else if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
diff --git a/java/droidstubs.go b/java/droidstubs.go
index d9efb40..5777b18 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -28,7 +28,7 @@
)
// The values allowed for Droidstubs' Api_levels_sdk_type
-var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib"}
+var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib", "system-server"}
func init() {
RegisterStubsBuildComponents(android.InitRegistrationContext)
@@ -134,7 +134,7 @@
// the dirs which Metalava extracts API levels annotations from.
Api_levels_annotations_dirs []string
- // the sdk kind which Metalava extracts API levels annotations from. Supports 'public', 'system' and 'module-lib' for now; defaults to public.
+ // the sdk kind which Metalava extracts API levels annotations from. Supports 'public', 'system', 'module-lib' and 'system-server'; defaults to public.
Api_levels_sdk_type *string
// the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
@@ -445,6 +445,8 @@
// for older releases. Similarly, module-lib falls back to system API.
var sdkDirs []string
switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
+ case "system-server":
+ sdkDirs = []string{"system-server", "module-lib", "system", "public"}
case "module-lib":
sdkDirs = []string{"module-lib", "system", "public"}
case "system":
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 2443692..25f8c86 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -122,7 +122,7 @@
"some-other-exported-dir",
],
api_levels_annotations_enabled: true,
- api_levels_sdk_type: "%s",
+ api_levels_sdk_type: "%s",
}
`, sdkType),
map[string][]byte{
@@ -169,6 +169,21 @@
}, patterns)
}
+func TestSystemServerDroidstubs(t *testing.T) {
+ patterns := getAndroidJarPatternsForDroidstubs(t, "system-server")
+
+ android.AssertArrayString(t, "order of patterns", []string{
+ "--android-jar-pattern somedir/%/system-server/android.jar",
+ "--android-jar-pattern someotherdir/%/system-server/android.jar",
+ "--android-jar-pattern somedir/%/module-lib/android.jar",
+ "--android-jar-pattern someotherdir/%/module-lib/android.jar",
+ "--android-jar-pattern somedir/%/system/android.jar",
+ "--android-jar-pattern someotherdir/%/system/android.jar",
+ "--android-jar-pattern somedir/%/public/android.jar",
+ "--android-jar-pattern someotherdir/%/public/android.jar",
+ }, patterns)
+}
+
func TestDroidstubsSandbox(t *testing.T) {
ctx, _ := testJavaWithFS(t, `
genrule {
diff --git a/java/fuzz.go b/java/fuzz.go
index d0f369f..1d6b913 100644
--- a/java/fuzz.go
+++ b/java/fuzz.go
@@ -15,6 +15,7 @@
package java
import (
+ "path/filepath"
"sort"
"strings"
@@ -26,6 +27,11 @@
"android/soong/fuzz"
)
+const (
+ hostString = "host"
+ targetString = "target"
+)
+
type jniProperties struct {
// list of jni libs
Jni_libs []string
@@ -39,8 +45,10 @@
}
func RegisterJavaFuzzBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("java_fuzz_host", FuzzFactory)
- ctx.RegisterSingletonType("java_fuzz_packaging", javaFuzzPackagingFactory)
+ ctx.RegisterModuleType("java_fuzz", JavaFuzzFactory)
+ ctx.RegisterModuleType("java_fuzz_host", JavaFuzzHostFactory)
+ ctx.RegisterSingletonType("java_fuzz_host_packaging", javaFuzzHostPackagingFactory)
+ ctx.RegisterSingletonType("java_fuzz_device_packaging", javaFuzzDevicePackagingFactory)
}
type JavaFuzzLibrary struct {
@@ -55,11 +63,11 @@
// sanitized for the given sanitizer or not.
func (j *JavaFuzzLibrary) IsSanitizerEnabledForJni(ctx android.BaseModuleContext, sanitizerName string) bool {
// TODO: once b/231370928 is resolved, please uncomment the loop
- // for _, s := range j.jniProperties.Sanitizers {
- // if sanitizerName == s {
- // return true
- // }
- // }
+ // for _, s := range j.jniProperties.Sanitizers {
+ // if sanitizerName == s {
+ // return true
+ // }
+ // }
return false
}
@@ -72,7 +80,6 @@
// this will be used by the ingestion pipeline to determine the version
// of jazzer to add to the fuzzer package
j.fuzzPackagedModule.FuzzProperties.Fuzz_config.IsJni = proptools.BoolPtr(true)
-
for _, target := range mctx.MultiTargets() {
sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"})
mctx.AddFarVariationDependencies(sharedLibVariations, cc.JniFuzzLibTag, j.jniProperties.Jni_libs...)
@@ -91,17 +98,28 @@
if j.fuzzPackagedModule.FuzzProperties.Dictionary != nil {
j.fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *j.fuzzPackagedModule.FuzzProperties.Dictionary)
}
-
if j.fuzzPackagedModule.FuzzProperties.Fuzz_config != nil {
configPath := android.PathForModuleOut(ctx, "config").Join(ctx, "config.json")
android.WriteFileRule(ctx, configPath, j.fuzzPackagedModule.FuzzProperties.Fuzz_config.String())
j.fuzzPackagedModule.Config = configPath
}
- ctx.VisitDirectDepsWithTag(cc.JniFuzzLibTag, func(dep android.Module) {
+ _, sharedDeps := cc.CollectAllSharedDependencies(ctx)
+
+ for _, dep := range sharedDeps {
sharedLibInfo := ctx.OtherModuleProvider(dep, cc.SharedLibraryInfoProvider).(cc.SharedLibraryInfo)
if sharedLibInfo.SharedLibrary != nil {
- libPath := android.PathForModuleOut(ctx, sharedLibInfo.SharedLibrary.Base())
+ // The .class jars are output in slightly different locations
+ // relative to the jni libs. Therefore, for consistency across
+ // host and device fuzzers of jni lib location, we save it in a
+ // native_libs directory.
+ var relPath string
+ if sharedLibInfo.Target.Arch.ArchType.Multilib == "lib64" {
+ relPath = filepath.Join("lib64", sharedLibInfo.SharedLibrary.Base())
+ } else {
+ relPath = filepath.Join("lib", sharedLibInfo.SharedLibrary.Base())
+ }
+ libPath := android.PathForModuleOut(ctx, relPath)
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
Input: sharedLibInfo.SharedLibrary,
@@ -111,18 +129,17 @@
} else {
ctx.PropertyErrorf("jni_libs", "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
}
- })
+ }
j.Library.GenerateAndroidBuildActions(ctx)
}
-// java_fuzz builds and links sources into a `.jar` file for the host.
+// java_fuzz_host builds and links sources into a `.jar` file for the host.
//
// By default, a java_fuzz produces a `.jar` file containing `.class` files.
// This jar is not suitable for installing on a device.
-func FuzzFactory() android.Module {
+func JavaFuzzHostFactory() android.Module {
module := &JavaFuzzLibrary{}
-
module.addHostProperties()
module.AddProperties(&module.jniProperties)
module.Module.properties.Installable = proptools.BoolPtr(true)
@@ -141,23 +158,54 @@
ctx.AppendProperties(&disableLinuxBionic)
})
- module.initModuleAndImport(module)
- android.InitSdkAwareModule(module)
- InitJavaModuleMultiTargets(module, android.HostSupported)
+ InitJavaModuleMultiTargets(module, android.HostSupportedNoCross)
return module
}
-// Responsible for generating rules that package fuzz targets into
-// their architecture & target/host specific zip file.
-type javaFuzzPackager struct {
+// java_fuzz builds and links sources into a `.jar` file for the device.
+// This generates .class files in a jar which can then be instrumented before
+// fuzzing in Android Runtime (ART: Android OS on emulator or device)
+func JavaFuzzFactory() android.Module {
+ module := &JavaFuzzLibrary{}
+ module.addHostAndDeviceProperties()
+ module.AddProperties(&module.jniProperties)
+ module.Module.properties.Installable = proptools.BoolPtr(true)
+ module.AddProperties(&module.fuzzPackagedModule.FuzzProperties)
+ module.Module.dexpreopter.isTest = true
+ module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true)
+ InitJavaModuleMultiTargets(module, android.DeviceSupported)
+ return module
+}
+
+// Responsible for generating rules that package host fuzz targets into
+// a zip file.
+type javaFuzzHostPackager struct {
fuzz.FuzzPackager
}
-func javaFuzzPackagingFactory() android.Singleton {
- return &javaFuzzPackager{}
+// Responsible for generating rules that package device fuzz targets into
+// a zip file.
+type javaFuzzDevicePackager struct {
+ fuzz.FuzzPackager
}
-func (s *javaFuzzPackager) GenerateBuildActions(ctx android.SingletonContext) {
+func javaFuzzHostPackagingFactory() android.Singleton {
+ return &javaFuzzHostPackager{}
+}
+
+func javaFuzzDevicePackagingFactory() android.Singleton {
+ return &javaFuzzDevicePackager{}
+}
+
+func (s *javaFuzzHostPackager) GenerateBuildActions(ctx android.SingletonContext) {
+ generateBuildActions(&s.FuzzPackager, hostString, ctx)
+}
+
+func (s *javaFuzzDevicePackager) GenerateBuildActions(ctx android.SingletonContext) {
+ generateBuildActions(&s.FuzzPackager, targetString, ctx)
+}
+
+func generateBuildActions(s *fuzz.FuzzPackager, hostOrTargetString string, ctx android.SingletonContext) {
// Map between each architecture + host/device combination.
archDirs := make(map[fuzz.ArchOs][]fuzz.FileToZip)
@@ -171,8 +219,14 @@
return
}
- if javaFuzzModule.Target().HostCross {
- return
+ if hostOrTargetString == hostString {
+ if !javaFuzzModule.Host() {
+ return
+ }
+ } else if hostOrTargetString == targetString {
+ if javaFuzzModule.Host() || javaFuzzModule.Target().HostCross {
+ return
+ }
}
fuzzModuleValidator := fuzz.FuzzModule{
@@ -185,12 +239,7 @@
return
}
- hostOrTargetString := "target"
- if javaFuzzModule.Host() {
- hostOrTargetString = "host"
- }
archString := javaFuzzModule.Arch().ArchType.String()
-
archDir := android.PathForIntermediates(ctx, "fuzz", hostOrTargetString, archString)
archOs := fuzz.ArchOs{HostOrTarget: hostOrTargetString, Arch: archString, Dir: archDir.String()}
@@ -201,7 +250,7 @@
files = s.PackageArtifacts(ctx, module, javaFuzzModule.fuzzPackagedModule, archDir, builder)
// Add .jar
- files = append(files, fuzz.FileToZip{javaFuzzModule.outputFile, ""})
+ files = append(files, fuzz.FileToZip{javaFuzzModule.implementationJarFile, ""})
// Add jni .so files
for _, fPath := range javaFuzzModule.jniFilePaths {
@@ -217,12 +266,22 @@
s.CreateFuzzPackage(ctx, archDirs, fuzz.Java, pctx)
}
-func (s *javaFuzzPackager) MakeVars(ctx android.MakeVarsContext) {
+func (s *javaFuzzHostPackager) MakeVars(ctx android.MakeVarsContext) {
packages := s.Packages.Strings()
sort.Strings(packages)
- ctx.Strict("SOONG_JAVA_FUZZ_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
+ ctx.Strict("SOONG_JAVA_FUZZ_HOST_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
// Preallocate the slice of fuzz targets to minimize memory allocations.
- s.PreallocateSlice(ctx, "ALL_JAVA_FUZZ_TARGETS")
+ s.PreallocateSlice(ctx, "ALL_JAVA_FUZZ_HOST_TARGETS")
+}
+
+func (s *javaFuzzDevicePackager) MakeVars(ctx android.MakeVarsContext) {
+ packages := s.Packages.Strings()
+ sort.Strings(packages)
+
+ ctx.Strict("SOONG_JAVA_FUZZ_DEVICE_PACKAGING_ARCH_MODULES", strings.Join(packages, " "))
+
+ // Preallocate the slice of fuzz targets to minimize memory allocations.
+ s.PreallocateSlice(ctx, "ALL_JAVA_FUZZ_DEVICE_TARGETS")
}
diff --git a/java/fuzz_test.go b/java/fuzz_test.go
index 0a2c945..186c3aa 100644
--- a/java/fuzz_test.go
+++ b/java/fuzz_test.go
@@ -65,9 +65,8 @@
osCommonTarget := result.Config.BuildOSCommonTarget.String()
- osCommonTargetWithSan := osCommonTarget + "_asan" + "_fuzzer"
- javac := result.ModuleForTests("foo", osCommonTargetWithSan).Rule("javac")
- combineJar := result.ModuleForTests("foo", osCommonTargetWithSan).Description("for javac")
+ javac := result.ModuleForTests("foo", osCommonTarget).Rule("javac")
+ combineJar := result.ModuleForTests("foo", osCommonTarget).Description("for javac")
if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
@@ -85,11 +84,11 @@
}
ctx := result.TestContext
- foo := ctx.ModuleForTests("foo", osCommonTargetWithSan).Module().(*JavaFuzzLibrary)
+ foo := ctx.ModuleForTests("foo", osCommonTarget).Module().(*JavaFuzzLibrary)
- expected := "libjni.so"
+ expected := "lib64/libjni.so"
if runtime.GOOS == "darwin" {
- expected = "libjni.dylib"
+ expected = "lib64/libjni.dylib"
}
fooJniFilePaths := foo.jniFilePaths
diff --git a/java/java.go b/java/java.go
index d04e52a..e37a77e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -25,6 +25,7 @@
"android/soong/bazel"
"android/soong/bazel/cquery"
+ "android/soong/remoteexec"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -59,6 +60,8 @@
ctx.RegisterModuleType("java_device_for_host", DeviceForHostFactory)
ctx.RegisterModuleType("java_host_for_device", HostForDeviceFactory)
ctx.RegisterModuleType("dex_import", DexImportFactory)
+ ctx.RegisterModuleType("java_api_library", ApiLibraryFactory)
+ ctx.RegisterModuleType("java_api_contribution", ApiContributionFactory)
// This mutator registers dependencies on dex2oat for modules that should be
// dexpreopted. This is done late when the final variants have been
@@ -211,6 +214,14 @@
PropertyName: "java_tests",
},
}
+
+ // Rule for generating device binary default wrapper
+ deviceBinaryWrapper = pctx.StaticRule("deviceBinaryWrapper", blueprint.RuleParams{
+ Command: `echo -e '#!/system/bin/sh\n` +
+ `export CLASSPATH=/system/framework/$jar_name\n` +
+ `exec app_process /$partition/bin $main_class "$$@"'> ${out}`,
+ Description: "Generating device binary wrapper ${jar_name}",
+ }, "jar_name", "partition", "main_class")
)
// JavaInfo contains information about a java module for use by modules that depend on it.
@@ -348,6 +359,7 @@
dataDeviceBinsTag = dependencyTag{name: "dataDeviceBins"}
staticLibTag = dependencyTag{name: "staticlib"}
libTag = dependencyTag{name: "javalib", runtimeLinked: true}
+ sdkLibTag = dependencyTag{name: "sdklib", runtimeLinked: true}
java9LibTag = dependencyTag{name: "java9lib", runtimeLinked: true}
pluginTag = dependencyTag{name: "plugin", toolchain: true}
errorpronePluginTag = dependencyTag{name: "errorprone-plugin", toolchain: true}
@@ -374,7 +386,7 @@
)
func IsLibDepTag(depTag blueprint.DependencyTag) bool {
- return depTag == libTag
+ return depTag == libTag || depTag == sdkLibTag
}
func IsStaticLibDepTag(depTag blueprint.DependencyTag) bool {
@@ -420,6 +432,7 @@
target android.Target
coverageFile android.OptionalPath
unstrippedFile android.Path
+ partition string
}
func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, d dexer) {
@@ -427,7 +440,7 @@
if sdkDep.useModule {
ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...)
ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...)
- ctx.AddVariationDependencies(nil, libTag, sdkDep.classpath...)
+ ctx.AddVariationDependencies(nil, sdkLibTag, sdkDep.classpath...)
if d.effectiveOptimizeEnabled() && sdkDep.hasStandardLibs() {
ctx.AddVariationDependencies(nil, proguardRaiseTag, config.LegacyCorePlatformBootclasspathLibraries...)
}
@@ -751,6 +764,9 @@
// The list of permitted packages that need to be passed to the prebuilts as they are used to
// create the updatable-bcp-packages.txt file.
PermittedPackages []string
+
+ // The value of the min_sdk_version property, translated into a number where possible.
+ MinSdkVersion *string `supported_build_releases:"Tiramisu+"`
}
func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
@@ -761,6 +777,13 @@
p.AidlIncludeDirs = j.AidlIncludeDirs()
p.PermittedPackages = j.PermittedPackagesForUpdatableBootJars()
+
+ // If the min_sdk_version was set then add the canonical representation of the API level to the
+ // snapshot.
+ if j.deviceProperties.Min_sdk_version != nil {
+ canonical := android.ReplaceFinalizedCodenames(ctx.SdkModuleContext().Config(), j.minSdkVersion.ApiLevel.String())
+ p.MinSdkVersion = proptools.StringPtr(canonical)
+ }
}
func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
@@ -779,6 +802,10 @@
propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
}
+ if p.MinSdkVersion != nil {
+ propertySet.AddProperty("min_sdk_version", *p.MinSdkVersion)
+ }
+
if len(p.PermittedPackages) > 0 {
propertySet.AddProperty("permitted_packages", p.PermittedPackages)
}
@@ -1396,7 +1423,31 @@
ctx.PropertyErrorf("wrapper", "wrapper is required for Windows")
}
- j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh")
+ if ctx.Device() {
+ // device binary should have a main_class property if it does not
+ // have a specific wrapper, so that a default wrapper can
+ // be generated for it.
+ if j.binaryProperties.Main_class == nil {
+ ctx.PropertyErrorf("main_class", "main_class property "+
+ "is required for device binary if no default wrapper is assigned")
+ } else {
+ wrapper := android.PathForModuleOut(ctx, ctx.ModuleName()+".sh")
+ jarName := j.Stem() + ".jar"
+ partition := j.PartitionTag(ctx.DeviceConfig())
+ ctx.Build(pctx, android.BuildParams{
+ Rule: deviceBinaryWrapper,
+ Output: wrapper,
+ Args: map[string]string{
+ "jar_name": jarName,
+ "partition": partition,
+ "main_class": String(j.binaryProperties.Main_class),
+ },
+ })
+ j.wrapperFile = wrapper
+ }
+ } else {
+ j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh")
+ }
}
ext := ""
@@ -1467,6 +1518,179 @@
return module
}
+type JavaApiContribution struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+
+ properties struct {
+ // name of the API surface
+ Api_surface *string
+
+ // relative path to the API signature text file
+ Api_file *string `android:"path"`
+ }
+}
+
+func ApiContributionFactory() android.Module {
+ module := &JavaApiContribution{}
+ android.InitAndroidModule(module)
+ android.InitDefaultableModule(module)
+ module.AddProperties(&module.properties)
+ return module
+}
+
+type JavaApiImportInfo struct {
+ ApiFile android.Path
+}
+
+var JavaApiImportProvider = blueprint.NewProvider(JavaApiImportInfo{})
+
+func (ap *JavaApiContribution) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ apiFile := android.PathForModuleSrc(ctx, String(ap.properties.Api_file))
+ ctx.SetProvider(JavaApiImportProvider, JavaApiImportInfo{
+ ApiFile: apiFile,
+ })
+}
+
+type ApiLibrary struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+
+ properties JavaApiLibraryProperties
+
+ stubsSrcJar android.WritablePath
+ stubsJar android.WritablePath
+}
+
+type JavaApiLibraryProperties struct {
+ // name of the API surface
+ Api_surface *string
+
+ // list of Java API contribution modules that consists this API surface
+ Api_contributions []string
+
+ // List of flags to be passed to the javac compiler to generate jar file
+ Javacflags []string
+}
+
+func ApiLibraryFactory() android.Module {
+ module := &ApiLibrary{}
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+ module.AddProperties(&module.properties)
+ return module
+}
+
+func (al *ApiLibrary) ApiSurface() *string {
+ return al.properties.Api_surface
+}
+
+func (al *ApiLibrary) StubsJar() android.Path {
+ return al.stubsJar
+}
+
+func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
+ srcs android.Paths, homeDir android.WritablePath) *android.RuleBuilderCommand {
+ rule.Command().Text("rm -rf").Flag(homeDir.String())
+ rule.Command().Text("mkdir -p").Flag(homeDir.String())
+
+ cmd := rule.Command()
+ cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
+
+ if metalavaUseRbe(ctx) {
+ rule.Remoteable(android.RemoteRuleSupports{RBE: true})
+ execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+ labels := map[string]string{"type": "tool", "name": "metalava"}
+
+ pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
+ rule.Rewrapper(&remoteexec.REParams{
+ Labels: labels,
+ ExecStrategy: execStrategy,
+ ToolchainInputs: []string{config.JavaCmd(ctx).String()},
+ Platform: map[string]string{remoteexec.PoolKey: pool},
+ })
+ }
+
+ cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
+ Flag(config.JavacVmFlags).
+ Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED").
+ FlagWithArg("-encoding ", "UTF-8").
+ FlagWithInputList("--source-files ", srcs, " ")
+
+ cmd.Flag("--no-banner").
+ Flag("--color").
+ Flag("--quiet").
+ Flag("--format=v2").
+ FlagWithArg("--repeat-errors-max ", "10").
+ FlagWithArg("--hide ", "UnresolvedImport").
+ FlagWithArg("--hide ", "InvalidNullabilityOverride").
+ FlagWithArg("--hide ", "ChangedDefault")
+
+ return cmd
+}
+
+func (al *ApiLibrary) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath) {
+ if stubsDir.Valid() {
+ cmd.FlagWithArg("--stubs ", stubsDir.String())
+ }
+}
+
+var javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
+
+func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+ apiContributions := al.properties.Api_contributions
+ for _, apiContributionName := range apiContributions {
+ ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName)
+ }
+}
+
+func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+
+ rule := android.NewRuleBuilder(pctx, ctx)
+
+ rule.Sbox(android.PathForModuleOut(ctx, "metalava"),
+ android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
+ SandboxInputs()
+
+ var stubsDir android.OptionalPath
+ stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, "metalava", "stubsDir"))
+ rule.Command().Text("rm -rf").Text(stubsDir.String())
+ rule.Command().Text("mkdir -p").Text(stubsDir.String())
+
+ homeDir := android.PathForModuleOut(ctx, "metalava", "home")
+
+ var srcFiles []android.Path
+ ctx.VisitDirectDepsWithTag(javaApiContributionTag, func(dep android.Module) {
+ provider := ctx.OtherModuleProvider(dep, JavaApiImportProvider).(JavaApiImportInfo)
+ srcFiles = append(srcFiles, android.PathForSource(ctx, provider.ApiFile.String()))
+ })
+
+ cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir)
+
+ al.stubsFlags(ctx, cmd, stubsDir)
+
+ al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
+ rule.Command().
+ BuiltTool("soong_zip").
+ Flag("-write_if_changed").
+ Flag("-jar").
+ FlagWithOutput("-o ", al.stubsSrcJar).
+ FlagWithArg("-C ", stubsDir.String()).
+ FlagWithArg("-D ", stubsDir.String())
+
+ rule.Build("metalava", "metalava merged")
+
+ al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), "android.jar")
+
+ var flags javaBuilderFlags
+ flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
+
+ TransformJavaToClasses(ctx, al.stubsJar, 0, android.Paths{},
+ android.Paths{al.stubsSrcJar}, flags, android.Paths{})
+
+ ctx.Phony(ctx.ModuleName(), al.stubsJar)
+}
+
//
// Java prebuilts
//
@@ -1654,7 +1878,7 @@
if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
switch tag {
- case libTag:
+ case libTag, sdkLibTag:
flags.classpath = append(flags.classpath, dep.HeaderJars...)
flags.dexClasspath = append(flags.dexClasspath, dep.HeaderJars...)
case staticLibTag:
@@ -1664,7 +1888,7 @@
}
} else if dep, ok := module.(SdkLibraryDependency); ok {
switch tag {
- case libTag:
+ case libTag, sdkLibTag:
flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...)
}
}
@@ -2178,7 +2402,7 @@
}
depTag := ctx.OtherModuleDependencyTag(depModule)
- if depTag == libTag {
+ if IsLibDepTag(depTag) {
// Ok, propagate <uses-library> through non-static library dependencies.
} else if tag, ok := depTag.(usesLibraryDependencyTag); ok && tag.sdkVersion == dexpreopt.AnySdkVersion {
// Ok, propagate <uses-library> through non-compatibility <uses-library> dependencies.
@@ -2273,11 +2497,21 @@
Deps bazel.LabelListAttribute
}
-// convertLibraryAttrsBp2Build converts a few shared attributes from java_* modules
-// and also separates dependencies into dynamic dependencies and static dependencies.
-// Each corresponding Bazel target type, can have a different method for handling
-// dynamic vs. static dependencies, and so these are returned to the calling function.
-func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *javaDependencyLabels) {
+// bp2BuildJavaInfo has information needed for the conversion of java*_modules
+// that is needed bor Bp2Build conversion but that requires different handling
+// depending on the module type.
+type bp2BuildJavaInfo struct {
+ // separates dependencies into dynamic dependencies and static dependencies.
+ DepLabels *javaDependencyLabels
+ hasKotlinSrcs bool
+}
+
+// convertLibraryAttrsBp2Build returns a javaCommonAttributes struct with
+// converted attributes shared across java_* modules and a bp2BuildJavaInfo struct
+// which has other non-attribute information needed for bp2build conversion
+// that needs different handling depending on the module types, and thus needs
+// to be returned to the calling function.
+func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo) {
var srcs bazel.LabelListAttribute
var deps bazel.LabelList
var staticDeps bazel.LabelList
@@ -2296,21 +2530,25 @@
protoSrcPartition := "proto"
logtagSrcPartition := "logtag"
aidlSrcPartition := "aidl"
+ kotlinPartition := "kotlin"
srcPartitions := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{
javaSrcPartition: bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true},
logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}},
protoSrcPartition: android.ProtoSrcLabelPartition,
aidlSrcPartition: android.AidlSrcLabelPartition,
+ kotlinPartition: bazel.LabelPartition{Extensions: []string{".kt"}},
})
javaSrcs := srcPartitions[javaSrcPartition]
+ kotlinSrcs := srcPartitions[kotlinPartition]
+ javaSrcs.Append(kotlinSrcs)
if !srcPartitions[logtagSrcPartition].IsEmpty() {
logtagsLibName := m.Name() + "_logtags"
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "event_log_tags",
- Bzl_load_location: "//build/make/tools:event_log_tags.bzl",
+ Bzl_load_location: "//build/bazel/rules/java:event_log_tags.bzl",
},
android.CommonAttributes{Name: logtagsLibName},
&eventLogTagsAttributes{
@@ -2382,7 +2620,18 @@
}
if m.properties.Libs != nil {
- deps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Libs))))
+
+ // TODO 244210934 ALIX Check if this else statement breaks presubmits get rid of it if it doesn't
+ if strings.HasPrefix(ctx.ModuleType(), "java_binary") || strings.HasPrefix(ctx.ModuleType(), "java_library") {
+ for _, d := range m.properties.Libs {
+ neverlinkLabel := android.BazelLabelForModuleDepSingle(ctx, d)
+ neverlinkLabel.Label = neverlinkLabel.Label + "-neverlink"
+ deps.Add(&neverlinkLabel)
+ }
+
+ } else {
+ deps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Libs))))
+ }
}
if m.properties.Static_libs != nil {
@@ -2402,17 +2651,25 @@
depLabels.Deps = bazel.MakeLabelListAttribute(deps)
depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps)
- return commonAttrs, depLabels
+ bp2BuildInfo := &bp2BuildJavaInfo{
+ DepLabels: depLabels,
+ hasKotlinSrcs: !kotlinSrcs.IsEmpty(),
+ }
+
+ return commonAttrs, bp2BuildInfo
}
type javaLibraryAttributes struct {
*javaCommonAttributes
- Deps bazel.LabelListAttribute
- Exports bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Exports bazel.LabelListAttribute
+ Neverlink bazel.BoolAttribute
+ Common_srcs bazel.LabelListAttribute
}
func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
- commonAttrs, depLabels := m.convertLibraryAttrsBp2Build(ctx)
+ commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx)
+ depLabels := bp2BuildInfo.DepLabels
deps := depLabels.Deps
if !commonAttrs.Srcs.IsEmpty() {
@@ -2427,18 +2684,38 @@
ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
}
+ var props bazel.BazelTargetModuleProperties
attrs := &javaLibraryAttributes{
javaCommonAttributes: commonAttrs,
Deps: deps,
Exports: depLabels.StaticDeps,
}
+ name := m.Name()
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "java_library",
- Bzl_load_location: "//build/bazel/rules/java:library.bzl",
+ if !bp2BuildInfo.hasKotlinSrcs && len(m.properties.Common_srcs) == 0 {
+ props = bazel.BazelTargetModuleProperties{
+ Rule_class: "java_library",
+ Bzl_load_location: "//build/bazel/rules/java:library.bzl",
+ }
+
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
+ neverlinkProp := true
+ neverLinkAttrs := &javaLibraryAttributes{
+ Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
+ Neverlink: bazel.BoolAttribute{Value: &neverlinkProp},
+ }
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name + "-neverlink"}, neverLinkAttrs)
+ } else {
+ attrs.Common_srcs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Common_srcs))
+
+ props = bazel.BazelTargetModuleProperties{
+ Rule_class: "kt_jvm_library",
+ Bzl_load_location: "@rules_kotlin//kotlin:jvm_library.bzl",
+ }
+ // TODO (b/244210934): create neverlink-duplicate target once kt_jvm_library supports neverlink attribute
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
}
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
}
type javaBinaryHostAttributes struct {
@@ -2451,7 +2728,8 @@
// JavaBinaryHostBp2Build is for java_binary_host bp2build.
func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) {
- commonAttrs, depLabels := m.convertLibraryAttrsBp2Build(ctx)
+ commonAttrs, bp2BuildInfo := m.convertLibraryAttrsBp2Build(ctx)
+ depLabels := bp2BuildInfo.DepLabels
deps := depLabels.Deps
deps.Append(depLabels.StaticDeps)
@@ -2520,7 +2798,8 @@
}
type bazelJavaImportAttributes struct {
- Jars bazel.LabelListAttribute
+ Jars bazel.LabelListAttribute
+ Exports bazel.LabelListAttribute
}
// java_import bp2Build converter.
@@ -2541,7 +2820,17 @@
}
props := bazel.BazelTargetModuleProperties{Rule_class: "java_import"}
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: android.RemoveOptionalPrebuiltPrefix(i.Name())}, attrs)
+ name := android.RemoveOptionalPrebuiltPrefix(i.Name())
+
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
+
+ neverlink := true
+ neverlinkAttrs := &javaLibraryAttributes{
+ Neverlink: bazel.BoolAttribute{Value: &neverlink},
+ Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
+ }
+ ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{Rule_class: "java_library"}, android.CommonAttributes{Name: name + "-neverlink"}, neverlinkAttrs)
+
}
var _ android.MixedBuildBuildable = (*Import)(nil)
diff --git a/java/java_test.go b/java/java_test.go
index 7f0cea7..ff15783 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -588,8 +588,8 @@
sdklibStubsJar := ctx.ModuleForTests("sdklib.stubs", "android_common").Rule("combineJar").Output
fooLibrary := fooModule.Module().(*Library)
- assertDeepEquals(t, "foo java sources incorrect",
- []string{"a.java"}, fooLibrary.compiledJavaSrcs.Strings())
+ assertDeepEquals(t, "foo unique sources incorrect",
+ []string{"a.java"}, fooLibrary.uniqueSrcFiles.Strings())
assertDeepEquals(t, "foo java source jars incorrect",
[]string{".intermediates/stubs-source/android_common/stubs-source-stubs.srcjar"},
@@ -1288,6 +1288,8 @@
}
func TestAidlIncludeDirFromConvertedFileGroupWithPathPropInMixedBuilds(t *testing.T) {
+ // TODO(b/247782695), TODO(b/242847534) Fix mixed builds for filegroups
+ t.Skip("Re-enable once filegroups are corrected for mixed builds")
bp := `
filegroup {
name: "foo_aidl",
@@ -1368,6 +1370,39 @@
}
}
+func TestAidlFlagsMinSdkVersionDroidstubs(t *testing.T) {
+ bpTemplate := `
+ droidstubs {
+ name: "foo-stubs",
+ srcs: ["foo.aidl"],
+ %s
+ system_modules: "none",
+ }
+ `
+ testCases := []struct {
+ desc string
+ sdkVersionBp string
+ minSdkVersionExpected string
+ }{
+ {
+ desc: "sdk_version not set, module compiles against private platform APIs",
+ sdkVersionBp: ``,
+ minSdkVersionExpected: "10000",
+ },
+ {
+ desc: "sdk_version set to none, module does not build against an SDK",
+ sdkVersionBp: `sdk_version: "none",`,
+ minSdkVersionExpected: "10000",
+ },
+ }
+ for _, tc := range testCases {
+ ctx := prepareForJavaTest.RunTestWithBp(t, fmt.Sprintf(bpTemplate, tc.sdkVersionBp))
+ aidlCmd := ctx.ModuleForTests("foo-stubs", "android_common").Rule("aidl").RuleParams.Command
+ expected := "--min_sdk_version=" + tc.minSdkVersionExpected
+ android.AssertStringDoesContain(t, "aidl command conatins incorrect min_sdk_version for testCse: "+tc.desc, aidlCmd, expected)
+ }
+}
+
func TestAidlEnforcePermissions(t *testing.T) {
ctx, _ := testJava(t, `
java_library {
@@ -1781,3 +1816,131 @@
t.Errorf("expected flags to be %q; was %q", expectedFlags, flags)
}
}
+
+func TestDeviceBinaryWrapperGeneration(t *testing.T) {
+ // Scenario 1: java_binary has main_class property in its bp
+ ctx, _ := testJava(t, `
+ java_binary {
+ name: "foo",
+ srcs: ["foo.java"],
+ main_class: "foo.bar.jb",
+ }
+ `)
+ wrapperPath := fmt.Sprint(ctx.ModuleForTests("foo", "android_arm64_armv8-a").AllOutputs())
+ if !strings.Contains(wrapperPath, "foo.sh") {
+ t.Errorf("wrapper file foo.sh is not generated")
+ }
+
+ // Scenario 2: java_binary has neither wrapper nor main_class, its build
+ // is expected to be failed.
+ testJavaError(t, "main_class property is required for device binary if no default wrapper is assigned", `
+ java_binary {
+ name: "foo",
+ srcs: ["foo.java"],
+ }`)
+}
+
+func TestJavaApiLibraryAndProviderLink(t *testing.T) {
+ provider_bp_a := `
+ java_api_contribution {
+ name: "foo1",
+ api_file: "foo1.txt",
+ }
+ `
+ provider_bp_b := `java_api_contribution {
+ name: "foo2",
+ api_file: "foo2.txt",
+ }
+ `
+ ctx, _ := testJavaWithFS(t, `
+ java_api_library {
+ name: "bar1",
+ api_surface: "public",
+ api_contributions: ["foo1"],
+ }
+
+ java_api_library {
+ name: "bar2",
+ api_surface: "system",
+ api_contributions: ["foo1", "foo2"],
+ }
+ `,
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ })
+
+ testcases := []struct {
+ moduleName string
+ sourceTextFileDirs []string
+ }{
+ {
+ moduleName: "bar1",
+ sourceTextFileDirs: []string{"a/foo1.txt"},
+ },
+ {
+ moduleName: "bar2",
+ sourceTextFileDirs: []string{"a/foo1.txt", "b/foo2.txt"},
+ },
+ }
+ for _, c := range testcases {
+ m := ctx.ModuleForTests(c.moduleName, "android_common")
+ manifest := m.Output("metalava.sbox.textproto")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+ manifestCommand := sboxProto.Commands[0].GetCommand()
+ sourceFilesFlag := "--source-files " + strings.Join(c.sourceTextFileDirs, " ")
+ android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
+ }
+}
+
+func TestJavaApiLibraryJarGeneration(t *testing.T) {
+ provider_bp_a := `
+ java_api_contribution {
+ name: "foo1",
+ api_file: "foo1.txt",
+ }
+ `
+ provider_bp_b := `java_api_contribution {
+ name: "foo2",
+ api_file: "foo2.txt",
+ }
+ `
+ ctx, _ := testJavaWithFS(t, `
+ java_api_library {
+ name: "bar1",
+ api_surface: "public",
+ api_contributions: ["foo1"],
+ }
+
+ java_api_library {
+ name: "bar2",
+ api_surface: "system",
+ api_contributions: ["foo1", "foo2"],
+ }
+ `,
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ })
+
+ testcases := []struct {
+ moduleName string
+ outputJarName string
+ }{
+ {
+ moduleName: "bar1",
+ outputJarName: "bar1/android.jar",
+ },
+ {
+ moduleName: "bar2",
+ outputJarName: "bar2/android.jar",
+ },
+ }
+ for _, c := range testcases {
+ m := ctx.ModuleForTests(c.moduleName, "android_common")
+ outputs := fmt.Sprint(m.AllOutputs())
+ if !strings.Contains(outputs, c.outputJarName) {
+ t.Errorf("Module output does not contain expected jar %s", c.outputJarName)
+ }
+ }
+}
diff --git a/java/legacy_core_platform_api_usage.go b/java/legacy_core_platform_api_usage.go
index 8e22491..6cb549e 100644
--- a/java/legacy_core_platform_api_usage.go
+++ b/java/legacy_core_platform_api_usage.go
@@ -20,202 +20,47 @@
)
var legacyCorePlatformApiModules = []string{
- "AAECarSystemUI",
- "AAECarSystemUI-tests",
"ArcSettings",
- "ahat-test-dump",
- "android.car",
- "android.test.mock",
- "android.test.mock.impl",
- "AoapTestDeviceApp",
- "AoapTestHostApp",
- "api-stubs-docs",
- "art_cts_jvmti_test_library",
- "art-gtest-jars-MyClassNatives",
- "BackupEncryption",
- "BackupFrameworksServicesRoboTests",
- "backuplib",
- "BandwidthEnforcementTest",
- "BlockedNumberProvider",
- "BluetoothInstrumentationTests",
- "BluetoothMidiLib",
- "BluetoothMidiService",
"BTTestApp",
- "CallEnhancement",
"CapCtrlInterface",
- "CarService",
- "CarServiceTest",
- "car-service-test-lib",
- "car-service-test-static-lib",
- "CertInstaller",
"com.qti.location.sdk",
- "com.qti.media.secureprocessor",
- "ConnectivityManagerTest",
- "ContactsProvider",
- "CorePerfTests",
- "core-tests-support",
- "cronet_impl_common_java",
- "cronet_impl_native_java",
- "cronet_impl_platform_java",
- "CtsAppExitTestCases",
- "CtsContentTestCases",
- "CtsLibcoreWycheproofBCTestCases",
- "CtsMediaTestCases",
- "CtsNetTestCases",
- "CtsNetTestCasesLatestSdk",
- "CtsSecurityTestCases",
- "CtsSuspendAppsTestCases",
- "CtsUsageStatsTestCases",
- "DeadpoolService",
- "DeadpoolServiceBtServices",
- "DeviceInfo",
- "DiagnosticTools",
- "DisplayCutoutEmulationEmu01Overlay",
- "DocumentsUIGoogleTests",
- "DocumentsUIPerfTests",
- "DocumentsUITests",
- "DocumentsUIUnitTests",
- "DownloadProvider",
- "DownloadProviderTests",
- "DownloadProviderUi",
- "ds-car-docs", // for AAOS API documentation only
- "DynamicSystemInstallationService",
- "EmergencyInfo-lib",
- "EthernetServiceTests",
- "ExternalStorageProvider",
"face-V1-0-javalib",
"FloralClocks",
"framework-jobscheduler",
"framework-minus-apex",
"framework-minus-apex-intdefs",
- "FrameworkOverlayG6QU3",
"FrameworksCoreTests",
- "FrameworksIkeTests",
- "FrameworksNetCommonTests",
- "FrameworksNetTests",
- "FrameworksServicesRoboTests",
- "FrameworksServicesTests",
- "FrameworksMockingServicesTests",
- "FrameworksUtilTests",
- "GtsIncrementalInstallTestCases",
- "GtsIncrementalInstallTriggerApp",
- "GtsInstallerV2TestCases",
"HelloOslo",
- "hid",
- "hidl_test_java_java",
- "hwbinder",
- "imssettings",
"izat.lib.glue",
- "KeyChain",
- "LocalSettingsLib",
- "LocalTransport",
- "lockagent",
- "mediaframeworktest",
"mediatek-ims-base",
- "MmsService",
"ModemTestMode",
"MtkCapCtrl",
- "MtpService",
- "MultiDisplayProvider",
"my.tests.snapdragonsdktest",
"NetworkSetting",
- "NetworkStackIntegrationTestsLib",
- "NetworkStackNextIntegrationTests",
- "NetworkStackNextTests",
- "NetworkStackTests",
- "NetworkStackTestsLib",
- "online-gcm-ref-docs",
- "online-gts-docs",
"PerformanceMode",
- "platform_library-docs",
- "PowerStatsService",
- "PrintSpooler",
"pxp-monitor",
"QColor",
"qcom.fmradio",
- "QDCMMobileApp",
"Qmmi",
"QPerformance",
- "remotesimlockmanagerlibrary",
- "RollbackTest",
"sam",
"saminterfacelibrary",
"sammanagerlibrary",
- "service-blobstore",
- "service-connectivity-pre-jarjar",
- "service-jobscheduler",
"services",
- "services.accessibility",
- "services.backup",
"services.core.unboosted",
- "services.devicepolicy",
- "services.print",
- "services.usage",
- "services.usb",
"Settings-core",
"SettingsGoogle",
"SettingsGoogleOverlayCoral",
"SettingsGoogleOverlayFlame",
"SettingsLib",
- "SettingsOverlayG020A",
- "SettingsOverlayG020B",
- "SettingsOverlayG020C",
- "SettingsOverlayG020D",
- "SettingsOverlayG020E",
- "SettingsOverlayG020E_VN",
- "SettingsOverlayG020F",
- "SettingsOverlayG020F_VN",
- "SettingsOverlayG020G",
- "SettingsOverlayG020G_VN",
- "SettingsOverlayG020H",
- "SettingsOverlayG020H_VN",
- "SettingsOverlayG020I",
- "SettingsOverlayG020I_VN",
- "SettingsOverlayG020J",
- "SettingsOverlayG020M",
- "SettingsOverlayG020N",
- "SettingsOverlayG020P",
- "SettingsOverlayG020Q",
- "SettingsOverlayG025H",
- "SettingsOverlayG025J",
- "SettingsOverlayG025M",
- "SettingsOverlayG025N",
- "SettingsOverlayG5NZ6",
- "SettingsProvider",
- "SettingsProviderTest",
"SettingsRoboTests",
- "Shell",
- "ShellTests",
"SimContact",
"SimContacts",
"SimSettings",
- "sl4a.Common",
- "StatementService",
- "SystemUI-core",
- "SystemUISharedLib",
- "SystemUI-tests",
"tcmiface",
- "Telecom",
- "TelecomUnitTests",
"telephony-common",
- "TelephonyProviderTests",
"TeleService",
- "testables",
- "TetheringTests",
- "TetheringTestsLib",
- "time_zone_distro_installer",
- "time_zone_distro_installer-tests",
- "time_zone_distro-tests",
- "time_zone_updater",
- "TMobilePlanProvider",
- "TvProvider",
- "uiautomator-stubs-docs",
- "uimgbamanagerlibrary",
- "UsbHostExternalManagementTestApp",
- "UserDictionaryProvider",
"UxPerformance",
- "WallpaperBackup",
- "WallpaperBackupAgentTests",
"WfdCommon",
}
diff --git a/java/lint.go b/java/lint.go
index 931820d..7a6e5d9 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -190,10 +190,8 @@
extraCheckModules := l.properties.Lint.Extra_check_modules
- if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" {
- if checkOnlyModules := ctx.Config().Getenv("ANDROID_LINT_CHECK_EXTRA_MODULES"); checkOnlyModules != "" {
- extraCheckModules = strings.Split(checkOnlyModules, ",")
- }
+ if extraCheckModulesEnv := ctx.Config().Getenv("ANDROID_LINT_CHECK_EXTRA_MODULES"); extraCheckModulesEnv != "" {
+ extraCheckModules = append(extraCheckModules, strings.Split(extraCheckModulesEnv, ",")...)
}
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(),
@@ -333,7 +331,7 @@
l.extraMainlineLintErrors = append(l.extraMainlineLintErrors, updatabilityChecks...)
// Skip lint warning checks for NewApi warnings for libcore where they come from source
// files that reference the API they are adding (b/208656169).
- if ctx.ModuleDir() != "libcore" {
+ if !strings.HasPrefix(ctx.ModuleDir(), "libcore") {
_, filtered := android.FilterList(l.properties.Lint.Warning_checks, updatabilityChecks)
if len(filtered) != 0 {
@@ -473,20 +471,23 @@
cmd.FlagWithOutput("--write-reference-baseline ", baseline)
- cmd.Text("|| (").Text("if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit 7)")
+ cmd.Text("; EXITCODE=$?; ")
+
+ // The sources in the sandbox may have been modified by --apply-suggestions, zip them up and
+ // export them out of the sandbox. Do this before exiting so that the suggestions exit even after
+ // a fatal error.
+ cmd.BuiltTool("soong_zip").
+ FlagWithOutput("-o ", android.PathForModuleOut(ctx, "lint", "suggested-fixes.zip")).
+ FlagWithArg("-C ", cmd.PathForInput(android.PathForSource(ctx))).
+ FlagWithInput("-r ", srcsList)
+
+ cmd.Text("; if [ $EXITCODE != 0 ]; then if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit $EXITCODE; fi")
rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
// The HTML output contains a date, remove it to make the output deterministic.
rule.Command().Text(`sed -i.tmp -e 's|Check performed at .*\(</nav>\)|\1|'`).Output(html)
- // The sources in the sandbox may have been modified by --apply-suggestions, zip them up and
- // export them out of the sandbox.
- rule.Command().BuiltTool("soong_zip").
- FlagWithOutput("-o ", android.PathForModuleOut(ctx, "lint", "suggested-fixes.zip")).
- FlagWithArg("-C ", cmd.PathForInput(android.PathForSource(ctx))).
- FlagWithInput("-r ", srcsList)
-
rule.Build("lint", "lint")
l.outputs = lintOutputs{
diff --git a/java/lint_defaults.txt b/java/lint_defaults.txt
index bff7221..519a702 100644
--- a/java/lint_defaults.txt
+++ b/java/lint_defaults.txt
@@ -39,6 +39,7 @@
# Downgrade existing errors to warnings
--warning_check AppCompatResource # 55 occurences in 10 modules
--warning_check AppLinkUrlError # 111 occurences in 53 modules
+--warning_check BinderGetCallingInMainThread
--warning_check ByteOrderMark # 2 occurences in 2 modules
--warning_check DuplicateActivity # 3 occurences in 3 modules
--warning_check DuplicateDefinition # 3623 occurences in 48 modules
diff --git a/java/lint_test.go b/java/lint_test.go
index 456e6ba..62450d5 100644
--- a/java/lint_test.go
+++ b/java/lint_test.go
@@ -271,7 +271,7 @@
"a.java",
],
min_sdk_version: "29",
- sdk_version: "module_current",
+ sdk_version: "XXX",
lint: {
strict_updatability_linting: true,
},
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 24f8253..f0de7a4 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -436,10 +436,10 @@
profile := bootImageProfileRule(ctx, imageConfig)
// Build boot image files for the android variants.
- androidBootImageFilesByArch := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
+ androidBootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
// Zip the android variant boot image files up.
- buildBootImageZipInPredefinedLocation(ctx, imageConfig, androidBootImageFilesByArch)
+ buildBootImageZipInPredefinedLocation(ctx, imageConfig, androidBootImageFiles.byArch)
// Build boot image files for the host variants. There are use directly by ART host side tests.
buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
diff --git a/java/plugin.go b/java/plugin.go
index 123dbd4..731dfda 100644
--- a/java/plugin.go
+++ b/java/plugin.go
@@ -66,7 +66,8 @@
// ConvertWithBp2build is used to convert android_app to Bazel.
func (p *Plugin) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
pluginName := p.Name()
- commonAttrs, depLabels := p.convertLibraryAttrsBp2Build(ctx)
+ commonAttrs, bp2BuildInfo := p.convertLibraryAttrsBp2Build(ctx)
+ depLabels := bp2BuildInfo.DepLabels
deps := depLabels.Deps
deps.Append(depLabels.StaticDeps)
diff --git a/java/robolectric.go b/java/robolectric.go
index 71ffdb1..2cb0798 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -23,6 +23,7 @@
"android/soong/android"
"android/soong/java/config"
"android/soong/tradefed"
+
"github.com/google/blueprint/proptools"
)
@@ -64,6 +65,10 @@
// The version number of a robolectric prebuilt to use from prebuilts/misc/common/robolectric
// instead of the one built from source in external/robolectric-shadows.
Robolectric_prebuilt_version *string
+
+ // Use /external/robolectric rather than /external/robolectric-shadows as the version of robolectri
+ // to use. /external/robolectric closely tracks github's master, and will fully replace /external/robolectric-shadows
+ Upstream *bool
}
type robolectricTest struct {
@@ -107,7 +112,11 @@
if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
ctx.AddVariationDependencies(nil, libTag, fmt.Sprintf(robolectricPrebuiltLibPattern, v))
} else {
- ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib)
+ if proptools.Bool(r.robolectricProperties.Upstream) {
+ ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib+"_upstream")
+ } else {
+ ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib)
+ }
}
ctx.AddVariationDependencies(nil, libTag, robolectricDefaultLibs...)
@@ -166,7 +175,7 @@
instrumentedApp.implementationAndResourcesJar,
}
- for _, dep := range ctx.GetDirectDepsWithTag(libTag) {
+ handleLibDeps := func(dep android.Module) {
m := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
r.libs = append(r.libs, ctx.OtherModuleName(dep))
if !android.InList(ctx.OtherModuleName(dep), config.FrameworkLibraries) {
@@ -174,15 +183,22 @@
}
}
+ for _, dep := range ctx.GetDirectDepsWithTag(libTag) {
+ handleLibDeps(dep)
+ }
+ for _, dep := range ctx.GetDirectDepsWithTag(sdkLibTag) {
+ handleLibDeps(dep)
+ }
+
r.combinedJar = android.PathForModuleOut(ctx, "robolectric_combined", r.outputFile.Base())
TransformJarsToJar(ctx, r.combinedJar, "combine jars", combinedJarJars, android.OptionalPath{},
false, nil, nil)
// TODO: this could all be removed if tradefed was used as the test runner, it will find everything
// annotated as a test and run it.
- for _, src := range r.compiledJavaSrcs {
+ for _, src := range r.uniqueSrcFiles {
s := src.Rel()
- if !strings.HasSuffix(s, "Test.java") {
+ if !strings.HasSuffix(s, "Test.java") && !strings.HasSuffix(s, "Test.kt") {
continue
} else if strings.HasSuffix(s, "/BaseRobolectricTest.java") {
continue
diff --git a/java/rro.go b/java/rro.go
index cd8c635..9d0667c 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -142,6 +142,10 @@
aaptLinkFlags = append(aaptLinkFlags,
"--rename-overlay-target-package "+*r.overridableProperties.Target_package_name)
}
+ if r.overridableProperties.Category != nil {
+ aaptLinkFlags = append(aaptLinkFlags,
+ "--rename-overlay-category "+*r.overridableProperties.Category)
+ }
r.aapt.buildActions(ctx, r, nil, nil, false, aaptLinkFlags...)
// Sign the built package
@@ -220,6 +224,9 @@
// the target package name of this overlay app. The target package name in the manifest file is used if one was not given.
Target_package_name *string
+
+ // the rro category of this overlay. The category in the manifest file is used if one was not given.
+ Category *string
}
type OverrideRuntimeResourceOverlay struct {
diff --git a/java/rro_test.go b/java/rro_test.go
index 00ba5ba..8067a47 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -201,6 +201,7 @@
base: "foo_overlay",
package_name: "com.android.bar.overlay",
target_package_name: "com.android.bar",
+ category: "mycategory",
}
`)
@@ -212,6 +213,7 @@
targetVariant string
packageFlag string
targetPackageFlag string
+ categoryFlag string
}{
{
variantName: "android_common",
@@ -228,6 +230,7 @@
targetVariant: "android_common_bar",
packageFlag: "com.android.bar.overlay",
targetPackageFlag: "com.android.bar",
+ categoryFlag: "mycategory",
},
}
for _, expected := range expectedVariants {
@@ -249,6 +252,7 @@
checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag)
checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", "")
checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-target-package", expected.targetPackageFlag)
+ checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-category", expected.categoryFlag)
}
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index d188133..56e5550 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -65,8 +65,27 @@
name string
// The api scope that this scope extends.
+ //
+ // This organizes the scopes into an extension hierarchy.
+ //
+ // If set this means that the API provided by this scope includes the API provided by the scope
+ // set in this field.
extends *apiScope
+ // The next api scope that a library that uses this scope can access.
+ //
+ // This organizes the scopes into an access hierarchy.
+ //
+ // If set this means that a library that can access this API can also access the API provided by
+ // the scope set in this field.
+ //
+ // A module that sets sdk_version: "<scope>_current" should have access to the <scope> API of
+ // every java_sdk_library that it depends on. If the library does not provide an API for <scope>
+ // then it will traverse up this access hierarchy to find an API that it does provide.
+ //
+ // If this is not set then it defaults to the scope set in extends.
+ canAccess *apiScope
+
// The legacy enabled status for a specific scope can be dependent on other
// properties that have been specified on the library so it is provided by
// a function that can determine the status by examining those properties.
@@ -107,7 +126,7 @@
// The scope specific prefix to add to the api file base of "current.txt" or "removed.txt".
apiFilePrefix string
- // The scope specific prefix to add to the sdk library module name to construct a scope specific
+ // The scope specific suffix to add to the sdk library module name to construct a scope specific
// module name.
moduleSuffix string
@@ -193,6 +212,11 @@
}
}
+ // By default, a library that can access a scope can also access the scope it extends.
+ if scope.canAccess == nil {
+ scope.canAccess = scope.extends
+ }
+
// Escape any special characters in the arguments. This is needed because droidstubs
// passes these directly to the shell command.
scope.droidstubsArgs = proptools.ShellEscapeList(scopeSpecificArgs)
@@ -310,6 +334,14 @@
apiScopeSystemServer = initApiScope(&apiScope{
name: "system-server",
extends: apiScopePublic,
+
+ // The system-server scope can access the module-lib scope.
+ //
+ // A module that provides a system-server API is appended to the standard bootclasspath that is
+ // used by the system server. So, it should be able to access module-lib APIs provided by
+ // libraries on the bootclasspath.
+ canAccess: apiScopeModuleLib,
+
// The system-server scope is disabled by default in legacy mode.
//
// Enabling this would break existing usages.
@@ -926,7 +958,7 @@
// If this does not support the requested api scope then find the closest available
// scope it does support. Returns nil if no such scope is available.
func (c *commonToSdkLibraryAndImport) findClosestScopePath(scope *apiScope) *scopePaths {
- for s := scope; s != nil; s = s.extends {
+ for s := scope; s != nil; s = s.canAccess {
if paths := c.findScopePaths(s); paths != nil {
return paths
}
@@ -1616,6 +1648,7 @@
// shared libs and static libs. So we need to add both of these libs to Libs property.
props.Libs = module.properties.Libs
props.Libs = append(props.Libs, module.properties.Static_libs...)
+ props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...)
props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
props.Java_version = module.properties.Java_version
@@ -2236,8 +2269,9 @@
Sdk_version *string
Libs []string
Jars []string
- Prefer *bool
Compile_dex *bool
+
+ android.UserSuppliedPrebuiltProperties
}{}
props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
props.Sdk_version = scopeProperties.Sdk_version
@@ -2247,7 +2281,7 @@
props.Jars = scopeProperties.Jars
// The imports are preferred if the java_sdk_library_import is preferred.
- props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
+ props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
// The imports need to be compiled to dex if the java_sdk_library_import requests it.
compileDex := module.properties.Compile_dex
@@ -2261,16 +2295,18 @@
func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
props := struct {
- Name *string
- Srcs []string
- Prefer *bool
+ Name *string
+ Srcs []string
+
+ android.UserSuppliedPrebuiltProperties
}{}
props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope))
props.Srcs = scopeProperties.Stub_srcs
- mctx.CreateModule(PrebuiltStubsSourcesFactory, &props)
// The stubs source is preferred if the java_sdk_library_import is preferred.
- props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
+ props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
+
+ mctx.CreateModule(PrebuiltStubsSourcesFactory, &props)
}
// Add the dependencies on the child module in the component deps mutator so that it
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 805bc22..210bfc3 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -18,6 +18,7 @@
"fmt"
"path/filepath"
"regexp"
+ "strings"
"testing"
"android/soong/android"
@@ -699,6 +700,80 @@
`)
}
+func TestJavaSdkLibrary_SystemServer_AccessToStubScopeLibs(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo-public", "foo-system", "foo-module-lib", "foo-system-server"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo-public",
+ srcs: ["a.java"],
+ api_packages: ["foo"],
+ public: {
+ enabled: true,
+ },
+ }
+
+ java_sdk_library {
+ name: "foo-system",
+ srcs: ["a.java"],
+ api_packages: ["foo"],
+ system: {
+ enabled: true,
+ },
+ }
+
+ java_sdk_library {
+ name: "foo-module-lib",
+ srcs: ["a.java"],
+ api_packages: ["foo"],
+ system: {
+ enabled: true,
+ },
+ module_lib: {
+ enabled: true,
+ },
+ }
+
+ java_sdk_library {
+ name: "foo-system-server",
+ srcs: ["a.java"],
+ api_packages: ["foo"],
+ system_server: {
+ enabled: true,
+ },
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["a.java"],
+ libs: ["foo-public", "foo-system", "foo-module-lib", "foo-system-server"],
+ sdk_version: "system_server_current",
+ }
+ `)
+
+ stubsPath := func(name string, scope *apiScope) string {
+ name = scope.stubsLibraryModuleName(name)
+ return fmt.Sprintf("out/soong/.intermediates/%[1]s/android_common/turbine-combined/%[1]s.jar", name)
+ }
+
+ // The bar library should depend on the highest (where system server is highest and public is
+ // lowest) API scopes provided by each of the foo-* modules. The highest API scope provided by the
+ // foo-<x> module is <x>.
+ barLibrary := result.ModuleForTests("bar", "android_common").Rule("javac")
+ stubLibraries := []string{
+ stubsPath("foo-public", apiScopePublic),
+ stubsPath("foo-system", apiScopeSystem),
+ stubsPath("foo-module-lib", apiScopeModuleLib),
+ stubsPath("foo-system-server", apiScopeSystemServer),
+ }
+ expectedPattern := fmt.Sprintf(`^-classpath .*:\Q%s\E$`, strings.Join(stubLibraries, ":"))
+ if expected, actual := expectedPattern, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ t.Errorf("expected pattern %q to match %#q", expected, actual)
+ }
+}
+
func TestJavaSdkLibrary_MissingScope(t *testing.T) {
prepareForJavaTest.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`requires api scope module-lib from foo but it only has \[\] available`)).
@@ -875,11 +950,12 @@
})
}
-func TestJavaSdkLibraryImport_Preferred(t *testing.T) {
+func testJavaSdkLibraryImport_Preferred(t *testing.T, prefer string, preparer android.FixturePreparer) {
result := android.GroupFixturePreparers(
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("sdklib"),
+ preparer,
).RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
@@ -893,11 +969,37 @@
java_sdk_library_import {
name: "sdklib",
- prefer: true,
+ `+prefer+`
public: {
jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
},
}
+
+ java_library {
+ name: "combined",
+ static_libs: [
+ "sdklib.stubs",
+ ],
+ java_resources: [
+ ":sdklib.stubs.source",
+ ":sdklib{.public.api.txt}",
+ ":sdklib{.public.removed-api.txt}",
+ ":sdklib{.public.annotations.zip}",
+ ],
+ sdk_version: "none",
+ system_modules: "none",
+ }
+
+ java_library {
+ name: "public",
+ srcs: ["a.java"],
+ libs: ["sdklib"],
+ sdk_version: "current",
+ }
`)
CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
@@ -913,9 +1015,48 @@
CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{
`dex2oatd`,
`prebuilt_sdklib.stubs`,
+ `prebuilt_sdklib.stubs.source`,
`sdklib.impl`,
`sdklib.xml`,
})
+
+ // Make sure that dependencies on child modules use the prebuilt when preferred.
+ CheckModuleDependencies(t, result.TestContext, "combined", "android_common", []string{
+ // Each use of :sdklib{...} adds a dependency onto prebuilt_sdklib.
+ `prebuilt_sdklib`,
+ `prebuilt_sdklib`,
+ `prebuilt_sdklib`,
+ `prebuilt_sdklib.stubs`,
+ `prebuilt_sdklib.stubs.source`,
+ })
+
+ // Make sure that dependencies on sdklib that resolve to one of the child libraries use the
+ // prebuilt library.
+ public := result.ModuleForTests("public", "android_common")
+ rule := public.Output("javac/public.jar")
+ inputs := rule.Implicits.Strings()
+ expected := "out/soong/.intermediates/prebuilt_sdklib.stubs/android_common/combined/sdklib.stubs.jar"
+ if !android.InList(expected, inputs) {
+ t.Errorf("expected %q to contain %q", inputs, expected)
+ }
+}
+
+func TestJavaSdkLibraryImport_Preferred(t *testing.T) {
+ t.Run("prefer", func(t *testing.T) {
+ testJavaSdkLibraryImport_Preferred(t, "prefer: true,", android.NullFixturePreparer)
+ })
+
+ t.Run("use_source_config_var", func(t *testing.T) {
+ testJavaSdkLibraryImport_Preferred(t,
+ "use_source_config_var: {config_namespace: \"acme\", var_name: \"use_source\"},",
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.VendorVars = map[string]map[string]string{
+ "acme": {
+ "use_source": "false",
+ },
+ }
+ }))
+ })
}
func TestJavaSdkLibraryEnforce(t *testing.T) {
@@ -1244,3 +1385,29 @@
}
`)
}
+
+func TestJavaSdkLibrary_StubOnlyLibs_PassedToDroidstubs(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ public: {
+ enabled: true,
+ },
+ stub_only_libs: ["bar-lib"],
+ }
+
+ java_library {
+ name: "bar-lib",
+ srcs: ["b.java"],
+ }
+ `)
+
+ // The foo.stubs.source should depend on bar-lib
+ fooStubsSources := result.ModuleForTests("foo.stubs.source", "android_common").Module().(*Droidstubs)
+ android.AssertStringListContains(t, "foo stubs should depend on bar-lib", fooStubsSources.Javadoc.properties.Libs, "bar-lib")
+}
diff --git a/java/testing.go b/java/testing.go
index 9cf5999..ccbb638 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -394,6 +394,7 @@
aidl: {
export_include_dirs: ["framework/aidl"],
},
+ compile_dex: true,
}
android_app {
diff --git a/licenses/Android.bp b/licenses/Android.bp
index 61b17bf..eabc303 100644
--- a/licenses/Android.bp
+++ b/licenses/Android.bp
@@ -839,84 +839,84 @@
license_kind {
name: "SPDX-license-identifier-LGPL",
- conditions: ["restricted"],
+ conditions: ["restricted_if_statically_linked"],
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.0",
- conditions: ["restricted"],
+ conditions: ["restricted_if_statically_linked"],
url: "https://spdx.org/licenses/LGPL-2.0.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.0+",
- conditions: ["restricted"],
+ conditions: ["restricted_if_statically_linked"],
url: "https://spdx.org/licenses/LGPL-2.0+.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.0-only",
- conditions: ["restricted"],
+ conditions: ["restricted_if_statically_linked"],
url: "https://spdx.org/licenses/LGPL-2.0-only.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.0-or-later",
- conditions: ["restricted"],
+ conditions: ["restricted_if_statically_linked"],
url: "https://spdx.org/licenses/LGPL-2.0-or-later.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.1",
- conditions: ["restricted"],
+ conditions: ["restricted_if_statically_linked"],
url: "https://spdx.org/licenses/LGPL-2.1.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.1+",
- conditions: ["restricted"],
+ conditions: ["restricted_if_statically_linked"],
url: "https://spdx.org/licenses/LGPL-2.1+.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.1-only",
- conditions: ["restricted"],
+ conditions: ["restricted_if_statically_linked"],
url: "https://spdx.org/licenses/LGPL-2.1-only.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-2.1-or-later",
- conditions: ["restricted"],
+ conditions: ["restricted_if_statically_linked"],
url: "https://spdx.org/licenses/LGPL-2.1-or-later.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-3.0",
- conditions: ["restricted"],
+ conditions: ["restricted_if_statically_linked"],
url: "https://spdx.org/licenses/LGPL-3.0.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-3.0+",
- conditions: ["restricted"],
+ conditions: ["restricted_if_statically_linked"],
url: "https://spdx.org/licenses/LGPL-3.0+.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-3.0-only",
- conditions: ["restricted"],
+ conditions: ["restricted_if_statically_linked"],
url: "https://spdx.org/licenses/LGPL-3.0-only.html",
}
license_kind {
name: "SPDX-license-identifier-LGPL-3.0-or-later",
- conditions: ["restricted"],
+ conditions: ["restricted_if_statically_linked"],
url: "https://spdx.org/licenses/LGPL-3.0-or-later.html",
}
license_kind {
name: "SPDX-license-identifier-LGPLLR",
- conditions: ["restricted"],
+ conditions: ["restricted_if_statically_linked"],
url: "https://spdx.org/licenses/LGPLLR.html",
}
@@ -1152,7 +1152,7 @@
license_kind {
name: "SPDX-license-identifier-WTFPL",
- conditions: ["notice"],
+ conditions: ["permissive"],
url: "https://spdx.org/licenses/WTFPL.html",
}
diff --git a/python/Android.bp b/python/Android.bp
index 99c02bd..e49fa6a 100644
--- a/python/Android.bp
+++ b/python/Android.bp
@@ -27,15 +27,3 @@
],
pluginFor: ["soong_build"],
}
-
-// We're transitioning all of these flags to be true by default.
-// This is a defaults flag that can be used to easily add all of them to
-// certain modules.
-python_defaults {
- name: "modern_python_path_defaults",
- dont_add_top_level_directories_to_path: true,
- dont_add_entrypoint_folder_to_path: true,
- proto: {
- respect_pkg_path: true,
- },
-}
diff --git a/python/binary.go b/python/binary.go
index e6324a3..670e0d3 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -34,7 +34,7 @@
}
type bazelPythonBinaryAttributes struct {
- Main *string
+ Main *bazel.Label
Srcs bazel.LabelListAttribute
Deps bazel.LabelListAttribute
Python_version *string
@@ -42,17 +42,6 @@
}
func pythonBinaryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
- var main *string
- for _, propIntf := range m.GetProperties() {
- if props, ok := propIntf.(*BinaryProperties); ok {
- // main is optional.
- if props.Main != nil {
- main = props.Main
- break
- }
- }
- }
-
// TODO(b/182306917): this doesn't fully handle all nested props versioned
// by the python version, which would have been handled by the version split
// mutator. This is sufficient for very simple python_binary_host modules
@@ -72,13 +61,24 @@
baseAttrs := m.makeArchVariantBaseAttributes(ctx)
attrs := &bazelPythonBinaryAttributes{
- Main: main,
+ Main: nil,
Srcs: baseAttrs.Srcs,
Deps: baseAttrs.Deps,
Python_version: python_version,
Imports: baseAttrs.Imports,
}
+ for _, propIntf := range m.GetProperties() {
+ if props, ok := propIntf.(*BinaryProperties); ok {
+ // main is optional.
+ if props.Main != nil {
+ main := android.BazelLabelForModuleSrcSingle(ctx, *props.Main)
+ attrs.Main = &main
+ break
+ }
+ }
+ }
+
props := bazel.BazelTargetModuleProperties{
// Use the native py_binary rule.
Rule_class: "py_binary",
@@ -116,22 +116,6 @@
// doesn't exist next to the Android.bp, this attribute doesn't need to be set to true
// explicitly.
Auto_gen_config *bool
-
- // Currently, both the root of the zipfile and all the directories 1 level
- // below that are added to the python path. When this flag is set to true,
- // only the root of the zipfile will be added to the python path. This flag
- // will be removed after all the python modules in the tree have been updated
- // to support it. When using embedded_launcher: true, this is already the
- // behavior. The default is currently false.
- Dont_add_top_level_directories_to_path *bool
-
- // Setting this to true will mimic Python 3.11+'s PYTHON_SAFE_PATH environment
- // variable or -P flag, even on older python versions. This is a temporary
- // flag while modules are changed to support it, eventually true will be the
- // default and the flag will be removed. The default is currently false. It
- // is only applicable when embedded_launcher is false, when embedded_launcher
- // is true this is already implied.
- Dont_add_entrypoint_folder_to_path *bool
}
type binaryDecorator struct {
@@ -191,14 +175,9 @@
}
})
}
-
- addTopDirectoriesToPath := !proptools.BoolDefault(binary.binaryProperties.Dont_add_top_level_directories_to_path, false)
- dontAddEntrypointFolderToPath := proptools.BoolDefault(binary.binaryProperties.Dont_add_entrypoint_folder_to_path, false)
-
binFile := registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath,
binary.getHostInterpreterName(ctx, actualVersion),
- main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...),
- addTopDirectoriesToPath, dontAddEntrypointFolderToPath)
+ main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...))
return android.OptionalPathForPath(binFile)
}
diff --git a/python/builder.go b/python/builder.go
index f7f9a99..b4ab206 100644
--- a/python/builder.go
+++ b/python/builder.go
@@ -43,17 +43,7 @@
hostPar = pctx.AndroidStaticRule("hostPar",
blueprint.RuleParams{
- Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' -e 's/ADD_TOP_DIRECTORIES_TO_PATH/$addTopDirectoriesToPath/g' build/soong/python/scripts/stub_template_host.txt > $out.main && ` +
- `echo "#!/usr/bin/env $interp" >${out}.prefix &&` +
- `$mergeParCmd -p --prefix ${out}.prefix -pm $out.main $out $srcsZips && ` +
- `chmod +x $out && (rm -f $out.main; rm -f ${out}.prefix)`,
- CommandDeps: []string{"$mergeParCmd", "build/soong/python/scripts/stub_template_host.txt"},
- },
- "interp", "main", "srcsZips", "addTopDirectoriesToPath")
-
- hostParWithoutAddingEntrypointFolderToPath = pctx.AndroidStaticRule("hostParWithoutAddingEntrypointFolderToPath",
- blueprint.RuleParams{
- Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/__soong_entrypoint_redirector__.py/g' -e 's/ADD_TOP_DIRECTORIES_TO_PATH/$addTopDirectoriesToPath/g' build/soong/python/scripts/stub_template_host.txt > $out.main && ` +
+ Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/__soong_entrypoint_redirector__.py/g' build/soong/python/scripts/stub_template_host.txt > $out.main && ` +
"sed -e 's/ENTRY_POINT/$main/g' build/soong/python/scripts/main_non_embedded.py >`dirname $out`/__soong_entrypoint_redirector__.py && " +
"$parCmd -o $out.entrypoint_zip -C `dirname $out` -f `dirname $out`/__soong_entrypoint_redirector__.py && " +
`echo "#!/usr/bin/env $interp" >${out}.prefix &&` +
@@ -61,7 +51,7 @@
"chmod +x $out && (rm -f $out.main; rm -f ${out}.prefix; rm -f $out.entrypoint_zip; rm -f `dirname $out`/__soong_entrypoint_redirector__.py)",
CommandDeps: []string{"$mergeParCmd", "$parCmd", "build/soong/python/scripts/stub_template_host.txt", "build/soong/python/scripts/main_non_embedded.py"},
},
- "interp", "main", "srcsZips", "addTopDirectoriesToPath")
+ "interp", "main", "srcsZips")
embeddedPar = pctx.AndroidStaticRule("embeddedPar",
blueprint.RuleParams{
@@ -92,7 +82,7 @@
func registerBuildActionForParFile(ctx android.ModuleContext, embeddedLauncher bool,
launcherPath android.OptionalPath, interpreter, main, binName string,
- srcsZips android.Paths, addTopDirectoriesToPath bool, dontAddEntrypointFolderToPath bool) android.Path {
+ srcsZips android.Paths) android.Path {
// .intermediate output path for bin executable.
binFile := android.PathForModuleOut(ctx, binName)
@@ -101,37 +91,17 @@
implicits := srcsZips
if !embeddedLauncher {
- addDirsString := "False"
- if addTopDirectoriesToPath {
- addDirsString = "True"
- }
- if dontAddEntrypointFolderToPath {
- ctx.Build(pctx, android.BuildParams{
- Rule: hostParWithoutAddingEntrypointFolderToPath,
- Description: "host python archive",
- Output: binFile,
- Implicits: implicits,
- Args: map[string]string{
- "interp": strings.Replace(interpreter, "/", `\/`, -1),
- "main": strings.Replace(strings.TrimSuffix(main, pyExt), "/", ".", -1),
- "srcsZips": strings.Join(srcsZips.Strings(), " "),
- "addTopDirectoriesToPath": addDirsString,
- },
- })
- } else {
- ctx.Build(pctx, android.BuildParams{
- Rule: hostPar,
- Description: "host python archive",
- Output: binFile,
- Implicits: implicits,
- Args: map[string]string{
- "interp": strings.Replace(interpreter, "/", `\/`, -1),
- "main": strings.Replace(main, "/", `\/`, -1),
- "srcsZips": strings.Join(srcsZips.Strings(), " "),
- "addTopDirectoriesToPath": addDirsString,
- },
- })
- }
+ ctx.Build(pctx, android.BuildParams{
+ Rule: hostPar,
+ Description: "host python archive",
+ Output: binFile,
+ Implicits: implicits,
+ Args: map[string]string{
+ "interp": strings.Replace(interpreter, "/", `\/`, -1),
+ "main": strings.Replace(strings.TrimSuffix(main, pyExt), "/", ".", -1),
+ "srcsZips": strings.Join(srcsZips.Strings(), " "),
+ },
+ })
} else if launcherPath.Valid() {
// added launcherPath to the implicits Ninja dependencies.
implicits = append(implicits, launcherPath.Path())
diff --git a/python/defaults.go b/python/defaults.go
index c54e7d0..3dc5bc4 100644
--- a/python/defaults.go
+++ b/python/defaults.go
@@ -19,7 +19,7 @@
)
func init() {
- android.RegisterModuleType("python_defaults", defaultsFactory)
+ android.RegisterModuleType("python_defaults", DefaultsFactory)
}
type Defaults struct {
@@ -30,7 +30,7 @@
func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
-func defaultsFactory() android.Module {
+func DefaultsFactory() android.Module {
module := &Defaults{}
module.AddProperties(
diff --git a/python/proto.go b/python/proto.go
index 53ebb58..400e72c 100644
--- a/python/proto.go
+++ b/python/proto.go
@@ -18,7 +18,7 @@
"android/soong/android"
)
-func genProto(ctx android.ModuleContext, protoFile android.Path, flags android.ProtoFlags, pkgPath string) android.Path {
+func genProto(ctx android.ModuleContext, protoFile android.Path, flags android.ProtoFlags) android.Path {
srcsZipFile := android.PathForModuleGen(ctx, protoFile.Base()+".srcszip")
outDir := srcsZipFile.ReplaceExtension(ctx, "tmp")
@@ -36,9 +36,6 @@
zipCmd := rule.Command().
BuiltTool("soong_zip").
FlagWithOutput("-o ", srcsZipFile)
- if pkgPath != "" {
- zipCmd.FlagWithArg("-P ", pkgPath)
- }
zipCmd.FlagWithArg("-C ", outDir.String()).
FlagWithArg("-D ", outDir.String())
diff --git a/python/python.go b/python/python.go
index f6029c2..24e1bb2 100644
--- a/python/python.go
+++ b/python/python.go
@@ -120,15 +120,6 @@
// whether the binary is required to be built with embedded launcher for this actual_version.
// this is set by the python version mutator based on version-specific properties
Embedded_launcher *bool `blueprint:"mutated"`
-
- Proto struct {
- // Whether generated python protos should include the pkg_path in
- // their import statements. This is a temporary flag to help transition to
- // the new behavior where this is always true. It will be removed after all
- // usages of protos with pkg_path have been updated. The default is currently
- // false.
- Respect_pkg_path *bool
- }
}
type baseAttributes struct {
@@ -677,10 +668,7 @@
protoFlags := android.GetProtoFlags(ctx, &p.protoProperties)
protoFlags.OutTypeFlag = "--python_out"
- // TODO(b/247578564): Change the default to true, and then eventually remove respect_pkg_path
- protosRespectPkgPath := proptools.BoolDefault(p.properties.Proto.Respect_pkg_path, false)
- pkgPathForProtos := pkgPath
- if pkgPathForProtos != "" && protosRespectPkgPath {
+ if pkgPath != "" {
pkgPathStagingDir := android.PathForModuleGen(ctx, "protos_staged_for_pkg_path")
rule := android.NewRuleBuilder(pctx, ctx)
var stagedProtoSrcs android.Paths
@@ -692,11 +680,10 @@
}
rule.Build("stage_protos_for_pkg_path", "Stage protos for pkg_path")
protoSrcs = stagedProtoSrcs
- pkgPathForProtos = ""
}
for _, srcFile := range protoSrcs {
- zip := genProto(ctx, srcFile, protoFlags, pkgPathForProtos)
+ zip := genProto(ctx, srcFile, protoFlags)
zips = append(zips, zip)
}
}
diff --git a/python/scripts/stub_template_host.txt b/python/scripts/stub_template_host.txt
index a0ddffe..5eedc18 100644
--- a/python/scripts/stub_template_host.txt
+++ b/python/scripts/stub_template_host.txt
@@ -23,16 +23,7 @@
zf.extractall(runfiles_path)
zf.close()
- # Add runfiles path to PYTHONPATH.
- python_path_entries = [runfiles_path]
-
- if ADD_TOP_DIRECTORIES_TO_PATH:
- # Add top dirs within runfiles path to PYTHONPATH.
- top_entries = [os.path.join(runfiles_path, i) for i in os.listdir(runfiles_path)]
- top_pkg_dirs = [i for i in top_entries if os.path.isdir(i)]
- python_path_entries += top_pkg_dirs
-
- new_python_path = ":".join(python_path_entries)
+ new_python_path = runfiles_path
old_python_path = os.environ.get(PYTHON_PATH)
if old_python_path:
diff --git a/python/tests/dont_import_folder_of_entrypoint/Android.bp b/python/tests/dont_import_folder_of_entrypoint/Android.bp
index fc62813..e54e9b2 100644
--- a/python/tests/dont_import_folder_of_entrypoint/Android.bp
+++ b/python/tests/dont_import_folder_of_entrypoint/Android.bp
@@ -1,3 +1,7 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
python_test_host {
name: "py_dont_import_folder_of_entrypoint_test",
main: "mypkg/main.py",
@@ -5,7 +9,6 @@
"mypkg/main.py",
"mypkg/mymodule.py",
],
- defaults: ["modern_python_path_defaults"],
}
python_test_host {
diff --git a/python/tests/proto_pkg_path/Android.bp b/python/tests/proto_pkg_path/Android.bp
index ef79850..a6bfd3f 100644
--- a/python/tests/proto_pkg_path/Android.bp
+++ b/python/tests/proto_pkg_path/Android.bp
@@ -12,6 +12,5 @@
pkg_path: "mylib/subpackage",
proto: {
canonical_path_from_root: false,
- respect_pkg_path: true,
},
}
diff --git a/python/tests/top_level_dirs/Android.bp b/python/tests/top_level_dirs/Android.bp
index 0b15ce7..574350a 100644
--- a/python/tests/top_level_dirs/Android.bp
+++ b/python/tests/top_level_dirs/Android.bp
@@ -1,3 +1,7 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
python_test_host {
name: "py_dont_add_top_level_dirs_test",
main: "main.py",
@@ -5,5 +9,4 @@
"main.py",
"mypkg/mymodule.py",
],
- dont_add_top_level_directories_to_path: true,
}
diff --git a/rust/binary.go b/rust/binary.go
index 41110f9..056888e 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -106,7 +106,7 @@
if static {
deps.CrtBegin = []string{"libc_musl_crtbegin_static"}
} else {
- deps.CrtBegin = []string{"libc_musl_crtbegin_dynamic", "musl_linker_script"}
+ deps.CrtBegin = []string{"libc_musl_crtbegin_dynamic"}
}
deps.CrtEnd = []string{"libc_musl_crtend"}
}
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 0199d3a..17d80dd 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -30,7 +30,7 @@
defaultBindgenFlags = []string{""}
// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
- bindgenClangVersion = "clang-r450784d"
+ bindgenClangVersion = "clang-r468909b"
_ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
@@ -51,7 +51,7 @@
})
_ = pctx.VariableFunc("bindgenClangLibdir", func(ctx android.PackageVarContext) string {
if ctx.Config().UseHostMusl() {
- return "musl/lib64/"
+ return "musl/lib/"
} else {
return "lib64/"
}
@@ -239,6 +239,10 @@
cflags = append(cflags, "-x c")
}
+ // clang-r468909b complains about the -x c in the flags in clang-sys parse_search_paths:
+ // clang: error: '-x c' after last input file has no effect [-Werror,-Wunused-command-line-argument]
+ cflags = append(cflags, "-Wno-unused-command-line-argument")
+
// 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")
diff --git a/rust/compiler.go b/rust/compiler.go
index bf6a488..6055158 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -161,7 +161,7 @@
// This is primarily meant for rust_binary and rust_ffi modules where the default
// linkage of libstd might need to be overridden in some use cases. This should
// generally be avoided with other module types since it may cause collisions at
- // linkage if all dependencies of the root binary module do not link against libstd\
+ // linkage if all dependencies of the root binary module do not link against libstd
// the same way.
Prefer_rlib *bool `android:"arch_variant"`
diff --git a/rust/config/Android.bp b/rust/config/Android.bp
index be73d69..79ea7a1 100644
--- a/rust/config/Android.bp
+++ b/rust/config/Android.bp
@@ -15,6 +15,7 @@
"arm64_device.go",
"global.go",
"lints.go",
+ "riscv64_device.go",
"toolchain.go",
"darwin_host.go",
"x86_linux_bionic_host.go",
diff --git a/rust/config/riscv64_device.go b/rust/config/riscv64_device.go
new file mode 100644
index 0000000..d014dbf
--- /dev/null
+++ b/rust/config/riscv64_device.go
@@ -0,0 +1,91 @@
+// Copyright 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 config
+
+import (
+ "strings"
+
+ "android/soong/android"
+)
+
+var (
+ Riscv64RustFlags = []string{}
+ Riscv64ArchFeatureRustFlags = map[string][]string{"": {}}
+ Riscv64LinkFlags = []string{}
+
+ Riscv64ArchVariantRustFlags = map[string][]string{"": {}}
+)
+
+func init() {
+ registerToolchainFactory(android.Android, android.Riscv64, Riscv64ToolchainFactory)
+
+ pctx.StaticVariable("Riscv64ToolchainRustFlags", strings.Join(Riscv64RustFlags, " "))
+ pctx.StaticVariable("Riscv64ToolchainLinkFlags", strings.Join(Riscv64LinkFlags, " "))
+
+ for variant, rustFlags := range Riscv64ArchVariantRustFlags {
+ pctx.StaticVariable("Riscv64"+variant+"VariantRustFlags",
+ strings.Join(rustFlags, " "))
+ }
+
+}
+
+type toolchainRiscv64 struct {
+ toolchain64Bit
+ toolchainRustFlags string
+}
+
+func (t *toolchainRiscv64) RustTriple() string {
+ return "riscv64-linux-android"
+}
+
+func (t *toolchainRiscv64) ToolchainLinkFlags() string {
+ // Prepend the lld flags from cc_config so we stay in sync with cc
+ return "${config.DeviceGlobalLinkFlags} ${cc_config.Riscv64Lldflags} ${config.Riscv64ToolchainLinkFlags}"
+}
+
+func (t *toolchainRiscv64) ToolchainRustFlags() string {
+ return t.toolchainRustFlags
+}
+
+func (t *toolchainRiscv64) RustFlags() string {
+ return "${config.Riscv64ToolchainRustFlags}"
+}
+
+func (t *toolchainRiscv64) Supported() bool {
+ return true
+}
+
+func (toolchainRiscv64) LibclangRuntimeLibraryArch() string {
+ return "riscv64"
+}
+
+func Riscv64ToolchainFactory(arch android.Arch) Toolchain {
+ archVariant := arch.ArchVariant
+
+ toolchainRustFlags := []string{
+ "${config.Riscv64ToolchainRustFlags}",
+ "${config.Riscv64" + archVariant + "VariantRustFlags}",
+ }
+
+ toolchainRustFlags = append(toolchainRustFlags, deviceGlobalRustFlags...)
+
+ for _, feature := range arch.ArchFeatures {
+ toolchainRustFlags = append(toolchainRustFlags, Riscv64ArchFeatureRustFlags[feature]...)
+ }
+
+ return &toolchainRiscv64{
+ toolchainRustFlags: strings.Join(toolchainRustFlags, " "),
+ }
+}
diff --git a/rust/fuzz.go b/rust/fuzz.go
index 586095c..6faf55c 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -34,6 +34,7 @@
*binaryDecorator
fuzzPackagedModule fuzz.FuzzPackagedModule
+ sharedLibraries android.Paths
}
var _ compiler = (*fuzzDecorator)(nil)
@@ -86,6 +87,15 @@
&fuzzer.fuzzPackagedModule.FuzzProperties)
}
+func (fuzzer *fuzzDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
+ out := fuzzer.binaryDecorator.compile(ctx, flags, deps)
+
+ // Grab the list of required shared libraries.
+ fuzzer.sharedLibraries, _ = cc.CollectAllSharedDependencies(ctx)
+
+ return out
+}
+
func (fuzzer *fuzzDecorator) stdLinkage(ctx *depsContext) RustLinkage {
return RlibLinkage
}
@@ -149,11 +159,8 @@
// The executable.
files = append(files, fuzz.FileToZip{rustModule.UnstrippedOutputFile(), ""})
- // Grab the list of required shared libraries.
- sharedLibraries := fuzz.CollectAllSharedDependencies(ctx, module, cc.UnstrippedOutputFile, cc.IsValidSharedDependency)
-
// Package shared libraries
- files = append(files, cc.GetSharedLibsToZip(sharedLibraries, rustModule, &s.FuzzPackager, archString, "lib", &sharedLibraryInstalled)...)
+ files = append(files, cc.GetSharedLibsToZip(fuzzModule.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/library.go b/rust/library.go
index c2ce9de..bc9c9aa 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -267,84 +267,94 @@
var _ libraryInterface = (*libraryDecorator)(nil)
var _ exportedFlagsProducer = (*libraryDecorator)(nil)
-// rust_library produces all rust variants.
+// rust_library produces all Rust variants (rust_library_dylib and
+// rust_library_rlib).
func RustLibraryFactory() android.Module {
module, library := NewRustLibrary(android.HostAndDeviceSupported)
library.BuildOnlyRust()
return module.Init()
}
-// rust_ffi produces all ffi variants.
+// rust_ffi produces all FFI variants (rust_ffi_shared and
+// rust_ffi_static).
func RustFFIFactory() android.Module {
module, library := NewRustLibrary(android.HostAndDeviceSupported)
library.BuildOnlyFFI()
return module.Init()
}
-// rust_library_dylib produces a dylib.
+// rust_library_dylib produces a Rust dylib (Rust crate type "dylib").
func RustLibraryDylibFactory() android.Module {
module, library := NewRustLibrary(android.HostAndDeviceSupported)
library.BuildOnlyDylib()
return module.Init()
}
-// rust_library_rlib produces an rlib.
+// rust_library_rlib produces an rlib (Rust crate type "rlib").
func RustLibraryRlibFactory() android.Module {
module, library := NewRustLibrary(android.HostAndDeviceSupported)
library.BuildOnlyRlib()
return module.Init()
}
-// rust_ffi_shared produces a shared library.
+// rust_ffi_shared produces a shared library (Rust crate type
+// "cdylib").
func RustFFISharedFactory() android.Module {
module, library := NewRustLibrary(android.HostAndDeviceSupported)
library.BuildOnlyShared()
return module.Init()
}
-// rust_ffi_static produces a static library.
+// rust_ffi_static produces a static library (Rust crate type
+// "staticlib").
func RustFFIStaticFactory() android.Module {
module, library := NewRustLibrary(android.HostAndDeviceSupported)
library.BuildOnlyStatic()
return module.Init()
}
-// rust_library_host produces all rust variants.
+// rust_library_host produces all Rust variants for the host
+// (rust_library_dylib_host and rust_library_rlib_host).
func RustLibraryHostFactory() android.Module {
module, library := NewRustLibrary(android.HostSupported)
library.BuildOnlyRust()
return module.Init()
}
-// rust_ffi_host produces all FFI variants.
+// rust_ffi_host produces all FFI variants for the host
+// (rust_ffi_static_host and rust_ffi_shared_host).
func RustFFIHostFactory() android.Module {
module, library := NewRustLibrary(android.HostSupported)
library.BuildOnlyFFI()
return module.Init()
}
-// rust_library_dylib_host produces a dylib.
+// rust_library_dylib_host produces a dylib for the host (Rust crate
+// type "dylib").
func RustLibraryDylibHostFactory() android.Module {
module, library := NewRustLibrary(android.HostSupported)
library.BuildOnlyDylib()
return module.Init()
}
-// rust_library_rlib_host produces an rlib.
+// rust_library_rlib_host produces an rlib for the host (Rust crate
+// type "rlib").
func RustLibraryRlibHostFactory() android.Module {
module, library := NewRustLibrary(android.HostSupported)
library.BuildOnlyRlib()
return module.Init()
}
-// rust_ffi_static_host produces a static library.
+// rust_ffi_static_host produces a static library for the host (Rust
+// crate type "staticlib").
func RustFFIStaticHostFactory() android.Module {
module, library := NewRustLibrary(android.HostSupported)
library.BuildOnlyStatic()
return module.Init()
}
-// rust_ffi_shared_host produces an shared library.
+// rust_ffi_shared_host produces an shared library for the host (Rust
+// crate type "cdylib").
func RustFFISharedHostFactory() android.Module {
module, library := NewRustLibrary(android.HostSupported)
library.BuildOnlyShared()
diff --git a/rust/library_test.go b/rust/library_test.go
index 4633cc7..e3e4d0f 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -30,11 +30,11 @@
srcs: ["foo.rs"],
crate_name: "foo",
}
- rust_ffi_host {
- name: "libfoo.ffi",
- srcs: ["foo.rs"],
- crate_name: "foo"
- }`)
+ rust_ffi_host {
+ name: "libfoo.ffi",
+ srcs: ["foo.rs"],
+ crate_name: "foo"
+ }`)
// Test all variants are being built.
libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
@@ -45,7 +45,7 @@
rlibCrateType := "rlib"
dylibCrateType := "dylib"
sharedCrateType := "cdylib"
- staticCrateType := "static"
+ staticCrateType := "staticlib"
// Test crate type for rlib is correct.
if !strings.Contains(libfooRlib.Args["rustcFlags"], "crate-type="+rlibCrateType) {
diff --git a/rust/rust.go b/rust/rust.go
index 1517e62..28a300b 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -1615,7 +1615,7 @@
}
}
- if depTag == procMacroDepTag {
+ if depTag == procMacroDepTag || depTag == customBindgenDepTag {
return false
}
@@ -1664,6 +1664,10 @@
}
}
+func (c *Module) Partition() string {
+ return ""
+}
+
var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault
var String = proptools.String
diff --git a/rust/sanitize.go b/rust/sanitize.go
index a3c5cb5..c68137e 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -189,16 +189,6 @@
}
}
- // TODO:(b/178369775)
- // For now sanitizing is only supported on devices
- if ctx.Os() == android.Android && Bool(s.Fuzzer) {
- sanitize.Properties.SanitizerEnabled = true
- }
-
- if ctx.Os() == android.Android && Bool(s.Address) {
- sanitize.Properties.SanitizerEnabled = true
- }
-
// HWASan requires AArch64 hardware feature (top-byte-ignore).
if ctx.Arch().ArchType != android.Arm64 || !ctx.Os().Bionic() {
s.Hwaddress = nil
@@ -219,7 +209,9 @@
s.Memtag_heap = nil
}
- if ctx.Os() == android.Android && (Bool(s.Hwaddress) || Bool(s.Address) || Bool(s.Memtag_heap)) {
+ // TODO:(b/178369775)
+ // For now sanitizing is only supported on devices
+ if ctx.Os() == android.Android && (Bool(s.Hwaddress) || Bool(s.Address) || Bool(s.Memtag_heap) || Bool(s.Fuzzer)) {
sanitize.Properties.SanitizerEnabled = true
}
}
diff --git a/scripts/gen_ndk_usedby_apex.sh b/scripts/gen_ndk_usedby_apex.sh
index 0d3ed5a..93d1370 100755
--- a/scripts/gen_ndk_usedby_apex.sh
+++ b/scripts/gen_ndk_usedby_apex.sh
@@ -19,6 +19,7 @@
# For example, current line llvm-readelf output is:
# 1: 00000000 0 FUNC GLOBAL DEFAULT UND dlopen@LIBC
# After the parse function below "dlopen" would be write to the output file.
+
printHelp() {
echo "**************************** Usage Instructions ****************************"
echo "This script is used to generate the Mainline modules used-by NDK symbols."
@@ -29,30 +30,33 @@
}
parseReadelfOutput() {
+ local readelfOutput=$1; shift
+ local ndkApisOutput=$1; shift
while IFS= read -r line
do
if [[ $line = *FUNC*GLOBAL*UND*@* ]] ;
then
- echo "$line" | sed -r 's/.*UND (.*@.*)/\1/g' >> "$2"
+ echo "$line" | sed -r 's/.*UND (.*@.*)/\1/g' >> "${ndkApisOutput}"
fi
- done < "$1"
- echo "" >> "$2"
+ done < "${readelfOutput}"
+ echo "" >> "${ndkApisOutput}"
}
unzipJarAndApk() {
- tmpUnzippedDir="$1"/tmpUnzipped
- [[ -e "$tmpUnzippedDir" ]] && rm -rf "$tmpUnzippedDir"
- mkdir -p "$tmpUnzippedDir"
- find "$1" -name "*.jar" -exec unzip -o {} -d "$tmpUnzippedDir" \;
- find "$1" -name "*.apk" -exec unzip -o {} -d "$tmpUnzippedDir" \;
- find "$tmpUnzippedDir" -name "*.MF" -exec rm {} \;
+ local dir="$1"; shift
+ local tmpUnzippedDir="$1"; shift
+ mkdir -p "${tmpUnzippedDir}"
+ find "$dir" -name "*.jar" -exec unzip -o {} -d "${tmpUnzippedDir}" \;
+ find "$dir" -name "*.apk" -exec unzip -o {} -d "${tmpUnzippedDir}" \;
+ find "${tmpUnzippedDir}" -name "*.MF" -exec rm {} \;
}
lookForExecFile() {
- dir="$1"
- readelf="$2"
- find "$dir" -type f -name "*.so" -exec "$2" --dyn-symbols {} >> "$dir"/../tmpReadelf.txt \;
- find "$dir" -type f -perm /111 ! -name "*.so" -exec "$2" --dyn-symbols {} >> "$dir"/../tmpReadelf.txt \;
+ local dir="$1"; shift
+ local readelf="$1"; shift
+ local tmpOutput="$1"; shift
+ find -L "$dir" -type f -name "*.so" -exec "${readelf}" --dyn-symbols {} >> "${tmpOutput}" \;
+ find -L "$dir" -type f -perm /111 ! -name "*.so" -exec "${readelf}" --dyn-symbols {} >> "${tmpOutput}" \;
}
if [[ "$1" == "help" ]]
@@ -62,11 +66,22 @@
then
echo "Wrong argument length. Expecting 3 argument representing image file directory, llvm-readelf tool path, output path."
else
- unzipJarAndApk "$1"
- lookForExecFile "$1" "$2"
- tmpReadelfOutput="$1/../tmpReadelf.txt"
- [[ -e "$3" ]] && rm "$3"
- parseReadelfOutput "$tmpReadelfOutput" "$3"
- [[ -e "$tmpReadelfOutput" ]] && rm "$tmpReadelfOutput"
- rm -rf "$1/tmpUnzipped"
-fi
\ No newline at end of file
+ imageDir="$1"; shift
+ readelf="$1"; shift
+ outputFile="$1"; shift
+
+ tmpReadelfOutput=$(mktemp /tmp/temporary-file.XXXXXXXX)
+ tmpUnzippedDir=$(mktemp -d /tmp/temporary-dir.XXXXXXXX)
+ trap 'rm -rf -- "${tmpReadelfOutput}" "${tmpUnzippedDir}"' EXIT
+
+ # If there are any jars or apks, unzip them to surface native files.
+ unzipJarAndApk "${imageDir}" "${tmpUnzippedDir}"
+ # Analyze the unzipped files.
+ lookForExecFile "${tmpUnzippedDir}" "${readelf}" "${tmpReadelfOutput}"
+
+ # Analyze the apex image staging dir itself.
+ lookForExecFile "${imageDir}" "${readelf}" "${tmpReadelfOutput}"
+
+ [[ -e "${outputFile}" ]] && rm "${outputFile}"
+ parseReadelfOutput "${tmpReadelfOutput}" "${outputFile}"
+fi
diff --git a/scripts/microfactory.bash b/scripts/microfactory.bash
index 192b38f..ce4a0e4 100644
--- a/scripts/microfactory.bash
+++ b/scripts/microfactory.bash
@@ -59,7 +59,7 @@
BUILDDIR=$(getoutdir) \
SRCDIR=${TOP} \
BLUEPRINTDIR=${TOP}/build/blueprint \
- EXTRA_ARGS="-pkg-path android/soong=${TOP}/build/soong -pkg-path rbcrun=${TOP}/build/make/tools/rbcrun -pkg-path google.golang.org/protobuf=${TOP}/external/golang-protobuf -pkg-path go.starlark.net=${TOP}/external/starlark-go" \
+ EXTRA_ARGS="-pkg-path android/soong=${TOP}/build/soong -pkg-path prebuilts/bazel/common/proto=${TOP}/prebuilts/bazel/common/proto -pkg-path rbcrun=${TOP}/build/make/tools/rbcrun -pkg-path google.golang.org/protobuf=${TOP}/external/golang-protobuf -pkg-path go.starlark.net=${TOP}/external/starlark-go" \
build_go $@
}
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 4be0ace..92ecd5e 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -17,6 +17,7 @@
import (
"fmt"
"path/filepath"
+ "strings"
"testing"
"android/soong/android"
@@ -80,7 +81,7 @@
// Add a platform_bootclasspath that depends on the fragment.
fixtureAddPlatformBootclasspathForBootclasspathFragment("com.android.art", "mybootclasspathfragment"),
- java.FixtureConfigureBootJars("com.android.art:mybootlib"),
+ java.PrepareForBootImageConfigTest,
android.FixtureWithRootAndroidBp(`
sdk {
name: "mysdk",
@@ -99,7 +100,7 @@
bootclasspath_fragment {
name: "mybootclasspathfragment",
image_name: "art",
- contents: ["mybootlib"],
+ contents: ["core1", "core2"],
apex_available: ["com.android.art"],
hidden_api: {
split_packages: ["*"],
@@ -113,19 +114,32 @@
}
java_library {
- name: "mybootlib",
+ name: "core1",
srcs: ["Test.java"],
system_modules: "none",
sdk_version: "none",
compile_dex: true,
apex_available: ["com.android.art"],
}
- `),
+
+ java_library {
+ name: "core2",
+ srcs: ["Test.java"],
+ system_modules: "none",
+ sdk_version: "none",
+ compile_dex: true,
+ apex_available: ["com.android.art"],
+ }
+`),
).RunTest(t)
// A preparer to update the test fixture used when processing an unpackage snapshot.
preparerForSnapshot := fixtureAddPrebuiltApexForBootclasspathFragment("com.android.art", "mybootclasspathfragment")
+ // Check that source on its own configures the bootImageConfig correctly.
+ java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/mybootclasspathfragment/android_common_apex10000/meta_lic")
+ java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic")
+
CheckSnapshot(t, result, "mysdk", "",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
@@ -136,7 +150,10 @@
visibility: ["//visibility:public"],
apex_available: ["com.android.art"],
image_name: "art",
- contents: ["mybootlib"],
+ contents: [
+ "core1",
+ "core2",
+ ],
hidden_api: {
annotation_flags: "hiddenapi/annotation-flags.csv",
metadata: "hiddenapi/metadata.csv",
@@ -148,11 +165,19 @@
}
java_import {
- name: "mybootlib",
+ name: "core1",
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["com.android.art"],
- jars: ["java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar"],
+ jars: ["java_boot_libs/snapshot/jars/are/invalid/core1.jar"],
+}
+
+java_import {
+ name: "core2",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["com.android.art"],
+ jars: ["java_boot_libs/snapshot/jars/are/invalid/core2.jar"],
}
`),
checkAllCopyRules(`
@@ -162,31 +187,54 @@
.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/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/core1.jar
+.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/core2.jar
`),
snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot),
// Check the behavior of the snapshot without the source.
snapshotTestChecker(checkSnapshotWithoutSource, func(t *testing.T, result *android.TestResult) {
- // Make sure that the boot jars package check rule includes the dex jar retrieved from the prebuilt apex.
- checkBootJarsPackageCheckRule(t, result, "out/soong/.intermediates/prebuilts/apex/com.android.art.deapexer/android_common/deapexer/javalib/mybootlib.jar")
+ // Make sure that the boot jars package check rule includes the dex jars retrieved from the prebuilt apex.
+ checkBootJarsPackageCheckRule(t, result,
+ "out/soong/.intermediates/prebuilts/apex/com.android.art.deapexer/android_common/deapexer/javalib/core1.jar",
+ "out/soong/.intermediates/prebuilts/apex/com.android.art.deapexer/android_common/deapexer/javalib/core2.jar",
+ "out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar")
+ java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/snapshot/mybootclasspathfragment/android_common_com.android.art/meta_lic")
+ java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic")
}),
snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot),
+
+ // Check the behavior of the snapshot when the source is preferred.
+ snapshotTestChecker(checkSnapshotWithSourcePreferred, func(t *testing.T, result *android.TestResult) {
+ java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/mybootclasspathfragment/android_common_apex10000/meta_lic")
+ java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic")
+ }),
+
snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot),
+
+ // Check the behavior of the snapshot when it is preferred.
+ snapshotTestChecker(checkSnapshotPreferredWithSource, func(t *testing.T, result *android.TestResult) {
+ java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/snapshot/prebuilt_mybootclasspathfragment/android_common_com.android.art/meta_lic")
+ java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic")
+ }),
)
- // Make sure that the boot jars package check rule includes the dex jar created from the source.
- checkBootJarsPackageCheckRule(t, result, "out/soong/.intermediates/mybootlib/android_common_apex10000/aligned/mybootlib.jar")
+ // Make sure that the boot jars package check rule includes the dex jars created from the source.
+ checkBootJarsPackageCheckRule(t, result,
+ "out/soong/.intermediates/core1/android_common_apex10000/aligned/core1.jar",
+ "out/soong/.intermediates/core2/android_common_apex10000/aligned/core2.jar",
+ "out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar")
}
// checkBootJarsPackageCheckRule checks that the supplied module is an input to the boot jars
// package check rule.
-func checkBootJarsPackageCheckRule(t *testing.T, result *android.TestResult, expectedModule string) {
+func checkBootJarsPackageCheckRule(t *testing.T, result *android.TestResult, expectedModules ...string) {
+ t.Helper()
platformBcp := result.ModuleForTests("platform-bootclasspath", "android_common")
bootJarsCheckRule := platformBcp.Rule("boot_jars_package_check")
command := bootJarsCheckRule.RuleParams.Command
- expectedCommandArgs := " out/soong/host/linux-x86/bin/dexdump build/soong/scripts/check_boot_jars/package_allowed_list.txt " + expectedModule + " &&"
+ expectedCommandArgs := " build/soong/scripts/check_boot_jars/package_allowed_list.txt " + strings.Join(expectedModules, " ") + " &&"
android.AssertStringDoesContain(t, "boot jars package check", command, expectedCommandArgs)
}
@@ -310,6 +358,7 @@
visibility: ["//visibility:public"],
apex_available: ["myapex"],
jars: ["java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar"],
+ min_sdk_version: "2",
permitted_packages: ["mybootlib"],
}
@@ -829,6 +878,7 @@
visibility: ["//visibility:public"],
apex_available: ["myapex"],
jars: ["java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar"],
+ min_sdk_version: "1",
permitted_packages: ["mybootlib"],
}
diff --git a/sdk/build_release.go b/sdk/build_release.go
index ac57a32..6bb05a3 100644
--- a/sdk/build_release.go
+++ b/sdk/build_release.go
@@ -100,6 +100,7 @@
// Add the dessert build releases from oldest to newest.
buildReleaseS = initBuildRelease("S")
buildReleaseT = initBuildRelease("Tiramisu")
+ buildReleaseU = initBuildRelease("UpsideDownCake")
// Add the current build release which is always treated as being more recent than any other
// build release, including those added in tests.
diff --git a/sdk/build_release_test.go b/sdk/build_release_test.go
index 13730cb..5bf57b5 100644
--- a/sdk/build_release_test.go
+++ b/sdk/build_release_test.go
@@ -42,7 +42,7 @@
android.AssertDeepEquals(t, "release", (*buildRelease)(nil), release)
// Uses a wildcard in the error message to allow for additional build releases to be added to
// the supported set without breaking this test.
- android.FailIfNoMatchingErrors(t, `unknown release "A", expected one of \[S,Tiramisu,F1,F2,current\]`, []error{err})
+ android.FailIfNoMatchingErrors(t, `unknown release "A", expected one of \[S,Tiramisu,UpsideDownCake,F1,F2,current\]`, []error{err})
})
}
@@ -60,7 +60,7 @@
t.Run("closed range", func(t *testing.T) {
set, err := parseBuildReleaseSet("S-F1")
android.AssertDeepEquals(t, "errors", nil, err)
- android.AssertStringEquals(t, "set", "[S,Tiramisu,F1]", set.String())
+ android.AssertStringEquals(t, "set", "[S,Tiramisu,UpsideDownCake,F1]", set.String())
})
invalidAReleaseMessage := `unknown release "A", expected one of ` + allBuildReleaseSet.String()
t.Run("invalid release", func(t *testing.T) {
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 51903ce3..2ade146 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -352,6 +352,73 @@
})
}
+func TestSnapshotWithJavaLibrary_MinSdkVersion(t *testing.T) {
+ runTest := func(t *testing.T, targetBuildRelease, minSdkVersion, expectedMinSdkVersion string) {
+ result := android.GroupFixturePreparers(
+ prepareForSdkTestWithJava,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_version_active_codenames = []string{"S", "Tiramisu", "Unfinalized"}
+ }),
+ android.FixtureMergeEnv(map[string]string{
+ "SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": targetBuildRelease,
+ }),
+ ).RunTestWithBp(t, fmt.Sprintf(`
+ sdk {
+ name: "mysdk",
+ java_header_libs: ["mylib"],
+ }
+
+ java_library {
+ name: "mylib",
+ srcs: ["Test.java"],
+ system_modules: "none",
+ sdk_version: "none",
+ compile_dex: true,
+ min_sdk_version: "%s",
+ }
+ `, minSdkVersion))
+
+ expectedMinSdkVersionLine := ""
+ if expectedMinSdkVersion != "" {
+ expectedMinSdkVersionLine = fmt.Sprintf(" min_sdk_version: %q,\n", expectedMinSdkVersion)
+ }
+
+ CheckSnapshot(t, result, "mysdk", "",
+ checkAndroidBpContents(fmt.Sprintf(`
+// This is auto-generated. DO NOT EDIT.
+
+java_import {
+ name: "mylib",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ jars: ["java/mylib.jar"],
+%s}
+`, expectedMinSdkVersionLine)),
+ )
+ }
+
+ t.Run("min_sdk_version=S in S", func(t *testing.T) {
+ // min_sdk_version was not added to java_import until Tiramisu.
+ runTest(t, "S", "S", "")
+ })
+
+ t.Run("min_sdk_version=S in Tiramisu", func(t *testing.T) {
+ // The canonical form of S is 31.
+ runTest(t, "Tiramisu", "S", "31")
+ })
+
+ t.Run("min_sdk_version=24 in Tiramisu", func(t *testing.T) {
+ // A numerical min_sdk_version is already in canonical form.
+ runTest(t, "Tiramisu", "24", "24")
+ })
+
+ t.Run("min_sdk_version=Unfinalized in latest", func(t *testing.T) {
+ // An unfinalized min_sdk_version has no numeric value yet.
+ runTest(t, "", "Unfinalized", "Unfinalized")
+ })
+}
+
func TestSnapshotWithJavaSystemserverLibrary(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 2f9aee9..108a664 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -409,60 +409,6 @@
)
})
- t.Run("SOONG_SDK_SNAPSHOT_PREFER=true", func(t *testing.T) {
- result := android.GroupFixturePreparers(
- preparer,
- android.FixtureMergeEnv(map[string]string{
- "SOONG_SDK_SNAPSHOT_PREFER": "true",
- }),
- ).RunTest(t)
-
- checkZipFile(t, result, "out/soong/.intermediates/mysdk/common_os/mysdk-current.zip")
-
- CheckSnapshot(t, result, "mysdk", "",
- checkAndroidBpContents(`
-// This is auto-generated. DO NOT EDIT.
-
-java_import {
- name: "myjavalib",
- prefer: true,
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
- jars: ["java/myjavalib.jar"],
-}
- `),
- )
- })
-
- t.Run("SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR=module:build_from_source", func(t *testing.T) {
- result := android.GroupFixturePreparers(
- preparer,
- android.FixtureMergeEnv(map[string]string{
- "SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR": "module:build_from_source",
- }),
- ).RunTest(t)
-
- checkZipFile(t, result, "out/soong/.intermediates/mysdk/common_os/mysdk-current.zip")
-
- CheckSnapshot(t, result, "mysdk", "",
- checkAndroidBpContents(`
-// This is auto-generated. DO NOT EDIT.
-
-java_import {
- name: "myjavalib",
- prefer: false,
- use_source_config_var: {
- config_namespace: "module",
- var_name: "build_from_source",
- },
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
- jars: ["java/myjavalib.jar"],
-}
- `),
- )
- })
-
t.Run("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE=S", func(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForSdkTestWithJava,
diff --git a/sdk/systemserverclasspath_fragment_sdk_test.go b/sdk/systemserverclasspath_fragment_sdk_test.go
index 1ac405d..2a17cdc 100644
--- a/sdk/systemserverclasspath_fragment_sdk_test.go
+++ b/sdk/systemserverclasspath_fragment_sdk_test.go
@@ -120,6 +120,7 @@
visibility: ["//visibility:public"],
apex_available: ["myapex"],
jars: ["java_systemserver_libs/snapshot/jars/are/invalid/mylib.jar"],
+ min_sdk_version: "2",
permitted_packages: ["mylib"],
}
@@ -181,6 +182,7 @@
visibility: ["//visibility:public"],
apex_available: ["myapex"],
jars: ["java_systemserver_libs/snapshot/jars/are/invalid/mylib.jar"],
+ min_sdk_version: "2",
permitted_packages: ["mylib"],
}
diff --git a/sdk/update.go b/sdk/update.go
index 92a13fa..baa2033 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -34,41 +34,6 @@
// Environment variables that affect the generated snapshot
// ========================================================
//
-// SOONG_SDK_SNAPSHOT_PREFER
-// By default every module in the generated snapshot has prefer: false. Building it
-// with SOONG_SDK_SNAPSHOT_PREFER=true will force them to use prefer: true.
-//
-// SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR
-// If set this specifies the Soong config var that can be used to control whether the prebuilt
-// modules from the generated snapshot or the original source modules. Values must be a colon
-// separated pair of strings, the first of which is the Soong config namespace, and the second
-// is the name of the variable within that namespace.
-//
-// The config namespace and var name are used to set the `use_source_config_var` property. That
-// in turn will cause the generated prebuilts to use the soong config variable to select whether
-// source or the prebuilt is used.
-// e.g. If an sdk snapshot is built using:
-// m SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR=acme:build_from_source sdkextensions-sdk
-// Then the resulting snapshot will include:
-// use_source_config_var: {
-// config_namespace: "acme",
-// var_name: "build_from_source",
-// }
-//
-// Assuming that the config variable is defined in .mk using something like:
-// $(call add_soong_config_namespace,acme)
-// $(call add_soong_config_var_value,acme,build_from_source,true)
-//
-// Then when the snapshot is unpacked in the repository it will have the following behavior:
-// m droid - will use the sdkextensions-sdk prebuilts if present. Otherwise, it will use the
-// sources.
-// m SOONG_CONFIG_acme_build_from_source=true droid - will use the sdkextensions-sdk
-// sources, if present. Otherwise, it will use the prebuilts.
-//
-// This is a temporary mechanism to control the prefer flags and will be removed once a more
-// maintainable solution has been implemented.
-// TODO(b/174997203): Remove when no longer necessary.
-//
// SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE
// This allows the target build release (i.e. the release version of the build within which
// the snapshot will be used) of the snapshot to be specified. If unspecified then it defaults
@@ -2019,29 +1984,12 @@
// Do not add the prefer property if the member snapshot module is a source module type.
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.
- // TODO(b/174997203): Remove once the ability to select the modules to prefer can be done
- // dynamically at build time not at snapshot generation time.
- prefer := config.IsEnvTrue("SOONG_SDK_SNAPSHOT_PREFER")
-
// Set prefer. Setting this to false is not strictly required as that is the default but it does
// provide a convenient hook to post-process the generated Android.bp file, e.g. in tests to
// check the behavior when a prebuilt is preferred. It also makes it explicit what the default
// behavior is for the module.
- bpModule.insertAfter("name", "prefer", prefer)
-
- configVar := config.Getenv("SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR")
- if configVar != "" {
- parts := strings.Split(configVar, ":")
- cfp := android.ConfigVarProperties{
- Config_namespace: proptools.StringPtr(parts[0]),
- Var_name: proptools.StringPtr(parts[1]),
- }
- bpModule.insertAfter("prefer", "use_source_config_var", cfp)
- }
+ bpModule.insertAfter("name", "prefer", false)
}
variants := selectApexVariantsWhereAvailable(ctx, member.variants)
diff --git a/snapshot/snapshot_base.go b/snapshot/snapshot_base.go
index 8e5dfe4..809ca3d 100644
--- a/snapshot/snapshot_base.go
+++ b/snapshot/snapshot_base.go
@@ -118,5 +118,6 @@
CrateName string `json:",omitempty"`
// dependencies
- Required []string `json:",omitempty"`
+ Required []string `json:",omitempty"`
+ Overrides []string `json:",omitempty"`
}
diff --git a/symbol_inject/macho.go b/symbol_inject/macho.go
index 9946d34..ca3d50e 100644
--- a/symbol_inject/macho.go
+++ b/symbol_inject/macho.go
@@ -16,9 +16,12 @@
import (
"debug/macho"
+ "encoding/binary"
"fmt"
"io"
+ "os"
"os/exec"
+ "path/filepath"
"sort"
"strings"
)
@@ -98,6 +101,80 @@
}
func CodeSignMachoFile(path string) error {
- cmd := exec.Command("/usr/bin/codesign", "--force", "-s", "-", path)
- return cmd.Run()
+ filename := filepath.Base(path)
+ cmd := exec.Command("/usr/bin/codesign", "--force", "-s", "-", "-i", filename, path)
+ if err := cmd.Run(); err != nil {
+ return err
+ }
+ return modifyCodeSignFlags(path)
+}
+
+const LC_CODE_SIGNATURE = 0x1d
+const CSSLOT_CODEDIRECTORY = 0
+
+// To make codesign not invalidated by stripping, modify codesign flags to 0x20002
+// (adhoc | linkerSigned).
+func modifyCodeSignFlags(path string) error {
+ f, err := os.OpenFile(path, os.O_RDWR, 0)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ // Step 1: find code signature section.
+ machoFile, err := macho.NewFile(f)
+ if err != nil {
+ return err
+ }
+ var codeSignSectionOffset uint32 = 0
+ var codeSignSectionSize uint32 = 0
+ for _, l := range machoFile.Loads {
+ data := l.Raw()
+ cmd := machoFile.ByteOrder.Uint32(data)
+ if cmd == LC_CODE_SIGNATURE {
+ codeSignSectionOffset = machoFile.ByteOrder.Uint32(data[8:])
+ codeSignSectionSize = machoFile.ByteOrder.Uint32(data[12:])
+ }
+ }
+ if codeSignSectionOffset == 0 {
+ return fmt.Errorf("code signature section not found")
+ }
+
+ data := make([]byte, codeSignSectionSize)
+ _, err = f.ReadAt(data, int64(codeSignSectionOffset))
+ if err != nil {
+ return err
+ }
+
+ // Step 2: get flags offset.
+ blobCount := binary.BigEndian.Uint32(data[8:])
+ off := 12
+ var codeDirectoryOff uint32 = 0
+ for blobCount > 0 {
+ blobType := binary.BigEndian.Uint32(data[off:])
+ if blobType == CSSLOT_CODEDIRECTORY {
+ codeDirectoryOff = binary.BigEndian.Uint32(data[off+4:])
+ break
+ }
+ blobCount--
+ off += 8
+ }
+ if codeDirectoryOff == 0 {
+ return fmt.Errorf("no code directory in code signature section")
+ }
+ flagsOff := codeSignSectionOffset + codeDirectoryOff + 12
+
+ // Step 3: modify flags.
+ flagsData := make([]byte, 4)
+ _, err = f.ReadAt(flagsData, int64(flagsOff))
+ if err != nil {
+ return err
+ }
+ oldFlags := binary.BigEndian.Uint32(flagsData)
+ if oldFlags != 0x2 {
+ return fmt.Errorf("unexpected flags in code signature section: 0x%x", oldFlags)
+ }
+ binary.BigEndian.PutUint32(flagsData, 0x20002)
+ _, err = f.WriteAt(flagsData, int64(flagsOff))
+ return err
}
diff --git a/tests/apex_comparison_tests.sh b/tests/apex_comparison_tests.sh
index 6bc0165..5fbbd0f 100755
--- a/tests/apex_comparison_tests.sh
+++ b/tests/apex_comparison_tests.sh
@@ -34,7 +34,7 @@
BAZEL_OUTPUT_DIR="$OUTPUT_DIR/bazel"
function call_bazel() {
- tools/bazel --output_base="$BAZEL_OUTPUT_DIR" $@
+ build/bazel/bin/bazel --output_base="$BAZEL_OUTPUT_DIR" $@
}
function cleanup {
@@ -58,7 +58,7 @@
######################
build/soong/soong_ui.bash --make-mode BP2BUILD_VERBOSE=1 --skip-soong-tests bp2build
-BAZEL_OUT="$(call_bazel info output_path)"
+BAZEL_OUT="$(call_bazel info --config=bp2build output_path)"
export TARGET_PRODUCT="module_arm"
call_bazel build --config=bp2build --config=ci --config=android \
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index e92a561..d89e6b7 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -285,6 +285,35 @@
}
+function test_create_global_include_directory() {
+ setup
+ run_soong
+ local mtime1=$(stat -c "%y" out/soong/build.ninja)
+
+ # Soong needs to know if top level directories like hardware/ exist for use
+ # as global include directories. Make sure that doesn't cause regens for
+ # unrelated changes to the top level directory.
+ mkdir -p system/core
+
+ run_soong
+ local mtime2=$(stat -c "%y" out/soong/build.ninja)
+ if [[ "$mtime1" != "$mtime2" ]]; then
+ fail "Output Ninja file changed when top level directory changed"
+ fi
+
+ # Make sure it does regen if a missing directory in the path of a global
+ # include directory is added.
+ mkdir -p system/core/include
+
+ run_soong
+ local mtime3=$(stat -c "%y" out/soong/build.ninja)
+ if [[ "$mtime2" = "$mtime3" ]]; then
+ fail "Output Ninja file did not change when global include directory created"
+ fi
+
+}
+
+
function test_add_file_to_soong_build() {
setup
run_soong
@@ -547,12 +576,48 @@
function test_bp2build_generates_marker_file {
setup
- create_mock_bazel
run_soong bp2build
+ if [[ ! -f "./out/soong/bp2build_files_marker" ]]; then
+ fail "bp2build marker file was not generated"
+ fi
+
if [[ ! -f "./out/soong/bp2build_workspace_marker" ]]; then
- fail "Marker file was not generated"
+ fail "symlink forest marker file was not generated"
+ fi
+}
+
+function test_bp2build_add_irrelevant_file {
+ setup
+
+ mkdir -p a/b
+ touch a/b/c.txt
+ cat > a/b/Android.bp <<'EOF'
+filegroup {
+ name: "c",
+ srcs: ["c.txt"],
+ bazel_module: { bp2build_available: true },
+}
+EOF
+
+ run_soong bp2build
+ if [[ ! -e out/soong/bp2build/a/b/BUILD.bazel ]]; then
+ fail "BUILD file in symlink forest was not created";
+ fi
+
+ local mtime1=$(stat -c "%y" out/soong/bp2build/a/b/BUILD.bazel)
+
+ touch a/irrelevant.txt
+ run_soong bp2build
+ local mtime2=$(stat -c "%y" out/soong/bp2build/a/b/BUILD.bazel)
+
+ if [[ "$mtime1" != "$mtime2" ]]; then
+ fail "BUILD.bazel file was regenerated"
+ fi
+
+ if [[ ! -e "out/soong/workspace/a/irrelevant.txt" ]]; then
+ fail "New file was not symlinked into symlink forest"
fi
}
@@ -838,6 +903,7 @@
test_add_file_to_soong_build
test_glob_during_bootstrapping
test_soong_build_rerun_iff_environment_changes
+test_create_global_include_directory
test_multiple_soong_build_modes
test_dump_json_module_graph
test_json_module_graph_back_and_forth_null_build
@@ -849,6 +915,7 @@
test_bp2build_null_build
test_bp2build_back_and_forth_null_build
test_bp2build_add_android_bp
+test_bp2build_add_irrelevant_file
test_bp2build_add_to_glob
test_bp2build_bazel_workspace_structure
test_bp2build_bazel_workspace_add_file
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
index 78af54d..679ac55 100755
--- a/tests/bp2build_bazel_test.sh
+++ b/tests/bp2build_bazel_test.sh
@@ -48,9 +48,52 @@
test_bp2build_null_build_with_globs
+function test_different_relative_outdir {
+ setup
+
+ mkdir -p a
+ touch a/g.txt
+ cat > a/Android.bp <<'EOF'
+filegroup {
+ name: "g",
+ srcs: ["g.txt"],
+ bazel_module: {bp2build_available: true},
+ }
+EOF
+
+ # A directory under $MOCK_TOP
+ outdir=out2
+ trap "rm -rf $outdir" EXIT
+ # Modify OUT_DIR in a subshell so it doesn't affect the top level one.
+ (export OUT_DIR=$outdir; run_soong bp2build && run_bazel build --config=bp2build //a:g)
+}
+
+test_different_relative_outdir
+
+function test_different_absolute_outdir {
+ setup
+
+ mkdir -p a
+ touch a/g.txt
+ cat > a/Android.bp <<'EOF'
+filegroup {
+ name: "g",
+ srcs: ["g.txt"],
+ bazel_module: {bp2build_available: true},
+ }
+EOF
+
+ # A directory under /tmp/...
+ outdir=$(mktemp -t -d st.XXXXX)
+ trap 'rm -rf $outdir' EXIT
+ # Modify OUT_DIR in a subshell so it doesn't affect the top level one.
+ (export OUT_DIR=$outdir; run_soong bp2build && run_bazel build --config=bp2build //a:g)
+}
+
+test_different_absolute_outdir
+
function test_bp2build_generates_all_buildfiles {
setup
- create_mock_bazel
mkdir -p foo/convertible_soong_module
cat > foo/convertible_soong_module/Android.bp <<'EOF'
@@ -114,11 +157,13 @@
fi
}
+_save_trap=$(trap -p EXIT)
+trap '[[ $? -ne 0 ]] && echo Are you running this locally? Try changing --sandbox_tmpfs_path to something other than /tmp/ in build/bazel/linux.bazelrc.' EXIT
test_bp2build_generates_all_buildfiles
+eval ${_save_trap}
function test_cc_correctness {
setup
- create_mock_bazel
mkdir -p a
cat > a/Android.bp <<EOF
diff --git a/tests/lib.sh b/tests/lib.sh
index 4b4d908..e40f0ad 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -82,6 +82,7 @@
}
function create_mock_soong {
+ create_mock_bazel
copy_directory build/blueprint
copy_directory build/soong
copy_directory build/make/tools/rbcrun
@@ -128,7 +129,6 @@
symlink_file WORKSPACE
symlink_file BUILD
- symlink_file tools/bazel
}
function run_bazel {
@@ -136,7 +136,7 @@
# output should not be parsed as such.
rm -rf out/ninja_build
- tools/bazel "$@"
+ build/bazel/bin/bazel "$@"
}
function run_ninja {
diff --git a/tests/mixed_mode_test.sh b/tests/mixed_mode_test.sh
index b408fd3..8949b42 100755
--- a/tests/mixed_mode_test.sh
+++ b/tests/mixed_mode_test.sh
@@ -12,9 +12,56 @@
function test_bazel_smoke {
setup
- create_mock_bazel
- STANDALONE_BAZEL=true run_bazel info
+ run_soong bp2build
+
+ run_bazel info --config=bp2build
}
+function test_add_irrelevant_file {
+ setup
+
+ mkdir -p soong_tests/a/b
+ touch soong_tests/a/b/c.txt
+ cat > soong_tests/a/b/Android.bp <<'EOF'
+filegroup {
+ name: "c",
+ srcs: ["c.txt"],
+ bazel_module: { bp2build_available: true },
+}
+EOF
+
+ run_soong --bazel-mode-staging nothing
+
+ if [[ ! -e out/soong/bp2build/soong_tests/a/b/BUILD.bazel ]]; then
+ fail "BUILD.bazel not created"
+ fi
+
+ if [[ ! -e out/soong/build.ninja ]]; then
+ fail "build.ninja not created"
+ fi
+
+ local mtime_build1=$(stat -c "%y" out/soong/bp2build/soong_tests/a/b/BUILD.bazel)
+ local mtime_ninja1=$(stat -c "%y" out/soong/build.ninja)
+
+ touch soong_tests/a/irrelevant.txt
+
+ run_soong --bazel-mode-staging nothing
+ local mtime_build2=$(stat -c "%y" out/soong/bp2build/soong_tests/a/b/BUILD.bazel)
+ local mtime_ninja2=$(stat -c "%y" out/soong/build.ninja)
+
+ if [[ "$mtime_build1" != "$mtime_build2" ]]; then
+ fail "BUILD.bazel was generated"
+ fi
+
+ if [[ "$mtime_ninja1" != "$mtime_ninja2" ]]; then
+ fail "build.ninja was regenerated"
+ fi
+
+ if [[ ! -e out/soong/workspace/soong_tests/a/irrelevant.txt ]]; then
+ fail "new file was not symlinked"
+ fi
+}
+
+test_add_irrelevant_file
test_bazel_smoke
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index cfcf804..7a8fca9 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -46,7 +46,6 @@
"soong-ui-tracer",
],
srcs: [
- "bazel.go",
"build.go",
"cleanbuild.go",
"config.go",
diff --git a/ui/build/bazel.go b/ui/build/bazel.go
deleted file mode 100644
index 0ebfcd8..0000000
--- a/ui/build/bazel.go
+++ /dev/null
@@ -1,257 +0,0 @@
-// Copyright 2020 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package build
-
-import (
- "bytes"
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
- "strings"
-
- "android/soong/bazel"
- "android/soong/shared"
- "android/soong/ui/metrics"
-)
-
-func getBazelInfo(ctx Context, config Config, bazelExecutable string, bazelEnv map[string]string, query string) string {
- infoCmd := Command(ctx, config, "bazel", bazelExecutable)
-
- if extraStartupArgs, ok := infoCmd.Environment.Get("BAZEL_STARTUP_ARGS"); ok {
- infoCmd.Args = append(infoCmd.Args, strings.Fields(extraStartupArgs)...)
- }
-
- // Obtain the output directory path in the execution root.
- infoCmd.Args = append(infoCmd.Args,
- "info",
- query,
- )
-
- for k, v := range bazelEnv {
- infoCmd.Environment.Set(k, v)
- }
-
- infoCmd.Dir = filepath.Join(config.OutDir(), "..")
-
- queryResult := strings.TrimSpace(string(infoCmd.OutputOrFatal()))
- return queryResult
-}
-
-// Main entry point to construct the Bazel build command line, environment
-// variables and post-processing steps (e.g. converge output directories)
-func runBazel(ctx Context, config Config) {
- ctx.BeginTrace(metrics.RunBazel, "bazel")
- defer ctx.EndTrace()
-
- // "droid" is the default ninja target.
- // TODO(b/160568333): stop hardcoding 'droid' to support building any
- // Ninja target.
- outputGroups := "droid"
- if len(config.ninjaArgs) > 0 {
- // At this stage, the residue slice of args passed to ninja
- // are the ninja targets to build, which can correspond directly
- // to ninja_build's output_groups.
- outputGroups = strings.Join(config.ninjaArgs, ",")
- }
-
- // Environment variables are the primary mechanism to pass information from
- // soong_ui configuration or context to Bazel.
- bazelEnv := make(map[string]string)
-
- // Use *_NINJA variables to pass the root-relative path of the combined,
- // kati-generated, soong-generated, and packaging Ninja files to Bazel.
- // Bazel reads these from the lunch() repository rule.
- bazelEnv["COMBINED_NINJA"] = config.CombinedNinjaFile()
- bazelEnv["KATI_NINJA"] = config.KatiBuildNinjaFile()
- bazelEnv["PACKAGE_NINJA"] = config.KatiPackageNinjaFile()
- bazelEnv["SOONG_NINJA"] = config.SoongNinjaFile()
-
- // NOTE: When Bazel is used, config.DistDir() is rigged to return a fake distdir under config.OutDir()
- // This is to ensure that Bazel can actually write there. See config.go for more details.
- bazelEnv["DIST_DIR"] = config.DistDir()
-
- bazelEnv["SHELL"] = "/bin/bash"
-
- // `tools/bazel` is the default entry point for executing Bazel in the AOSP
- // source tree.
- bazelExecutable := filepath.Join("tools", "bazel")
- cmd := Command(ctx, config, "bazel", bazelExecutable)
-
- // Append custom startup flags to the Bazel command. Startup flags affect
- // the Bazel server itself, and any changes to these flags would incur a
- // restart of the server, losing much of the in-memory incrementality.
- if extraStartupArgs, ok := cmd.Environment.Get("BAZEL_STARTUP_ARGS"); ok {
- cmd.Args = append(cmd.Args, strings.Fields(extraStartupArgs)...)
- }
-
- // Start constructing the `build` command.
- actionName := bazel.BazelNinjaExecRunName
- cmd.Args = append(cmd.Args,
- "build",
- // Use output_groups to select the set of outputs to produce from a
- // ninja_build target.
- "--output_groups="+outputGroups,
- // Generate a performance profile
- "--profile="+filepath.Join(shared.BazelMetricsFilename(config, actionName)),
- "--slim_profile=true",
- )
-
- if config.UseRBE() {
- for _, envVar := range []string{
- // RBE client
- "RBE_compare",
- "RBE_exec_strategy",
- "RBE_invocation_id",
- "RBE_log_dir",
- "RBE_num_retries_if_mismatched",
- "RBE_platform",
- "RBE_remote_accept_cache",
- "RBE_remote_update_cache",
- "RBE_server_address",
- // TODO: remove old FLAG_ variables.
- "FLAG_compare",
- "FLAG_exec_root",
- "FLAG_exec_strategy",
- "FLAG_invocation_id",
- "FLAG_log_dir",
- "FLAG_platform",
- "FLAG_remote_accept_cache",
- "FLAG_remote_update_cache",
- "FLAG_server_address",
- } {
- cmd.Args = append(cmd.Args,
- "--action_env="+envVar)
- }
-
- // We need to calculate --RBE_exec_root ourselves
- ctx.Println("Getting Bazel execution_root...")
- cmd.Args = append(cmd.Args, "--action_env=RBE_exec_root="+getBazelInfo(ctx, config, bazelExecutable, bazelEnv, "execution_root"))
- }
-
- // Ensure that the PATH environment variable value used in the action
- // environment is the restricted set computed from soong_ui, and not a
- // user-provided one, for hermeticity reasons.
- if pathEnvValue, ok := config.environ.Get("PATH"); ok {
- cmd.Environment.Set("PATH", pathEnvValue)
- cmd.Args = append(cmd.Args, "--action_env=PATH="+pathEnvValue)
- }
-
- // Allow Bazel actions to see the SHELL variable (passed to Bazel above)
- cmd.Args = append(cmd.Args, "--action_env=SHELL")
-
- // Append custom build flags to the Bazel command. Changes to these flags
- // may invalidate Bazel's analysis cache.
- // These should be appended as the final args, so that they take precedence.
- if extraBuildArgs, ok := cmd.Environment.Get("BAZEL_BUILD_ARGS"); ok {
- cmd.Args = append(cmd.Args, strings.Fields(extraBuildArgs)...)
- }
-
- // Append the label of the default ninja_build target.
- cmd.Args = append(cmd.Args,
- "//:"+config.TargetProduct()+"-"+config.TargetBuildVariant(),
- )
-
- // Execute the command at the root of the directory.
- cmd.Dir = filepath.Join(config.OutDir(), "..")
-
- for k, v := range bazelEnv {
- cmd.Environment.Set(k, v)
- }
-
- // Make a human-readable version of the bazelEnv map
- bazelEnvStringBuffer := new(bytes.Buffer)
- for k, v := range bazelEnv {
- fmt.Fprintf(bazelEnvStringBuffer, "%s=%s ", k, v)
- }
-
- // Print the implicit command line
- ctx.Println("Bazel implicit command line: " + strings.Join(cmd.Environment.Environ(), " ") + " " + cmd.Cmd.String() + "\n")
-
- // Print the explicit command line too
- ctx.Println("Bazel explicit command line: " + bazelEnvStringBuffer.String() + cmd.Cmd.String() + "\n")
-
- // Execute the build command.
- cmd.RunAndStreamOrFatal()
-
- // Post-processing steps start here. Once the Bazel build completes, the
- // output files are still stored in the execution root, not in $OUT_DIR.
- // Ensure that the $OUT_DIR contains the expected set of files by symlinking
- // the files from the execution root's output direction into $OUT_DIR.
-
- ctx.Println("Getting Bazel output_path...")
- outputBasePath := getBazelInfo(ctx, config, bazelExecutable, bazelEnv, "output_path")
- // TODO: Don't hardcode out/ as the bazel output directory. This is
- // currently hardcoded as ninja_build.output_root.
- bazelNinjaBuildOutputRoot := filepath.Join(outputBasePath, "..", "out")
-
- ctx.Println("Populating output directory...")
- populateOutdir(ctx, config, bazelNinjaBuildOutputRoot, ".")
-}
-
-// For all files F recursively under rootPath/relativePath, creates symlinks
-// such that OutDir/F resolves to rootPath/F via symlinks.
-// NOTE: For distdir paths we rename files instead of creating symlinks, so that the distdir is independent.
-func populateOutdir(ctx Context, config Config, rootPath string, relativePath string) {
- destDir := filepath.Join(rootPath, relativePath)
- os.MkdirAll(destDir, 0755)
- files, err := ioutil.ReadDir(destDir)
- if err != nil {
- ctx.Fatal(err)
- }
-
- for _, f := range files {
- // The original Bazel file path
- destPath := filepath.Join(destDir, f.Name())
-
- // The desired Soong file path
- srcPath := filepath.Join(config.OutDir(), relativePath, f.Name())
-
- destLstatResult, destLstatErr := os.Lstat(destPath)
- if destLstatErr != nil {
- ctx.Fatalf("Unable to Lstat dest %s: %s", destPath, destLstatErr)
- }
-
- srcLstatResult, srcLstatErr := os.Lstat(srcPath)
-
- if srcLstatErr == nil {
- if srcLstatResult.IsDir() && destLstatResult.IsDir() {
- // src and dest are both existing dirs - recurse on the dest dir contents...
- populateOutdir(ctx, config, rootPath, filepath.Join(relativePath, f.Name()))
- } else {
- // Ignore other pre-existing src files (could be pre-existing files, directories, symlinks, ...)
- // This can arise for files which are generated under OutDir outside of soong_build, such as .bootstrap files.
- // FIXME: This might cause a problem later e.g. if a symlink in the build graph changes...
- }
- } else {
- if !os.IsNotExist(srcLstatErr) {
- ctx.Fatalf("Unable to Lstat src %s: %s", srcPath, srcLstatErr)
- }
-
- if strings.Contains(destDir, config.DistDir()) {
- // We need to make a "real" file/dir instead of making a symlink (because the distdir can't have symlinks)
- // Rename instead of copy in order to save disk space.
- if err := os.Rename(destPath, srcPath); err != nil {
- ctx.Fatalf("Unable to rename %s -> %s due to error %s", srcPath, destPath, err)
- }
- } else {
- // src does not exist, so try to create a src -> dest symlink (i.e. a Soong path -> Bazel path symlink)
- if err := os.Symlink(destPath, srcPath); err != nil {
- ctx.Fatalf("Unable to create symlink %s -> %s due to error %s", srcPath, destPath, err)
- }
- }
- }
- }
-}
diff --git a/ui/build/build.go b/ui/build/build.go
index ab8cd56..d49a754 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -90,7 +90,7 @@
}
}
-// These are bitmasks which can be used to check whether various flags are set e.g. whether to use Bazel.
+// These are bitmasks which can be used to check whether various flags are set
const (
_ = iota
// Whether to run the kati config step.
@@ -102,9 +102,7 @@
// Whether to include the kati-generated ninja file in the combined ninja.
RunKatiNinja = 1 << iota
// Whether to run ninja on the combined ninja.
- RunNinja = 1 << iota
- // Whether to run bazel on the combined ninja.
- RunBazel = 1 << iota
+ RunNinja = 1 << iota
RunBuildTests = 1 << iota
RunAll = RunProductConfig | RunSoong | RunKati | RunKatiNinja | RunNinja
)
@@ -112,13 +110,19 @@
// checkBazelMode fails the build if there are conflicting arguments for which bazel
// build mode to use.
func checkBazelMode(ctx Context, config Config) {
- if config.Environment().IsEnvTrue("USE_BAZEL_ANALYSIS") {
- ctx.Fatalln("USE_BAZEL_ANALYSIS is deprecated. Unset USE_BAZEL_ANALYSIS.\n" +
- "Use --bazel-mode-dev instead. For example: `m --bazel-mode-dev nothing`")
+ count := 0
+ if config.bazelProdMode {
+ count++
}
- if config.bazelProdMode && config.bazelDevMode {
+ if config.bazelDevMode {
+ count++
+ }
+ if config.bazelStagingMode {
+ count++
+ }
+ if count > 1 {
ctx.Fatalln("Conflicting bazel mode.\n" +
- "Do not specify both --bazel-mode and --bazel-mode-dev")
+ "Do not specify more than one of --bazel-mode and --bazel-mode-dev and --bazel-mode-staging ")
}
}
@@ -318,11 +322,6 @@
runNinjaForBuild(ctx, config)
}
-
- // Currently, using Bazel requires Kati and Soong to run first, so check whether to run Bazel last.
- if what&RunBazel != 0 {
- runBazel(ctx, config)
- }
}
func evaluateWhatToRun(config Config, verboseln func(v ...interface{})) int {
diff --git a/ui/build/config.go b/ui/build/config.go
index 14a99d0..c98601e 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -71,6 +71,7 @@
checkbuild bool
dist bool
jsonModuleGraph bool
+ apiBp2build bool // Generate BUILD files for Soong modules that contribute APIs
bp2build bool
queryview bool
reportMkMetrics bool // Collect and report mk2bp migration progress metrics.
@@ -81,6 +82,7 @@
skipSoong bool
skipNinja bool
skipSoongTests bool
+ searchApiDir bool // Scan the Android.bp files generated in out/api_surfaces
// From the product config
katiArgs []string
@@ -99,8 +101,9 @@
pathReplaced bool
- bazelProdMode bool
- bazelDevMode bool
+ bazelProdMode bool
+ bazelDevMode bool
+ bazelStagingMode bool
// Set by multiproduct_kati
emptyNinjaFile bool
@@ -234,6 +237,19 @@
return nil
}
+func defaultBazelProdMode(cfg *configImpl) bool {
+ // Envirnoment flag to disable Bazel for users which experience
+ // broken bazel-handled builds, or significant performance regressions.
+ if cfg.IsBazelMixedBuildForceDisabled() {
+ return false
+ }
+ // Darwin-host builds are currently untested with Bazel.
+ if runtime.GOOS == "darwin" {
+ return false
+ }
+ return true
+}
+
func NewConfig(ctx Context, args ...string) Config {
ret := &configImpl{
environ: OsEnvironment(),
@@ -387,13 +403,13 @@
if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
return override
}
- if ret.environ.IsEnvTrue("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN") {
- return java17Home
- }
if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN is no longer supported. An OpenJDK 11 toolchain is now the global default.")
}
- return java11Home
+ if toolchain17, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN"); ok && toolchain17 != "true" {
+ ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK17_TOOLCHAIN is no longer supported. An OpenJDK 17 toolchain is now the global default.")
+ }
+ return java17Home
}()
absJavaHome := absPath(ctx, javaHome)
@@ -462,10 +478,11 @@
func buildConfig(config Config) *smpb.BuildConfig {
c := &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(config.ForceUseGoma()),
- UseGoma: proto.Bool(config.UseGoma()),
- UseRbe: proto.Bool(config.UseRBE()),
- BazelMixedBuild: proto.Bool(config.BazelBuildEnabled()),
+ ForceUseGoma: proto.Bool(config.ForceUseGoma()),
+ UseGoma: proto.Bool(config.UseGoma()),
+ UseRbe: proto.Bool(config.UseRBE()),
+ BazelMixedBuild: proto.Bool(config.BazelBuildEnabled()),
+ ForceDisableBazelMixedBuild: proto.Bool(config.IsBazelMixedBuildForceDisabled()),
}
c.Targets = append(c.Targets, config.arguments...)
@@ -720,6 +737,10 @@
c.bazelProdMode = true
} else if arg == "--bazel-mode-dev" {
c.bazelDevMode = true
+ } else if arg == "--bazel-mode-staging" {
+ c.bazelStagingMode = true
+ } else if arg == "--search-api-dir" {
+ c.searchApiDir = true
} else if len(arg) > 0 && arg[0] == '-' {
parseArgNum := func(def int) int {
if len(arg) > 2 {
@@ -756,6 +777,8 @@
c.jsonModuleGraph = true
} else if arg == "bp2build" {
c.bp2build = true
+ } else if arg == "api_bp2build" {
+ c.apiBp2build = true
} else if arg == "queryview" {
c.queryview = true
} else if arg == "soong_docs" {
@@ -767,6 +790,9 @@
c.arguments = append(c.arguments, arg)
}
}
+ if (!c.bazelProdMode) && (!c.bazelDevMode) && (!c.bazelStagingMode) {
+ c.bazelProdMode = defaultBazelProdMode(c)
+ }
}
func (c *configImpl) configureLocale(ctx Context) {
@@ -833,7 +859,7 @@
return true
}
- if !c.JsonModuleGraph() && !c.Bp2Build() && !c.Queryview() && !c.SoongDocs() {
+ if !c.JsonModuleGraph() && !c.Bp2Build() && !c.Queryview() && !c.SoongDocs() && !c.ApiBp2build() {
// Command line was empty, the default Ninja target is built
return true
}
@@ -873,10 +899,18 @@
return filepath.Join(c.OutDir(), "bazel")
}
+func (c *configImpl) bazelOutputBase() string {
+ return filepath.Join(c.BazelOutDir(), "output")
+}
+
func (c *configImpl) SoongOutDir() string {
return filepath.Join(c.OutDir(), "soong")
}
+func (c *configImpl) ApiSurfacesOutDir() string {
+ return filepath.Join(c.OutDir(), "api_surfaces")
+}
+
func (c *configImpl) PrebuiltOS() string {
switch runtime.GOOS {
case "linux":
@@ -904,7 +938,11 @@
return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
}
-func (c *configImpl) Bp2BuildMarkerFile() string {
+func (c *configImpl) Bp2BuildFilesMarkerFile() string {
+ return shared.JoinPath(c.SoongOutDir(), "bp2build_files_marker")
+}
+
+func (c *configImpl) Bp2BuildWorkspaceMarkerFile() string {
return shared.JoinPath(c.SoongOutDir(), "bp2build_workspace_marker")
}
@@ -916,6 +954,10 @@
return shared.JoinPath(c.SoongOutDir(), "queryview.marker")
}
+func (c *configImpl) ApiBp2buildMarkerFile() string {
+ return shared.JoinPath(c.SoongOutDir(), "api_bp2build.marker")
+}
+
func (c *configImpl) ModuleGraphFile() string {
return shared.JoinPath(c.SoongOutDir(), "module-graph.json")
}
@@ -957,6 +999,10 @@
return c.bp2build
}
+func (c *configImpl) ApiBp2build() bool {
+ return c.apiBp2build
+}
+
func (c *configImpl) Queryview() bool {
return c.queryview
}
@@ -1104,7 +1150,7 @@
}
func (c *configImpl) BazelBuildEnabled() bool {
- return c.bazelProdMode || c.bazelDevMode
+ return c.bazelProdMode || c.bazelDevMode || c.bazelStagingMode
}
func (c *configImpl) StartRBE() bool {
@@ -1438,6 +1484,10 @@
return c.emptyNinjaFile
}
+func (c *configImpl) IsBazelMixedBuildForceDisabled() bool {
+ return c.Environment().IsEnvTrue("BUILD_BROKEN_DISABLE_BAZEL")
+}
+
func GetMetricsUploader(topDir string, env *Environment) string {
if p, ok := env.Get("METRICS_UPLOADER"); ok {
metricsUploader := filepath.Join(topDir, p)
diff --git a/ui/build/config_test.go b/ui/build/config_test.go
index 150ec35..940d85c 100644
--- a/ui/build/config_test.go
+++ b/ui/build/config_test.go
@@ -28,6 +28,7 @@
"android/soong/ui/logger"
smpb "android/soong/ui/metrics/metrics_proto"
"android/soong/ui/status"
+
"google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/proto"
@@ -89,7 +90,9 @@
t.Fatal(err)
})
+ env := Environment([]string{})
c := &configImpl{
+ environ: &env,
parallel: -1,
keepGoing: -1,
}
@@ -1008,46 +1011,62 @@
useBazel bool
bazelDevMode bool
bazelProdMode bool
+ bazelStagingMode bool
expectedBuildConfig *smpb.BuildConfig
}{
{
name: "none set",
environ: Environment{},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(false),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
},
},
{
name: "force use goma",
environ: Environment{"FORCE_USE_GOMA=1"},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(true),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
+ ForceUseGoma: proto.Bool(true),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(false),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
},
},
{
name: "use goma",
environ: Environment{"USE_GOMA=1"},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(true),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(true),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(false),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
},
},
{
name: "use rbe",
environ: Environment{"USE_RBE=1"},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(true),
- BazelMixedBuild: proto.Bool(false),
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(true),
+ BazelMixedBuild: proto.Bool(false),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
+ },
+ },
+ {
+ name: "disable mixed builds",
+ environ: Environment{"BUILD_BROKEN_DISABLE_BAZEL=1"},
+ expectedBuildConfig: &smpb.BuildConfig{
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(false),
+ ForceDisableBazelMixedBuild: proto.Bool(true),
},
},
{
@@ -1055,10 +1074,11 @@
environ: Environment{},
useBazel: true,
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(false),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
},
},
{
@@ -1066,10 +1086,11 @@
environ: Environment{},
bazelDevMode: true,
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(true),
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(true),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
},
},
{
@@ -1077,10 +1098,23 @@
environ: Environment{},
bazelProdMode: true,
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(true),
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(true),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
+ },
+ },
+ {
+ name: "bazel mixed build from staging mode",
+ environ: Environment{},
+ bazelStagingMode: true,
+ expectedBuildConfig: &smpb.BuildConfig{
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(true),
+ ForceDisableBazelMixedBuild: proto.Bool(false),
},
},
{
@@ -1089,11 +1123,12 @@
useBazel: true,
arguments: []string{"droid", "dist"},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
- Targets: []string{"droid", "dist"},
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ BazelMixedBuild: proto.Bool(false),
+ Targets: []string{"droid", "dist"},
+ ForceDisableBazelMixedBuild: proto.Bool(false),
},
},
{
@@ -1102,14 +1137,16 @@
"FORCE_USE_GOMA=1",
"USE_GOMA=1",
"USE_RBE=1",
+ "BUILD_BROKEN_DISABLE_BAZEL=1",
},
useBazel: true,
bazelDevMode: true,
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(true),
- UseGoma: proto.Bool(true),
- UseRbe: proto.Bool(true),
- BazelMixedBuild: proto.Bool(true),
+ ForceUseGoma: proto.Bool(true),
+ UseGoma: proto.Bool(true),
+ UseRbe: proto.Bool(true),
+ BazelMixedBuild: proto.Bool(true),
+ ForceDisableBazelMixedBuild: proto.Bool(true),
},
},
}
@@ -1118,10 +1155,11 @@
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
c := &configImpl{
- environ: &tc.environ,
- bazelDevMode: tc.bazelDevMode,
- bazelProdMode: tc.bazelProdMode,
- arguments: tc.arguments,
+ environ: &tc.environ,
+ bazelDevMode: tc.bazelDevMode,
+ bazelProdMode: tc.bazelProdMode,
+ bazelStagingMode: tc.bazelStagingMode,
+ arguments: tc.arguments,
}
config := Config{c}
checkBazelMode(ctx, config)
diff --git a/ui/build/context.go b/ui/build/context.go
index 4a4352c..2fef0d0 100644
--- a/ui/build/context.go
+++ b/ui/build/context.go
@@ -48,7 +48,7 @@
c.Tracer.Begin(desc, c.Thread)
}
if c.Metrics != nil {
- c.Metrics.EventTracer.Begin(name, desc, c.Thread)
+ c.Metrics.EventTracer.Begin(name, desc)
}
}
@@ -58,7 +58,7 @@
c.Tracer.End(c.Thread)
}
if c.Metrics != nil {
- c.Metrics.SetTimeMetrics(c.Metrics.EventTracer.End(c.Thread))
+ c.Metrics.SetTimeMetrics(c.Metrics.EventTracer.End())
}
}
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index adc56ac..b3b3866 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -154,10 +154,7 @@
"HOST_CROSS_OS",
"BUILD_ID",
"OUT_DIR",
- "SOONG_SDK_SNAPSHOT_PREFER",
"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE",
- "SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR",
- "SOONG_SDK_SNAPSHOT_VERSION",
}
func Banner(make_vars map[string]string) string {
diff --git a/ui/build/finder.go b/ui/build/finder.go
index 4d6ad42..3f628cf 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -63,7 +63,7 @@
// Set up configuration parameters for the Finder cache.
cacheParams := finder.CacheParams{
WorkingDirectory: dir,
- RootDirs: []string{"."},
+ RootDirs: androidBpSearchDirs(config),
FollowSymlinks: config.environ.IsEnvTrue("ALLOW_BP_UNDER_SYMLINKS"),
ExcludeDirs: []string{".git", ".repo"},
PruneFiles: pruneFiles,
@@ -100,6 +100,15 @@
return f
}
+func androidBpSearchDirs(config Config) []string {
+ dirs := []string{"."} // always search from root of source tree.
+ if config.searchApiDir {
+ // Search in out/api_surfaces
+ dirs = append(dirs, config.ApiSurfacesOutDir())
+ }
+ return dirs
+}
+
// Finds the list of Bazel-related files (BUILD, WORKSPACE and Starlark) in the tree.
func findBazelFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) {
matches := []string{}
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index 6231e52..c3e52c6 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -94,6 +94,9 @@
}
func startRBE(ctx Context, config Config) {
+ if !config.GoogleProdCredsExist() && prodCredsAuthType(config) {
+ ctx.Fatalf("Unable to start RBE reproxy\nFAILED: Missing LOAS credentials.")
+ }
ctx.BeginTrace(metrics.RunSetupTool, "rbe_bootstrap")
defer ctx.EndTrace()
diff --git a/ui/build/sandbox_config.go b/ui/build/sandbox_config.go
index 1b46459..1d32d86 100644
--- a/ui/build/sandbox_config.go
+++ b/ui/build/sandbox_config.go
@@ -27,6 +27,15 @@
return sc.srcDirIsRO
}
+// Return the mount flag of the source directory in the nsjail command
+func (sc *SandboxConfig) SrcDirMountFlag() string {
+ ret := "-B" // Read-write
+ if sc.SrcDirIsRO() {
+ ret = "-R" // Read-only
+ }
+ return ret
+}
+
func (sc *SandboxConfig) SetSrcDirRWAllowlist(allowlist []string) {
sc.srcDirRWAllowlist = allowlist
}
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index 5b2046e..edb3b66 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -101,7 +101,7 @@
// srcDir is /tmp/.* in integration tests, which is a child dir of /tmp
// nsjail throws an error if a child dir is mounted before its parent
"-B", "/tmp",
- "-B", sandboxConfig.srcDir,
+ c.config.sandboxConfig.SrcDirMountFlag(), sandboxConfig.srcDir,
"-B", sandboxConfig.outDir,
}
@@ -148,13 +148,6 @@
func (c *Cmd) wrapSandbox() {
wd, _ := os.Getwd()
- var srcDirMountFlag string
- if c.config.sandboxConfig.SrcDirIsRO() {
- srcDirMountFlag = "-R"
- } else {
- srcDirMountFlag = "-B" //Read-Write
- }
-
sandboxArgs := []string{
// The executable to run
"-x", c.Path,
@@ -195,7 +188,7 @@
"-B", "/tmp",
// Mount source
- srcDirMountFlag, sandboxConfig.srcDir,
+ c.config.sandboxConfig.SrcDirMountFlag(), sandboxConfig.srcDir,
//Mount out dir as read-write
"-B", sandboxConfig.outDir,
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 3ef77c7..abaf5ae 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -41,11 +41,13 @@
availableEnvFile = "soong.environment.available"
usedEnvFile = "soong.environment.used"
- soongBuildTag = "build"
- bp2buildTag = "bp2build"
- jsonModuleGraphTag = "modulegraph"
- queryviewTag = "queryview"
- soongDocsTag = "soong_docs"
+ soongBuildTag = "build"
+ bp2buildFilesTag = "bp2build_files"
+ bp2buildWorkspaceTag = "bp2build_workspace"
+ jsonModuleGraphTag = "modulegraph"
+ queryviewTag = "queryview"
+ apiBp2buildTag = "api_bp2build"
+ soongDocsTag = "soong_docs"
// bootstrapEpoch is used to determine if an incremental build is incompatible with the current
// version of bootstrap and needs cleaning before continuing the build. Increment this for
@@ -193,6 +195,12 @@
allArgs = append(allArgs, commonArgs...)
allArgs = append(allArgs, environmentArgs(config, name)...)
+ if profileCpu := os.Getenv("SOONG_PROFILE_CPU"); profileCpu != "" {
+ allArgs = append(allArgs, "--cpuprofile", profileCpu+"."+name)
+ }
+ if profileMem := os.Getenv("SOONG_PROFILE_MEM"); profileMem != "" {
+ allArgs = append(allArgs, "--memprofile", profileMem+"."+name)
+ }
allArgs = append(allArgs, "Android.bp")
return bootstrap.PrimaryBuilderInvocation{
@@ -234,9 +242,10 @@
func bootstrapGlobFileList(config Config) []string {
return []string{
config.NamedGlobFile(soongBuildTag),
- config.NamedGlobFile(bp2buildTag),
+ config.NamedGlobFile(bp2buildFilesTag),
config.NamedGlobFile(jsonModuleGraphTag),
config.NamedGlobFile(queryviewTag),
+ config.NamedGlobFile(apiBp2buildTag),
config.NamedGlobFile(soongDocsTag),
}
}
@@ -258,6 +267,9 @@
if config.bazelDevMode {
mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--bazel-mode-dev")
}
+ if config.bazelStagingMode {
+ mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--bazel-mode-staging")
+ }
mainSoongBuildInvocation := primaryBuilderInvocation(
config,
@@ -271,20 +283,33 @@
// Mixed builds call Bazel from soong_build and they therefore need the
// Bazel workspace to be available. Make that so by adding a dependency on
// the bp2build marker file to the action that invokes soong_build .
- mainSoongBuildInvocation.Inputs = append(mainSoongBuildInvocation.Inputs,
- config.Bp2BuildMarkerFile())
+ mainSoongBuildInvocation.OrderOnlyInputs = append(mainSoongBuildInvocation.OrderOnlyInputs,
+ config.Bp2BuildWorkspaceMarkerFile())
}
bp2buildInvocation := primaryBuilderInvocation(
config,
- bp2buildTag,
- config.Bp2BuildMarkerFile(),
+ bp2buildFilesTag,
+ config.Bp2BuildFilesMarkerFile(),
[]string{
- "--bp2build_marker", config.Bp2BuildMarkerFile(),
+ "--bp2build_marker", config.Bp2BuildFilesMarkerFile(),
},
fmt.Sprintf("converting Android.bp files to BUILD files at %s/bp2build", config.SoongOutDir()),
)
+ bp2buildWorkspaceInvocation := primaryBuilderInvocation(
+ config,
+ bp2buildWorkspaceTag,
+ config.Bp2BuildWorkspaceMarkerFile(),
+ []string{
+ "--symlink_forest_marker", config.Bp2BuildWorkspaceMarkerFile(),
+ },
+ fmt.Sprintf("Creating Bazel symlink forest"),
+ )
+
+ bp2buildWorkspaceInvocation.Inputs = append(bp2buildWorkspaceInvocation.Inputs,
+ config.Bp2BuildFilesMarkerFile(), filepath.Join(config.FileListDir(), "bazel.list"))
+
jsonModuleGraphInvocation := primaryBuilderInvocation(
config,
jsonModuleGraphTag,
@@ -307,6 +332,19 @@
fmt.Sprintf("generating the Soong module graph as a Bazel workspace at %s", queryviewDir),
)
+ // The BUILD files will be generated in out/soong/.api_bp2build (no symlinks to src files)
+ // The final workspace will be generated in out/soong/api_bp2build
+ apiBp2buildDir := filepath.Join(config.SoongOutDir(), ".api_bp2build")
+ apiBp2buildInvocation := primaryBuilderInvocation(
+ config,
+ apiBp2buildTag,
+ config.ApiBp2buildMarkerFile(),
+ []string{
+ "--bazel_api_bp2build_dir", apiBp2buildDir,
+ },
+ fmt.Sprintf("generating BUILD files for API contributions at %s", apiBp2buildDir),
+ )
+
soongDocsInvocation := primaryBuilderInvocation(
config,
soongDocsTag,
@@ -343,8 +381,10 @@
primaryBuilderInvocations: []bootstrap.PrimaryBuilderInvocation{
mainSoongBuildInvocation,
bp2buildInvocation,
+ bp2buildWorkspaceInvocation,
jsonModuleGraphInvocation,
queryviewInvocation,
+ apiBp2buildInvocation,
soongDocsInvocation},
}
@@ -380,12 +420,15 @@
soongBuildEnv := config.Environment().Copy()
soongBuildEnv.Set("TOP", os.Getenv("TOP"))
// For Bazel mixed builds.
- soongBuildEnv.Set("BAZEL_PATH", "./tools/bazel")
- soongBuildEnv.Set("BAZEL_HOME", filepath.Join(config.BazelOutDir(), "bazelhome"))
- soongBuildEnv.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output"))
+ soongBuildEnv.Set("BAZEL_PATH", "./build/bazel/bin/bazel")
+ // Bazel's HOME var is set to an output subdirectory which doesn't exist. This
+ // prevents Bazel from file I/O in the actual user HOME directory.
+ soongBuildEnv.Set("BAZEL_HOME", absPath(ctx, filepath.Join(config.BazelOutDir(), "bazelhome")))
+ soongBuildEnv.Set("BAZEL_OUTPUT_BASE", config.bazelOutputBase())
soongBuildEnv.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
soongBuildEnv.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
soongBuildEnv.Set("LOG_DIR", config.LogsDir())
+ soongBuildEnv.Set("BAZEL_DEPS_FILE", absPath(ctx, filepath.Join(config.BazelOutDir(), "bazel.list")))
// For Soong bootstrapping tests
if os.Getenv("ALLOW_MISSING_DEPENDENCIES") == "true" {
@@ -404,7 +447,7 @@
checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(soongBuildTag))
if config.BazelBuildEnabled() || config.Bp2Build() {
- checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(bp2buildTag))
+ checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(bp2buildFilesTag))
}
if config.JsonModuleGraph() {
@@ -415,6 +458,10 @@
checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(queryviewTag))
}
+ if config.ApiBp2build() {
+ checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(apiBp2buildTag))
+ }
+
if config.SoongDocs() {
checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(soongDocsTag))
}
@@ -471,13 +518,17 @@
}
if config.Bp2Build() {
- targets = append(targets, config.Bp2BuildMarkerFile())
+ targets = append(targets, config.Bp2BuildWorkspaceMarkerFile())
}
if config.Queryview() {
targets = append(targets, config.QueryviewMarkerFile())
}
+ if config.ApiBp2build() {
+ targets = append(targets, config.ApiBp2buildMarkerFile())
+ }
+
if config.SoongDocs() {
targets = append(targets, config.SoongDocsHtml())
}
@@ -487,17 +538,22 @@
targets = append(targets, config.SoongNinjaFile())
}
- ninja("bootstrap", "bootstrap.ninja", targets...)
-
if shouldCollectBuildSoongMetrics(config) {
- soongBuildMetrics := loadSoongBuildMetrics(ctx, config)
- if soongBuildMetrics != nil {
- logSoongBuildMetrics(ctx, soongBuildMetrics)
- if ctx.Metrics != nil {
- ctx.Metrics.SetSoongBuildMetrics(soongBuildMetrics)
- }
+ soongBuildMetricsFile := filepath.Join(config.LogsDir(), "soong_build_metrics.pb")
+ if err := os.Remove(soongBuildMetricsFile); err != nil && !os.IsNotExist(err) {
+ ctx.Verbosef("Failed to remove %s", soongBuildMetricsFile)
}
+ defer func() {
+ soongBuildMetrics := loadSoongBuildMetrics(ctx, soongBuildMetricsFile)
+ if soongBuildMetrics != nil {
+ logSoongBuildMetrics(ctx, soongBuildMetrics)
+ if ctx.Metrics != nil {
+ ctx.Metrics.SetSoongBuildMetrics(soongBuildMetrics)
+ }
+ }
+ }()
}
+ ninja("bootstrap", "bootstrap.ninja", targets...)
distGzipFile(ctx, config, config.SoongNinjaFile(), "soong")
distFile(ctx, config, config.SoongVarsFile(), "soong")
@@ -536,8 +592,7 @@
return config.SoongBuildInvocationNeeded()
}
-func loadSoongBuildMetrics(ctx Context, config Config) *soong_metrics_proto.SoongBuildMetrics {
- soongBuildMetricsFile := filepath.Join(config.LogsDir(), "soong_build_metrics.pb")
+func loadSoongBuildMetrics(ctx Context, soongBuildMetricsFile string) *soong_metrics_proto.SoongBuildMetrics {
buf, err := os.ReadFile(soongBuildMetricsFile)
if errors.Is(err, fs.ErrNotExist) {
// Soong may not have run during this invocation
diff --git a/ui/build/test_build.go b/ui/build/test_build.go
index 86c8568..2efc732 100644
--- a/ui/build/test_build.go
+++ b/ui/build/test_build.go
@@ -18,14 +18,44 @@
"bufio"
"fmt"
"path/filepath"
+ "regexp"
"runtime"
"sort"
"strings"
+ "sync"
"android/soong/ui/metrics"
"android/soong/ui/status"
)
+var (
+ // bazel output paths are in __main__/bazel-out/<config-specific-path>/bin
+ bazelOutputPathRegexOnce sync.Once
+ bazelOutputPathRegexp *regexp.Regexp
+)
+
+func bazelOutputPathPattern(config Config) *regexp.Regexp {
+ bazelOutputPathRegexOnce.Do(func() {
+ // Bazel output files are in <Bazel output base>/execroot/__main__/bazel-out/<config>/bin
+ bazelOutRoot := filepath.Join(regexp.QuoteMeta(config.bazelOutputBase()), "execroot", "__main__", "bazel-out")
+ bazelOutputPathRegexp = regexp.MustCompile(bazelOutRoot + "/[^/]+/bin")
+ })
+ return bazelOutputPathRegexp
+}
+
+func ignoreBazelPath(config Config, path string) bool {
+ bazelRoot := filepath.Join(config.bazelOutputBase(), "execroot")
+ // Don't check bazel output regexp unless it is Bazel path
+ if strings.HasPrefix(path, bazelRoot) {
+ bazelOutputRegexp := bazelOutputPathPattern(config)
+ // if the file is a bazel path that is _not_ a Bazel generated file output, we rely on Bazel to
+ // ensure the paths to exist. If it _is_ a Bazel output path, we expect that it should be built
+ // by Ninja.
+ return !bazelOutputRegexp.MatchString(path)
+ }
+ return false
+}
+
// Checks for files in the out directory that have a rule that depends on them but no rule to
// create them. This catches a common set of build failures where a rule to generate a file is
// deleted (either by deleting a module in an Android.mk file, or by modifying the build system
@@ -97,6 +127,10 @@
// full build rules in the primary build.ninja file.
continue
}
+
+ if ignoreBazelPath(config, line) {
+ continue
+ }
danglingRules[line] = true
}
diff --git a/ui/build/upload.go b/ui/build/upload.go
index 687f519..9f14bdd 100644
--- a/ui/build/upload.go
+++ b/ui/build/upload.go
@@ -18,6 +18,7 @@
// another.
import (
+ "fmt"
"io/ioutil"
"os"
"path/filepath"
@@ -56,7 +57,9 @@
}
if fi.IsDir() {
- if l, err := ioutil.ReadDir(p); err == nil {
+ if l, err := ioutil.ReadDir(p); err != nil {
+ _, _ = fmt.Fprintf(os.Stderr, "Failed to find files under %s\n", p)
+ } else {
files := make([]string, 0, len(l))
for _, fi := range l {
files = append(files, filepath.Join(p, fi.Name()))
diff --git a/ui/logger/Android.bp b/ui/logger/Android.bp
index 269a5a0..7883ea6 100644
--- a/ui/logger/Android.bp
+++ b/ui/logger/Android.bp
@@ -25,4 +25,7 @@
testSrcs: [
"logger_test.go",
],
+ deps: [
+ "soong-ui-metrics",
+ ],
}
diff --git a/ui/logger/logger.go b/ui/logger/logger.go
index 9b26ae8..1185298 100644
--- a/ui/logger/logger.go
+++ b/ui/logger/logger.go
@@ -29,6 +29,7 @@
package logger
import (
+ "android/soong/ui/metrics"
"errors"
"fmt"
"io"
@@ -72,8 +73,8 @@
Output(calldepth int, str string) error
}
-// fatalLog is the type used when Fatal[f|ln]
-type fatalLog struct {
+// fatalError is the type used when Fatal[f|ln]
+type fatalError struct {
error
}
@@ -127,7 +128,7 @@
if p == nil {
return
- } else if log, ok := p.(fatalLog); ok {
+ } else if log, ok := p.(fatalError); ok {
fn(error(log))
} else {
panic(p)
@@ -141,6 +142,7 @@
fileLogger *log.Logger
mutex sync.Mutex
file *os.File
+ metrics *metrics.Metrics
}
var _ Logger = &stdLogger{}
@@ -149,9 +151,14 @@
// os.Stderr, but it may be a buffer for tests, or a separate log file if
// the user doesn't need to see the output.
func New(out io.Writer) *stdLogger {
+ return NewWithMetrics(out, nil)
+}
+
+func NewWithMetrics(out io.Writer, m *metrics.Metrics) *stdLogger {
return &stdLogger{
stderr: log.New(out, "", log.Ltime),
fileLogger: log.New(ioutil.Discard, "", log.Ldate|log.Lmicroseconds|log.Llongfile),
+ metrics: m,
}
}
@@ -201,7 +208,7 @@
fatal := false
p := recover()
- if _, ok := p.(fatalLog); ok {
+ if _, ok := p.(fatalError); ok {
fatal = true
p = nil
} else if p != nil {
@@ -217,40 +224,56 @@
}
}
+type verbosityLevel int
+
+const (
+ verboseLog verbosityLevel = iota
+ infoLog
+ fatalLog
+ panicLog
+)
+
// Output writes string to both stderr and the file log.
func (s *stdLogger) Output(calldepth int, str string) error {
- s.stderr.Output(calldepth+1, str)
+ return s.output(calldepth, str, infoLog)
+}
+
+// output writes string to stderr, the file log, and if fatal or panic, to metrics.
+func (s *stdLogger) output(calldepth int, str string, level verbosityLevel) error {
+ if level != verboseLog || s.verbose {
+ s.stderr.Output(calldepth+1, str)
+ }
+ if level >= fatalLog {
+ s.metrics.SetFatalOrPanicMessage(str)
+ }
return s.fileLogger.Output(calldepth+1, str)
}
// VerboseOutput is equivalent to Output, but only goes to the file log
// unless SetVerbose(true) has been called.
func (s *stdLogger) VerboseOutput(calldepth int, str string) error {
- if s.verbose {
- s.stderr.Output(calldepth+1, str)
- }
- return s.fileLogger.Output(calldepth+1, str)
+ return s.output(calldepth, str, verboseLog)
}
// Print prints to both stderr and the file log.
// Arguments are handled in the manner of fmt.Print.
func (s *stdLogger) Print(v ...interface{}) {
output := fmt.Sprint(v...)
- s.Output(2, output)
+ s.output(2, output, infoLog)
}
// Printf prints to both stderr and the file log.
// Arguments are handled in the manner of fmt.Printf.
func (s *stdLogger) Printf(format string, v ...interface{}) {
output := fmt.Sprintf(format, v...)
- s.Output(2, output)
+ s.output(2, output, infoLog)
}
// Println prints to both stderr and the file log.
// Arguments are handled in the manner of fmt.Println.
func (s *stdLogger) Println(v ...interface{}) {
output := fmt.Sprintln(v...)
- s.Output(2, output)
+ s.output(2, output, infoLog)
}
// Verbose is equivalent to Print, but only goes to the file log unless
@@ -278,43 +301,43 @@
// Cleanup will convert to a os.Exit(1).
func (s *stdLogger) Fatal(v ...interface{}) {
output := fmt.Sprint(v...)
- s.Output(2, output)
- panic(fatalLog{errors.New(output)})
+ s.output(2, output, fatalLog)
+ panic(fatalError{errors.New(output)})
}
// Fatalf is equivalent to Printf() followed by a call to panic() that
// Cleanup will convert to a os.Exit(1).
func (s *stdLogger) Fatalf(format string, v ...interface{}) {
output := fmt.Sprintf(format, v...)
- s.Output(2, output)
- panic(fatalLog{errors.New(output)})
+ s.output(2, output, fatalLog)
+ panic(fatalError{errors.New(output)})
}
// Fatalln is equivalent to Println() followed by a call to panic() that
// Cleanup will convert to a os.Exit(1).
func (s *stdLogger) Fatalln(v ...interface{}) {
output := fmt.Sprintln(v...)
- s.Output(2, output)
- panic(fatalLog{errors.New(output)})
+ s.output(2, output, fatalLog)
+ panic(fatalError{errors.New(output)})
}
// Panic is equivalent to Print() followed by a call to panic().
func (s *stdLogger) Panic(v ...interface{}) {
output := fmt.Sprint(v...)
- s.Output(2, output)
+ s.output(2, output, panicLog)
panic(output)
}
// Panicf is equivalent to Printf() followed by a call to panic().
func (s *stdLogger) Panicf(format string, v ...interface{}) {
output := fmt.Sprintf(format, v...)
- s.Output(2, output)
+ s.output(2, output, panicLog)
panic(output)
}
// Panicln is equivalent to Println() followed by a call to panic().
func (s *stdLogger) Panicln(v ...interface{}) {
output := fmt.Sprintln(v...)
- s.Output(2, output)
+ s.output(2, output, panicLog)
panic(output)
}
diff --git a/ui/metrics/Android.bp b/ui/metrics/Android.bp
index 05db1d7..2301c56 100644
--- a/ui/metrics/Android.bp
+++ b/ui/metrics/Android.bp
@@ -25,7 +25,6 @@
"soong-ui-metrics_upload_proto",
"soong-ui-metrics_proto",
"soong-ui-mk_metrics_proto",
- "soong-ui-tracer",
"soong-shared",
],
srcs: [
diff --git a/ui/metrics/event.go b/ui/metrics/event.go
index ebe664f..b3a027e 100644
--- a/ui/metrics/event.go
+++ b/ui/metrics/event.go
@@ -31,7 +31,6 @@
"time"
soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
- "android/soong/ui/tracer"
"google.golang.org/protobuf/proto"
)
@@ -50,6 +49,10 @@
// for metrics analysis).
desc string
+ nonZeroExitCode bool
+
+ errorMsg *string
+
// The time that the event started to occur.
start time.Time
@@ -68,13 +71,18 @@
func (e event) perfInfo() soong_metrics_proto.PerfInfo {
realTime := uint64(_now().Sub(e.start).Nanoseconds())
- return soong_metrics_proto.PerfInfo{
+ perfInfo := soong_metrics_proto.PerfInfo{
Description: proto.String(e.desc),
Name: proto.String(e.name),
StartTime: proto.Uint64(uint64(e.start.UnixNano())),
RealTime: proto.Uint64(realTime),
ProcessesResourceInfo: e.procResInfo,
+ NonZeroExit: proto.Bool(e.nonZeroExitCode),
}
+ if m := e.errorMsg; m != nil {
+ perfInfo.ErrorMessage = proto.String(*m)
+ }
+ return perfInfo
}
// EventTracer is an array of events that provides functionality to trace a
@@ -94,6 +102,9 @@
// peek returns the active build event.
func (t *EventTracer) peek() *event {
+ if t.empty() {
+ return nil
+ }
return (*t)[t.lastIndex()]
}
@@ -137,12 +148,12 @@
}
// Begin starts tracing the event.
-func (t *EventTracer) Begin(name, desc string, _ tracer.Thread) {
+func (t *EventTracer) Begin(name, desc string) {
t.push(newEvent(name, desc))
}
// End performs post calculations such as duration of the event, aggregates
// the collected performance information into PerfInfo protobuf message.
-func (t *EventTracer) End(tracer.Thread) soong_metrics_proto.PerfInfo {
+func (t *EventTracer) End() soong_metrics_proto.PerfInfo {
return t.pop().perfInfo()
}
diff --git a/ui/metrics/event_test.go b/ui/metrics/event_test.go
index 043450b..a80e7cf 100644
--- a/ui/metrics/event_test.go
+++ b/ui/metrics/event_test.go
@@ -17,8 +17,6 @@
import (
"testing"
"time"
-
- "android/soong/ui/tracer"
)
func TestEnd(t *testing.T) {
@@ -35,8 +33,31 @@
start: startTime,
})
- perf := et.End(tracer.Thread(0))
+ perf := et.End()
if perf.GetRealTime() != uint64(dur.Nanoseconds()) {
t.Errorf("got %d, want %d nanoseconds for event duration", perf.GetRealTime(), dur.Nanoseconds())
}
}
+
+func TestEndWithError(t *testing.T) {
+ startTime := time.Date(2020, time.July, 13, 13, 0, 0, 0, time.UTC)
+ dur := time.Nanosecond * 10
+ initialNow := _now
+ _now = func() time.Time { return startTime.Add(dur) }
+ defer func() { _now = initialNow }()
+
+ err := "foobar"
+ et := &EventTracer{}
+ et.push(&event{
+ desc: "test",
+ name: "test",
+ start: startTime,
+ nonZeroExitCode: true,
+ errorMsg: &err,
+ })
+
+ perf := et.End()
+ if msg := perf.GetErrorMessage(); msg != err {
+ t.Errorf("got %q, want %q for even error message", msg, err)
+ }
+}
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index 0c62865..ce2d946 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -125,6 +125,21 @@
}
}
+// SetFatalOrPanicMessage stores a non-zero exit and the relevant message in the latest event if
+// available or the metrics base.
+func (m *Metrics) SetFatalOrPanicMessage(errMsg string) {
+ if m == nil {
+ return
+ }
+ if event := m.EventTracer.peek(); event != nil {
+ event.nonZeroExitCode = true
+ event.errorMsg = &errMsg
+ } else {
+ m.metrics.ErrorMessage = proto.String(errMsg)
+ }
+ m.metrics.NonZeroExit = proto.Bool(true)
+}
+
// BuildConfig stores information about the build configuration.
func (m *Metrics) BuildConfig(b *soong_metrics_proto.BuildConfig) {
m.metrics.BuildConfig = b
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index 2dd8299..90d124b 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -338,6 +338,12 @@
BazelRuns []*PerfInfo `protobuf:"bytes,27,rep,name=bazel_runs,json=bazelRuns" json:"bazel_runs,omitempty"`
// The metrics of the experiment config fetcher
ExpConfigFetcher *ExpConfigFetcher `protobuf:"bytes,28,opt,name=exp_config_fetcher,json=expConfigFetcher" json:"exp_config_fetcher,omitempty"`
+ // Whether the build exited with a panic or non-zero exit code, includes both
+ // non-zero exits of recorded phases and non-recorded phases of the build.
+ NonZeroExit *bool `protobuf:"varint,29,opt,name=non_zero_exit,json=nonZeroExit" json:"non_zero_exit,omitempty"`
+ // The error message due to a non-zero exit _only_ if it did not occur in a
+ // recorded phase of the build.
+ ErrorMessage *string `protobuf:"bytes,30,opt,name=error_message,json=errorMessage" json:"error_message,omitempty"`
}
// Default values for MetricsBase fields.
@@ -576,6 +582,20 @@
return nil
}
+func (x *MetricsBase) GetNonZeroExit() bool {
+ if x != nil && x.NonZeroExit != nil {
+ return *x.NonZeroExit
+ }
+ return false
+}
+
+func (x *MetricsBase) GetErrorMessage() string {
+ if x != nil && x.ErrorMessage != nil {
+ return *x.ErrorMessage
+ }
+ return ""
+}
+
type BuildConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -592,6 +612,8 @@
// These are the targets soong passes to ninja, these targets include special
// targets such as droid as well as the regular build targets.
Targets []string `protobuf:"bytes,6,rep,name=targets" json:"targets,omitempty"`
+ // Whether the user explicitly disabled bazel mixed builds for this build.
+ ForceDisableBazelMixedBuild *bool `protobuf:"varint,7,opt,name=force_disable_bazel_mixed_build,json=forceDisableBazelMixedBuild" json:"force_disable_bazel_mixed_build,omitempty"`
}
func (x *BuildConfig) Reset() {
@@ -668,6 +690,13 @@
return nil
}
+func (x *BuildConfig) GetForceDisableBazelMixedBuild() bool {
+ if x != nil && x.ForceDisableBazelMixedBuild != nil {
+ return *x.ForceDisableBazelMixedBuild
+ }
+ return false
+}
+
type SystemResourceInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -746,6 +775,11 @@
MemoryUse *uint64 `protobuf:"varint,5,opt,name=memory_use,json=memoryUse" json:"memory_use,omitempty"`
// The resource information of each executed process.
ProcessesResourceInfo []*ProcessResourceInfo `protobuf:"bytes,6,rep,name=processes_resource_info,json=processesResourceInfo" json:"processes_resource_info,omitempty"`
+ // Whether the phase of tool running exited with a panic or non-zero exit
+ // code.
+ NonZeroExit *bool `protobuf:"varint,7,opt,name=non_zero_exit,json=nonZeroExit" json:"non_zero_exit,omitempty"`
+ // The error message, if any, due to a non-zero exit.
+ ErrorMessage *string `protobuf:"bytes,8,opt,name=error_message,json=errorMessage" json:"error_message,omitempty"`
}
func (x *PerfInfo) Reset() {
@@ -823,6 +857,20 @@
return nil
}
+func (x *PerfInfo) GetNonZeroExit() bool {
+ if x != nil && x.NonZeroExit != nil {
+ return *x.NonZeroExit
+ }
+ return false
+}
+
+func (x *PerfInfo) GetErrorMessage() string {
+ if x != nil && x.ErrorMessage != nil {
+ return *x.ErrorMessage
+ }
+ return ""
+}
+
type ProcessResourceInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1361,7 +1409,7 @@
var file_metrics_proto_rawDesc = []byte{
0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x13, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x22, 0xad, 0x0d, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
+ 0x72, 0x69, 0x63, 0x73, 0x22, 0xf6, 0x0d, 0x0a, 0x0b, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
0x42, 0x61, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x61,
0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01,
0x28, 0x03, 0x52, 0x12, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d,
@@ -1461,152 +1509,166 @@
0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
0x73, 0x2e, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68,
0x65, 0x72, 0x52, 0x10, 0x65, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74,
- 0x63, 0x68, 0x65, 0x72, 0x22, 0x30, 0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x56, 0x61, 0x72,
- 0x69, 0x61, 0x6e, 0x74, 0x12, 0x08, 0x0a, 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0d,
- 0x0a, 0x09, 0x55, 0x53, 0x45, 0x52, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x07, 0x0a,
- 0x03, 0x45, 0x4e, 0x47, 0x10, 0x02, 0x22, 0x3c, 0x0a, 0x04, 0x41, 0x72, 0x63, 0x68, 0x12, 0x0b,
- 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41,
- 0x52, 0x4d, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x52, 0x4d, 0x36, 0x34, 0x10, 0x02, 0x12,
- 0x07, 0x0a, 0x03, 0x58, 0x38, 0x36, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x58, 0x38, 0x36, 0x5f,
- 0x36, 0x34, 0x10, 0x04, 0x22, 0xd3, 0x01, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f,
- 0x6e, 0x66, 0x69, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x5f, 0x67, 0x6f, 0x6d, 0x61,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x75, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12,
- 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x5f, 0x72, 0x62, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x06, 0x75, 0x73, 0x65, 0x52, 0x62, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x63,
- 0x65, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x55, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x24,
- 0x0a, 0x0e, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x61, 0x73, 0x5f, 0x6e, 0x69, 0x6e, 0x6a, 0x61,
- 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x41, 0x73, 0x4e,
- 0x69, 0x6e, 0x6a, 0x61, 0x12, 0x2a, 0x0a, 0x11, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69,
- 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x0f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64,
- 0x12, 0x18, 0x0a, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28,
- 0x09, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x22, 0x6f, 0x0a, 0x12, 0x53, 0x79,
- 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f,
- 0x12, 0x32, 0x0a, 0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63,
- 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
- 0x13, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x4d, 0x65,
- 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c,
- 0x65, 0x5f, 0x63, 0x70, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x76,
- 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x70, 0x75, 0x73, 0x22, 0x81, 0x02, 0x0a, 0x08,
- 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64,
- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
- 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d,
- 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x04, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a,
- 0x09, 0x72, 0x65, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04,
- 0x52, 0x08, 0x72, 0x65, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0a, 0x6d, 0x65,
- 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02,
- 0x18, 0x01, 0x52, 0x09, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x65, 0x12, 0x60, 0x0a,
- 0x17, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75,
- 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28,
- 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f,
- 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73,
- 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22,
- 0xb9, 0x03, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75,
- 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x75,
- 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d,
- 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f,
- 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x04, 0x52, 0x10, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63,
- 0x72, 0x6f, 0x73, 0x12, 0x1c, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b,
- 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b,
- 0x62, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f,
- 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69,
- 0x6e, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a,
- 0x11, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c,
- 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50,
- 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f,
- 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09,
- 0x69, 0x6f, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f,
- 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52,
- 0x0a, 0x69, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76,
- 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
- 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52,
- 0x18, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78,
- 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76,
- 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
- 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52,
- 0x1a, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74,
- 0x65, 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x0e,
- 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x5b,
- 0x0a, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69,
- 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c,
- 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53,
- 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x0b,
- 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x6d,
- 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0e,
- 0x6e, 0x75, 0x6d, 0x5f, 0x6f, 0x66, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4f, 0x66, 0x4d, 0x6f, 0x64, 0x75, 0x6c,
- 0x65, 0x73, 0x22, 0x2f, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65,
- 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09,
- 0x0a, 0x05, 0x53, 0x4f, 0x4f, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4b,
- 0x45, 0x10, 0x02, 0x22, 0x6c, 0x0a, 0x1a, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55,
- 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62,
- 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x42, 0x61, 0x73, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x22, 0x62, 0x0a, 0x1b, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65,
- 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
- 0x12, 0x43, 0x0a, 0x04, 0x63, 0x75, 0x6a, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f,
- 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
- 0x72, 0x69, 0x63, 0x73, 0x2e, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65,
- 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52,
- 0x04, 0x63, 0x75, 0x6a, 0x73, 0x22, 0xcc, 0x02, 0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x42,
- 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d,
- 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x6f,
- 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74,
- 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74,
- 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63,
- 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74, 0x6f,
- 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a,
- 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a,
- 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c,
- 0x6c, 0x6f, 0x63, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68,
- 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b,
- 0x6d, 0x61, 0x78, 0x48, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x65,
- 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f,
- 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
- 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e,
- 0x74, 0x73, 0x12, 0x50, 0x0a, 0x11, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c,
- 0x64, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e,
+ 0x63, 0x68, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x6f, 0x6e, 0x5f, 0x7a, 0x65, 0x72, 0x6f,
+ 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x6e,
+ 0x5a, 0x65, 0x72, 0x6f, 0x45, 0x78, 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f,
+ 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x30, 0x0a,
+ 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x12, 0x08, 0x0a,
+ 0x04, 0x55, 0x53, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x53, 0x45, 0x52, 0x44,
+ 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x45, 0x4e, 0x47, 0x10, 0x02, 0x22,
+ 0x3c, 0x0a, 0x04, 0x41, 0x72, 0x63, 0x68, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f,
+ 0x57, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x52, 0x4d, 0x10, 0x01, 0x12, 0x09, 0x0a,
+ 0x05, 0x41, 0x52, 0x4d, 0x36, 0x34, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x58, 0x38, 0x36, 0x10,
+ 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x58, 0x38, 0x36, 0x5f, 0x36, 0x34, 0x10, 0x04, 0x22, 0x99, 0x02,
+ 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x19, 0x0a,
+ 0x08, 0x75, 0x73, 0x65, 0x5f, 0x67, 0x6f, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x07, 0x75, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x5f,
+ 0x72, 0x62, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x75, 0x73, 0x65, 0x52, 0x62,
+ 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x67,
+ 0x6f, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x66, 0x6f, 0x72, 0x63, 0x65,
+ 0x55, 0x73, 0x65, 0x47, 0x6f, 0x6d, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x62, 0x61, 0x7a, 0x65, 0x6c,
+ 0x5f, 0x61, 0x73, 0x5f, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x0c, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x41, 0x73, 0x4e, 0x69, 0x6e, 0x6a, 0x61, 0x12, 0x2a, 0x0a,
+ 0x11, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69,
+ 0x6c, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x4d,
+ 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x61, 0x72,
+ 0x67, 0x65, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x74, 0x61, 0x72, 0x67,
+ 0x65, 0x74, 0x73, 0x12, 0x44, 0x0a, 0x1f, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x69, 0x73,
+ 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, 0x7a, 0x65, 0x6c, 0x5f, 0x6d, 0x69, 0x78, 0x65, 0x64,
+ 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1b, 0x66, 0x6f,
+ 0x72, 0x63, 0x65, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x61, 0x7a, 0x65, 0x6c, 0x4d,
+ 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x22, 0x6f, 0x0a, 0x12, 0x53, 0x79, 0x73,
+ 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12,
+ 0x32, 0x0a, 0x15, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61,
+ 0x6c, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13,
+ 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, 0x68, 0x79, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x4d, 0x65, 0x6d,
+ 0x6f, 0x72, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65,
+ 0x5f, 0x63, 0x70, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x76, 0x61,
+ 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x70, 0x75, 0x73, 0x22, 0xca, 0x02, 0x0a, 0x08, 0x50,
+ 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72,
+ 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65,
+ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
+ 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a,
+ 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09,
+ 0x72, 0x65, 0x61, 0x6c, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x08, 0x72, 0x65, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0a, 0x6d, 0x65, 0x6d,
+ 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x02, 0x18,
+ 0x01, 0x52, 0x09, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x17,
+ 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
+ 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e,
0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49,
- 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73,
- 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xdb, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66,
- 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x06, 0x73, 0x74, 0x61,
- 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x73, 0x6f, 0x6f, 0x6e,
- 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e,
- 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72,
- 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73,
- 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d,
- 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d,
- 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x04, 0x52, 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x22, 0x47, 0x0a, 0x0c, 0x43, 0x6f, 0x6e,
- 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f,
- 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4e, 0x46,
- 0x49, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12,
- 0x11, 0x0a, 0x0d, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x43, 0x45, 0x52, 0x54,
- 0x10, 0x03, 0x22, 0x91, 0x01, 0x0a, 0x0f, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c,
- 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3d, 0x0a, 0x1b, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f,
- 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f,
- 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x18, 0x6d, 0x69, 0x78,
- 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f,
- 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x3f, 0x0a, 0x1c, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62,
- 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f,
- 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x19, 0x6d, 0x69, 0x78,
- 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d,
- 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x42, 0x28, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x69, 0x63, 0x73, 0x2e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75,
+ 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x15, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
+ 0x65, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22,
+ 0x0a, 0x0d, 0x6e, 0x6f, 0x6e, 0x5f, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18,
+ 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x6e, 0x5a, 0x65, 0x72, 0x6f, 0x45, 0x78,
+ 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73,
+ 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72,
+ 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xb9, 0x03, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x63,
+ 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12,
+ 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
+ 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65,
+ 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x75,
+ 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x2c, 0x0a,
+ 0x12, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63,
+ 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x73, 0x79, 0x73, 0x74, 0x65,
+ 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x1c, 0x0a, 0x0a, 0x6d,
+ 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b, 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b, 0x62, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x69, 0x6e,
+ 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x05,
+ 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46,
+ 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x70,
+ 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74,
+ 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62,
+ 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6f, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4b,
+ 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x6b,
+ 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x75,
+ 0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79,
+ 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65,
+ 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61,
+ 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65,
+ 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79,
+ 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65,
+ 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e,
+ 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63,
+ 0x68, 0x65, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x0e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79,
+ 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x5b, 0x0a, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
+ 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x73,
+ 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66,
+ 0x6f, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3a, 0x07, 0x55,
+ 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73,
+ 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x79,
+ 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
+ 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x6f, 0x66, 0x5f, 0x6d,
+ 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75,
+ 0x6d, 0x4f, 0x66, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x2f, 0x0a, 0x0b, 0x42, 0x75,
+ 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b,
+ 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x4f, 0x4f, 0x4e, 0x47, 0x10,
+ 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4b, 0x45, 0x10, 0x02, 0x22, 0x6c, 0x0a, 0x1a, 0x43,
+ 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e,
+ 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
+ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a,
+ 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20,
+ 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x42, 0x61, 0x73, 0x65,
+ 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x62, 0x0a, 0x1b, 0x43, 0x72, 0x69,
+ 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79,
+ 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x43, 0x0a, 0x04, 0x63, 0x75, 0x6a, 0x73,
+ 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62,
+ 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x43, 0x72, 0x69,
+ 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79,
+ 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x04, 0x63, 0x75, 0x6a, 0x73, 0x22, 0xcc, 0x02,
+ 0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72,
+ 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1a, 0x0a,
+ 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52,
+ 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x6f, 0x74,
+ 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63,
+ 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61,
+ 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x53, 0x69, 0x7a, 0x65, 0x12,
+ 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65,
+ 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x48, 0x65, 0x61, 0x70, 0x53,
+ 0x69, 0x7a, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20,
+ 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c,
+ 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e,
+ 0x66, 0x6f, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x50, 0x0a, 0x11, 0x6d, 0x69,
+ 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18,
+ 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
+ 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x69, 0x78, 0x65,
+ 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x6d, 0x69, 0x78,
+ 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xdb, 0x01, 0x0a,
+ 0x10, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65,
+ 0x72, 0x12, 0x4a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x0e, 0x32, 0x32, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f,
+ 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69,
+ 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53,
+ 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a,
+ 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x69, 0x63,
+ 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f,
+ 0x73, 0x22, 0x47, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75,
+ 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x00,
+ 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05,
+ 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x49, 0x53, 0x53, 0x49,
+ 0x4e, 0x47, 0x5f, 0x47, 0x43, 0x45, 0x52, 0x54, 0x10, 0x03, 0x22, 0x91, 0x01, 0x0a, 0x0f, 0x4d,
+ 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3d,
+ 0x0a, 0x1b, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x65, 0x6e,
+ 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20,
+ 0x03, 0x28, 0x09, 0x52, 0x18, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x45,
+ 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x3f, 0x0a,
+ 0x1c, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x69, 0x73,
+ 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20,
+ 0x03, 0x28, 0x09, 0x52, 0x19, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44,
+ 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x42, 0x28,
+ 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f,
+ 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index 4f8fe7f..07a7df1 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -111,6 +111,14 @@
// The metrics of the experiment config fetcher
optional ExpConfigFetcher exp_config_fetcher = 28;
+
+ // Whether the build exited with a panic or non-zero exit code, includes both
+ // non-zero exits of recorded phases and non-recorded phases of the build.
+ optional bool non_zero_exit = 29;
+
+ // The error message due to a non-zero exit _only_ if it did not occur in a
+ // recorded phase of the build.
+ optional string error_message = 30;
}
message BuildConfig {
@@ -130,6 +138,9 @@
// These are the targets soong passes to ninja, these targets include special
// targets such as droid as well as the regular build targets.
repeated string targets = 6;
+
+ // Whether the user explicitly disabled bazel mixed builds for this build.
+ optional bool force_disable_bazel_mixed_build = 7;
}
message SystemResourceInfo {
@@ -160,6 +171,13 @@
// The resource information of each executed process.
repeated ProcessResourceInfo processes_resource_info = 6;
+
+ // Whether the phase of tool running exited with a panic or non-zero exit
+ // code.
+ optional bool non_zero_exit = 7;
+
+ // The error message, if any, due to a non-zero exit.
+ optional string error_message = 8;
}
message ProcessResourceInfo {