Merge "Globally enable -Wdefaulted-function-deleted."
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/Android.bp b/android/Android.bp
index e0ad58f..29a88f2 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -30,6 +30,7 @@
srcs: [
"androidmk.go",
"apex.go",
+ "api_domain.go",
"api_levels.go",
"arch.go",
"arch_list.go",
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index cc854a3..10c3d09 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -33,10 +33,15 @@
// 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 (
Bp2buildDefaultConfig = Bp2BuildConfig{
+ "art": Bp2BuildDefaultTrue,
"art/libartbase": Bp2BuildDefaultTrueRecursively,
"art/libartpalette": Bp2BuildDefaultTrueRecursively,
"art/libdexfile": Bp2BuildDefaultTrueRecursively,
@@ -44,16 +49,22 @@
"art/runtime": Bp2BuildDefaultTrueRecursively,
"art/tools": Bp2BuildDefaultTrue,
"bionic": Bp2BuildDefaultTrueRecursively,
+ "bootable/recovery/minadbd": Bp2BuildDefaultTrue,
+ "bootable/recovery/minui": Bp2BuildDefaultTrue,
+ "bootable/recovery/applypatch": 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,
"build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir
"build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue,
"build/soong/cc/symbolfile": Bp2BuildDefaultTrue,
+ "build/soong/licenses": Bp2BuildDefaultTrue,
"build/soong/linkerconfig": Bp2BuildDefaultTrueRecursively,
"build/soong/scripts": Bp2BuildDefaultTrueRecursively,
@@ -98,11 +109,14 @@
"external/aac": Bp2BuildDefaultTrueRecursively,
"external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
"external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively,
+ "external/auto": Bp2BuildDefaultTrue,
"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,
@@ -119,15 +133,21 @@
"external/icu": Bp2BuildDefaultTrueRecursively,
"external/icu/android_icu4j": Bp2BuildDefaultFalse, // java rules incomplete
"external/icu/icu4j": Bp2BuildDefaultFalse, // java rules incomplete
+ "external/jacoco": Bp2BuildDefaultTrueRecursively,
"external/jarjar": 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,
@@ -137,9 +157,11 @@
"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/objenesis": Bp2BuildDefaultTrueRecursively,
"external/openscreen": Bp2BuildDefaultTrueRecursively,
"external/pcre": Bp2BuildDefaultTrueRecursively,
"external/protobuf": Bp2BuildDefaultTrueRecursively,
@@ -154,29 +176,39 @@
"external/zopfli": Bp2BuildDefaultTrueRecursively,
"external/zstd": Bp2BuildDefaultTrueRecursively,
+ "frameworks/av": Bp2BuildDefaultTrue,
"frameworks/av/media/codecs": Bp2BuildDefaultTrueRecursively,
+ "frameworks/av/media/codec2/components/aom": Bp2BuildDefaultTrueRecursively,
"frameworks/av/media/liberror": Bp2BuildDefaultTrueRecursively,
"frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively,
+ "frameworks/av/media/module/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/streaming_proto": Bp2BuildDefaultTrueRecursively,
+ "frameworks/base/tools/aapt2": Bp2BuildDefaultTrue,
"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,
@@ -190,6 +222,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,
@@ -207,6 +247,7 @@
"packages/apps/DevCamera": Bp2BuildDefaultTrue,
"packages/apps/HTMLViewer": Bp2BuildDefaultTrue,
"packages/apps/Protips": Bp2BuildDefaultTrue,
+ "packages/apps/SafetyRegulatoryInfo": Bp2BuildDefaultTrue,
"packages/apps/WallpaperPicker": Bp2BuildDefaultTrue,
"packages/modules/StatsD/lib/libstatssocket": Bp2BuildDefaultTrueRecursively,
"packages/modules/adb": Bp2BuildDefaultTrue,
@@ -218,6 +259,7 @@
"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)
@@ -227,6 +269,7 @@
"prebuilts/runtime/mainline/platform/sdk": Bp2BuildDefaultTrueRecursively,
"prebuilts/sdk/current/extras/app-toolkit": Bp2BuildDefaultTrue,
"prebuilts/sdk/current/support": Bp2BuildDefaultTrue,
+ "prebuilts/tools": Bp2BuildDefaultTrue,
"prebuilts/tools/common/m2": Bp2BuildDefaultTrue,
"system/apex": Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures
@@ -236,6 +279,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,
@@ -243,12 +288,16 @@
"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,
"system/libfmq": Bp2BuildDefaultTrue,
@@ -268,6 +317,7 @@
"system/libprocinfo": Bp2BuildDefaultTrue,
"system/libziparchive": Bp2BuildDefaultTrueRecursively,
"system/logging": Bp2BuildDefaultTrueRecursively,
+ "system/media": Bp2BuildDefaultTrue,
"system/media/audio": Bp2BuildDefaultTrueRecursively,
"system/media/audio_utils": Bp2BuildDefaultTrueRecursively,
"system/memory/libion": Bp2BuildDefaultTrueRecursively,
@@ -276,6 +326,8 @@
"system/testing/gtest_extras": Bp2BuildDefaultTrueRecursively,
"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,
@@ -293,15 +345,22 @@
// build/make/tools/signapk BUILD file is generated, so build/make/tools is not recursive.
"build/make/tools":/* recursive = */ false,
"build/pesto":/* recursive = */ true,
- "build/soong/ui/metrics/bp2build_progress_metrics_proto":/* recursive = */ true,
+ "build/soong":/* recursive = */ true,
// external/bazelbuild-rules_android/... is needed by mixed builds, otherwise mixed builds analysis fails
// e.g. ERROR: Analysis of target '@soong_injection//mixed_builds:buildroot' failed
"external/bazelbuild-rules_android":/* recursive = */ true,
+ "external/bazelbuild-rules_license":/* recursive = */ true,
+ "external/bazelbuild-kotlin-rules":/* recursive = */ true,
"external/bazel-skylib":/* recursive = */ true,
"external/guava":/* recursive = */ true,
"external/jsr305":/* recursive = */ true,
"external/protobuf":/* recursive = */ false,
+
+ // this BUILD file is globbed by //external/icu/icu4c/source:icu4c_test_data's "data/**/*".
+ "external/icu/icu4c/source/data/unidata/norm2":/* recursive = */ false,
+
+ "frameworks/base/tools/codegen":/* recursive = */ true,
"frameworks/ex/common":/* recursive = */ true,
"packages/apps/Music":/* recursive = */ true,
@@ -320,21 +379,32 @@
}
Bp2buildModuleAlwaysConvertList = []string{
+ "libidmap2_policies",
+ "libSurfaceFlingerProp",
// cc mainline modules
"code_coverage.policy",
"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",
+ "com.android.neuralnetworks",
"com.android.neuralnetworks-androidManifest",
"com.android.neuralnetworks.certificate",
"com.android.neuralnetworks.key",
"flatbuffer_headers",
+ "framework-cppstream-protos",
+ "framework-javastream-protos",
+ "framework-connectivity-protos",
"gemmlowp_headers",
"gl_headers",
+ "ipconnectivity-proto-src",
+ "libaidlcommonsupport",
"libandroid_runtime_lazy",
"libandroid_runtime_vm_headers",
"libaudioclient_aidl_conversion_util",
@@ -343,37 +413,51 @@
"libbinder_aidl",
"libbinder_headers",
"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",
+ "libneuralnetworks",
+ "libgraphicsenv",
"libhardware",
"libhardware_headers",
- "libincfs_headers",
"libnativeloader-headers",
"libnativewindow_headers",
"libneuralnetworks_headers",
+ "libneuralnetworks_packageinfo",
"libopus",
- "libpdx_headers",
"libprocpartition",
"libruy_static",
"libandroidio",
"libandroidio_srcs",
"libserviceutils",
+ "libstagefright_amrnbenc",
+ "libstagefright_amrnbdec",
+ "libstagefright_amrwbdec",
+ "libstagefright_amrwbenc",
+ "libstagefright_amrnb_common",
"libstagefright_enc_common",
+ "libstagefright_flacdec",
+ "libstagefright_foundation",
"libstagefright_foundation_headers",
"libstagefright_headers",
+ "libstagefright_m4vh263dec",
+ "libstagefright_m4vh263enc",
+ "libstagefright_mp3dec",
+ "libstagefright_mp3dec_headers",
"libsurfaceflinger_headers",
"libsync",
"libtextclassifier_hash_headers",
"libtextclassifier_hash_static",
"libtflite_kernel_utils",
"libtinyxml2",
+ "libui",
"libui-types",
"libui_headers",
"libvorbisidec",
@@ -381,13 +465,33 @@
"media_plugin_headers",
"mediaswcodec.policy",
"mediaswcodec.xml",
+ "neuralnetworks_types",
+ "neuralnetworks_utils_hal_aidl",
+ "neuralnetworks_utils_hal_common",
+ "neuralnetworks_utils_hal_service",
+ "neuralnetworks_utils_hal_1_0",
+ "neuralnetworks_utils_hal_1_1",
+ "neuralnetworks_utils_hal_1_2",
+ "neuralnetworks_utils_hal_1_3",
+ "libneuralnetworks_common",
+ // packagemanager_aidl_interface is created implicitly in packagemanager_aidl module
+ "packagemanager_aidl_interface",
"philox_random",
"philox_random_headers",
"server_configurable_flags",
+ "service-permission-streaming-proto-sources",
+ "statslog_neuralnetworks.cpp",
+ "statslog_neuralnetworks.h",
"tensorflow_headers",
+ "libstagefright_bufferpool@2.0",
+ "libstagefright_bufferpool@2.0.1",
+ "libSurfaceFlingerProp",
+
+ // prebuilts
+ "prebuilt_stats-log-api-gen",
+
// fastboot
- "bootimg_headers",
"fastboot",
"libfastboot",
"liblp",
@@ -398,6 +502,10 @@
"libavb",
"avb_headers",
+ //external/libxml2
+ "xmllint",
+ "libxml2",
+
//external/fec
"libfec_rs",
@@ -416,6 +524,7 @@
//system/extras/verity/fec
"fec",
+ "boot_signer",
//packages/apps/Car/libs/car-ui-lib/car-ui-androidx
// genrule dependencies for java_imports
@@ -445,17 +554,132 @@
"ILogcatManagerService_aidl",
"libincremental_aidl-cpp",
"incremental_aidl",
+
+ //frameworks/native/cmds/cmd
+ "libcmd",
+
+ //system/core/fs_mgr/libdm
+ "libdm",
+
+ //system/core/fs_mgr/libfiemap
+ "libfiemap_headers",
+ "libfiemap_passthrough_srcs",
+ "libfiemap_srcs",
+
+ //system/gsid
+ "libgsi",
+ "libgsi_headers",
+
+ //system/core/libkeyutils
+ "libkeyutils",
+
+ //bootable/recovery/otautil
+ "libotautil",
+
+ //system/vold
+ "libvold_headers",
+
+ //system/extras/libfscrypt
+ "libfscrypt",
+
+ //system/core/fs_mgr
+ "libfstab",
+
+ //bootable/recovery/fuse_sideload
+ "libfusesideload",
+
+ //system/core/fs_mgr/libfs_avb
+ "libfs_avb",
+
+ //system/core/fs_mgr
+ "libfs_mgr",
+
+ "libcodec2_hidl@1.0",
+ "libcodec2_hidl@1.1",
+ "libcodec2_hidl@1.2",
+ "libcodec2_hidl_plugin_stub",
+ "libcodec2_hidl_plugin",
+ "libstagefright_bufferqueue_helper_novndk",
+ "libGLESv2",
+ "libEGL",
+ "libcodec2_vndk",
+ "libnativeloader_lazy",
+ "libnativeloader",
+ "libEGL_getProcAddress",
+ "libEGL_blobCache",
+
+ "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",
}
Bp2buildModuleTypeAlwaysConvertList = []string{
+ "aidl_interface_headers",
+ "license",
"linker_config",
"java_import",
"java_import_host",
"sysprop_library",
- "aidl_interface_headers",
+ "bpf",
}
+ // Add the names of modules that bp2build should never convert, if it is
+ // in the package allowlist. An error will be thrown if a module must
+ // not be here and in the alwaysConvert lists.
+ //
+ // For prebuilt modules (e.g. android_library_import), remember to add
+ // 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
@@ -492,39 +716,32 @@
"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
-
- // proto support
- "libstats_proto_host", // TODO(b/236055697): handle protos from other packages
+ // 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
+ "prebuilt_robolectric-monitor-1.0.2-alpha1",
// path property for filegroups
"conscrypt", // TODO(b/210751803), we don't handle path property for filegroups
"conscrypt-for-host", // TODO(b/210751803), we don't handle path property for filegroups
"host-libprotobuf-java-full", // TODO(b/210751803), we don't handle path property for filegroups
- "libprotobuf-internal-protos", // TODO(b/210751803), we don't handle path property for filegroups
"libprotobuf-internal-python-srcs", // TODO(b/210751803), we don't handle path property for filegroups
"libprotobuf-java-full", // TODO(b/210751803), we don't handle path property for filegroups
"libprotobuf-java-util-full", // TODO(b/210751803), we don't handle path property for filegroups
"auto_value_plugin_resources", // TODO(b/210751803), we don't handle path property for filegroups
// go deps:
- "analyze_bcpf", // depends on bpmodify a blueprint_go_binary.
- "apex-protos", // depends on soong_zip, a go binary
- "generated_android_icu4j_src_files", "generated_android_icu4j_test_files", "icu4c_test_data", // depends on unconverted modules: soong_zip
- "host_bionic_linker_asm", // depends on extract_linker, a go binary.
- "host_bionic_linker_script", // depends on extract_linker, a go binary.
- "libc_musl_sysroot_bionic_arch_headers", // depends on soong_zip
- "libc_musl_sysroot_zlib_headers", // depends on soong_zip and zip2zip
- "libc_musl_sysroot_bionic_headers", // 218405924, depends on soong_zip and generates duplicate srcs
- "libc_musl_sysroot_libc++_headers", "libc_musl_sysroot_libc++abi_headers", // depends on soong_zip, zip2zip
- "robolectric-sqlite4java-native", // depends on soong_zip, a go binary
- "robolectric_tzdata", // depends on soong_zip, a go binary
+ "analyze_bcpf", // depends on bpmodify a blueprint_go_binary.
+ "host_bionic_linker_asm", // depends on extract_linker, a go binary.
+ "host_bionic_linker_script", // depends on extract_linker, a go binary.
+
+ // in cmd attribute of genrule rule //system/timezone/output_data:robolectric_tzdata: label '//system/timezone/output_data:iana/tzdata' in $(location) expression is not a declared prerequisite of this rule
+ "robolectric_tzdata",
// rust support
"libtombstoned_client_rust_bridge_code", "libtombstoned_client_wrapper", // rust conversions are not supported
// unconverted deps
"CarHTMLViewer", // depends on unconverted modules android.car-stubs, car-ui-lib
- "abb", // depends on unconverted modules: libcmd, libbinder
"adb", // depends on unconverted modules: AdbWinApi, libandroidfw, libopenscreen-discovery, libopenscreen-platform-impl, libusb, bin2c_fastdeployagent, AdbWinUsbApi
"android_icu4j_srcgen", // depends on unconverted modules: currysrc
"android_icu4j_srcgen_binary", // depends on unconverted modules: android_icu4j_srcgen, currysrc
@@ -534,9 +751,10 @@
"com.android.runtime", // depends on unconverted modules: bionic-linker-config, linkerconfig
"currysrc", // depends on unconverted modules: currysrc_org.eclipse, guavalib, jopt-simple-4.9
"dex2oat-script", // depends on unconverted modules: dex2oat
- "generated_android_icu4j_resources", // depends on unconverted modules: android_icu4j_srcgen_binary, soong_zip
- "generated_android_icu4j_test_resources", // depends on unconverted modules: android_icu4j_srcgen_binary, soong_zip
+ "generated_android_icu4j_resources", // depends on unconverted modules: android_icu4j_srcgen_binary
+ "generated_android_icu4j_test_resources", // depends on unconverted modules: android_icu4j_srcgen_binary
"host-libprotobuf-java-nano", // b/220869005, depends on libprotobuf-java-nano
+ "jacoco-stubs", // b/245767077, depends on droidstubs
"libapexutil", // depends on unconverted modules: apex-info-list-tinyxml
"libart", // depends on unconverted modules: apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api, art_operator_srcs, libcpu_features, libodrstatslog, libelffile, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfile, libnativebridge, libnativeloader, libsigchain, libartbase, libprofile, cpp-define-generator-asm-support
"libart-runtime-gtest", // depends on unconverted modules: libgtest_isolated, libart-compiler, libdexfile, libprofile, libartbase, libartbase-art-gtest
@@ -559,19 +777,29 @@
"libstatslog_art", // depends on unconverted modules: statslog_art.cpp, statslog_art.h
"linker_reloc_bench_main", // depends on unconverted modules: liblinker_reloc_bench_*
"pbtombstone", "crash_dump", // depends on libdebuggerd, libunwindstack
- "robolectric-sqlite4java-0.282", // depends on unconverted modules: robolectric-sqlite4java-import, robolectric-sqlite4java-native
- "static_crasher", // depends on unconverted modules: libdebuggerd_handler
- "stats-log-api-gen", // depends on unconverted modules: libstats_proto_host
- "statslog.cpp", "statslog.h", "statslog.rs", // depends on unconverted modules: stats-log-api-gen
- "statslog_art.cpp", "statslog_art.h", "statslog_header.rs", // depends on unconverted modules: stats-log-api-gen
- "test_fips", // depends on unconverted modules: adb
- "timezone-host", // depends on unconverted modules: art.module.api.annotations
- "truth-host-prebuilt", // depends on unconverted modules: truth-prebuilt
- "truth-prebuilt", // depends on unconverted modules: asm-7.0, guava
+ "robolectric-sqlite4java-0.282", // depends on unconverted modules: robolectric-sqlite4java-import, robolectric-sqlite4java-native
+ "static_crasher", // depends on unconverted modules: libdebuggerd_handler
+ "test_fips", // depends on unconverted modules: adb
+ "timezone-host", // depends on unconverted modules: art.module.api.annotations
+ "truth-host-prebuilt", // depends on unconverted modules: truth-prebuilt
+ "truth-prebuilt", // depends on unconverted modules: asm-7.0, guava
// '//bionic/libc:libc_bp2build_cc_library_static' is duplicated in the 'deps' attribute of rule
"toybox-static",
+ // aidl files not created
+ "overlayable_policy_aidl_interface",
+
+ //prebuilts/tools/common/m2
+ // 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",
@@ -596,6 +824,8 @@
"libnativebridge6-test-case",
"libnativebridge6prezygotefork",
+ "libandroidfw_tests", "aapt2_tests", // failing due to data path issues
+
// cc_test with unconverted deps, or are device-only (and not verified to pass yet)
"AMRWBEncTest",
"AmrnbDecoderTest", // depends on unconverted modules: libaudioutils, libsndfile
@@ -605,11 +835,6 @@
"Mp3DecoderTest", // depends on unconverted modules: libsndfile, libaudioutils
"Mpeg4H263DecoderTest", // depends on unconverted modules: libstagefright_foundation
"Mpeg4H263EncoderTest",
- "adb_crypto_test",
- "adb_pairing_auth_test",
- "adb_pairing_connection_test",
- "adb_tls_connection_test",
- "adbd_test", // depends on unconverted modules: libusb
"avcdec",
"avcenc",
"bionic-benchmarks-tests",
@@ -658,7 +883,6 @@
"libBionicCtsGtestMain", // depends on unconverted modules: libgtest_isolated
"libBionicLoaderTests", // depends on unconverted modules: libmeminfo
"libapexutil_tests", // depends on unconverted modules: apex-info-list-tinyxml, libapexutil
- "libavservices_minijail_unittest",
"libcutils_sockets_test",
"libexpectedutils_test",
"libhwbinder_latency",
@@ -705,7 +929,6 @@
"yuvconstants",
"yuvconvert",
"zipalign_tests",
- // "zlib_tests",
// cc_test_library
"clang_diagnostic_tests",
@@ -739,6 +962,7 @@
"libdlext_test_norelro",
"libdlext_test_recursive",
"libdlext_test_zip",
+ "libdvrcommon_test",
"libfortify1-new-tests-clang",
"libfortify1-new-tests-clang",
"libfortify1-tests-clang",
@@ -1031,6 +1255,39 @@
"libtest_with_dependency_loop_b_tmp",
"libtest_with_dependency_loop_c",
"libtestshared",
+
+ // depends on unconverted libprotobuf-java-nano
+ "dnsresolverprotosnano",
+ "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{}
@@ -1079,10 +1336,21 @@
"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
+ "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",
}
ProdMixedBuildsEnabledList = []string{
- // This list left intentionally empty for now. Add specific module names
- // to have them built by Bazel in Prod Mixed Builds mode.
+ "com.android.adbd",
}
)
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/androidmk.go b/android/androidmk.go
index 006e43d..18e3e7a 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -366,7 +366,9 @@
// Collate the contributions this module makes to the dist.
distContributions := &distContributions{}
- distContributions.licenseMetadataFile = amod.licenseMetadataFile
+ if !exemptFromRequiredApplicableLicensesProperty(mod.(Module)) {
+ distContributions.licenseMetadataFile = amod.licenseMetadataFile
+ }
// Iterate over this module's dist structs, merged from the dist and dists properties.
for _, dist := range amod.Dists() {
@@ -458,10 +460,12 @@
ret = append(ret, fmt.Sprintf(".PHONY: %s\n", d.goals))
// Create dist-for-goals calls for each of the copy instructions.
for _, c := range d.copies {
- ret = append(
- ret,
- fmt.Sprintf("$(if $(strip $(ALL_TARGETS.%s.META_LIC)),,$(eval ALL_TARGETS.%s.META_LIC := %s))\n",
- c.from.String(), c.from.String(), distContributions.licenseMetadataFile.String()))
+ if distContributions.licenseMetadataFile != nil {
+ ret = append(
+ ret,
+ fmt.Sprintf("$(if $(strip $(ALL_TARGETS.%s.META_LIC)),,$(eval ALL_TARGETS.%s.META_LIC := %s))\n",
+ c.from.String(), c.from.String(), distContributions.licenseMetadataFile.String()))
+ }
ret = append(
ret,
fmt.Sprintf("$(call dist-for-goals,%s,%s:%s)\n", d.goals, c.from.String(), c.dest))
diff --git a/android/apex.go b/android/apex.go
index 00b7241..3c945ae 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -454,8 +454,6 @@
}
return InList(what, apex_available) ||
(what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available)) ||
- (what == "com.android.btservices" && InList("com.android.bluetooth", apex_available)) || // TODO b/243054261
- (what == "com.android.bluetooth" && InList("com.android.btservices", apex_available)) || // TODO b/243054261
(strings.HasPrefix(what, "com.android.gki.") && InList(AvailableToGkiApex, apex_available))
}
diff --git a/android/api_domain.go b/android/api_domain.go
new file mode 100644
index 0000000..0993e3d
--- /dev/null
+++ b/android/api_domain.go
@@ -0,0 +1,123 @@
+// 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 android
+
+import (
+ "github.com/google/blueprint"
+
+ "android/soong/bazel"
+)
+
+func init() {
+ RegisterApiDomainBuildComponents(InitRegistrationContext)
+}
+
+func RegisterApiDomainBuildComponents(ctx RegistrationContext) {
+ ctx.RegisterModuleType("api_domain", ApiDomainFactory)
+}
+
+type ApiSurface int
+
+// TODO(b/246656800): Reconcile with android.SdkKind
+const (
+ PublicApi ApiSurface = iota
+ SystemApi
+ VendorApi
+)
+
+func (a ApiSurface) String() string {
+ switch a {
+ case PublicApi:
+ return "publicapi"
+ case SystemApi:
+ return "systemapi"
+ case VendorApi:
+ return "vendorapi"
+ default:
+ return "invalid"
+ }
+}
+
+type apiDomain struct {
+ ModuleBase
+ BazelModuleBase
+
+ properties apiDomainProperties
+}
+
+type apiDomainProperties struct {
+ // cc library contributions (.h files/.map.txt) of this API domain
+ // This dependency is a no-op in Soong, but the corresponding Bazel target in the bp2build workspace will provide a `CcApiContributionInfo` provider
+ Cc_api_contributions []string
+}
+
+func ApiDomainFactory() Module {
+ m := &apiDomain{}
+ m.AddProperties(&m.properties)
+ InitAndroidArchModule(m, DeviceSupported, MultilibBoth)
+ return m
+}
+
+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 that matches (os,arch) 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(ctx.Target().Variations(), nil, cc)
+ }
+}
+
+// API domain does not have any builld actions yet
+func (a *apiDomain) GenerateAndroidBuildActions(ctx ModuleContext) {
+}
+
+const (
+ apiContributionSuffix = ".contribution"
+)
+
+// ApiContributionTargetName returns the name of the bp2build target (e.g. cc_api_contribution) of contribution modules (e.g. ndk_library)
+// A suffix is necessary to prevent a name collision with the base target in the same bp2build bazel package
+func ApiContributionTargetName(moduleName string) string {
+ return moduleName + apiContributionSuffix
+}
+
+// For each contributing cc_library, format the name to its corresponding contribution bazel target in the bp2build workspace
+func contributionBazelAttributes(ctx TopDownMutatorContext, contributions []string) bazel.LabelListAttribute {
+ addSuffix := func(ctx BazelConversionPathContext, module blueprint.Module) string {
+ baseLabel := BazelModuleLabel(ctx, module)
+ return ApiContributionTargetName(baseLabel)
+ }
+ bazelLabels := BazelLabelForModuleDepsWithFn(ctx, contributions, addSuffix)
+ return bazel.MakeLabelListAttribute(bazelLabels)
+}
+
+type bazelApiDomainAttributes struct {
+ Cc_api_contributions bazel.LabelListAttribute
+}
+
+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",
+ }
+ attrs := &bazelApiDomainAttributes{
+ Cc_api_contributions: contributionBazelAttributes(ctx, a.properties.Cc_api_contributions),
+ }
+ ctx.CreateBazelTargetModule(props, CommonAttributes{
+ Name: ctx.ModuleName(),
+ }, attrs)
+}
diff --git a/android/arch.go b/android/arch.go
index 9bc9d89..75ee922 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -147,10 +147,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 +319,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.
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 eb6aca4..d30cb80 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -32,10 +32,13 @@
Bp2BuildTopLevel = "."
)
-// Bp2buildAidlLibrary describes a filegroup module that are converted to aidl_library
-type Bp2buildAidlLibrary interface {
+// FileGroupAsLibrary describes a filegroup module that is converted to some library
+// such as aidl_library or proto_library.
+type FileGroupAsLibrary interface {
ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) bool
+ ShouldConvertToProtoLibrary(ctx BazelConversionPathContext) bool
GetAidlLibraryLabel(ctx BazelConversionPathContext) string
+ GetProtoLibraryLabel(ctx BazelConversionPathContext) string
}
type BazelConversionStatus struct {
@@ -131,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 {
@@ -412,6 +420,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)
@@ -443,8 +458,8 @@
if ok, directoryPath := bp2buildDefaultTrueRecursively(packagePath, allowlist.defaultConfig); ok {
if moduleNameAllowed {
ctx.ModuleErrorf("A module cannot be in a directory marked Bp2BuildDefaultTrue"+
- " or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: '%s'",
- directoryPath)
+ " or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: '%s'"+
+ " Module: '%s'", directoryPath, moduleName)
return false
}
@@ -474,21 +489,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
@@ -507,6 +528,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 93b6779..29695d6 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -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
@@ -137,6 +144,9 @@
// Returns the results of the GetApexInfo query (including output files)
GetApexInfo(label string, cfgkey configKey) (cquery.ApexCqueryInfo, 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
@@ -160,16 +170,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,
@@ -215,6 +227,7 @@
LabelToCcInfo map[string]cquery.CcInfo
LabelToPythonBinary map[string]string
LabelToApexInfo map[string]cquery.ApexCqueryInfo
+ LabelToCcBinary map[string]cquery.CcUnstrippedInfo
}
func (m MockBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
@@ -240,6 +253,11 @@
panic("unimplemented")
}
+func (m MockBazelContext) GetCcUnstrippedInfo(label string, _ configKey) (cquery.CcUnstrippedInfo, error) {
+ result, _ := m.LabelToCcBinary[label]
+ return result, nil
+}
+
func (m MockBazelContext) InvokeBazel(_ Config) error {
panic("unimplemented")
}
@@ -261,23 +279,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 +305,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
@@ -295,13 +314,21 @@
}
func (bazelCtx *bazelContext) GetApexInfo(label string, cfgKey configKey) (cquery.ApexCqueryInfo, error) {
- key := cqueryKey{label, cquery.GetApexInfo, cfgKey}
+ key := makeCqueryKey(label, cquery.GetApexInfo, cfgKey)
if rawString, ok := bazelCtx.results[key]; ok {
return cquery.GetApexInfo.ParseResult(strings.TrimSpace(rawString)), nil
}
return cquery.ApexCqueryInfo{}, 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)), nil
+ }
+ return cquery.CcUnstrippedInfo{}, fmt.Errorf("no bazel response for %s", key)
+}
+
func (n noopBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
panic("unimplemented")
}
@@ -322,6 +349,11 @@
panic("unimplemented")
}
+func (n noopBazelContext) GetCcUnstrippedInfo(_ string, _ configKey) (cquery.CcUnstrippedInfo, error) {
+ //TODO implement me
+ panic("implement me")
+}
+
func (n noopBazelContext) InvokeBazel(_ Config) error {
panic("unimplemented")
}
@@ -415,6 +447,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 +489,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 +523,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,
@@ -517,15 +580,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 {
@@ -694,6 +756,31 @@
formatString := `
# This file is generated by soong_build. Do not edit.
+# a drop-in replacement for json.encode(), not available in cquery environment
+# TODO(cparsons): bring json module in and remove this function
+def json_encode(input):
+ # Avoiding recursion by limiting
+ # - a dict to contain anything except a dict
+ # - a list to contain only primitives
+ def encode_primitive(p):
+ t = type(p)
+ if t == "string" or t == "int":
+ return repr(p)
+ fail("unsupported value '%%s' of type '%%s'" %% (p, type(p)))
+
+ def encode_list(list):
+ return "[%%s]" %% ", ".join([encode_primitive(item) for item in list])
+
+ def encode_list_or_primitive(v):
+ return encode_list(v) if type(v) == "list" else encode_primitive(v)
+
+ if type(input) == "dict":
+ # TODO(juu): the result is read line by line so can't use '\n' yet
+ kv_pairs = [("%%s: %%s" %% (encode_primitive(k), encode_list_or_primitive(v))) for (k, v) in input.items()]
+ return "{ %%s }" %% ", ".join(kv_pairs)
+ else:
+ return encode_list_or_primitive(input)
+
# Label Map Section
%s
@@ -727,18 +814,13 @@
fail("expected platform name of the form 'android_<arch>' or 'linux_<arch>', but was " + str(platforms))
return "UNKNOWN"
-def json_for_file(key, file):
- return '"' + key + '":"' + file.path + '"'
-
-def json_for_files(key, files):
- return '"' + key + '":[' + ",".join(['"' + f.path + '"' for f in files]) + ']'
-
-def json_for_labels(key, ll):
- return '"' + key + '":[' + ",".join(['"' + str(x) + '"' for x in ll]) + ']'
-
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
@@ -810,15 +892,16 @@
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))
+ cqueryOutput, cqueryErr, err := context.issueBazelCommand(cqueryCommandWithFlag)
if err != nil {
return err
}
- if err = ioutil.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"), []byte(cqueryOutput), 0666); err != nil {
+ 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
}
-
cqueryResults := map[string]string{}
for _, outputLine := range strings.Split(cqueryOutput, "\n") {
if strings.Contains(outputLine, ">>") {
@@ -854,8 +937,8 @@
}
}
aqueryCmd := bazelCommand{"aquery", fmt.Sprintf("deps(%s)", buildrootLabel)}
- if aqueryOutput, _, err := context.issueBazelCommand(context.paths, bazel.AqueryBuildRootRunName, aqueryCmd,
- extraFlags...); err == nil {
+ if aqueryOutput, _, err := context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.AqueryBuildRootRunName, aqueryCmd,
+ extraFlags...)); err == nil {
context.buildStatements, context.depsets, err = bazel.AqueryBuildStatements([]byte(aqueryOutput))
}
if err != nil {
@@ -866,7 +949,7 @@
// 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 {
+ if _, _, err = context.issueBazelCommand(context.createBazelCommand(context.paths, bazel.BazelBuildPhonyRootRunName, buildCmd)); err != nil {
return err
}
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
index ec2541b..dc2261c 100644
--- a/android/bazel_handler_test.go
+++ b/android/bazel_handler_test.go
@@ -13,10 +13,10 @@
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)
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index bbdae96..b2ea22f 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -202,20 +202,26 @@
return labels
}
-// Returns true if a prefix + components[:i] + /Android.bp exists
-// TODO(b/185358476) Could check for BUILD file instead of checking for Android.bp file, or ensure BUILD is always generated?
-func directoryHasBlueprint(fs pathtools.FileSystem, prefix string, components []string, componentIndex int) bool {
- blueprintPath := prefix
- if blueprintPath != "" {
- blueprintPath = blueprintPath + "/"
- }
- blueprintPath = blueprintPath + strings.Join(components[:componentIndex+1], "/")
- blueprintPath = blueprintPath + "/Android.bp"
- if exists, _, _ := fs.Exists(blueprintPath); exists {
+// Returns true if a prefix + components[:i] is a package boundary.
+//
+// A package boundary is determined by a BUILD file in the directory. This can happen in 2 cases:
+//
+// 1. An Android.bp exists, which bp2build will always convert to a sibling BUILD file.
+// 2. An Android.bp doesn't exist, but a checked-in BUILD/BUILD.bazel file exists, and that file
+// is allowlisted by the bp2build configuration to be merged into the symlink forest workspace.
+func isPackageBoundary(config Config, prefix string, components []string, componentIndex int) bool {
+ prefix = filepath.Join(prefix, filepath.Join(components[:componentIndex+1]...))
+ if exists, _, _ := config.fs.Exists(filepath.Join(prefix, "Android.bp")); exists {
return true
- } else {
- return false
+ } else if config.Bp2buildPackageConfig.ShouldKeepExistingBuildFileForDir(prefix) {
+ if exists, _, _ := config.fs.Exists(filepath.Join(prefix, "BUILD")); exists {
+ return true
+ } else if exists, _, _ := config.fs.Exists(filepath.Join(prefix, "BUILD.bazel")); exists {
+ return true
+ }
}
+
+ return false
}
// Transform a path (if necessary) to acknowledge package boundaries
@@ -242,17 +248,37 @@
newPath.Label = path.Label
return newPath
}
-
- newLabel := ""
+ if strings.HasPrefix(path.Label, "./") {
+ // Drop "./" for consistent handling of paths.
+ // Specifically, to not let "." be considered a package boundary.
+ // Say `inputPath` is `x/Android.bp` and that file has some module
+ // with `srcs=["y/a.c", "z/b.c"]`.
+ // And say the directory tree is:
+ // x
+ // âââ Android.bp
+ // âââ y
+ // â âââ a.c
+ // â âââ Android.bp
+ // âââ z
+ // âââ b.c
+ // Then bazel equivalent labels in srcs should be:
+ // //x/y:a.c, x/z/b.c
+ // The above should still be the case if `x/Android.bp` had
+ // srcs=["./y/a.c", "./z/b.c"]
+ // However, if we didn't strip "./", we'd get
+ // //x/./y:a.c, //x/.:z/b.c
+ path.Label = strings.TrimPrefix(path.Label, "./")
+ }
pathComponents := strings.Split(path.Label, "/")
- foundBlueprint := false
+ newLabel := ""
+ foundPackageBoundary := false
// Check the deepest subdirectory first and work upwards
for i := len(pathComponents) - 1; i >= 0; i-- {
pathComponent := pathComponents[i]
var sep string
- if !foundBlueprint && directoryHasBlueprint(ctx.Config().fs, ctx.ModuleDir(), pathComponents, i) {
+ if !foundPackageBoundary && isPackageBoundary(ctx.Config(), ctx.ModuleDir(), pathComponents, i) {
sep = ":"
- foundBlueprint = true
+ foundPackageBoundary = true
} else {
sep = "/"
}
@@ -262,7 +288,7 @@
newLabel = pathComponent + sep + newLabel
}
}
- if foundBlueprint {
+ if foundPackageBoundary {
// Ensure paths end up looking like //bionic/... instead of //./bionic/...
moduleDir := ctx.ModuleDir()
if strings.HasPrefix(moduleDir, ".") {
@@ -508,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_paths_test.go b/android/bazel_paths_test.go
index b047511..450bf76 100644
--- a/android/bazel_paths_test.go
+++ b/android/bazel_paths_test.go
@@ -17,6 +17,10 @@
import (
"path/filepath"
"testing"
+
+ "android/soong/bazel"
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/pathtools"
)
type TestBazelPathContext struct{}
@@ -29,7 +33,7 @@
return cfg
}
-func (*TestBazelPathContext) AddNinjaFileDeps(deps ...string) {
+func (*TestBazelPathContext) AddNinjaFileDeps(...string) {
panic("Unimplemented")
}
@@ -106,3 +110,74 @@
t.Errorf("incorrect OutputPath.Rel(): expected %q, got %q", expectedRelPath, out.Rel())
}
}
+
+type TestBazelConversionPathContext struct {
+ TestBazelConversionContext
+ moduleDir string
+ cfg Config
+}
+
+func (ctx *TestBazelConversionPathContext) AddNinjaFileDeps(...string) {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) GlobWithDeps(string, []string) ([]string, error) {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) PropertyErrorf(string, string, ...interface{}) {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) GetDirectDep(string) (blueprint.Module, blueprint.DependencyTag) {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) ModuleFromName(string) (blueprint.Module, bool) {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) AddUnconvertedBp2buildDep(string) {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) AddMissingBp2buildDep(string) {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) Module() Module {
+ panic("Unimplemented")
+}
+
+func (ctx *TestBazelConversionPathContext) Config() Config {
+ return ctx.cfg
+}
+
+func (ctx *TestBazelConversionPathContext) ModuleDir() string {
+ return ctx.moduleDir
+}
+
+func TestTransformSubpackagePath(t *testing.T) {
+ cfg := NullConfig("out", "out/soong")
+ cfg.fs = pathtools.MockFs(map[string][]byte{
+ "x/Android.bp": nil,
+ "x/y/Android.bp": nil,
+ })
+
+ var ctx BazelConversionPathContext = &TestBazelConversionPathContext{
+ moduleDir: "x",
+ cfg: cfg,
+ }
+ pairs := map[string]string{
+ "y/a.c": "//x/y:a.c",
+ "./y/a.c": "//x/y:a.c",
+ "z/b.c": "z/b.c",
+ "./z/b.c": "z/b.c",
+ }
+ for in, out := range pairs {
+ actual := transformSubpackagePath(ctx, bazel.Label{Label: in}).Label
+ if actual != out {
+ t.Errorf("expected:\n%v\nactual:\n%v", out, actual)
+ }
+ }
+}
diff --git a/android/bazel_test.go b/android/bazel_test.go
index b578cca..3164b23 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 {
@@ -266,7 +294,7 @@
{
description: "module allowlist and enabled directory",
shouldConvert: false,
- expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir'"},
+ expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir' Module: 'foo'"},
module: TestBazelModule{
TestModuleInfo: bazel.TestModuleInfo{
ModuleName: "foo",
@@ -287,7 +315,7 @@
{
description: "module allowlist and enabled subdirectory",
shouldConvert: false,
- expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir'"},
+ expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir' Module: 'foo'"},
module: TestBazelModule{
TestModuleInfo: bazel.TestModuleInfo{
ModuleName: "foo",
diff --git a/android/config.go b/android/config.go
index 745410f..4992882 100644
--- a/android/config.go
+++ b/android/config.go
@@ -83,6 +83,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
@@ -124,6 +127,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.
@@ -1619,6 +1627,14 @@
return uncheckedFinalApiLevel(apiLevel)
}
+func (c *deviceConfig) BuildBrokenClangAsFlags() bool {
+ return c.config.productVariables.BuildBrokenClangAsFlags
+}
+
+func (c *deviceConfig) BuildBrokenClangCFlags() bool {
+ return c.config.productVariables.BuildBrokenClangCFlags
+}
+
func (c *deviceConfig) BuildBrokenClangProperty() bool {
return c.config.productVariables.BuildBrokenClangProperty
}
diff --git a/android/filegroup.go b/android/filegroup.go
index e609f63..6b11172 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -33,6 +33,8 @@
ctx.RegisterModuleType("filegroup", FileGroupFactory)
})
+var convertedProtoLibrarySuffix = "_bp2build_converted"
+
// IsFilegroup checks that a module is a filegroup type
func IsFilegroup(ctx bazel.OtherModuleContext, m blueprint.Module) bool {
return ctx.OtherModuleType(m) == "filegroup"
@@ -117,6 +119,24 @@
ctx.CreateBazelTargetModule(props, CommonAttributes{Name: fg.Name()}, attrs)
} else {
+ 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,
+ }
+
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
+ CommonAttributes{Name: fg.Name() + convertedProtoLibrarySuffix},
+ attrs)
+ }
+
+ // TODO(b/242847534): Still convert to a filegroup because other unconverted
+ // modules may depend on the filegroup
attrs := &bazelFilegroupAttributes{
Srcs: srcs,
}
@@ -150,14 +170,14 @@
type fileGroup struct {
ModuleBase
BazelModuleBase
- Bp2buildAidlLibrary
+ FileGroupAsLibrary
properties fileGroupProperties
srcs Paths
}
var _ MixedBuildBuildable = (*fileGroup)(nil)
var _ SourceFileProducer = (*fileGroup)(nil)
-var _ Bp2buildAidlLibrary = (*fileGroup)(nil)
+var _ FileGroupAsLibrary = (*fileGroup)(nil)
// filegroup contains a list of files that are referenced by other modules
// properties (such as "srcs") using the syntax ":<name>". filegroup are
@@ -243,11 +263,19 @@
}
func (fg *fileGroup) ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) bool {
+ return fg.shouldConvertToLibrary(ctx, ".aidl")
+}
+
+func (fg *fileGroup) ShouldConvertToProtoLibrary(ctx BazelConversionPathContext) bool {
+ return fg.shouldConvertToLibrary(ctx, ".proto")
+}
+
+func (fg *fileGroup) shouldConvertToLibrary(ctx BazelConversionPathContext, suffix string) bool {
if len(fg.properties.Srcs) == 0 || !fg.ShouldConvertWithBp2build(ctx) {
return false
}
for _, src := range fg.properties.Srcs {
- if !strings.HasSuffix(src, ".aidl") {
+ if !strings.HasSuffix(src, suffix) {
return false
}
}
@@ -255,6 +283,14 @@
}
func (fg *fileGroup) GetAidlLibraryLabel(ctx BazelConversionPathContext) string {
+ return fg.getFileGroupAsLibraryLabel(ctx)
+}
+
+func (fg *fileGroup) GetProtoLibraryLabel(ctx BazelConversionPathContext) string {
+ return fg.getFileGroupAsLibraryLabel(ctx) + convertedProtoLibrarySuffix
+}
+
+func (fg *fileGroup) getFileGroupAsLibraryLabel(ctx BazelConversionPathContext) string {
if ctx.OtherModuleDir(fg.module) == ctx.ModuleDir() {
return ":" + fg.Name()
} else {
@@ -265,12 +301,19 @@
// Given a name in srcs prop, check to see if the name references a filegroup
// and the filegroup is converted to aidl_library
func IsConvertedToAidlLibrary(ctx BazelConversionPathContext, name string) bool {
+ if fg, ok := ToFileGroupAsLibrary(ctx, name); ok {
+ return fg.ShouldConvertToAidlLibrary(ctx)
+ }
+ return false
+}
+
+func ToFileGroupAsLibrary(ctx BazelConversionPathContext, name string) (FileGroupAsLibrary, bool) {
if module, ok := ctx.ModuleFromName(name); ok {
if IsFilegroup(ctx, module) {
- if fg, ok := module.(Bp2buildAidlLibrary); ok {
- return fg.ShouldConvertToAidlLibrary(ctx)
+ if fg, ok := module.(FileGroupAsLibrary); ok {
+ return fg, true
}
}
}
- return false
+ return nil, false
}
diff --git a/android/gen_notice.go b/android/gen_notice.go
index e2b839f..008aac5 100644
--- a/android/gen_notice.go
+++ b/android/gen_notice.go
@@ -111,6 +111,9 @@
}
func (m *genNoticeModule) DepsMutator(ctx BottomUpMutatorContext) {
+ if ctx.ContainsProperty("licenses") {
+ ctx.PropertyErrorf("licenses", "not supported on \"gen_notice\" modules")
+ }
if proptools.Bool(m.properties.Html) && proptools.Bool(m.properties.Xml) {
ctx.ModuleErrorf("can be html or xml but not both")
}
@@ -179,7 +182,7 @@
// The visibility property needs to be checked and parsed by the visibility module.
setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
- initAndroidModuleBase(module)
+ InitAndroidArchModule(module, DeviceSupported, MultilibCommon)
InitDefaultableModule(module)
return module
@@ -195,6 +198,16 @@
return nil, fmt.Errorf("unrecognized tag %q", tag)
}
+var _ AndroidMkEntriesProvider = (*genNoticeModule)(nil)
+
+// Implements AndroidMkEntriesProvider
+func (m *genNoticeModule) AndroidMkEntries() []AndroidMkEntries {
+ return []AndroidMkEntries{AndroidMkEntries{
+ Class: "ETC",
+ OutputFile: OptionalPathForPath(m.output),
+ }}
+}
+
// missingReferencesRule emits an ErrorRule for missing module references.
func missingReferencesRule(ctx BuilderContext, m *genNoticeModule) {
if len(m.missing) < 1 {
diff --git a/android/gen_notice_test.go b/android/gen_notice_test.go
index 4ad2ecf..99d982b 100644
--- a/android/gen_notice_test.go
+++ b/android/gen_notice_test.go
@@ -21,7 +21,7 @@
}`),
},
expectedErrors: []string{
- `unrecognized property "licenses"`,
+ `not supported on "gen_notice" modules`,
},
},
{
diff --git a/android/license.go b/android/license.go
index ebee055..cde5e6e 100644
--- a/android/license.go
+++ b/android/license.go
@@ -15,7 +15,10 @@
package android
import (
+ "android/soong/bazel"
+ "fmt"
"github.com/google/blueprint"
+ "os"
)
type licenseKindDependencyTag struct {
@@ -48,14 +51,55 @@
Visibility []string
}
+var _ Bazelable = &licenseModule{}
+
type licenseModule struct {
ModuleBase
DefaultableModuleBase
SdkBase
+ BazelModuleBase
properties licenseProperties
}
+type bazelLicenseAttributes struct {
+ License_kinds []string
+ Copyright_notice *string
+ License_text bazel.LabelAttribute
+ Package_name *string
+ Visibility []string
+}
+
+func (m *licenseModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
+ attrs := &bazelLicenseAttributes{
+ License_kinds: m.properties.License_kinds,
+ Copyright_notice: m.properties.Copyright_notice,
+ Package_name: m.properties.Package_name,
+ Visibility: m.properties.Visibility,
+ }
+
+ // TODO(asmundak): Soong supports multiple license texts while Bazel's license
+ // rule does not. Have android_license create a genrule to concatenate multiple
+ // license texts.
+ if len(m.properties.License_text) > 1 && ctx.Config().IsEnvTrue("BP2BUILD_VERBOSE") {
+ fmt.Fprintf(os.Stderr, "warning: using only the first license_text item from //%s:%s\n",
+ ctx.ModuleDir(), m.Name())
+ }
+ if len(m.properties.License_text) >= 1 {
+ attrs.License_text.SetValue(BazelLabelForModuleSrcSingle(ctx, m.properties.License_text[0]))
+ }
+
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "android_license",
+ Bzl_load_location: "//build/bazel/rules/license:license.bzl",
+ },
+ CommonAttributes{
+ Name: m.Name(),
+ },
+ attrs)
+}
+
func (m *licenseModule) DepsMutator(ctx BottomUpMutatorContext) {
ctx.AddVariationDependencies(nil, licenseKindTag, m.properties.License_kinds...)
}
@@ -78,7 +122,7 @@
module := &licenseModule{}
base := module.base()
- module.AddProperties(&base.nameProperties, &module.properties)
+ module.AddProperties(&base.nameProperties, &module.properties, &base.commonProperties.BazelConversionStatus)
// The visibility property needs to be checked and parsed by the visibility module.
setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
@@ -86,6 +130,7 @@
InitSdkAwareModule(module)
initAndroidModuleBase(module)
InitDefaultableModule(module)
+ InitBazelModule(module)
return module
}
diff --git a/android/license_kind.go b/android/license_kind.go
index 838dedd..24b91e4 100644
--- a/android/license_kind.go
+++ b/android/license_kind.go
@@ -14,6 +14,8 @@
package android
+import "android/soong/bazel"
+
func init() {
RegisterLicenseKindBuildComponents(InitRegistrationContext)
}
@@ -32,13 +34,39 @@
Visibility []string
}
+var _ Bazelable = &licenseKindModule{}
+
type licenseKindModule struct {
ModuleBase
DefaultableModuleBase
+ BazelModuleBase
properties licenseKindProperties
}
+type bazelLicenseKindAttributes struct {
+ Conditions []string
+ Url string
+ Visibility []string
+}
+
+func (m *licenseKindModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
+ attrs := &bazelLicenseKindAttributes{
+ Conditions: m.properties.Conditions,
+ Url: m.properties.Url,
+ Visibility: m.properties.Visibility,
+ }
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "license_kind",
+ Bzl_load_location: "@rules_license//rules:license_kind.bzl",
+ },
+ CommonAttributes{
+ Name: m.Name(),
+ },
+ attrs)
+}
+
func (m *licenseKindModule) DepsMutator(ctx BottomUpMutatorContext) {
// Nothing to do.
}
@@ -51,13 +79,14 @@
module := &licenseKindModule{}
base := module.base()
- module.AddProperties(&base.nameProperties, &module.properties)
+ module.AddProperties(&base.nameProperties, &module.properties, &base.commonProperties.BazelConversionStatus)
// The visibility property needs to be checked and parsed by the visibility module.
setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
initAndroidModuleBase(module)
InitDefaultableModule(module)
+ InitBazelModule(module)
return module
}
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/makevars.go b/android/makevars.go
index a74185a..5165a55 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 {
diff --git a/android/module.go b/android/module.go
index 5908233..5aecb05 100644
--- a/android/module.go
+++ b/android/module.go
@@ -915,8 +915,19 @@
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
}
// constraintAttributes represents Bazel attributes pertaining to build constraints,
@@ -1169,7 +1180,9 @@
mod := ctx.Module().base()
// Assert passed-in attributes include Name
if len(attrs.Name) == 0 {
- ctx.ModuleErrorf("CommonAttributes in fillCommonBp2BuildModuleAttrs expects a `.Name`!")
+ if ctx.ModuleType() != "package" {
+ ctx.ModuleErrorf("CommonAttributes in fillCommonBp2BuildModuleAttrs expects a `.Name`!")
+ }
}
depsToLabelList := func(deps []string) bazel.LabelListAttribute {
@@ -1227,22 +1240,21 @@
}
}
- required := depsToLabelList(mod.commonProperties.Required)
+ 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 {
- // TODO(b/234748998) Remove this requiredFiltered workaround when aapt2 converts successfully
- requiredFiltered := archProps.Required
- if attrs.Name == "apexer" {
- requiredFiltered = make([]string, 0, len(archProps.Required))
- for _, req := range archProps.Required {
- if req != "aapt2" && req != "apexer" {
- requiredFiltered = append(requiredFiltered, req)
- }
- }
- }
- required.SetSelectValue(axis, config, depsToLabelList(requiredFiltered).Value)
+ _, requiredWithoutCycles := RemoveFromList(ctx.ModuleName(), archProps.Required)
+ requiredWithoutCycles = FirstUniqueStrings(requiredWithoutCycles)
+ required.SetSelectValue(axis, config, depsToLabelList(requiredWithoutCycles).Value)
if !neitherHostNorDevice {
if archProps.Enabled != nil {
if axis != bazel.OsConfigurationAxis || osSupport[config] {
@@ -1302,7 +1314,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)
@@ -1520,7 +1537,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)
}
@@ -3543,10 +3560,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]
}
@@ -3558,18 +3594,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 fc7bc29..a3ff761 100644
--- a/android/namespace.go
+++ b/android/namespace.go
@@ -166,10 +166,10 @@
return namespace
}
-// A NamelessModule can never be looked up by name. It must still implement Name(), but the return
-// value doesn't have to be unique.
-type NamelessModule interface {
- Nameless()
+// A NamespacelessModule can never be looked up by name. It must still implement Name(), and the name
+// still has to be unique.
+type NamespacelessModule interface {
+ Namespaceless()
}
func (r *NameResolver) NewModule(ctx blueprint.NamespaceContext, moduleGroup blueprint.ModuleGroup, module blueprint.Module) (namespace blueprint.Namespace, errs []error) {
@@ -183,7 +183,7 @@
return nil, nil
}
- if _, ok := module.(NamelessModule); ok {
+ if _, ok := module.(NamespacelessModule); ok {
return nil, nil
}
diff --git a/android/neverallow.go b/android/neverallow.go
index 00078a0..1cdccc3 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -58,6 +58,7 @@
AddNeverAllowRules(createMakefileGoalRules()...)
AddNeverAllowRules(createInitFirstStageRules()...)
AddNeverAllowRules(createProhibitFrameworkAccessRules()...)
+ AddNeverAllowRules(createBp2BuildRule())
}
// Add a NeverAllow rule to the set of rules to apply.
@@ -65,6 +66,13 @@
neverallows = append(neverallows, rules...)
}
+func createBp2BuildRule() Rule {
+ return NeverAllow().
+ With("bazel_module.bp2build_available", "true").
+ Because("setting bp2build_available in Android.bp is not " +
+ "supported for custom conversion, use allowlists.go instead.")
+}
+
func createIncludeDirsRules() []Rule {
notInIncludeDir := []string{
"art",
diff --git a/android/package.go b/android/package.go
index 878e4c4..2bf6521 100644
--- a/android/package.go
+++ b/android/package.go
@@ -15,6 +15,7 @@
package android
import (
+ "android/soong/bazel"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -37,12 +38,33 @@
Default_applicable_licenses []string
}
+type bazelPackageAttributes struct {
+ Default_visibility []string
+ Default_applicable_licenses bazel.LabelListAttribute
+}
+
type packageModule struct {
ModuleBase
+ BazelModuleBase
properties packageProperties
}
+var _ Bazelable = &packageModule{}
+
+func (p *packageModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "package",
+ },
+ CommonAttributes{},
+ &bazelPackageAttributes{
+ Default_applicable_licenses: bazel.MakeLabelListAttribute(BazelLabelForModuleDeps(ctx, p.properties.Default_applicable_licenses)),
+ // FIXME(asmundak): once b/221436821 is resolved
+ Default_visibility: []string{"//visibility:public"},
+ })
+}
+
func (p *packageModule) GenerateAndroidBuildActions(ModuleContext) {
// Nothing to do.
}
@@ -59,7 +81,7 @@
func PackageFactory() Module {
module := &packageModule{}
- module.AddProperties(&module.properties)
+ module.AddProperties(&module.properties, &module.commonProperties.BazelConversionStatus)
// The name is the relative path from build root to the directory containing this
// module. Set that name at the earliest possible moment that information is available
@@ -76,5 +98,7 @@
// its checking and parsing phases so make it the primary licenses property.
setPrimaryLicensesProperty(module, "default_applicable_licenses", &module.properties.Default_applicable_licenses)
+ InitBazelModule(module)
+
return module
}
diff --git a/android/paths.go b/android/paths.go
index 27f4bf5..dbcdb23 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1638,6 +1638,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 8ad16a6..3cac9a1 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -15,9 +15,10 @@
package android
import (
- "android/soong/bazel"
"strings"
+ "android/soong/bazel"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -154,13 +155,22 @@
// Bp2buildProtoInfo contains information necessary to pass on to language specific conversion.
type Bp2buildProtoInfo struct {
- Type *string
- Name string
+ Type *string
+ Name string
+ Proto_libs bazel.LabelList
}
-type protoAttrs struct {
+type ProtoAttrs struct {
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
+// be added to the BUILD file in that package and a mapping should be added here
+var includeDirsToProtoDeps = map[string]string{
+ "external/protobuf/src": "//external/protobuf:libprotobuf-proto",
}
// Bp2buildProtoProperties converts proto properties, creating a proto_library and returning the
@@ -171,36 +181,71 @@
return info, false
}
- info.Name = m.Name() + "_proto"
- attrs := protoAttrs{
- Srcs: srcs,
- }
+ var protoLibraries bazel.LabelList
+ var directProtoSrcs bazel.LabelList
- for axis, configToProps := range m.GetArchVariantProperties(ctx, &ProtoProperties{}) {
- for _, rawProps := range configToProps {
- var props *ProtoProperties
- var ok bool
- if props, ok = rawProps.(*ProtoProperties); !ok {
- ctx.ModuleErrorf("Could not cast ProtoProperties to expected type")
- }
- if axis == bazel.NoConfigAxis {
- info.Type = props.Proto.Type
-
- if !proptools.BoolDefault(props.Proto.Canonical_path_from_root, canonicalPathFromRootDefault) {
- // an empty string indicates to strips the package path
- path := ""
- attrs.Strip_import_prefix = &path
- }
- } else if props.Proto.Type != info.Type && props.Proto.Type != nil {
- ctx.ModuleErrorf("Cannot handle arch-variant types for protos at this time.")
- }
+ // For filegroups that should be converted to proto_library just collect the
+ // labels of converted proto_library targets.
+ for _, protoSrc := range srcs.Value.Includes {
+ src := protoSrc.OriginalModuleName
+ if fg, ok := ToFileGroupAsLibrary(ctx, src); ok &&
+ fg.ShouldConvertToProtoLibrary(ctx) {
+ protoLibraries.Add(&bazel.Label{
+ Label: fg.GetProtoLibraryLabel(ctx),
+ })
+ } else {
+ directProtoSrcs.Add(&protoSrc)
}
}
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
- CommonAttributes{Name: info.Name},
- &attrs)
+ info.Name = m.Name() + "_proto"
+
+ if len(directProtoSrcs.Includes) > 0 {
+ attrs := ProtoAttrs{
+ Srcs: bazel.MakeLabelListAttribute(directProtoSrcs),
+ }
+ attrs.Deps.Append(bazel.MakeLabelListAttribute(protoLibraries))
+
+ for axis, configToProps := range m.GetArchVariantProperties(ctx, &ProtoProperties{}) {
+ for _, rawProps := range configToProps {
+ var props *ProtoProperties
+ var ok bool
+ if props, ok = rawProps.(*ProtoProperties); !ok {
+ ctx.ModuleErrorf("Could not cast ProtoProperties to expected type")
+ }
+ if axis == bazel.NoConfigAxis {
+ info.Type = props.Proto.Type
+
+ if !proptools.BoolDefault(props.Proto.Canonical_path_from_root, canonicalPathFromRootDefault) {
+ // an empty string indicates to strips the package path
+ path := ""
+ attrs.Strip_import_prefix = &path
+ }
+
+ for _, dir := range props.Proto.Include_dirs {
+ if dep, ok := includeDirsToProtoDeps[dir]; ok {
+ attrs.Deps.Add(bazel.MakeLabelAttribute(dep))
+ } else {
+ ctx.PropertyErrorf("Could not find the proto_library target for include dir", dir)
+ }
+ }
+ } else if props.Proto.Type != info.Type && props.Proto.Type != nil {
+ ctx.ModuleErrorf("Cannot handle arch-variant types for protos at this time.")
+ }
+ }
+ }
+
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
+ CommonAttributes{Name: info.Name},
+ &attrs)
+
+ protoLibraries.Add(&bazel.Label{
+ Label: ":" + info.Name,
+ })
+ }
+
+ info.Proto_libs = protoLibraries
return info, true
}
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/sdk.go b/android/sdk.go
index a477cba..bd2f5d1 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -74,6 +74,26 @@
sdkAwareWithoutModule
}
+// minApiLevelForSdkSnapshot provides access to the min_sdk_version for MinApiLevelForSdkSnapshot
+type minApiLevelForSdkSnapshot interface {
+ MinSdkVersion(ctx EarlyModuleContext) SdkSpec
+}
+
+// MinApiLevelForSdkSnapshot returns the ApiLevel of the min_sdk_version of the supplied module.
+//
+// If the module does not provide a min_sdk_version then it defaults to 1.
+func MinApiLevelForSdkSnapshot(ctx EarlyModuleContext, module Module) ApiLevel {
+ minApiLevel := NoneApiLevel
+ if m, ok := module.(minApiLevelForSdkSnapshot); ok {
+ minApiLevel = m.MinSdkVersion(ctx).ApiLevel
+ }
+ if minApiLevel == NoneApiLevel {
+ // The default min API level is 1.
+ minApiLevel = uncheckedFinalApiLevel(1)
+ }
+ return minApiLevel
+}
+
// SdkRef refers to a version of an SDK
type SdkRef struct {
Name string
@@ -715,8 +735,13 @@
// have common values. Those fields are cleared and the common value added to the common
// properties.
//
- // A field annotated with a tag of `sdk:"keep"` will be treated as if it
- // was not capitalized, i.e. not optimized for common values.
+ // A field annotated with a tag of `sdk:"ignore"` will be treated as if it
+ // was not capitalized, i.e. ignored and not optimized for common values.
+ //
+ // A field annotated with a tag of `sdk:"keep"` will not be cleared even if the value is common
+ // across multiple structs. Common values will still be copied into the common property struct.
+ // So, if the same value is placed in all structs populated from variants that value would be
+ // copied into all common property structs and so be available in every instance.
//
// A field annotated with a tag of `android:"arch_variant"` will be allowed to have
// values that differ by arch, fields not tagged as such must have common values across
@@ -903,18 +928,18 @@
// the locations of any of their prebuilt files in the snapshot by os type to prevent them
// from colliding. See OsPrefix().
//
- // This property is the same for all variants of a member and so would be optimized away
- // if it was not explicitly kept.
- Os_count int `sdk:"keep"`
+ // Ignore this property during optimization. This is needed because this property is the same for
+ // all variants of a member and so would be optimized away if it was not ignored.
+ Os_count int `sdk:"ignore"`
// The os type for which these properties refer.
//
// Provided to allow a member to differentiate between os types in the locations of their
// prebuilt files when it supports more than one os type.
//
- // This property is the same for all os type specific variants of a member and so would be
- // optimized away if it was not explicitly kept.
- Os OsType `sdk:"keep"`
+ // Ignore this property during optimization. This is needed because this property is the same for
+ // all variants of a member and so would be optimized away if it was not ignored.
+ Os OsType `sdk:"ignore"`
// The setting to use for the compile_multilib property.
Compile_multilib string `android:"arch_variant"`
diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go
index cd36ae0..c0f4523 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -172,7 +172,7 @@
"soong_config_module_type_import_" + fmt.Sprintf("%p", m)
}
-func (*soongConfigModuleTypeImport) Nameless() {}
+func (*soongConfigModuleTypeImport) Namespaceless() {}
func (*soongConfigModuleTypeImport) GenerateAndroidBuildActions(ModuleContext) {}
// Create dummy modules for soong_config_module_type and soong_config_*_variable
@@ -280,9 +280,9 @@
}
func (m *soongConfigModuleTypeModule) Name() string {
- return m.properties.Name
+ return m.properties.Name + fmt.Sprintf("%p", m)
}
-func (*soongConfigModuleTypeModule) Nameless() {}
+func (*soongConfigModuleTypeModule) Namespaceless() {}
func (*soongConfigModuleTypeModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
type soongConfigStringVariableDummyModule struct {
@@ -315,15 +315,15 @@
}
func (m *soongConfigStringVariableDummyModule) Name() string {
- return m.properties.Name
+ return m.properties.Name + fmt.Sprintf("%p", m)
}
-func (*soongConfigStringVariableDummyModule) Nameless() {}
+func (*soongConfigStringVariableDummyModule) Namespaceless() {}
func (*soongConfigStringVariableDummyModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
func (m *soongConfigBoolVariableDummyModule) Name() string {
- return m.properties.Name
+ return m.properties.Name + fmt.Sprintf("%p", m)
}
-func (*soongConfigBoolVariableDummyModule) Nameless() {}
+func (*soongConfigBoolVariableDummyModule) Namespaceless() {}
func (*soongConfigBoolVariableDummyModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
// importModuleTypes registers the module factories for a list of module types defined
diff --git a/android/test_config.go b/android/test_config.go
index 0f88d51..de546c4 100644
--- a/android/test_config.go
+++ b/android/test_config.go
@@ -91,6 +91,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 3708501..f9f9670 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -461,6 +461,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 +673,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
}
@@ -1037,7 +1083,7 @@
}
}
if !found {
- t.Errorf("missing the expected error %q (checked %d error(s))", pattern, len(errs))
+ t.Errorf("could not match the expected error regex %q (checked %d error(s))", pattern, len(errs))
for i, err := range errs {
t.Errorf("errs[%d] = %q", i, err)
}
diff --git a/android/variable.go b/android/variable.go
index 7a080fe..37ecab5 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -430,6 +430,8 @@
ShippingApiLevel *string `json:",omitempty"`
+ BuildBrokenClangAsFlags bool `json:",omitempty"`
+ BuildBrokenClangCFlags bool `json:",omitempty"`
BuildBrokenClangProperty bool `json:",omitempty"`
BuildBrokenDepfile *bool `json:",omitempty"`
BuildBrokenEnforceSyspropOwner bool `json:",omitempty"`
@@ -592,6 +594,9 @@
// "acme__board__soc_a", "acme__board__soc_b", and
// "acme__board__conditions_default"
FullConfig string
+
+ // keeps track of whether this product variable is nested under an arch variant
+ OuterAxis bazel.ConfigurationAxis
}
func (p *ProductConfigProperty) AlwaysEmit() bool {
@@ -600,11 +605,11 @@
func (p *ProductConfigProperty) ConfigurationAxis() bazel.ConfigurationAxis {
if p.Namespace == "" {
- return bazel.ProductVariableConfigurationAxis(p.FullConfig)
+ return bazel.ProductVariableConfigurationAxis(p.FullConfig, p.OuterAxis)
} else {
// Soong config variables can be uniquely identified by the namespace
// (e.g. acme, android) and the product variable name (e.g. board, size)
- return bazel.ProductVariableConfigurationAxis(p.Namespace + "__" + p.Name)
+ return bazel.ProductVariableConfigurationAxis(p.Namespace+"__"+p.Name, bazel.NoConfigAxis)
}
}
@@ -663,9 +668,11 @@
moduleBase.variableProperties,
"",
"",
- &productConfigProperties)
+ &productConfigProperties,
+ bazel.ConfigurationAxis{},
+ )
- for _, configToProps := range moduleBase.GetArchVariantProperties(ctx, moduleBase.variableProperties) {
+ for axis, configToProps := range moduleBase.GetArchVariantProperties(ctx, moduleBase.variableProperties) {
for config, props := range configToProps {
// GetArchVariantProperties is creating an instance of the requested type
// and productVariablesValues expects an interface, so no need to cast
@@ -674,7 +681,8 @@
props,
"",
config,
- &productConfigProperties)
+ &productConfigProperties,
+ axis)
}
}
}
@@ -687,7 +695,8 @@
namespacedVariableProp,
namespace,
"",
- &productConfigProperties)
+ &productConfigProperties,
+ bazel.NoConfigAxis)
}
}
}
@@ -803,6 +812,7 @@
p.Name,
p.FullConfig,
zeroValue,
+ bazel.NoConfigAxis,
)
}
}
@@ -810,7 +820,7 @@
}
func (p *ProductConfigProperties) AddProductConfigProperty(
- propertyName, namespace, productVariableName, config string, property interface{}) {
+ propertyName, namespace, productVariableName, config string, property interface{}, outerAxis bazel.ConfigurationAxis) {
if (*p)[propertyName] == nil {
(*p)[propertyName] = make(map[ProductConfigProperty]interface{})
}
@@ -819,6 +829,7 @@
Namespace: namespace, // e.g. acme, android
Name: productVariableName, // e.g. size, feature1, feature2, FEATURE3, board
FullConfig: config, // e.g. size, feature1-x86, size__conditions_default
+ OuterAxis: outerAxis,
}
if existing, ok := (*p)[propertyName][productConfigProp]; ok && namespace != "" {
@@ -869,7 +880,7 @@
return v, true
}
-func (productConfigProperties *ProductConfigProperties) AddProductConfigProperties(namespace, suffix string, variableValues reflect.Value) {
+func (productConfigProperties *ProductConfigProperties) AddProductConfigProperties(namespace, suffix string, variableValues reflect.Value, outerAxis bazel.ConfigurationAxis) {
// variableValues can either be a product_variables or
// soong_config_variables struct.
//
@@ -974,7 +985,8 @@
namespace, // e.g. acme, android
productVariableName, // e.g. size, feature1, FEATURE2, board
config,
- field.Field(k).Interface(), // e.g. ["-DDEFAULT"], ["foo", "bar"]
+ field.Field(k).Interface(), // e.g. ["-DDEFAULT"], ["foo", "bar"],
+ outerAxis,
)
}
} else if property.Kind() != reflect.Interface {
@@ -988,6 +1000,7 @@
productVariableName,
config,
property.Interface(),
+ outerAxis,
)
}
}
@@ -998,14 +1011,14 @@
// product_variables and soong_config_variables to structs that can be generated
// as select statements.
func productVariableValues(
- fieldName string, variableProps interface{}, namespace, suffix string, productConfigProperties *ProductConfigProperties) {
+ fieldName string, variableProps interface{}, namespace, suffix string, productConfigProperties *ProductConfigProperties, outerAxis bazel.ConfigurationAxis) {
if suffix != "" {
suffix = "-" + suffix
}
// variableValues represent the product_variables or soong_config_variables struct.
variableValues := reflect.ValueOf(variableProps).Elem().FieldByName(fieldName)
- productConfigProperties.AddProductConfigProperties(namespace, suffix, variableValues)
+ productConfigProperties.AddProductConfigProperties(namespace, suffix, variableValues, outerAxis)
}
func VariableMutator(mctx BottomUpMutatorContext) {
diff --git a/apex/apex.go b/apex/apex.go
index 949809a..88a057f 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -286,6 +286,9 @@
Arm64 struct {
ApexNativeDependencies
}
+ Riscv64 struct {
+ ApexNativeDependencies
+ }
X86 struct {
ApexNativeDependencies
}
@@ -787,6 +790,8 @@
depsList = append(depsList, a.archProperties.Arch.Arm.ApexNativeDependencies)
case android.Arm64:
depsList = append(depsList, a.archProperties.Arch.Arm64.ApexNativeDependencies)
+ case android.Riscv64:
+ depsList = append(depsList, a.archProperties.Arch.Riscv64.ApexNativeDependencies)
case android.X86:
depsList = append(depsList, a.archProperties.Arch.X86.ApexNativeDependencies)
case android.X86_64:
@@ -1559,7 +1564,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 +1575,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 +1588,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 +1607,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)
}
@@ -2659,9 +2664,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 +2736,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
@@ -3054,36 +3066,6 @@
//
// Module separator
//
- m["com.android.bluetooth"] = []string{
- "bluetooth-protos-lite",
- "internal_include_headers",
- "libaudio-a2dp-hw-utils",
- "libaudio-hearing-aid-hw-utils",
- "libbluetooth",
- "libbluetooth-types",
- "libbluetooth-types-header",
- "libbluetooth_gd",
- "libbluetooth_headers",
- "libbluetooth_jni",
- "libbt-audio-hal-interface",
- "libbt-bta",
- "libbt-common",
- "libbt-hci",
- "libbt-platform-protos-lite",
- "libbt-protos-lite",
- "libbt-sbc-decoder",
- "libbt-sbc-encoder",
- "libbt-stack",
- "libbt-utils",
- "libbtcore",
- "libbtdevice",
- "libbte",
- "libbtif",
- "libchrome",
- }
- //
- // Module separator
- //
m["com.android.cellbroadcast"] = []string{"CellBroadcastApp", "CellBroadcastServiceModule"}
//
// Module separator
@@ -3365,7 +3347,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
@@ -3427,16 +3410,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()
}
@@ -3486,7 +3472,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,
diff --git a/apex/apex_test.go b/apex/apex_test.go
index d6803f6..2e116c7 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -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 {
@@ -7235,12 +7337,18 @@
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")
+ cmd := generateFsRule.RuleParams.Command
+ ensureContains(t, cmd, "AppSet.zip")
}
func TestAppSetBundlePrebuilt(t *testing.T) {
@@ -7271,6 +7379,28 @@
android.AssertStringEquals(t, "myapex input", extractorOutput, copiedApex.Input.String())
}
+func TestApexSetApksModuleAssignment(t *testing.T) {
+ ctx := testApex(t, `
+ apex_set {
+ name: "myapex",
+ set: ":myapex_apks_file",
+ }
+
+ filegroup {
+ name: "myapex_apks_file",
+ srcs: ["myapex.apks"],
+ }
+ `)
+
+ m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
+
+ // Check that the extractor produces the correct apks file from the input module
+ extractorOutput := "out/soong/.intermediates/myapex.apex.extractor/android_common/extracted/myapex.apks"
+ extractedApex := m.Output(extractorOutput)
+
+ android.AssertArrayString(t, "extractor input", []string{"myapex.apks"}, extractedApex.Inputs.Strings())
+}
+
func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer android.FixturePreparer, fragments ...java.ApexVariantReference) {
t.Helper()
@@ -8843,19 +8973,7 @@
android.FixtureWithRootAndroidBp(bp),
dexpreopt.FixtureSetApexBootJars("myapex:mybootclasspathlib"),
dexpreopt.FixtureSetApexSystemServerJars("myapex:mysystemserverclasspathlib"),
- android.FixtureMergeEnv(map[string]string{
- "EMMA_INSTRUMENT": "true",
- }),
- // need to mock jacocoagent here to satisfy dependency added for
- // instrumented libraries at build time
- android.FixtureAddFile("jacocoagent/Android.bp", []byte(`
- java_library {
- name: "jacocoagent",
- srcs: ["Test.java"],
- system_modules: "none",
- sdk_version: "none",
- }
- `)),
+ java.PrepareForTestWithJacocoInstrumentation,
).RunTest(t)
// Make sure jacoco ran on both mylib and mybootclasspathlib
diff --git a/apex/builder.go b/apex/builder.go
index b95b3bd..e4c1673 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)
}
@@ -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,8 +1096,11 @@
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.builtFile
+ appSetFiles[f.installDir] = f.module.(*java.AndroidAppSet).PackedAdditionalOutputs()
} else {
readOnlyPaths = append(readOnlyPaths, pathInApex)
}
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 172a201..70308c8 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -500,6 +500,9 @@
Arm64 struct {
Src *string `android:"path"`
}
+ Riscv64 struct {
+ Src *string `android:"path"`
+ }
X86 struct {
Src *string `android:"path"`
}
@@ -527,6 +530,8 @@
src = String(p.Arch.Arm.Src)
case android.Arm64:
src = String(p.Arch.Arm64.Src)
+ case android.Riscv64:
+ src = String(p.Arch.Riscv64.Src)
case android.X86:
src = String(p.Arch.X86.Src)
case android.X86_64:
@@ -537,7 +542,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.
}
@@ -840,17 +849,17 @@
type ApexExtractorProperties struct {
// the .apks file path that contains prebuilt apex files to be extracted.
- Set *string
+ Set *string `android:"path"`
Sanitized struct {
None struct {
- Set *string
+ Set *string `android:"path"`
}
Address struct {
- Set *string
+ Set *string `android:"path"`
}
Hwaddress struct {
- Set *string
+ Set *string `android:"path"`
}
}
diff --git a/bazel/configurability.go b/bazel/configurability.go
index e1cdd4a..a93aa00 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"
@@ -69,6 +71,9 @@
AndroidAndInApex = "android-in_apex"
AndroidAndNonApex = "android-non_apex"
+
+ InApex = "in_apex"
+ NonApex = "non_apex"
)
func PowerSetWithoutEmptySet[T any](items []T) [][]T {
@@ -96,6 +101,7 @@
"arm64": {
"dotprod",
},
+ "riscv64": {},
"x86": {
"ssse3",
"sse4",
@@ -161,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",
@@ -184,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},
@@ -198,6 +205,12 @@
AndroidAndNonApex: "//build/bazel/rules/apex:android-non_apex",
ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
}
+
+ inApexMap = map[string]string{
+ InApex: "//build/bazel/rules/apex:in_apex",
+ NonApex: "//build/bazel/rules/apex:non_apex",
+ ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
+ }
)
// basic configuration types
@@ -210,6 +223,7 @@
osArch
productVariables
osAndInApex
+ inApex
)
func osArchString(os string, arch string) string {
@@ -224,6 +238,7 @@
osArch: "arch_os",
productVariables: "product_variables",
osAndInApex: "os_in_apex",
+ inApex: "in_apex",
}[ct]
}
@@ -251,6 +266,10 @@
if _, ok := osAndInApexMap[config]; !ok {
panic(fmt.Errorf("Unknown os+in_apex config: %s", config))
}
+ case inApex:
+ if _, ok := inApexMap[config]; !ok {
+ panic(fmt.Errorf("Unknown in_apex config: %s", config))
+ }
default:
panic(fmt.Errorf("Unrecognized ConfigurationType %d", ct))
}
@@ -276,6 +295,8 @@
return fmt.Sprintf("%s:%s", productVariableBazelPackage, config)
case osAndInApex:
return osAndInApexMap[config]
+ case inApex:
+ return inApexMap[config]
default:
panic(fmt.Errorf("Unrecognized ConfigurationType %d", ca.configurationType))
}
@@ -292,13 +313,16 @@
OsArchConfigurationAxis = ConfigurationAxis{configurationType: osArch}
// An axis for os+in_apex-specific configurations
OsAndInApexAxis = ConfigurationAxis{configurationType: osAndInApex}
+ // An axis for in_apex-specific configurations
+ InApexAxis = ConfigurationAxis{configurationType: inApex}
)
// ProductVariableConfigurationAxis returns an axis for the given product variable
-func ProductVariableConfigurationAxis(variable string) ConfigurationAxis {
+func ProductVariableConfigurationAxis(variable string, outerAxis ConfigurationAxis) ConfigurationAxis {
return ConfigurationAxis{
configurationType: productVariables,
subType: variable,
+ outerAxisType: outerAxis.configurationType,
}
}
@@ -309,6 +333,8 @@
// some configuration types (e.g. productVariables) have multiple independent axes, subType helps
// distinguish between them without needing to list all 17 product variables.
subType string
+ // used to keep track of which product variables are arch variant
+ outerAxisType configurationType
}
func (ca *ConfigurationAxis) less(other ConfigurationAxis) bool {
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index 5cee6ac..fa73fb2 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 {
@@ -30,6 +31,7 @@
// but general cc_library will also have dynamic libraries in output files).
RootDynamicLibraries []string
TocFile string
+ UnstrippedOutput string
}
type getOutputFilesRequestType struct{}
@@ -135,12 +137,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]
path = shared_info.output_file.path
sharedLibraries.append(path)
rootSharedLibraries += [path]
+ unstripped = path
+ if unstripped_tag in providers(target):
+ unstripped = providers(target)[unstripped_tag].unstripped.path
else:
for linker_input in linker_inputs:
for library in linker_input.libraries:
@@ -158,63 +165,29 @@
# NOTE: It's OK if there's no ToC, as Soong just uses it for optimization
pass
-returns = [
- outputFiles,
- ccObjectFiles,
- sharedLibraries,
- staticLibraries,
- includes,
- system_includes,
- headers,
- rootStaticArchives,
- rootSharedLibraries,
- [toc_file]
-]
+return json_encode({
+ "OutputFiles": outputFiles,
+ "CcObjectFiles": ccObjectFiles,
+ "CcSharedLibraryFiles": sharedLibraries,
+ "CcStaticLibraryFiles": staticLibraries,
+ "Includes": includes,
+ "SystemIncludes": system_includes,
+ "Headers": headers,
+ "RootStaticArchives": rootStaticArchives,
+ "RootDynamicLibraries": rootSharedLibraries,
+ "TocFile": toc_file,
+ "UnstrippedOutput": unstripped,
+})`
-return "|".join([", ".join(r) for r in returns])`
}
// 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 getCcInfoType) ParseResult(rawString string) (CcInfo, error) {
- const expectedLen = 10
- splitString := strings.Split(rawString, "|")
- if len(splitString) != expectedLen {
- return CcInfo{}, fmt.Errorf("expected %d items, got %q", expectedLen, splitString)
- }
- outputFilesString := splitString[0]
- ccObjectsString := splitString[1]
- ccSharedLibrariesString := splitString[2]
- ccStaticLibrariesString := splitString[3]
- includesString := splitString[4]
- systemIncludesString := splitString[5]
- headersString := splitString[6]
- rootStaticArchivesString := splitString[7]
- rootDynamicLibrariesString := splitString[8]
- tocFile := splitString[9] // NOTE: Will be the empty string if there wasn't
-
- outputFiles := splitOrEmpty(outputFilesString, ", ")
- ccObjects := splitOrEmpty(ccObjectsString, ", ")
- ccSharedLibraries := splitOrEmpty(ccSharedLibrariesString, ", ")
- ccStaticLibraries := splitOrEmpty(ccStaticLibrariesString, ", ")
- includes := splitOrEmpty(includesString, ", ")
- systemIncludes := splitOrEmpty(systemIncludesString, ", ")
- headers := splitOrEmpty(headersString, ", ")
- rootStaticArchives := splitOrEmpty(rootStaticArchivesString, ", ")
- rootDynamicLibraries := splitOrEmpty(rootDynamicLibrariesString, ", ")
- return CcInfo{
- OutputFiles: outputFiles,
- CcObjectFiles: ccObjects,
- CcSharedLibraryFiles: ccSharedLibraries,
- CcStaticLibraryFiles: ccStaticLibraries,
- Includes: includes,
- SystemIncludes: systemIncludes,
- Headers: headers,
- RootStaticArchives: rootStaticArchives,
- RootDynamicLibraries: rootDynamicLibraries,
- TocFile: tocFile,
- }, nil
+ var ccInfo CcInfo
+ parseJson(rawString, &ccInfo)
+ return ccInfo, nil
}
// Query Bazel for the artifacts generated by the apex modules.
@@ -235,14 +208,14 @@
// - 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 "{%s}" % ",".join([
- json_for_file("signed_output", info.signed_output),
- json_for_file("unsigned_output", info.unsigned_output),
- json_for_labels("provides_native_libs", info.provides_native_libs),
- json_for_labels("requires_native_libs", info.requires_native_libs),
- json_for_files("bundle_key_pair", info.bundle_key_pair),
- json_for_files("container_key_pair", info.container_key_pair)
- ])`
+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]
+})`
}
type ApexCqueryInfo struct {
@@ -259,12 +232,47 @@
// Starlark given in StarlarkFunctionBody.
func (g getApexInfoType) ParseResult(rawString string) ApexCqueryInfo {
var info ApexCqueryInfo
- if err := json.Unmarshal([]byte(rawString), &info); err != nil {
- panic(fmt.Errorf("cannot parse cquery result '%s': %s", rawString, err))
- }
+ parseJson(rawString, &info)
return info
}
+// 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 {
+ var info CcUnstrippedInfo
+ parseJson(rawString, &info)
+ return info
+}
+
+type CcUnstrippedInfo struct {
+ OutputFile string
+ UnstrippedOutput string
+}
+
// splitOrEmpty is a modification of strings.Split() that returns an empty list
// if the given string is empty.
func splitOrEmpty(s string, sep string) []string {
@@ -274,3 +282,13 @@
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{}) {
+ decoder := json.NewDecoder(strings.NewReader(jsonString))
+ 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", jsonString, err))
+ }
+}
diff --git a/bazel/cquery/request_type_test.go b/bazel/cquery/request_type_test.go
index 34248ce..0f51cc0 100644
--- a/bazel/cquery/request_type_test.go
+++ b/bazel/cquery/request_type_test.go
@@ -1,9 +1,8 @@
package cquery
import (
- "fmt"
+ "encoding/json"
"reflect"
- "strings"
"testing"
)
@@ -63,74 +62,48 @@
}
func TestGetCcInfoParseResults(t *testing.T) {
- const expectedSplits = 10
- noResult := strings.Repeat("|", expectedSplits-1)
testCases := []struct {
- description string
- input string
- expectedOutput CcInfo
- expectedErrorMessage string
+ description string
+ inputCcInfo CcInfo
+ expectedOutput CcInfo
}{
{
- description: "no result",
- input: noResult,
- expectedOutput: CcInfo{
- OutputFiles: []string{},
- CcObjectFiles: []string{},
- CcSharedLibraryFiles: []string{},
- CcStaticLibraryFiles: []string{},
- Includes: []string{},
- SystemIncludes: []string{},
- Headers: []string{},
- RootStaticArchives: []string{},
- RootDynamicLibraries: []string{},
- TocFile: "",
- },
+ description: "no result",
+ inputCcInfo: CcInfo{},
+ expectedOutput: CcInfo{},
},
{
description: "only output",
- input: "test" + noResult,
+ inputCcInfo: CcInfo{
+ OutputFiles: []string{"test", "test3"},
+ },
expectedOutput: CcInfo{
- OutputFiles: []string{"test"},
- CcObjectFiles: []string{},
- CcSharedLibraryFiles: []string{},
- CcStaticLibraryFiles: []string{},
- Includes: []string{},
- SystemIncludes: []string{},
- Headers: []string{},
- RootStaticArchives: []string{},
- RootDynamicLibraries: []string{},
- TocFile: "",
+ OutputFiles: []string{"test", "test3"},
},
},
{
description: "only ToC",
- input: noResult + "test",
+ inputCcInfo: CcInfo{
+ TocFile: "test",
+ },
expectedOutput: CcInfo{
- OutputFiles: []string{},
- CcObjectFiles: []string{},
- CcSharedLibraryFiles: []string{},
- CcStaticLibraryFiles: []string{},
- Includes: []string{},
- SystemIncludes: []string{},
- Headers: []string{},
- RootStaticArchives: []string{},
- RootDynamicLibraries: []string{},
- TocFile: "test",
+ TocFile: "test",
},
},
{
description: "all items set",
- input: "out1, out2" +
- "|object1, object2" +
- "|shared_lib1, shared_lib2" +
- "|static_lib1, static_lib2" +
- "|., dir/subdir" +
- "|system/dir, system/other/dir" +
- "|dir/subdir/hdr.h" +
- "|rootstaticarchive1" +
- "|rootdynamiclibrary1" +
- "|lib.so.toc",
+ inputCcInfo: CcInfo{
+ OutputFiles: []string{"out1", "out2"},
+ CcObjectFiles: []string{"object1", "object2"},
+ CcSharedLibraryFiles: []string{"shared_lib1", "shared_lib2"},
+ CcStaticLibraryFiles: []string{"static_lib1", "static_lib2"},
+ Includes: []string{".", "dir/subdir"},
+ SystemIncludes: []string{"system/dir", "system/other/dir"},
+ Headers: []string{"dir/subdir/hdr.h"},
+ RootStaticArchives: []string{"rootstaticarchive1"},
+ RootDynamicLibraries: []string{"rootdynamiclibrary1"},
+ TocFile: "lib.so.toc",
+ },
expectedOutput: CcInfo{
OutputFiles: []string{"out1", "out2"},
CcObjectFiles: []string{"object1", "object2"},
@@ -144,24 +117,12 @@
TocFile: "lib.so.toc",
},
},
- {
- description: "too few result splits",
- input: "|",
- expectedOutput: CcInfo{},
- expectedErrorMessage: fmt.Sprintf("expected %d items, got %q", expectedSplits, []string{"", ""}),
- },
- {
- description: "too many result splits",
- input: strings.Repeat("|", expectedSplits+1), // 2 too many
- expectedOutput: CcInfo{},
- expectedErrorMessage: fmt.Sprintf("expected %d items, got %q", expectedSplits, make([]string, expectedSplits+2)),
- },
}
for _, tc := range testCases {
- actualOutput, err := GetCcInfo.ParseResult(tc.input)
- if (err == nil && tc.expectedErrorMessage != "") ||
- (err != nil && err.Error() != tc.expectedErrorMessage) {
- t.Errorf("%q:\nexpected Error %s\n, got %s", tc.description, tc.expectedErrorMessage, err)
+ 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)
}
@@ -204,3 +165,31 @@
}
}
}
+
+func TestGetCcUnstrippedParseResults(t *testing.T) {
+ 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 {
+ actualOutput := GetCcUnstrippedInfo.ParseResult(tc.input)
+ if !reflect.DeepEqual(tc.expectedOutput, actualOutput) {
+ t.Errorf("%q: expected %#v != actual %#v", tc.description, tc.expectedOutput, actualOutput)
+ }
+ }
+}
diff --git a/bazel/properties.go b/bazel/properties.go
index d82fa64..823cda8 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
@@ -309,7 +320,19 @@
_, containsProductVariables := axisTypes[productVariables]
if containsProductVariables {
if containsOs || containsArch || containsOsArch {
- return fmt.Errorf("label attribute could not be collapsed as it has two or more unrelated axes")
+ if containsArch {
+ allProductVariablesAreArchVariant := true
+ for k := range la.ConfigurableValues {
+ if k.configurationType == productVariables && k.outerAxisType != arch {
+ allProductVariablesAreArchVariant = false
+ }
+ }
+ if !allProductVariablesAreArchVariant {
+ return fmt.Errorf("label attribute could not be collapsed as it has two or more unrelated axes")
+ }
+ } else {
+ return fmt.Errorf("label attribute could not be collapsed as it has two or more unrelated axes")
+ }
}
}
if (containsOs && containsArch) || (containsOsArch && (containsOs || containsArch)) {
@@ -708,7 +731,7 @@
switch axis.configurationType {
case noConfig:
lla.Value = list
- case arch, os, osArch, productVariables, osAndInApex:
+ case arch, os, osArch, productVariables, osAndInApex, inApex:
if lla.ConfigurableValues == nil {
lla.ConfigurableValues = make(configurableLabelLists)
}
@@ -724,7 +747,7 @@
switch axis.configurationType {
case noConfig:
return lla.Value
- case arch, os, osArch, productVariables, osAndInApex:
+ case arch, os, osArch, productVariables, osAndInApex, inApex:
return lla.ConfigurableValues[axis][config]
default:
panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
@@ -1166,6 +1189,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/bazel/properties_test.go b/bazel/properties_test.go
index dc4d5b0..8729381 100644
--- a/bazel/properties_test.go
+++ b/bazel/properties_test.go
@@ -247,13 +247,13 @@
OsArchConfigurationAxis: labelListSelectValues{
"linux_x86": makeLabelList([]string{"linux_x86_include"}, []string{}),
},
- ProductVariableConfigurationAxis("product_with_defaults"): labelListSelectValues{
+ ProductVariableConfigurationAxis("product_with_defaults", NoConfigAxis): labelListSelectValues{
"a": makeLabelList([]string{}, []string{"not_in_value"}),
"b": makeLabelList([]string{"b_val"}, []string{}),
"c": makeLabelList([]string{"c_val"}, []string{}),
ConditionsDefaultConfigKey: makeLabelList([]string{"c_val", "default", "default2"}, []string{}),
},
- ProductVariableConfigurationAxis("product_only_with_excludes"): labelListSelectValues{
+ ProductVariableConfigurationAxis("product_only_with_excludes", NoConfigAxis): labelListSelectValues{
"a": makeLabelList([]string{}, []string{"not_in_value"}),
},
},
@@ -281,7 +281,7 @@
"linux_x86": makeLabels("linux_x86_include"),
ConditionsDefaultConfigKey: nilLabels,
},
- ProductVariableConfigurationAxis("product_with_defaults"): {
+ ProductVariableConfigurationAxis("product_with_defaults", NoConfigAxis): {
"a": nilLabels,
"b": makeLabels("b_val"),
"c": makeLabels("c_val"),
@@ -674,7 +674,7 @@
OsArchConfigurationAxis: stringListSelectValues{
"linux_x86": {"linux_x86_include"},
},
- ProductVariableConfigurationAxis("a"): stringListSelectValues{
+ ProductVariableConfigurationAxis("a", NoConfigAxis): stringListSelectValues{
"a": []string{"not_in_value"},
},
},
@@ -699,7 +699,7 @@
"linux": []string{"linux_include"},
},
OsArchConfigurationAxis: stringListSelectValues{},
- ProductVariableConfigurationAxis("a"): stringListSelectValues{
+ ProductVariableConfigurationAxis("a", NoConfigAxis): stringListSelectValues{
"a": []string{"not_in_value"},
},
}
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 3d9fc5a..7c9af1a 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -63,8 +63,11 @@
"java_library_host_conversion_test.go",
"java_plugin_conversion_test.go",
"java_proto_conversion_test.go",
+ "license_conversion_test.go",
+ "license_kind_conversion_test.go",
"linker_config_conversion_test.go",
"ndk_headers_conversion_test.go",
+ "package_conversion_test.go",
"performance_test.go",
"prebuilt_etc_conversion_test.go",
"python_binary_conversion_test.go",
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/androidbp_to_build_templates.go b/bp2build/androidbp_to_build_templates.go
index 5fed4fa..9b21c32 100644
--- a/bp2build/androidbp_to_build_templates.go
+++ b/bp2build/androidbp_to_build_templates.go
@@ -23,7 +23,7 @@
// A macro call in the BUILD file representing a Soong module, with space
// for expanding more attributes.
- soongModuleTarget = `soong_module(
+ soongModuleTargetTemplate = `soong_module(
name = "%s",
soong_module_name = "%s",
soong_module_type = "%s",
@@ -31,10 +31,13 @@
soong_module_deps = %s,
%s)`
- bazelTarget = `%s(
+ ruleTargetTemplate = `%s(
name = "%s",
%s)`
+ unnamedRuleTargetTemplate = `%s(
+%s)`
+
// A simple provider to mark and differentiate Soong module rule shims from
// regular Bazel rules. Every Soong module rule shim returns a
// SoongModuleInfo provider, and can only depend on rules returning
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
index b0a2966..a666e49 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"
)
@@ -120,7 +121,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 +154,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 +281,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 +314,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 +393,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 +425,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 +449,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 +560,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 +618,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 +654,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 +672,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 +1059,193 @@
}),
}})
}
+
+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"`,
+ }),
+ }})
+}
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
new file mode 100644
index 0000000..224008f
--- /dev/null
+++ b/bp2build/api_domain_conversion_test.go
@@ -0,0 +1,68 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bp2build
+
+import (
+ "testing"
+
+ "android/soong/android"
+ "android/soong/cc"
+)
+
+func registerApiDomainModuleTypes(ctx android.RegistrationContext) {
+ android.RegisterApiDomainBuildComponents(ctx)
+ cc.RegisterNdkModuleTypes(ctx)
+ cc.RegisterLibraryBuildComponents(ctx)
+}
+
+func TestApiDomainContributionsTest(t *testing.T) {
+ bp := `
+ api_domain {
+ name: "system",
+ cc_api_contributions: [
+ "libfoo.ndk",
+ "libbar",
+ ],
+ }
+ `
+ fs := map[string]string{
+ "libfoo/Android.bp": `
+ ndk_library {
+ name: "libfoo",
+ }
+ `,
+ "libbar/Android.bp": `
+ cc_library {
+ name: "libbar",
+ }
+ `,
+ }
+ expectedBazelTarget := MakeBazelTargetNoRestrictions(
+ "api_domain",
+ "system",
+ AttrNameToString{
+ "cc_api_contributions": `[
+ "//libfoo:libfoo.ndk.contribution",
+ "//libbar:libbar.contribution",
+ ]`,
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ },
+ )
+ RunApiBp2BuildTestCase(t, registerApiDomainModuleTypes, Bp2buildTestCase{
+ Blueprint: bp,
+ ExpectedBazelTargets: []string{expectedBazelTarget},
+ Filesystem: fs,
+ })
+}
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 cf46533..82ce115 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -64,7 +64,16 @@
// BazelTargets is a typedef for a slice of BazelTarget objects.
type BazelTargets []BazelTarget
-// sort a list of BazelTargets in-place by name
+func (targets BazelTargets) packageRule() *BazelTarget {
+ for _, target := range targets {
+ if target.ruleClass == "package" {
+ return &target
+ }
+ }
+ return nil
+}
+
+// sort a list of BazelTargets in-place, by name, and by generated/handcrafted types.
func (targets BazelTargets) sort() {
sort.Slice(targets, func(i, j int) bool {
return targets[i].name < targets[j].name
@@ -77,7 +86,9 @@
func (targets BazelTargets) String() string {
var res string
for i, target := range targets {
- res += target.content
+ if target.ruleClass != "package" {
+ res += target.content
+ }
if i != len(targets)-1 {
res += "\n\n"
}
@@ -152,6 +163,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
@@ -170,6 +184,8 @@
return "Bp2Build"
case QueryView:
return "QueryView"
+ case ApiBp2build:
+ return "ApiBp2build"
default:
return fmt.Sprintf("%d", mode)
}
@@ -231,6 +247,7 @@
// 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),
}
@@ -261,20 +278,21 @@
// target in a BUILD file, we don't autoconvert them.
// Log the module.
- metrics.AddConvertedModule(m, moduleType, Handcrafted)
+ metrics.AddConvertedModule(m, moduleType, dir, Handcrafted)
} else if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() {
// Handle modules converted to generated targets.
// Log the module.
- metrics.AddConvertedModule(aModule, moduleType, Generated)
+ metrics.AddConvertedModule(aModule, moduleType, dir, Generated)
// Handle modules with unconverted deps. By default, emit a warning.
if unconvertedDeps := aModule.GetUnconvertedBp2buildDeps(); len(unconvertedDeps) > 0 {
msg := fmt.Sprintf("%s %s:%s depends on unconverted modules: %s",
moduleType, bpCtx.ModuleDir(m), m.Name(), strings.Join(unconvertedDeps, ", "))
- if ctx.unconvertedDepMode == warnUnconvertedDeps {
+ switch ctx.unconvertedDepMode {
+ case warnUnconvertedDeps:
metrics.moduleWithUnconvertedDepsMsgs = append(metrics.moduleWithUnconvertedDepsMsgs, msg)
- } else if ctx.unconvertedDepMode == errorModulesUnconvertedDeps {
+ case errorModulesUnconvertedDeps:
errs = append(errs, fmt.Errorf(msg))
return
}
@@ -282,14 +300,17 @@
if unconvertedDeps := aModule.GetMissingBp2buildDeps(); len(unconvertedDeps) > 0 {
msg := fmt.Sprintf("%s %s:%s depends on missing modules: %s",
moduleType, bpCtx.ModuleDir(m), m.Name(), strings.Join(unconvertedDeps, ", "))
- if ctx.unconvertedDepMode == warnUnconvertedDeps {
+ switch ctx.unconvertedDepMode {
+ case warnUnconvertedDeps:
metrics.moduleWithMissingDepsMsgs = append(metrics.moduleWithMissingDepsMsgs, msg)
- } else if ctx.unconvertedDepMode == errorModulesUnconvertedDeps {
+ case errorModulesUnconvertedDeps:
errs = append(errs, fmt.Errorf(msg))
return
}
}
- targets = generateBazelTargets(bpCtx, aModule)
+ var targetErrs []error
+ targets, targetErrs = generateBazelTargets(bpCtx, aModule)
+ errs = append(errs, targetErrs...)
for _, t := range targets {
// A module can potentially generate more than 1 Bazel
// target, each of a different rule class.
@@ -306,8 +327,15 @@
// be mapped cleanly to a bazel label.
return
}
- t := generateSoongModuleTarget(bpCtx, m)
+ t, err := generateSoongModuleTarget(bpCtx, m)
+ if err != nil {
+ 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
@@ -332,7 +360,7 @@
// TODO(b/198619163): We should change this to export_files(glob(["**/*"])) instead, but doing that causes these errors:
// "Error in exports_files: generated label '//external/avb:avbtool' conflicts with existing py_binary rule"
// So we need to solve all the "target ... is both a rule and a file" warnings first.
- for dir, _ := range dirs {
+ for dir := range dirs {
buildFileToTargets[dir] = append(buildFileToTargets[dir], BazelTarget{
name: "bp2build_all_srcs",
content: `filegroup(name = "bp2build_all_srcs", srcs = glob(["**/*"]))`,
@@ -347,12 +375,18 @@
}, errs
}
-func generateBazelTargets(ctx bpToBuildContext, m android.Module) []BazelTarget {
+func generateBazelTargets(ctx bpToBuildContext, m android.Module) ([]BazelTarget, []error) {
var targets []BazelTarget
+ var errs []error
for _, m := range m.Bp2buildTargets() {
- targets = append(targets, generateBazelTarget(ctx, m))
+ target, err := generateBazelTarget(ctx, m)
+ if err != nil {
+ errs = append(errs, err)
+ return targets, errs
+ }
+ targets = append(targets, target)
}
- return targets
+ return targets, errs
}
type bp2buildModule interface {
@@ -363,13 +397,16 @@
BazelAttributes() []interface{}
}
-func generateBazelTarget(ctx bpToBuildContext, m bp2buildModule) BazelTarget {
+func generateBazelTarget(ctx bpToBuildContext, m bp2buildModule) (BazelTarget, error) {
ruleClass := m.BazelRuleClass()
bzlLoadLocation := m.BazelRuleLoadLocation()
// extract the bazel attributes from the module.
attrs := m.BazelAttributes()
- props := extractModuleProperties(attrs, true)
+ props, err := extractModuleProperties(attrs, true)
+ if err != nil {
+ return BazelTarget{}, err
+ }
// name is handled in a special manner
delete(props.Attrs, "name")
@@ -377,25 +414,26 @@
// Return the Bazel target with rule class and attributes, ready to be
// code-generated.
attributes := propsToAttributes(props.Attrs)
+ var content string
targetName := m.TargetName()
+ if targetName != "" {
+ content = fmt.Sprintf(ruleTargetTemplate, ruleClass, targetName, attributes)
+ } else {
+ content = fmt.Sprintf(unnamedRuleTargetTemplate, ruleClass, attributes)
+ }
return BazelTarget{
name: targetName,
packageName: m.TargetPackage(),
ruleClass: ruleClass,
bzlLoadLocation: bzlLoadLocation,
- content: fmt.Sprintf(
- bazelTarget,
- ruleClass,
- targetName,
- attributes,
- ),
- }
+ content: content,
+ }, nil
}
// Convert a module and its deps and props into a Bazel macro/rule
// representation in the BUILD file.
-func generateSoongModuleTarget(ctx bpToBuildContext, m blueprint.Module) BazelTarget {
- props := getBuildProperties(ctx, m)
+func generateSoongModuleTarget(ctx bpToBuildContext, m blueprint.Module) (BazelTarget, error) {
+ props, err := getBuildProperties(ctx, m)
// TODO(b/163018919): DirectDeps can have duplicate (module, variant)
// items, if the modules are added using different DependencyTag. Figure
@@ -422,28 +460,28 @@
return BazelTarget{
name: targetName,
content: fmt.Sprintf(
- soongModuleTarget,
+ soongModuleTargetTemplate,
targetName,
ctx.ModuleName(m),
canonicalizeModuleType(ctx.ModuleType(m)),
ctx.ModuleSubDir(m),
depLabelList,
attributes),
- }
+ }, err
}
-func getBuildProperties(ctx bpToBuildContext, m blueprint.Module) BazelAttributes {
+func getBuildProperties(ctx bpToBuildContext, m blueprint.Module) (BazelAttributes, error) {
// TODO: this omits properties for blueprint modules (blueprint_go_binary,
// bootstrap_go_binary, bootstrap_go_package), which will have to be handled separately.
if aModule, ok := m.(android.Module); ok {
return extractModuleProperties(aModule.GetProperties(), false)
}
- return BazelAttributes{}
+ return BazelAttributes{}, nil
}
// Generically extract module properties and types into a map, keyed by the module property name.
-func extractModuleProperties(props []interface{}, checkForDuplicateProperties bool) BazelAttributes {
+func extractModuleProperties(props []interface{}, checkForDuplicateProperties bool) (BazelAttributes, error) {
ret := map[string]string{}
// Iterate over this android.Module's property structs.
@@ -456,24 +494,29 @@
// manipulate internal props, if needed.
if isStructPtr(propertiesValue.Type()) {
structValue := propertiesValue.Elem()
- for k, v := range extractStructProperties(structValue, 0) {
+ ok, err := extractStructProperties(structValue, 0)
+ if err != nil {
+ return BazelAttributes{}, err
+ }
+ for k, v := range ok {
if existing, exists := ret[k]; checkForDuplicateProperties && exists {
- panic(fmt.Errorf(
+ return BazelAttributes{}, fmt.Errorf(
"%s (%v) is present in properties whereas it should be consolidated into a commonAttributes",
- k, existing))
+ k, existing)
}
ret[k] = v
}
} else {
- panic(fmt.Errorf(
- "properties must be a pointer to a struct, got %T",
- propertiesValue.Interface()))
+ return BazelAttributes{},
+ fmt.Errorf(
+ "properties must be a pointer to a struct, got %T",
+ propertiesValue.Interface())
}
}
return BazelAttributes{
Attrs: ret,
- }
+ }, nil
}
func isStructPtr(t reflect.Type) bool {
@@ -531,7 +574,12 @@
}
// Sort and print the struct props by the key.
- structProps := extractStructProperties(propertyValue, indent)
+ structProps, err := extractStructProperties(propertyValue, indent)
+
+ if err != nil {
+ return "", err
+ }
+
if len(structProps) == 0 {
return "", nil
}
@@ -550,11 +598,13 @@
// which each property value correctly pretty-printed and indented at the right nest level,
// since property structs can be nested. In Starlark, nested structs are represented as nested
// dicts: https://docs.bazel.build/skylark/lib/dict.html
-func extractStructProperties(structValue reflect.Value, indent int) map[string]string {
+func extractStructProperties(structValue reflect.Value, indent int) (map[string]string, error) {
if structValue.Kind() != reflect.Struct {
- panic(fmt.Errorf("Expected a reflect.Struct type, but got %s", structValue.Kind()))
+ return map[string]string{}, fmt.Errorf("Expected a reflect.Struct type, but got %s", structValue.Kind())
}
+ var err error
+
ret := map[string]string{}
structType := structValue.Type()
for i := 0; i < structValue.NumField(); i++ {
@@ -575,7 +625,10 @@
fieldValue = fieldValue.Elem()
}
if fieldValue.Type().Kind() == reflect.Struct {
- propsToMerge := extractStructProperties(fieldValue, indent)
+ propsToMerge, err := extractStructProperties(fieldValue, indent)
+ if err != nil {
+ return map[string]string{}, err
+ }
for prop, value := range propsToMerge {
ret[prop] = value
}
@@ -584,20 +637,20 @@
}
propertyName := proptools.PropertyNameForField(field.Name)
- prettyPrintedValue, err := prettyPrint(fieldValue, indent+1, false)
+ var prettyPrintedValue string
+ prettyPrintedValue, err = prettyPrint(fieldValue, indent+1, false)
if err != nil {
- panic(
- fmt.Errorf(
- "Error while parsing property: %q. %s",
- propertyName,
- err))
+ return map[string]string{}, fmt.Errorf(
+ "Error while parsing property: %q. %s",
+ propertyName,
+ err)
}
if prettyPrintedValue != "" {
ret[propertyName] = prettyPrintedValue
}
}
- return ret
+ return ret, nil
}
func isZero(value reflect.Value) bool {
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index dd28c3c..7c24a94 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -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",
@@ -971,6 +976,24 @@
},
},
{
+ Description: "filegroup with dot-slash-prefixed srcs",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ Blueprint: `filegroup {
+ name: "fg_foo",
+ srcs: ["./a", "./b"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a",
+ "b",
+ ]`,
+ }),
+ },
+ },
+ {
Description: "filegroup with excludes srcs",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
@@ -987,57 +1010,6 @@
},
},
{
- Description: "filegroup with glob",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: `filegroup {
- name: "fg_foo",
- srcs: ["**/*.txt"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "other/a.txt",
- "other/b.txt",
- "other/subdir/a.txt",
- ]`,
- }),
- },
- Filesystem: map[string]string{
- "other/a.txt": "",
- "other/b.txt": "",
- "other/subdir/a.txt": "",
- "other/file": "",
- },
- },
- {
- Description: "filegroup with glob in subdir",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Dir: "other",
- Filesystem: map[string]string{
- "other/Android.bp": `filegroup {
- name: "fg_foo",
- srcs: ["**/*.txt"],
- bazel_module: { bp2build_available: true },
-}`,
- "other/a.txt": "",
- "other/b.txt": "",
- "other/subdir/a.txt": "",
- "other/file": "",
- },
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "a.txt",
- "b.txt",
- "subdir/a.txt",
- ]`,
- }),
- },
- },
- {
Description: "depends_on_other_dir_module",
ModuleTypeUnderTest: "filegroup",
ModuleTypeUnderTestFactory: android.FileGroupFactory,
@@ -1086,6 +1058,29 @@
}`,
},
},
+ {
+ Description: "depends_on_other_missing_module_error",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ UnconvertedDepsMode: errorModulesUnconvertedDeps,
+ Blueprint: `filegroup {
+ name: "foobar",
+ srcs: [
+ "c",
+ "//other:foo",
+ "//other:goo",
+ ],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedErr: fmt.Errorf(`filegroup .:foobar depends on missing modules: //other:goo`),
+ Filesystem: map[string]string{"other/Android.bp": `filegroup {
+ name: "foo",
+ srcs: ["a"],
+ bazel_module: { bp2build_available: true },
+}
+`,
+ },
+ },
}
for _, testCase := range testCases {
@@ -1095,8 +1090,6 @@
}
}
-type bp2buildMutator = func(android.TopDownMutatorContext)
-
func TestAllowlistingBp2buildTargetsExplicitly(t *testing.T) {
testCases := []struct {
moduleTypeUnderTest string
@@ -1429,6 +1422,226 @@
}
}
+func TestGlob(t *testing.T) {
+ testCases := []Bp2buildTestCase{
+ {
+ Description: "filegroup with glob",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ Blueprint: `filegroup {
+ name: "fg_foo",
+ srcs: ["**/*.txt"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "other/a.txt",
+ "other/b.txt",
+ "other/subdir/a.txt",
+ ]`,
+ }),
+ },
+ Filesystem: map[string]string{
+ "other/a.txt": "",
+ "other/b.txt": "",
+ "other/subdir/a.txt": "",
+ "other/file": "",
+ },
+ },
+ {
+ Description: "filegroup with glob in subdir",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ Dir: "other",
+ Filesystem: map[string]string{
+ "other/Android.bp": `filegroup {
+ name: "fg_foo",
+ srcs: ["**/*.txt"],
+ bazel_module: { bp2build_available: true },
+}`,
+ "other/a.txt": "",
+ "other/b.txt": "",
+ "other/subdir/a.txt": "",
+ "other/file": "",
+ },
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a.txt",
+ "b.txt",
+ "subdir/a.txt",
+ ]`,
+ }),
+ },
+ },
+ {
+ Description: "filegroup with glob with no kept BUILD files",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ KeepBuildFileForDirs: []string{
+ // empty
+ },
+ Blueprint: `filegroup {
+ name: "fg_foo",
+ srcs: ["**/*.txt"],
+ bazel_module: { bp2build_available: true },
+}`,
+ Filesystem: map[string]string{
+ "a.txt": "",
+ "b.txt": "",
+ "foo/BUILD": "",
+ "foo/a.txt": "",
+ "foo/bar/BUILD": "",
+ "foo/bar/b.txt": "",
+ },
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a.txt",
+ "b.txt",
+ "foo/a.txt",
+ "foo/bar/b.txt",
+ ]`,
+ }),
+ },
+ },
+ {
+ Description: "filegroup with glob with kept BUILD file",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ KeepBuildFileForDirs: []string{
+ "foo",
+ },
+ Blueprint: `filegroup {
+ name: "fg_foo",
+ srcs: ["**/*.txt"],
+ bazel_module: { bp2build_available: true },
+}`,
+ Filesystem: map[string]string{
+ "a.txt": "",
+ "b.txt": "",
+ "foo/BUILD": "",
+ "foo/a.txt": "",
+ "foo/bar/BUILD": "",
+ "foo/bar/b.txt": "",
+ },
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a.txt",
+ "b.txt",
+ "//foo:a.txt",
+ "//foo:bar/b.txt",
+ ]`,
+ }),
+ },
+ },
+ {
+ Description: "filegroup with glob with kept BUILD.bazel file",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ KeepBuildFileForDirs: []string{
+ "foo",
+ },
+ Blueprint: `filegroup {
+ name: "fg_foo",
+ srcs: ["**/*.txt"],
+ bazel_module: { bp2build_available: true },
+}`,
+ Filesystem: map[string]string{
+ "a.txt": "",
+ "b.txt": "",
+ "foo/BUILD.bazel": "",
+ "foo/a.txt": "",
+ "foo/bar/BUILD.bazel": "",
+ "foo/bar/b.txt": "",
+ },
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a.txt",
+ "b.txt",
+ "//foo:a.txt",
+ "//foo:bar/b.txt",
+ ]`,
+ }),
+ },
+ },
+ {
+ Description: "filegroup with glob with Android.bp file as boundary",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ Blueprint: `filegroup {
+ name: "fg_foo",
+ srcs: ["**/*.txt"],
+ bazel_module: { bp2build_available: true },
+}`,
+ Filesystem: map[string]string{
+ "a.txt": "",
+ "b.txt": "",
+ "foo/Android.bp": "",
+ "foo/a.txt": "",
+ "foo/bar/Android.bp": "",
+ "foo/bar/b.txt": "",
+ },
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a.txt",
+ "b.txt",
+ "//foo:a.txt",
+ "//foo/bar:b.txt",
+ ]`,
+ }),
+ },
+ },
+ {
+ Description: "filegroup with glob in subdir with kept BUILD and BUILD.bazel file",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ Dir: "other",
+ KeepBuildFileForDirs: []string{
+ "other/foo",
+ "other/foo/bar",
+ // deliberately not other/foo/baz/BUILD.
+ },
+ Filesystem: map[string]string{
+ "other/Android.bp": `filegroup {
+ name: "fg_foo",
+ srcs: ["**/*.txt"],
+ bazel_module: { bp2build_available: true },
+}`,
+ "other/a.txt": "",
+ "other/b.txt": "",
+ "other/foo/BUILD": "",
+ "other/foo/a.txt": "",
+ "other/foo/bar/BUILD.bazel": "",
+ "other/foo/bar/b.txt": "",
+ "other/foo/baz/BUILD": "",
+ "other/foo/baz/c.txt": "",
+ },
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "srcs": `[
+ "a.txt",
+ "b.txt",
+ "//other/foo:a.txt",
+ "//other/foo/bar:b.txt",
+ "//other/foo:baz/c.txt",
+ ]`,
+ }),
+ },
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.Description, func(t *testing.T) {
+ RunBp2BuildTestCaseSimple(t, testCase)
+ })
+ }
+}
+
func TestGlobExcludeSrcs(t *testing.T) {
testCases := []Bp2buildTestCase{
{
@@ -1518,6 +1731,22 @@
},
},
{
+ Description: "Required into data test, cyclic self reference is filtered out",
+ ModuleTypeUnderTest: "filegroup",
+ ModuleTypeUnderTestFactory: android.FileGroupFactory,
+ Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + `
+filegroup {
+ name: "fg_foo",
+ required: ["reqd", "fg_foo"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
+ "data": `[":reqd"]`,
+ }),
+ },
+ },
+ {
Description: "Required via arch into data test",
ModuleTypeUnderTest: "python_library",
ModuleTypeUnderTestFactory: python.PythonLibraryFactory,
@@ -1597,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 67d4a1c..8aa2c3e 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -45,6 +45,7 @@
type ccBinaryBp2buildTestCase struct {
description string
+ filesystem map[string]string
blueprint string
targets []testBazelTarget
}
@@ -79,6 +80,7 @@
ModuleTypeUnderTestFactory: cc.BinaryFactory,
Description: description,
Blueprint: binaryReplacer.Replace(testCase.blueprint),
+ Filesystem: testCase.filesystem,
})
})
}
@@ -94,6 +96,7 @@
ModuleTypeUnderTestFactory: cc.BinaryHostFactory,
Description: description,
Blueprint: hostBinaryReplacer.Replace(testCase.blueprint),
+ Filesystem: testCase.filesystem,
})
})
}
@@ -101,6 +104,9 @@
func TestBasicCcBinary(t *testing.T) {
runCcBinaryTests(t, ccBinaryBp2buildTestCase{
description: "basic -- properties -> attrs with little/no transformation",
+ filesystem: map[string]string{
+ soongCcVersionLibBpPath: soongCcVersionLibBp,
+ },
blueprint: `
{rule_name} {
name: "foo",
@@ -146,9 +152,10 @@
"keep_symbols_list": ["symbol"],
"none": True,
}`,
- "sdk_version": `"current"`,
- "min_sdk_version": `"29"`,
- "use_version_lib": `True`,
+ "sdk_version": `"current"`,
+ "min_sdk_version": `"29"`,
+ "use_version_lib": `True`,
+ "whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
},
},
},
@@ -194,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",
@@ -669,3 +715,77 @@
},
})
}
+
+func TestCcBinaryWithSyspropSrcs(t *testing.T) {
+ runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
+ description: "cc_binary with sysprop sources",
+ blueprint: `
+{rule_name} {
+ name: "foo",
+ srcs: [
+ "bar.sysprop",
+ "baz.sysprop",
+ "blah.cpp",
+ ],
+ min_sdk_version: "5",
+}`,
+ targets: []testBazelTarget{
+ {"sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `[
+ "bar.sysprop",
+ "baz.sysprop",
+ ]`,
+ }},
+ {"cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }},
+ {"cc_binary", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`,
+ }},
+ },
+ })
+}
+
+func TestCcBinaryWithSyspropSrcsSomeConfigs(t *testing.T) {
+ runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
+ description: "cc_binary with sysprop sources in some configs but not others",
+ blueprint: `
+{rule_name} {
+ name: "foo",
+ srcs: [
+ "blah.cpp",
+ ],
+ target: {
+ android: {
+ srcs: ["bar.sysprop"],
+ },
+ },
+ min_sdk_version: "5",
+}`,
+ targets: []testBazelTarget{
+ {"sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `select({
+ "//build/bazel/platforms/os:android": ["bar.sysprop"],
+ "//conditions:default": [],
+ })`,
+ }},
+ {"cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }},
+ {"cc_binary", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `select({
+ "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"],
+ "//conditions:default": [],
+ })`,
+ }},
+ },
+ })
+}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 5117c62..0d6d5b8 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -27,7 +27,16 @@
soongCcLibraryPreamble = `
cc_defaults {
name: "linux_bionic_supported",
-}`
+}
+`
+
+ soongCcVersionLibBpPath = "build/soong/cc/libbuildversion/Android.bp"
+ soongCcVersionLibBp = `
+cc_library_static {
+ name: "libbuildversion",
+ bazel_module: { bp2build_available: false },
+}
+`
soongCcProtoLibraries = `
cc_library {
@@ -62,9 +71,10 @@
ModuleTypeUnderTest: "cc_library",
ModuleTypeUnderTestFactory: cc.LibraryFactory,
Filesystem: map[string]string{
- "android.cpp": "",
- "bionic.cpp": "",
- "darwin.cpp": "",
+ soongCcVersionLibBpPath: soongCcVersionLibBp,
+ "android.cpp": "",
+ "bionic.cpp": "",
+ "darwin.cpp": "",
// Refer to cc.headerExts for the supported header extensions in Soong.
"header.h": "",
"header.hh": "",
@@ -143,9 +153,10 @@
"//build/bazel/platforms/os:linux_bionic": ["bionic.cpp"],
"//conditions:default": [],
})`,
- "sdk_version": `"current"`,
- "min_sdk_version": `"29"`,
- "use_version_lib": `True`,
+ "sdk_version": `"current"`,
+ "min_sdk_version": `"29"`,
+ "use_version_lib": `True`,
+ "implementation_whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
}),
})
}
@@ -859,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",
@@ -871,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,
}
@@ -878,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",
@@ -900,9 +918,11 @@
arch: {
arm: {
version_script: "arm.map",
+ dynamic_list: "dynamic_arm.list",
},
arm64: {
version_script: "arm64.map",
+ dynamic_list: "dynamic_arm64.list",
},
},
@@ -914,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"]`,
@@ -929,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",
@@ -1337,6 +1409,7 @@
"strip": true,
"inject_bssl_hash": true,
"has_stubs": true,
+ "use_version_lib": true,
}
sharedAttrs := AttrNameToString{}
@@ -1355,26 +1428,6 @@
return []string{staticTarget, sharedTarget}
}
-func makeCcStubSuiteTargets(name string, attrs AttrNameToString) string {
- if _, hasStubs := attrs["stubs_symbol_file"]; !hasStubs {
- return ""
- }
- STUB_SUITE_ATTRS := map[string]string{
- "stubs_symbol_file": "symbol_file",
- "stubs_versions": "versions",
- "soname": "soname",
- "source_library": "source_library",
- }
-
- stubSuiteAttrs := AttrNameToString{}
- for key, _ := range attrs {
- if _, stubSuiteAttr := STUB_SUITE_ATTRS[key]; stubSuiteAttr {
- stubSuiteAttrs[STUB_SUITE_ATTRS[key]] = attrs[key]
- }
- }
- return MakeBazelTarget("cc_stub_suite", name+"_stub_libs", stubSuiteAttrs)
-}
-
func TestCCLibraryNoLibCrtFalse(t *testing.T) {
runCcLibraryTestCase(t, Bp2buildTestCase{
ModuleTypeUnderTest: "cc_library",
@@ -2078,7 +2131,8 @@
"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
"deps": `[":libprotobuf-cpp-lite"]`,
}), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
}),
},
})
@@ -2104,7 +2158,8 @@
"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
"deps": `[":libprotobuf-cpp-lite"]`,
}), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
}),
},
})
@@ -2129,7 +2184,8 @@
"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
"deps": `[":libprotobuf-cpp-lite"]`,
}), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
}),
},
})
@@ -2156,7 +2212,8 @@
"implementation_whole_archive_deps": `[":foo_cc_proto"]`,
"deps": `[":libprotobuf-cpp-full"]`,
}), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-full"]`,
+ "dynamic_deps": `[":libprotobuf-cpp-full"]`,
+ "implementation_whole_archive_deps": `[":foo_cc_proto"]`,
}),
},
})
@@ -2183,7 +2240,8 @@
"implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
"deps": `[":libprotobuf-cpp-lite"]`,
}), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
}),
},
})
@@ -2217,6 +2275,179 @@
})
}
+func TestCcLibraryProtoIncludeDirs(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: soongCcProtoPreamble + `cc_library {
+ name: "foo",
+ srcs: ["foo.proto"],
+ proto: {
+ include_dirs: ["external/protobuf/src"],
+ },
+ include_build_directory: false,
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
+ "srcs": `["foo.proto"]`,
+ "deps": `["//external/protobuf:libprotobuf-proto"]`,
+ }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
+ "deps": `[":foo_proto"]`,
+ }), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "deps": `[":libprotobuf-cpp-lite"]`,
+ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
+ }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryProtoIncludeDirsUnknown(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: soongCcProtoPreamble + `cc_library {
+ name: "foo",
+ srcs: ["foo.proto"],
+ proto: {
+ include_dirs: ["external/protobuf/abc"],
+ },
+ include_build_directory: false,
+}`,
+ ExpectedErr: fmt.Errorf("module \"foo\": Could not find the proto_library target for include dir: external/protobuf/abc"),
+ })
+}
+
+func TestCcLibraryConvertedProtoFilegroups(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: soongCcProtoPreamble + `
+filegroup {
+ name: "a_fg_proto",
+ srcs: ["a_fg.proto"],
+}
+
+cc_library {
+ name: "a",
+ srcs: [
+ ":a_fg_proto",
+ "a.proto",
+ ],
+ proto: {
+ export_proto_headers: true,
+ },
+ include_build_directory: false,
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("proto_library", "a_proto", AttrNameToString{
+ "deps": `[":a_fg_proto_bp2build_converted"]`,
+ "srcs": `["a.proto"]`,
+ }), MakeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", AttrNameToString{
+ "deps": `[
+ ":a_fg_proto_bp2build_converted",
+ ":a_proto",
+ ]`,
+ }), MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
+ "deps": `[":libprotobuf-cpp-lite"]`,
+ "whole_archive_deps": `[":a_cc_proto_lite"]`,
+ }), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
+ "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ "whole_archive_deps": `[":a_cc_proto_lite"]`,
+ }), MakeBazelTargetNoRestrictions("proto_library", "a_fg_proto_bp2build_converted", AttrNameToString{
+ "srcs": `["a_fg.proto"]`,
+ "tags": `["manual"]`,
+ }), MakeBazelTargetNoRestrictions("filegroup", "a_fg_proto", AttrNameToString{
+ "srcs": `["a_fg.proto"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryConvertedProtoFilegroupsNoProtoFiles(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: soongCcProtoPreamble + `
+filegroup {
+ name: "a_fg_proto",
+ srcs: ["a_fg.proto"],
+}
+
+cc_library {
+ name: "a",
+ srcs: [
+ ":a_fg_proto",
+ ],
+ proto: {
+ export_proto_headers: true,
+ },
+ include_build_directory: false,
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", AttrNameToString{
+ "deps": `[":a_fg_proto_bp2build_converted"]`,
+ }), MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
+ "deps": `[":libprotobuf-cpp-lite"]`,
+ "whole_archive_deps": `[":a_cc_proto_lite"]`,
+ }), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
+ "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ "whole_archive_deps": `[":a_cc_proto_lite"]`,
+ }), MakeBazelTargetNoRestrictions("proto_library", "a_fg_proto_bp2build_converted", AttrNameToString{
+ "srcs": `["a_fg.proto"]`,
+ "tags": `["manual"]`,
+ }), MakeBazelTargetNoRestrictions("filegroup", "a_fg_proto", AttrNameToString{
+ "srcs": `["a_fg.proto"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryExternalConvertedProtoFilegroups(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Filesystem: map[string]string{
+ "path/to/A/Android.bp": `
+filegroup {
+ name: "a_fg_proto",
+ srcs: ["a_fg.proto"],
+}`,
+ },
+ Blueprint: soongCcProtoPreamble + `
+cc_library {
+ name: "a",
+ srcs: [
+ ":a_fg_proto",
+ "a.proto",
+ ],
+ proto: {
+ export_proto_headers: true,
+ },
+ include_build_directory: false,
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("proto_library", "a_proto", AttrNameToString{
+ "deps": `["//path/to/A:a_fg_proto_bp2build_converted"]`,
+ "srcs": `["a.proto"]`,
+ }), MakeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", AttrNameToString{
+ "deps": `[
+ "//path/to/A:a_fg_proto_bp2build_converted",
+ ":a_proto",
+ ]`,
+ }), MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
+ "deps": `[":libprotobuf-cpp-lite"]`,
+ "whole_archive_deps": `[":a_cc_proto_lite"]`,
+ }), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
+ "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
+ "whole_archive_deps": `[":a_cc_proto_lite"]`,
+ }),
+ },
+ })
+}
+
func TestCcLibraryProtoFilegroups(t *testing.T) {
runCcLibraryTestCase(t, Bp2buildTestCase{
ModuleTypeUnderTest: "cc_library",
@@ -2512,6 +2743,239 @@
)
}
+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",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Filesystem: map[string]string{
+ "bar.map.txt": "",
+ },
+ Blueprint: `
+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"],
+ target: {
+ android: {
+ shared_libs: ["barlib"],
+ },
+ },
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: makeCcLibraryTargets("foolib", AttrNameToString{
+ "implementation_dynamic_deps": `select({
+ "//build/bazel/rules/apex:android-in_apex": [":barlib_stub_libs_current"],
+ "//conditions:default": [":barlib"],
+ })`,
+ "local_includes": `["."]`,
+ }),
+ })
+}
+
func TestCcLibraryEscapeLdflags(t *testing.T) {
runCcLibraryTestCase(t, Bp2buildTestCase{
ModuleTypeUnderTest: "cc_library",
@@ -2745,12 +3209,12 @@
]`,
}),
MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "whole_archive_deps": `[":foo_cc_aidl_library"]`,
- "local_includes": `["."]`,
+ "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
+ "local_includes": `["."]`,
}),
MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "whole_archive_deps": `[":foo_cc_aidl_library"]`,
- "local_includes": `["."]`,
+ "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
+ "local_includes": `["."]`,
}),
},
})
@@ -2764,23 +3228,57 @@
Filesystem: map[string]string{
"path/to/A/Android.bp": `
filegroup {
- name: "A_aidl",
- srcs: ["aidl/A.aidl"],
- path: "aidl",
+ name: "A_aidl",
+ srcs: ["aidl/A.aidl"],
+ path: "aidl",
}`,
},
Blueprint: `
cc_library {
- name: "foo",
- srcs: [
- ":A_aidl",
- ],
+ name: "foo",
+ srcs: [
+ ":A_aidl",
+ ],
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
"deps": `["//path/to/A:A_aidl"]`,
}),
MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
+ "local_includes": `["."]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "local_includes": `["."]`,
+ "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryWithExportAidlHeaders(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library with export aidl headers",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library {
+ name: "foo",
+ srcs: [
+ "Foo.aidl",
+ ],
+ aidl: {
+ export_aidl_headers: true,
+ }
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
+ "srcs": `["Foo.aidl"]`,
+ }),
+ MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
+ "deps": `[":foo_aidl_library"]`,
+ }),
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
"whole_archive_deps": `[":foo_cc_aidl_library"]`,
"local_includes": `["."]`,
}),
@@ -2791,3 +3289,222 @@
},
})
}
+
+func TestCcLibraryWithTargetApex(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library with target.apex",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library {
+ name: "foo",
+ shared_libs: ["bar", "baz"],
+ static_libs: ["baz", "buh"],
+ target: {
+ apex: {
+ exclude_shared_libs: ["bar"],
+ exclude_static_libs: ["buh"],
+ }
+ }
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "implementation_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
+ "//build/bazel/rules/apex:non_apex": [":buh__BP2BUILD__MISSING__DEP"],
+ "//conditions:default": [],
+ })`,
+ "implementation_dynamic_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
+ "//build/bazel/rules/apex:non_apex": [":bar__BP2BUILD__MISSING__DEP"],
+ "//conditions:default": [],
+ })`,
+ "local_includes": `["."]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "implementation_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
+ "//build/bazel/rules/apex:non_apex": [":buh__BP2BUILD__MISSING__DEP"],
+ "//conditions:default": [],
+ })`,
+ "implementation_dynamic_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
+ "//build/bazel/rules/apex:non_apex": [":bar__BP2BUILD__MISSING__DEP"],
+ "//conditions:default": [],
+ })`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryWithTargetApexAndExportLibHeaders(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library with target.apex and export_shared|static_lib_headers",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ shared_libs: ["bar", "baz"],
+ static_libs: ["abc"],
+ export_shared_lib_headers: ["baz"],
+ export_static_lib_headers: ["abc"],
+ target: {
+ apex: {
+ exclude_shared_libs: ["baz", "bar"],
+ exclude_static_libs: ["abc"],
+ }
+ }
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "implementation_dynamic_deps": `select({
+ "//build/bazel/rules/apex:non_apex": [":bar__BP2BUILD__MISSING__DEP"],
+ "//conditions:default": [],
+ })`,
+ "dynamic_deps": `select({
+ "//build/bazel/rules/apex:non_apex": [":baz__BP2BUILD__MISSING__DEP"],
+ "//conditions:default": [],
+ })`,
+ "deps": `select({
+ "//build/bazel/rules/apex:non_apex": [":abc__BP2BUILD__MISSING__DEP"],
+ "//conditions:default": [],
+ })`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryWithSyspropSrcs(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library with sysprop sources",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library {
+ name: "foo",
+ srcs: [
+ "bar.sysprop",
+ "baz.sysprop",
+ "blah.cpp",
+ ],
+ min_sdk_version: "5",
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `[
+ "bar.sysprop",
+ "baz.sysprop",
+ ]`,
+ }),
+ MakeBazelTarget("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }),
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryWithSyspropSrcsSomeConfigs(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library with sysprop sources in some configs but not others",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library {
+ name: "foo",
+ host_supported: true,
+ srcs: [
+ "blah.cpp",
+ ],
+ target: {
+ android: {
+ srcs: ["bar.sysprop"],
+ },
+ },
+ min_sdk_version: "5",
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `select({
+ "//build/bazel/platforms/os:android": ["bar.sysprop"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTargetNoRestrictions("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }),
+ MakeBazelTargetNoRestrictions("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `select({
+ "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTargetNoRestrictions("cc_library_shared", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `select({
+ "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryWithAidlAndSharedLibs(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_aidl_library depends on shared libs from parent cc_library_static",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ srcs: [
+ "Foo.aidl",
+ ],
+ shared_libs: [
+ "bar",
+ "baz",
+ ],
+ export_shared_lib_headers: [
+ "baz",
+ ],
+}` +
+ simpleModuleDoNotConvertBp2build("cc_library", "bar") +
+ simpleModuleDoNotConvertBp2build("cc_library", "baz"),
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
+ "srcs": `["Foo.aidl"]`,
+ }),
+ MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
+ "deps": `[":foo_aidl_library"]`,
+ "implementation_dynamic_deps": `[
+ ":baz",
+ ":bar",
+ ]`,
+ }),
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
+ "dynamic_deps": `[":baz"]`,
+ "implementation_dynamic_deps": `[":bar"]`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
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 4d8e59b..b86f607 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)",
+ ]`,
}),
},
})
@@ -454,6 +498,9 @@
func TestCcLibrarySharedUseVersionLib(t *testing.T) {
runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Filesystem: map[string]string{
+ soongCcVersionLibBpPath: soongCcVersionLibBp,
+ },
Blueprint: soongCcProtoPreamble + `cc_library_shared {
name: "foo",
use_version_lib: true,
@@ -461,7 +508,8 @@
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "use_version_lib": "True",
+ "use_version_lib": "True",
+ "implementation_whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
}),
},
})
@@ -484,12 +532,21 @@
`,
},
Blueprint: soongCcLibraryPreamble,
- ExpectedBazelTargets: []string{MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
- "has_stubs": `True`,
+ ExpectedBazelTargets: []string{makeCcStubSuiteTargets("a", AttrNameToString{
+ "soname": `"a.so"`,
+ "source_library": `":a"`,
+ "stubs_symbol_file": `"a.map.txt"`,
+ "stubs_versions": `[
+ "28",
+ "29",
+ "current",
+ ]`,
}),
+ MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
+ "has_stubs": `True`,
+ }),
},
- },
- )
+ })
}
func TestCcLibrarySharedSystemSharedLibsSharedEmpty(t *testing.T) {
@@ -714,3 +771,77 @@
},
})
}
+
+func TestCcLibrarySharedWithSyspropSrcs(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_shared with sysprop sources",
+ Blueprint: `
+cc_library_shared {
+ name: "foo",
+ srcs: [
+ "bar.sysprop",
+ "baz.sysprop",
+ "blah.cpp",
+ ],
+ min_sdk_version: "5",
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `[
+ "bar.sysprop",
+ "baz.sysprop",
+ ]`,
+ }),
+ MakeBazelTarget("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibrarySharedWithSyspropSrcsSomeConfigs(t *testing.T) {
+ runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_shared with sysprop sources in some configs but not others",
+ Blueprint: `
+cc_library_shared {
+ name: "foo",
+ srcs: [
+ "blah.cpp",
+ ],
+ target: {
+ android: {
+ srcs: ["bar.sysprop"],
+ },
+ },
+ min_sdk_version: "5",
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `select({
+ "//build/bazel/platforms/os:android": ["bar.sysprop"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTarget("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `select({
+ "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 0637ba2..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",
],
@@ -1392,6 +1412,16 @@
Description: "cc_library_static system_shared_lib empty for linux_bionic variant",
Blueprint: soongCcLibraryStaticPreamble +
simpleModuleDoNotConvertBp2build("cc_library", "libc") + `
+
+cc_library {
+ name: "libm",
+ stubs: {
+ symbol_file: "libm.map.txt",
+ versions: ["current"],
+ },
+ bazel_module: { bp2build_available: false },
+}
+
cc_library_static {
name: "used_in_bionic_oses",
target: {
@@ -1414,7 +1444,20 @@
cc_library_static {
name: "keep_for_empty_system_shared_libs",
shared_libs: ["libc"],
- system_shared_libs: [],
+ system_shared_libs: [],
+ include_build_directory: false,
+}
+
+cc_library_static {
+ name: "used_with_stubs",
+ shared_libs: ["libm"],
+ include_build_directory: false,
+}
+
+cc_library_static {
+ name: "keep_with_stubs",
+ shared_libs: ["libm"],
+ system_shared_libs: [],
include_build_directory: false,
}
`,
@@ -1424,7 +1467,15 @@
"implementation_dynamic_deps": `[":libc"]`,
"system_dynamic_deps": `[]`,
}),
+ MakeBazelTarget("cc_library_static", "keep_with_stubs", AttrNameToString{
+ "implementation_dynamic_deps": `select({
+ "//build/bazel/rules/apex:android-in_apex": [":libm_stub_libs_current"],
+ "//conditions:default": [":libm"],
+ })`,
+ "system_dynamic_deps": `[]`,
+ }),
MakeBazelTarget("cc_library_static", "used_in_bionic_oses", AttrNameToString{}),
+ MakeBazelTarget("cc_library_static", "used_with_stubs", AttrNameToString{}),
},
})
}
@@ -1454,14 +1505,37 @@
func TestCcLibraryStaticUseVersionLib(t *testing.T) {
runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+ Filesystem: map[string]string{
+ soongCcVersionLibBpPath: soongCcVersionLibBp,
+ },
Blueprint: soongCcProtoPreamble + `cc_library_static {
name: "foo",
use_version_lib: true,
+ static_libs: ["libbuildversion"],
include_build_directory: false,
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "use_version_lib": "True",
+ "implementation_whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryStaticUseVersionLibHasDep(t *testing.T) {
+ runCcLibraryStaticTestCase(t, Bp2buildTestCase{
+ Filesystem: map[string]string{
+ soongCcVersionLibBpPath: soongCcVersionLibBp,
+ },
+ Blueprint: soongCcProtoPreamble + `cc_library_static {
+ name: "foo",
+ use_version_lib: true,
+ whole_static_libs: ["libbuildversion"],
+ include_build_directory: false,
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
}),
},
})
@@ -1575,3 +1649,77 @@
},
})
}
+
+func TestCcLibraryStaticWithSyspropSrcs(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_static with sysprop sources",
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ srcs: [
+ "bar.sysprop",
+ "baz.sysprop",
+ "blah.cpp",
+ ],
+ min_sdk_version: "5",
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `[
+ "bar.sysprop",
+ "baz.sysprop",
+ ]`,
+ }),
+ MakeBazelTarget("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }),
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`,
+ }),
+ },
+ })
+}
+
+func TestCcLibraryStaticWithSyspropSrcsSomeConfigs(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library_static with sysprop sources in some configs but not others",
+ Blueprint: `
+cc_library_static {
+ name: "foo",
+ srcs: [
+ "blah.cpp",
+ ],
+ target: {
+ android: {
+ srcs: ["bar.sysprop"],
+ },
+ },
+ min_sdk_version: "5",
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("sysprop_library", "foo_sysprop_library", AttrNameToString{
+ "srcs": `select({
+ "//build/bazel/platforms/os:android": ["bar.sysprop"],
+ "//conditions:default": [],
+ })`,
+ }),
+ MakeBazelTarget("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
+ "dep": `":foo_sysprop_library"`,
+ "min_sdk_version": `"5"`,
+ }),
+ MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
+ "srcs": `["blah.cpp"]`,
+ "local_includes": `["."]`,
+ "min_sdk_version": `"5"`,
+ "whole_archive_deps": `select({
+ "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"],
+ "//conditions:default": [],
+ })`,
+ }),
+ },
+ })
+}
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/cc_test_conversion_test.go b/bp2build/cc_test_conversion_test.go
index 9b7748f..8c2d30d 100644
--- a/bp2build/cc_test_conversion_test.go
+++ b/bp2build/cc_test_conversion_test.go
@@ -148,3 +148,27 @@
},
})
}
+
+func TestCcTest_TestOptions_Tags(t *testing.T) {
+ runCcTestTestCase(t, ccTestBp2buildTestCase{
+ description: "cc test with test_options.tags converted to tags",
+ blueprint: `
+cc_test {
+ name: "mytest",
+ host_supported: true,
+ srcs: ["test.cpp"],
+ test_options: { tags: ["no-remote"] },
+}
+`,
+ targets: []testBazelTarget{
+ {"cc_test", "mytest", AttrNameToString{
+ "tags": `["no-remote"]`,
+ "local_includes": `["."]`,
+ "srcs": `["test.cpp"]`,
+ "gtest": "True",
+ "isolated": "True",
+ },
+ },
+ },
+ })
+}
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 6fb2823..4d8b8a4 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -34,6 +34,12 @@
files = append(files, newFile("metrics", "converted_modules.txt", strings.Join(metrics.convertedModules, "\n")))
+ convertedModulePathMap, err := json.MarshalIndent(metrics.convertedModulePathMap, "", "\t")
+ if err != nil {
+ panic(err)
+ }
+ files = append(files, newFile("metrics", "converted_modules_path_map.json", string(convertedModulePathMap)))
+
files = append(files, newFile("product_config", "soong_config_variables.bzl", cfg.Bp2buildSoongConfigDefinitions.String()))
files = append(files, newFile("product_config", "arch_configuration.bzl", android.StarlarkArchConfigurations()))
@@ -91,15 +97,19 @@
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.
`
-
- // Hardcode the default visibility.
- content += "package(default_visibility = [\"//visibility:public\"])\n"
content += targets.LoadStatements()
+ content += "\n\n"
+ // Get package rule from the handcrafted BUILD file, otherwise emit the default one.
+ prText := "package(default_visibility = [\"//visibility:public\"])\n"
+ if pr := targets.packageRule(); pr != nil {
+ prText = pr.content
+ }
+ content += prText
} else if mode == QueryView {
content = soongModuleLoad
}
@@ -136,16 +146,17 @@
var (
// Certain module property names are blocklisted/ignored here, for the reasons commented.
ignoredPropNames = map[string]bool{
- "name": true, // redundant, since this is explicitly generated for every target
- "from": true, // reserved keyword
- "in": true, // reserved keyword
- "size": true, // reserved for tests
- "arch": true, // interface prop type is not supported yet.
- "multilib": true, // interface prop type is not supported yet.
- "target": true, // interface prop type is not supported yet.
- "visibility": true, // Bazel has native visibility semantics. Handle later.
- "features": true, // There is already a built-in attribute 'features' which cannot be overridden.
- "for": true, // reserved keyword, b/233579439
+ "name": true, // redundant, since this is explicitly generated for every target
+ "from": true, // reserved keyword
+ "in": true, // reserved keyword
+ "size": true, // reserved for tests
+ "arch": true, // interface prop type is not supported yet.
+ "multilib": true, // interface prop type is not supported yet.
+ "target": true, // interface prop type is not supported yet.
+ "visibility": true, // Bazel has native visibility semantics. Handle later.
+ "features": true, // There is already a built-in attribute 'features' which cannot be overridden.
+ "for": true, // reserved keyword, b/233579439
+ "versions_with_info": true, // TODO(b/245730552) struct properties not fully supported
}
)
@@ -159,7 +170,7 @@
// internal to Soong only, and these fields do not have PkgPath.
return true
}
- // fields with tag `blueprint:"mutated"` are exported to enable modification in mutators, etc
+ // fields with tag `blueprint:"mutated"` are exported to enable modification in mutators, etc.
// but cannot be set in a .bp file
if proptools.HasTag(field, "blueprint", "mutated") {
return true
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index 0cb711c..b696a98 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -116,6 +116,10 @@
basename: "converted_modules.txt",
},
{
+ dir: "metrics",
+ basename: "converted_modules_path_map.json",
+ },
+ {
dir: "product_config",
basename: "soong_config_variables.bzl",
},
diff --git a/bp2build/filegroup_conversion_test.go b/bp2build/filegroup_conversion_test.go
index de09a17..e978fb3 100644
--- a/bp2build/filegroup_conversion_test.go
+++ b/bp2build/filegroup_conversion_test.go
@@ -15,10 +15,10 @@
package bp2build
import (
- "android/soong/android"
"fmt"
-
"testing"
+
+ "android/soong/android"
)
func runFilegroupTestCase(t *testing.T, tc Bp2buildTestCase) {
@@ -121,3 +121,44 @@
]`}),
}})
}
+
+func TestFilegroupWithProtoSrcs(t *testing.T) {
+ runFilegroupTestCase(t, Bp2buildTestCase{
+ Description: "filegroup with proto and non-proto srcs",
+ Filesystem: map[string]string{},
+ Blueprint: `
+filegroup {
+ name: "foo",
+ srcs: ["proto/foo.proto"],
+ path: "proto",
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("proto_library", "foo_bp2build_converted", AttrNameToString{
+ "srcs": `["proto/foo.proto"]`,
+ "strip_import_prefix": `"proto"`,
+ "tags": `["manual"]`}),
+ MakeBazelTargetNoRestrictions("filegroup", "foo", AttrNameToString{
+ "srcs": `["proto/foo.proto"]`}),
+ }})
+}
+
+func TestFilegroupWithProtoAndNonProtoSrcs(t *testing.T) {
+ runFilegroupTestCase(t, Bp2buildTestCase{
+ Description: "filegroup with proto and non-proto srcs",
+ Filesystem: map[string]string{},
+ Blueprint: `
+filegroup {
+ name: "foo",
+ srcs: [
+ "foo.proto",
+ "buf.cpp",
+ ],
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("filegroup", "foo", AttrNameToString{
+ "srcs": `[
+ "foo.proto",
+ "buf.cpp",
+ ]`}),
+ }})
+}
diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go
index a8bfecd..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) {
@@ -61,7 +62,7 @@
{
moduleType: "genrule",
factory: genrule.GenRuleFactory,
- genDir: "$(GENDIR)",
+ genDir: "$(RULEDIR)",
},
{
moduleType: "cc_genrule",
@@ -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/license_conversion_test.go b/bp2build/license_conversion_test.go
new file mode 100644
index 0000000..ea6b27a
--- /dev/null
+++ b/bp2build/license_conversion_test.go
@@ -0,0 +1,81 @@
+// 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"
+ "testing"
+)
+
+func registerLicenseModuleTypes(_ android.RegistrationContext) {}
+
+func TestLicenseBp2Build(t *testing.T) {
+ tests := []struct {
+ description string
+ module string
+ expected ExpectedRuleTarget
+ }{
+ {
+ description: "license kind and text notice",
+ module: `
+license {
+ name: "my_license",
+ license_kinds: [ "SPDX-license-identifier-Apache-2.0"],
+ license_text: [ "NOTICE"],
+}`,
+ expected: ExpectedRuleTarget{
+ "android_license",
+ "my_license",
+ AttrNameToString{
+ "license_kinds": `["SPDX-license-identifier-Apache-2.0"]`,
+ "license_text": `"NOTICE"`,
+ },
+ android.HostAndDeviceDefault,
+ },
+ },
+ {
+ description: "visibility, package_name, copyright_notice",
+ module: `
+license {
+ name: "my_license",
+ package_name: "my_package",
+ visibility: [":__subpackages__"],
+ copyright_notice: "Copyright © 2022",
+}`,
+ expected: ExpectedRuleTarget{
+ "android_license",
+ "my_license",
+ AttrNameToString{
+ "copyright_notice": `"Copyright © 2022"`,
+ "package_name": `"my_package"`,
+ "visibility": `[":__subpackages__"]`,
+ },
+ android.HostAndDeviceDefault,
+ },
+ },
+ }
+
+ for _, test := range tests {
+ RunBp2BuildTestCase(t,
+ registerLicenseModuleTypes,
+ Bp2buildTestCase{
+ Description: test.description,
+ ModuleTypeUnderTest: "license",
+ ModuleTypeUnderTestFactory: android.LicenseFactory,
+ Blueprint: test.module,
+ ExpectedBazelTargets: []string{test.expected.String()},
+ })
+ }
+}
diff --git a/bp2build/license_kind_conversion_test.go b/bp2build/license_kind_conversion_test.go
new file mode 100644
index 0000000..eda116c
--- /dev/null
+++ b/bp2build/license_kind_conversion_test.go
@@ -0,0 +1,69 @@
+// 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"
+ "testing"
+)
+
+func registerLicenseKindModuleTypes(_ android.RegistrationContext) {}
+
+func TestLicenseKindBp2Build(t *testing.T) {
+ tests := []struct {
+ description string
+ module string
+ expected ExpectedRuleTarget
+ }{
+ {
+ description: "license_kind",
+ module: `
+license_kind {
+ name: "my_license",
+ conditions: [
+ "by_exception_only",
+ "not_allowed",
+ ],
+ url: "https://spdx.org/licenses/0BSD",
+ visibility: ["//visibility:public"],
+}`,
+ expected: ExpectedRuleTarget{
+ "license_kind",
+ "my_license",
+ AttrNameToString{
+ "conditions": `[
+ "by_exception_only",
+ "not_allowed",
+ ]`,
+ "url": `"https://spdx.org/licenses/0BSD"`,
+ "visibility": `["//visibility:public"]`,
+ },
+ android.HostAndDeviceDefault,
+ },
+ },
+ }
+
+ for _, test := range tests {
+ RunBp2BuildTestCase(t,
+ registerLicenseKindModuleTypes,
+ Bp2buildTestCase{
+ Description: test.description,
+ ModuleTypeUnderTest: "license_kind",
+ ModuleTypeUnderTestFactory: android.LicenseKindFactory,
+ Blueprint: test.module,
+ ExpectedBazelTargets: []string{test.expected.String()},
+ })
+ }
+}
diff --git a/bp2build/metrics.go b/bp2build/metrics.go
index 3a21c34..0b45996 100644
--- a/bp2build/metrics.go
+++ b/bp2build/metrics.go
@@ -9,6 +9,7 @@
"android/soong/android"
"android/soong/shared"
"android/soong/ui/metrics/bp2build_metrics_proto"
+
"github.com/google/blueprint"
)
@@ -38,6 +39,9 @@
// List of converted modules
convertedModules []string
+ // Map of converted modules and paths to call
+ convertedModulePathMap map[string]string
+
// Counts of converted modules by module type.
convertedModuleTypeCount map[string]uint64
@@ -147,10 +151,11 @@
Handcrafted
)
-func (metrics *CodegenMetrics) AddConvertedModule(m blueprint.Module, moduleType string, conversionType ConversionType) {
+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.convertedModulePathMap[moduleName] = "//" + dir
metrics.convertedModuleTypeCount[moduleType] += 1
metrics.totalModuleTypeCount[moduleType] += 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
new file mode 100644
index 0000000..819ab25
--- /dev/null
+++ b/bp2build/ndk_library_conversion_test.go
@@ -0,0 +1,77 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bp2build
+
+import (
+ "testing"
+
+ "android/soong/cc"
+)
+
+func TestNdkLibraryContributionSymbolFile(t *testing.T) {
+ bp := `
+ ndk_library {
+ name: "libfoo",
+ symbol_file: "libfoo.map.txt",
+ }
+ `
+ expectedBazelTarget := MakeBazelTargetNoRestrictions(
+ "cc_api_contribution",
+ "libfoo.ndk.contribution",
+ AttrNameToString{
+ "api": `"libfoo.map.txt"`,
+ "api_surfaces": `["publicapi"]`,
+ "library_name": `"libfoo"`,
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ },
+ )
+ RunApiBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
+ Blueprint: bp,
+ ExpectedBazelTargets: []string{expectedBazelTarget},
+ })
+}
+
+func TestNdkLibraryContributionHeaders(t *testing.T) {
+ bp := `
+ ndk_library {
+ name: "libfoo",
+ symbol_file: "libfoo.map.txt",
+ export_header_libs: ["libfoo_headers"],
+ }
+ `
+ fs := map[string]string{
+ "header_directory/Android.bp": `
+ ndk_headers {
+ name: "libfoo_headers",
+ }
+ `,
+ }
+ expectedBazelTarget := MakeBazelTargetNoRestrictions(
+ "cc_api_contribution",
+ "libfoo.ndk.contribution",
+ AttrNameToString{
+ "api": `"libfoo.map.txt"`,
+ "api_surfaces": `["publicapi"]`,
+ "library_name": `"libfoo"`,
+ "hdrs": `["//header_directory:libfoo_headers.contribution"]`,
+ "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+ },
+ )
+ RunApiBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{
+ Blueprint: bp,
+ Filesystem: fs,
+ ExpectedBazelTargets: []string{expectedBazelTarget},
+ })
+}
diff --git a/bp2build/package_conversion_test.go b/bp2build/package_conversion_test.go
new file mode 100644
index 0000000..3704b2d
--- /dev/null
+++ b/bp2build/package_conversion_test.go
@@ -0,0 +1,85 @@
+// 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/genrule"
+ "testing"
+)
+
+func registerDependentModules(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("license", android.LicenseFactory)
+ ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
+}
+
+func TestPackage(t *testing.T) {
+ tests := []struct {
+ description string
+ modules string
+ expected []ExpectedRuleTarget
+ }{
+ {
+ description: "with default applicable licenses",
+ modules: `
+license {
+ name: "my_license",
+ visibility: [":__subpackages__"],
+ license_kinds: ["SPDX-license-identifier-Apache-2.0"],
+ license_text: ["NOTICE"],
+}
+
+package {
+ default_applicable_licenses: ["my_license"],
+}
+`,
+ expected: []ExpectedRuleTarget{
+ {
+ "package",
+ "",
+ AttrNameToString{
+ "default_applicable_licenses": `[":my_license"]`,
+ "default_visibility": `["//visibility:public"]`,
+ },
+ android.HostAndDeviceDefault,
+ },
+ {
+ "android_license",
+ "my_license",
+ AttrNameToString{
+ "license_kinds": `["SPDX-license-identifier-Apache-2.0"]`,
+ "license_text": `"NOTICE"`,
+ "visibility": `[":__subpackages__"]`,
+ },
+ android.HostAndDeviceDefault,
+ },
+ },
+ },
+ }
+ for _, test := range tests {
+ expected := make([]string, 0, len(test.expected))
+ for _, e := range test.expected {
+ expected = append(expected, e.String())
+ }
+ RunBp2BuildTestCase(t, registerDependentModules,
+ Bp2buildTestCase{
+ Description: test.description,
+ ModuleTypeUnderTest: "package",
+ ModuleTypeUnderTestFactory: android.PackageFactory,
+ Blueprint: test.modules,
+ ExpectedBazelTargets: expected,
+ })
+ }
+}
diff --git a/bp2build/prebuilt_etc_conversion_test.go b/bp2build/prebuilt_etc_conversion_test.go
index b1e70dc..aa0a5b7 100644
--- a/bp2build/prebuilt_etc_conversion_test.go
+++ b/bp2build/prebuilt_etc_conversion_test.go
@@ -15,10 +15,11 @@
package bp2build
import (
+ "fmt"
+ "testing"
+
"android/soong/android"
"android/soong/etc"
-
- "testing"
)
func runPrebuiltEtcTestCase(t *testing.T, tc Bp2buildTestCase) {
@@ -128,6 +129,32 @@
"dir": `"etc/tz"`,
})}})
}
+func TestPrebuiltEtcProductVariables(t *testing.T) {
+ runPrebuiltEtcTestCase(t, Bp2buildTestCase{
+ Description: "prebuilt etc - product variables",
+ Filesystem: map[string]string{},
+ Blueprint: `
+prebuilt_etc {
+ name: "apex_tz_version",
+ src: "version/tz_version",
+ filename: "tz_version",
+ product_variables: {
+ native_coverage: {
+ src: "src1",
+ },
+ },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{
+ "filename": `"tz_version"`,
+ "src": `select({
+ "//build/bazel/product_variables:native_coverage": "src1",
+ "//conditions:default": "version/tz_version",
+ })`,
+ "dir": `"etc"`,
+ })}})
+}
func runPrebuiltUsrShareTestCase(t *testing.T, tc Bp2buildTestCase) {
t.Helper()
@@ -265,3 +292,57 @@
"dir": `"etc"`,
})}})
}
+
+func TestPrebuiltEtcProductVariableArchSrcs(t *testing.T) {
+ runPrebuiltEtcTestCase(t, Bp2buildTestCase{
+ Description: "prebuilt etc- SRcs from arch variant product variables",
+ Filesystem: map[string]string{},
+ Blueprint: `
+prebuilt_etc {
+ name: "foo",
+ filename: "fooFilename",
+ arch: {
+ arm: {
+ src: "armSrc",
+ product_variables: {
+ native_coverage: {
+ src: "nativeCoverageArmSrc",
+ },
+ },
+ },
+ },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("prebuilt_file", "foo", AttrNameToString{
+ "filename": `"fooFilename"`,
+ "dir": `"etc"`,
+ "src": `select({
+ "//build/bazel/platforms/arch:arm": "armSrc",
+ "//build/bazel/product_variables:native_coverage-arm": "nativeCoverageArmSrc",
+ "//conditions:default": None,
+ })`,
+ })}})
+}
+
+func TestPrebuiltEtcProductVariableError(t *testing.T) {
+ runPrebuiltEtcTestCase(t, Bp2buildTestCase{
+ Description: "",
+ Filesystem: map[string]string{},
+ Blueprint: `
+prebuilt_etc {
+ name: "foo",
+ filename: "fooFilename",
+ arch: {
+ arm: {
+ src: "armSrc",
+ },
+ },
+ product_variables: {
+ native_coverage: {
+ src: "nativeCoverageArmSrc",
+ },
+ },
+}`,
+ ExpectedErr: fmt.Errorf("label attribute could not be collapsed"),
+ })
+}
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..7c39a11 100644
--- a/bp2build/symlink_forest.go
+++ b/bp2build/symlink_forest.go
@@ -285,6 +285,17 @@
// Neither is a directory. Merge them.
srcBuildFile := shared.JoinPath(topdir, srcChild)
generatedBuildFile := shared.JoinPath(topdir, buildFilesChild)
+ // Add the src and generated build files as dependencies so that bp2build
+ // is rerun when they change. Currently, this is only really necessary
+ // for srcBuildFile, because if we regenerate the generated build files
+ // we will always rerun the symlink forest generation as well. If that
+ // is later split up into separate, fully dependency-tracing steps, then
+ // we'll need srcBuildFile as well. Adding srcBuildFile here today
+ // technically makes it a dependency of bp2build_workspace_marker, which
+ // also implicitly outputs that file, but since bp2build_workspace_marker
+ // will always have a newer timestamp than the generatedBuildFile it
+ // shouldn't be a problem.
+ *acc = append(*acc, srcBuildFile, generatedBuildFile)
err = mergeBuildFiles(shared.JoinPath(topdir, forestChild), srcBuildFile, generatedBuildFile, cfg.IsEnvTrue("BP2BUILD_VERBOSE"))
if err != nil {
fmt.Fprintf(os.Stderr, "Error merging %s and %s: %s",
diff --git a/bp2build/testing.go b/bp2build/testing.go
index a0d512f..31aa830 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -24,19 +24,14 @@
"strings"
"testing"
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
"android/soong/android/allowlists"
"android/soong/bazel"
)
var (
- // A default configuration for tests to not have to specify bp2build_available on top level targets.
- bp2buildConfig = android.NewBp2BuildAllowlist().SetDefaultConfig(
- allowlists.Bp2BuildConfig{
- android.Bp2BuildTopLevel: allowlists.Bp2BuildDefaultTrueRecursively,
- },
- )
-
buildDir string
)
@@ -87,9 +82,30 @@
// An error with a string contained within the string of the expected error
ExpectedErr error
UnconvertedDepsMode unconvertedDepsMode
+
+ // For every directory listed here, the BUILD file for that directory will
+ // be merged with the generated BUILD file. This allows custom BUILD targets
+ // to be used in tests, or use BUILD files to draw package boundaries.
+ KeepBuildFileForDirs []string
}
func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
+ 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) {
+ 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)
@@ -105,10 +121,21 @@
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.
+ bp2buildConfig := android.NewBp2BuildAllowlist().SetDefaultConfig(
+ allowlists.Bp2BuildConfig{
+ android.Bp2BuildTopLevel: allowlists.Bp2BuildDefaultTrueRecursively,
+ },
+ )
+ for _, f := range tc.KeepBuildFileForDirs {
+ bp2buildConfig.SetKeepExistingBuildFile(map[string]bool{
+ f: /*recursive=*/ false,
+ })
+ }
ctx.RegisterBp2BuildConfig(bp2buildConfig)
- ctx.RegisterForBazelConversion()
_, parseErrs := ctx.ParseFileList(dir, toParse)
if errored(t, tc, parseErrs) {
@@ -141,7 +168,7 @@
android.FailIfErrored(t, errs)
}
if actualCount, expectedCount := len(bazelTargets), len(tc.ExpectedBazelTargets); actualCount != expectedCount {
- t.Errorf("%s: Expected %d bazel target (%s), got `%d`` (%s)",
+ t.Errorf("%s: Expected %d bazel target (%s), got %d (%s)",
tc.Description, expectedCount, tc.ExpectedBazelTargets, actualCount, bazelTargets)
} else {
for i, target := range bazelTargets {
@@ -188,6 +215,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 {
@@ -310,6 +339,7 @@
String_ptr_prop *string
String_list_prop []string
Arch_paths bazel.LabelListAttribute
+ Api bazel.LabelAttribute
}
func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
@@ -354,6 +384,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) {
@@ -384,6 +431,9 @@
func generateBazelTargetsForDir(codegenCtx *CodegenContext, dir string) (BazelTargets, []error) {
// TODO: Set generateFilegroups to true and/or remove the generateFilegroups argument completely
res, err := GenerateBazelTargets(codegenCtx, false)
+ if err != nil {
+ return BazelTargets{}, err
+ }
return res.buildFileToTargets[dir], err
}
@@ -426,7 +476,9 @@
}
attrStrings := make([]string, 0, len(attrs)+1)
- attrStrings = append(attrStrings, fmt.Sprintf(` name = "%s",`, name))
+ if name != "" {
+ attrStrings = append(attrStrings, fmt.Sprintf(` name = "%s",`, name))
+ }
for _, k := range android.SortedStringKeys(attrs) {
attrStrings = append(attrStrings, fmt.Sprintf(" %s = %s,", k, attrs[k]))
}
@@ -447,3 +499,34 @@
func MakeBazelTarget(typ, name string, attrs AttrNameToString) string {
return makeBazelTargetHostOrDevice(typ, name, attrs, android.DeviceSupported)
}
+
+type ExpectedRuleTarget struct {
+ Rule string
+ Name string
+ Attrs AttrNameToString
+ Hod android.HostOrDeviceSupported
+}
+
+func (ebr ExpectedRuleTarget) String() string {
+ return makeBazelTargetHostOrDevice(ebr.Rule, ebr.Name, ebr.Attrs, ebr.Hod)
+}
+
+func makeCcStubSuiteTargets(name string, attrs AttrNameToString) string {
+ if _, hasStubs := attrs["stubs_symbol_file"]; !hasStubs {
+ return ""
+ }
+ STUB_SUITE_ATTRS := map[string]string{
+ "stubs_symbol_file": "symbol_file",
+ "stubs_versions": "versions",
+ "soname": "soname",
+ "source_library": "source_library",
+ }
+
+ stubSuiteAttrs := AttrNameToString{}
+ for key, _ := range attrs {
+ if _, stubSuiteAttr := STUB_SUITE_ATTRS[key]; stubSuiteAttr {
+ stubSuiteAttrs[STUB_SUITE_ATTRS[key]] = attrs[key]
+ }
+ }
+ return MakeBazelTarget("cc_stub_suite", name+"_stub_libs", stubSuiteAttrs)
+}
diff --git a/bpf/bpf.go b/bpf/bpf.go
index e89cc4e..60a410d 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -21,6 +21,8 @@
"strings"
"android/soong/android"
+ "android/soong/bazel"
+ "android/soong/bazel/cquery"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -93,6 +95,7 @@
type bpf struct {
android.ModuleBase
+ android.BazelModuleBase
properties BpfProperties
@@ -237,6 +240,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 +292,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..92819a1 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
@@ -59,7 +62,7 @@
echo
echo "Running Bazel smoke test..."
-STANDALONE_BAZEL=true "${TOP}/tools/bazel" --batch --max_idle_secs=1 info
+STANDALONE_BAZEL=true "${TOP}/tools/bazel" --batch --max_idle_secs=1 help
echo
echo "Running Soong test..."
diff --git a/cc/Android.bp b/cc/Android.bp
index 2963c77..8860f78 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -99,6 +99,7 @@
"library_headers_test.go",
"library_stub_test.go",
"library_test.go",
+ "lto_test.go",
"ndk_test.go",
"object_test.go",
"prebuilt_test.go",
diff --git a/cc/androidmk.go b/cc/androidmk.go
index a9ba1a9..58bb57c 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -546,7 +546,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 +567,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..a6d7507 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 {
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 c1a3bef..d6d052f 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -28,14 +28,17 @@
)
const (
- cSrcPartition = "c"
- asSrcPartition = "as"
- asmSrcPartition = "asm"
- lSrcPartition = "l"
- llSrcPartition = "ll"
- cppSrcPartition = "cpp"
- protoSrcPartition = "proto"
- aidlSrcPartition = "aidl"
+ cSrcPartition = "c"
+ asSrcPartition = "as"
+ asmSrcPartition = "asm"
+ lSrcPartition = "l"
+ llSrcPartition = "ll"
+ cppSrcPartition = "cpp"
+ protoSrcPartition = "proto"
+ aidlSrcPartition = "aidl"
+ syspropSrcPartition = "sysprop"
+
+ stubsSuffix = "_stub_libs_current"
)
// staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties --
@@ -77,10 +80,10 @@
if !exists || !android.IsFilegroup(otherModuleCtx, m) {
return labelStr, false
}
- // If the filegroup is already converted to aidl_library, skip creating
- // _c_srcs, _as_srcs, _cpp_srcs filegroups
- fg, _ := m.(android.Bp2buildAidlLibrary)
- if fg.ShouldConvertToAidlLibrary(ctx) {
+ // If the filegroup is already converted to aidl_library or proto_library,
+ // skip creating _c_srcs, _as_srcs, _cpp_srcs filegroups
+ fg, _ := m.(android.FileGroupAsLibrary)
+ if fg.ShouldConvertToAidlLibrary(ctx) || fg.ShouldConvertToProtoLibrary(ctx) {
return labelStr, false
}
return labelStr + suffix, true
@@ -102,7 +105,8 @@
llSrcPartition: bazel.LabelPartition{Extensions: []string{".ll"}},
// C++ is the "catch-all" group, and comprises generated sources because we don't
// know the language of these sources until the genrule is executed.
- cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true},
+ cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true},
+ syspropSrcPartition: bazel.LabelPartition{Extensions: []string{".sysprop"}},
}
return bazel.PartitionLabelListAttribute(ctx, &srcs, labels)
@@ -165,12 +169,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))
@@ -223,32 +235,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)
}
})
@@ -257,7 +267,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 {
@@ -280,11 +290,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,
}
}
@@ -318,6 +333,9 @@
llSrcs bazel.LabelListAttribute
lexopts bazel.StringListAttribute
+ // Sysprop sources
+ syspropSrcs bazel.LabelListAttribute
+
hdrs bazel.LabelListAttribute
rtti bazel.BoolAttribute
@@ -358,7 +376,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
@@ -373,15 +391,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
}
@@ -415,10 +425,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)
}
@@ -480,6 +490,7 @@
ca.asmSrcs = partitionedSrcs[asmSrcPartition]
ca.lSrcs = partitionedSrcs[lSrcPartition]
ca.llSrcs = partitionedSrcs[llSrcPartition]
+ ca.syspropSrcs = partitionedSrcs[syspropSrcPartition]
ca.absoluteIncludes.DeduplicateAxesFromBase()
ca.localIncludes.DeduplicateAxesFromBase()
@@ -504,19 +515,6 @@
return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedSrcsLabelList), anySrcs
}
-// Given a name in srcs prop, check to see if the name references a filegroup
-// and the filegroup is converted to aidl_library
-func isConvertedToAidlLibrary(ctx android.BazelConversionPathContext, name string) bool {
- if module, ok := ctx.ModuleFromName(name); ok {
- if android.IsFilegroup(ctx, module) {
- if fg, ok := module.(android.Bp2buildAidlLibrary); ok {
- return fg.ShouldConvertToAidlLibrary(ctx)
- }
- }
- }
- return false
-}
-
func bp2buildStdVal(std *string, prefix string, useGnu bool) *string {
defaultVal := prefix + "_std_default"
// If c{,pp}std properties are not specified, don't generate them in the BUILD file.
@@ -723,20 +721,32 @@
(&compilerAttrs.srcs).Add(bp2BuildYasm(ctx, module, compilerAttrs))
protoDep := bp2buildProto(ctx, module, compilerAttrs.protoSrcs)
- aidlDep := bp2buildCcAidlLibrary(ctx, module, compilerAttrs.aidlSrcs)
// bp2buildProto will only set wholeStaticLib or implementationWholeStaticLib, but we don't know
// which. This will add the newly generated proto library to the appropriate attribute and nothing
// to the other
(&linkerAttrs).wholeArchiveDeps.Add(protoDep.wholeStaticLib)
(&linkerAttrs).implementationWholeArchiveDeps.Add(protoDep.implementationWholeStaticLib)
- // TODO(b/243023967) Add aidlDep to implementationWholeArchiveDeps if aidl.export_aidl_headers is true
- (&linkerAttrs).wholeArchiveDeps.Add(aidlDep)
+
+ aidlDep := bp2buildCcAidlLibrary(ctx, module, compilerAttrs.aidlSrcs, linkerAttrs)
+ if aidlDep != nil {
+ if lib, ok := module.linker.(*libraryDecorator); ok {
+ if proptools.Bool(lib.Properties.Aidl.Export_aidl_headers) {
+ (&linkerAttrs).wholeArchiveDeps.Add(aidlDep)
+ } else {
+ (&linkerAttrs).implementationWholeArchiveDeps.Add(aidlDep)
+ }
+ }
+ }
convertedLSrcs := bp2BuildLex(ctx, module.Name(), compilerAttrs)
(&compilerAttrs).srcs.Add(&convertedLSrcs.srcName)
(&compilerAttrs).cSrcs.Add(&convertedLSrcs.cSrcName)
+ if !compilerAttrs.syspropSrcs.IsEmpty() {
+ (&linkerAttrs).wholeArchiveDeps.Add(bp2buildCcSysprop(ctx, module.Name(), module.Properties.Min_sdk_version, compilerAttrs.syspropSrcs))
+ }
+
features := compilerAttrs.features.Clone().Append(linkerAttrs.features)
features.DeduplicateAxesFromBase()
@@ -749,78 +759,69 @@
}
}
-func bp2buildAidlLibraries(
- ctx android.Bp2buildMutatorContext,
- m *Module,
- aidlSrcs bazel.LabelListAttribute,
-) bazel.LabelList {
- var aidlLibraries bazel.LabelList
- var directAidlSrcs bazel.LabelList
-
- // Make a list of labels that correspond to filegroups that are already converted to aidl_library
- for _, aidlSrc := range aidlSrcs.Value.Includes {
- src := aidlSrc.OriginalModuleName
- if isConvertedToAidlLibrary(ctx, src) {
- module, _ := ctx.ModuleFromName(src)
- fg, _ := module.(android.Bp2buildAidlLibrary)
- aidlLibraries.Add(&bazel.Label{
- Label: fg.GetAidlLibraryLabel(ctx),
- })
- } else {
- directAidlSrcs.Add(&aidlSrc)
- }
- }
-
- if len(directAidlSrcs.Includes) > 0 {
- aidlLibraryLabel := m.Name() + "_aidl_library"
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "aidl_library",
- Bzl_load_location: "//build/bazel/rules/aidl:library.bzl",
- },
- android.CommonAttributes{Name: aidlLibraryLabel},
- &aidlLibraryAttributes{
- Srcs: bazel.MakeLabelListAttribute(directAidlSrcs),
- },
- )
- aidlLibraries.Add(&bazel.Label{
- Label: ":" + aidlLibraryLabel,
- })
- }
- return aidlLibraries
-}
-
func bp2buildCcAidlLibrary(
ctx android.Bp2buildMutatorContext,
m *Module,
- aidlSrcs bazel.LabelListAttribute,
+ aidlLabelList bazel.LabelListAttribute,
+ linkerAttrs linkerAttributes,
) *bazel.LabelAttribute {
- suffix := "_cc_aidl_library"
- ccAidlLibrarylabel := m.Name() + suffix
+ if !aidlLabelList.IsEmpty() {
+ aidlLibs, aidlSrcs := aidlLabelList.Partition(func(src bazel.Label) bool {
+ if fg, ok := android.ToFileGroupAsLibrary(ctx, src.OriginalModuleName); ok &&
+ fg.ShouldConvertToAidlLibrary(ctx) {
+ return true
+ }
+ return false
+ })
- aidlLibraries := bp2buildAidlLibraries(ctx, m, aidlSrcs)
+ if !aidlSrcs.IsEmpty() {
+ aidlLibName := m.Name() + "_aidl_library"
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "aidl_library",
+ Bzl_load_location: "//build/bazel/rules/aidl:library.bzl",
+ },
+ android.CommonAttributes{Name: aidlLibName},
+ &aidlLibraryAttributes{
+ Srcs: aidlSrcs,
+ },
+ )
+ aidlLibs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}})
+ }
- if aidlLibraries.IsEmpty() {
- return nil
+ if !aidlLibs.IsEmpty() {
+ ccAidlLibrarylabel := m.Name() + "_cc_aidl_library"
+ // Since cc_aidl_library only needs the dynamic deps (aka shared libs) from the parent cc library for compiling,
+ // we err on the side of not re-exporting the headers of the dynamic deps from cc_aidl_lirary
+ // because the parent cc library already has all the dynamic deps
+ implementationDynamicDeps := bazel.MakeLabelListAttribute(
+ bazel.AppendBazelLabelLists(
+ linkerAttrs.dynamicDeps.Value,
+ linkerAttrs.implementationDynamicDeps.Value,
+ ),
+ )
+
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_aidl_library",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_aidl_library.bzl",
+ },
+ android.CommonAttributes{Name: ccAidlLibrarylabel},
+ &ccAidlLibraryAttributes{
+ Deps: aidlLibs,
+ Implementation_dynamic_deps: implementationDynamicDeps,
+ },
+ )
+ label := &bazel.LabelAttribute{
+ Value: &bazel.Label{
+ Label: ":" + ccAidlLibrarylabel,
+ },
+ }
+ return label
+ }
}
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "cc_aidl_library",
- Bzl_load_location: "//build/bazel/rules/cc:cc_aidl_library.bzl",
- },
- android.CommonAttributes{Name: ccAidlLibrarylabel},
- &ccAidlLibraryAttributes{
- Deps: bazel.MakeLabelListAttribute(aidlLibraries),
- },
- )
-
- label := &bazel.LabelAttribute{
- Value: &bazel.Label{
- Label: ":" + ccAidlLibrarylabel,
- },
- }
- return label
+ return nil
}
func bp2BuildParseSdkAttributes(module *Module) sdkAttributes {
@@ -862,19 +863,77 @@
var (
soongSystemSharedLibs = []string{"libc", "libm", "libdl"}
+ versionLib = "libbuildversion"
)
+// resolveTargetApex re-adds the shared and static libs in target.apex.exclude_shared|static_libs props to non-apex variant
+// since all libs are already excluded by default
+func (la *linkerAttributes) resolveTargetApexProp(ctx android.BazelConversionPathContext, isBinary bool, props *BaseLinkerProperties) {
+ sharedLibsForNonApex := maybePartitionExportedAndImplementationsDeps(
+ ctx,
+ true,
+ props.Target.Apex.Exclude_shared_libs,
+ props.Export_shared_lib_headers,
+ bazelLabelForSharedDeps,
+ )
+ dynamicDeps := la.dynamicDeps.SelectValue(bazel.InApexAxis, bazel.NonApex)
+ implDynamicDeps := la.implementationDynamicDeps.SelectValue(bazel.InApexAxis, bazel.NonApex)
+ (&dynamicDeps).Append(sharedLibsForNonApex.export)
+ (&implDynamicDeps).Append(sharedLibsForNonApex.implementation)
+ la.dynamicDeps.SetSelectValue(bazel.InApexAxis, bazel.NonApex, dynamicDeps)
+ la.implementationDynamicDeps.SetSelectValue(bazel.InApexAxis, bazel.NonApex, implDynamicDeps)
+
+ staticLibsForNonApex := maybePartitionExportedAndImplementationsDeps(
+ ctx,
+ !isBinary,
+ props.Target.Apex.Exclude_static_libs,
+ props.Export_static_lib_headers,
+ bazelLabelForSharedDeps,
+ )
+ deps := la.deps.SelectValue(bazel.InApexAxis, bazel.NonApex)
+ implDeps := la.implementationDeps.SelectValue(bazel.InApexAxis, bazel.NonApex)
+ (&deps).Append(staticLibsForNonApex.export)
+ (&implDeps).Append(staticLibsForNonApex.implementation)
+ la.deps.SetSelectValue(bazel.InApexAxis, bazel.NonApex, deps)
+ la.implementationDeps.SetSelectValue(bazel.InApexAxis, bazel.NonApex, implDeps)
+}
+
func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, isBinary bool, axis bazel.ConfigurationAxis, config string, props *BaseLinkerProperties) {
// Use a single variable to capture usage of nocrt in arch variants, so there's only 1 error message for this module
var axisFeatures []string
wholeStaticLibs := android.FirstUniqueStrings(props.Whole_static_libs)
- la.wholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, wholeStaticLibs, props.Exclude_static_libs))
+ staticLibs := android.FirstUniqueStrings(android.RemoveListFromList(props.Static_libs, wholeStaticLibs))
+ if axis == bazel.NoConfigAxis {
+ la.useVersionLib.SetSelectValue(axis, config, props.Use_version_lib)
+ if proptools.Bool(props.Use_version_lib) {
+ versionLibAlreadyInDeps := android.InList(versionLib, wholeStaticLibs)
+ // remove from static libs so there is no duplicate dependency
+ _, staticLibs = android.RemoveFromList(versionLib, staticLibs)
+ // only add the dep if it is not in progress
+ if !versionLibAlreadyInDeps {
+ if isBinary {
+ wholeStaticLibs = append(wholeStaticLibs, versionLib)
+ } else {
+ la.implementationWholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, []string{versionLib}, props.Exclude_static_libs))
+ }
+ }
+ }
+ }
+
// Excludes to parallel Soong:
// https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=247-249;drc=088b53577dde6e40085ffd737a1ae96ad82fc4b0
- staticLibs := android.FirstUniqueStrings(android.RemoveListFromList(props.Static_libs, wholeStaticLibs))
+ la.wholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, wholeStaticLibs, props.Exclude_static_libs))
- staticDeps := maybePartitionExportedAndImplementationsDepsExcludes(ctx, !isBinary, staticLibs, props.Exclude_static_libs, props.Export_static_lib_headers, bazelLabelForStaticDepsExcludes)
+ staticDeps := maybePartitionExportedAndImplementationsDepsExcludes(
+ ctx,
+ !isBinary,
+ staticLibs,
+ // Exclude static libs in Exclude_static_libs and Target.Apex.Exclude_static_libs props
+ append(props.Exclude_static_libs, props.Target.Apex.Exclude_static_libs...),
+ props.Export_static_lib_headers,
+ bazelLabelForStaticDepsExcludes,
+ )
headerLibs := android.FirstUniqueStrings(props.Header_libs)
hDeps := maybePartitionExportedAndImplementationsDeps(ctx, !isBinary, headerLibs, props.Export_header_lib_headers, bazelLabelForHeaderDeps)
@@ -906,9 +965,19 @@
la.usedSystemDynamicDepAsDynamicDep[el] = true
}
- sharedDeps := maybePartitionExportedAndImplementationsDepsExcludes(ctx, !isBinary, sharedLibs, props.Exclude_shared_libs, props.Export_shared_lib_headers, bazelLabelForSharedDepsExcludes)
+ sharedDeps := maybePartitionExportedAndImplementationsDepsExcludes(
+ ctx,
+ !isBinary,
+ sharedLibs,
+ // Exclude shared libs in Exclude_shared_libs and Target.Apex.Exclude_shared_libs props
+ append(props.Exclude_shared_libs, props.Target.Apex.Exclude_shared_libs...),
+ props.Export_shared_lib_headers,
+ bazelLabelForSharedDepsExcludes,
+ )
la.dynamicDeps.SetSelectValue(axis, config, sharedDeps.export)
la.implementationDynamicDeps.SetSelectValue(axis, config, sharedDeps.implementation)
+ la.resolveTargetApexProp(ctx, isBinary, props)
+
if axis == bazel.NoConfigAxis || (axis == bazel.OsConfigurationAxis && config == bazel.OsAndroid) {
// If a dependency in la.implementationDynamicDeps has stubs, its stub variant should be
// used when the dependency is linked in a APEX. The dependencies in NoConfigAxis and
@@ -927,7 +996,7 @@
stubLibLabels := []bazel.Label{}
for _, l := range depsWithStubs {
- l.Label = l.Label + "_stub_libs_current"
+ l.Label = l.Label + stubsSuffix
stubLibLabels = append(stubLibLabels, l)
}
inApexSelectValue := la.implementationDynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex)
@@ -937,14 +1006,14 @@
(&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels))
(&nonApexSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
(&defaultSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
- la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, inApexSelectValue)
- la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, nonApexSelectValue)
- la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, defaultSelectValue)
+ la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.FirstUniqueBazelLabelList(inApexSelectValue))
+ la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue))
+ la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, bazel.FirstUniqueBazelLabelList(defaultSelectValue))
} else if config == bazel.OsAndroid {
(&inApexSelectValue).Append(bazel.MakeLabelList(stubLibLabels))
(&nonApexSelectValue).Append(bazel.MakeLabelList(depsWithStubs))
- la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, inApexSelectValue)
- la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, nonApexSelectValue)
+ la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.FirstUniqueBazelLabelList(inApexSelectValue))
+ la.implementationDynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, bazel.FirstUniqueBazelLabelList(nonApexSelectValue))
}
}
}
@@ -965,25 +1034,28 @@
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())
- if axis == bazel.NoConfigAxis {
- la.useVersionLib.SetSelectValue(axis, config, props.Use_version_lib)
- }
-
// it's very unlikely for nocrt to be arch variant, so bp2build doesn't support it.
if props.crt() != nil {
if axis == bazel.NoConfigAxis {
@@ -1088,12 +1160,20 @@
if la.systemDynamicDeps.IsNil() && len(la.usedSystemDynamicDepAsDynamicDep) > 0 {
toRemove := bazelLabelForSharedDeps(ctx, android.SortedStringKeys(la.usedSystemDynamicDepAsDynamicDep))
la.dynamicDeps.Exclude(bazel.NoConfigAxis, "", toRemove)
- la.implementationDynamicDeps.Exclude(bazel.NoConfigAxis, "", toRemove)
- la.implementationDynamicDeps.Exclude(bazel.NoConfigAxis, "", toRemove)
la.dynamicDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
la.dynamicDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove)
+ la.implementationDynamicDeps.Exclude(bazel.NoConfigAxis, "", toRemove)
la.implementationDynamicDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
la.implementationDynamicDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove)
+
+ la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, toRemove)
+ la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex, toRemove)
+ stubsToRemove := make([]bazel.Label, 0, len(la.usedSystemDynamicDepAsDynamicDep))
+ for _, lib := range toRemove.Includes {
+ lib.Label += stubsSuffix
+ stubsToRemove = append(stubsToRemove, lib)
+ }
+ la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.AndroidAndInApex, bazel.MakeLabelList(stubsToRemove))
}
la.deps.ResolveExcludes()
@@ -1160,10 +1240,14 @@
return exported
}
+func BazelLabelNameForStaticModule(baseLabel string) string {
+ return baseLabel + "_bp2build_cc_library_static"
+}
+
func bazelLabelForStaticModule(ctx android.BazelConversionPathContext, m blueprint.Module) string {
label := android.BazelModuleLabel(ctx, m)
if ccModule, ok := m.(*Module); ok && ccModule.typ() == fullLibrary && !android.GetBp2BuildAllowList().GenerateCcLibraryStaticOnly(m.Name()) {
- label += "_bp2build_cc_library_static"
+ return BazelLabelNameForStaticModule(label)
}
return label
}
diff --git a/cc/builder.go b/cc/builder.go
index cb21b1f..39f7dc3 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -672,11 +672,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
@@ -1135,7 +1140,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 3129160..eb7c639 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -51,7 +51,6 @@
ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
ctx.BottomUp("version", versionMutator).Parallel()
ctx.BottomUp("begin", BeginMutator).Parallel()
- ctx.BottomUp("sysprop_cc", SyspropMutator).Parallel()
})
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
@@ -617,6 +616,10 @@
XrefCcFiles() android.Paths
}
+type overridable interface {
+ overriddenModules() []string
+}
+
type libraryDependencyKind int
const (
@@ -2392,18 +2395,8 @@
}
}
- // sysprop_library has to support both C++ and Java. So sysprop_library internally creates one
- // C++ implementation library and one Java implementation library. When a module links against
- // sysprop_library, the C++ implementation library has to be linked. syspropImplLibraries is a
- // map from sysprop_library to implementation library; it will be used in whole_static_libs,
- // static_libs, and shared_libs.
- syspropImplLibraries := syspropImplLibraries(actx.Config())
-
for _, lib := range deps.WholeStaticLibs {
depTag := libraryDependencyTag{Kind: staticLibraryDependency, wholeStatic: true, reexportFlags: true}
- if impl, ok := syspropImplLibraries[lib]; ok {
- lib = impl
- }
lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs)
@@ -2421,10 +2414,6 @@
depTag.excludeInApex = true
}
- if impl, ok := syspropImplLibraries[lib]; ok {
- lib = impl
- }
-
lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs)
actx.AddVariationDependencies([]blueprint.Variation{
@@ -2454,10 +2443,6 @@
depTag.excludeInApex = true
}
- if impl, ok := syspropImplLibraries[lib]; ok {
- lib = impl
- }
-
name, version := StubsLibNameAndVersion(lib)
sharedLibNames = append(sharedLibNames, name)
@@ -3349,6 +3334,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)
}
@@ -3636,6 +3626,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)
}
@@ -3656,6 +3656,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
@@ -3669,6 +3676,7 @@
sharedLibrary
headerLibrary
testBin // testBinary already declared
+ ndkLibrary
)
func (c *Module) typ() moduleType {
@@ -3705,6 +3713,8 @@
return staticLibrary
}
return sharedLibrary
+ } else if c.isNDKStubLibrary() {
+ return ndkLibrary
}
return unknownType
}
@@ -3714,7 +3724,9 @@
prebuilt := c.IsPrebuilt()
switch c.typ() {
case binary:
- if !prebuilt {
+ if prebuilt {
+ prebuiltBinaryBp2Build(ctx, c)
+ } else {
binaryBp2build(ctx, c)
}
case testBin:
@@ -3748,6 +3760,26 @@
}
}
+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)
+ }
+}
+
// Defaults
type Defaults struct {
android.ModuleBase
@@ -3835,6 +3867,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 5d569cc..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)
@@ -4386,3 +4474,93 @@
})
}
}
+
+func TestCcBuildBrokenClangAsFlags(t *testing.T) {
+ tests := []struct {
+ name string
+ clangAsFlags []string
+ BuildBrokenClangAsFlags bool
+ err string
+ }{
+ {
+ name: "error when clang_asflags is set",
+ clangAsFlags: []string{"-a", "-b"},
+ err: "clang_asflags: property is deprecated",
+ },
+ {
+ name: "no error when BuildBrokenClangAsFlags is explicitly set to true",
+ clangAsFlags: []string{"-a", "-b"},
+ BuildBrokenClangAsFlags: true,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ bp := fmt.Sprintf(`
+ cc_library {
+ name: "foo",
+ clang_asflags: %s,
+ }`, `["`+strings.Join(test.clangAsFlags, `","`)+`"]`)
+
+ if test.err == "" {
+ android.GroupFixturePreparers(
+ prepareForCcTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ if test.BuildBrokenClangAsFlags {
+ variables.BuildBrokenClangAsFlags = test.BuildBrokenClangAsFlags
+ }
+ }),
+ ).RunTestWithBp(t, bp)
+ } else {
+ prepareForCcTest.
+ ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(test.err)).
+ RunTestWithBp(t, bp)
+ }
+ })
+ }
+}
+
+func TestCcBuildBrokenClangCFlags(t *testing.T) {
+ tests := []struct {
+ name string
+ clangCFlags []string
+ BuildBrokenClangCFlags bool
+ err string
+ }{
+ {
+ name: "error when clang_cflags is set",
+ clangCFlags: []string{"-a", "-b"},
+ err: "clang_cflags: property is deprecated",
+ },
+ {
+ name: "no error when BuildBrokenClangCFlags is explicitly set to true",
+ clangCFlags: []string{"-a", "-b"},
+ BuildBrokenClangCFlags: true,
+ },
+ }
+
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ bp := fmt.Sprintf(`
+ cc_library {
+ name: "foo",
+ clang_cflags: %s,
+ }`, `["`+strings.Join(test.clangCFlags, `","`)+`"]`)
+
+ if test.err == "" {
+ android.GroupFixturePreparers(
+ prepareForCcTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ if test.BuildBrokenClangCFlags {
+ variables.BuildBrokenClangCFlags = test.BuildBrokenClangCFlags
+ }
+ }),
+ ).RunTestWithBp(t, bp)
+ } else {
+ prepareForCcTest.
+ ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(test.err)).
+ RunTestWithBp(t, bp)
+ }
+ })
+ }
+}
diff --git a/cc/compiler.go b/cc/compiler.go
index 3c904b8..a751754 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -441,12 +441,24 @@
// TODO: debug
flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Release.Cflags)...)
- CheckBadCompilerFlags(ctx, "clang_cflags", compiler.Properties.Clang_cflags)
- CheckBadCompilerFlags(ctx, "clang_asflags", compiler.Properties.Clang_asflags)
+ if !ctx.DeviceConfig().BuildBrokenClangCFlags() && len(compiler.Properties.Clang_cflags) != 0 {
+ ctx.PropertyErrorf("clang_cflags", "property is deprecated, see Changes.md file")
+ } else {
+ CheckBadCompilerFlags(ctx, "clang_cflags", compiler.Properties.Clang_cflags)
+ }
+ if !ctx.DeviceConfig().BuildBrokenClangAsFlags() && len(compiler.Properties.Clang_asflags) != 0 {
+ ctx.PropertyErrorf("clang_asflags", "property is deprecated, see Changes.md file")
+ } else {
+ CheckBadCompilerFlags(ctx, "clang_asflags", compiler.Properties.Clang_asflags)
+ }
flags.Local.CFlags = config.ClangFilterUnknownCflags(flags.Local.CFlags)
- flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Clang_cflags)...)
- flags.Local.AsFlags = append(flags.Local.AsFlags, esc(compiler.Properties.Clang_asflags)...)
+ if !ctx.DeviceConfig().BuildBrokenClangCFlags() {
+ flags.Local.CFlags = append(flags.Local.CFlags, esc(compiler.Properties.Clang_cflags)...)
+ }
+ if !ctx.DeviceConfig().BuildBrokenClangAsFlags() {
+ flags.Local.AsFlags = append(flags.Local.AsFlags, esc(compiler.Properties.Clang_asflags)...)
+ }
flags.Local.CppFlags = config.ClangFilterUnknownCflags(flags.Local.CppFlags)
flags.Local.ConlyFlags = config.ClangFilterUnknownCflags(flags.Local.ConlyFlags)
flags.Local.LdFlags = config.ClangFilterUnknownCflags(flags.Local.LdFlags)
@@ -565,7 +577,7 @@
flags.aidlFlags = append(flags.aidlFlags, includeDirsToFlags(rootAidlIncludeDirs))
}
- if Bool(compiler.Properties.Aidl.Generate_traces) {
+ if proptools.BoolDefault(compiler.Properties.Aidl.Generate_traces, true) {
flags.aidlFlags = append(flags.aidlFlags, "-t")
}
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/arm_device.go b/cc/config/arm_device.go
index d702c61..b53a097 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)
@@ -255,18 +250,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 +261,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 deebcaf..e6b9459 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -147,6 +147,11 @@
"-fdebug-info-for-profiling",
}
+ commonGlobalLldflags = []string{
+ "-fuse-ld=lld",
+ "-Wl,--icf=safe",
+ }
+
deviceGlobalCppflags = []string{
"-fvisibility-inlines-hidden",
}
@@ -164,13 +169,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{}
@@ -178,7 +179,7 @@
hostGlobalLdflags = []string{}
- hostGlobalLldflags = []string{"-fuse-ld=lld"}
+ hostGlobalLldflags = commonGlobalLldflags
commonGlobalCppflags = []string{
"-Wsign-promo",
@@ -241,6 +242,10 @@
"-Wno-error=unused-but-set-parameter", // http://b/197240255
// New warnings to be fixed after clang-r458507
"-Wno-error=unqualified-std-cast-call", // http://b/239662094
+ // New warnings to be fixed after clang-r468909
+ "-Wno-error=array-parameter", // http://b/241941550
+ "-Wno-error=deprecated-builtins", // http://b/241601211
+ "-Wno-error=deprecated", // in external/googletest/googletest
}
noOverrideExternalGlobalCflags = []string{
@@ -287,7 +292,12 @@
"-Wno-deprecated-non-prototype",
}
- llvmNextExtraCommonGlobalCflags = []string{}
+ 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
+ }
IllegalFlags = []string{
"-w",
@@ -300,17 +310,14 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r458507"
- ClangDefaultShortVersion = "15.0.1"
+ ClangDefaultVersion = "clang-r468909b"
+ ClangDefaultShortVersion = "15.0.3"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
"device/",
"vendor/",
}
-
- // Directories with warnings from Android.mk files.
- WarningAllowedOldProjects = []string{}
)
// BazelCcToolchainVars generates bzl file content containing variables for
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
new file mode 100644
index 0000000..825be7f
--- /dev/null
+++ b/cc/config/riscv64_device.go
@@ -0,0 +1,141 @@
+// 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",
+ "-Wl,-z,separate-code",
+ }
+
+ 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..ad205cf 100644
--- a/cc/config/tidy.go
+++ b/cc/config/tidy.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "regexp"
"strings"
)
@@ -57,17 +58,14 @@
)
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 != "" {
return override
}
checks := strings.Join([]string{
- "-*",
"android-*",
"bugprone-*",
"cert-*",
@@ -94,7 +92,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,28 +106,34 @@
// -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") {
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.
+ // 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.
pctx.VariableFunc("TidyExternalVendorChecks", func(ctx android.PackageVarContext) string {
if override := ctx.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",
}, ",")
})
@@ -201,11 +205,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.
@@ -237,3 +248,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..eb71aa1 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
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..96a53bf 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -66,13 +66,20 @@
"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, " "))
// Use the device gcc toolchain for now
- pctx.StaticVariable("LinuxBionicGccRoot", "${X86_64GccRoot}")
+ pctx.StaticVariable("LinuxBionicGccVersion", x86_64GccVersion)
+ pctx.SourcePathVariable("LinuxBionicGccRoot",
+ "prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${LinuxBionicGccVersion}")
}
type toolchainLinuxBionic struct {
@@ -84,18 +91,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 1b126de..740405e 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -109,7 +109,7 @@
}, "-l")
muslCrtBeginStaticBinary, muslCrtEndStaticBinary = []string{"libc_musl_crtbegin_static"}, []string{"libc_musl_crtend"}
- muslCrtBeginSharedBinary, muslCrtEndSharedBinary = []string{"libc_musl_crtbegin_dynamic", "musl_linker_script"}, []string{"libc_musl_crtend"}
+ muslCrtBeginSharedBinary, muslCrtEndSharedBinary = []string{"libc_musl_crtbegin_dynamic"}, []string{"libc_musl_crtend"}
muslCrtBeginSharedLibrary, muslCrtEndSharedLibrary = []string{"libc_musl_crtbegin_so"}, []string{"libc_musl_crtend_so"}
muslDefaultSharedLibraries = []string{"libc_musl"}
@@ -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..0fbe45c 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 {
@@ -142,13 +143,6 @@
return flags
}
-func UnstrippedOutputFile(module android.Module) android.Path {
- if mod, ok := module.(LinkableInterface); ok {
- return mod.UnstrippedOutputFile()
- }
- panic("UnstrippedOutputFile called on non-LinkableInterface module: " + module.Name())
-}
-
// IsValidSharedDependency takes a module and determines if it is a unique shared library
// that should be installed in the fuzz target output directories. This function
// returns true, unless:
@@ -270,22 +264,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 +393,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 +400,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 +472,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/gen.go b/cc/gen.go
index 08b49c9..dfbb177 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -229,6 +229,34 @@
return cppFile, headers.Paths()
}
+func bp2buildCcSysprop(ctx android.Bp2buildMutatorContext, moduleName string, minSdkVersion *string, srcs bazel.LabelListAttribute) *bazel.LabelAttribute {
+ labels := SyspropLibraryLabels{
+ SyspropLibraryLabel: moduleName + "_sysprop_library",
+ StaticLibraryLabel: moduleName + "_cc_sysprop_library_static",
+ }
+ Bp2buildSysprop(ctx, labels, srcs, minSdkVersion)
+ return createLabelAttributeCorrespondingToSrcs(":"+labels.StaticLibraryLabel, srcs)
+}
+
+// Creates a LabelAttribute for a given label where the value is only set for
+// the same config values that have values in a given LabelListAttribute
+func createLabelAttributeCorrespondingToSrcs(baseLabelName string, srcs bazel.LabelListAttribute) *bazel.LabelAttribute {
+ baseLabel := bazel.Label{Label: baseLabelName}
+ label := bazel.LabelAttribute{}
+ if !srcs.Value.IsNil() && !srcs.Value.IsEmpty() {
+ label.Value = &baseLabel
+ return &label
+ }
+ for axis, configToSrcs := range srcs.ConfigurableValues {
+ for config, val := range configToSrcs {
+ if !val.IsNil() && !val.IsEmpty() {
+ label.SetSelectValue(axis, config, baseLabel)
+ }
+ }
+ }
+ return &label
+}
+
// Used to communicate information from the genSources method back to the library code that uses
// it.
type generatedSourceInfo struct {
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 8804bbb..a590b22 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.
@@ -276,7 +277,8 @@
}
type ccAidlLibraryAttributes struct {
- Deps bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Implementation_dynamic_deps bazel.LabelListAttribute
}
type stripAttributes struct {
@@ -287,6 +289,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
@@ -339,14 +351,15 @@
Copts: *compilerAttrs.copts.Clone().Append(sharedAttrs.Copts),
Hdrs: *compilerAttrs.hdrs.Clone().Append(sharedAttrs.Hdrs),
- Deps: *linkerAttrs.deps.Clone().Append(sharedAttrs.Deps),
- Implementation_deps: *linkerAttrs.implementationDeps.Clone().Append(sharedAttrs.Implementation_deps),
- Dynamic_deps: *linkerAttrs.dynamicDeps.Clone().Append(sharedAttrs.Dynamic_deps),
- Implementation_dynamic_deps: *linkerAttrs.implementationDynamicDeps.Clone().Append(sharedAttrs.Implementation_dynamic_deps),
- Whole_archive_deps: *linkerAttrs.wholeArchiveDeps.Clone().Append(sharedAttrs.Whole_archive_deps),
- System_dynamic_deps: *linkerAttrs.systemDynamicDeps.Clone().Append(sharedAttrs.System_dynamic_deps),
- Runtime_deps: linkerAttrs.runtimeDeps,
- sdkAttributes: bp2BuildParseSdkAttributes(m),
+ Deps: *linkerAttrs.deps.Clone().Append(sharedAttrs.Deps),
+ Implementation_deps: *linkerAttrs.implementationDeps.Clone().Append(sharedAttrs.Implementation_deps),
+ Dynamic_deps: *linkerAttrs.dynamicDeps.Clone().Append(sharedAttrs.Dynamic_deps),
+ Implementation_dynamic_deps: *linkerAttrs.implementationDynamicDeps.Clone().Append(sharedAttrs.Implementation_dynamic_deps),
+ Whole_archive_deps: *linkerAttrs.wholeArchiveDeps.Clone().Append(sharedAttrs.Whole_archive_deps),
+ Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps,
+ System_dynamic_deps: *linkerAttrs.systemDynamicDeps.Clone().Append(sharedAttrs.System_dynamic_deps),
+ Runtime_deps: linkerAttrs.runtimeDeps,
+ sdkAttributes: bp2BuildParseSdkAttributes(m),
}
staticTargetAttrs := &bazelCcLibraryStaticAttributes{
@@ -366,7 +379,6 @@
Stl: compilerAttrs.stl,
Cpp_std: compilerAttrs.cppStd,
C_std: compilerAttrs.cStd,
- Use_version_lib: linkerAttrs.useVersionLib,
Features: baseAttributes.features,
}
@@ -393,13 +405,7 @@
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,
}
@@ -441,6 +447,10 @@
android.CommonAttributes{Name: m.Name()},
sharedTargetAttrs, sharedAttrs.Enabled)
+ createStubsBazelTargetIfNeeded(ctx, m, compilerAttrs, exportedIncludes, baseAttributes)
+}
+
+func createStubsBazelTargetIfNeeded(ctx android.TopDownMutatorContext, m *Module, compilerAttrs compilerAttributes, exportedIncludes BazelIncludes, baseAttributes baseAttributes) {
if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 {
stubSuitesProps := bazel.BazelTargetModuleProperties{
Rule_class: "cc_stub_suite",
@@ -461,6 +471,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
@@ -734,7 +885,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 {
@@ -1084,6 +1235,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)
@@ -2222,10 +2379,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",
@@ -2630,8 +2797,7 @@
attrs = &bazelCcLibraryStaticAttributes{
staticOrSharedAttributes: commonAttrs,
- Use_libcrt: linkerAttrs.useLibcrt,
- Use_version_lib: linkerAttrs.useVersionLib,
+ Use_libcrt: linkerAttrs.useLibcrt,
Rtti: compilerAttrs.rtti,
Stl: compilerAttrs.stl,
@@ -2677,13 +2843,7 @@
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,
@@ -2701,6 +2861,7 @@
modType = "cc_library_static"
} else {
modType = "cc_library_shared"
+ createStubsBazelTargetIfNeeded(ctx, module, compilerAttrs, exportedIncludes, baseAttributes)
}
props := bazel.BazelTargetModuleProperties{
Rule_class: modType,
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..1283d76 100644
--- a/cc/library_stub.go
+++ b/cc/library_stub.go
@@ -26,10 +26,6 @@
func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("cc_api_library", CcApiLibraryFactory)
ctx.RegisterModuleType("cc_api_headers", CcApiHeadersFactory)
-
- // 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)
}
// 'cc_api_library' is a module type which is from the exported API surface
@@ -169,136 +165,3 @@
// Stub from API surface should be available for any APEX.
return true
}
-
-func CcApiStubLibraryFactory() android.Module {
- module, decorator := NewLibrary(android.DeviceSupported)
- apiStubDecorator := &apiStubDecorator{
- libraryDecorator: decorator,
- }
- apiStubDecorator.BuildOnlyShared()
-
- module.compiler = apiStubDecorator
- module.linker = apiStubDecorator
- module.installer = nil
- module.library = apiStubDecorator
- module.Properties.HideFromMake = true // TODO: remove
-
- 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"`
-}
-
-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 contrib.properties.First_version == nil {
- ctx.PropertyErrorf("first_version", "%v does not have first_version for stub variants", ctx.ModuleName())
- }
-}
-
-// 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)
-}
-
-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}
- }
- return outputs
-}
-
-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}
-}
-*/
diff --git a/cc/library_stub_test.go b/cc/library_stub_test.go
index cd06172..288a34c 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
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 5d2fba0..1afa1dd 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -15,9 +15,9 @@
package cc
import (
- "github.com/google/blueprint/proptools"
-
"android/soong/android"
+
+ "github.com/google/blueprint/proptools"
)
// LTO (link-time optimization) allows the compiler to optimize and generate
@@ -49,9 +49,12 @@
// Dep properties indicate that this module needs to be built with LTO
// since it is an object dependency of an LTO module.
- FullDep bool `blueprint:"mutated"`
- ThinDep bool `blueprint:"mutated"`
- NoLtoDep bool `blueprint:"mutated"`
+ FullEnabled bool `blueprint:"mutated"`
+ ThinEnabled bool `blueprint:"mutated"`
+ NoLtoEnabled bool `blueprint:"mutated"`
+ FullDep bool `blueprint:"mutated"`
+ ThinDep bool `blueprint:"mutated"`
+ NoLtoDep bool `blueprint:"mutated"`
// Use clang lld instead of gnu ld.
Use_clang_lld *bool
@@ -70,7 +73,7 @@
func (lto *lto) begin(ctx BaseModuleContext) {
if ctx.Config().IsEnvTrue("DISABLE_LTO") {
- lto.Properties.Lto.Never = proptools.BoolPtr(true)
+ lto.Properties.NoLtoEnabled = true
}
}
@@ -88,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
@@ -101,6 +109,7 @@
}
flags.Local.CFlags = append(flags.Local.CFlags, ltoCFlag)
+ flags.Local.AsFlags = append(flags.Local.AsFlags, ltoCFlag)
flags.Local.LdFlags = append(flags.Local.LdFlags, ltoCFlag)
flags.Local.LdFlags = append(flags.Local.LdFlags, ltoLdFlag)
@@ -150,15 +159,15 @@
}
func (lto *lto) FullLTO() bool {
- return lto != nil && Bool(lto.Properties.Lto.Full)
+ return lto != nil && (proptools.Bool(lto.Properties.Lto.Full) || lto.Properties.FullEnabled)
}
func (lto *lto) ThinLTO() bool {
- return lto != nil && Bool(lto.Properties.Lto.Thin)
+ return lto != nil && (proptools.Bool(lto.Properties.Lto.Thin) || lto.Properties.ThinEnabled)
}
func (lto *lto) Never() bool {
- return lto != nil && Bool(lto.Properties.Lto.Never)
+ return lto != nil && (proptools.Bool(lto.Properties.Lto.Never) || lto.Properties.NoLtoEnabled)
}
func GlobalThinLTO(ctx android.BaseModuleContext) bool {
@@ -254,13 +263,13 @@
// LTO properties for dependencies
if name == "lto-full" {
- variation.lto.Properties.Lto.Full = proptools.BoolPtr(true)
+ variation.lto.Properties.FullEnabled = true
}
if name == "lto-thin" {
- variation.lto.Properties.Lto.Thin = proptools.BoolPtr(true)
+ variation.lto.Properties.ThinEnabled = true
}
if name == "lto-none" {
- variation.lto.Properties.Lto.Never = proptools.BoolPtr(true)
+ variation.lto.Properties.NoLtoEnabled = true
}
variation.Properties.PreventInstall = true
variation.Properties.HideFromMake = true
diff --git a/cc/lto_test.go b/cc/lto_test.go
new file mode 100644
index 0000000..b52f2b6
--- /dev/null
+++ b/cc/lto_test.go
@@ -0,0 +1,90 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cc
+
+import (
+ "android/soong/android"
+ "strings"
+ "testing"
+
+ "github.com/google/blueprint"
+)
+
+func TestThinLtoDeps(t *testing.T) {
+ bp := `
+ cc_library {
+ name: "lto_enabled",
+ srcs: ["src.c"],
+ static_libs: ["foo"],
+ shared_libs: ["bar"],
+ lto: {
+ thin: true,
+ }
+ }
+ cc_library {
+ name: "foo",
+ static_libs: ["baz"],
+ }
+ cc_library {
+ name: "bar",
+ static_libs: ["qux"],
+ }
+ cc_library {
+ name: "baz",
+ }
+ cc_library {
+ name: "qux",
+ }
+`
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ ).RunTestWithBp(t, bp)
+
+ libLto := result.ModuleForTests("lto_enabled", "android_arm64_armv8-a_shared").Module()
+ libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static_lto-thin").Module()
+ libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static_lto-thin").Module()
+
+ hasDep := func(m android.Module, wantDep android.Module) bool {
+ var found bool
+ result.VisitDirectDeps(m, func(dep blueprint.Module) {
+ if dep == wantDep {
+ found = true
+ }
+ })
+ return found
+ }
+
+ if !hasDep(libLto, libFoo) {
+ t.Errorf("'lto_enabled' missing dependency on thin lto variant of 'foo'")
+ }
+
+ if !hasDep(libFoo, libBaz) {
+ t.Errorf("'lto_enabled' missing dependency on thin lto variant of transitive dep 'baz'")
+ }
+
+ barVariants := result.ModuleVariantsForTests("bar")
+ for _, v := range barVariants {
+ if strings.Contains(v, "lto-thin") {
+ t.Errorf("Expected variants for 'bar' to not contain 'lto-thin', but found %q", v)
+ }
+ }
+ quxVariants := result.ModuleVariantsForTests("qux")
+ for _, v := range quxVariants {
+ if strings.Contains(v, "lto-thin") {
+ t.Errorf("Expected variants for 'qux' to not contain 'lto-thin', but found %q", v)
+ }
+ }
+}
diff --git a/cc/makevars.go b/cc/makevars.go
index 8154436..c70d4a6 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -53,7 +53,6 @@
func makeStringOfWarningAllowedProjects() string {
allProjects := append([]string{}, config.WarningAllowedProjects...)
- allProjects = append(allProjects, config.WarningAllowedOldProjects...)
sort.Strings(allProjects)
// Makefile rules use pattern "path/%" to match module paths.
if len(allProjects) > 0 {
@@ -315,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 5e06948..7354be9 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -147,16 +147,6 @@
}
}
-const (
- apiContributionSuffix = ".contribution"
-)
-
-// apiContributionTargetName returns the name of the cc_api(headers|contribution) bp2build target of ndk modules
-// A suffix is necessary to prevent a name collision with the base ndk_(library|header) target in the same bp2build bazel package
-func apiContributionTargetName(moduleName string) string {
- return moduleName + apiContributionSuffix
-}
-
// TODO(b/243196151): Populate `system` and `arch` metadata
type bazelCcApiHeadersAttributes struct {
Hdrs bazel.LabelListAttribute
@@ -179,11 +169,13 @@
Include_dir: include_dir,
}
ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: apiContributionTargetName(ctx.ModuleName()),
+ Name: android.ApiContributionTargetName(ctx.ModuleName()),
}, 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)
}
@@ -202,7 +194,6 @@
module := &headerModule{}
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
- android.InitBazelModule(module)
return module
}
@@ -273,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
@@ -329,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 e2b9682..49a919e 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -25,6 +25,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/bazel"
"android/soong/cc/config"
)
@@ -568,5 +569,43 @@
func NdkLibraryFactory() android.Module {
module := newStubLibrary()
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
+ android.InitBazelModule(module)
return module
}
+
+type bazelCcApiContributionAttributes struct {
+ Api bazel.LabelAttribute
+ Api_surfaces bazel.StringListAttribute
+ Hdrs bazel.LabelListAttribute
+ Library_name string
+}
+
+// Names of the cc_api_header targets in the bp2build workspace
+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, hdrLibs, addSuffix)
+}
+
+func ndkLibraryBp2build(ctx android.TopDownMutatorContext, m *Module) {
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_api_contribution",
+ Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl",
+ }
+ stubLibrary := m.compiler.(*stubDecorator)
+ attrs := &bazelCcApiContributionAttributes{
+ Library_name: stubLibrary.implementationModuleName(m.Name()),
+ Api_surfaces: bazel.MakeStringListAttribute(
+ []string{android.PublicApi.String()}),
+ }
+ if symbolFile := stubLibrary.properties.Symbol_file; symbolFile != nil {
+ apiLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(symbolFile)).Label
+ attrs.Api = *bazel.MakeLabelAttribute(apiLabel)
+ }
+ 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/object.go b/cc/object.go
index 65a11e0..1a96b72 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "strings"
"android/soong/android"
"android/soong/bazel"
@@ -254,22 +255,31 @@
var outputFile android.Path
builderFlags := flagsToBuilderFlags(flags)
+ outputName := ctx.ModuleName()
+ if !strings.HasSuffix(outputName, objectExtension) {
+ outputName += objectExtension
+ }
if len(objs.objFiles) == 1 && String(object.Properties.Linker_script) == "" {
- outputFile = objs.objFiles[0]
-
- if String(object.Properties.Prefix_symbols) != "" {
- output := android.PathForModuleOut(ctx, ctx.ModuleName()+objectExtension)
- transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), outputFile,
- builderFlags, output)
- outputFile = output
- }
- } else {
- output := android.PathForModuleOut(ctx, ctx.ModuleName()+objectExtension)
+ output := android.PathForModuleOut(ctx, outputName)
outputFile = output
if String(object.Properties.Prefix_symbols) != "" {
- input := android.PathForModuleOut(ctx, "unprefixed", ctx.ModuleName()+objectExtension)
+ transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), objs.objFiles[0],
+ builderFlags, output)
+ } else {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: objs.objFiles[0],
+ Output: output,
+ })
+ }
+ } else {
+ output := android.PathForModuleOut(ctx, outputName)
+ outputFile = output
+
+ if String(object.Properties.Prefix_symbols) != "" {
+ input := android.PathForModuleOut(ctx, "unprefixed", outputName)
transformBinaryPrefixSymbols(ctx, String(object.Properties.Prefix_symbols), input,
builderFlags, output)
output = input
diff --git a/cc/object_test.go b/cc/object_test.go
index 259a892..5359a35 100644
--- a/cc/object_test.go
+++ b/cc/object_test.go
@@ -15,6 +15,7 @@
package cc
import (
+ "fmt"
"testing"
"android/soong/android"
@@ -107,3 +108,65 @@
expectedOutputFiles := []string{"outputbase/execroot/__main__/bazel_out.o"}
android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
}
+
+func TestCcObjectOutputFile(t *testing.T) {
+ testcases := []struct {
+ name string
+ moduleName string
+ bp string
+ }{
+ {
+ name: "normal",
+ moduleName: "foo",
+ bp: `
+ srcs: ["bar.c"],
+ `,
+ },
+ {
+ name: "suffix",
+ moduleName: "foo.o",
+ bp: `
+ srcs: ["bar.c"],
+ `,
+ },
+ {
+ name: "keep symbols",
+ moduleName: "foo",
+ bp: `
+ srcs: ["bar.c"],
+ prefix_symbols: "foo_",
+ `,
+ },
+ {
+ name: "partial linking",
+ moduleName: "foo",
+ bp: `
+ srcs: ["bar.c", "baz.c"],
+ `,
+ },
+ {
+ name: "partial linking and prefix symbols",
+ moduleName: "foo",
+ bp: `
+ srcs: ["bar.c", "baz.c"],
+ prefix_symbols: "foo_",
+ `,
+ },
+ }
+
+ for _, testcase := range testcases {
+ bp := fmt.Sprintf(`
+ cc_object {
+ name: "%s",
+ %s
+ }
+ `, testcase.moduleName, testcase.bp)
+ t.Run(testcase.name, func(t *testing.T) {
+ ctx := PrepareForIntegrationTestWithCc.RunTestWithBp(t, bp)
+ android.AssertPathRelativeToTopEquals(t, "expected output file foo.o",
+ fmt.Sprintf("out/soong/.intermediates/%s/android_arm64_armv8-a/foo.o", testcase.moduleName),
+ ctx.ModuleForTests(testcase.moduleName, "android_arm64_armv8-a").Output("foo.o").Output)
+ })
+ }
+
+}
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/proto.go b/cc/proto.go
index 8e6d5ed..cf5ed04 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -178,7 +178,7 @@
var ret bp2buildProtoDeps
protoInfo, ok := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, protoSrcs)
- if !ok {
+ if !ok || protoInfo.Proto_libs.IsEmpty() {
return ret
}
@@ -201,9 +201,8 @@
dep := android.BazelLabelForModuleDepSingle(ctx, depName)
ret.protoDep = &bazel.LabelAttribute{Value: &dep}
- protoLabel := bazel.Label{Label: ":" + protoInfo.Name}
var protoAttrs protoAttributes
- protoAttrs.Deps.SetValue(bazel.LabelList{Includes: []bazel.Label{protoLabel}})
+ protoAttrs.Deps.SetValue(protoInfo.Proto_libs)
name := m.Name() + suffix
diff --git a/cc/sanitize.go b/cc/sanitize.go
index edff059..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.
@@ -714,8 +728,13 @@
if Bool(sanitize.Properties.Sanitize.Memtag_stack) {
flags.Local.CFlags = append(flags.Local.CFlags, memtagStackCommonFlags...)
+ // TODO(fmayer): remove -Wno-error once https://reviews.llvm.org/D127917 is in Android toolchain.
+ flags.Local.CFlags = append(flags.Local.CFlags, "-Wno-error=frame-larger-than")
flags.Local.AsFlags = append(flags.Local.AsFlags, memtagStackCommonFlags...)
flags.Local.LdFlags = append(flags.Local.LdFlags, memtagStackCommonFlags...)
+ // This works around LLD complaining about the stack frame size.
+ // TODO(fmayer): remove once https://reviews.llvm.org/D127917 is in Android toolchain.
+ flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--no-fatal-warnings")
}
if (Bool(sanitize.Properties.Sanitize.Memtag_heap) || Bool(sanitize.Properties.Sanitize.Memtag_stack)) && ctx.binary() {
@@ -876,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:
@@ -890,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:
@@ -1374,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) {
@@ -1398,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
}
}
@@ -1443,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/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/strip.go b/cc/strip.go
index c60e135..5c32d8b 100644
--- a/cc/strip.go
+++ b/cc/strip.go
@@ -56,7 +56,9 @@
forceEnable := Bool(stripper.StripProperties.Strip.All) ||
Bool(stripper.StripProperties.Strip.Keep_symbols) ||
Bool(stripper.StripProperties.Strip.Keep_symbols_and_debug_frame)
- return !forceDisable && (forceEnable || defaultEnable)
+ // create_minidebuginfo doesn't work for riscv64 yet, disable stripping for now
+ riscv64 := actx.Arch().ArchType == android.Riscv64
+ return !forceDisable && (forceEnable || defaultEnable) && !riscv64
}
// Keep this consistent with //build/bazel/rules/stripped_shared_library.bzl.
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/sysprop.go b/cc/sysprop.go
index f578b50..2b1e354 100644
--- a/cc/sysprop.go
+++ b/cc/sysprop.go
@@ -14,56 +14,58 @@
package cc
-// This file contains a map to redirect dependencies towards sysprop_library.
-// As sysprop_library has to support both Java and C++, sysprop_library internally
-// generates cc_library and java_library. For example, the following sysprop_library
-//
-// sysprop_library {
-// name: "foo",
-// }
-//
-// will internally generate with prefix "lib"
-//
-// cc_library {
-// name: "libfoo",
-// }
-//
-// When a cc module links against "foo", build system will redirect the
-// dependency to "libfoo". To do that, SyspropMutator gathers all sysprop_library,
-// records their cc implementation library names to a map. The map will be used in
-// cc.Module.DepsMutator.
-
import (
- "sync"
-
"android/soong/android"
+ "android/soong/bazel"
)
-type syspropLibraryInterface interface {
- BaseModuleName() string
- CcImplementationModuleName() string
+// TODO(b/240463568): Additional properties will be added for API validation
+type bazelSyspropLibraryAttributes struct {
+ Srcs bazel.LabelListAttribute
}
-var (
- syspropImplLibrariesKey = android.NewOnceKey("syspropImplLibirares")
- syspropImplLibrariesLock sync.Mutex
-)
-
-func syspropImplLibraries(config android.Config) map[string]string {
- return config.Once(syspropImplLibrariesKey, func() interface{} {
- return make(map[string]string)
- }).(map[string]string)
+type bazelCcSyspropLibraryAttributes struct {
+ Dep bazel.LabelAttribute
+ Min_sdk_version *string
}
-// gather list of sysprop libraries
-func SyspropMutator(mctx android.BottomUpMutatorContext) {
- if m, ok := mctx.Module().(syspropLibraryInterface); ok {
- syspropImplLibraries := syspropImplLibraries(mctx.Config())
- syspropImplLibrariesLock.Lock()
- defer syspropImplLibrariesLock.Unlock()
+type SyspropLibraryLabels struct {
+ SyspropLibraryLabel string
+ SharedLibraryLabel string
+ StaticLibraryLabel string
+}
- // BaseModuleName is the name of sysprop_library
- // CcImplementationModuleName is the name of cc_library generated by sysprop_library
- syspropImplLibraries[m.BaseModuleName()] = m.CcImplementationModuleName()
+func Bp2buildSysprop(ctx android.Bp2buildMutatorContext, labels SyspropLibraryLabels, srcs bazel.LabelListAttribute, minSdkVersion *string) {
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "sysprop_library",
+ Bzl_load_location: "//build/bazel/rules/sysprop:sysprop_library.bzl",
+ },
+ android.CommonAttributes{Name: labels.SyspropLibraryLabel},
+ &bazelSyspropLibraryAttributes{
+ Srcs: srcs,
+ })
+
+ attrs := &bazelCcSyspropLibraryAttributes{
+ Dep: *bazel.MakeLabelAttribute(":" + labels.SyspropLibraryLabel),
+ Min_sdk_version: minSdkVersion,
}
+
+ if labels.SharedLibraryLabel != "" {
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_sysprop_library_shared",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_sysprop_library.bzl",
+ },
+ android.CommonAttributes{Name: labels.SharedLibraryLabel},
+ attrs)
+ }
+
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_sysprop_library_static",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_sysprop_library.bzl",
+ },
+ android.CommonAttributes{Name: labels.StaticLibraryLabel},
+ attrs)
}
diff --git a/cc/test.go b/cc/test.go
index 28a0e5e..715c537 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -659,6 +659,7 @@
testBinaryAttrs.binaryAttributes = binaryBp2buildAttrs(ctx, m)
var data bazel.LabelListAttribute
+ var tags bazel.StringListAttribute
testBinaryProps := m.GetArchVariantProperties(ctx, &TestBinaryProperties{})
for axis, configToProps := range testBinaryProps {
@@ -670,6 +671,7 @@
combinedData.Append(android.BazelLabelForModuleDeps(ctx, p.Data_bins))
combinedData.Append(android.BazelLabelForModuleDeps(ctx, p.Data_libs))
data.SetSelectValue(axis, config, combinedData)
+ tags.SetSelectValue(axis, config, p.Test_options.Tags)
}
}
}
@@ -690,6 +692,7 @@
android.CommonAttributes{
Name: m.Name(),
Data: data,
+ Tags: tags,
},
&testBinaryAttrs)
}
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..810d089 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -76,9 +76,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.
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 1cf64de..c420567 100644
--- a/cmd/extract_apks/main.go
+++ b/cmd/extract_apks/main.go
@@ -29,6 +29,7 @@
"google.golang.org/protobuf/proto"
+ "android/soong/cmd/extract_apks/bundle_proto"
android_bundle_proto "android/soong/cmd/extract_apks/bundle_proto"
"android/soong/third_party/zip"
)
@@ -75,7 +76,7 @@
return nil, err
}
bytes := make([]byte, tocFile.FileHeader.UncompressedSize64)
- if _, err := rc.Read(bytes); err != io.EOF {
+ if _, err := rc.Read(bytes); err != nil && err != io.EOF {
return nil, err
}
rc.Close()
@@ -197,6 +198,49 @@
*android_bundle_proto.MultiAbiTargeting
}
+type multiAbiValue []*bundle_proto.Abi
+
+func (m multiAbiValue) compare(other multiAbiValue) int {
+ min := func(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+ }
+
+ sortAbis := func(abiSlice multiAbiValue) func(i, j int) bool {
+ return func(i, j int) bool {
+ // sort priorities greatest to least
+ return multiAbiPriorities[abiSlice[i].Alias] > multiAbiPriorities[abiSlice[j].Alias]
+ }
+ }
+
+ m = append(multiAbiValue{}, m...)
+ sort.Slice(m, sortAbis(m))
+ other = append(multiAbiValue{}, other...)
+ sort.Slice(other, sortAbis(other))
+
+ for i := 0; i < min(len(m), len(other)); i++ {
+ if multiAbiPriorities[m[i].Alias] > multiAbiPriorities[other[i].Alias] {
+ return 1
+ }
+ if multiAbiPriorities[m[i].Alias] < multiAbiPriorities[other[i].Alias] {
+ return -1
+ }
+ }
+
+ if len(m) == len(other) {
+ return 0
+ }
+ if len(m) > len(other) {
+ return 1
+ }
+ return -1
+}
+
+// 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 {
if t.MultiAbiTargeting == nil {
return true
@@ -204,31 +248,45 @@
if _, ok := config.abis[android_bundle_proto.Abi_UNSPECIFIED_CPU_ARCHITECTURE]; ok {
return true
}
- // Find the one with the highest priority.
- highestPriority := 0
- for _, v := range t.GetValue() {
- for _, a := range v.GetAbi() {
- if _, ok := config.abis[a.Alias]; ok {
- if highestPriority < multiAbiPriorities[a.Alias] {
- highestPriority = multiAbiPriorities[a.Alias]
- }
+
+ multiAbiIsValid := func(m multiAbiValue) bool {
+ for _, abi := range m {
+ if _, ok := config.abis[abi.Alias]; !ok {
+ return false
}
}
+ return true
}
- if highestPriority == 0 {
+
+ // ensure that the current value is valid for our config
+ valueSetContainsViableAbi := false
+ multiAbiSet := t.GetValue()
+ for _, multiAbi := range multiAbiSet {
+ if multiAbiIsValid(multiAbi.GetAbi()) {
+ valueSetContainsViableAbi = true
+ }
+ }
+
+ if !valueSetContainsViableAbi {
return false
}
+
// See if there are any matching alternatives with a higher priority.
- for _, v := range t.GetAlternatives() {
- for _, a := range v.GetAbi() {
- if _, ok := config.abis[a.Alias]; ok {
- if highestPriority < multiAbiPriorities[a.Alias] {
- // There's a better one. Skip this one.
- return false
- }
+ for _, altMultiAbi := range t.GetAlternatives() {
+ if !multiAbiIsValid(altMultiAbi.GetAbi()) {
+ continue
+ }
+
+ for _, multiAbi := range multiAbiSet {
+ valueAbis := multiAbiValue(multiAbi.GetAbi())
+ altAbis := multiAbiValue(altMultiAbi.GetAbi())
+ if valueAbis.compare(altAbis) < 0 {
+ // An alternative has a higher priority, don't use this one
+ return false
}
}
}
+
return true
}
diff --git a/cmd/extract_apks/main_test.go b/cmd/extract_apks/main_test.go
index f5e4046..c1d712d 100644
--- a/cmd/extract_apks/main_test.go
+++ b/cmd/extract_apks/main_test.go
@@ -420,6 +420,370 @@
}
}
+func TestSelectApks_ApexSet_Variants(t *testing.T) {
+ testCases := []testDesc{
+ {
+ protoText: `
+variant {
+ targeting {
+ sdk_version_targeting {value {min {value: 29}}}
+ multi_abi_targeting {
+ value {abi {alias: ARMEABI_V7A}}
+ alternatives {
+ abi {alias: ARMEABI_V7A}
+ abi {alias: ARM64_V8A}
+ }
+ alternatives {abi {alias: ARM64_V8A}}
+ alternatives {abi {alias: X86}}
+ alternatives {
+ abi {alias: X86}
+ abi {alias: X86_64}
+ }
+ }
+ }
+ apk_set {
+ module_metadata {
+ name: "base"
+ delivery_type: INSTALL_TIME
+ }
+ apk_description {
+ targeting {
+ multi_abi_targeting {
+ value {abi {alias: ARMEABI_V7A}}
+ alternatives {
+ abi {alias: ARMEABI_V7A}
+ abi {alias: ARM64_V8A}
+ }
+ alternatives {abi {alias: ARM64_V8A}}
+ alternatives {abi {alias: X86}}
+ alternatives {
+ abi {alias: X86}
+ abi {alias: X86_64}
+ }
+ }
+ }
+ path: "standalones/standalone-armeabi_v7a.apex"
+ }
+ }
+ variant_number: 0
+}
+variant {
+ targeting {
+ sdk_version_targeting {value {min {value: 29}}}
+ multi_abi_targeting {
+ value {abi {alias: ARM64_V8A}}
+ alternatives {abi {alias: ARMEABI_V7A}}
+ alternatives {
+ abi {alias: ARMEABI_V7A}
+ abi {alias: ARM64_V8A}
+ }
+ alternatives {abi {alias: X86}}
+ alternatives {
+ abi {alias: X86}
+ abi {alias: X86_64}
+ }
+ }
+ }
+ apk_set {
+ module_metadata {
+ name: "base"
+ delivery_type: INSTALL_TIME
+ }
+ apk_description {
+ targeting {
+ multi_abi_targeting {
+ value {abi {alias: ARM64_V8A}}
+ alternatives {abi {alias: ARMEABI_V7A}}
+ alternatives {
+ abi {alias: ARMEABI_V7A}
+ abi {alias: ARM64_V8A}
+ }
+ alternatives {abi {alias: X86}}
+ alternatives {
+ abi {alias: X86}
+ abi {alias: X86_64}
+ }
+ }
+ }
+ path: "standalones/standalone-arm64_v8a.apex"
+ }
+ }
+ variant_number: 1
+}
+variant {
+ targeting {
+ sdk_version_targeting {value {min {value: 29}}}
+ multi_abi_targeting {
+ value {
+ abi {alias: ARMEABI_V7A}
+ abi {alias: ARM64_V8A}
+ }
+ alternatives {abi {alias: ARMEABI_V7A}}
+ alternatives {abi {alias: ARM64_V8A}}
+ alternatives {abi {alias: X86}}
+ alternatives {
+ abi {alias: X86}
+ abi {alias: X86_64}
+ }
+ }
+ }
+ apk_set {
+ module_metadata {
+ name: "base"
+ delivery_type: INSTALL_TIME
+ }
+ apk_description {
+ targeting {
+ multi_abi_targeting {
+ value {
+ abi {alias: ARMEABI_V7A}
+ abi {alias: ARM64_V8A}
+ }
+ alternatives {abi {alias: ARMEABI_V7A}}
+ alternatives {abi {alias: ARM64_V8A}}
+ alternatives {abi {alias: X86}}
+ alternatives {
+ abi {alias: X86}
+ abi {alias: X86_64}
+ }
+ }
+ }
+ path: "standalones/standalone-armeabi_v7a.arm64_v8a.apex"
+ }
+ }
+ variant_number: 2
+}
+variant {
+ targeting {
+ sdk_version_targeting {value {min {value: 29}}}
+ multi_abi_targeting {
+ value {abi {alias: X86}}
+ alternatives {abi {alias: ARMEABI_V7A}}
+ alternatives {
+ abi {alias: ARMEABI_V7A}
+ abi {alias: ARM64_V8A}
+ }
+ alternatives {abi {alias: ARM64_V8A}}
+ alternatives {
+ abi {alias: X86}
+ abi {alias: X86_64}
+ }
+ }
+ }
+ apk_set {
+ module_metadata {
+ name: "base"
+ delivery_type: INSTALL_TIME
+ }
+ apk_description {
+ targeting {
+ multi_abi_targeting {
+ value {abi {alias: X86}}
+ alternatives {abi {alias: ARMEABI_V7A}}
+ alternatives {
+ abi {alias: ARMEABI_V7A}
+ abi {alias: ARM64_V8A}
+ }
+ alternatives {abi {alias: ARM64_V8A}}
+ alternatives {
+ abi {alias: X86}
+ abi {alias: X86_64}
+ }
+ }
+ }
+ path: "standalones/standalone-x86.apex"
+ }
+ }
+ variant_number: 3
+}
+variant {
+ targeting {
+ sdk_version_targeting {value {min {value: 29}}}
+ multi_abi_targeting {
+ value {
+ abi {alias: X86}
+ abi {alias: X86_64}
+ }
+ alternatives {abi {alias: ARMEABI_V7A}}
+ alternatives {
+ abi {alias: ARMEABI_V7A}
+ abi {alias: ARM64_V8A}
+ }
+ alternatives {abi {alias: ARM64_V8A}}
+ alternatives {abi {alias: X86}}
+ }
+ }
+ apk_set {
+ module_metadata {
+ name: "base"
+ delivery_type: INSTALL_TIME
+ }
+ apk_description {
+ targeting {
+ multi_abi_targeting {
+ value {
+ abi {alias: X86}
+ abi {alias: X86_64}
+ }
+ alternatives {abi {alias: ARMEABI_V7A}}
+ alternatives {
+ abi {alias: ARMEABI_V7A}
+ abi {alias: ARM64_V8A}
+ }
+ alternatives {abi {alias: ARM64_V8A}}
+ alternatives {abi {alias: X86}}
+ }
+ }
+ path: "standalones/standalone-x86.x86_64.apex"
+ }
+ }
+ variant_number: 4
+}
+`,
+ configs: []testConfigDesc{
+ {
+ name: "multi-variant multi-target ARM",
+ targetConfig: TargetConfig{
+ sdkVersion: 33,
+ screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
+ bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
+ },
+ abis: map[bp.Abi_AbiAlias]int{
+ bp.Abi_ARM64_V8A: 0,
+ bp.Abi_ARMEABI_V7A: 1,
+ },
+ },
+ expected: SelectionResult{
+ "base",
+ []string{
+ "standalones/standalone-armeabi_v7a.arm64_v8a.apex",
+ },
+ },
+ },
+ {
+ name: "multi-variant single-target arm",
+ targetConfig: TargetConfig{
+ sdkVersion: 33,
+ screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
+ bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
+ },
+ abis: map[bp.Abi_AbiAlias]int{
+ bp.Abi_ARMEABI_V7A: 0,
+ },
+ },
+ expected: SelectionResult{
+ "base",
+ []string{
+ "standalones/standalone-armeabi_v7a.apex",
+ },
+ },
+ },
+ {
+ name: "multi-variant single-target arm64",
+ targetConfig: TargetConfig{
+ sdkVersion: 33,
+ screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
+ bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
+ },
+ abis: map[bp.Abi_AbiAlias]int{
+ bp.Abi_ARM64_V8A: 0,
+ },
+ },
+ expected: SelectionResult{
+ "base",
+ []string{
+ "standalones/standalone-arm64_v8a.apex",
+ },
+ },
+ },
+ {
+ name: "multi-variant multi-target x86",
+ targetConfig: TargetConfig{
+ sdkVersion: 33,
+ screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
+ bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
+ },
+ abis: map[bp.Abi_AbiAlias]int{
+ bp.Abi_X86: 0,
+ bp.Abi_X86_64: 1,
+ },
+ },
+ expected: SelectionResult{
+ "base",
+ []string{
+ "standalones/standalone-x86.x86_64.apex",
+ },
+ },
+ },
+ {
+ name: "multi-variant single-target x86",
+ targetConfig: TargetConfig{
+ sdkVersion: 33,
+ screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
+ bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
+ },
+ abis: map[bp.Abi_AbiAlias]int{
+ bp.Abi_X86: 0,
+ },
+ },
+ expected: SelectionResult{
+ "base",
+ []string{
+ "standalones/standalone-x86.apex",
+ },
+ },
+ },
+ {
+ name: "multi-variant single-target x86_64",
+ targetConfig: TargetConfig{
+ sdkVersion: 33,
+ screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
+ bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
+ },
+ abis: map[bp.Abi_AbiAlias]int{
+ bp.Abi_X86_64: 0,
+ },
+ },
+ expected: SelectionResult{},
+ },
+ {
+ name: "multi-variant multi-target cross-target",
+ targetConfig: TargetConfig{
+ sdkVersion: 33,
+ screenDpi: map[bp.ScreenDensity_DensityAlias]bool{
+ bp.ScreenDensity_DENSITY_UNSPECIFIED: true,
+ },
+ abis: map[bp.Abi_AbiAlias]int{
+ bp.Abi_ARM64_V8A: 0,
+ bp.Abi_X86_64: 1,
+ },
+ },
+ expected: SelectionResult{
+ "base",
+ []string{
+ "standalones/standalone-arm64_v8a.apex",
+ },
+ },
+ },
+ },
+ },
+ }
+ for _, testCase := range testCases {
+ var toc bp.BuildApksResult
+ if err := prototext.Unmarshal([]byte(testCase.protoText), &toc); err != nil {
+ t.Fatal(err)
+ }
+ for _, config := range testCase.configs {
+ t.Run(config.name, func(t *testing.T) {
+ actual := selectApks(&toc, config.targetConfig)
+ if !reflect.DeepEqual(config.expected, actual) {
+ t.Errorf("expected %v, got %v", config.expected, actual)
+ }
+ })
+ }
+ }
+}
+
type testZip2ZipWriter struct {
entries map[string]string
}
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..0ba25c8 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -24,6 +24,7 @@
"time"
"android/soong/android"
+ "android/soong/bazel"
"android/soong/bp2build"
"android/soong/shared"
"android/soong/ui/metrics/bp2build_metrics_proto"
@@ -48,11 +49,12 @@
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
cmdlineArgs bootstrap.Args
)
@@ -81,6 +83,7 @@
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(&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")
@@ -129,6 +132,8 @@
buildMode = android.Bp2build
} else if bazelQueryViewDir != "" {
buildMode = android.GenerateQueryView
+ } else if bazelApiBp2buildDir != "" {
+ buildMode = android.ApiBp2build
} else if moduleGraphFile != "" {
buildMode = android.GenerateModuleGraph
} else if docFile != "" {
@@ -162,10 +167,15 @@
return configuration.BazelContext.InvokeBazel(configuration)
}
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...)
@@ -178,7 +188,7 @@
defer ctx.EventHandler.End("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,6 +196,96 @@
touch(shared.JoinPath(topDir, queryviewMarker))
}
+// 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, extraNinjaDeps []string) string {
+ // Create a new context and register mutators that are only meaningful to API export
+ ctx := android.NewContext(configuration)
+ ctx.EventHandler.Begin("api_bp2build")
+ defer ctx.EventHandler.End("api_bp2build")
+ ctx.SetNameInterface(newNameResolver(configuration))
+ 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.CodegenMetrics{})
+ 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()...)
+
+ // Create the symlink forest
+ symlinkDeps := bp2build.PlantSymlinkForest(
+ configuration,
+ 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, "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")
@@ -248,6 +348,8 @@
return bp2buildMarker
} else if configuration.IsMixedBuildsEnabled() {
runMixedModeBuild(configuration, ctx, extraNinjaDeps)
+ } else if configuration.BuildMode == android.ApiBp2build {
+ return runApiBp2build(configuration, extraNinjaDeps)
} else {
var stopBefore bootstrap.StopBefore
if configuration.BuildMode == android.GenerateModuleGraph {
@@ -476,12 +578,22 @@
return files, nil
}
+func bazelArtifacts() []string {
+ return []string{
+ "bazel-bin",
+ "bazel-genfiles",
+ "bazel-out",
+ "bazel-testlogs",
+ "bazel-" + filepath.Base(topDir),
+ }
+}
+
// 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) {
+ var codegenMetrics bp2build.CodegenMetrics
eventHandler := metrics.EventHandler{}
- var metrics bp2build.CodegenMetrics
eventHandler.Do("bp2build", func() {
// Register an alternate set of singletons and mutators for bazel
@@ -494,43 +606,43 @@
bp2buildCtx.SetNameInterface(newNameResolver(configuration))
bp2buildCtx.RegisterForBazelConversion()
+ var ninjaDeps []string
+ ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
+
// 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 {
+ if modulePaths, err := bp2buildCtx.ListModulePaths("."); err != nil {
panic(err)
+ } else {
+ ninjaDeps = append(ninjaDeps, modulePaths...)
}
- extraNinjaDeps = append(extraNinjaDeps, modulePaths...)
-
// 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...)
+ eventHandler.Do("bootstrap", func() {
+ blueprintArgs := cmdlineArgs
+ bootstrapDeps := bootstrap.RunBlueprint(blueprintArgs, bootstrap.StopBeforePrepareBuildActions, bp2buildCtx.Context, configuration)
+ ninjaDeps = append(ninjaDeps, bootstrapDeps...)
+ })
globListFiles := writeBuildGlobsNinjaFile(bp2buildCtx, 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.
+ // and print conversion codegenMetrics to the user.
codegenContext := bp2build.NewCodegenContext(configuration, *bp2buildCtx, bp2build.Bp2Build)
- metrics = bp2build.Codegen(codegenContext)
+ eventHandler.Do("codegen", func() {
+ codegenMetrics = 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),
- }
+ excludes := bazelArtifacts()
if outDir[0] != '/' {
excludes = append(excludes, outDir)
@@ -547,11 +659,17 @@
excludes = append(excludes, getTemporaryExcludes()...)
- symlinkForestDeps := bp2build.PlantSymlinkForest(
- configuration, topDir, workspaceRoot, generatedRoot, ".", excludes)
+ // 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.
+ eventHandler.Do("symlink_forest", func() {
+ symlinkForestDeps := bp2build.PlantSymlinkForest(
+ configuration, topDir, workspaceRoot, generatedRoot, ".", excludes)
+ ninjaDeps = append(ninjaDeps, symlinkForestDeps...)
+ })
ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
- ninjaDeps = append(ninjaDeps, symlinkForestDeps...)
writeDepFile(bp2buildMarker, eventHandler, ninjaDeps)
@@ -563,9 +681,9 @@
// 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, configuration, eventHandler)
}
// Write Bp2Build metrics into $LOG_DIR
@@ -586,3 +704,14 @@
}
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..cd1d6fb 100644
--- a/cmd/soong_build/queryview.go
+++ b/cmd/soong_build/queryview.go
@@ -23,8 +23,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 +34,9 @@
}
filesToWrite := bp2build.CreateBazelFiles(ctx.Config(), ruleShims, res.BuildDirToTargets(),
- bp2build.QueryView)
+ ctx.Mode())
for _, f := range filesToWrite {
- if err := writeReadOnlyFile(bazelQueryViewDir, f); err != nil {
+ if err := writeReadOnlyFile(outDir, f); err != nil {
return err
}
}
diff --git a/cmd/zip2zip/BUILD.bazel b/cmd/zip2zip/BUILD.bazel
new file mode 100644
index 0000000..1915a2d
--- /dev/null
+++ b/cmd/zip2zip/BUILD.bazel
@@ -0,0 +1,18 @@
+# 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.
+
+alias(
+ name = "zip2zip",
+ actual = "//prebuilts/build-tools:linux-x86/bin/zip2zip",
+)
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/dexpreopt.go b/dexpreopt/dexpreopt.go
index d8011d6..fdfd22e 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -201,6 +201,11 @@
if apex := global.AllApexSystemServerJars(ctx).ApexOfJar(lib); apex != "" {
return fmt.Sprintf("/apex/%s/javalib/%s.jar", apex, lib)
}
+
+ if apex := global.AllPlatformSystemServerJars(ctx).ApexOfJar(lib); apex == "system_ext" {
+ return fmt.Sprintf("/system_ext/framework/%s.jar", lib)
+ }
+
return fmt.Sprintf("/system/framework/%s.jar", lib)
}
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 07e4fad..429b5ff 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -59,6 +59,15 @@
android.PathForOutput(ctx, fmt.Sprintf("%s/enforce_uses_libraries.status", name)))
}
+func testSystemExtSystemServerModuleConfig(ctx android.PathContext, name string) *ModuleConfig {
+ return createTestModuleConfig(
+ name,
+ fmt.Sprintf("/system_ext/framework/%s.jar", name),
+ android.PathForOutput(ctx, fmt.Sprintf("%s/dexpreopt/%s.jar", name, name)),
+ android.PathForOutput(ctx, fmt.Sprintf("%s/aligned/%s.jar", name, name)),
+ android.PathForOutput(ctx, fmt.Sprintf("%s/enforce_uses_libraries.status", name)))
+}
+
func createTestModuleConfig(name, dexLocation string, buildPath, dexPath, enforceUsesLibrariesStatusFile android.OutputPath) *ModuleConfig {
return &ModuleConfig{
Name: name,
@@ -213,6 +222,29 @@
android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String())
}
+func TestDexPreoptSystemExtSystemServerJars(t *testing.T) {
+ config := android.TestConfig("out", nil, "", nil)
+ ctx := android.BuilderContextForTesting(config)
+ globalSoong := globalSoongConfigForTests()
+ global := GlobalConfigForTests(ctx)
+ module := testSystemExtSystemServerModuleConfig(ctx, "service-A")
+
+ global.StandaloneSystemServerJars = android.CreateTestConfiguredJarList(
+ []string{"system_ext:service-A"})
+
+ rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ wantInstalls := android.RuleBuilderInstalls{
+ {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.odex"), "/system_ext/framework/oat/arm/service-A.odex"},
+ {android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.vdex"), "/system_ext/framework/oat/arm/service-A.vdex"},
+ }
+
+ android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String())
+}
+
func TestDexPreoptApexStandaloneSystemServerJars(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
diff --git a/docs/perf.md b/docs/perf.md
index 86a27b4..694dcf1 100644
--- a/docs/perf.md
+++ b/docs/perf.md
@@ -221,6 +221,18 @@
various .ninja files. The files are (mostly) human-readable, but a (slow) web
interface can be used by running `NINJA_ARGS="-t browse <target>" m`.
+There is also `SOONG_UI_NINJA_ARGS`, which passes ninja arguments to soong ui's
+ninja invocations, e.g. to emit $OUT_DIR/soong/build.ninja, $OUT_DIR/soong/module-graph.json, etc.
+
+```bash
+$ m nothing
+$ touch Android.bp
+$ SOONG_UI_NINJA_ARGS="-d explain" m nothing
+...
+ninja explain: restat of output out/soong/build.ninja older than most recent input Android.bp
+...
+```
+
#### Builds take a long time
If the long part in the trace view of a build is a relatively solid block, then
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index b2361ce..baad58e 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -31,6 +31,7 @@
"encoding/json"
"fmt"
"path/filepath"
+ "reflect"
"strings"
"github.com/google/blueprint/proptools"
@@ -295,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
@@ -677,9 +688,10 @@
Filename_from_src bazel.BoolAttribute
}
-// ConvertWithBp2build performs bp2build conversion of PrebuiltEtc
-// All prebuilt_* modules are PrebuiltEtc, which we treat uniformily as *PrebuiltFile*
-func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+// Bp2buildHelper returns a bazelPrebuiltFileAttributes used for the conversion
+// of prebuilt_* modules. bazelPrebuiltFileAttributes has the common attributes
+// used by both prebuilt_etc_xml and other prebuilt_* moodules
+func (module *PrebuiltEtc) Bp2buildHelper(ctx android.TopDownMutatorContext) *bazelPrebuiltFileAttributes {
var src bazel.LabelAttribute
for axis, configToProps := range module.GetArchVariantProperties(ctx, &prebuiltEtcProperties{}) {
for config, p := range configToProps {
@@ -692,6 +704,22 @@
src.SetSelectValue(axis, config, label)
}
}
+
+ for propName, productConfigProps := range android.ProductVariableProperties(ctx) {
+ for configProp, propVal := range productConfigProps {
+ if propName == "Src" {
+ props, ok := propVal.(*string)
+ if !ok {
+ ctx.PropertyErrorf(" Expected Property to have type string, but was %s\n", reflect.TypeOf(propVal).String())
+ continue
+ }
+ if props != nil {
+ label := android.BazelLabelForModuleSrcSingle(ctx, *props)
+ src.SetSelectValue(configProp.ConfigurationAxis(), configProp.SelectKey(), label)
+ }
+ }
+ }
+ }
}
var filename string
@@ -710,10 +738,6 @@
}
var dir = module.installDirBase
- // prebuilt_file supports only `etc` or `usr/share`
- if !(dir == "etc" || dir == "usr/share") {
- return
- }
if subDir := module.subdirProperties.Sub_dir; subDir != nil {
dir = dir + "/" + *subDir
}
@@ -735,6 +759,22 @@
attrs.Filename_from_src = bazel.BoolAttribute{Value: moduleProps.Filename_from_src}
}
+ return attrs
+
+}
+
+// ConvertWithBp2build performs bp2build conversion of PrebuiltEtc
+// prebuilt_* modules (except prebuilt_etc_xml) are PrebuiltEtc,
+// which we treat as *PrebuiltFile*
+func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ var dir = module.installDirBase
+ // prebuilt_file supports only `etc` or `usr/share`
+ if !(dir == "etc" || dir == "usr/share") {
+ return
+ }
+
+ attrs := module.Bp2buildHelper(ctx)
+
props := bazel.BazelTargetModuleProperties{
Rule_class: "prebuilt_file",
Bzl_load_location: "//build/bazel/rules:prebuilt_file.bzl",
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/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 7a0dac3..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
@@ -909,12 +925,7 @@
cmd = strings.Replace(*m.properties.Cmd, "$(in)", "$(SRCS)", -1)
cmd = strings.Replace(cmd, "$(out)", "$(OUTS)", -1)
}
-
- genDir := "$(GENDIR)"
- if t := ctx.ModuleType(); t == "cc_genrule" || t == "java_genrule" || t == "java_genrule_host" {
- genDir = "$(RULEDIR)"
- }
- cmd = strings.Replace(cmd, "$(genDir)", genDir, -1)
+ cmd = strings.Replace(cmd, "$(genDir)", "$(RULEDIR)", -1)
if len(tools.Value.Includes) > 0 {
cmd = strings.Replace(cmd, "$(location)", fmt.Sprintf("$(location %s)", tools.Value.Includes[0].Label), -1)
cmd = strings.Replace(cmd, "$(locations)", fmt.Sprintf("$(locations %s)", tools.Value.Includes[0].Label), -1)
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index cd941cc..63f8fa9 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -790,6 +790,94 @@
result.ModuleForTests("gen_all", "").Module().(*useSource).srcs)
}
+func TestGenSrcsWithNonRootAndroidBpOutputFiles(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForGenRuleTest,
+ android.FixtureMergeMockFs(android.MockFS{
+ "external-protos/path/Android.bp": []byte(`
+ filegroup {
+ name: "external-protos",
+ srcs: ["baz/baz.proto", "bar.proto"],
+ }
+ `),
+ "package-dir/Android.bp": []byte(`
+ gensrcs {
+ name: "module-name",
+ cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
+ srcs: [
+ "src/foo.proto",
+ ":external-protos",
+ ],
+ output_extension: "proto.h",
+ }
+ `),
+ }),
+ ).RunTest(t)
+
+ exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs"
+ gen := result.Module("module-name", "").(*Module)
+
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "include path",
+ []string{exportedIncludeDir},
+ gen.exportedIncludeDirs,
+ )
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "files",
+ []string{
+ exportedIncludeDir + "/package-dir/src/foo.proto.h",
+ exportedIncludeDir + "/external-protos/path/baz/baz.proto.h",
+ exportedIncludeDir + "/external-protos/path/bar.proto.h",
+ },
+ gen.outputFiles,
+ )
+}
+
+func TestGenSrcsWithSrcsFromExternalPackage(t *testing.T) {
+ bp := `
+ gensrcs {
+ name: "module-name",
+ cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
+ srcs: [
+ ":external-protos",
+ ],
+ output_extension: "proto.h",
+ }
+ `
+ result := android.GroupFixturePreparers(
+ prepareForGenRuleTest,
+ android.FixtureMergeMockFs(android.MockFS{
+ "external-protos/path/Android.bp": []byte(`
+ filegroup {
+ name: "external-protos",
+ srcs: ["foo/foo.proto", "bar.proto"],
+ }
+ `),
+ }),
+ ).RunTestWithBp(t, bp)
+
+ exportedIncludeDir := "out/soong/.intermediates/module-name/gen/gensrcs"
+ gen := result.Module("module-name", "").(*Module)
+
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "include path",
+ []string{exportedIncludeDir},
+ gen.exportedIncludeDirs,
+ )
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "files",
+ []string{
+ exportedIncludeDir + "/external-protos/path/foo/foo.proto.h",
+ exportedIncludeDir + "/external-protos/path/bar.proto.h",
+ },
+ gen.outputFiles,
+ )
+}
+
func TestPrebuiltTool(t *testing.T) {
testcases := []struct {
name string
diff --git a/java/Android.bp b/java/Android.bp
index 9df4ab4..0bf7a0b 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",
@@ -64,6 +65,7 @@
"plugin.go",
"prebuilt_apis.go",
"proto.go",
+ "resourceshrinker.go",
"robolectric.go",
"rro.go",
"sdk.go",
@@ -86,6 +88,7 @@
"dex_test.go",
"dexpreopt_test.go",
"dexpreopt_bootjars_test.go",
+ "dexpreopt_config_test.go",
"droiddoc_test.go",
"droidstubs_test.go",
"genrule_test.go",
diff --git a/java/aapt2.go b/java/aapt2.go
index 5346ddf..7845a0b 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -256,17 +256,21 @@
var aapt2ConvertRule = pctx.AndroidStaticRule("aapt2Convert",
blueprint.RuleParams{
- Command: `${config.Aapt2Cmd} convert --output-format proto $in -o $out`,
+ Command: `${config.Aapt2Cmd} convert --output-format $format $in -o $out`,
CommandDeps: []string{"${config.Aapt2Cmd}"},
- })
+ }, "format",
+)
// Converts xml files and resource tables (resources.arsc) in the given jar/apk file to a proto
// format. The proto definition is available at frameworks/base/tools/aapt2/Resources.proto.
-func aapt2Convert(ctx android.ModuleContext, out android.WritablePath, in android.Path) {
+func aapt2Convert(ctx android.ModuleContext, out android.WritablePath, in android.Path, format string) {
ctx.Build(pctx, android.BuildParams{
Rule: aapt2ConvertRule,
Input: in,
Output: out,
- Description: "convert to proto",
+ Description: "convert to " + format,
+ Args: map[string]string{
+ "format": format,
+ },
})
}
diff --git a/java/aar.go b/java/aar.go
index d5996ba..6261f29 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -270,7 +270,7 @@
func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkContext,
classLoaderContexts dexpreopt.ClassLoaderContextMap, excludedLibs []string,
- extraLinkFlags ...string) {
+ enforceDefaultTargetSdkVersion bool, extraLinkFlags ...string) {
transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags :=
aaptLibs(ctx, sdkContext, classLoaderContexts)
@@ -283,15 +283,16 @@
manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
manifestPath := ManifestFixer(ctx, manifestSrcPath, ManifestFixerParams{
- SdkContext: sdkContext,
- ClassLoaderContexts: classLoaderContexts,
- IsLibrary: a.isLibrary,
- DefaultManifestVersion: a.defaultManifestVersion,
- UseEmbeddedNativeLibs: a.useEmbeddedNativeLibs,
- UsesNonSdkApis: a.usesNonSdkApis,
- UseEmbeddedDex: a.useEmbeddedDex,
- HasNoCode: a.hasNoCode,
- LoggingParent: a.LoggingParent,
+ SdkContext: sdkContext,
+ ClassLoaderContexts: classLoaderContexts,
+ IsLibrary: a.isLibrary,
+ DefaultManifestVersion: a.defaultManifestVersion,
+ UseEmbeddedNativeLibs: a.useEmbeddedNativeLibs,
+ UsesNonSdkApis: a.usesNonSdkApis,
+ UseEmbeddedDex: a.useEmbeddedDex,
+ HasNoCode: a.hasNoCode,
+ LoggingParent: a.LoggingParent,
+ EnforceDefaultTargetSdkVersion: enforceDefaultTargetSdkVersion,
})
// Add additional manifest files to transitive manifests.
@@ -439,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)
}
@@ -535,7 +536,7 @@
func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.aapt.isLibrary = true
a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
- a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts, nil)
+ a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts, nil, false)
a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 522b664..c785310 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -43,13 +43,12 @@
// targetSdkVersion for manifest_fixer
// When TARGET_BUILD_APPS is not empty, this method returns 10000 for modules targeting an unreleased SDK
// This enables release builds (that run with TARGET_BUILD_APPS=[val...]) to target APIs that have not yet been finalized as part of an SDK
-func targetSdkVersionForManifestFixer(ctx android.ModuleContext, sdkContext android.SdkContext) string {
- targetSdkVersionSpec := sdkContext.TargetSdkVersion(ctx)
- // Return 10000 for modules targeting "current" if either
- // 1. The module is built in unbundled mode (TARGET_BUILD_APPS not empty)
- // 2. The module is run as part of MTS, and should be testable on stable branches
+func targetSdkVersionForManifestFixer(ctx android.ModuleContext, params ManifestFixerParams) string {
+ targetSdkVersionSpec := params.SdkContext.TargetSdkVersion(ctx)
+
+ // Check if we want to return 10000
// TODO(b/240294501): Determine the rules for handling test apexes
- if targetSdkVersionSpec.ApiLevel.IsPreview() && (ctx.Config().UnbundledBuildApps() || includedInMts(ctx.Module())) {
+ if shouldReturnFinalOrFutureInt(ctx, targetSdkVersionSpec, params.EnforceDefaultTargetSdkVersion) {
return strconv.Itoa(android.FutureApiLevel.FinalOrFutureInt())
}
targetSdkVersion, err := targetSdkVersionSpec.EffectiveVersionString(ctx)
@@ -59,6 +58,17 @@
return targetSdkVersion
}
+// Return true for modules targeting "current" if either
+// 1. The module is built in unbundled mode (TARGET_BUILD_APPS not empty)
+// 2. The module is run as part of MTS, and should be testable on stable branches
+// Do not return 10000 if we are enforcing default targetSdkVersion and sdk has been finalised
+func shouldReturnFinalOrFutureInt(ctx android.ModuleContext, targetSdkVersionSpec android.SdkSpec, enforceDefaultTargetSdkVersion bool) bool {
+ if enforceDefaultTargetSdkVersion && ctx.Config().PlatformSdkFinal() {
+ return false
+ }
+ return targetSdkVersionSpec.ApiLevel.IsPreview() && (ctx.Config().UnbundledBuildApps() || includedInMts(ctx.Module()))
+}
+
// Helper function that casts android.Module to java.androidTestApp
// If this type conversion is possible, it queries whether the test app is included in an MTS suite
func includedInMts(module android.Module) bool {
@@ -69,16 +79,17 @@
}
type ManifestFixerParams struct {
- SdkContext android.SdkContext
- ClassLoaderContexts dexpreopt.ClassLoaderContextMap
- IsLibrary bool
- DefaultManifestVersion string
- UseEmbeddedNativeLibs bool
- UsesNonSdkApis bool
- UseEmbeddedDex bool
- HasNoCode bool
- TestOnly bool
- LoggingParent string
+ SdkContext android.SdkContext
+ ClassLoaderContexts dexpreopt.ClassLoaderContextMap
+ IsLibrary bool
+ DefaultManifestVersion string
+ UseEmbeddedNativeLibs bool
+ UsesNonSdkApis bool
+ UseEmbeddedDex bool
+ HasNoCode bool
+ TestOnly bool
+ LoggingParent string
+ EnforceDefaultTargetSdkVersion bool
}
// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
@@ -137,7 +148,7 @@
var argsMapper = make(map[string]string)
if params.SdkContext != nil {
- targetSdkVersion := targetSdkVersionForManifestFixer(ctx, params.SdkContext)
+ targetSdkVersion := targetSdkVersionForManifestFixer(ctx, params)
args = append(args, "--targetSdkVersion ", targetSdkVersion)
if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
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 bccd37f..2a51e10 100755
--- a/java/app.go
+++ b/java/app.go
@@ -101,6 +101,15 @@
PreventInstall bool `blueprint:"mutated"`
IsCoverageVariant bool `blueprint:"mutated"`
+ // It can be set to test the behaviour of default target sdk version.
+ // Only required when updatable: false. It is an error if updatable: true and this is false.
+ Enforce_default_target_sdk_version *bool
+
+ // If set, the targetSdkVersion for the target is set to the latest default API level.
+ // This would be by default false, unless updatable: true or
+ // enforce_default_target_sdk_version: true in which case this defaults to true.
+ EnforceDefaultTargetSdkVersion bool `blueprint:"mutated"`
+
// Whether this app is considered mainline updatable or not. When set to true, this will enforce
// additional rules to make sure an app can safely be updated. Default is false.
// Prefer using other specific properties if build behaviour must be changed; avoid using this
@@ -296,6 +305,18 @@
} else {
ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
}
+
+ if !BoolDefault(a.appProperties.Enforce_default_target_sdk_version, true) {
+ ctx.PropertyErrorf("enforce_default_target_sdk_version", "Updatable apps must enforce default target sdk version")
+ }
+ // TODO(b/227460469) after all the modules removes the target sdk version, throw an error if the target sdk version is explicitly set.
+ if a.deviceProperties.Target_sdk_version == nil {
+ a.SetEnforceDefaultTargetSdkVersion(true)
+ }
+ }
+
+ if Bool(a.appProperties.Enforce_default_target_sdk_version) {
+ a.SetEnforceDefaultTargetSdkVersion(true)
}
a.checkPlatformAPI(ctx)
@@ -427,7 +448,7 @@
a.aapt.defaultManifestVersion = android.DefaultUpdatableModuleVersion
}
a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts,
- a.usesLibraryProperties.Exclude_uses_libs, aaptLinkFlags...)
+ a.usesLibraryProperties.Exclude_uses_libs, a.enforceDefaultTargetSdkVersion(), aaptLinkFlags...)
// apps manifests are handled by aapt, don't let Module see them
a.properties.Manifest = nil
@@ -526,7 +547,8 @@
// Reads and prepends a main cert from the default cert dir if it hasn't been set already, i.e. it
// isn't a cert module reference. Also checks and enforces system cert restriction if applicable.
-func processMainCert(m android.ModuleBase, certPropValue string, certificates []Certificate, ctx android.ModuleContext) []Certificate {
+func processMainCert(m android.ModuleBase, certPropValue string, certificates []Certificate,
+ ctx android.ModuleContext) (mainCertificate Certificate, allCertificates []Certificate) {
if android.SrcIsModule(certPropValue) == "" {
var mainCert Certificate
if certPropValue != "" {
@@ -558,7 +580,22 @@
}
}
- return certificates
+ if len(certificates) > 0 {
+ mainCertificate = certificates[0]
+ } else {
+ // This can be reached with an empty certificate list if AllowMissingDependencies is set
+ // and the certificate property for this module is a module reference to a missing module.
+ if !ctx.Config().AllowMissingDependencies() && len(ctx.GetMissingDependencies()) > 0 {
+ panic("Should only get here if AllowMissingDependencies set and there are missing dependencies")
+ }
+ // Set a certificate to avoid panics later when accessing it.
+ mainCertificate = Certificate{
+ Key: android.PathForModuleOut(ctx, "missing.pk8"),
+ Pem: android.PathForModuleOut(ctx, "missing.pem"),
+ }
+ }
+
+ return mainCertificate, certificates
}
func (a *AndroidApp) InstallApkName() string {
@@ -632,29 +669,14 @@
dexJarFile := a.dexBuildActions(ctx)
- jniLibs, prebuiltJniPackages, certificateDeps := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
+ jniLibs, prebuiltJniPackages, certificates := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
jniJarFile := a.jniBuildActions(jniLibs, prebuiltJniPackages, ctx)
if ctx.Failed() {
return
}
- certificates := processMainCert(a.ModuleBase, a.getCertString(ctx), certificateDeps, ctx)
-
- // This can be reached with an empty certificate list if AllowMissingDependencies is set
- // and the certificate property for this module is a module reference to a missing module.
- if len(certificates) > 0 {
- a.certificate = certificates[0]
- } else {
- if !ctx.Config().AllowMissingDependencies() && len(ctx.GetMissingDependencies()) > 0 {
- panic("Should only get here if AllowMissingDependencies set and there are missing dependencies")
- }
- // Set a certificate to avoid panics later when accessing it.
- a.certificate = Certificate{
- Key: android.PathForModuleOut(ctx, "missing.pk8"),
- Pem: android.PathForModuleOut(ctx, "missing.pem"),
- }
- }
+ a.certificate, certificates = processMainCert(a.ModuleBase, a.getCertString(ctx), certificates, ctx)
// Build a final signed app package.
packageFile := android.PathForModuleOut(ctx, a.installApkName+".apk")
@@ -667,10 +689,9 @@
if lineage := String(a.overridableAppProperties.Lineage); lineage != "" {
lineageFile = android.PathForModuleSrc(ctx, lineage)
}
-
rotationMinSdkVersion := String(a.overridableAppProperties.RotationMinSdkVersion)
- CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion)
+ CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion, Bool(a.dexProperties.Optimize.Shrink_resources))
a.outputFile = packageFile
if v4SigningRequested {
a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)
@@ -699,7 +720,7 @@
if v4SigningRequested {
v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk.idsig")
}
- CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion)
+ CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion, false)
a.extraOutputFiles = append(a.extraOutputFiles, packageFile)
if v4SigningRequested {
a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)
@@ -777,6 +798,7 @@
target: module.Target(),
coverageFile: dep.CoverageOutputFile(),
unstrippedFile: dep.UnstrippedOutputFile(),
+ partition: dep.Partition(),
})
} else {
ctx.ModuleErrorf("dependency %q missing output file", otherName)
@@ -865,6 +887,14 @@
a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(ctx).String(), depsInfo)
}
+func (a *AndroidApp) enforceDefaultTargetSdkVersion() bool {
+ return a.appProperties.EnforceDefaultTargetSdkVersion
+}
+
+func (a *AndroidApp) SetEnforceDefaultTargetSdkVersion(val bool) {
+ a.appProperties.EnforceDefaultTargetSdkVersion = val
+}
+
func (a *AndroidApp) Updatable() bool {
return Bool(a.appProperties.Updatable)
}
@@ -1456,8 +1486,8 @@
*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.
@@ -1469,15 +1499,8 @@
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,
@@ -1485,7 +1508,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_builder.go b/java/app_builder.go
index 18a9751..d20a6bf 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -52,7 +52,7 @@
})
func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
- packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, v4SignatureFile android.WritablePath, lineageFile android.Path, rotationMinSdkVersion string) {
+ packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, v4SignatureFile android.WritablePath, lineageFile android.Path, rotationMinSdkVersion string, shrinkResources bool) {
unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk"
unsignedApk := android.PathForModuleOut(ctx, unsignedApkName)
@@ -65,7 +65,6 @@
if jniJarFile != nil {
inputs = append(inputs, jniJarFile)
}
-
ctx.Build(pctx, android.BuildParams{
Rule: combineApk,
Inputs: inputs,
@@ -73,6 +72,11 @@
Implicits: deps,
})
+ if shrinkResources {
+ shrunkenApk := android.PathForModuleOut(ctx, "resource-shrunken", unsignedApk.Base())
+ ShrinkResources(ctx, unsignedApk, shrunkenApk)
+ unsignedApk = shrunkenApk
+ }
SignAppPackage(ctx, outputFile, unsignedApk, certificates, v4SignatureFile, lineageFile, rotationMinSdkVersion)
}
@@ -84,7 +88,6 @@
certificateArgs = append(certificateArgs, c.Pem.String(), c.Key.String())
deps = append(deps, c.Pem, c.Key)
}
-
outputFiles := android.WritablePaths{signedApk}
var flags []string
if v4SignatureFile != nil {
@@ -182,7 +185,7 @@
packageFile, jniJarFile, dexJarFile android.Path) {
protoResJarFile := android.PathForModuleOut(ctx, "package-res.pb.apk")
- aapt2Convert(ctx, protoResJarFile, packageFile)
+ aapt2Convert(ctx, protoResJarFile, packageFile, "proto")
var zips android.Paths
diff --git a/java/app_import.go b/java/app_import.go
index d6dca38..6e603c9 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -318,19 +318,17 @@
if a.isPrebuiltFrameworkRes() {
a.outputFile = srcApk
- certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
+ a.certificate, certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
if len(certificates) != 1 {
ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates)
}
- a.certificate = certificates[0]
} else if a.preprocessed {
a.outputFile = srcApk
a.certificate = PresignedCertificate
} else if !Bool(a.properties.Presigned) {
// If the certificate property is empty at this point, default_dev_cert must be set to true.
// Which makes processMainCert's behavior for the empty cert string WAI.
- certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
- a.certificate = certificates[0]
+ a.certificate, certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
signed := android.PathForModuleOut(ctx, "signed", apkFilename)
var lineageFile android.Path
if lineage := String(a.properties.Lineage); lineage != "" {
diff --git a/java/app_import_test.go b/java/app_import_test.go
index 41be092..ad27e3a 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -807,3 +807,23 @@
}
}
}
+
+func TestAppImportMissingCertificateAllowMissingDependencies(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestWithAllowMissingDependencies,
+ android.PrepareForTestWithAndroidMk,
+ ).RunTestWithBp(t, `
+ android_app_import {
+ name: "foo",
+ apk: "a.apk",
+ certificate: ":missing_certificate",
+ }`)
+
+ foo := result.ModuleForTests("foo", "android_common")
+ fooApk := foo.Output("signed/foo.apk")
+ if fooApk.Rule != android.ErrorRule {
+ t.Fatalf("expected ErrorRule for foo.apk, got %s", fooApk.Rule.String())
+ }
+ android.AssertStringDoesContain(t, "expected error rule message", fooApk.Args["error"], "missing dependencies: missing_certificate\n")
+}
diff --git a/java/app_set.go b/java/app_set.go
index 694b167..d99fadb 100644
--- a/java/app_set.go
+++ b/java/app_set.go
@@ -90,10 +90,11 @@
}
var TargetCpuAbi = map[string]string{
- "arm": "ARMEABI_V7A",
- "arm64": "ARM64_V8A",
- "x86": "X86",
- "x86_64": "X86_64",
+ "arm": "ARMEABI_V7A",
+ "arm64": "ARM64_V8A",
+ "riscv64": "RISCV64",
+ "x86": "X86",
+ "x86_64": "X86_64",
}
func SupportedAbis(ctx android.ModuleContext) []string {
diff --git a/java/app_test.go b/java/app_test.go
index 23635b9..e216c63 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -3057,6 +3057,179 @@
}
}
+func TestDefaultAppTargetSdkVersionForUpdatableModules(t *testing.T) {
+ platform_sdk_codename := "Tiramisu"
+ platform_sdk_version := 33
+ testCases := []struct {
+ name string
+ platform_sdk_final bool
+ targetSdkVersionInBp *string
+ targetSdkVersionExpected *string
+ updatable bool
+ }{
+ {
+ name: "Non-Updatable Module: Android.bp has older targetSdkVersion",
+ targetSdkVersionInBp: proptools.StringPtr("29"),
+ targetSdkVersionExpected: proptools.StringPtr("29"),
+ updatable: false,
+ },
+ {
+ name: "Updatable Module: Android.bp has older targetSdkVersion",
+ targetSdkVersionInBp: proptools.StringPtr("30"),
+ targetSdkVersionExpected: proptools.StringPtr("30"),
+ updatable: true,
+ },
+ {
+ name: "Updatable Module: Android.bp has no targetSdkVersion",
+ targetSdkVersionExpected: proptools.StringPtr("10000"),
+ updatable: true,
+ },
+ {
+ name: "[SDK finalised] Non-Updatable Module: Android.bp has older targetSdkVersion",
+ platform_sdk_final: true,
+ targetSdkVersionInBp: proptools.StringPtr("30"),
+ targetSdkVersionExpected: proptools.StringPtr("30"),
+ updatable: false,
+ },
+ {
+ name: "[SDK finalised] Updatable Module: Android.bp has older targetSdkVersion",
+ platform_sdk_final: true,
+ targetSdkVersionInBp: proptools.StringPtr("30"),
+ targetSdkVersionExpected: proptools.StringPtr("30"),
+ updatable: true,
+ },
+ {
+ name: "[SDK finalised] Updatable Module: Android.bp has targetSdkVersion as platform sdk codename",
+ platform_sdk_final: true,
+ targetSdkVersionInBp: proptools.StringPtr(platform_sdk_codename),
+ targetSdkVersionExpected: proptools.StringPtr("33"),
+ updatable: true,
+ },
+ {
+ name: "[SDK finalised] Updatable Module: Android.bp has no targetSdkVersion",
+ platform_sdk_final: true,
+ targetSdkVersionExpected: proptools.StringPtr("33"),
+ updatable: true,
+ },
+ }
+ for _, testCase := range testCases {
+ bp := fmt.Sprintf(`
+ android_app {
+ name: "foo",
+ sdk_version: "current",
+ min_sdk_version: "29",
+ target_sdk_version: "%v",
+ updatable: %t,
+ enforce_default_target_sdk_version: %t
+ }
+ `, proptools.String(testCase.targetSdkVersionInBp), testCase.updatable, testCase.updatable) // enforce default target sdk version if app is updatable
+
+ fixture := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestWithAllowMissingDependencies,
+ android.PrepareForTestWithAndroidMk,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ // explicitly set following platform variables to make the test deterministic
+ variables.Platform_sdk_final = &testCase.platform_sdk_final
+ variables.Platform_sdk_version = &platform_sdk_version
+ variables.Platform_sdk_codename = &platform_sdk_codename
+ variables.Platform_version_active_codenames = []string{platform_sdk_codename}
+ variables.Unbundled_build_apps = []string{"sampleModule"}
+ }),
+ )
+
+ result := fixture.RunTestWithBp(t, bp)
+ foo := result.ModuleForTests("foo", "android_common")
+
+ manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
+ android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+*testCase.targetSdkVersionExpected)
+ }
+}
+
+func TestEnforceDefaultAppTargetSdkVersionFlag(t *testing.T) {
+ platform_sdk_codename := "Tiramisu"
+ platform_sdk_version := 33
+ testCases := []struct {
+ name string
+ enforceDefaultTargetSdkVersion bool
+ expectedError string
+ platform_sdk_final bool
+ targetSdkVersionInBp string
+ targetSdkVersionExpected string
+ updatable bool
+ }{
+ {
+ name: "Not enforcing Target SDK Version: Android.bp has older targetSdkVersion",
+ enforceDefaultTargetSdkVersion: false,
+ targetSdkVersionInBp: "29",
+ targetSdkVersionExpected: "29",
+ updatable: false,
+ },
+ {
+ name: "[SDK finalised] Enforce Target SDK Version: Android.bp has current targetSdkVersion",
+ enforceDefaultTargetSdkVersion: true,
+ platform_sdk_final: true,
+ targetSdkVersionInBp: "current",
+ targetSdkVersionExpected: "33",
+ updatable: true,
+ },
+ {
+ name: "[SDK finalised] Enforce Target SDK Version: Android.bp has current targetSdkVersion",
+ enforceDefaultTargetSdkVersion: true,
+ platform_sdk_final: false,
+ targetSdkVersionInBp: "current",
+ targetSdkVersionExpected: "10000",
+ updatable: false,
+ },
+ {
+ name: "Not enforcing Target SDK Version for Updatable app",
+ enforceDefaultTargetSdkVersion: false,
+ expectedError: "Updatable apps must enforce default target sdk version",
+ targetSdkVersionInBp: "29",
+ targetSdkVersionExpected: "29",
+ updatable: true,
+ },
+ }
+ for _, testCase := range testCases {
+ errExpected := testCase.expectedError != ""
+ bp := fmt.Sprintf(`
+ android_app {
+ name: "foo",
+ enforce_default_target_sdk_version: %t,
+ sdk_version: "current",
+ min_sdk_version: "29",
+ target_sdk_version: "%v",
+ updatable: %t
+ }
+ `, testCase.enforceDefaultTargetSdkVersion, testCase.targetSdkVersionInBp, testCase.updatable)
+
+ fixture := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestWithAllowMissingDependencies,
+ android.PrepareForTestWithAndroidMk,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ // explicitly set following platform variables to make the test deterministic
+ variables.Platform_sdk_final = &testCase.platform_sdk_final
+ variables.Platform_sdk_version = &platform_sdk_version
+ variables.Platform_sdk_codename = &platform_sdk_codename
+ variables.Unbundled_build_apps = []string{"sampleModule"}
+ }),
+ )
+
+ errorHandler := android.FixtureExpectsNoErrors
+ if errExpected {
+ errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError)
+ }
+ result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp)
+
+ if !errExpected {
+ foo := result.ModuleForTests("foo", "android_common")
+ manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
+ android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
+ }
+ }
+}
+
func TestAppMissingCertificateAllowMissingDependencies(t *testing.T) {
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
diff --git a/java/base.go b/java/base.go
index 53f0f52..96f36e8 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))
}
}
@@ -650,6 +652,10 @@
return false
}
+func (j *Module) setInstrument(value bool) {
+ j.properties.Instrument = value
+}
+
func (j *Module) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
return android.SdkSpecFrom(ctx, String(j.deviceProperties.Sdk_version))
}
@@ -789,9 +795,6 @@
} else if j.shouldInstrumentStatic(ctx) {
ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent")
}
- if j.shouldInstrument(ctx) {
- ctx.AddVariationDependencies(nil, libTag, "jacocoagent")
- }
if j.useCompose() {
ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag,
@@ -862,7 +865,9 @@
// add flags for dirs containing AIDL srcs that haven't been specified yet
flags = append(flags, genAidlIncludeFlags(ctx, aidlSrcs, includeDirs))
- if Bool(j.deviceProperties.Aidl.Generate_traces) {
+ sdkVersion := (j.SdkVersion(ctx)).Kind
+ defaultTrace := ((sdkVersion == android.SdkSystemServer) || (sdkVersion == android.SdkCore) || (sdkVersion == android.SdkCorePlatform))
+ if proptools.BoolDefault(j.deviceProperties.Aidl.Generate_traces, defaultTrace) {
flags = append(flags, "-t")
}
@@ -890,7 +895,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?")
}
@@ -1075,15 +1080,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
@@ -1091,7 +1107,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
@@ -1129,12 +1145,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...)
@@ -1147,7 +1158,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
@@ -1157,7 +1168,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
}
@@ -1182,8 +1193,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
@@ -1198,12 +1207,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" {
@@ -1228,7 +1237,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)
@@ -1240,8 +1249,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)
@@ -1254,7 +1263,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() {
@@ -1435,10 +1444,6 @@
j.headerJarFile = j.implementationJarFile
}
- if j.shouldInstrumentInApex(ctx) {
- j.properties.Instrument = true
- }
-
// enforce syntax check to jacoco filters for any build (http://b/183622051)
specs := j.jacocoModuleToZipCommand(ctx)
if ctx.Failed() {
@@ -1956,7 +1961,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...)
@@ -1976,7 +1981,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)
}
@@ -2049,7 +2054,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 9316807..3a28c59 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -257,14 +257,14 @@
// Returns a *HiddenAPIOutput containing the paths for the generated files. Returns nil if the
// module cannot contribute to hidden API processing, e.g. because it is a prebuilt module in a
// versioned sdk.
- produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput
+ produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput
// produceBootImageFiles will attempt to produce rules to create the boot image files at the paths
// predefined in the bootImageConfig.
//
// 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)
@@ -716,8 +717,6 @@
// This is an exception to support end-to-end test for SdkExtensions, until such support exists.
if android.InList("test_framework-sdkextensions", possibleUpdatableModules) {
jars = jars.Append("com.android.sdkext", "test_framework-sdkextensions")
- } else if android.InList("AddNewActivity", possibleUpdatableModules) {
- jars = jars.Append("test_com.android.cts.frameworkresapkplits", "AddNewActivity")
} else if android.InList("test_framework-apexd", possibleUpdatableModules) {
jars = jars.Append("com.android.apex.test_package", "test_framework-apexd")
} else if global.ApexBootJars.Len() != 0 && !android.IsModuleInVersionedSdk(ctx.Module()) {
@@ -761,7 +760,7 @@
// Delegate the production of the hidden API all-flags.csv file to a module type specific method.
common := ctx.Module().(commonBootclasspathFragment)
- output := common.produceHiddenAPIOutput(ctx, contents, input)
+ output := common.produceHiddenAPIOutput(ctx, contents, fragments, input)
// If the source or prebuilts module does not provide a signature patterns file then generate one
// from the flags.
@@ -769,7 +768,7 @@
// their own.
if output.SignaturePatternsPath == nil {
output.SignaturePatternsPath = buildRuleSignaturePatternsFile(
- ctx, output.AllFlagsPath, []string{"*"}, nil, nil)
+ ctx, output.AllFlagsPath, []string{"*"}, nil, nil, "")
}
// Initialize a HiddenAPIInfo structure.
@@ -840,30 +839,15 @@
// isTestFragment returns true if the current module is a test bootclasspath_fragment.
func (b *BootclasspathFragmentModule) isTestFragment() bool {
- if b.testFragment {
- return true
- }
-
- // TODO(b/194063708): Once test fragments all use bootclasspath_fragment_test
- // Some temporary exceptions until all test fragments use the
- // bootclasspath_fragment_test module type.
- name := b.BaseModuleName()
- if strings.HasPrefix(name, "test_") {
- return true
- }
- if name == "apex.apexd_test_bootclasspath-fragment" {
- return true
- }
-
- return false
+ return b.testFragment
}
-// produceHiddenAPIOutput produces the hidden API all-flags.csv file (and supporting files)
-// for the fragment as well as encoding the flags in the boot dex jars.
-func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
+// generateHiddenApiFlagRules generates rules to generate hidden API flags and compute the signature
+// patterns file.
+func (b *BootclasspathFragmentModule) generateHiddenApiFlagRules(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput, bootDexInfoByModule bootDexInfoByModule, suffix string) HiddenAPIFlagOutput {
// Generate the rules to create the hidden API flags and update the supplied hiddenAPIInfo with the
// paths to the created files.
- output := hiddenAPIRulesForBootclasspathFragment(ctx, contents, input)
+ flagOutput := hiddenAPIFlagRulesForBootclasspathFragment(ctx, bootDexInfoByModule, contents, input, suffix)
// If the module specifies split_packages or package_prefixes then use those to generate the
// signature patterns.
@@ -871,8 +855,8 @@
packagePrefixes := input.PackagePrefixes
singlePackages := input.SinglePackages
if splitPackages != nil || packagePrefixes != nil || singlePackages != nil {
- output.SignaturePatternsPath = buildRuleSignaturePatternsFile(
- ctx, output.AllFlagsPath, splitPackages, packagePrefixes, singlePackages)
+ flagOutput.SignaturePatternsPath = buildRuleSignaturePatternsFile(
+ ctx, flagOutput.AllFlagsPath, splitPackages, packagePrefixes, singlePackages, suffix)
} else if !b.isTestFragment() {
ctx.ModuleErrorf(`Must specify at least one of the split_packages, package_prefixes and single_packages properties
If this is a new bootclasspath_fragment or you are unsure what to do add the
@@ -884,14 +868,76 @@
should specify here. If you are happy with its suggestions then you can add
the --fix option and it will fix them for you.`, b.BaseModuleName())
}
+ return flagOutput
+}
+
+// produceHiddenAPIOutput produces the hidden API all-flags.csv file (and supporting files)
+// for the fragment as well as encoding the flags in the boot dex jars.
+func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
+ // Gather information about the boot dex files for the boot libraries provided by this fragment.
+ bootDexInfoByModule := extractBootDexInfoFromModules(ctx, contents)
+
+ // Generate the flag file needed to encode into the dex files.
+ flagOutput := b.generateHiddenApiFlagRules(ctx, contents, input, bootDexInfoByModule, "")
+
+ // Encode those flags into the dex files of the contents of this fragment.
+ encodedBootDexFilesByModule := hiddenAPIEncodeRulesForBootclasspathFragment(ctx, bootDexInfoByModule, flagOutput.AllFlagsPath)
+
+ // Store that information for return for use by other rules.
+ output := &HiddenAPIOutput{
+ HiddenAPIFlagOutput: flagOutput,
+ EncodedBootDexFilesByModule: encodedBootDexFilesByModule,
+ }
+
+ // Get the ApiLevel associated with SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE, defaulting to current
+ // if not set.
+ config := ctx.Config()
+ targetApiLevel := android.ApiLevelOrPanic(ctx,
+ config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", "current"))
+
+ // Filter the contents list to remove any modules that do not support the target build release.
+ // The current build release supports all the modules.
+ contentsForSdkSnapshot := []android.Module{}
+ for _, module := range contents {
+ // If the module has a min_sdk_version that is higher than the target build release then it will
+ // not work on the target build release and so must not be included in the sdk snapshot.
+ minApiLevel := android.MinApiLevelForSdkSnapshot(ctx, module)
+ if minApiLevel.GreaterThan(targetApiLevel) {
+ continue
+ }
+
+ contentsForSdkSnapshot = append(contentsForSdkSnapshot, module)
+ }
+
+ var flagFilesByCategory FlagFilesByCategory
+ if len(contentsForSdkSnapshot) != len(contents) {
+ // The sdk snapshot has different contents to the runtime fragment so it is not possible to
+ // reuse the hidden API information generated for the fragment. So, recompute that information
+ // for the sdk snapshot.
+ filteredInput := b.createHiddenAPIFlagInput(ctx, contentsForSdkSnapshot, fragments)
+
+ // Gather information about the boot dex files for the boot libraries provided by this fragment.
+ filteredBootDexInfoByModule := extractBootDexInfoFromModules(ctx, contentsForSdkSnapshot)
+ flagOutput = b.generateHiddenApiFlagRules(ctx, contentsForSdkSnapshot, filteredInput, filteredBootDexInfoByModule, "-for-sdk-snapshot")
+ flagFilesByCategory = filteredInput.FlagFilesByCategory
+ } else {
+ // The sdk snapshot has the same contents as the runtime fragment so reuse that information.
+ flagFilesByCategory = input.FlagFilesByCategory
+ }
+
+ // Make the information available for the sdk snapshot.
+ ctx.SetProvider(HiddenAPIInfoForSdkProvider, HiddenAPIInfoForSdk{
+ FlagFilesByCategory: flagFilesByCategory,
+ HiddenAPIFlagOutput: flagOutput,
+ })
return output
}
// 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.
@@ -903,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.
@@ -927,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 {
@@ -1049,7 +1095,7 @@
// Get the hidden API information from the module.
mctx := ctx.SdkModuleContext()
- hiddenAPIInfo := mctx.OtherModuleProvider(module, HiddenAPIInfoProvider).(HiddenAPIInfo)
+ hiddenAPIInfo := mctx.OtherModuleProvider(module, HiddenAPIInfoForSdkProvider).(HiddenAPIInfoForSdk)
b.Flag_files_by_category = hiddenAPIInfo.FlagFilesByCategory
// Copy all the generated file paths.
@@ -1191,7 +1237,7 @@
}
// produceHiddenAPIOutput returns a path to the prebuilt all-flags.csv or nil if none is specified.
-func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
+func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
pathForOptionalSrc := func(src *string, defaultPath android.Path) android.Path {
if src == nil {
return defaultPath
@@ -1232,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)
@@ -1257,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.
@@ -1276,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/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index 2bfb255..2541f14 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -96,23 +96,6 @@
}
func TestBootclasspathFragment_Coverage(t *testing.T) {
- prepareForTestWithFrameworkCoverage := android.GroupFixturePreparers(
- android.FixtureMergeEnv(map[string]string{
- "EMMA_INSTRUMENT": "true",
- "EMMA_INSTRUMENT_FRAMEWORK": "true",
- }),
- // need to mock jacocoagent here to satisfy dependency added for
- // instrumented libraries at build time
- android.FixtureAddFile("jacocoagent/Android.bp", []byte(`
- java_library {
- name: "jacocoagent",
- srcs: ["Test.java"],
- system_modules: "none",
- sdk_version: "none",
- }
- `)),
- )
-
prepareWithBp := android.FixtureWithRootAndroidBp(`
bootclasspath_fragment {
name: "myfragment",
@@ -191,7 +174,7 @@
t.Run("with coverage", func(t *testing.T) {
result := android.GroupFixturePreparers(
- prepareForTestWithFrameworkCoverage,
+ prepareForTestWithFrameworkJacocoInstrumentation,
preparer,
).RunTest(t)
checkContents(t, result, "mybootlib", "coveragelib")
@@ -425,22 +408,6 @@
},
}
- bootclasspath_fragment {
- name: "test_fragment",
- contents: ["mysdklibrary"],
- hidden_api: {
- split_packages: [],
- },
- }
-
- bootclasspath_fragment {
- name: "apex.apexd_test_bootclasspath-fragment",
- contents: ["mysdklibrary"],
- hidden_api: {
- split_packages: [],
- },
- }
-
bootclasspath_fragment_test {
name: "a_test_fragment",
contents: ["mysdklibrary"],
@@ -462,12 +429,6 @@
fragment := result.Module("myfragment", "android_common").(*BootclasspathFragmentModule)
android.AssertBoolEquals(t, "not a test fragment", false, fragment.isTestFragment())
- fragment = result.Module("test_fragment", "android_common").(*BootclasspathFragmentModule)
- android.AssertBoolEquals(t, "is a test fragment by prefix", true, fragment.isTestFragment())
-
fragment = result.Module("a_test_fragment", "android_common").(*BootclasspathFragmentModule)
android.AssertBoolEquals(t, "is a test fragment by type", true, fragment.isTestFragment())
-
- fragment = result.Module("apex.apexd_test_bootclasspath-fragment", "android_common").(*BootclasspathFragmentModule)
- android.AssertBoolEquals(t, "is a test fragment by name", true, fragment.isTestFragment())
}
diff --git a/java/config/config.go b/java/config/config.go
index 422f860..45b668b 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -78,12 +78,12 @@
func init() {
pctx.Import("github.com/google/blueprint/bootstrap")
- exportedVars.ExportStringStaticVariable("JavacHeapSize", "2048M")
+ exportedVars.ExportStringStaticVariable("JavacHeapSize", "4096M")
exportedVars.ExportStringStaticVariable("JavacHeapFlags", "-J-Xmx${JavacHeapSize}")
// 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.
@@ -128,12 +128,7 @@
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")
@@ -160,6 +155,7 @@
pctx.HostBinToolVariable("ApiCheckCmd", "apicheck")
pctx.HostBinToolVariable("D8Cmd", "d8")
pctx.HostBinToolVariable("R8Cmd", "r8")
+ pctx.HostBinToolVariable("ResourceShrinkerCmd", "resourceshrinker")
pctx.HostBinToolVariable("HiddenAPICmd", "hiddenapi")
pctx.HostBinToolVariable("ExtractApksCmd", "extract_apks")
pctx.VariableFunc("TurbineJar", func(ctx android.PackageVarContext) string {
diff --git a/java/dex.go b/java/dex.go
index a44d792..de36b18 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -63,6 +63,8 @@
// classes referenced by the app manifest. Defaults to false.
No_aapt_flags *bool
+ Shrink_resources *bool
+
// Flags to pass to proguard.
Proguard_flags []string
@@ -200,6 +202,16 @@
"--verbose")
}
+ // Supplying the platform build flag disables various features like API modeling and desugaring.
+ // For targets with a stable min SDK version (i.e., when the min SDK is both explicitly specified
+ // and managed+versioned), we suppress this flag to ensure portability.
+ // Note: Targets with a min SDK kind of core_platform (e.g., framework.jar) or unspecified (e.g.,
+ // services.jar), are not classified as stable, which is WAI.
+ // TODO(b/232073181): Expand to additional min SDK cases after validation.
+ if !minSdkVersion.Stable() {
+ flags = append(flags, "--android-platform-build")
+ }
+
effectiveVersion, err := minSdkVersion.EffectiveVersion(ctx)
if err != nil {
ctx.PropertyErrorf("min_sdk_version", "%s", err)
diff --git a/java/dex_test.go b/java/dex_test.go
index a3e2ded..6617873 100644
--- a/java/dex_test.go
+++ b/java/dex_test.go
@@ -30,6 +30,19 @@
platform_apis: true,
}
+ android_app {
+ name: "stable_app",
+ srcs: ["foo.java"],
+ sdk_version: "current",
+ min_sdk_version: "31",
+ }
+
+ android_app {
+ name: "core_platform_app",
+ srcs: ["foo.java"],
+ sdk_version: "core_platform",
+ }
+
java_library {
name: "lib",
srcs: ["foo.java"],
@@ -42,11 +55,15 @@
`)
app := result.ModuleForTests("app", "android_common")
+ stableApp := result.ModuleForTests("stable_app", "android_common")
+ corePlatformApp := result.ModuleForTests("core_platform_app", "android_common")
lib := result.ModuleForTests("lib", "android_common")
staticLib := result.ModuleForTests("static_lib", "android_common")
appJavac := app.Rule("javac")
appR8 := app.Rule("r8")
+ stableAppR8 := stableApp.Rule("r8")
+ corePlatformAppR8 := corePlatformApp.Rule("r8")
libHeader := lib.Output("turbine-combined/lib.jar").Output
staticLibHeader := staticLib.Output("turbine-combined/static_lib.jar").Output
@@ -61,6 +78,12 @@
appR8.Args["r8Flags"], staticLibHeader.String())
android.AssertStringDoesContain(t, "expected -ignorewarnings in app r8 flags",
appR8.Args["r8Flags"], "-ignorewarnings")
+ android.AssertStringDoesContain(t, "expected --android-platform-build in app r8 flags",
+ appR8.Args["r8Flags"], "--android-platform-build")
+ android.AssertStringDoesNotContain(t, "expected no --android-platform-build in stable_app r8 flags",
+ stableAppR8.Args["r8Flags"], "--android-platform-build")
+ android.AssertStringDoesContain(t, "expected --android-platform-build in core_platform_app r8 flags",
+ corePlatformAppR8.Args["r8Flags"], "--android-platform-build")
}
func TestR8Flags(t *testing.T) {
@@ -88,7 +111,8 @@
appR8.Args["r8Flags"], "-dontobfuscate")
android.AssertStringDoesNotContain(t, "expected no -ignorewarnings in app r8 flags",
appR8.Args["r8Flags"], "-ignorewarnings")
-
+ android.AssertStringDoesContain(t, "expected --android-platform-build in app r8 flags",
+ appR8.Args["r8Flags"], "--android-platform-build")
}
func TestD8(t *testing.T) {
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 4e416fc..b3faae8 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)
@@ -764,11 +803,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 +872,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/droiddoc.go b/java/droiddoc.go
index 9b1f43b..2173dae 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...)
}
}
@@ -367,7 +367,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) {
@@ -684,7 +684,7 @@
outDir, srcJarDir, srcJarList android.Path, sourcepaths android.Paths) *android.RuleBuilderCommand {
cmd := rule.Command().
- BuiltTool("soong_javac_wrapper").Tool(config.JavadocCmd(ctx)).
+ BuiltTool("soong_javac_wrapper").Tool(android.PathForSource(ctx, "prebuilts/jdk/jdk11/linux-x86/bin/javadoc")).
Flag(config.JavacVmFlags).
FlagWithArg("-encoding ", "UTF-8").
FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "javadoc.rsp"), srcs).
@@ -755,6 +755,7 @@
return rule.Command().
BuiltTool("dokka").
Flag(config.JavacVmFlags).
+ Flag("-J--add-opens=java.base/java.lang=ALL-UNNAMED").
Flag(srcJarDir.String()).
FlagWithInputList("-classpath ", dokkaClasspath, ":").
FlagWithArg("-format ", "dac").
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 12590ca..5777b18 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -17,6 +17,7 @@
import (
"fmt"
"path/filepath"
+ "regexp"
"strings"
"github.com/google/blueprint/proptools"
@@ -27,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)
@@ -133,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.
@@ -142,6 +143,10 @@
// if set to true, collect the values used by the Dev tools and
// write them in files packaged with the SDK. Defaults to false.
Write_sdk_values *bool
+
+ // path or filegroup to file defining extension an SDK name <-> numerical ID mapping and
+ // what APIs exist in which SDKs; passed to metalava via --sdk-extensions-info
+ Extensions_info_file *string `android:"path"`
}
// Used by xsd_config
@@ -398,9 +403,20 @@
filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
var dirs []string
+ var extensions_dir string
ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
if t, ok := m.(*ExportedDroiddocDir); ok {
+ extRegex := regexp.MustCompile(t.dir.String() + `/extensions/[0-9]+/public/.*\.jar`)
+
+ // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
+ // ideally this should be read from prebuiltApis.properties.Extensions_*
for _, dep := range t.deps {
+ if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
+ if extensions_dir == "" {
+ extensions_dir = t.dir.String() + "/extensions"
+ }
+ cmd.Implicit(dep)
+ }
if dep.Base() == filename {
cmd.Implicit(dep)
}
@@ -429,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":
@@ -445,6 +463,16 @@
cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
}
}
+
+ if d.properties.Extensions_info_file != nil {
+ if extensions_dir == "" {
+ ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
+ }
+ info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
+ cmd.Implicit(info_file)
+ cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
+ cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
+ }
}
func metalavaUseRbe(ctx android.ModuleContext) bool {
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 9fdfdde..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 {
@@ -259,3 +274,33 @@
t.Errorf("inputs of %q must be []string{%q}, but was %#v.", moduleName, systemJar, systemJars)
}
}
+
+func TestDroidstubsWithSdkExtensions(t *testing.T) {
+ ctx, _ := testJavaWithFS(t, `
+ droiddoc_exported_dir {
+ name: "sdk-dir",
+ path: "sdk",
+ }
+
+ droidstubs {
+ name: "baz-stubs",
+ api_levels_annotations_dirs: ["sdk-dir"],
+ api_levels_annotations_enabled: true,
+ extensions_info_file: ":info-file",
+ }
+
+ filegroup {
+ name: "info-file",
+ srcs: ["sdk/extensions/info.txt"],
+ }
+ `,
+ map[string][]byte{
+ "sdk/extensions/1/public/some-mainline-module-stubs.jar": nil,
+ "sdk/extensions/info.txt": nil,
+ })
+ m := ctx.ModuleForTests("baz-stubs", "android_common")
+ manifest := m.Output("metalava.sbox.textproto")
+ cmdline := String(android.RuleBuilderSboxProtoForTests(t, manifest).Commands[0].Command)
+ android.AssertStringDoesContain(t, "sdk-extensions-root present", cmdline, "--sdk-extensions-root sdk/extensions")
+ android.AssertStringDoesContain(t, "sdk-extensions-info present", cmdline, "--sdk-extensions-info sdk/extensions/info.txt")
+}
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/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 7b67803..5474ae1 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -594,6 +594,23 @@
var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
+// HiddenAPIInfoForSdk contains information provided by the hidden API processing for use
+// by the sdk snapshot.
+//
+// That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API
+// processing.
+type HiddenAPIInfoForSdk struct {
+ // FlagFilesByCategory maps from the flag file category to the paths containing information for
+ // that category.
+ FlagFilesByCategory FlagFilesByCategory
+
+ // The output from the hidden API processing needs to be made available to other modules.
+ HiddenAPIFlagOutput
+}
+
+// Provides hidden API info for the sdk snapshot.
+var HiddenAPIInfoForSdkProvider = blueprint.NewProvider(HiddenAPIInfoForSdk{})
+
// ModuleStubDexJars contains the stub dex jars provided by a single module.
//
// It maps a *HiddenAPIScope to the path to stub dex jars appropriate for that scope. See
@@ -1024,8 +1041,11 @@
// patterns that will select a subset of the monolithic flags.
func buildRuleSignaturePatternsFile(
ctx android.ModuleContext, flagsPath android.Path,
- splitPackages []string, packagePrefixes []string, singlePackages []string) android.Path {
- patternsFile := android.PathForModuleOut(ctx, "modular-hiddenapi", "signature-patterns.csv")
+ splitPackages []string, packagePrefixes []string, singlePackages []string,
+ suffix string) android.Path {
+ hiddenApiSubDir := "modular-hiddenapi" + suffix
+
+ patternsFile := android.PathForModuleOut(ctx, hiddenApiSubDir, "signature-patterns.csv")
// Create a rule to validate the output from the following rule.
rule := android.NewRuleBuilder(pctx, ctx)
@@ -1042,7 +1062,7 @@
FlagForEachArg("--package-prefix ", packagePrefixes).
FlagForEachArg("--single-package ", singlePackages).
FlagWithOutput("--output ", patternsFile)
- rule.Build("hiddenAPISignaturePatterns", "hidden API signature patterns")
+ rule.Build("hiddenAPISignaturePatterns"+suffix, "hidden API signature patterns"+suffix)
return patternsFile
}
@@ -1116,8 +1136,8 @@
return validFile
}
-// hiddenAPIRulesForBootclasspathFragment will generate all the flags for a fragment of the
-// bootclasspath and then encode the flags into the boot dex files.
+// hiddenAPIFlagRulesForBootclasspathFragment will generate all the flags for a fragment of the
+// bootclasspath.
//
// It takes:
// * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind.
@@ -1130,31 +1150,27 @@
// * metadata.csv
// * index.csv
// * all-flags.csv
-// * encoded boot dex files
-func hiddenAPIRulesForBootclasspathFragment(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
- hiddenApiSubDir := "modular-hiddenapi"
-
- // Gather information about the boot dex files for the boot libraries provided by this fragment.
- bootDexInfoByModule := extractBootDexInfoFromModules(ctx, contents)
+func hiddenAPIFlagRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, contents []android.Module, input HiddenAPIFlagInput, suffix string) HiddenAPIFlagOutput {
+ hiddenApiSubDir := "modular-hiddenapi" + suffix
// Generate the stub-flags.csv.
stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
- buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil)
+ buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile"+suffix, "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil)
// Extract the classes jars from the contents.
classesJars := extractClassesJarsFromModules(contents)
// Generate the set of flags from the annotations in the source code.
annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
- buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags", classesJars, stubFlagsCSV, annotationFlagsCSV)
+ buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags"+suffix, classesJars, stubFlagsCSV, annotationFlagsCSV)
// Generate the metadata from the annotations in the source code.
metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
- buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata", classesJars, stubFlagsCSV, metadataCSV)
+ buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata"+suffix, classesJars, stubFlagsCSV, metadataCSV)
// Generate the index file from the CSV files in the classes jars.
indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
- buildRuleToGenerateIndex(ctx, "modular hiddenapi index", classesJars, indexCSV)
+ buildRuleToGenerateIndex(ctx, "modular hiddenapi index"+suffix, classesJars, indexCSV)
// Removed APIs need to be marked and in order to do that the hiddenAPIInfo needs to specify files
// containing dex signatures of all the removed APIs. In the monolithic files that is done by
@@ -1162,15 +1178,44 @@
// signatures, see the combined-removed-dex module. This does that automatically by using the
// *removed.txt files retrieved from the java_sdk_library modules that are specified in the
// stub_libs and contents properties of a bootclasspath_fragment.
- removedDexSignatures := buildRuleToGenerateRemovedDexSignatures(ctx, input.RemovedTxtFiles)
+ removedDexSignatures := buildRuleToGenerateRemovedDexSignatures(ctx, suffix, input.RemovedTxtFiles)
// Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
// files.
allFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
- buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", allFlagsCSV, stubFlagsCSV, android.Paths{annotationFlagsCSV}, input.FlagFilesByCategory, nil, removedDexSignatures)
+ buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags"+suffix, "modular hiddenapi all flags"+suffix, allFlagsCSV, stubFlagsCSV, android.Paths{annotationFlagsCSV}, input.FlagFilesByCategory, nil, removedDexSignatures)
+ // Generate the filtered-stub-flags.csv file which contains the filtered stub flags that will be
+ // compared against the monolithic stub flags.
+ filteredStubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-stub-flags.csv")
+ buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredStubFlags"+suffix,
+ "modular hiddenapi filtered stub flags"+suffix, stubFlagsCSV, filteredStubFlagsCSV,
+ HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
+
+ // Generate the filtered-flags.csv file which contains the filtered flags that will be compared
+ // against the monolithic flags.
+ filteredFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-flags.csv")
+ buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredFlags"+suffix,
+ "modular hiddenapi filtered flags"+suffix, allFlagsCSV, filteredFlagsCSV,
+ HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
+
+ // Store the paths in the info for use by other modules and sdk snapshot generation.
+ return HiddenAPIFlagOutput{
+ AnnotationFlagsPath: annotationFlagsCSV,
+ MetadataPath: metadataCSV,
+ IndexPath: indexCSV,
+ StubFlagsPath: stubFlagsCSV,
+ AllFlagsPath: allFlagsCSV,
+ FilteredStubFlagsPath: filteredStubFlagsCSV,
+ FilteredFlagsPath: filteredFlagsCSV,
+ }
+}
+
+// hiddenAPIEncodeRulesForBootclasspathFragment generates rules to encode hidden API flags into the
+// dex jars in bootDexInfoByModule.
+func hiddenAPIEncodeRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, allFlagsCSV android.Path) bootDexJarByModule {
// Encode the flags into the boot dex files.
- encodedBootDexJarsByModule := map[string]android.Path{}
+ encodedBootDexJarsByModule := bootDexJarByModule{}
outputDir := android.PathForModuleOut(ctx, "hiddenapi-modular/encoded").OutputPath
for _, name := range android.SortedStringKeys(bootDexInfoByModule) {
bootDexInfo := bootDexInfoByModule[name]
@@ -1178,43 +1223,15 @@
encodedDex := hiddenAPIEncodeDex(ctx, unencodedDex, allFlagsCSV, bootDexInfo.uncompressDex, bootDexInfo.minSdkVersion, outputDir)
encodedBootDexJarsByModule[name] = encodedDex
}
-
- // Generate the filtered-stub-flags.csv file which contains the filtered stub flags that will be
- // compared against the monolithic stub flags.
- filteredStubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-stub-flags.csv")
- buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredStubFlags",
- "modular hiddenapi filtered stub flags", stubFlagsCSV, filteredStubFlagsCSV,
- HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
-
- // Generate the filtered-flags.csv file which contains the filtered flags that will be compared
- // against the monolithic flags.
- filteredFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-flags.csv")
- buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredFlags",
- "modular hiddenapi filtered flags", allFlagsCSV, filteredFlagsCSV,
- HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
-
- // Store the paths in the info for use by other modules and sdk snapshot generation.
- output := HiddenAPIOutput{
- HiddenAPIFlagOutput: HiddenAPIFlagOutput{
- AnnotationFlagsPath: annotationFlagsCSV,
- MetadataPath: metadataCSV,
- IndexPath: indexCSV,
- StubFlagsPath: stubFlagsCSV,
- AllFlagsPath: allFlagsCSV,
- FilteredStubFlagsPath: filteredStubFlagsCSV,
- FilteredFlagsPath: filteredFlagsCSV,
- },
- EncodedBootDexFilesByModule: encodedBootDexJarsByModule,
- }
- return &output
+ return encodedBootDexJarsByModule
}
-func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, removedTxtFiles android.Paths) android.OptionalPath {
+func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, suffix string, removedTxtFiles android.Paths) android.OptionalPath {
if len(removedTxtFiles) == 0 {
return android.OptionalPath{}
}
- output := android.PathForModuleOut(ctx, "modular-hiddenapi/removed-dex-signatures.txt")
+ output := android.PathForModuleOut(ctx, "module-hiddenapi"+suffix, "removed-dex-signatures.txt")
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
@@ -1222,7 +1239,7 @@
Flag("--no-banner").
Inputs(removedTxtFiles).
FlagWithOutput("--dex-api ", output)
- rule.Build("modular-hiddenapi-removed-dex-signatures", "modular hiddenapi removed dex signatures")
+ rule.Build("modular-hiddenapi-removed-dex-signatures"+suffix, "modular hiddenapi removed dex signatures"+suffix)
return android.OptionalPathForPath(output)
}
diff --git a/java/jacoco.go b/java/jacoco.go
index e11c2ce..f8012b8 100644
--- a/java/jacoco.go
+++ b/java/jacoco.go
@@ -47,6 +47,34 @@
"strippedJar", "stripSpec", "tmpDir", "tmpJar")
)
+func jacocoDepsMutator(ctx android.BottomUpMutatorContext) {
+ type instrumentable interface {
+ shouldInstrument(ctx android.BaseModuleContext) bool
+ shouldInstrumentInApex(ctx android.BaseModuleContext) bool
+ setInstrument(value bool)
+ }
+
+ j, ok := ctx.Module().(instrumentable)
+ if !ctx.Module().Enabled() || !ok {
+ return
+ }
+
+ if j.shouldInstrumentInApex(ctx) {
+ j.setInstrument(true)
+ }
+
+ if j.shouldInstrument(ctx) && ctx.ModuleName() != "jacocoagent" {
+ // We can use AddFarVariationDependencies here because, since this dep
+ // is added as libs only (i.e. a compiletime CLASSPATH entry only),
+ // the first variant of jacocoagent is sufficient to prevent
+ // compile time errors.
+ // At this stage in the build, AddVariationDependencies is not always
+ // able to procure a variant of jacocoagent that matches the calling
+ // module.
+ ctx.AddFarVariationDependencies(ctx.Module().Target().Variations(), libTag, "jacocoagent")
+ }
+}
+
// Instruments a jar using the Jacoco command line interface. Uses stripSpec to extract a subset
// of the classes in inputJar into strippedJar, instruments strippedJar into tmpJar, and then
// combines the classes in tmpJar with inputJar (preferring the instrumented classes in tmpJar)
diff --git a/java/java.go b/java/java.go
index 0251b57..5091d26 100644
--- a/java/java.go
+++ b/java/java.go
@@ -66,6 +66,8 @@
// to support the checks in dexpreoptDisabled().
ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("dexpreopt_tool_deps", dexpreoptToolDepsMutator).Parallel()
+ // needs access to ApexInfoProvider which is available after variant creation
+ ctx.BottomUp("jacoco_deps", jacocoDepsMutator).Parallel()
})
ctx.RegisterSingletonType("logtags", LogtagsSingleton)
@@ -346,6 +348,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}
@@ -372,7 +375,7 @@
)
func IsLibDepTag(depTag blueprint.DependencyTag) bool {
- return depTag == libTag
+ return depTag == libTag || depTag == sdkLibTag
}
func IsStaticLibDepTag(depTag blueprint.DependencyTag) bool {
@@ -418,6 +421,7 @@
target android.Target
coverageFile android.OptionalPath
unstrippedFile android.Path
+ partition string
}
func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, d dexer) {
@@ -425,7 +429,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...)
}
@@ -1652,7 +1656,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:
@@ -1662,7 +1666,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))...)
}
}
@@ -2176,7 +2180,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.
diff --git a/java/java_test.go b/java/java_test.go
index 7f0cea7..d2373e3 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"},
diff --git a/java/lint.go b/java/lint.go
index 931820d..fcd6d31 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -473,20 +473,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 01e7e6e..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
@@ -91,6 +92,7 @@
--warning_check StringFormatInvalid # 148 occurences in 11 modules
--warning_check StringFormatMatches # 4800 occurences in 30 modules
--warning_check UnknownId # 8 occurences in 7 modules
+--warning_check UnspecifiedImmutableFlag
--warning_check ValidFragment # 12 occurences in 5 modules
--warning_check ValidRestrictions # 5 occurences in 1 modules
--warning_check WebViewLayout # 3 occurences in 1 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/prebuilt_apis.go b/java/prebuilt_apis.go
index 9449707..c6acd55 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -255,12 +255,11 @@
if p.properties.Extensions_dir != nil {
extensionApiFiles := globExtensionDirs(mctx, p, "api/*.txt")
for k, v := range getLatest(extensionApiFiles) {
- if v.version > mctx.Config().PlatformBaseSdkExtensionVersion() {
- if _, exists := latest[k]; !exists {
- mctx.ModuleErrorf("Module %v finalized for extension %d but never during an API level; likely error", v.module, v.version)
- }
- latest[k] = v
+ if _, exists := latest[k]; !exists {
+ mctx.ModuleErrorf("Module %v finalized for extension %d but never during an API level; likely error", v.module, v.version)
}
+ // The extension version is always at least as new as the last sdk int version (potentially identical)
+ latest[k] = v
}
}
diff --git a/java/prebuilt_apis_test.go b/java/prebuilt_apis_test.go
index 75422ad..2b84353 100644
--- a/java/prebuilt_apis_test.go
+++ b/java/prebuilt_apis_test.go
@@ -61,7 +61,7 @@
}
func TestPrebuiltApis_WithExtensions(t *testing.T) {
- runTestWithBaseExtensionLevel := func(v int) (foo_input string, bar_input string) {
+ runTestWithBaseExtensionLevel := func(v int) (foo_input, bar_input, baz_input string) {
result := android.GroupFixturePreparers(
prepareForJavaTest,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
@@ -69,7 +69,7 @@
}),
FixtureWithPrebuiltApisAndExtensions(map[string][]string{
"31": {"foo"},
- "32": {"foo", "bar"},
+ "32": {"foo", "bar", "baz"},
"current": {"foo", "bar"},
}, map[string][]string{
"1": {"foo"},
@@ -78,15 +78,24 @@
).RunTest(t)
foo_input = result.ModuleForTests("foo.api.public.latest", "").Rule("generator").Implicits[0].String()
bar_input = result.ModuleForTests("bar.api.public.latest", "").Rule("generator").Implicits[0].String()
+ baz_input = result.ModuleForTests("baz.api.public.latest", "").Rule("generator").Implicits[0].String()
return
}
- // Here, the base extension level is 1, so extension level 2 is the latest
- foo_input, bar_input := runTestWithBaseExtensionLevel(1)
- android.AssertStringEquals(t, "Expected latest = extension level 2", "prebuilts/sdk/extensions/2/public/api/foo.txt", foo_input)
- android.AssertStringEquals(t, "Expected latest = extension level 2", "prebuilts/sdk/extensions/2/public/api/bar.txt", bar_input)
+ // Extension 2 is the latest for both foo and bar, finalized after the base extension version.
+ foo_input, bar_input, baz_input := runTestWithBaseExtensionLevel(1)
+ android.AssertStringEquals(t, "Expected latest foo = extension level 2", "prebuilts/sdk/extensions/2/public/api/foo.txt", foo_input)
+ android.AssertStringEquals(t, "Expected latest bar = extension level 2", "prebuilts/sdk/extensions/2/public/api/bar.txt", bar_input)
+ android.AssertStringEquals(t, "Expected latest baz = api level 32", "prebuilts/sdk/32/public/api/baz.txt", baz_input)
- // Here, the base extension level is 2, so 2 is not later than 32.
- foo_input, bar_input = runTestWithBaseExtensionLevel(2)
- android.AssertStringEquals(t, "Expected latest = api level 32", "prebuilts/sdk/32/public/api/foo.txt", foo_input)
- android.AssertStringEquals(t, "Expected latest = api level 32", "prebuilts/sdk/32/public/api/bar.txt", bar_input)
+ // Extension 2 is the latest for both foo and bar, finalized together with 32
+ foo_input, bar_input, baz_input = runTestWithBaseExtensionLevel(2)
+ android.AssertStringEquals(t, "Expected latest foo = extension level 2", "prebuilts/sdk/extensions/2/public/api/foo.txt", foo_input)
+ android.AssertStringEquals(t, "Expected latest bar = extension level 2", "prebuilts/sdk/extensions/2/public/api/bar.txt", bar_input)
+ android.AssertStringEquals(t, "Expected latest baz = api level 32", "prebuilts/sdk/32/public/api/baz.txt", baz_input)
+
+ // Extension 3 is the current extension, but it has not yet been finalized.
+ foo_input, bar_input, baz_input = runTestWithBaseExtensionLevel(3)
+ android.AssertStringEquals(t, "Expected latest foo = extension level 2", "prebuilts/sdk/extensions/2/public/api/foo.txt", foo_input)
+ android.AssertStringEquals(t, "Expected latest bar = extension level 2", "prebuilts/sdk/extensions/2/public/api/bar.txt", bar_input)
+ android.AssertStringEquals(t, "Expected latest baz = api level 32", "prebuilts/sdk/32/public/api/baz.txt", baz_input)
}
diff --git a/java/resourceshrinker.go b/java/resourceshrinker.go
new file mode 100644
index 0000000..6d59601
--- /dev/null
+++ b/java/resourceshrinker.go
@@ -0,0 +1,43 @@
+// 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 (
+ "android/soong/android"
+
+ "github.com/google/blueprint"
+)
+
+var shrinkResources = pctx.AndroidStaticRule("shrinkResources",
+ blueprint.RuleParams{
+ Command: `${config.ResourceShrinkerCmd} --output $out --input $in --raw_resources $raw_resources`,
+ CommandDeps: []string{"${config.ResourceShrinkerCmd}"},
+ }, "raw_resources")
+
+func ShrinkResources(ctx android.ModuleContext, apk android.Path, outputFile android.WritablePath) {
+ protoFile := android.PathForModuleOut(ctx, apk.Base()+".proto.apk")
+ aapt2Convert(ctx, protoFile, apk, "proto")
+ strictModeFile := android.PathForSource(ctx, "prebuilts/cmdline-tools/shrinker.xml")
+ protoOut := android.PathForModuleOut(ctx, apk.Base()+".proto.out.apk")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: shrinkResources,
+ Input: protoFile,
+ Output: protoOut,
+ Args: map[string]string{
+ "raw_resources": strictModeFile.String(),
+ },
+ })
+ aapt2Convert(ctx, outputFile, protoOut, "binary")
+}
diff --git a/java/robolectric.go b/java/robolectric.go
index 71ffdb1..b6116ec 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"
)
@@ -166,7 +167,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 +175,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 c12e748..9d0667c 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -142,11 +142,15 @@
aaptLinkFlags = append(aaptLinkFlags,
"--rename-overlay-target-package "+*r.overridableProperties.Target_package_name)
}
- r.aapt.buildActions(ctx, r, nil, nil, aaptLinkFlags...)
+ 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
_, _, certificates := collectAppDeps(ctx, r, false, false)
- certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx)
+ r.certificate, certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx)
signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk")
var lineageFile android.Path
if lineage := String(r.properties.Lineage); lineage != "" {
@@ -156,7 +160,6 @@
rotationMinSdkVersion := String(r.properties.RotationMinSdkVersion)
SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates, nil, lineageFile, rotationMinSdkVersion)
- r.certificate = certificates[0]
r.outputFile = signed
partition := rroPartition(ctx)
@@ -221,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 8f499b1..fad1df7 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.
@@ -539,7 +571,7 @@
}
// TODO: determines whether to create HTML doc or not
- //Html_doc *bool
+ // Html_doc *bool
}
// Paths to outputs from java_sdk_library and java_sdk_library_import.
@@ -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
}
@@ -1354,7 +1386,7 @@
// Provide additional information for inclusion in an sdk's generated .info file.
additionalSdkInfo := map[string]interface{}{}
additionalSdkInfo["dist_stem"] = module.distStem()
- baseModuleName := module.BaseModuleName()
+ baseModuleName := module.distStem()
scopes := map[string]interface{}{}
additionalSdkInfo["scopes"] = scopes
for scope, scopePaths := range module.scopePaths {
@@ -2236,8 +2268,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 +2280,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 +2294,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
@@ -2904,6 +2939,18 @@
type sdkLibrarySdkMemberProperties struct {
android.SdkMemberPropertiesBase
+ // Stem name for files in the sdk snapshot.
+ //
+ // This is used to construct the path names of various sdk library files in the sdk snapshot to
+ // make sure that they match the finalized versions of those files in prebuilts/sdk.
+ //
+ // This property is marked as keep so that it will be kept in all instances of this struct, will
+ // not be cleared but will be copied to common structs. That is needed because this field is used
+ // to construct many file names for other parts of this struct and so it needs to be present in
+ // all structs. If it was not marked as keep then it would be cleared in some structs and so would
+ // be unavailable for generating file names if there were other properties that were still set.
+ Stem string `sdk:"keep"`
+
// Scope to per scope properties.
Scopes map[*apiScope]*scopeProperties
@@ -2965,6 +3012,9 @@
func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
sdk := variant.(*SdkLibrary)
+ // Copy the stem name for files in the sdk snapshot.
+ s.Stem = sdk.distStem()
+
s.Scopes = make(map[*apiScope]*scopeProperties)
for _, apiScope := range allApiScopes {
paths := sdk.findScopePaths(apiScope)
@@ -3017,6 +3067,8 @@
propertySet.AddProperty("permitted_packages", s.Permitted_packages)
}
+ stem := s.Stem
+
for _, apiScope := range allApiScopes {
if properties, ok := s.Scopes[apiScope]; ok {
scopeSet := propertySet.AddPropertySet(apiScope.propertyName)
@@ -3025,7 +3077,7 @@
var jars []string
for _, p := range properties.Jars {
- dest := filepath.Join(scopeDir, ctx.Name()+"-stubs.jar")
+ dest := filepath.Join(scopeDir, stem+"-stubs.jar")
ctx.SnapshotBuilder().CopyToSnapshot(p, dest)
jars = append(jars, dest)
}
@@ -3033,31 +3085,31 @@
if ctx.SdkModuleContext().Config().IsEnvTrue("SOONG_SDK_SNAPSHOT_USE_SRCJAR") {
// Copy the stubs source jar into the snapshot zip as is.
- srcJarSnapshotPath := filepath.Join(scopeDir, ctx.Name()+".srcjar")
+ srcJarSnapshotPath := filepath.Join(scopeDir, stem+".srcjar")
ctx.SnapshotBuilder().CopyToSnapshot(properties.StubsSrcJar, srcJarSnapshotPath)
scopeSet.AddProperty("stub_srcs", []string{srcJarSnapshotPath})
} else {
// Merge the stubs source jar into the snapshot zip so that when it is unpacked
// the source files are also unpacked.
- snapshotRelativeDir := filepath.Join(scopeDir, ctx.Name()+"_stub_sources")
+ snapshotRelativeDir := filepath.Join(scopeDir, stem+"_stub_sources")
ctx.SnapshotBuilder().UnzipToSnapshot(properties.StubsSrcJar, snapshotRelativeDir)
scopeSet.AddProperty("stub_srcs", []string{snapshotRelativeDir})
}
if properties.CurrentApiFile != nil {
- currentApiSnapshotPath := apiScope.snapshotRelativeCurrentApiTxtPath(ctx.Name())
+ currentApiSnapshotPath := apiScope.snapshotRelativeCurrentApiTxtPath(stem)
ctx.SnapshotBuilder().CopyToSnapshot(properties.CurrentApiFile, currentApiSnapshotPath)
scopeSet.AddProperty("current_api", currentApiSnapshotPath)
}
if properties.RemovedApiFile != nil {
- removedApiSnapshotPath := apiScope.snapshotRelativeRemovedApiTxtPath(ctx.Name())
+ removedApiSnapshotPath := apiScope.snapshotRelativeRemovedApiTxtPath(stem)
ctx.SnapshotBuilder().CopyToSnapshot(properties.RemovedApiFile, removedApiSnapshotPath)
scopeSet.AddProperty("removed_api", removedApiSnapshotPath)
}
if properties.AnnotationsZip != nil {
- annotationsSnapshotPath := filepath.Join(scopeDir, ctx.Name()+"_annotations.zip")
+ annotationsSnapshotPath := filepath.Join(scopeDir, stem+"_annotations.zip")
ctx.SnapshotBuilder().CopyToSnapshot(properties.AnnotationsZip, annotationsSnapshotPath)
scopeSet.AddProperty("annotations", annotationsSnapshotPath)
}
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 805bc22..096bca8 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) {
diff --git a/java/testing.go b/java/testing.go
index 511cc5d..49430ee 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -59,11 +59,9 @@
}.AddToFixture(),
)
-// Test fixture preparer that will define all default java modules except the
-// fake_tool_binary for dex2oatd.
-var PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd = android.GroupFixturePreparers(
- // Make sure that all the module types used in the defaults are registered.
- PrepareForTestWithJavaBuildComponents,
+var prepareForTestWithFrameworkDeps = android.GroupFixturePreparers(
+ // The java default module definitions.
+ android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", gatherRequiredDepsForTest()),
// Additional files needed when test disallows non-existent source.
android.MockFS{
// Needed for framework-res
@@ -77,8 +75,14 @@
"build/make/core/proguard.flags": nil,
"build/make/core/proguard_basic_keeps.flags": nil,
}.AddToFixture(),
- // The java default module definitions.
- android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", gatherRequiredDepsForTest()),
+)
+
+// Test fixture preparer that will define all default java modules except the
+// fake_tool_binary for dex2oatd.
+var PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd = android.GroupFixturePreparers(
+ // Make sure that all the module types used in the defaults are registered.
+ PrepareForTestWithJavaBuildComponents,
+ prepareForTestWithFrameworkDeps,
// Add dexpreopt compat libs (android.test.base, etc.) and a fake dex2oatd module.
dexpreopt.PrepareForTestWithDexpreoptCompatLibs,
)
@@ -141,6 +145,30 @@
"30": {},
})
+var prepareForTestWithFrameworkJacocoInstrumentation = android.GroupFixturePreparers(
+ android.FixtureMergeEnv(map[string]string{
+ "EMMA_INSTRUMENT_FRAMEWORK": "true",
+ }),
+ PrepareForTestWithJacocoInstrumentation,
+)
+
+// PrepareForTestWithJacocoInstrumentation creates a mock jacocoagent library that can be
+// depended on as part of the build process for instrumented Java modules.
+var PrepareForTestWithJacocoInstrumentation = android.GroupFixturePreparers(
+ android.FixtureMergeEnv(map[string]string{
+ "EMMA_INSTRUMENT": "true",
+ }),
+ android.FixtureAddFile("jacocoagent/Test.java", nil),
+ android.FixtureAddFile("jacocoagent/Android.bp", []byte(`
+ java_library {
+ name: "jacocoagent",
+ host_supported: true,
+ srcs: ["Test.java"],
+ sdk_version: "current",
+ }
+ `)),
+)
+
// FixtureWithPrebuiltApis creates a preparer that will define prebuilt api modules for the
// specified releases and modules.
//
@@ -365,6 +393,7 @@
aidl: {
export_include_dirs: ["framework/aidl"],
},
+ compile_dex: true,
}
android_app {
diff --git a/licenses/Android.bp b/licenses/Android.bp
index 133f7f7..61b17bf 100644
--- a/licenses/Android.bp
+++ b/licenses/Android.bp
@@ -42,7 +42,7 @@
license_kind {
name: "SPDX-license-identifier-0BSD",
- conditions: ["unencumbered"],
+ conditions: ["permissive"],
url: "https://spdx.org/licenses/0BSD",
}
@@ -762,7 +762,7 @@
license_kind {
name: "SPDX-license-identifier-GPL-2.0-with-classpath-exception",
- conditions: ["restricted"],
+ conditions: ["permissive"],
url: "https://spdx.org/licenses/GPL-2.0-with-classpath-exception.html",
}
@@ -810,7 +810,7 @@
license_kind {
name: "SPDX-license-identifier-GPL-with-classpath-exception",
- conditions: ["restricted"],
+ conditions: ["permissive"],
}
license_kind {
@@ -933,7 +933,7 @@
license_kind {
name: "SPDX-license-identifier-MIT-0",
- conditions: ["notice"],
+ conditions: ["permissive"],
url: "https://spdx.org/licenses/MIT-0.html",
}
diff --git a/linkerconfig/proto/Android.bp b/linkerconfig/proto/Android.bp
index 3b1e4ab..754e7bf 100644
--- a/linkerconfig/proto/Android.bp
+++ b/linkerconfig/proto/Android.bp
@@ -19,14 +19,6 @@
python_library_host {
name: "linker_config_proto",
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- },
- },
srcs: [
"linker_config.proto",
],
diff --git a/python/Android.bp b/python/Android.bp
index e49fa6a..99c02bd 100644
--- a/python/Android.bp
+++ b/python/Android.bp
@@ -27,3 +27,15 @@
],
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 af29bb6..1f49a54 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,6 +116,22 @@
// 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 {
@@ -128,10 +144,6 @@
IntermPathForModuleOut() android.OptionalPath
}
-var (
- StubTemplateHost = "build/soong/python/scripts/stub_template_host.txt"
-)
-
func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
module := newModule(hod, android.MultilibFirst)
decorator := &binaryDecorator{pythonInstaller: NewPythonInstaller("bin", "")}
@@ -180,9 +192,13 @@
})
}
+ addTopDirectoriesToPath := !proptools.BoolDefault(binary.binaryProperties.Dont_add_top_level_directories_to_path, true)
+ dontAddEntrypointFolderToPath := proptools.BoolDefault(binary.binaryProperties.Dont_add_entrypoint_folder_to_path, true)
+
binFile := registerBuildActionForParFile(ctx, embeddedLauncher, launcherPath,
binary.getHostInterpreterName(ctx, actualVersion),
- main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...))
+ main, binary.getStem(ctx), append(android.Paths{srcsZip}, depsSrcsZips...),
+ addTopDirectoriesToPath, dontAddEntrypointFolderToPath)
return android.OptionalPathForPath(binFile)
}
diff --git a/python/builder.go b/python/builder.go
index 7d7239c..f7f9a99 100644
--- a/python/builder.go
+++ b/python/builder.go
@@ -20,7 +20,6 @@
"strings"
"android/soong/android"
-
"github.com/google/blueprint"
_ "github.com/google/blueprint/bootstrap"
)
@@ -44,13 +43,25 @@
hostPar = pctx.AndroidStaticRule("hostPar",
blueprint.RuleParams{
- Command: `sed -e 's/%interpreter%/$interp/g' -e 's/%main%/$main/g' $template > $stub && ` +
+ 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 $stub $out $srcsZips && ` +
- `chmod +x $out && (rm -f $stub; rm -f ${out}.prefix)`,
- CommandDeps: []string{"$mergeParCmd"},
+ `$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", "template", "stub", "srcsZips")
+ "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 && ` +
+ "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 &&` +
+ `$mergeParCmd -p --prefix ${out}.prefix -pm $out.main $out $srcsZips $out.entrypoint_zip && ` +
+ "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")
embeddedPar = pctx.AndroidStaticRule("embeddedPar",
blueprint.RuleParams{
@@ -58,7 +69,7 @@
`sed 's/ENTRY_POINT/$main/' build/soong/python/scripts/main.py >$out.main &&` +
`$mergeParCmd -p -pm $out.main --prefix $launcher $out $srcsZips && ` +
`chmod +x $out && rm -rf $out.main`,
- CommandDeps: []string{"$mergeParCmd", "$parCmd", "build/soong/python/scripts/main.py"},
+ CommandDeps: []string{"$mergeParCmd", "build/soong/python/scripts/main.py"},
},
"main", "srcsZips", "launcher")
@@ -81,7 +92,7 @@
func registerBuildActionForParFile(ctx android.ModuleContext, embeddedLauncher bool,
launcherPath android.OptionalPath, interpreter, main, binName string,
- srcsZips android.Paths) android.Path {
+ srcsZips android.Paths, addTopDirectoriesToPath bool, dontAddEntrypointFolderToPath bool) android.Path {
// .intermediate output path for bin executable.
binFile := android.PathForModuleOut(ctx, binName)
@@ -90,26 +101,37 @@
implicits := srcsZips
if !embeddedLauncher {
- // the path of stub_template_host.txt from source tree.
- template := android.PathForSource(ctx, StubTemplateHost)
- implicits = append(implicits, template)
-
- // intermediate output path for __main__.py
- stub := android.PathForModuleOut(ctx, mainFileName).String()
-
- 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),
- "template": template.String(),
- "stub": stub,
- "srcsZips": strings.Join(srcsZips.Strings(), " "),
- },
- })
+ 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,
+ },
+ })
+ }
} 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 dba23a7..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,16 +30,13 @@
func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
-func defaultsFactory() android.Module {
- return DefaultsFactory()
-}
-
-func DefaultsFactory(props ...interface{}) android.Module {
+func DefaultsFactory() android.Module {
module := &Defaults{}
- module.AddProperties(props...)
module.AddProperties(
&BaseProperties{},
+ &android.ProtoProperties{},
+ &BinaryProperties{},
)
android.InitDefaultsModule(module)
diff --git a/python/python.go b/python/python.go
index 8364169..6f3a0ec 100644
--- a/python/python.go
+++ b/python/python.go
@@ -120,6 +120,15 @@
// 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 {
@@ -347,10 +356,6 @@
protoExt = ".proto"
pyVersion2 = "PY2"
pyVersion3 = "PY3"
- initFileName = "__init__.py"
- mainFileName = "__main__.py"
- entryPointFile = "entry_point.txt"
- parFileExt = ".zip"
internalPath = "internal"
)
@@ -672,8 +677,25 @@
protoFlags := android.GetProtoFlags(ctx, &p.protoProperties)
protoFlags.OutTypeFlag = "--python_out"
+ protosRespectPkgPath := proptools.BoolDefault(p.properties.Proto.Respect_pkg_path, true)
+ pkgPathForProtos := pkgPath
+ if pkgPathForProtos != "" && protosRespectPkgPath {
+ pkgPathStagingDir := android.PathForModuleGen(ctx, "protos_staged_for_pkg_path")
+ rule := android.NewRuleBuilder(pctx, ctx)
+ var stagedProtoSrcs android.Paths
+ for _, srcFile := range protoSrcs {
+ stagedProtoSrc := pkgPathStagingDir.Join(ctx, pkgPath, srcFile.Rel())
+ rule.Command().Text("mkdir -p").Flag(filepath.Base(stagedProtoSrc.String()))
+ rule.Command().Text("cp -f").Input(srcFile).Output(stagedProtoSrc)
+ stagedProtoSrcs = append(stagedProtoSrcs, stagedProtoSrc)
+ }
+ rule.Build("stage_protos_for_pkg_path", "Stage protos for pkg_path")
+ protoSrcs = stagedProtoSrcs
+ pkgPathForProtos = ""
+ }
+
for _, srcFile := range protoSrcs {
- zip := genProto(ctx, srcFile, protoFlags, pkgPath)
+ zip := genProto(ctx, srcFile, protoFlags, pkgPathForProtos)
zips = append(zips, zip)
}
}
diff --git a/python/python_test.go b/python/python_test.go
index f57f504..42a1ffb 100644
--- a/python/python_test.go
+++ b/python/python_test.go
@@ -300,8 +300,6 @@
filepath.Join("dir", "file2.py"): nil,
filepath.Join("dir", "bin.py"): nil,
filepath.Join("dir", "file4.py"): nil,
- StubTemplateHost: []byte(`PYTHON_BINARY = '%interpreter%'
- MAIN_FILE = '%main%'`),
},
expectedBinaries: []pyModule{
{
diff --git a/python/scripts/main_non_embedded.py b/python/scripts/main_non_embedded.py
new file mode 100644
index 0000000..ffbaaa8
--- /dev/null
+++ b/python/scripts/main_non_embedded.py
@@ -0,0 +1,6 @@
+import runpy
+
+# The purpose of this file is to implement python 3.11+'s
+# PYTHON_SAFE_PATH / -P option on older python versions.
+
+runpy._run_module_as_main("ENTRY_POINT", alter_argv=False)
diff --git a/python/scripts/stub_template_host.txt b/python/scripts/stub_template_host.txt
index 138404b..a0ddffe 100644
--- a/python/scripts/stub_template_host.txt
+++ b/python/scripts/stub_template_host.txt
@@ -1,7 +1,6 @@
#!/usr/bin/env '%interpreter%'
import os
-import re
import tempfile
import shutil
import sys
@@ -15,56 +14,31 @@
# Don't imply 'import site' on initialization
PYTHON_ARG = '-S'
-def SearchPathEnv(name):
- search_path = os.getenv('PATH', os.defpath).split(os.pathsep)
- for directory in search_path:
- if directory == '': continue
- path = os.path.join(directory, name)
- # Check if path is actual executable file.
- if os.path.isfile(path) and os.access(path, os.X_OK):
- return path
- return None
-
-def FindPythonBinary():
- if PYTHON_BINARY.startswith('/'):
- # Case 1: Python interpreter is directly provided with absolute path.
- return PYTHON_BINARY
- else:
- # Case 2: Find Python interpreter through environment variable: PATH.
- return SearchPathEnv(PYTHON_BINARY)
-
-# Create the runfiles tree by extracting the zip file
-def ExtractRunfiles():
- temp_dir = tempfile.mkdtemp("", "Soong.python_")
- zf = zipfile.ZipFile(os.path.dirname(__file__))
- zf.extractall(temp_dir)
- return temp_dir
-
def Main():
args = sys.argv[1:]
- new_env = {}
- runfiles_path = None
-
+ runfiles_path = tempfile.mkdtemp(prefix="Soong.python_")
try:
- runfiles_path = ExtractRunfiles()
+ zf = zipfile.ZipFile(os.path.dirname(__file__))
+ zf.extractall(runfiles_path)
+ zf.close()
# Add runfiles path to PYTHONPATH.
python_path_entries = [runfiles_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
+ 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)
old_python_path = os.environ.get(PYTHON_PATH)
- separator = ':'
- new_python_path = separator.join(python_path_entries)
- # Copy old PYTHONPATH.
if old_python_path:
- new_python_path += separator + old_python_path
- new_env[PYTHON_PATH] = new_python_path
+ os.environ.update({PYTHON_PATH: new_python_path + ":" + old_python_path})
+ else:
+ os.environ.update({PYTHON_PATH: new_python_path})
# Now look for main python source file.
main_filepath = os.path.join(runfiles_path, MAIN_FILE)
@@ -73,21 +47,14 @@
assert os.access(main_filepath, os.R_OK), \
'Cannot exec() %r: file not readable.' % main_filepath
- python_program = FindPythonBinary()
- if python_program is None:
- raise AssertionError('Could not find python binary: ' + PYTHON_BINARY)
- args = [python_program, PYTHON_ARG, main_filepath] + args
-
- os.environ.update(new_env)
+ args = [PYTHON_BINARY, PYTHON_ARG, main_filepath] + args
sys.stdout.flush()
- retCode = subprocess.call(args)
- sys.exit(retCode)
- except:
- raise
+ # close_fds=False so that you can run binaries with files provided on the command line:
+ # my_python_app --file <(echo foo)
+ sys.exit(subprocess.call(args, close_fds=False))
finally:
- if runfiles_path is not None:
- shutil.rmtree(runfiles_path, True)
+ shutil.rmtree(runfiles_path, ignore_errors=True)
if __name__ == '__main__':
Main()
diff --git a/python/tests/dont_import_folder_of_entrypoint/Android.bp b/python/tests/dont_import_folder_of_entrypoint/Android.bp
new file mode 100644
index 0000000..ea5076e
--- /dev/null
+++ b/python/tests/dont_import_folder_of_entrypoint/Android.bp
@@ -0,0 +1,27 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+python_test_host {
+ name: "py_dont_import_folder_of_entrypoint_test",
+ main: "mypkg/main.py",
+ srcs: [
+ "mypkg/main.py",
+ "mypkg/mymodule.py",
+ ],
+ defaults: ["modern_python_path_defaults"],
+}
+
+python_test_host {
+ name: "py_dont_import_folder_of_entrypoint_test_embedded_launcher",
+ main: "mypkg/main.py",
+ srcs: [
+ "mypkg/main.py",
+ "mypkg/mymodule.py",
+ ],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
+}
diff --git a/python/tests/dont_import_folder_of_entrypoint/mypkg/main.py b/python/tests/dont_import_folder_of_entrypoint/mypkg/main.py
new file mode 100644
index 0000000..c6a36ed
--- /dev/null
+++ b/python/tests/dont_import_folder_of_entrypoint/mypkg/main.py
@@ -0,0 +1,15 @@
+import unittest
+import sys
+
+class TestProtoWithPkgPath(unittest.TestCase):
+
+ def test_cant_import_mymodule_directly(self):
+ with self.assertRaises(ImportError):
+ import mymodule
+
+ def test_can_import_mymodule_by_parent_package(self):
+ import mypkg.mymodule
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/tests/dont_import_folder_of_entrypoint/mypkg/mymodule.py b/python/tests/dont_import_folder_of_entrypoint/mypkg/mymodule.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/python/tests/dont_import_folder_of_entrypoint/mypkg/mymodule.py
diff --git a/python/tests/proto_pkg_path/Android.bp b/python/tests/proto_pkg_path/Android.bp
new file mode 100644
index 0000000..ef79850
--- /dev/null
+++ b/python/tests/proto_pkg_path/Android.bp
@@ -0,0 +1,17 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+python_test_host {
+ name: "py_proto_pkg_path_test",
+ main: "main.py",
+ srcs: [
+ "main.py",
+ "proto/*.proto",
+ ],
+ pkg_path: "mylib/subpackage",
+ proto: {
+ canonical_path_from_root: false,
+ respect_pkg_path: true,
+ },
+}
diff --git a/python/tests/proto_pkg_path/main.py b/python/tests/proto_pkg_path/main.py
new file mode 100644
index 0000000..c4acdde
--- /dev/null
+++ b/python/tests/proto_pkg_path/main.py
@@ -0,0 +1,18 @@
+import sys
+
+import unittest
+import mylib.subpackage.proto.test_pb2 as test_pb2
+import mylib.subpackage.proto.common_pb2 as common_pb2
+
+print(sys.path)
+
+class TestProtoWithPkgPath(unittest.TestCase):
+
+ def test_main(self):
+ x = test_pb2.MyMessage(name="foo",
+ common = common_pb2.MyCommonMessage(common="common"))
+ self.assertEqual(x.name, "foo")
+ self.assertEqual(x.common.common, "common")
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/tests/proto_pkg_path/proto/common.proto b/python/tests/proto_pkg_path/proto/common.proto
new file mode 100644
index 0000000..b24b8ea
--- /dev/null
+++ b/python/tests/proto_pkg_path/proto/common.proto
@@ -0,0 +1,5 @@
+syntax = "proto3";
+
+message MyCommonMessage {
+ string common = 1;
+}
diff --git a/python/tests/proto_pkg_path/proto/test.proto b/python/tests/proto_pkg_path/proto/test.proto
new file mode 100644
index 0000000..55f3b17
--- /dev/null
+++ b/python/tests/proto_pkg_path/proto/test.proto
@@ -0,0 +1,8 @@
+syntax = "proto3";
+
+import "mylib/subpackage/proto/common.proto";
+
+message MyMessage {
+ string name = 1;
+ MyCommonMessage common = 2;
+}
diff --git a/python/tests/top_level_dirs/Android.bp b/python/tests/top_level_dirs/Android.bp
new file mode 100644
index 0000000..fe13d4f
--- /dev/null
+++ b/python/tests/top_level_dirs/Android.bp
@@ -0,0 +1,13 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+python_test_host {
+ name: "py_dont_add_top_level_dirs_test",
+ main: "main.py",
+ srcs: [
+ "main.py",
+ "mypkg/mymodule.py",
+ ],
+ dont_add_top_level_directories_to_path: true,
+}
diff --git a/python/tests/top_level_dirs/main.py b/python/tests/top_level_dirs/main.py
new file mode 100644
index 0000000..9f30bfa
--- /dev/null
+++ b/python/tests/top_level_dirs/main.py
@@ -0,0 +1,17 @@
+import unittest
+import sys
+
+print(sys.path, file=sys.stderr)
+
+class TestProtoWithPkgPath(unittest.TestCase):
+
+ def test_cant_import_mymodule_directly(self):
+ with self.assertRaises(ImportError):
+ import mymodule
+
+ def test_can_import_mymodule_by_parent_package(self):
+ import mypkg.mymodule
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/python/tests/top_level_dirs/mypkg/mymodule.py b/python/tests/top_level_dirs/mypkg/mymodule.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/python/tests/top_level_dirs/mypkg/mymodule.py
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/global.go b/rust/config/global.go
index e676837..81aec7e 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -24,7 +24,7 @@
var pctx = android.NewPackageContext("android/soong/rust/config")
var (
- RustDefaultVersion = "1.63.0"
+ RustDefaultVersion = "1.64.0"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2021"
Stdlibs = []string{
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/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/Android.bp b/scripts/Android.bp
index b5b588b..5dd45cd 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -199,6 +199,17 @@
],
}
+python_binary_host {
+ name: "build-apex-bundle",
+ main: "build-apex-bundle.py",
+ srcs: [
+ "build-apex-bundle.py",
+ ],
+ required: [
+ "bundletool",
+ ],
+}
+
sh_binary_host {
name: "list_image",
src: "list_image.sh",
diff --git a/scripts/OWNERS b/scripts/OWNERS
index 3f4f9c0..7b003fd 100644
--- a/scripts/OWNERS
+++ b/scripts/OWNERS
@@ -1,5 +1,4 @@
per-file system-clang-format,system-clang-format-2 = enh@google.com,smoreland@google.com
-per-file build-aml-prebuilts.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com
per-file construct_context.py = ngeoffray@google.com,calin@google.com,skvadrik@google.com
per-file conv_linker_config.py = kiyoungkim@google.com, jiyong@google.com, jooyung@google.com
-per-file gen_ndk*.sh,gen_java*.sh = sophiez@google.com, allenhair@google.com
\ No newline at end of file
+per-file gen_ndk*.sh,gen_java*.sh = sophiez@google.com, allenhair@google.com
diff --git a/scripts/build-aml-prebuilts.sh b/scripts/build-aml-prebuilts.sh
deleted file mode 100755
index 1a16f7c..0000000
--- a/scripts/build-aml-prebuilts.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/bash -e
-
-# This script is similar to "m" but builds in --soong-only mode, and handles
-# special cases to make that mode work. All arguments are passed on to
-# build/soong/soong_ui.bash.
-#
-# --soong-only bypasses the kati step and hence the make logic that e.g. doesn't
-# handle more than two device architectures. It is particularly intended for use
-# with TARGET_PRODUCT=mainline_sdk to build 'sdk' and 'module_export' Soong
-# modules in TARGET_ARCH_SUITE=mainline_sdk mode so that they get all four
-# device architectures (artifacts get installed in $OUT_DIR/soong/mainline-sdks
-# - cf PathForMainlineSdksInstall in android/paths.go).
-#
-# TODO(b/174315599): Replace this script completely with a 'soong_ui.bash
-# --soong-only' invocation. For now it is still necessary to set up
-# build_number.txt.
-
-if [ ! -e build/soong/soong_ui.bash ]; then
- echo "$0 must be run from the top of the tree"
- exit 1
-fi
-
-export OUT_DIR=${OUT_DIR:-out}
-
-if [ -e ${OUT_DIR}/soong/.soong.kati_enabled ]; then
- # If ${OUT_DIR} has been created without --soong-only, Soong will create an
- # ${OUT_DIR}/soong/build.ninja that leaves out many targets which are
- # expected to be supplied by the .mk files, and that might cause errors in
- # "m --soong-only" below. We therefore default to a different out dir
- # location in that case.
- AML_OUT_DIR=out/aml
- echo "Avoiding in-make OUT_DIR '${OUT_DIR}' - building in '${AML_OUT_DIR}' instead"
- OUT_DIR=${AML_OUT_DIR}
-fi
-
-mkdir -p ${OUT_DIR}/soong
-
-# The --dumpvars-mode invocation will run Soong in normal make mode where it
-# creates .soong.kati_enabled. That would clobber our real out directory, so we
-# need to use a different OUT_DIR.
-vars="$(OUT_DIR=${OUT_DIR}/dumpvars_mode build/soong/soong_ui.bash \
- --dumpvars-mode --vars=BUILD_NUMBER)"
-# Assign to a variable and eval that, since bash ignores any error status
-# from the command substitution if it's directly on the eval line.
-eval $vars
-
-# Some Soong build rules may require this, and the failure mode if it's missing
-# is confusing (b/172548608).
-echo -n ${BUILD_NUMBER} > ${OUT_DIR}/soong/build_number.txt
-
-build/soong/soong_ui.bash --make-mode --soong-only "$@"
diff --git a/scripts/build-apex-bundle.py b/scripts/build-apex-bundle.py
new file mode 100644
index 0000000..dcdd9ef
--- /dev/null
+++ b/scripts/build-apex-bundle.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2022 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""A tool to create an APEX bundle out of Soong-built base.zip"""
+
+from __future__ import print_function
+
+import argparse
+import sys
+import tempfile
+import zipfile
+import os
+import json
+import subprocess
+
+
+def parse_args():
+ """Parse commandline arguments."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--overwrite',
+ action='store_true',
+ help='If set, any previous existing output will be overwritten')
+ parser.add_argument('--output', help='specify the output .aab file')
+ parser.add_argument(
+ 'input', help='specify the input <apex name>-base.zip file')
+ return parser.parse_args()
+
+
+def build_bundle(input, output, overwrite):
+ base_zip = zipfile.ZipFile(input)
+
+ tmpdir = tempfile.mkdtemp()
+ tmp_base_zip = os.path.join(tmpdir, 'base.zip')
+ tmp_bundle_config = os.path.join(tmpdir, 'bundle_config.json')
+
+ bundle_config = None
+ abi = []
+
+ # This block performs three tasks
+ # - extract/load bundle_config.json from input => bundle_config
+ # - get ABI from input => abi
+ # - discard bundle_config.json from input => tmp/base.zip
+ with zipfile.ZipFile(tmp_base_zip, 'a') as out:
+ for info in base_zip.infolist():
+
+ # discard bundle_config.json
+ if info.filename == 'bundle_config.json':
+ bundle_config = json.load(base_zip.open(info.filename))
+ continue
+
+ # get ABI from apex/{abi}.img
+ dir, basename = os.path.split(info.filename)
+ name, ext = os.path.splitext(basename)
+ if dir == 'apex' and ext == '.img':
+ abi.append(name)
+
+ # copy entries to tmp/base.zip
+ out.writestr(info, base_zip.open(info.filename).read())
+
+ base_zip.close()
+
+ if not bundle_config:
+ raise ValueError(f'bundle_config.json not found in {input}')
+ if len(abi) != 1:
+ raise ValueError(f'{input} should have only a single apex/*.img file')
+
+ # add ABI to tmp/bundle_config.json
+ apex_config = bundle_config['apex_config']
+ if 'supported_abi_set' not in apex_config:
+ apex_config['supported_abi_set'] = []
+ supported_abi_set = apex_config['supported_abi_set']
+ supported_abi_set.append({'abi': abi})
+
+ with open(tmp_bundle_config, 'w') as out:
+ json.dump(bundle_config, out)
+
+ # invoke bundletool
+ cmd = [
+ 'bundletool', 'build-bundle', '--config', tmp_bundle_config, '--modules',
+ tmp_base_zip, '--output', output
+ ]
+ if overwrite:
+ cmd.append('--overwrite')
+ subprocess.check_call(cmd)
+
+
+def main():
+ """Program entry point."""
+ try:
+ args = parse_args()
+ build_bundle(args.input, args.output, args.overwrite)
+
+ # pylint: disable=broad-except
+ except Exception as err:
+ print('error: ' + str(err), file=sys.stderr)
+ sys.exit(-1)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/hiddenapi/Android.bp b/scripts/hiddenapi/Android.bp
index 07878f9..1e89efe 100644
--- a/scripts/hiddenapi/Android.bp
+++ b/scripts/hiddenapi/Android.bp
@@ -18,29 +18,31 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
+python_defaults {
+ name: "hiddenapi_defaults",
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
+}
+
python_binary_host {
name: "analyze_bcpf",
main: "analyze_bcpf.py",
+ defaults: ["hiddenapi_defaults"],
srcs: ["analyze_bcpf.py"],
// Make sure that the bpmodify tool is built.
data: [":bpmodify"],
libs: [
"signature_trie",
],
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- embedded_launcher: true,
- },
- },
}
python_test_host {
name: "analyze_bcpf_test",
main: "analyze_bcpf_test.py",
+ defaults: ["hiddenapi_defaults"],
srcs: [
"analyze_bcpf.py",
"analyze_bcpf_test.py",
@@ -50,15 +52,6 @@
libs: [
"signature_trie",
],
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- embedded_launcher: true,
- },
- },
test_options: {
unit_test: true,
},
@@ -67,49 +60,25 @@
python_binary_host {
name: "merge_csv",
main: "merge_csv.py",
+ defaults: ["hiddenapi_defaults"],
srcs: ["merge_csv.py"],
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- embedded_launcher: true,
- },
- },
}
python_binary_host {
name: "generate_hiddenapi_lists",
main: "generate_hiddenapi_lists.py",
+ defaults: ["hiddenapi_defaults"],
srcs: ["generate_hiddenapi_lists.py"],
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- embedded_launcher: true,
- },
- },
}
python_test_host {
name: "generate_hiddenapi_lists_test",
main: "generate_hiddenapi_lists_test.py",
+ defaults: ["hiddenapi_defaults"],
srcs: [
"generate_hiddenapi_lists.py",
"generate_hiddenapi_lists_test.py",
],
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- embedded_launcher: true,
- },
- },
test_options: {
unit_test: true,
},
@@ -123,17 +92,9 @@
python_test_host {
name: "signature_trie_test",
main: "signature_trie_test.py",
+ defaults: ["hiddenapi_defaults"],
srcs: ["signature_trie_test.py"],
libs: ["signature_trie"],
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- embedded_launcher: true,
- },
- },
test_options: {
unit_test: true,
},
@@ -142,24 +103,17 @@
python_binary_host {
name: "verify_overlaps",
main: "verify_overlaps.py",
+ defaults: ["hiddenapi_defaults"],
srcs: ["verify_overlaps.py"],
libs: [
"signature_trie",
],
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- embedded_launcher: true,
- },
- },
}
python_test_host {
name: "verify_overlaps_test",
main: "verify_overlaps_test.py",
+ defaults: ["hiddenapi_defaults"],
srcs: [
"verify_overlaps.py",
"verify_overlaps_test.py",
@@ -167,15 +121,6 @@
libs: [
"signature_trie",
],
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- embedded_launcher: true,
- },
- },
test_options: {
unit_test: true,
},
@@ -184,34 +129,18 @@
python_binary_host {
name: "signature_patterns",
main: "signature_patterns.py",
+ defaults: ["hiddenapi_defaults"],
srcs: ["signature_patterns.py"],
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- embedded_launcher: true,
- },
- },
}
python_test_host {
name: "signature_patterns_test",
main: "signature_patterns_test.py",
+ defaults: ["hiddenapi_defaults"],
srcs: [
"signature_patterns.py",
"signature_patterns_test.py",
],
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- embedded_launcher: true,
- },
- },
test_options: {
unit_test: true,
},
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 c93055a..1b64130 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)
}
@@ -895,3 +943,222 @@
snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot),
)
}
+
+func testSnapshotWithBootClasspathFragment_MinSdkVersion(t *testing.T, targetBuildRelease string,
+ expectedSdkSnapshot string,
+ expectedCopyRules string,
+ expectedStubFlagsInputs []string,
+ suffix string) {
+
+ result := android.GroupFixturePreparers(
+ prepareForSdkTestWithJava,
+ java.PrepareForTestWithJavaDefaultModules,
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.FixtureWithLastReleaseApis("mysdklibrary", "mynewsdklibrary"),
+ java.FixtureConfigureApexBootJars("myapex:mysdklibrary", "myapex:mynewsdklibrary"),
+ prepareForSdkTestWithApex,
+
+ // Add a platform_bootclasspath that depends on the fragment.
+ fixtureAddPlatformBootclasspathForBootclasspathFragment("myapex", "mybootclasspathfragment"),
+
+ android.FixtureMergeEnv(map[string]string{
+ "SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": targetBuildRelease,
+ }),
+
+ android.FixtureWithRootAndroidBp(`
+ sdk {
+ name: "mysdk",
+ apexes: ["myapex"],
+ }
+
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ min_sdk_version: "S",
+ bootclasspath_fragments: ["mybootclasspathfragment"],
+ }
+
+ bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ apex_available: ["myapex"],
+ contents: [
+ "mysdklibrary",
+ "mynewsdklibrary",
+ ],
+
+ hidden_api: {
+ split_packages: [],
+ },
+ }
+
+ java_sdk_library {
+ name: "mysdklibrary",
+ apex_available: ["myapex"],
+ srcs: ["Test.java"],
+ shared_library: false,
+ public: {enabled: true},
+ min_sdk_version: "S",
+ }
+
+ java_sdk_library {
+ name: "mynewsdklibrary",
+ apex_available: ["myapex"],
+ srcs: ["Test.java"],
+ compile_dex: true,
+ public: {enabled: true},
+ min_sdk_version: "Tiramisu",
+ permitted_packages: ["mynewsdklibrary"],
+ }
+ `),
+ ).RunTest(t)
+
+ bcpf := result.ModuleForTests("mybootclasspathfragment", "android_common")
+ rule := bcpf.Output("out/soong/.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi" + suffix + "/stub-flags.csv")
+ android.AssertPathsRelativeToTopEquals(t, "stub flags inputs", expectedStubFlagsInputs, rule.Implicits)
+
+ CheckSnapshot(t, result, "mysdk", "",
+ checkAndroidBpContents(expectedSdkSnapshot),
+ checkAllCopyRules(expectedCopyRules),
+ )
+}
+
+func TestSnapshotWithBootClasspathFragment_MinSdkVersion(t *testing.T) {
+ t.Run("target S build", func(t *testing.T) {
+ expectedSnapshot := `
+// This is auto-generated. DO NOT EDIT.
+
+prebuilt_bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["myapex"],
+ contents: ["mysdklibrary"],
+ hidden_api: {
+ annotation_flags: "hiddenapi/annotation-flags.csv",
+ metadata: "hiddenapi/metadata.csv",
+ index: "hiddenapi/index.csv",
+ stub_flags: "hiddenapi/stub-flags.csv",
+ all_flags: "hiddenapi/all-flags.csv",
+ },
+}
+
+java_sdk_library_import {
+ name: "mysdklibrary",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["myapex"],
+ shared_library: false,
+ public: {
+ jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
+ stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
+ current_api: "sdk_library/public/mysdklibrary.txt",
+ removed_api: "sdk_library/public/mysdklibrary-removed.txt",
+ sdk_version: "current",
+ },
+}
+`
+ expectedCopyRules := `
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/annotation-flags.csv -> hiddenapi/annotation-flags.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/metadata.csv -> hiddenapi/metadata.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/index.csv -> hiddenapi/index.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/stub-flags.csv -> hiddenapi/stub-flags.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/all-flags.csv -> hiddenapi/all-flags.csv
+.intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
+.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
+.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
+`
+
+ // On S the stub flags should only be generated from mysdklibrary as mynewsdklibrary is not part
+ // of the snapshot.
+ expectedStubFlagsInputs := []string{
+ "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar",
+ "out/soong/.intermediates/mysdklibrary/android_common/aligned/mysdklibrary.jar",
+ }
+
+ testSnapshotWithBootClasspathFragment_MinSdkVersion(t, "S",
+ expectedSnapshot, expectedCopyRules, expectedStubFlagsInputs, "-for-sdk-snapshot")
+ })
+
+ t.Run("target-Tiramisu-build", func(t *testing.T) {
+ expectedSnapshot := `
+// This is auto-generated. DO NOT EDIT.
+
+prebuilt_bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["myapex"],
+ contents: [
+ "mysdklibrary",
+ "mynewsdklibrary",
+ ],
+ hidden_api: {
+ annotation_flags: "hiddenapi/annotation-flags.csv",
+ metadata: "hiddenapi/metadata.csv",
+ index: "hiddenapi/index.csv",
+ signature_patterns: "hiddenapi/signature-patterns.csv",
+ filtered_stub_flags: "hiddenapi/filtered-stub-flags.csv",
+ filtered_flags: "hiddenapi/filtered-flags.csv",
+ },
+}
+
+java_sdk_library_import {
+ name: "mysdklibrary",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["myapex"],
+ shared_library: false,
+ public: {
+ jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
+ stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
+ current_api: "sdk_library/public/mysdklibrary.txt",
+ removed_api: "sdk_library/public/mysdklibrary-removed.txt",
+ sdk_version: "current",
+ },
+}
+
+java_sdk_library_import {
+ name: "mynewsdklibrary",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["myapex"],
+ shared_library: true,
+ compile_dex: true,
+ permitted_packages: ["mynewsdklibrary"],
+ public: {
+ jars: ["sdk_library/public/mynewsdklibrary-stubs.jar"],
+ stub_srcs: ["sdk_library/public/mynewsdklibrary_stub_sources"],
+ current_api: "sdk_library/public/mynewsdklibrary.txt",
+ removed_api: "sdk_library/public/mynewsdklibrary-removed.txt",
+ sdk_version: "current",
+ },
+}
+`
+ expectedCopyRules := `
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/index.csv -> hiddenapi/index.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv
+.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv
+.intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
+.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
+.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
+.intermediates/mynewsdklibrary.stubs/android_common/javac/mynewsdklibrary.stubs.jar -> sdk_library/public/mynewsdklibrary-stubs.jar
+.intermediates/mynewsdklibrary.stubs.source/android_common/metalava/mynewsdklibrary.stubs.source_api.txt -> sdk_library/public/mynewsdklibrary.txt
+.intermediates/mynewsdklibrary.stubs.source/android_common/metalava/mynewsdklibrary.stubs.source_removed.txt -> sdk_library/public/mynewsdklibrary-removed.txt
+`
+
+ // On tiramisu the stub flags should be generated from both mynewsdklibrary and mysdklibrary as
+ // they are both part of the snapshot.
+ expectedStubFlagsInputs := []string{
+ "out/soong/.intermediates/mynewsdklibrary.stubs/android_common/dex/mynewsdklibrary.stubs.jar",
+ "out/soong/.intermediates/mynewsdklibrary/android_common/aligned/mynewsdklibrary.jar",
+ "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar",
+ "out/soong/.intermediates/mysdklibrary/android_common/aligned/mysdklibrary.jar",
+ }
+
+ testSnapshotWithBootClasspathFragment_MinSdkVersion(t, "Tiramisu",
+ expectedSnapshot, expectedCopyRules, expectedStubFlagsInputs, "")
+ })
+}
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 7ab5285..51903ce3 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -889,6 +889,56 @@
)
}
+func TestSnapshotWithJavaSdkLibrary_DistStem(t *testing.T) {
+ result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
+ sdk {
+ name: "mysdk",
+ java_sdk_libs: ["myjavalib-foo"],
+ }
+
+ java_sdk_library {
+ name: "myjavalib-foo",
+ apex_available: ["//apex_available:anyapex"],
+ srcs: ["Test.java"],
+ sdk_version: "current",
+ shared_library: false,
+ public: {
+ enabled: true,
+ },
+ dist_stem: "myjavalib",
+ }
+ `)
+
+ CheckSnapshot(t, result, "mysdk", "",
+ checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_sdk_library_import {
+ name: "myjavalib-foo",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:anyapex"],
+ shared_library: false,
+ public: {
+ jars: ["sdk_library/public/myjavalib-stubs.jar"],
+ stub_srcs: ["sdk_library/public/myjavalib_stub_sources"],
+ current_api: "sdk_library/public/myjavalib.txt",
+ removed_api: "sdk_library/public/myjavalib-removed.txt",
+ sdk_version: "current",
+ },
+}
+`),
+ checkAllCopyRules(`
+.intermediates/myjavalib-foo.stubs/android_common/javac/myjavalib-foo.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib-foo.stubs.source/android_common/metalava/myjavalib-foo.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib-foo.stubs.source/android_common/metalava/myjavalib-foo.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+`),
+ checkMergeZips(
+ ".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
+ ),
+ )
+}
+
func TestSnapshotWithJavaSdkLibrary_UseSrcJar(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForSdkTestWithJavaSdkLibrary,
@@ -1004,7 +1054,7 @@
java_sdk_library {
name: "myjavalib",
srcs: ["Test.java"],
- sdk_version: "current",
+ sdk_version: "S",
shared_library: false,
annotations_enabled: true,
public: {
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 1ec12c3..2f9aee9 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -218,15 +218,16 @@
}
type testPropertiesStruct struct {
- name string
- private string
- Public_Kept string `sdk:"keep"`
- S_Common string
- S_Different string `android:"arch_variant"`
- A_Common []string
- A_Different []string `android:"arch_variant"`
- F_Common *bool
- F_Different *bool `android:"arch_variant"`
+ name string
+ private string
+ Public_Ignore string `sdk:"ignore"`
+ Public_Keep string `sdk:"keep"`
+ S_Common string
+ S_Different string `android:"arch_variant"`
+ A_Common []string
+ A_Different []string `android:"arch_variant"`
+ F_Common *bool
+ F_Different *bool `android:"arch_variant"`
EmbeddedPropertiesStruct
}
@@ -244,30 +245,32 @@
common := &testPropertiesStruct{name: "common"}
structs := []propertiesContainer{
&testPropertiesStruct{
- name: "struct-0",
- private: "common",
- Public_Kept: "common",
- S_Common: "common",
- S_Different: "upper",
- A_Common: []string{"first", "second"},
- A_Different: []string{"alpha", "beta"},
- F_Common: proptools.BoolPtr(false),
- F_Different: proptools.BoolPtr(false),
+ name: "struct-0",
+ private: "common",
+ Public_Ignore: "common",
+ Public_Keep: "keep",
+ S_Common: "common",
+ S_Different: "upper",
+ A_Common: []string{"first", "second"},
+ A_Different: []string{"alpha", "beta"},
+ F_Common: proptools.BoolPtr(false),
+ F_Different: proptools.BoolPtr(false),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "embedded_common",
S_Embedded_Different: "embedded_upper",
},
},
&testPropertiesStruct{
- name: "struct-1",
- private: "common",
- Public_Kept: "common",
- S_Common: "common",
- S_Different: "lower",
- A_Common: []string{"first", "second"},
- A_Different: []string{"alpha", "delta"},
- F_Common: proptools.BoolPtr(false),
- F_Different: proptools.BoolPtr(true),
+ name: "struct-1",
+ private: "common",
+ Public_Ignore: "common",
+ Public_Keep: "keep",
+ S_Common: "common",
+ S_Different: "lower",
+ A_Common: []string{"first", "second"},
+ A_Different: []string{"alpha", "delta"},
+ F_Common: proptools.BoolPtr(false),
+ F_Different: proptools.BoolPtr(true),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "embedded_common",
S_Embedded_Different: "embedded_lower",
@@ -282,15 +285,16 @@
android.AssertDeepEquals(t, "common properties not correct",
&testPropertiesStruct{
- name: "common",
- private: "",
- Public_Kept: "",
- S_Common: "common",
- S_Different: "",
- A_Common: []string{"first", "second"},
- A_Different: []string(nil),
- F_Common: proptools.BoolPtr(false),
- F_Different: nil,
+ name: "common",
+ private: "",
+ Public_Ignore: "",
+ Public_Keep: "keep",
+ S_Common: "common",
+ S_Different: "",
+ A_Common: []string{"first", "second"},
+ A_Different: []string(nil),
+ F_Common: proptools.BoolPtr(false),
+ F_Different: nil,
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "embedded_common",
S_Embedded_Different: "",
@@ -300,15 +304,16 @@
android.AssertDeepEquals(t, "updated properties[0] not correct",
&testPropertiesStruct{
- name: "struct-0",
- private: "common",
- Public_Kept: "common",
- S_Common: "",
- S_Different: "upper",
- A_Common: nil,
- A_Different: []string{"alpha", "beta"},
- F_Common: nil,
- F_Different: proptools.BoolPtr(false),
+ name: "struct-0",
+ private: "common",
+ Public_Ignore: "common",
+ Public_Keep: "keep",
+ S_Common: "",
+ S_Different: "upper",
+ A_Common: nil,
+ A_Different: []string{"alpha", "beta"},
+ F_Common: nil,
+ F_Different: proptools.BoolPtr(false),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "",
S_Embedded_Different: "embedded_upper",
@@ -318,15 +323,16 @@
android.AssertDeepEquals(t, "updated properties[1] not correct",
&testPropertiesStruct{
- name: "struct-1",
- private: "common",
- Public_Kept: "common",
- S_Common: "",
- S_Different: "lower",
- A_Common: nil,
- A_Different: []string{"alpha", "delta"},
- F_Common: nil,
- F_Different: proptools.BoolPtr(true),
+ name: "struct-1",
+ private: "common",
+ Public_Ignore: "common",
+ Public_Keep: "keep",
+ S_Common: "",
+ S_Different: "lower",
+ A_Common: nil,
+ A_Different: []string{"alpha", "delta"},
+ F_Common: nil,
+ F_Different: proptools.BoolPtr(true),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "",
S_Embedded_Different: "embedded_lower",
@@ -482,6 +488,7 @@
name: "mysdklibrary",
srcs: ["Test.java"],
compile_dex: true,
+ sdk_version: "S",
public: {enabled: true},
permitted_packages: ["mysdklibrary"],
}
diff --git a/sdk/update.go b/sdk/update.go
index 5c9376b..92a13fa 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -211,11 +211,14 @@
container = parent.(android.SdkAware)
}
+ minApiLevel := android.MinApiLevelForSdkSnapshot(ctx, child)
+
export := memberTag.ExportMember()
s.memberVariantDeps = append(s.memberVariantDeps, sdkMemberVariantDep{
sdkVariant: s,
memberType: memberType,
variant: child.(android.SdkAware),
+ minApiLevel: minApiLevel,
container: container,
export: export,
exportedComponentsInfo: exportedComponentsInfo,
@@ -332,10 +335,28 @@
// <arch>/lib/
// libFoo.so : a stub library
+func (s sdk) targetBuildRelease(ctx android.ModuleContext) *buildRelease {
+ config := ctx.Config()
+ targetBuildReleaseEnv := config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", buildReleaseCurrent.name)
+ targetBuildRelease, err := nameToRelease(targetBuildReleaseEnv)
+ if err != nil {
+ ctx.ModuleErrorf("invalid SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE: %s", err)
+ targetBuildRelease = buildReleaseCurrent
+ }
+
+ return targetBuildRelease
+}
+
// buildSnapshot is the main function in this source file. It creates rules to copy
// the contents (header files, stub libraries, etc) into the zip file.
func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) {
+ targetBuildRelease := s.targetBuildRelease(ctx)
+ targetApiLevel, err := android.ApiLevelFromUser(ctx, targetBuildRelease.name)
+ if err != nil {
+ targetApiLevel = android.FutureApiLevel
+ }
+
// Aggregate all the sdkMemberVariantDep instances from all the sdk variants.
hasLicenses := false
var memberVariantDeps []sdkMemberVariantDep
@@ -346,12 +367,18 @@
// Filter out any sdkMemberVariantDep that is a component of another.
memberVariantDeps = filterOutComponents(ctx, memberVariantDeps)
- // Record the names of all the members, both explicitly specified and implicitly
- // included.
+ // Record the names of all the members, both explicitly specified and implicitly included. Also,
+ // record the names of any members that should be excluded from this snapshot.
allMembersByName := make(map[string]struct{})
exportedMembersByName := make(map[string]struct{})
+ excludedMembersByName := make(map[string]struct{})
- addMember := func(name string, export bool) {
+ addMember := func(name string, export bool, exclude bool) {
+ if exclude {
+ excludedMembersByName[name] = struct{}{}
+ return
+ }
+
allMembersByName[name] = struct{}{}
if export {
exportedMembersByName[name] = struct{}{}
@@ -362,11 +389,15 @@
name := memberVariantDep.variant.Name()
export := memberVariantDep.export
- addMember(name, export)
+ // If the minApiLevel of the member is greater than the target API level then exclude it from
+ // this snapshot.
+ exclude := memberVariantDep.minApiLevel.GreaterThan(targetApiLevel)
+
+ addMember(name, export, exclude)
// Add any components provided by the module.
for _, component := range memberVariantDep.exportedComponentsInfo.Components {
- addMember(component, export)
+ addMember(component, export, exclude)
}
if memberVariantDep.memberType == android.LicenseModuleSdkMemberType {
@@ -382,18 +413,9 @@
modules: make(map[string]*bpModule),
}
- config := ctx.Config()
-
// Always add -current to the end
snapshotFileSuffix := "-current"
- targetBuildReleaseEnv := config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", buildReleaseCurrent.name)
- targetBuildRelease, err := nameToRelease(targetBuildReleaseEnv)
- if err != nil {
- ctx.ModuleErrorf("invalid SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE: %s", err)
- targetBuildRelease = buildReleaseCurrent
- }
-
builder := &snapshotBuilder{
ctx: ctx,
sdk: s,
@@ -404,6 +426,7 @@
prebuiltModules: make(map[string]*bpModule),
allMembersByName: allMembersByName,
exportedMembersByName: exportedMembersByName,
+ excludedMembersByName: excludedMembersByName,
targetBuildRelease: targetBuildRelease,
}
s.builderForTests = builder
@@ -437,6 +460,10 @@
}
name := member.name
+ if _, ok := excludedMembersByName[name]; ok {
+ continue
+ }
+
requiredTraits := traits[name]
if requiredTraits == nil {
requiredTraits = android.EmptySdkMemberTraitSet()
@@ -1034,6 +1061,9 @@
// The set of exported members by name.
exportedMembersByName map[string]struct{}
+ // The set of members which have been excluded from this snapshot; by name.
+ excludedMembersByName map[string]struct{}
+
// The target build release for which the snapshot is to be generated.
targetBuildRelease *buildRelease
@@ -1218,6 +1248,9 @@
func (s *snapshotBuilder) snapshotSdkMemberNames(members []string, required bool) []string {
var references []string = nil
for _, m := range members {
+ if _, ok := s.excludedMembersByName[m]; ok {
+ continue
+ }
references = append(references, s.snapshotSdkMemberName(m, required))
}
return references
@@ -1260,6 +1293,9 @@
// The names of additional component modules provided by the variant.
exportedComponentsInfo android.ExportedComponentsInfo
+
+ // The minimum API level on which this module is supported.
+ minApiLevel android.ApiLevel
}
var _ android.SdkMember = (*sdkMember)(nil)
@@ -2136,6 +2172,11 @@
// Retrieves the value on which common value optimization will be performed.
getter fieldAccessorFunc
+ // True if the field should never be cleared.
+ //
+ // This is set to true if and only if the field is annotated with `sdk:"keep"`.
+ keep bool
+
// The empty value for the field.
emptyValue reflect.Value
@@ -2181,8 +2222,8 @@
continue
}
- // Ignore fields whose value should be kept.
- if proptools.HasTag(field, "sdk", "keep") {
+ // Ignore fields tagged with sdk:"ignore".
+ if proptools.HasTag(field, "sdk", "ignore") {
continue
}
@@ -2200,6 +2241,8 @@
}
}
+ keep := proptools.HasTag(field, "sdk", "keep")
+
// Save a copy of the field index for use in the function.
fieldIndex := f
@@ -2239,6 +2282,7 @@
name,
filter,
fieldGetter,
+ keep,
reflect.Zero(field.Type),
proptools.HasTag(field, "android", "arch_variant"),
}
@@ -2358,11 +2402,13 @@
if commonValue != nil {
emptyValue := property.emptyValue
fieldGetter(commonStructValue).Set(*commonValue)
- for i := 0; i < sliceValue.Len(); i++ {
- container := sliceValue.Index(i).Interface().(propertiesContainer)
- itemValue := reflect.ValueOf(container.optimizableProperties())
- fieldValue := fieldGetter(itemValue)
- fieldValue.Set(emptyValue)
+ if !property.keep {
+ for i := 0; i < sliceValue.Len(); i++ {
+ container := sliceValue.Index(i).Interface().(propertiesContainer)
+ itemValue := reflect.ValueOf(container.optimizableProperties())
+ fieldValue := fieldGetter(itemValue)
+ fieldValue.Set(emptyValue)
+ }
}
}
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/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 0785f89..1f0d28d 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -365,7 +365,10 @@
// sysprop_library creates schematized APIs from sysprop description files (.sysprop).
// Both Java and C++ modules can link against sysprop_library, and API stability check
// against latest APIs (see build/soong/scripts/freeze-sysprop-api-files.sh)
-// is performed.
+// is performed. Note that the generated C++ module has its name prefixed with
+// `lib`, and it is this module that should be depended on from other C++
+// modules; i.e., if the sysprop_library module is named `foo`, C++ modules
+// should depend on `libfoo`.
func syspropLibraryFactory() android.Module {
m := &syspropLibrary{}
@@ -570,43 +573,14 @@
}
// TODO(b/240463568): Additional properties will be added for API validation
-type bazelSyspropLibraryAttributes struct {
- Srcs bazel.LabelListAttribute
-}
-
-type bazelCcSyspropLibraryAttributes struct {
- Dep bazel.LabelAttribute
- Min_sdk_version *string
-}
-
func (m *syspropLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "sysprop_library",
- Bzl_load_location: "//build/bazel/rules/sysprop:sysprop_library.bzl",
- },
- android.CommonAttributes{Name: m.Name()},
- &bazelSyspropLibraryAttributes{
- Srcs: bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Srcs)),
- })
-
- attrs := &bazelCcSyspropLibraryAttributes{
- Dep: *bazel.MakeLabelAttribute(":" + m.Name()),
- Min_sdk_version: m.properties.Cpp.Min_sdk_version,
+ labels := cc.SyspropLibraryLabels{
+ SyspropLibraryLabel: m.BaseModuleName(),
+ SharedLibraryLabel: m.CcImplementationModuleName(),
+ StaticLibraryLabel: cc.BazelLabelNameForStaticModule(m.CcImplementationModuleName()),
}
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "cc_sysprop_library_shared",
- Bzl_load_location: "//build/bazel/rules/cc:cc_sysprop_library.bzl",
- },
- android.CommonAttributes{Name: m.CcImplementationModuleName()},
- attrs)
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "cc_sysprop_library_static",
- Bzl_load_location: "//build/bazel/rules/cc:cc_sysprop_library.bzl",
- },
- android.CommonAttributes{Name: m.CcImplementationModuleName() + "_bp2build_cc_library_static"},
- attrs)
+ cc.Bp2buildSysprop(ctx,
+ labels,
+ bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Srcs)),
+ m.properties.Cpp.Min_sdk_version)
}
diff --git a/sysprop/sysprop_library_conversion_test.go b/sysprop/sysprop_library_conversion_test.go
index c72faf3..89adf7d 100644
--- a/sysprop/sysprop_library_conversion_test.go
+++ b/sysprop/sysprop_library_conversion_test.go
@@ -41,7 +41,7 @@
`,
ExpectedBazelTargets: []string{
bp2build.MakeBazelTargetNoRestrictions("sysprop_library",
- "sysprop_foo_sysprop_library",
+ "sysprop_foo",
bp2build.AttrNameToString{
"srcs": `[
"foo.sysprop",
@@ -51,12 +51,12 @@
bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_shared",
"libsysprop_foo",
bp2build.AttrNameToString{
- "dep": `":sysprop_foo_sysprop_library"`,
+ "dep": `":sysprop_foo"`,
}),
bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_static",
"libsysprop_foo_bp2build_cc_library_static",
bp2build.AttrNameToString{
- "dep": `":sysprop_foo_sysprop_library"`,
+ "dep": `":sysprop_foo"`,
}),
},
})
@@ -86,7 +86,7 @@
`,
ExpectedBazelTargets: []string{
bp2build.MakeBazelTargetNoRestrictions("sysprop_library",
- "sysprop_foo_sysprop_library",
+ "sysprop_foo",
bp2build.AttrNameToString{
"srcs": `[
"foo.sysprop",
@@ -96,13 +96,13 @@
bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_shared",
"libsysprop_foo",
bp2build.AttrNameToString{
- "dep": `":sysprop_foo_sysprop_library"`,
+ "dep": `":sysprop_foo"`,
"min_sdk_version": `"5"`,
}),
bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_static",
"libsysprop_foo_bp2build_cc_library_static",
bp2build.AttrNameToString{
- "dep": `":sysprop_foo_sysprop_library"`,
+ "dep": `":sysprop_foo"`,
"min_sdk_version": `"5"`,
}),
},
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 88ef615..80b86e0 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -209,32 +209,32 @@
cc_library {
name: "cc-client-platform",
srcs: ["d.cpp"],
- static_libs: ["sysprop-platform"],
+ static_libs: ["libsysprop-platform"],
}
cc_library_static {
name: "cc-client-platform-static",
srcs: ["d.cpp"],
- whole_static_libs: ["sysprop-platform"],
+ whole_static_libs: ["libsysprop-platform"],
}
cc_library {
name: "cc-client-product",
srcs: ["d.cpp"],
product_specific: true,
- static_libs: ["sysprop-platform-on-product", "sysprop-vendor-on-product"],
+ static_libs: ["libsysprop-platform-on-product", "libsysprop-vendor-on-product"],
}
cc_library {
name: "cc-client-vendor",
srcs: ["d.cpp"],
soc_specific: true,
- static_libs: ["sysprop-platform", "sysprop-vendor"],
+ static_libs: ["libsysprop-platform", "libsysprop-vendor"],
}
cc_binary_host {
name: "hostbin",
- static_libs: ["sysprop-platform"],
+ static_libs: ["libsysprop-platform"],
}
`)
diff --git a/tests/apex_comparison_tests.sh b/tests/apex_comparison_tests.sh
index ac3c177..61d131b 100755
--- a/tests/apex_comparison_tests.sh
+++ b/tests/apex_comparison_tests.sh
@@ -58,9 +58,10 @@
######################
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)"
-call_bazel build --config=bp2build --config=ci --config=android_arm \
+export TARGET_PRODUCT="module_arm"
+call_bazel build --config=bp2build --config=ci --config=android \
//packages/modules/adb/apex:com.android.adbd \
//system/timezone/apex:com.android.tzdata \
//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex
@@ -86,7 +87,7 @@
# Compare the outputs of `deapexer list`, which lists the contents of the apex filesystem image.
local SOONG_APEX="$SOONG_OUTPUT_DIR/$APEX"
- local BAZEL_APEX="$BAZEL_OUT/android_arm-fastbuild/bin/$APEX_DIR/$APEX"
+ local BAZEL_APEX="$BAZEL_OUT/android_target-fastbuild/bin/$APEX_DIR/$APEX"
local SOONG_LIST="$OUTPUT_DIR/soong.list"
local BAZEL_LIST="$OUTPUT_DIR/bazel.list"
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
index 3cdf6aa..ad21d7d 100755
--- a/tests/bp2build_bazel_test.sh
+++ b/tests/bp2build_bazel_test.sh
@@ -48,6 +48,52 @@
test_bp2build_null_build_with_globs
+function test_different_relative_outdir {
+ setup
+ create_mock_bazel
+
+ 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
+ create_mock_bazel
+
+ 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
@@ -103,7 +149,7 @@
fi
# NOTE: We don't actually use the extra BUILD file for anything here
- run_bazel build --package_path=out/soong/workspace //foo/...
+ run_bazel build --config=android --package_path=out/soong/workspace //foo/...
local the_answer_file="bazel-out/android_target-fastbuild/bin/foo/convertible_soong_module/the_answer.txt"
if [[ ! -f "${the_answer_file}" ]]; then
@@ -114,7 +160,10 @@
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
@@ -146,10 +195,10 @@
run_soong bp2build
- run_bazel build --package_path=out/soong/workspace //a:qq
+ run_bazel build --config=android --package_path=out/soong/workspace //a:qq
local -r output_mtime1=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o)
- run_bazel build --package_path=out/soong/workspace //a:qq
+ run_bazel build --config=android --package_path=out/soong/workspace //a:qq
local -r output_mtime2=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o)
if [[ "$output_mtime1" != "$output_mtime2" ]]; then
@@ -160,7 +209,7 @@
#define QQ 2
EOF
- run_bazel build --package_path=out/soong/workspace //a:qq
+ run_bazel build --config=android --package_path=out/soong/workspace //a:qq
local -r output_mtime3=$(stat -c "%y" bazel-bin/a/_objs/qq/qq.o)
if [[ "$output_mtime1" == "$output_mtime3" ]]; then
diff --git a/tests/lib.sh b/tests/lib.sh
index 6210e77..4b4d908 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -123,6 +123,8 @@
symlink_directory prebuilts/jdk
symlink_directory external/bazel-skylib
symlink_directory external/bazelbuild-rules_android
+ symlink_directory external/bazelbuild-rules_license
+ symlink_directory external/bazelbuild-kotlin-rules
symlink_file WORKSPACE
symlink_file BUILD
diff --git a/tests/mixed_mode_test.sh b/tests/mixed_mode_test.sh
index b408fd3..f6fffad 100755
--- a/tests/mixed_mode_test.sh
+++ b/tests/mixed_mode_test.sh
@@ -14,7 +14,9 @@
setup
create_mock_bazel
- STANDALONE_BAZEL=true run_bazel info
+ run_soong bp2build
+
+ run_bazel info --config=bp2build
}
test_bazel_smoke
diff --git a/ui/build/build.go b/ui/build/build.go
index ff2d5f2..2022e50 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -112,10 +112,6 @@
// 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`")
- }
if config.bazelProdMode && config.bazelDevMode {
ctx.Fatalln("Conflicting bazel mode.\n" +
"Do not specify both --bazel-mode and --bazel-mode-dev")
@@ -249,41 +245,7 @@
SetupPath(ctx, config)
- what := RunAll
- if config.Checkbuild() {
- what |= RunBuildTests
- }
- if config.SkipConfig() {
- ctx.Verboseln("Skipping Config as requested")
- what = what &^ RunProductConfig
- }
- if config.SkipKati() {
- ctx.Verboseln("Skipping Kati as requested")
- what = what &^ RunKati
- }
- if config.SkipKatiNinja() {
- ctx.Verboseln("Skipping use of Kati ninja as requested")
- what = what &^ RunKatiNinja
- }
- if config.SkipSoong() {
- ctx.Verboseln("Skipping use of Soong as requested")
- what = what &^ RunSoong
- }
-
- if config.SkipNinja() {
- ctx.Verboseln("Skipping Ninja as requested")
- what = what &^ RunNinja
- }
-
- if !config.SoongBuildInvocationNeeded() {
- // This means that the output of soong_build is not needed and thus it would
- // run unnecessarily. In addition, if this code wasn't there invocations
- // with only special-cased target names like "m bp2build" would result in
- // passing Ninja the empty target list and it would then build the default
- // targets which is not what the user asked for.
- what = what &^ RunNinja
- what = what &^ RunKati
- }
+ what := evaluateWhatToRun(config, ctx.Verboseln)
if config.StartGoma() {
startGoma(ctx, config)
@@ -359,6 +321,46 @@
}
}
+func evaluateWhatToRun(config Config, verboseln func(v ...interface{})) int {
+ //evaluate what to run
+ what := RunAll
+ if config.Checkbuild() {
+ what |= RunBuildTests
+ }
+ if config.SkipConfig() {
+ verboseln("Skipping Config as requested")
+ what = what &^ RunProductConfig
+ }
+ if config.SkipKati() {
+ verboseln("Skipping Kati as requested")
+ what = what &^ RunKati
+ }
+ if config.SkipKatiNinja() {
+ verboseln("Skipping use of Kati ninja as requested")
+ what = what &^ RunKatiNinja
+ }
+ if config.SkipSoong() {
+ verboseln("Skipping use of Soong as requested")
+ what = what &^ RunSoong
+ }
+
+ if config.SkipNinja() {
+ verboseln("Skipping Ninja as requested")
+ what = what &^ RunNinja
+ }
+
+ if !config.SoongBuildInvocationNeeded() {
+ // This means that the output of soong_build is not needed and thus it would
+ // run unnecessarily. In addition, if this code wasn't there invocations
+ // with only special-cased target names like "m bp2build" would result in
+ // passing Ninja the empty target list and it would then build the default
+ // targets which is not what the user asked for.
+ what = what &^ RunNinja
+ what = what &^ RunKati
+ }
+ return what
+}
+
var distWaitGroup sync.WaitGroup
// waitForDist waits for all backgrounded distGzipFile and distFile writes to finish
diff --git a/ui/build/config.go b/ui/build/config.go
index 14a99d0..f6f5b46 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.
@@ -387,13 +388,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)
@@ -756,6 +757,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" {
@@ -833,7 +836,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
}
@@ -916,6 +919,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 +964,10 @@
return c.bp2build
}
+func (c *configImpl) ApiBp2build() bool {
+ return c.apiBp2build
+}
+
func (c *configImpl) Queryview() bool {
return c.queryview
}
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/soong.go b/ui/build/soong.go
index ff6d68f..28c6ec9 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -32,7 +32,6 @@
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
- "github.com/google/blueprint/deptools"
"github.com/google/blueprint/microfactory"
"google.golang.org/protobuf/proto"
@@ -46,6 +45,7 @@
bp2buildTag = "bp2build"
jsonModuleGraphTag = "modulegraph"
queryviewTag = "queryview"
+ apiBp2buildTag = "api_bp2build"
soongDocsTag = "soong_docs"
// bootstrapEpoch is used to determine if an incremental build is incompatible with the current
@@ -238,6 +238,7 @@
config.NamedGlobFile(bp2buildTag),
config.NamedGlobFile(jsonModuleGraphTag),
config.NamedGlobFile(queryviewTag),
+ config.NamedGlobFile(apiBp2buildTag),
config.NamedGlobFile(soongDocsTag),
}
}
@@ -308,6 +309,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,
@@ -346,15 +360,13 @@
bp2buildInvocation,
jsonModuleGraphInvocation,
queryviewInvocation,
+ apiBp2buildInvocation,
soongDocsInvocation},
}
- bootstrapDeps := bootstrap.RunBlueprint(blueprintArgs, bootstrap.DoEverything, blueprintCtx, blueprintConfig)
- bootstrapDepFile := shared.JoinPath(config.SoongOutDir(), "bootstrap.ninja.d")
- err := deptools.WriteDepFile(bootstrapDepFile, blueprintArgs.OutFile, bootstrapDeps)
- if err != nil {
- ctx.Fatalf("Error writing depfile '%s': %s", bootstrapDepFile, err)
- }
+ // since `bootstrap.ninja` is regenerated unconditionally, we ignore the deps, i.e. little
+ // reason to write a `bootstrap.ninja.d` file
+ _ = bootstrap.RunBlueprint(blueprintArgs, bootstrap.DoEverything, blueprintCtx, blueprintConfig)
}
func checkEnvironmentFile(currentEnv *Environment, envFile string) {
@@ -385,11 +397,14 @@
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"))
+ // 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", filepath.Join(config.BazelOutDir(), "output"))
soongBuildEnv.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
soongBuildEnv.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
soongBuildEnv.Set("LOG_DIR", config.LogsDir())
+ soongBuildEnv.Set("BAZEL_DEPS_FILE", filepath.Join(os.Getenv("TOP"), config.OutDir(), "tools", "bazel.list"))
// For Soong bootstrapping tests
if os.Getenv("ALLOW_MISSING_DEPENDENCIES") == "true" {
@@ -419,6 +434,10 @@
checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(queryviewTag))
}
+ if config.ApiBp2build() {
+ checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(apiBp2buildTag))
+ }
+
if config.SoongDocs() {
checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(soongDocsTag))
}
@@ -482,6 +501,10 @@
targets = append(targets, config.QueryviewMarkerFile())
}
+ if config.ApiBp2build() {
+ targets = append(targets, config.ApiBp2buildMarkerFile())
+ }
+
if config.SoongDocs() {
targets = append(targets, config.SoongDocsHtml())
}
diff --git a/xml/Android.bp b/xml/Android.bp
index 1542930..d4753de 100644
--- a/xml/Android.bp
+++ b/xml/Android.bp
@@ -9,6 +9,7 @@
"blueprint",
"blueprint-pathtools",
"soong",
+ "soong-bp2build",
"soong-android",
"soong-etc",
],
@@ -18,6 +19,7 @@
],
testSrcs: [
"xml_test.go",
+ "xml_conversion_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/xml/xml.go b/xml/xml.go
index c281078..8c0c072 100644
--- a/xml/xml.go
+++ b/xml/xml.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "android/soong/bazel"
"android/soong/etc"
"github.com/google/blueprint"
@@ -67,6 +68,8 @@
}
type prebuiltEtcXml struct {
+ android.BazelModuleBase
+
etc.PrebuiltEtc
properties prebuiltEtcXmlProperties
@@ -129,5 +132,40 @@
etc.InitPrebuiltEtcModule(&module.PrebuiltEtc, "etc")
// This module is device-only
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ android.InitBazelModule(module)
return module
}
+
+type bazelPrebuiltEtcXmlAttributes struct {
+ Src bazel.LabelAttribute
+ Filename bazel.LabelAttribute
+ Dir string
+ Installable bazel.BoolAttribute
+ Filename_from_src bazel.BoolAttribute
+ Schema *string
+}
+
+func (p *prebuiltEtcXml) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ baseAttrs := p.PrebuiltEtc.Bp2buildHelper(ctx)
+
+ var schema *string
+ if p.properties.Schema != nil {
+ schema = p.properties.Schema
+ }
+
+ attrs := &bazelPrebuiltEtcXmlAttributes{
+ Src: baseAttrs.Src,
+ Filename: baseAttrs.Filename,
+ Dir: baseAttrs.Dir,
+ Installable: baseAttrs.Installable,
+ Filename_from_src: baseAttrs.Filename_from_src,
+ Schema: schema,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "prebuilt_xml",
+ Bzl_load_location: "//build/bazel/rules/prebuilt_xml.bzl",
+ }
+
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: p.Name()}, attrs)
+}
diff --git a/xml/xml_conversion_test.go b/xml/xml_conversion_test.go
new file mode 100644
index 0000000..6606ddc
--- /dev/null
+++ b/xml/xml_conversion_test.go
@@ -0,0 +1,129 @@
+// 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 xml
+
+import (
+ "android/soong/android"
+ "android/soong/bp2build"
+
+ "testing"
+)
+
+func runXmlPrebuiltEtcTestCase(t *testing.T, tc bp2build.Bp2buildTestCase) {
+ t.Helper()
+ (&tc).ModuleTypeUnderTest = "prebuilt_etc_xml"
+ (&tc).ModuleTypeUnderTestFactory = PrebuiltEtcXmlFactory
+ bp2build.RunBp2BuildTestCase(t, registerXmlModuleTypes, tc)
+}
+
+func registerXmlModuleTypes(ctx android.RegistrationContext) {
+}
+
+func TestXmlPrebuiltEtcSimple(t *testing.T) {
+ runXmlPrebuiltEtcTestCase(t, bp2build.Bp2buildTestCase{
+ Description: "prebuilt_etc_xml - simple example",
+ Filesystem: map[string]string{},
+ Blueprint: `
+prebuilt_etc_xml {
+ name: "foo",
+ src: "fooSrc",
+ filename: "fooFileName",
+ sub_dir: "fooDir",
+ schema: "foo.dtd",
+}
+`,
+ ExpectedBazelTargets: []string{
+ bp2build.MakeBazelTarget("prebuilt_xml", "foo", bp2build.AttrNameToString{
+ "src": `"fooSrc"`,
+ "filename": `"fooFileName"`,
+ "dir": `"etc/fooDir"`,
+ "schema": `"foo.dtd"`,
+ })}})
+}
+
+func TestXmlPrebuiltEtcFilenameFromSrc(t *testing.T) {
+ runXmlPrebuiltEtcTestCase(t, bp2build.Bp2buildTestCase{
+ Description: "prebuilt_etc_xml - filenameFromSrc True ",
+ Filesystem: map[string]string{},
+ Blueprint: `
+prebuilt_etc_xml {
+ name: "foo",
+ src: "fooSrc",
+ filename_from_src: true,
+ sub_dir: "fooDir",
+ schema: "foo.dtd",
+}
+`,
+ ExpectedBazelTargets: []string{
+ bp2build.MakeBazelTarget("prebuilt_xml", "foo", bp2build.AttrNameToString{
+ "src": `"fooSrc"`,
+ "filename": `"fooSrc"`,
+ "dir": `"etc/fooDir"`,
+ "schema": `"foo.dtd"`,
+ })}})
+}
+
+func TestXmlPrebuiltEtcFilenameAndFilenameFromSrc(t *testing.T) {
+ runXmlPrebuiltEtcTestCase(t, bp2build.Bp2buildTestCase{
+ Description: "prebuilt_etc_xml - filename provided and filenameFromSrc True ",
+ Filesystem: map[string]string{},
+ Blueprint: `
+prebuilt_etc_xml {
+ name: "foo",
+ src: "fooSrc",
+ filename: "fooFileName",
+ filename_from_src: true,
+ sub_dir: "fooDir",
+ schema: "foo.dtd",
+}
+`,
+ ExpectedBazelTargets: []string{
+ bp2build.MakeBazelTarget("prebuilt_xml", "foo", bp2build.AttrNameToString{
+ "src": `"fooSrc"`,
+ "filename": `"fooFileName"`,
+ "dir": `"etc/fooDir"`,
+ "schema": `"foo.dtd"`,
+ })}})
+}
+
+func TestXmlPrebuiltEtcFileNameFromSrcMultipleSrcs(t *testing.T) {
+ runXmlPrebuiltEtcTestCase(t, bp2build.Bp2buildTestCase{
+ Description: "prebuilt_etc - filename_from_src is true but there are multiple srcs",
+ Filesystem: map[string]string{},
+ Blueprint: `
+prebuilt_etc_xml {
+ name: "foo",
+ filename_from_src: true,
+ arch: {
+ arm: {
+ src: "barSrc",
+ },
+ arm64: {
+ src: "bazSrc",
+ },
+ }
+}
+`,
+ ExpectedBazelTargets: []string{
+ bp2build.MakeBazelTarget("prebuilt_xml", "foo", bp2build.AttrNameToString{
+ "filename_from_src": `True`,
+ "dir": `"etc"`,
+ "src": `select({
+ "//build/bazel/platforms/arch:arm": "barSrc",
+ "//build/bazel/platforms/arch:arm64": "bazSrc",
+ "//conditions:default": None,
+ })`,
+ })}})
+}
diff --git a/zip/cmd/BUILD.bazel b/zip/cmd/BUILD.bazel
new file mode 100644
index 0000000..e04a1e1
--- /dev/null
+++ b/zip/cmd/BUILD.bazel
@@ -0,0 +1,20 @@
+# 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.
+
+# TODO(b/194644518): Switch to the source version when Bazel can build go
+# binaries.
+alias(
+ name = "soong_zip",
+ actual = "//prebuilts/build-tools:linux-x86/bin/soong_zip",
+)