diff options
136 files changed, 5073 insertions, 1719 deletions
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go index 256b24c2c..f8f73386f 100644 --- a/android/allowlists/allowlists.go +++ b/android/allowlists/allowlists.go @@ -37,8 +37,9 @@ const ( var ( Bp2buildDefaultConfig = Bp2BuildConfig{ - "art/libartpalette": Bp2BuildDefaultTrueRecursively, + "art": Bp2BuildDefaultTrue, "art/libartbase": Bp2BuildDefaultTrueRecursively, + "art/libartpalette": Bp2BuildDefaultTrueRecursively, "art/libdexfile": Bp2BuildDefaultTrueRecursively, "art/libnativebridge": Bp2BuildDefaultTrueRecursively, "art/runtime": Bp2BuildDefaultTrueRecursively, @@ -46,20 +47,17 @@ var ( "bionic": Bp2BuildDefaultTrueRecursively, "bootable/recovery/tools/recovery_l10n": Bp2BuildDefaultTrue, - "build/bazel/examples/aidl": Bp2BuildDefaultTrueRecursively, - "build/bazel/examples/apex/minimal": Bp2BuildDefaultTrueRecursively, - "build/bazel/examples/soong_config_variables": Bp2BuildDefaultTrueRecursively, - "build/bazel/examples/python": Bp2BuildDefaultTrueRecursively, - "build/bazel/examples/gensrcs": Bp2BuildDefaultTrueRecursively, - "build/make/target/product/security": Bp2BuildDefaultTrue, - "build/make/tools/signapk": Bp2BuildDefaultTrue, - "build/make/tools/zipalign": Bp2BuildDefaultTrueRecursively, - "build/soong": Bp2BuildDefaultTrue, - "build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir - "build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue, - "build/soong/cc/symbolfile": Bp2BuildDefaultTrue, - "build/soong/linkerconfig": Bp2BuildDefaultTrueRecursively, - "build/soong/scripts": Bp2BuildDefaultTrueRecursively, + "build/bazel": Bp2BuildDefaultTrueRecursively, + "build/make/target/product/security": Bp2BuildDefaultTrue, + "build/make/tools/signapk": Bp2BuildDefaultTrue, + "build/make/tools/zipalign": Bp2BuildDefaultTrueRecursively, + "build/soong": Bp2BuildDefaultTrue, + "build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir + "build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue, + "build/soong/cc/symbolfile": Bp2BuildDefaultTrue, + "build/soong/licenses": Bp2BuildDefaultTrue, + "build/soong/linkerconfig": Bp2BuildDefaultTrueRecursively, + "build/soong/scripts": Bp2BuildDefaultTrueRecursively, "cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively, "development/apps/DevelopmentSettings": Bp2BuildDefaultTrue, @@ -102,6 +100,7 @@ var ( "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, @@ -123,7 +122,10 @@ var ( "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/javassist": Bp2BuildDefaultTrueRecursively, + "external/javaparser": Bp2BuildDefaultTrueRecursively, "external/javapoet": Bp2BuildDefaultTrueRecursively, "external/jemalloc_new": Bp2BuildDefaultTrueRecursively, "external/jsoncpp": Bp2BuildDefaultTrueRecursively, @@ -138,10 +140,13 @@ var ( "external/libjpeg-turbo": Bp2BuildDefaultTrueRecursively, "external/libmpeg2": Bp2BuildDefaultTrueRecursively, "external/libpng": Bp2BuildDefaultTrueRecursively, + "external/libvpx": Bp2BuildDefaultTrueRecursively, + "external/libyuv": Bp2BuildDefaultTrueRecursively, "external/lz4/lib": Bp2BuildDefaultTrue, "external/lzma/C": Bp2BuildDefaultTrueRecursively, "external/mdnsresponder": Bp2BuildDefaultTrueRecursively, "external/minijail": Bp2BuildDefaultTrueRecursively, + "external/openscreen": Bp2BuildDefaultTrueRecursively, "external/pcre": Bp2BuildDefaultTrueRecursively, "external/protobuf": Bp2BuildDefaultTrueRecursively, "external/python/six": Bp2BuildDefaultTrueRecursively, @@ -149,14 +154,17 @@ var ( "external/scudo": Bp2BuildDefaultTrueRecursively, "external/selinux/libselinux": Bp2BuildDefaultTrueRecursively, "external/selinux/libsepol": Bp2BuildDefaultTrueRecursively, + "external/speex": Bp2BuildDefaultTrueRecursively, "external/toybox": Bp2BuildDefaultTrueRecursively, "external/zlib": Bp2BuildDefaultTrueRecursively, "external/zopfli": Bp2BuildDefaultTrueRecursively, "external/zstd": Bp2BuildDefaultTrueRecursively, + "frameworks/av": Bp2BuildDefaultTrue, "frameworks/av/media/codecs": Bp2BuildDefaultTrueRecursively, "frameworks/av/media/liberror": Bp2BuildDefaultTrueRecursively, "frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively, + "frameworks/av/media/module/minijail": Bp2BuildDefaultTrueRecursively, "frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue, "frameworks/base/services/tests/servicestests/aidl": Bp2BuildDefaultTrue, "frameworks/base/startop/apps/test": Bp2BuildDefaultTrue, @@ -172,7 +180,39 @@ var ( "frameworks/native/opengl/tests/testViewport": Bp2BuildDefaultTrue, "frameworks/proto_logging/stats/stats_log_api_gen": Bp2BuildDefaultTrueRecursively, - "libnativehelper": Bp2BuildDefaultTrueRecursively, + "hardware/interfaces": Bp2BuildDefaultTrue, + "hardware/interfaces/common/aidl": Bp2BuildDefaultTrue, + "hardware/interfaces/configstore/1.0": Bp2BuildDefaultTrue, + "hardware/interfaces/configstore/1.1": Bp2BuildDefaultTrue, + "hardware/interfaces/configstore/utils": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/allocator/aidl": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/allocator/2.0": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/allocator/3.0": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/allocator/4.0": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/bufferqueue/1.0": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/bufferqueue/2.0": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/common/1.0": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/common/1.1": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/common/1.2": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/common/aidl": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/mapper/2.0": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/mapper/2.1": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/mapper/3.0": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/mapper/4.0": Bp2BuildDefaultTrue, + "hardware/interfaces/media/1.0": Bp2BuildDefaultTrue, + "hardware/interfaces/media/bufferpool/2.0": Bp2BuildDefaultTrue, + "hardware/interfaces/media/c2/1.0": Bp2BuildDefaultTrue, + "hardware/interfaces/media/c2/1.1": Bp2BuildDefaultTrue, + "hardware/interfaces/media/c2/1.2": Bp2BuildDefaultTrue, + "hardware/interfaces/media/omx/1.0": Bp2BuildDefaultTrue, + "hardware/interfaces/neuralnetworks/1.0": Bp2BuildDefaultTrue, + "hardware/interfaces/neuralnetworks/1.1": Bp2BuildDefaultTrue, + "hardware/interfaces/neuralnetworks/1.2": Bp2BuildDefaultTrue, + "hardware/interfaces/neuralnetworks/1.3": Bp2BuildDefaultTrue, + "hardware/interfaces/neuralnetworks/aidl": Bp2BuildDefaultTrue, + + "libnativehelper": Bp2BuildDefaultTrueRecursively, + "packages/apps/DevCamera": Bp2BuildDefaultTrue, "packages/apps/HTMLViewer": Bp2BuildDefaultTrue, "packages/apps/Protips": Bp2BuildDefaultTrue, @@ -187,13 +227,17 @@ var ( "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) + "platform_testing/tests/example": Bp2BuildDefaultTrueRecursively, + "prebuilts/clang/host/linux-x86": Bp2BuildDefaultTrueRecursively, "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 @@ -211,6 +255,7 @@ var ( "system/core/libprocessgroup/cgrouprc": Bp2BuildDefaultTrue, "system/core/libprocessgroup/cgrouprc_format": Bp2BuildDefaultTrue, "system/core/libsystem": Bp2BuildDefaultTrueRecursively, + "system/core/libsysutils": Bp2BuildDefaultTrueRecursively, "system/core/libutils": Bp2BuildDefaultTrueRecursively, "system/core/libvndksupport": Bp2BuildDefaultTrueRecursively, "system/core/property_service/libpropertyinfoparser": Bp2BuildDefaultTrueRecursively, @@ -218,21 +263,33 @@ var ( "system/libartpalette": Bp2BuildDefaultTrueRecursively, "system/libbase": Bp2BuildDefaultTrueRecursively, "system/libfmq": Bp2BuildDefaultTrue, + "system/libhidl/libhidlmemory": Bp2BuildDefaultTrue, + "system/libhidl/transport": Bp2BuildDefaultTrue, + "system/libhidl/transport/allocator/1.0": Bp2BuildDefaultTrue, "system/libhidl/transport/base/1.0": Bp2BuildDefaultTrue, "system/libhidl/transport/manager/1.0": Bp2BuildDefaultTrue, "system/libhidl/transport/manager/1.1": Bp2BuildDefaultTrue, "system/libhidl/transport/manager/1.2": Bp2BuildDefaultTrue, + "system/libhidl/transport/memory/1.0": Bp2BuildDefaultTrue, + "system/libhidl/transport/memory/token/1.0": Bp2BuildDefaultTrue, + "system/libhidl/transport/safe_union/1.0": Bp2BuildDefaultTrue, + "system/libhidl/transport/token/1.0": Bp2BuildDefaultTrue, + "system/libhidl/transport/token/1.0/utils": Bp2BuildDefaultTrue, "system/libhwbinder": Bp2BuildDefaultTrueRecursively, "system/libprocinfo": Bp2BuildDefaultTrue, "system/libziparchive": Bp2BuildDefaultTrueRecursively, - "system/logging/liblog": Bp2BuildDefaultTrueRecursively, + "system/logging": Bp2BuildDefaultTrueRecursively, + "system/media": Bp2BuildDefaultTrue, "system/media/audio": Bp2BuildDefaultTrueRecursively, + "system/media/audio_utils": Bp2BuildDefaultTrueRecursively, "system/memory/libion": Bp2BuildDefaultTrueRecursively, "system/memory/libmemunreachable": Bp2BuildDefaultTrueRecursively, "system/sepolicy/apex": Bp2BuildDefaultTrueRecursively, + "system/testing/gtest_extras": Bp2BuildDefaultTrueRecursively, "system/timezone/apex": Bp2BuildDefaultTrueRecursively, "system/timezone/output_data": Bp2BuildDefaultTrueRecursively, "system/tools/sysprop": Bp2BuildDefaultTrue, + "system/tools/aidl/build/tests_bp2build": Bp2BuildDefaultTrue, "system/unwinding/libunwindstack": Bp2BuildDefaultTrueRecursively, "tools/apksig": Bp2BuildDefaultTrue, @@ -244,24 +301,7 @@ var ( // This is actually build/bazel/build.BAZEL symlinked to ./BUILD ".":/*recursive = */ false, - // build/bazel/examples/apex/... BUILD files should be generated, so - // build/bazel is not recursive. Instead list each subdirectory under - // build/bazel explicitly. - "build/bazel":/* recursive = */ false, - "build/bazel/ci/dist":/* recursive = */ false, - "build/bazel/examples/android_app":/* recursive = */ true, - "build/bazel/examples/cc":/* recursive = */ true, - "build/bazel/examples/java":/* recursive = */ true, - "build/bazel/examples/partitions":/* recursive = */ true, - "build/bazel/bazel_skylib":/* recursive = */ true, - "build/bazel/rules":/* recursive = */ true, - "build/bazel/rules_cc":/* recursive = */ true, - "build/bazel/scripts":/* recursive = */ true, - "build/bazel/tests":/* recursive = */ true, - "build/bazel/platforms":/* recursive = */ true, - "build/bazel/product_config":/* recursive = */ true, - "build/bazel/product_variables":/* recursive = */ true, - "build/bazel/vendor/google":/* recursive = */ true, + "build/bazel":/* recursive = */ true, "build/bazel_common_rules":/* recursive = */ true, // build/make/tools/signapk BUILD file is generated, so build/make/tools is not recursive. "build/make/tools":/* recursive = */ false, @@ -271,9 +311,13 @@ var ( // 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, + "frameworks/base/tools/codegen":/* recursive = */ true, "frameworks/ex/common":/* recursive = */ true, "packages/apps/Music":/* recursive = */ true, @@ -281,6 +325,7 @@ var ( "prebuilts/bazel":/* recursive = */ true, "prebuilts/bundletool":/* recursive = */ true, + "prebuilts/clang/host/linux-x86":/* recursive = */ false, "prebuilts/gcc":/* recursive = */ true, "prebuilts/build-tools":/* recursive = */ true, "prebuilts/jdk/jdk11":/* recursive = */ false, @@ -295,6 +340,7 @@ var ( "code_coverage.policy", "code_coverage.policy.other", "codec2_soft_exports", + "codecs_g711dec", "com.android.media.swcodec-androidManifest", "com.android.media.swcodec-ld.config.txt", "com.android.media.swcodec-mediaswcodec.rc", @@ -306,15 +352,16 @@ var ( "flatbuffer_headers", "gemmlowp_headers", "gl_headers", + "libaidlcommonsupport", "libandroid_runtime_lazy", "libandroid_runtime_vm_headers", "libaudioclient_aidl_conversion_util", - "libaudioutils_fixedfft", "libbinder", "libbinder_device_interface_sources", "libbinder_aidl", "libbinder_headers", "libbinder_headers_platform_shared", + "libbinderthreadstateutils", "libbluetooth-types-header", "libbufferhub_headers", "libcodec2", @@ -324,6 +371,10 @@ var ( "libdvr_headers", "libgsm", "libgui_bufferqueue_sources", + "libgrallocusage", + "libgralloctypes", + "libnativewindow", + "libgraphicsenv", "libhardware", "libhardware_headers", "libincfs_headers", @@ -337,15 +388,28 @@ var ( "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", + "libgui_aidl", + "libui", "libui-types", "libui_headers", "libvorbisidec", @@ -353,11 +417,24 @@ var ( "media_plugin_headers", "mediaswcodec.policy", "mediaswcodec.xml", + "neuralnetworks_types", + "neuralnetworks_utils_hal_aidl", + "neuralnetworks_utils_hal_common", + "neuralnetworks_utils_hal_1_0", + "neuralnetworks_utils_hal_1_1", + "neuralnetworks_utils_hal_1_2", + "neuralnetworks_utils_hal_1_3", + "libneuralnetworks_common", "philox_random", "philox_random_headers", "server_configurable_flags", "tensorflow_headers", + "libgui_headers", + "libstagefright_bufferpool@2.0", + "libstagefright_bufferpool@2.0.1", + "libSurfaceFlingerProp", + // fastboot "bootimg_headers", "fastboot", @@ -407,26 +484,47 @@ var ( //frameworks/native/libs/input "inputconstants_aidl", + + // needed for aidl_interface's ndk backend + "libbinder_ndk", + + "libusb", + + // needed by liblogd + "ILogcatManagerService_aidl", + "libincremental_aidl-cpp", + "incremental_aidl", + + //frameworks/native/cmds/cmd + "libcmd", } Bp2buildModuleTypeAlwaysConvertList = []string{ + "license", "linker_config", "java_import", "java_import_host", + "sysprop_library", "aidl_interface_headers", } Bp2buildModuleDoNotConvertList = []string{ // cc bugs - "libactivitymanager_aidl", // TODO(b/207426160): Unsupported use of aidl sources (via Dactivity_manager_procstate_aidl) in a cc_library - "gen-kotlin-build-file.py", // TODO(b/198619163) module has same name as source + "libactivitymanager_aidl", // TODO(b/207426160): Unsupported use of aidl sources (via Dactivity_manager_procstate_aidl) in a cc_library + + // TODO(b/198619163) module has same name as source + "logtagd.rc", + "libgtest_ndk_c++", "libgtest_main_ndk_c++", // TODO(b/201816222): Requires sdk_version support. - "linkerconfig", "mdnsd", // TODO(b/202876379): has arch-variant static_executable + + // TODO(b/202876379): has arch-variant static_executable + "linkerconfig", + "mdnsd", + "libcutils_test_static", + "KernelLibcutilsTest", + "linker", // TODO(b/228316882): cc_binary uses link_crt - "libdebuggerd", // TODO(b/228314770): support product variable-specific header_libs "versioner", // TODO(b/228313961): depends on prebuilt shared library libclang-cpp_host as a shared library, which does not supply expected providers for a shared library - "libspeexresampler", // TODO(b/231995978): Filter out unknown cflags - "libvpx", // TODO(b/240756936): Arm neon variant not supported "art_libartbase_headers", // TODO(b/236268577): Header libraries do not support export_shared_libs_headers "apexer_test", // Requires aapt2 "apexer_test_host_tools", @@ -479,7 +577,6 @@ var ( // 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 @@ -492,7 +589,7 @@ var ( "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 "host-libprotobuf-java-nano", // b/220869005, depends on libprotobuf-java-nano - "libadb_host", // depends on unconverted modules: AdbWinApi, libopenscreen-discovery, libopenscreen-platform-impl, libusb + "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 @@ -501,6 +598,7 @@ var ( "libartbased-art-gtest", // depends on unconverted modules: libgtest_isolated, libartd, libartd-compiler, libdexfiled, libprofiled "libartd", // depends on unconverted modules: art_operator_srcs, libcpu_features, libodrstatslog, libelffiled, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfiled, libnativebridge, libnativeloader, libsigchain, libartbased, libprofiled, cpp-define-generator-asm-support, apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api "libartd-runtime-gtest", // depends on unconverted modules: libgtest_isolated, libartd-compiler, libdexfiled, libprofiled, libartbased, libartbased-art-gtest + "libdebuggerd", // depends on unconverted module: libdexfile "libdebuggerd_handler", // depends on unconverted module libdebuggerd_handler_core "libdebuggerd_handler_core", "libdebuggerd_handler_fallback", // depends on unconverted module libdebuggerd "libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette @@ -510,7 +608,7 @@ var ( "libnativehelper_lazy_mts_jni", "libnativehelper_mts_jni", // depends on unconverted modules: libnativetesthelper_jni, libgmock_ndk "libnativetesthelper_jni", // depends on unconverted modules: libgtest_ndk_c++ "libprotobuf-java-nano", // b/220869005, depends on non-public_current SDK - "libstatslog", // depends on unconverted modules: libstatspull, statsd-aidl-ndk, libbinder_ndk + "libstatslog", // depends on unconverted modules: libstatspull, statsd-aidl-ndk "libstatslog_art", // depends on unconverted modules: statslog_art.cpp, statslog_art.h "linker_reloc_bench_main", // depends on unconverted modules: liblinker_reloc_bench_* "pbtombstone", "crash_dump", // depends on libdebuggerd, libunwindstack @@ -524,30 +622,461 @@ var ( "truth-host-prebuilt", // depends on unconverted modules: truth-prebuilt "truth-prebuilt", // depends on unconverted modules: asm-7.0, guava - // b/215723302; awaiting tz{data,_version} to then rename targets conflicting with srcs - "tzdata", - "tz_version", - // '//bionic/libc:libc_bp2build_cc_library_static' is duplicated in the 'deps' attribute of rule "toybox-static", - // Do not convert the following modules because of duplicate labels checking in Bazel. - // See b/241283350. They should be removed from this list once the bug is fixed. - "libartpalette", - "libartbase", - "libdexfile", - "libartbased", - "libdexfile_static", - "libartbase-testing", - "libartbased-testing", - "libdexfile_support", - "libunwindstack", - "libunwindstack_local", - "libfdtrack", - "libc_malloc_debug", - "libutilscallstack", - "libunwindstack_utils", - "unwind_for_offline", + // cc_test related. + // Failing host cc_tests + "memunreachable_unit_test", + "libprocinfo_test", + "ziparchive-tests", + "gtest_isolated_tests", + "libunwindstack_unit_test", + "task_profiles_test", + "power_tests", // failing test on server, but not on host + + // reflect: call of reflect.Value.NumField on interface Value + // affects all cc_tests that depend on art_defaults + "libnativebridge-tests", + "libnativeloader_test", + "art_libnativebridge_cts_tests", + "art_standalone_libdexfile_external_tests", + "art_standalone_libdexfile_support_tests", + "libnativebridge-lazy-tests", + "libnativebridge-test-case", + "libnativebridge2-test-case", + "libnativebridge3-test-case", + "libnativebridge6-test-case", + "libnativebridge6prezygotefork", + + // cc_test with unconverted deps, or are device-only (and not verified to pass yet) + "AMRWBEncTest", + "AmrnbDecoderTest", // depends on unconverted modules: libaudioutils, libsndfile + "AmrnbEncoderTest", // depends on unconverted modules: libaudioutils, libsndfile + "AmrwbDecoderTest", // depends on unconverted modules: libsndfile, libaudioutils + "AmrwbEncoderTest", // depends on unconverted modules: libaudioutils, libsndfile + "Mp3DecoderTest", // depends on unconverted modules: libsndfile, libaudioutils + "Mpeg4H263DecoderTest", // depends on unconverted modules: libstagefright_foundation + "Mpeg4H263EncoderTest", + "avcdec", + "avcenc", + "bionic-benchmarks-tests", + "bionic-fortify-runtime-asan-test", + "bionic-stress-tests", + "bionic-unit-tests", + "bionic-unit-tests-glibc", + "bionic-unit-tests-static", + "boringssl_crypto_test", + "boringssl_ssl_test", + "cfi_test_helper", + "cfi_test_helper2", + "cintltst32", + "cintltst64", + "compare", + "cpuid", + "debuggerd_test", // depends on unconverted modules: libdebuggerd + "elftls_dlopen_ie_error_helper", + "exec_linker_helper", + "fastdeploy_test", // depends on unconverted modules: AdbWinApi, libadb_host, libandroidfw, libfastdeploy_host, libopenscreen-discovery, libopenscreen-platform-impl, libusb + "fdtrack_test", + "google-benchmark-test", + "googletest-param-test-test_ndk", // depends on unconverted modules: libgtest_ndk_c++ + "gtest-typed-test_test", + "gtest-typed-test_test_ndk", // depends on unconverted modules: libgtest_ndk_c++, libgtest_main_ndk_c++ + "gtest_ndk_tests", // depends on unconverted modules: libgtest_ndk_c++, libgtest_main_ndk_c++ + "gtest_ndk_tests_no_main", // depends on unconverted modules: libgtest_ndk_c++ + "gtest_prod_test_ndk", // depends on unconverted modules: libgtest_ndk_c++, libgtest_main_ndk_c++ + "gtest_tests", + "gtest_tests_no_main", + "gwp_asan_unittest", + "half_test", + "hashcombine_test", + "hevcdec", + "hevcenc", + "hwbinderThroughputTest", // depends on unconverted modules: android.hardware.tests.libhwbinder@1.0-impl.test, android.hardware.tests.libhwbinder@1.0 + "i444tonv12_eg", + "icu4c_sample_break", + "intltest32", + "intltest64", + "ion-unit-tests", + "jemalloc5_integrationtests", + "jemalloc5_unittests", + "ld_config_test_helper", + "ld_preload_test_helper", + "libBionicCtsGtestMain", // depends on unconverted modules: libgtest_isolated + "libBionicLoaderTests", // depends on unconverted modules: libmeminfo + "libapexutil_tests", // depends on unconverted modules: apex-info-list-tinyxml, libapexutil + "libcutils_sockets_test", + "libexpectedutils_test", + "libhwbinder_latency", + "liblog-host-test", // failing tests + "libminijail_test", + "libminijail_unittest_gtest", + "libpackagelistparser_test", + "libprotobuf_vendor_suffix_test", + "libstagefright_amrnbdec_test", // depends on unconverted modules: libsndfile, libaudioutils + "libstagefright_amrnbenc_test", + "libstagefright_amrwbdec_test", // depends on unconverted modules: libsndfile, libaudioutils + "libstagefright_m4vh263enc_test", + "libstagefright_mp3dec_test", // depends on unconverted modules: libsndfile, libaudioutils + "libstatssocket_test", + "libvndksupport-tests", + "libyuv_unittest", + "linker-unit-tests", + "malloc_debug_system_tests", + "malloc_debug_unit_tests", + "malloc_hooks_system_tests", + "mat_test", + "mathtest", + "memunreachable_binder_test", // depends on unconverted modules: libbinder + "memunreachable_test", + "metadata_tests", + "minijail0_cli_unittest_gtest", + "mpeg2dec", + "mvcdec", + "ns_hidden_child_helper", + "pngtest", + "preinit_getauxval_test_helper", + "preinit_syscall_test_helper", + "psnr", + "quat_test", + "rappor-tests", // depends on unconverted modules: jsr305, guava + "scudo_unit_tests", + "stats-log-api-gen-test", // depends on unconverted modules: libstats_proto_host + "syscall_filter_unittest_gtest", + "sysprop_test", // depends on unconverted modules: libcom.android.sysprop.tests + "thread_exit_cb_helper", + "tls_properties_helper", + "ulp", + "vec_test", + "yuvconstants", + "yuvconvert", + "zipalign_tests", + + // cc_test_library + "clang_diagnostic_tests", + "exec_linker_helper_lib", + "fortify_disabled_for_tidy", + "ld_config_test_helper_lib1", + "ld_config_test_helper_lib2", + "ld_config_test_helper_lib3", + "ld_preload_test_helper_lib1", + "ld_preload_test_helper_lib2", + "libBionicElfTlsLoaderTests", + "libBionicElfTlsTests", + "libBionicElfTlsTests", + "libBionicFramePointerTests", + "libBionicFramePointerTests", + "libBionicStandardTests", + "libBionicStandardTests", + "libBionicTests", + "libart-broken", + "libatest_simple_zip", + "libcfi-test", + "libcfi-test-bad", + "libcrash_test", + // "libcrypto_fuzz_unsafe", + "libdl_preempt_test_1", + "libdl_preempt_test_2", + "libdl_test_df_1_global", + "libdlext_test", + "libdlext_test_different_soname", + "libdlext_test_fd", + "libdlext_test_norelro", + "libdlext_test_recursive", + "libdlext_test_zip", + "libfortify1-new-tests-clang", + "libfortify1-new-tests-clang", + "libfortify1-tests-clang", + "libfortify1-tests-clang", + "libfortify2-new-tests-clang", + "libfortify2-new-tests-clang", + "libfortify2-tests-clang", + "libfortify2-tests-clang", + "libgnu-hash-table-library", + "libicutest_static", + "liblinker_reloc_bench_000", + "liblinker_reloc_bench_001", + "liblinker_reloc_bench_002", + "liblinker_reloc_bench_003", + "liblinker_reloc_bench_004", + "liblinker_reloc_bench_005", + "liblinker_reloc_bench_006", + "liblinker_reloc_bench_007", + "liblinker_reloc_bench_008", + "liblinker_reloc_bench_009", + "liblinker_reloc_bench_010", + "liblinker_reloc_bench_011", + "liblinker_reloc_bench_012", + "liblinker_reloc_bench_013", + "liblinker_reloc_bench_014", + "liblinker_reloc_bench_015", + "liblinker_reloc_bench_016", + "liblinker_reloc_bench_017", + "liblinker_reloc_bench_018", + "liblinker_reloc_bench_019", + "liblinker_reloc_bench_020", + "liblinker_reloc_bench_021", + "liblinker_reloc_bench_022", + "liblinker_reloc_bench_023", + "liblinker_reloc_bench_024", + "liblinker_reloc_bench_025", + "liblinker_reloc_bench_026", + "liblinker_reloc_bench_027", + "liblinker_reloc_bench_028", + "liblinker_reloc_bench_029", + "liblinker_reloc_bench_030", + "liblinker_reloc_bench_031", + "liblinker_reloc_bench_032", + "liblinker_reloc_bench_033", + "liblinker_reloc_bench_034", + "liblinker_reloc_bench_035", + "liblinker_reloc_bench_036", + "liblinker_reloc_bench_037", + "liblinker_reloc_bench_038", + "liblinker_reloc_bench_039", + "liblinker_reloc_bench_040", + "liblinker_reloc_bench_041", + "liblinker_reloc_bench_042", + "liblinker_reloc_bench_043", + "liblinker_reloc_bench_044", + "liblinker_reloc_bench_045", + "liblinker_reloc_bench_046", + "liblinker_reloc_bench_047", + "liblinker_reloc_bench_048", + "liblinker_reloc_bench_049", + "liblinker_reloc_bench_050", + "liblinker_reloc_bench_051", + "liblinker_reloc_bench_052", + "liblinker_reloc_bench_053", + "liblinker_reloc_bench_054", + "liblinker_reloc_bench_055", + "liblinker_reloc_bench_056", + "liblinker_reloc_bench_057", + "liblinker_reloc_bench_058", + "liblinker_reloc_bench_059", + "liblinker_reloc_bench_060", + "liblinker_reloc_bench_061", + "liblinker_reloc_bench_062", + "liblinker_reloc_bench_063", + "liblinker_reloc_bench_064", + "liblinker_reloc_bench_065", + "liblinker_reloc_bench_066", + "liblinker_reloc_bench_067", + "liblinker_reloc_bench_068", + "liblinker_reloc_bench_069", + "liblinker_reloc_bench_070", + "liblinker_reloc_bench_071", + "liblinker_reloc_bench_072", + "liblinker_reloc_bench_073", + "liblinker_reloc_bench_074", + "liblinker_reloc_bench_075", + "liblinker_reloc_bench_076", + "liblinker_reloc_bench_077", + "liblinker_reloc_bench_078", + "liblinker_reloc_bench_079", + "liblinker_reloc_bench_080", + "liblinker_reloc_bench_081", + "liblinker_reloc_bench_082", + "liblinker_reloc_bench_083", + "liblinker_reloc_bench_084", + "liblinker_reloc_bench_085", + "liblinker_reloc_bench_086", + "liblinker_reloc_bench_087", + "liblinker_reloc_bench_088", + "liblinker_reloc_bench_089", + "liblinker_reloc_bench_090", + "liblinker_reloc_bench_091", + "liblinker_reloc_bench_092", + "liblinker_reloc_bench_093", + "liblinker_reloc_bench_094", + "liblinker_reloc_bench_095", + "liblinker_reloc_bench_096", + "liblinker_reloc_bench_097", + "liblinker_reloc_bench_098", + "liblinker_reloc_bench_099", + "liblinker_reloc_bench_100", + "liblinker_reloc_bench_101", + "liblinker_reloc_bench_102", + "liblinker_reloc_bench_103", + "liblinker_reloc_bench_104", + "liblinker_reloc_bench_105", + "liblinker_reloc_bench_106", + "liblinker_reloc_bench_107", + "liblinker_reloc_bench_108", + "liblinker_reloc_bench_109", + "liblinker_reloc_bench_110", + "liblinker_reloc_bench_111", + "liblinker_reloc_bench_112", + "liblinker_reloc_bench_113", + "liblinker_reloc_bench_114", + "liblinker_reloc_bench_115", + "liblinker_reloc_bench_116", + "liblinker_reloc_bench_117", + "liblinker_reloc_bench_118", + "liblinker_reloc_bench_119", + "liblinker_reloc_bench_120", + "liblinker_reloc_bench_121", + "liblinker_reloc_bench_122", + "liblinker_reloc_bench_123", + "liblinker_reloc_bench_124", + "liblinker_reloc_bench_125", + "liblinker_reloc_bench_126", + "liblinker_reloc_bench_127", + "liblinker_reloc_bench_128", + "liblinker_reloc_bench_129", + "liblinker_reloc_bench_130", + "liblinker_reloc_bench_131", + "liblinker_reloc_bench_132", + "liblinker_reloc_bench_133", + "liblinker_reloc_bench_134", + "liblinker_reloc_bench_135", + "liblinker_reloc_bench_136", + "liblinker_reloc_bench_137", + "liblinker_reloc_bench_138", + "liblinker_reloc_bench_139", + "liblinker_reloc_bench_140", + "liblinker_reloc_bench_141", + "liblinker_reloc_bench_142", + "liblinker_reloc_bench_143", + "liblinker_reloc_bench_144", + "liblinker_reloc_bench_145", + "liblinker_reloc_bench_146", + "liblinker_reloc_bench_147", + "liblinker_reloc_bench_148", + "liblinker_reloc_bench_149", + "liblinker_reloc_bench_150", + "liblinker_reloc_bench_151", + "liblinker_reloc_bench_152", + "liblinker_reloc_bench_153", + "liblinker_reloc_bench_154", + "liblinker_reloc_bench_155", + "liblinker_reloc_bench_156", + "liblinker_reloc_bench_157", + "liblinker_reloc_bench_158", + "liblinker_reloc_bench_159", + "liblinker_reloc_bench_160", + "liblinker_reloc_bench_161", + "liblinker_reloc_bench_162", + "liblinker_reloc_bench_163", + "liblinker_reloc_bench_164", + "liblinker_reloc_bench_165", + "liblinker_reloc_bench_166", + "liblinker_reloc_bench_167", + "liblinker_reloc_bench_168", + "libns_hidden_child_app", + "libns_hidden_child_global", + "libns_hidden_child_internal", + "libns_hidden_child_public", + "libnstest_dlopened", + "libnstest_ns_a_public1", + "libnstest_ns_a_public1_internal", + "libnstest_ns_b_public2", + "libnstest_ns_b_public3", + "libnstest_private", + "libnstest_private_external", + "libnstest_public", + "libnstest_public_internal", + "libnstest_root", + "libnstest_root_not_isolated", + "librelocations-ANDROID_REL", + "librelocations-ANDROID_RELR", + "librelocations-RELR", + "librelocations-fat", + "libsegment_gap_inner", + "libsegment_gap_outer", + // "libssl_fuzz_unsafe", + "libstatssocket_private", + "libsysv-hash-table-library", + "libtest_atexit", + "libtest_check_order_dlsym", + "libtest_check_order_dlsym_1_left", + "libtest_check_order_dlsym_2_right", + "libtest_check_order_dlsym_3_c", + "libtest_check_order_dlsym_a", + "libtest_check_order_dlsym_b", + "libtest_check_order_dlsym_d", + "libtest_check_order_reloc_root", + "libtest_check_order_reloc_root_1", + "libtest_check_order_reloc_root_2", + "libtest_check_order_reloc_siblings", + "libtest_check_order_reloc_siblings_1", + "libtest_check_order_reloc_siblings_2", + "libtest_check_order_reloc_siblings_3", + "libtest_check_order_reloc_siblings_a", + "libtest_check_order_reloc_siblings_b", + "libtest_check_order_reloc_siblings_c", + "libtest_check_order_reloc_siblings_c_1", + "libtest_check_order_reloc_siblings_c_2", + "libtest_check_order_reloc_siblings_d", + "libtest_check_order_reloc_siblings_e", + "libtest_check_order_reloc_siblings_f", + "libtest_check_rtld_next_from_library", + "libtest_dlopen_df_1_global", + "libtest_dlopen_from_ctor", + "libtest_dlopen_from_ctor_main", + "libtest_dlopen_weak_undefined_func", + "libtest_dlsym_df_1_global", + "libtest_dlsym_from_this", + "libtest_dlsym_from_this_child", + "libtest_dlsym_from_this_grandchild", + "libtest_dlsym_weak_func", + "libtest_dt_runpath_a", + "libtest_dt_runpath_b", + "libtest_dt_runpath_c", + "libtest_dt_runpath_d", + "libtest_dt_runpath_d_zip", + "libtest_dt_runpath_x", + "libtest_dt_runpath_y", + "libtest_elftls_dynamic", + "libtest_elftls_dynamic_filler_1", + "libtest_elftls_dynamic_filler_2", + "libtest_elftls_dynamic_filler_3", + "libtest_elftls_shared_var", + "libtest_elftls_shared_var_ie", + "libtest_elftls_tprel", + "libtest_empty", + "libtest_ifunc", + "libtest_ifunc_variable", + "libtest_ifunc_variable_impl", + "libtest_indirect_thread_local_dtor", + "libtest_init_fini_order_child", + "libtest_init_fini_order_grand_child", + "libtest_init_fini_order_root", + "libtest_init_fini_order_root2", + "libtest_missing_symbol", + "libtest_missing_symbol_child_private", + "libtest_missing_symbol_child_public", + "libtest_missing_symbol_root", + "libtest_nodelete_1", + "libtest_nodelete_2", + "libtest_nodelete_dt_flags_1", + "libtest_pthread_atfork", + "libtest_relo_check_dt_needed_order", + "libtest_relo_check_dt_needed_order_1", + "libtest_relo_check_dt_needed_order_2", + "libtest_simple", + "libtest_thread_local_dtor", + "libtest_thread_local_dtor2", + "libtest_two_parents_child", + "libtest_two_parents_parent1", + "libtest_two_parents_parent2", + "libtest_versioned_lib", + "libtest_versioned_libv1", + "libtest_versioned_libv2", + "libtest_versioned_otherlib", + "libtest_versioned_otherlib_empty", + "libtest_versioned_uselibv1", + "libtest_versioned_uselibv2", + "libtest_versioned_uselibv2_other", + "libtest_versioned_uselibv3_other", + "libtest_with_dependency", + "libtest_with_dependency_loop", + "libtest_with_dependency_loop_a", + "libtest_with_dependency_loop_b", + "libtest_with_dependency_loop_b_tmp", + "libtest_with_dependency_loop_c", + "libtestshared", } Bp2buildCcLibraryStaticOnlyList = []string{} @@ -569,30 +1098,8 @@ var ( "libadb_pairing_connection_static", "libadb_pairing_server", "libadb_pairing_server_static", - // TODO(b/204811222) support suffix in cc_binary - "acvp_modulewrapper", - "android.hardware.media.c2@1.0-service-v4l2", - "app_process", - "bar_test", - "bench_cxa_atexit", - "bench_noop", - "bench_noop_nostl", - "bench_noop_static", - "boringssl_self_test", - "boringssl_self_test_vendor", - "bssl", - "cavp", - "crash_dump", + // TODO(b/240563612) Needing `stem` selection support for cc_binary "crasher", - "libcxx_test_template", - "linker", - "memory_replay", - "native_bridge_guest_linker", - "native_bridge_stub_library_defaults", - "noop", - "simpleperf_ndk", - "toybox-static", - "zlib_bench", // java_import[_host] issues // tradefed prebuilts depend on libprotobuf @@ -619,4 +1126,8 @@ var ( "prebuilt_platform-robolectric-4.5.1-prebuilt", "prebuilt_currysrc_org.eclipse", } + + ProdMixedBuildsEnabledList = []string{ + "com.android.adbd", + } ) diff --git a/android/androidmk.go b/android/androidmk.go index 006e43def..18e3e7ac4 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -366,7 +366,9 @@ func (a *AndroidMkEntries) getDistContributions(mod blueprint.Module) *distContr // 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 @@ func generateDistContributionsForMake(distContributions *distContributions) []st 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 00b724137..3c945ae6a 100644 --- a/android/apex.go +++ b/android/apex.go @@ -454,8 +454,6 @@ func CheckAvailableForApex(what string, apex_available []string) bool { } 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/arch.go b/android/arch.go index 1952b1716..9bc9d8924 100644 --- a/android/arch.go +++ b/android/arch.go @@ -19,6 +19,7 @@ import ( "fmt" "reflect" "runtime" + "sort" "strings" "android/soong/bazel" @@ -2084,13 +2085,22 @@ func (m *ModuleBase) GetArchVariantProperties(ctx ArchVariantContext, propertySe // For each arch type (x86, arm64, etc.) for _, arch := range ArchTypeList() { // Arch properties are sometimes sharded (see createArchPropTypeDesc() ). - // Iterate over ever shard and extract a struct with the same type as the + // Iterate over every shard and extract a struct with the same type as the // input one that contains the data specific to that arch. propertyStructs := make([]reflect.Value, 0) + archFeaturePropertyStructs := make(map[string][]reflect.Value, 0) for _, archProperty := range archProperties { archTypeStruct, ok := getArchTypeStruct(ctx, archProperty, arch) if ok { propertyStructs = append(propertyStructs, archTypeStruct) + + // For each feature this arch supports (arm: neon, x86: ssse3, sse4, ...) + for _, feature := range archFeatures[arch] { + prefix := "arch." + arch.Name + "." + feature + if featureProperties, ok := getChildPropertyStruct(ctx, archTypeStruct, feature, prefix); ok { + archFeaturePropertyStructs[feature] = append(archFeaturePropertyStructs[feature], featureProperties) + } + } } multilibStruct, ok := getMultilibStruct(ctx, archProperty, arch) if ok { @@ -2098,10 +2108,31 @@ func (m *ModuleBase) GetArchVariantProperties(ctx ArchVariantContext, propertySe } } - // Create a new instance of the requested property set - value := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface() - - archToProp[arch.Name] = mergeStructs(ctx, propertyStructs, value) + archToProp[arch.Name] = mergeStructs(ctx, propertyStructs, propertySet) + + // In soong, if multiple features match the current configuration, they're + // all used. In bazel, we have to have unambiguous select() statements, so + // we can't have two features that are both active in the same select(). + // One alternative is to split out each feature into a separate select(), + // but then it's difficult to support exclude_srcs, which may need to + // exclude things from the regular arch select() statement if a certain + // feature is active. Instead, keep the features in the same select + // statement as the arches, but emit the power set of all possible + // combinations of features, so that bazel can match the most precise one. + allFeatures := make([]string, 0, len(archFeaturePropertyStructs)) + for feature := range archFeaturePropertyStructs { + allFeatures = append(allFeatures, feature) + } + for _, features := range bazel.PowerSetWithoutEmptySet(allFeatures) { + sort.Strings(features) + propsForCurrentFeatureSet := make([]reflect.Value, 0) + propsForCurrentFeatureSet = append(propsForCurrentFeatureSet, propertyStructs...) + for _, feature := range features { + propsForCurrentFeatureSet = append(propsForCurrentFeatureSet, archFeaturePropertyStructs[feature]...) + } + archToProp[arch.Name+"-"+strings.Join(features, "-")] = + mergeStructs(ctx, propsForCurrentFeatureSet, propertySet) + } } axisToProps[bazel.ArchConfigurationAxis] = archToProp diff --git a/android/bazel.go b/android/bazel.go index 71eb036b2..dd1de7bf0 100644 --- a/android/bazel.go +++ b/android/bazel.go @@ -17,9 +17,6 @@ package android import ( "bufio" "errors" - "fmt" - "io/ioutil" - "path/filepath" "strings" "github.com/google/blueprint" @@ -35,10 +32,13 @@ const ( 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 { @@ -78,7 +78,7 @@ type bazelModuleProperties struct { // Properties contains common module properties for Bazel migration purposes. type properties struct { - // In USE_BAZEL_ANALYSIS=1 mode, this represents the Bazel target replacing + // In "Bazel mixed build" mode, this represents the Bazel target replacing // this Soong module. Bazel_module bazelModuleProperties } @@ -117,7 +117,6 @@ type Bazelable interface { GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string ShouldConvertWithBp2build(ctx BazelConversionContext) bool shouldConvertWithBp2build(ctx bazelOtherModuleContext, module blueprint.Module) bool - GetBazelBuildFileContents(c Config, path, name string) (string, error) ConvertWithBp2build(ctx TopDownMutatorContext) // namespacedVariableProps is a map from a soong config variable namespace @@ -211,7 +210,7 @@ func (b *BazelModuleBase) GetBazelLabel(ctx BazelConversionPathContext, module b return "" // no label for unconverted module } -type bp2BuildConversionAllowlist struct { +type Bp2BuildConversionAllowlist struct { // Configure modules in these directories to enable bp2build_available: true or false by default. defaultConfig allowlists.Bp2BuildConfig @@ -219,16 +218,16 @@ type bp2BuildConversionAllowlist struct { // in the synthetic Bazel workspace. keepExistingBuildFile map[string]bool - // Per-module allowlist to always opt modules in of both bp2build and mixed builds. - // These modules are usually in directories with many other modules that are not ready for - // conversion. + // Per-module allowlist to always opt modules into both bp2build and Bazel Dev Mode mixed + // builds. These modules are usually in directories with many other modules that are not ready + // for conversion. // // A module can either be in this list or its directory allowlisted entirely // in bp2buildDefaultConfig, but not both at the same time. moduleAlwaysConvert map[string]bool - // Per-module-type allowlist to always opt modules in to both bp2build and mixed builds - // when they have the same type as one listed. + // Per-module-type allowlist to always opt modules in to both bp2build and + // Bazel Dev Mode mixed builds when they have the same type as one listed. moduleTypeAlwaysConvert map[string]bool // Per-module denylist to always opt modules out of bp2build conversion. @@ -241,14 +240,14 @@ type bp2BuildConversionAllowlist struct { // GenerateCcLibraryStaticOnly returns whether a cc_library module should only // generate a static version of itself based on the current global configuration. -func (a bp2BuildConversionAllowlist) GenerateCcLibraryStaticOnly(moduleName string) bool { +func (a Bp2BuildConversionAllowlist) GenerateCcLibraryStaticOnly(moduleName string) bool { return a.ccLibraryStaticOnly[moduleName] } -// NewBp2BuildAllowlist creates a new, empty bp2BuildConversionAllowlist +// NewBp2BuildAllowlist creates a new, empty Bp2BuildConversionAllowlist // which can be populated using builder pattern Set* methods -func NewBp2BuildAllowlist() bp2BuildConversionAllowlist { - return bp2BuildConversionAllowlist{ +func NewBp2BuildAllowlist() Bp2BuildConversionAllowlist { + return Bp2BuildConversionAllowlist{ allowlists.Bp2BuildConfig{}, map[string]bool{}, map[string]bool{}, @@ -259,7 +258,7 @@ func NewBp2BuildAllowlist() bp2BuildConversionAllowlist { } // SetDefaultConfig copies the entries from defaultConfig into the allowlist -func (a bp2BuildConversionAllowlist) SetDefaultConfig(defaultConfig allowlists.Bp2BuildConfig) bp2BuildConversionAllowlist { +func (a Bp2BuildConversionAllowlist) SetDefaultConfig(defaultConfig allowlists.Bp2BuildConfig) Bp2BuildConversionAllowlist { if a.defaultConfig == nil { a.defaultConfig = allowlists.Bp2BuildConfig{} } @@ -271,7 +270,7 @@ func (a bp2BuildConversionAllowlist) SetDefaultConfig(defaultConfig allowlists.B } // SetKeepExistingBuildFile copies the entries from keepExistingBuildFile into the allowlist -func (a bp2BuildConversionAllowlist) SetKeepExistingBuildFile(keepExistingBuildFile map[string]bool) bp2BuildConversionAllowlist { +func (a Bp2BuildConversionAllowlist) SetKeepExistingBuildFile(keepExistingBuildFile map[string]bool) Bp2BuildConversionAllowlist { if a.keepExistingBuildFile == nil { a.keepExistingBuildFile = map[string]bool{} } @@ -283,7 +282,7 @@ func (a bp2BuildConversionAllowlist) SetKeepExistingBuildFile(keepExistingBuildF } // SetModuleAlwaysConvertList copies the entries from moduleAlwaysConvert into the allowlist -func (a bp2BuildConversionAllowlist) SetModuleAlwaysConvertList(moduleAlwaysConvert []string) bp2BuildConversionAllowlist { +func (a Bp2BuildConversionAllowlist) SetModuleAlwaysConvertList(moduleAlwaysConvert []string) Bp2BuildConversionAllowlist { if a.moduleAlwaysConvert == nil { a.moduleAlwaysConvert = map[string]bool{} } @@ -295,7 +294,7 @@ func (a bp2BuildConversionAllowlist) SetModuleAlwaysConvertList(moduleAlwaysConv } // SetModuleTypeAlwaysConvertList copies the entries from moduleTypeAlwaysConvert into the allowlist -func (a bp2BuildConversionAllowlist) SetModuleTypeAlwaysConvertList(moduleTypeAlwaysConvert []string) bp2BuildConversionAllowlist { +func (a Bp2BuildConversionAllowlist) SetModuleTypeAlwaysConvertList(moduleTypeAlwaysConvert []string) Bp2BuildConversionAllowlist { if a.moduleTypeAlwaysConvert == nil { a.moduleTypeAlwaysConvert = map[string]bool{} } @@ -307,7 +306,7 @@ func (a bp2BuildConversionAllowlist) SetModuleTypeAlwaysConvertList(moduleTypeAl } // SetModuleDoNotConvertList copies the entries from moduleDoNotConvert into the allowlist -func (a bp2BuildConversionAllowlist) SetModuleDoNotConvertList(moduleDoNotConvert []string) bp2BuildConversionAllowlist { +func (a Bp2BuildConversionAllowlist) SetModuleDoNotConvertList(moduleDoNotConvert []string) Bp2BuildConversionAllowlist { if a.moduleDoNotConvert == nil { a.moduleDoNotConvert = map[string]bool{} } @@ -319,7 +318,7 @@ func (a bp2BuildConversionAllowlist) SetModuleDoNotConvertList(moduleDoNotConver } // SetCcLibraryStaticOnlyList copies the entries from ccLibraryStaticOnly into the allowlist -func (a bp2BuildConversionAllowlist) SetCcLibraryStaticOnlyList(ccLibraryStaticOnly []string) bp2BuildConversionAllowlist { +func (a Bp2BuildConversionAllowlist) SetCcLibraryStaticOnlyList(ccLibraryStaticOnly []string) Bp2BuildConversionAllowlist { if a.ccLibraryStaticOnly == nil { a.ccLibraryStaticOnly = map[string]bool{} } @@ -330,33 +329,15 @@ func (a bp2BuildConversionAllowlist) SetCcLibraryStaticOnlyList(ccLibraryStaticO return a } -var bp2BuildAllowListKey = NewOnceKey("Bp2BuildAllowlist") -var bp2buildAllowlist OncePer - -func GetBp2BuildAllowList() bp2BuildConversionAllowlist { - return bp2buildAllowlist.Once(bp2BuildAllowListKey, func() interface{} { - return NewBp2BuildAllowlist().SetDefaultConfig(allowlists.Bp2buildDefaultConfig). - SetKeepExistingBuildFile(allowlists.Bp2buildKeepExistingBuildFile). - SetModuleAlwaysConvertList(allowlists.Bp2buildModuleAlwaysConvertList). - SetModuleTypeAlwaysConvertList(allowlists.Bp2buildModuleTypeAlwaysConvertList). - SetModuleDoNotConvertList(allowlists.Bp2buildModuleDoNotConvertList). - SetCcLibraryStaticOnlyList(allowlists.Bp2buildCcLibraryStaticOnlyList) - }).(bp2BuildConversionAllowlist) -} - // ShouldKeepExistingBuildFileForDir returns whether an existing BUILD file should be // added to the build symlink forest based on the current global configuration. -func ShouldKeepExistingBuildFileForDir(dir string) bool { - return shouldKeepExistingBuildFileForDir(GetBp2BuildAllowList(), dir) -} - -func shouldKeepExistingBuildFileForDir(allowlist bp2BuildConversionAllowlist, dir string) bool { - if _, ok := allowlist.keepExistingBuildFile[dir]; ok { +func (a Bp2BuildConversionAllowlist) ShouldKeepExistingBuildFileForDir(dir string) bool { + if _, ok := a.keepExistingBuildFile[dir]; ok { // Exact dir match return true } // Check if subtree match - for prefix, recursive := range allowlist.keepExistingBuildFile { + for prefix, recursive := range a.keepExistingBuildFile { if recursive { if strings.HasPrefix(dir, prefix+"/") { return true @@ -367,6 +348,20 @@ func shouldKeepExistingBuildFileForDir(allowlist bp2BuildConversionAllowlist, di return false } +var bp2BuildAllowListKey = NewOnceKey("Bp2BuildAllowlist") +var bp2buildAllowlist OncePer + +func GetBp2BuildAllowList() Bp2BuildConversionAllowlist { + return bp2buildAllowlist.Once(bp2BuildAllowListKey, func() interface{} { + return NewBp2BuildAllowlist().SetDefaultConfig(allowlists.Bp2buildDefaultConfig). + SetKeepExistingBuildFile(allowlists.Bp2buildKeepExistingBuildFile). + SetModuleAlwaysConvertList(allowlists.Bp2buildModuleAlwaysConvertList). + SetModuleTypeAlwaysConvertList(allowlists.Bp2buildModuleTypeAlwaysConvertList). + SetModuleDoNotConvertList(allowlists.Bp2buildModuleDoNotConvertList). + SetCcLibraryStaticOnlyList(allowlists.Bp2buildCcLibraryStaticOnlyList) + }).(Bp2BuildConversionAllowlist) +} + // MixedBuildsEnabled returns true if a module is ready to be replaced by a // converted or handcrafted Bazel target. As a side effect, calling this // method will also log whether this module is mixed build enabled for @@ -431,7 +426,7 @@ func (b *BazelModuleBase) shouldConvertWithBp2build(ctx bazelOtherModuleContext, } moduleName := module.Name() - allowlist := ctx.Config().bp2buildPackageConfig + allowlist := ctx.Config().Bp2buildPackageConfig moduleNameAllowed := allowlist.moduleAlwaysConvert[moduleName] moduleTypeAllowed := allowlist.moduleTypeAlwaysConvert[ctx.OtherModuleType(module)] allowlistConvert := moduleNameAllowed || moduleTypeAllowed @@ -447,20 +442,12 @@ func (b *BazelModuleBase) shouldConvertWithBp2build(ctx bazelOtherModuleContext, return false } - if allowlistConvert && shouldKeepExistingBuildFileForDir(allowlist, packagePath) { - if moduleNameAllowed { - ctx.ModuleErrorf("A module cannot be in a directory listed in keepExistingBuildFile"+ - " and also be in moduleAlwaysConvert. Directory: '%s'", packagePath) - return false - } - } - // This is a tristate value: true, false, or unset. 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 } @@ -510,28 +497,6 @@ func bp2buildDefaultTrueRecursively(packagePath string, config allowlists.Bp2Bui return false, packagePath } -// GetBazelBuildFileContents returns the file contents of a hand-crafted BUILD file if available or -// an error if there are errors reading the file. -// TODO(b/181575318): currently we append the whole BUILD file, let's change that to do -// something more targeted based on the rule type and target. -func (b *BazelModuleBase) GetBazelBuildFileContents(c Config, path, name string) (string, error) { - if !strings.Contains(b.HandcraftedLabel(), path) { - return "", fmt.Errorf("%q not found in bazel_module.label %q", path, b.HandcraftedLabel()) - } - name = filepath.Join(path, name) - f, err := c.fs.Open(name) - if err != nil { - return "", err - } - defer f.Close() - - data, err := ioutil.ReadAll(f) - if err != nil { - return "", err - } - return string(data[:]), nil -} - func registerBp2buildConversionMutator(ctx RegisterMutatorsContext) { ctx.TopDown("bp2build_conversion", convertWithBp2build).Parallel() } diff --git a/android/bazel_handler.go b/android/bazel_handler.go index d87f98869..3e490dd94 100644 --- a/android/bazel_handler.go +++ b/android/bazel_handler.go @@ -343,7 +343,30 @@ func (m noopBazelContext) AqueryDepsets() []bazel.AqueryDepset { } func NewBazelContext(c *config) (BazelContext, error) { - if !c.IsMixedBuildsEnabled() { + var modulesDefaultToBazel bool + disabledModules := map[string]bool{} + enabledModules := map[string]bool{} + + switch c.BuildMode { + case BazelProdMode: + modulesDefaultToBazel = false + + for _, enabledProdModule := range allowlists.ProdMixedBuildsEnabledList { + enabledModules[enabledProdModule] = true + } + case BazelDevMode: + modulesDefaultToBazel = true + + // Don't use partially-converted cc_library targets in mixed builds, + // since mixed builds would generally rely on both static and shared + // variants of a cc_library. + for staticOnlyModule, _ := range GetBp2BuildAllowList().ccLibraryStaticOnly { + disabledModules[staticOnlyModule] = true + } + for _, disabledDevModule := range allowlists.MixedBuildsDisabledList { + disabledModules[disabledDevModule] = true + } + default: return noopBazelContext{}, nil } @@ -352,24 +375,12 @@ func NewBazelContext(c *config) (BazelContext, error) { return nil, err } - // TODO(cparsons): Use a different allowlist depending on prod vs. dev - // bazel mode. - disabledModules := map[string]bool{} - // Don't use partially-converted cc_library targets in mixed builds, - // since mixed builds would generally rely on both static and shared - // variants of a cc_library. - for staticOnlyModule, _ := range GetBp2BuildAllowList().ccLibraryStaticOnly { - disabledModules[staticOnlyModule] = true - } - for _, disabledDevModule := range allowlists.MixedBuildsDisabledList { - disabledModules[disabledDevModule] = true - } - return &bazelContext{ bazelRunner: &builtinBazelRunner{}, paths: p, requests: make(map[cqueryKey]bool), - modulesDefaultToBazel: true, + modulesDefaultToBazel: modulesDefaultToBazel, + bazelEnabledModules: enabledModules, bazelDisabledModules: disabledModules, }, nil } @@ -683,6 +694,31 @@ def %s(target): 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 @@ -716,15 +752,6 @@ def get_arch(target): 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) diff --git a/android/bazel_test.go b/android/bazel_test.go index 98f0a46d9..dbe6067f2 100644 --- a/android/bazel_test.go +++ b/android/bazel_test.go @@ -158,7 +158,7 @@ func (m TestBazelModule) GenerateBuildActions(blueprint.ModuleContext) { type TestBazelConversionContext struct { omc bazel.OtherModuleTestContext - allowlist bp2BuildConversionAllowlist + allowlist Bp2BuildConversionAllowlist errors []string } @@ -183,7 +183,7 @@ func (bcc *TestBazelConversionContext) ModuleErrorf(format string, args ...inter func (bcc *TestBazelConversionContext) Config() Config { return Config{ &config{ - bp2buildPackageConfig: bcc.allowlist, + Bp2buildPackageConfig: bcc.allowlist, }, } } @@ -202,7 +202,7 @@ func TestBp2BuildAllowlist(t *testing.T) { shouldConvert bool expectedErrors []string module TestBazelModule - allowlist bp2BuildConversionAllowlist + allowlist Bp2BuildConversionAllowlist }{ { description: "allowlist enables module", @@ -215,7 +215,7 @@ func TestBp2BuildAllowlist(t *testing.T) { }, BazelModuleBase: bazelableBazelModuleBase, }, - allowlist: bp2BuildConversionAllowlist{ + allowlist: Bp2BuildConversionAllowlist{ moduleAlwaysConvert: map[string]bool{ "foo": true, }, @@ -233,7 +233,7 @@ func TestBp2BuildAllowlist(t *testing.T) { }, BazelModuleBase: bazelableBazelModuleBase, }, - allowlist: bp2BuildConversionAllowlist{ + allowlist: Bp2BuildConversionAllowlist{ moduleAlwaysConvert: map[string]bool{ "foo": true, }, @@ -254,7 +254,7 @@ func TestBp2BuildAllowlist(t *testing.T) { }, BazelModuleBase: bazelableBazelModuleBase, }, - allowlist: bp2BuildConversionAllowlist{ + allowlist: Bp2BuildConversionAllowlist{ moduleAlwaysConvert: map[string]bool{ "foo": true, }, @@ -264,30 +264,9 @@ func TestBp2BuildAllowlist(t *testing.T) { }, }, { - description: "module in allowlist and existing BUILD file", - shouldConvert: false, - expectedErrors: []string{"A module cannot be in a directory listed in keepExistingBuildFile and also be in moduleAlwaysConvert. Directory: 'existing/build/dir'"}, - module: TestBazelModule{ - TestModuleInfo: bazel.TestModuleInfo{ - ModuleName: "foo", - Typ: "rule1", - Dir: "existing/build/dir", - }, - BazelModuleBase: bazelableBazelModuleBase, - }, - allowlist: bp2BuildConversionAllowlist{ - moduleAlwaysConvert: map[string]bool{ - "foo": true, - }, - keepExistingBuildFile: map[string]bool{ - "existing/build/dir": true, - }, - }, - }, - { 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", @@ -296,7 +275,7 @@ func TestBp2BuildAllowlist(t *testing.T) { }, BazelModuleBase: bazelableBazelModuleBase, }, - allowlist: bp2BuildConversionAllowlist{ + allowlist: Bp2BuildConversionAllowlist{ moduleAlwaysConvert: map[string]bool{ "foo": true, }, @@ -308,7 +287,7 @@ func TestBp2BuildAllowlist(t *testing.T) { { 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", @@ -317,7 +296,7 @@ func TestBp2BuildAllowlist(t *testing.T) { }, BazelModuleBase: bazelableBazelModuleBase, }, - allowlist: bp2BuildConversionAllowlist{ + allowlist: Bp2BuildConversionAllowlist{ moduleAlwaysConvert: map[string]bool{ "foo": true, }, @@ -344,7 +323,7 @@ func TestBp2BuildAllowlist(t *testing.T) { }, }, }, - allowlist: bp2BuildConversionAllowlist{ + allowlist: Bp2BuildConversionAllowlist{ moduleAlwaysConvert: map[string]bool{ "foo": true, }, diff --git a/android/config.go b/android/config.go index 5ca94209f..745410f1e 100644 --- a/android/config.go +++ b/android/config.go @@ -96,7 +96,6 @@ const ( // Use bazel during analysis of build modules from an allowlist carefully // curated by the build team to be proven stable. - // TODO(cparsons): Implement this mode. BazelProdMode ) @@ -190,7 +189,7 @@ type config struct { mockBpList string BuildMode SoongBuildMode - bp2buildPackageConfig bp2BuildConversionAllowlist + Bp2buildPackageConfig Bp2BuildConversionAllowlist Bp2buildSoongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions // If testAllowNonExistentPaths is true then PathForSource and PathForModuleSrc won't error @@ -481,17 +480,9 @@ func NewConfig(moduleListFile string, buildMode SoongBuildMode, runGoTests bool, config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0] } - // Checking USE_BAZEL_ANALYSIS must be done here instead of in the caller, so - // that we can invoke IsEnvTrue (which also registers the env var as a - // dependency of the build). - // TODO(cparsons): Remove this hack once USE_BAZEL_ANALYSIS is removed. - if buildMode == AnalysisNoBazel && config.IsEnvTrue("USE_BAZEL_ANALYSIS") { - buildMode = BazelDevMode - } - config.BuildMode = buildMode config.BazelContext, err = NewBazelContext(config) - config.bp2buildPackageConfig = GetBp2BuildAllowList() + config.Bp2buildPackageConfig = GetBp2BuildAllowList() return Config{config}, err } @@ -678,9 +669,7 @@ func (c *config) DeviceName() string { // DeviceProduct returns the current product target. There could be multiple of // these per device type. // -// NOTE: Do not base conditional logic on this value. It may break product -// -// inheritance. +// NOTE: Do not base conditional logic on this value. It may break product inheritance. func (c *config) DeviceProduct() string { return *c.productVariables.DeviceProduct } @@ -1630,6 +1619,10 @@ func (c *deviceConfig) ShippingApiLevel() ApiLevel { return uncheckedFinalApiLevel(apiLevel) } +func (c *deviceConfig) BuildBrokenClangProperty() bool { + return c.config.productVariables.BuildBrokenClangProperty +} + func (c *deviceConfig) BuildBrokenEnforceSyspropOwner() bool { return c.config.productVariables.BuildBrokenEnforceSyspropOwner } diff --git a/android/filegroup.go b/android/filegroup.go index e609f6362..6b1117230 100644 --- a/android/filegroup.go +++ b/android/filegroup.go @@ -33,6 +33,8 @@ var PrepareForTestWithFilegroup = FixtureRegisterWithContext(func(ctx Registrati 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 @@ func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) { 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 fileGroupProperties struct { 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) ProcessBazelQueryResponse(ctx ModuleContext) { } 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) ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) } 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 @@ func (fg *fileGroup) GetAidlLibraryLabel(ctx BazelConversionPathContext) string // 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 e2b839f69..008aac5e2 100644 --- a/android/gen_notice.go +++ b/android/gen_notice.go @@ -111,6 +111,9 @@ type genNoticeModule struct { } 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 @@ func GenNoticeFactory() Module { // 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 @@ func (m *genNoticeModule) OutputFiles(tag string) (Paths, error) { 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 4ad2ecfa9..99d982bda 100644 --- a/android/gen_notice_test.go +++ b/android/gen_notice_test.go @@ -21,7 +21,7 @@ var genNoticeTests = []struct { }`), }, expectedErrors: []string{ - `unrecognized property "licenses"`, + `not supported on "gen_notice" modules`, }, }, { diff --git a/android/license.go b/android/license.go index ebee05576..cde5e6e6e 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 @@ type licenseProperties struct { 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 @@ func LicenseFactory() Module { 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 @@ func LicenseFactory() Module { InitSdkAwareModule(module) initAndroidModuleBase(module) InitDefaultableModule(module) + InitBazelModule(module) return module } diff --git a/android/license_kind.go b/android/license_kind.go index 838deddd2..24b91e4c2 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 @@ type licenseKindProperties struct { 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 @@ func LicenseKindFactory() Module { 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/module.go b/android/module.go index 5908233a2..a0725bc8c 100644 --- a/android/module.go +++ b/android/module.go @@ -1169,7 +1169,9 @@ func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutator 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 { diff --git a/android/namespace.go b/android/namespace.go index fc7bc290f..a3ff76125 100644 --- a/android/namespace.go +++ b/android/namespace.go @@ -166,10 +166,10 @@ func (r *NameResolver) findNamespace(path string) (namespace *Namespace) { 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 @@ func (r *NameResolver) NewModule(ctx blueprint.NamespaceContext, moduleGroup blu return nil, nil } - if _, ok := module.(NamelessModule); ok { + if _, ok := module.(NamespacelessModule); ok { return nil, nil } diff --git a/android/package.go b/android/package.go index 878e4c4ed..2bf652126 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 @@ type packageProperties struct { 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 (p *packageModule) qualifiedModuleId(ctx BaseModuleContext) qualifiedModule 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 @@ func PackageFactory() Module { // 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 1f6912589..27f4bf577 100644 --- a/android/paths.go +++ b/android/paths.go @@ -1474,41 +1474,6 @@ func pathForModuleOut(ctx ModuleOutPathContext) OutputPath { return PathForOutput(ctx, ".intermediates", ctx.ModuleDir(), ctx.ModuleName(), ctx.ModuleSubDir()) } -// PathForVndkRefAbiDump returns an OptionalPath representing the path of the -// reference abi dump for the given module. This is not guaranteed to be valid. -func PathForVndkRefAbiDump(ctx ModuleInstallPathContext, version, fileName string, - isNdk, isVndk, isGzip bool) OptionalPath { - - currentArchType := ctx.Arch().ArchType - primaryArchType := ctx.Config().DevicePrimaryArchType() - archName := currentArchType.String() - if currentArchType != primaryArchType { - archName += "_" + primaryArchType.String() - } - - var dirName string - if isNdk { - dirName = "ndk" - } else if isVndk { - dirName = "vndk" - } else { - dirName = "platform" // opt-in libs - } - - binderBitness := ctx.DeviceConfig().BinderBitness() - - var ext string - if isGzip { - ext = ".lsdump.gz" - } else { - ext = ".lsdump" - } - - return ExistentPathForSource(ctx, "prebuilts", "abi-dumps", dirName, - version, binderBitness, archName, "source-based", - fileName+ext) -} - // PathForModuleOut returns a Path representing the paths... under the module's // output directory. func PathForModuleOut(ctx ModuleOutPathContext, paths ...string) ModuleOutPath { diff --git a/android/proto.go b/android/proto.go index 8ad16a6a3..3cac9a185 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 @@ func ProtoRule(rule *RuleBuilder, protoFile Path, flags ProtoFlags, deps Paths, // 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 @@ func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, m *ModuleBase, srcs baz return info, false } - info.Name = m.Name() + "_proto" - attrs := protoAttrs{ - Srcs: srcs, + var protoLibraries bazel.LabelList + var directProtoSrcs bazel.LabelList + + // 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) + } } - 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 + info.Name = m.Name() + "_proto" - 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 + 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.") } - } 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, + }) } - ctx.CreateBazelTargetModule( - bazel.BazelTargetModuleProperties{Rule_class: "proto_library"}, - CommonAttributes{Name: info.Name}, - &attrs) + info.Proto_libs = protoLibraries return info, true } diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go index cd36ae066..c0f452396 100644 --- a/android/soong_config_modules.go +++ b/android/soong_config_modules.go @@ -172,7 +172,7 @@ func (m *soongConfigModuleTypeImport) Name() string { "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 SoongConfigModuleTypeFactory() Module { } 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 SoongConfigBoolVariableDummyFactory() Module { } 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/testing.go b/android/testing.go index ef5e5a988..7b74c89a2 100644 --- a/android/testing.go +++ b/android/testing.go @@ -213,8 +213,8 @@ func (ctx *TestContext) FinalDepsMutators(f RegisterMutatorFunc) { ctx.finalDeps = append(ctx.finalDeps, f) } -func (ctx *TestContext) RegisterBp2BuildConfig(config bp2BuildConversionAllowlist) { - ctx.config.bp2buildPackageConfig = config +func (ctx *TestContext) RegisterBp2BuildConfig(config Bp2BuildConversionAllowlist) { + ctx.config.Bp2buildPackageConfig = config } // PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules @@ -1037,7 +1037,7 @@ func FailIfNoMatchingErrors(t *testing.T, pattern string, errs []error) bool { } } 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 2d7b0bf8e..b15605170 100644 --- a/android/variable.go +++ b/android/variable.go @@ -430,6 +430,7 @@ type productVariables struct { ShippingApiLevel *string `json:",omitempty"` + BuildBrokenClangProperty bool `json:",omitempty"` BuildBrokenDepfile *bool `json:",omitempty"` BuildBrokenEnforceSyspropOwner bool `json:",omitempty"` BuildBrokenTrebleSyspropNeverallow bool `json:",omitempty"` @@ -591,6 +592,9 @@ type ProductConfigProperty struct { // "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 { @@ -599,11 +603,11 @@ func (p *ProductConfigProperty) AlwaysEmit() bool { 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) } } @@ -662,9 +666,11 @@ func ProductVariableProperties(ctx BazelConversionPathContext) ProductConfigProp 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 @@ -673,7 +679,8 @@ func ProductVariableProperties(ctx BazelConversionPathContext) ProductConfigProp props, "", config, - &productConfigProperties) + &productConfigProperties, + axis) } } } @@ -686,7 +693,8 @@ func ProductVariableProperties(ctx BazelConversionPathContext) ProductConfigProp namespacedVariableProp, namespace, "", - &productConfigProperties) + &productConfigProperties, + bazel.NoConfigAxis) } } } @@ -802,6 +810,7 @@ func (props *ProductConfigProperties) zeroValuesForNamespacedVariables() { p.Name, p.FullConfig, zeroValue, + bazel.NoConfigAxis, ) } } @@ -809,7 +818,7 @@ func (props *ProductConfigProperties) zeroValuesForNamespacedVariables() { } 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{}) } @@ -818,6 +827,7 @@ func (p *ProductConfigProperties) AddProductConfigProperty( 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 != "" { @@ -868,7 +878,7 @@ func maybeExtractConfigVarProp(v reflect.Value) (reflect.Value, bool) { 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. // @@ -973,7 +983,8 @@ func (productConfigProperties *ProductConfigProperties) AddProductConfigProperti 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 { @@ -987,6 +998,7 @@ func (productConfigProperties *ProductConfigProperties) AddProductConfigProperti productVariableName, config, property.Interface(), + outerAxis, ) } } @@ -997,14 +1009,14 @@ func (productConfigProperties *ProductConfigProperties) AddProductConfigProperti // 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 949809ad9..2e54e7e6a 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -3054,36 +3054,6 @@ func makeApexAvailableBaseline() map[string][]string { // // 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 diff --git a/apex/apex_test.go b/apex/apex_test.go index 49a5d2ab1..18052912a 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -8843,9 +8843,7 @@ func TestApexJavaCoverage(t *testing.T) { android.FixtureWithRootAndroidBp(bp), dexpreopt.FixtureSetApexBootJars("myapex:mybootclasspathlib"), dexpreopt.FixtureSetApexSystemServerJars("myapex:mysystemserverclasspathlib"), - android.FixtureMergeEnv(map[string]string{ - "EMMA_INSTRUMENT": "true", - }), + java.PrepareForTestWithJacocoInstrumentation, ).RunTest(t) // Make sure jacoco ran on both mylib and mybootclasspathlib diff --git a/bazel/configurability.go b/bazel/configurability.go index d9b0a12b4..7ff202bf2 100644 --- a/bazel/configurability.go +++ b/bazel/configurability.go @@ -16,6 +16,8 @@ package bazel import ( "fmt" + "math" + "sort" "strings" ) @@ -69,6 +71,71 @@ const ( AndroidAndNonApex = "android-non_apex" ) +func PowerSetWithoutEmptySet[T any](items []T) [][]T { + resultSize := int(math.Pow(2, float64(len(items)))) + powerSet := make([][]T, 0, resultSize-1) + for i := 1; i < resultSize; i++ { + combination := make([]T, 0) + for j := 0; j < len(items); j++ { + if (i>>j)%2 == 1 { + combination = append(combination, items[j]) + } + } + powerSet = append(powerSet, combination) + } + return powerSet +} + +func createPlatformArchMap() map[string]string { + // Copy of archFeatures from android/arch_list.go because the bazel + // package can't access the android package + archFeatures := map[string][]string{ + "arm": { + "neon", + }, + "arm64": { + "dotprod", + }, + "x86": { + "ssse3", + "sse4", + "sse4_1", + "sse4_2", + "aes_ni", + "avx", + "avx2", + "avx512", + "popcnt", + "movbe", + }, + "x86_64": { + "ssse3", + "sse4", + "sse4_1", + "sse4_2", + "aes_ni", + "avx", + "avx2", + "avx512", + "popcnt", + }, + } + result := make(map[string]string) + for arch, allFeatures := range archFeatures { + result[arch] = "//build/bazel/platforms/arch:" + arch + // Sometimes we want to select on multiple features being active, so + // add the power set of all possible features to the map. More details + // in android.ModuleBase.GetArchVariantProperties + for _, features := range PowerSetWithoutEmptySet(allFeatures) { + sort.Strings(features) + archFeaturesName := arch + "-" + strings.Join(features, "-") + result[archFeaturesName] = "//build/bazel/platforms/arch/variants:" + archFeaturesName + } + } + result[ConditionsDefaultConfigKey] = ConditionsDefaultSelectKey + return result +} + var ( // These are the list of OSes and architectures with a Bazel config_setting // and constraint value equivalent. These exist in arch.go, but the android @@ -77,13 +144,7 @@ var ( // A map of architectures to the Bazel label of the constraint_value // for the @platforms//cpu:cpu constraint_setting - platformArchMap = map[string]string{ - archArm: "//build/bazel/platforms/arch:arm", - archArm64: "//build/bazel/platforms/arch:arm64", - archX86: "//build/bazel/platforms/arch:x86", - archX86_64: "//build/bazel/platforms/arch:x86_64", - ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of as arch select map. - } + platformArchMap = createPlatformArchMap() // A map of target operating systems to the Bazel label of the // constraint_value for the @platforms//os:os constraint_setting @@ -234,10 +295,11 @@ var ( ) // 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, } } @@ -248,6 +310,8 @@ type ConfigurationAxis struct { // 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 5cee6acf8..cf8e9f70c 100644 --- a/bazel/cquery/request_type.go +++ b/bazel/cquery/request_type.go @@ -235,14 +235,14 @@ func (g getApexInfoType) Name() string { // - The function body should not be indented outside of its own scope. func (g getApexInfoType) StarlarkFunctionBody() string { return `info = providers(target)["//build/bazel/rules/apex:apex.bzl%ApexInfo"] -return "{%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,7 +259,9 @@ type ApexCqueryInfo struct { // Starlark given in StarlarkFunctionBody. func (g getApexInfoType) ParseResult(rawString string) ApexCqueryInfo { var info ApexCqueryInfo - if err := json.Unmarshal([]byte(rawString), &info); err != nil { + decoder := json.NewDecoder(strings.NewReader(rawString)) + decoder.DisallowUnknownFields() //useful to detect typos, e.g. in unit tests + if err := decoder.Decode(&info); err != nil { panic(fmt.Errorf("cannot parse cquery result '%s': %s", rawString, err)) } return info diff --git a/bazel/cquery/request_type_test.go b/bazel/cquery/request_type_test.go index 34248ce81..46eb0b62a 100644 --- a/bazel/cquery/request_type_test.go +++ b/bazel/cquery/request_type_test.go @@ -161,7 +161,7 @@ func TestGetCcInfoParseResults(t *testing.T) { 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) + t.Errorf("%q:\n%12s: %q\n%12s: %q", tc.description, "expect Error", tc.expectedErrorMessage, "but got", err) } else if err == nil && !reflect.DeepEqual(tc.expectedOutput, actualOutput) { t.Errorf("%q:\n expected %#v\n!= actual %#v", tc.description, tc.expectedOutput, actualOutput) } diff --git a/bazel/properties.go b/bazel/properties.go index 13e36b582..11f62477d 100644 --- a/bazel/properties.go +++ b/bazel/properties.go @@ -309,7 +309,19 @@ func (la *LabelAttribute) Collapse() error { _, 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)) { @@ -725,7 +737,7 @@ func (lla *LabelListAttribute) SelectValue(axis ConfigurationAxis, config string case noConfig: return lla.Value case arch, os, osArch, productVariables, osAndInApex: - return (lla.ConfigurableValues[axis][config]) + return lla.ConfigurableValues[axis][config] default: panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis)) } diff --git a/bazel/properties_test.go b/bazel/properties_test.go index dc4d5b0f5..8729381b5 100644 --- a/bazel/properties_test.go +++ b/bazel/properties_test.go @@ -247,13 +247,13 @@ func TestResolveExcludes(t *testing.T) { 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 @@ func TestResolveExcludes(t *testing.T) { "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 @@ func TestDeduplicateAxesFromBase(t *testing.T) { OsArchConfigurationAxis: stringListSelectValues{ "linux_x86": {"linux_x86_include"}, }, - ProductVariableConfigurationAxis("a"): stringListSelectValues{ + ProductVariableConfigurationAxis("a", NoConfigAxis): stringListSelectValues{ "a": []string{"not_in_value"}, }, }, @@ -699,7 +699,7 @@ func TestDeduplicateAxesFromBase(t *testing.T) { "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 d327157d5..7c9af1a82 100644 --- a/bp2build/Android.bp +++ b/bp2build/Android.bp @@ -18,7 +18,6 @@ bootstrap_go_package { "testing.go", ], deps: [ - "aidl-soong-rules", "soong-android", "soong-android-allowlists", "soong-android-soongconfig", @@ -37,7 +36,6 @@ bootstrap_go_package { ], testSrcs: [ "aar_conversion_test.go", - "aidl_interface_conversion_test.go", "android_app_certificate_conversion_test.go", "android_app_conversion_test.go", "apex_conversion_test.go", @@ -53,6 +51,7 @@ bootstrap_go_package { "cc_prebuilt_library_conversion_test.go", "cc_prebuilt_library_shared_test.go", "cc_prebuilt_library_static_test.go", + "cc_test_conversion_test.go", "cc_yasm_conversion_test.go", "conversion_test.go", "filegroup_conversion_test.go", @@ -64,7 +63,11 @@ bootstrap_go_package { "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/aar_conversion_test.go b/bp2build/aar_conversion_test.go index 8e7c2b5da..ff8269420 100644 --- a/bp2build/aar_conversion_test.go +++ b/bp2build/aar_conversion_test.go @@ -53,7 +53,7 @@ android_library { } `, ExpectedBazelTargets: []string{ - makeBazelTarget( + MakeBazelTarget( "android_library", "TestLib", AttrNameToString{ @@ -120,7 +120,7 @@ android_library_import { } `, ExpectedBazelTargets: []string{ - makeBazelTarget( + MakeBazelTarget( "aar_import", "TestImport", AttrNameToString{ diff --git a/bp2build/aidl_interface_conversion_test.go b/bp2build/aidl_interface_conversion_test.go deleted file mode 100644 index 38d902d3b..000000000 --- a/bp2build/aidl_interface_conversion_test.go +++ /dev/null @@ -1,249 +0,0 @@ -package bp2build - -import ( - "android/soong/aidl" - "android/soong/android" - "testing" -) - -func runAidlInterfaceTestCase(t *testing.T, tc Bp2buildTestCase) { - t.Helper() - RunBp2BuildTestCase( - t, - func(ctx android.RegistrationContext) { - ctx.RegisterModuleType("aidl_interface", aidl.AidlInterfaceFactory) - ctx.RegisterModuleType("aidl_interface_headers", aidl.AidlInterfaceHeadersFactory) - }, - tc, - ) -} - -func TestAidlInterfaceHeaders(t *testing.T) { - runAidlInterfaceTestCase(t, Bp2buildTestCase{ - Description: `aidl_interface_headers`, - Blueprint: ` -aidl_interface_headers { - name: "aidl-interface-headers", - include_dir: "src", - srcs: [ - "src/A.aidl", - ], -} -`, - ExpectedBazelTargets: []string{ - MakeBazelTargetNoRestrictions("aidl_library", "aidl-interface-headers", AttrNameToString{ - "strip_import_prefix": `"src"`, - "hdrs": `["src/A.aidl"]`, - }), - }, - }) -} - -func TestAidlInterface(t *testing.T) { - runAidlInterfaceTestCase(t, Bp2buildTestCase{ - Description: `aidl_interface with single "latest" aidl_interface import`, - Blueprint: ` -aidl_interface_headers { - name: "aidl-interface-headers", -} -aidl_interface { - name: "aidl-interface-import", - versions: [ - "1", - "2", - ], -} -aidl_interface { - name: "aidl-interface1", - flags: ["--flag1"], - imports: [ - "aidl-interface-import-V1", - ], - headers: [ - "aidl-interface-headers", - ], - versions: [ - "1", - "2", - "3", - ], -}`, - ExpectedBazelTargets: []string{ - MakeBazelTargetNoRestrictions("aidl_library", "aidl-interface-headers", AttrNameToString{}), - MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface-import", AttrNameToString{ - "backends": `[ - "cpp", - "java", - "ndk", - ]`, - "versions": `[ - "1", - "2", - ]`, - }), - MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface1", AttrNameToString{ - "backends": `[ - "cpp", - "java", - "ndk", - ]`, - "deps": `[ - ":aidl-interface-import-V1", - ":aidl-interface-headers", - ]`, - "flags": `["--flag1"]`, - "versions": `[ - "1", - "2", - "3", - ]`, - }), - }, - }) -} - -func TestAidlInterfaceWithNoProperties(t *testing.T) { - runAidlInterfaceTestCase(t, Bp2buildTestCase{ - Description: `aidl_interface no properties set`, - Blueprint: ` -aidl_interface { - name: "aidl-interface1", -} -`, - ExpectedBazelTargets: []string{ - MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface1", AttrNameToString{ - "backends": `[ - "cpp", - "java", - "ndk", - ]`, - }), - }, - }) -} - -func TestAidlInterfaceWithDisabledBackends(t *testing.T) { - runAidlInterfaceTestCase(t, Bp2buildTestCase{ - Description: `aidl_interface with some backends disabled`, - Blueprint: ` -aidl_interface { - name: "aidl-interface1", - backend: { - ndk: { - enabled: false, - }, - cpp: { - enabled: false, - }, - }, -} -`, - ExpectedBazelTargets: []string{ - MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface1", AttrNameToString{ - "backends": `["java"]`, - }), - }, - }) -} - -func TestAidlInterfaceWithLatestImport(t *testing.T) { - runAidlInterfaceTestCase(t, Bp2buildTestCase{ - Description: `aidl_interface with single "latest" aidl_interface import`, - Blueprint: ` -aidl_interface { - name: "aidl-interface-import", - versions: [ - "1", - "2", - ], -} -aidl_interface { - name: "aidl-interface1", - imports: [ - "aidl-interface-import", - ], - versions: [ - "1", - "2", - "3", - ], -}`, - ExpectedBazelTargets: []string{ - MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface-import", AttrNameToString{ - "backends": `[ - "cpp", - "java", - "ndk", - ]`, - "versions": `[ - "1", - "2", - ]`, - }), - MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface1", AttrNameToString{ - "backends": `[ - "cpp", - "java", - "ndk", - ]`, - "deps": `[":aidl-interface-import-latest"]`, - "versions": `[ - "1", - "2", - "3", - ]`, - }), - }, - }) -} - -func TestAidlInterfaceWithVersionedImport(t *testing.T) { - runAidlInterfaceTestCase(t, Bp2buildTestCase{ - Description: `aidl_interface with single versioned aidl_interface import`, - Blueprint: ` -aidl_interface { - name: "aidl-interface-import", - versions: [ - "1", - "2", - ], -} -aidl_interface { - name: "aidl-interface1", - imports: [ - "aidl-interface-import-V2", - ], - versions: [ - "1", - "2", - "3", - ], -}`, - ExpectedBazelTargets: []string{ - MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface-import", AttrNameToString{ - "backends": `[ - "cpp", - "java", - "ndk", - ]`, - "versions": `[ - "1", - "2", - ]`, - }), - MakeBazelTargetNoRestrictions("aidl_interface", "aidl-interface1", AttrNameToString{ - "backends": `[ - "cpp", - "java", - "ndk", - ]`, - "deps": `[":aidl-interface-import-V2"]`, - "versions": `[ - "1", - "2", - "3", - ]`, - }), - }, - }) -} diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go index a37af12bd..e112be3a3 100644 --- a/bp2build/android_app_conversion_test.go +++ b/bp2build/android_app_conversion_test.go @@ -47,7 +47,7 @@ android_app { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("android_binary", "TestApp", AttrNameToString{ + MakeBazelTarget("android_binary", "TestApp", AttrNameToString{ "srcs": `["app.java"]`, "manifest": `"AndroidManifest.xml"`, "resource_files": `["res/res.png"]`, @@ -79,7 +79,7 @@ android_app { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("android_binary", "TestApp", AttrNameToString{ + MakeBazelTarget("android_binary", "TestApp", AttrNameToString{ "srcs": `["app.java"]`, "manifest": `"manifest/AndroidManifest.xml"`, "resource_files": `[ @@ -119,7 +119,7 @@ android_app { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("android_binary", "TestApp", AttrNameToString{ + MakeBazelTarget("android_binary", "TestApp", AttrNameToString{ "srcs": `select({ "//build/bazel/platforms/arch:arm": ["arm.java"], "//build/bazel/platforms/arch:x86": ["x86.java"], diff --git a/bp2build/androidbp_to_build_templates.go b/bp2build/androidbp_to_build_templates.go index 5fed4fab5..9b21c3278 100644 --- a/bp2build/androidbp_to_build_templates.go +++ b/bp2build/androidbp_to_build_templates.go @@ -23,7 +23,7 @@ load("//build/bazel/queryview_rules:soong_module.bzl", "soong_module") // 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 @@ load("//build/bazel/queryview_rules:soong_module.bzl", "soong_module") 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 415e69558..b0a2966b3 100644 --- a/bp2build/apex_conversion_test.go +++ b/bp2build/apex_conversion_test.go @@ -141,7 +141,7 @@ apex { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{ "android_manifest": `"ApogeeAndroidManifest.xml"`, "binaries": `[ ":cc_binary_1", @@ -203,7 +203,7 @@ apex { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{ "file_contexts": `"//a/b:com.android.apogee-file_contexts"`, "manifest": `"apex_manifest.json"`, }), @@ -223,7 +223,7 @@ apex { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{ "file_contexts": `"file_contexts_file"`, "manifest": `"apex_manifest.json"`, }), @@ -252,7 +252,7 @@ apex { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{ "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`, "manifest": `"apex_manifest.json"`, }), @@ -275,7 +275,7 @@ filegroup { }, Blueprint: createMultilibBlueprint("both"), ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{ "native_shared_libs_32": `[ ":native_shared_lib_1", ":native_shared_lib_3", @@ -319,7 +319,7 @@ filegroup { }, Blueprint: createMultilibBlueprint("first"), ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{ "native_shared_libs_32": `select({ "//build/bazel/platforms/arch:arm": [ ":native_shared_lib_1", @@ -368,7 +368,7 @@ filegroup { }, Blueprint: createMultilibBlueprint("32"), ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{ "native_shared_libs_32": `[ ":native_shared_lib_1", ":native_shared_lib_3", @@ -399,7 +399,7 @@ filegroup { }, Blueprint: createMultilibBlueprint("64"), ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{ "native_shared_libs_64": `select({ "//build/bazel/platforms/arch:arm64": [ ":native_shared_lib_1", @@ -439,7 +439,7 @@ apex { manifest: "apogee_manifest.json", } `, - ExpectedBazelTargets: []string{makeBazelTarget("apex", "com.android.apogee", AttrNameToString{ + ExpectedBazelTargets: []string{MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{ "manifest": `"apogee_manifest.json"`, "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`, }), @@ -467,7 +467,7 @@ apex { bazel_module: { bp2build_available: true }, } `, - ExpectedBazelTargets: []string{makeBazelTarget("apex", "apogee", AttrNameToString{ + ExpectedBazelTargets: []string{MakeBazelTarget("apex", "apogee", AttrNameToString{ "manifest": `"manifest.json"`, "file_contexts": `"//system/sepolicy/apex:apogee-file_contexts"`, }), @@ -624,7 +624,7 @@ override_apex { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ "android_manifest": `"ApogeeAndroidManifest.xml"`, "binaries": `[ ":cc_binary_1", @@ -684,7 +684,7 @@ override_apex { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`, "manifest": `"//a/b:apex_manifest.json"`, }), @@ -718,7 +718,7 @@ override_apex { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`, "manifest": `"//a/b:apogee_manifest.json"`, }), @@ -750,7 +750,7 @@ override_apex { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`, "manifest": `"apex_manifest.json"`, }), @@ -783,7 +783,7 @@ override_apex { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`, "manifest": `"apogee_manifest.json"`, }), @@ -816,7 +816,7 @@ override_apex { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`, "manifest": `"apex_manifest.json"`, "package_name": `"com.google.android.apogee"`, @@ -855,7 +855,7 @@ override_apex { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`, "manifest": `"apex_manifest.json"`, "prebuilts": `[":prebuilt_file"]`, @@ -900,7 +900,7 @@ override_apex { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`, "manifest": `"apex_manifest.json"`, "prebuilts": `[":prebuilt_file2"]`, @@ -940,7 +940,7 @@ override_apex { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`, "manifest": `"apex_manifest.json"`, "prebuilts": `[]`, @@ -974,7 +974,7 @@ override_apex { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`, "manifest": `"apex_manifest.json"`, "logging_parent": `"foo.bar.baz"`, @@ -1009,7 +1009,7 @@ override_apex { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ + MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{ "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`, "manifest": `"apex_manifest.json"`, "logging_parent": `"foo.bar.baz.override"`, diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go index 242ea1e69..ee162b263 100644 --- a/bp2build/build_conversion.go +++ b/bp2build/build_conversion.go @@ -43,7 +43,6 @@ type BazelTarget struct { content string ruleClass string bzlLoadLocation string - handcrafted bool } // IsLoadedFromStarlark determines if the BazelTarget's rule class is loaded from a .bzl file, @@ -65,25 +64,18 @@ func (t BazelTarget) Label() string { // BazelTargets is a typedef for a slice of BazelTarget objects. type BazelTargets []BazelTarget -// HasHandcraftedTargetsreturns true if a set of bazel targets contain -// handcrafted ones. -func (targets BazelTargets) hasHandcraftedTargets() bool { +func (targets BazelTargets) packageRule() *BazelTarget { for _, target := range targets { - if target.handcrafted { - return true + if target.ruleClass == "package" { + return &target } } - return false + 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 { - if targets[i].handcrafted != targets[j].handcrafted { - // Handcrafted targets will be generated after the bp2build generated targets. - return targets[j].handcrafted - } - // This will cover all bp2build generated targets. return targets[i].name < targets[j].name }) } @@ -94,19 +86,9 @@ func (targets BazelTargets) sort() { func (targets BazelTargets) String() string { var res string for i, target := range targets { - // There is only at most 1 handcrafted "target", because its contents - // represent the entire BUILD file content from the tree. See - // build_conversion.go#getHandcraftedBuildContent for more information. - // - // Add a header to make it easy to debug where the handcrafted targets - // are in a generated BUILD file. - if target.handcrafted { - res += "# -----------------------------\n" - res += "# Section: Handcrafted targets. \n" - res += "# -----------------------------\n\n" + if target.ruleClass != "package" { + res += target.content } - - res += target.content if i != len(targets)-1 { res += "\n\n" } @@ -256,7 +238,6 @@ func (r conversionResults) BuildDirToTargets() map[string]BazelTargets { func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (conversionResults, []error) { buildFileToTargets := make(map[string]BazelTargets) - buildFileToAppend := make(map[string]bool) // Simple metrics tracking for bp2build metrics := CodegenMetrics{ @@ -288,30 +269,10 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers // Handle modules converted to handcrafted targets. // // Since these modules are associated with some handcrafted - // target in a BUILD file, we simply append the entire contents - // of that BUILD file to the generated BUILD file. - // - // The append operation is only done once, even if there are - // multiple modules from the same directory associated to - // targets in the same BUILD file (or package). + // target in a BUILD file, we don't autoconvert them. // Log the module. metrics.AddConvertedModule(m, moduleType, Handcrafted) - - pathToBuildFile := getBazelPackagePath(b) - if _, exists := buildFileToAppend[pathToBuildFile]; exists { - // Append the BUILD file content once per package, at most. - return - } - t, err := getHandcraftedBuildContent(ctx, b, pathToBuildFile) - if err != nil { - errs = append(errs, fmt.Errorf("Error converting %s: %s", bpCtx.ModuleName(m), err)) - return - } - targets = append(targets, t) - // TODO(b/181575318): currently we append the whole BUILD file, let's change that to do - // something more targeted based on the rule type and target - buildFileToAppend[pathToBuildFile] = true } else if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() { // Handle modules converted to generated targets. @@ -339,7 +300,9 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers 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. @@ -356,7 +319,10 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers // 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) default: errs = append(errs, fmt.Errorf("Unknown code-generation mode: %s", ctx.Mode())) @@ -373,6 +339,15 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers if generateFilegroups { // Add a filegroup target that exposes all sources in the subtree of this package // NOTE: This also means we generate a BUILD file for every Android.bp file (as long as it has at least one module) + // + // This works because: https://bazel.build/reference/be/functions#exports_files + // "As a legacy behaviour, also files mentioned as input to a rule are exported with the + // default visibility until the flag --incompatible_no_implicit_file_export is flipped. However, this behavior + // should not be relied upon and actively migrated away from." + // + // 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 { buildFileToTargets[dir] = append(buildFileToTargets[dir], BazelTarget{ name: "bp2build_all_srcs", @@ -388,35 +363,18 @@ func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (convers }, errs } -func getBazelPackagePath(b android.Bazelable) string { - label := b.HandcraftedLabel() - pathToBuildFile := strings.TrimPrefix(label, "//") - pathToBuildFile = strings.Split(pathToBuildFile, ":")[0] - return pathToBuildFile -} - -func getHandcraftedBuildContent(ctx *CodegenContext, b android.Bazelable, pathToBuildFile string) (BazelTarget, error) { - p := android.ExistentPathForSource(ctx, pathToBuildFile, HandcraftedBuildFileName) - if !p.Valid() { - return BazelTarget{}, fmt.Errorf("Could not find file %q for handcrafted target.", pathToBuildFile) - } - c, err := b.GetBazelBuildFileContents(ctx.Config(), pathToBuildFile, HandcraftedBuildFileName) - if err != nil { - return BazelTarget{}, err - } - // TODO(b/181575318): once this is more targeted, we need to include name, rule class, etc - return BazelTarget{ - content: c, - handcrafted: true, - }, nil -} - -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 { @@ -427,13 +385,16 @@ type bp2buildModule interface { 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") @@ -441,26 +402,26 @@ func generateBazelTarget(ctx bpToBuildContext, m bp2buildModule) BazelTarget { // 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, - ), - handcrafted: false, - } + 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 @@ -487,28 +448,28 @@ func generateSoongModuleTarget(ctx bpToBuildContext, m blueprint.Module) BazelTa 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. @@ -521,24 +482,29 @@ func extractModuleProperties(props []interface{}, checkForDuplicateProperties bo // 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 { @@ -596,7 +562,12 @@ func prettyPrint(propertyValue reflect.Value, indent int, emitZeroValues bool) ( } // 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 } @@ -615,11 +586,13 @@ func prettyPrint(propertyValue reflect.Value, indent int, emitZeroValues bool) ( // 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++ { @@ -640,7 +613,10 @@ func extractStructProperties(structValue reflect.Value, indent int) map[string]s 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 } @@ -649,20 +625,20 @@ func extractStructProperties(structValue reflect.Value, indent int) map[string]s } 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 1ac7518a8..dd28c3c94 100644 --- a/bp2build/build_conversion_test.go +++ b/bp2build/build_conversion_test.go @@ -238,7 +238,7 @@ func TestGenerateBazelTargetModules(t *testing.T) { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("custom", "foo", AttrNameToString{ + MakeBazelTarget("custom", "foo", AttrNameToString{ "string_literal_prop": `""`, }), }, @@ -251,7 +251,7 @@ func TestGenerateBazelTargetModules(t *testing.T) { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("custom", "foo", AttrNameToString{ + MakeBazelTarget("custom", "foo", AttrNameToString{ "string_literal_prop": `"PROP"`, }), }, @@ -267,7 +267,7 @@ func TestGenerateBazelTargetModules(t *testing.T) { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("custom", "foo", AttrNameToString{ + MakeBazelTarget("custom", "foo", AttrNameToString{ "string_literal_prop": `select({ "//build/bazel/platforms/arch:arm": "ARM", "//build/bazel/platforms/arch:arm64": "ARM64", @@ -284,7 +284,7 @@ func TestGenerateBazelTargetModules(t *testing.T) { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("custom", "foo", AttrNameToString{ + MakeBazelTarget("custom", "foo", AttrNameToString{ "string_ptr_prop": `""`, }), }, @@ -298,7 +298,7 @@ func TestGenerateBazelTargetModules(t *testing.T) { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("custom", "foo", AttrNameToString{ + MakeBazelTarget("custom", "foo", AttrNameToString{ "string_list_prop": `[ "a", "b", @@ -316,7 +316,7 @@ func TestGenerateBazelTargetModules(t *testing.T) { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("custom", "foo", AttrNameToString{ + MakeBazelTarget("custom", "foo", AttrNameToString{ "string_list_prop": `[ "\t", "\n", @@ -339,10 +339,10 @@ custom { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("custom", "dep", AttrNameToString{ + MakeBazelTarget("custom", "dep", AttrNameToString{ "arch_paths": `["abc"]`, }), - makeBazelTarget("custom", "has_dep", AttrNameToString{ + MakeBazelTarget("custom", "has_dep", AttrNameToString{ "arch_paths": `[":dep"]`, }), }, @@ -355,7 +355,7 @@ custom { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("custom", "has_dep", AttrNameToString{ + MakeBazelTarget("custom", "has_dep", AttrNameToString{ "arch_paths": `[":dep__BP2BUILD__MISSING__DEP"]`, }), }, @@ -391,7 +391,7 @@ custom { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("custom", "arch_paths", AttrNameToString{ + MakeBazelTarget("custom", "arch_paths", AttrNameToString{ "arch_paths": `select({ "//build/bazel/platforms/arch:arm": [ "arm.txt", @@ -469,10 +469,10 @@ custom { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("custom", "dep", AttrNameToString{ + MakeBazelTarget("custom", "dep", AttrNameToString{ "arch_paths": `["abc"]`, }), - makeBazelTarget("custom", "has_dep", AttrNameToString{ + MakeBazelTarget("custom", "has_dep", AttrNameToString{ "arch_paths": `select({ "//build/bazel/platforms/arch:x86": [":dep"], "//conditions:default": [], @@ -488,7 +488,7 @@ custom { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("custom", "embedded_props", AttrNameToString{ + MakeBazelTarget("custom", "embedded_props", AttrNameToString{ "embedded_attr": `"abc"`, }), }, @@ -501,7 +501,7 @@ custom { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("custom", "ptr_to_embedded_props", AttrNameToString{ + MakeBazelTarget("custom", "ptr_to_embedded_props", AttrNameToString{ "other_embedded_attr": `"abc"`, }), }, @@ -751,7 +751,7 @@ func TestBp2buildHostAndDevice(t *testing.T) { for _, tc := range testCases { t.Run(tc.Description, func(t *testing.T) { - runBp2BuildTestCaseSimple(t, tc) + RunBp2BuildTestCaseSimple(t, tc) }) } } @@ -1299,9 +1299,7 @@ func TestCombineBuildFilesBp2buildTargets(t *testing.T) { name: "fg_foo", bazel_module: { label: "//other:fg_foo" }, }`, - ExpectedBazelTargets: []string{ - `// BUILD file`, - }, + ExpectedBazelTargets: []string{}, Filesystem: map[string]string{ "other/BUILD.bazel": `// BUILD file`, }, @@ -1319,9 +1317,7 @@ func TestCombineBuildFilesBp2buildTargets(t *testing.T) { name: "foo", bazel_module: { label: "//other:foo" }, }`, - ExpectedBazelTargets: []string{ - `// BUILD file`, - }, + ExpectedBazelTargets: []string{}, Filesystem: map[string]string{ "other/BUILD.bazel": `// BUILD file`, }, @@ -1349,7 +1345,6 @@ func TestCombineBuildFilesBp2buildTargets(t *testing.T) { }, ExpectedBazelTargets: []string{ MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{}), - `// definition for fg_bar`, }, }, { @@ -1375,7 +1370,6 @@ func TestCombineBuildFilesBp2buildTargets(t *testing.T) { }`, ExpectedBazelTargets: []string{ MakeBazelTargetNoRestrictions("filegroup", "fg_bar", map[string]string{}), - `// BUILD file`, }, }, } @@ -1420,9 +1414,6 @@ func TestCombineBuildFilesBp2buildTargets(t *testing.T) { if actualCount != expectedCount { t.Errorf("Expected %d bazel target, got %d\n%s", expectedCount, actualCount, bazelTargets) } - if !strings.Contains(bazelTargets.String(), "Section: Handcrafted targets. ") { - t.Errorf("Expected string representation of bazelTargets to contain handcrafted section header.") - } for i, target := range bazelTargets { actualContent := target.content expectedContent := testCase.ExpectedBazelTargets[i] @@ -1503,7 +1494,7 @@ func TestGlobExcludeSrcs(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.Description, func(t *testing.T) { - runBp2BuildTestCaseSimple(t, testCase) + RunBp2BuildTestCaseSimple(t, testCase) }) } } @@ -1545,7 +1536,7 @@ python_library { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("py_library", "fg_foo", map[string]string{ + MakeBazelTarget("py_library", "fg_foo", map[string]string{ "data": `select({ "//build/bazel/platforms/arch:arm": [":reqdarm"], "//build/bazel/platforms/arch:x86": [":reqdx86"], @@ -1572,7 +1563,7 @@ python_library { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("py_library", "fg_foo", map[string]string{ + MakeBazelTarget("py_library", "fg_foo", map[string]string{ "data": `[ "data.bin", ":reqd", @@ -1602,7 +1593,7 @@ filegroup { for _, tc := range testCases { t.Run(tc.Description, func(t *testing.T) { - runBp2BuildTestCaseSimple(t, tc) + RunBp2BuildTestCaseSimple(t, tc) }) } } diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go index 9e449eb10..67d4a1c96 100644 --- a/bp2build/cc_binary_conversion_test.go +++ b/bp2build/cc_binary_conversion_test.go @@ -605,8 +605,67 @@ func TestCcBinaryWithInstructionSet(t *testing.T) { "//conditions:default": [], })`, "local_includes": `["."]`, - }, - }, + }}, + }, + }) +} + +func TestCcBinaryEmptySuffix(t *testing.T) { + runCcBinaryTests(t, ccBinaryBp2buildTestCase{ + description: "binary with empty suffix", + blueprint: ` +{rule_name} { + name: "foo", + suffix: "", +}`, + targets: []testBazelTarget{ + {"cc_binary", "foo", AttrNameToString{ + "local_includes": `["."]`, + "suffix": `""`, + }}, + }, + }) +} + +func TestCcBinarySuffix(t *testing.T) { + runCcBinaryTests(t, ccBinaryBp2buildTestCase{ + description: "binary with suffix", + blueprint: ` +{rule_name} { + name: "foo", + suffix: "-suf", +} +`, + targets: []testBazelTarget{ + {"cc_binary", "foo", AttrNameToString{ + "local_includes": `["."]`, + "suffix": `"-suf"`, + }}, + }, + }) +} + +func TestCcArchVariantBinarySuffix(t *testing.T) { + runCcBinaryTests(t, ccBinaryBp2buildTestCase{ + description: "binary with suffix", + blueprint: ` +{rule_name} { + name: "foo", + arch: { + arm64: { suffix: "-64" }, + arm: { suffix: "-32" }, + }, +} +`, + targets: []testBazelTarget{ + {"cc_binary", "foo", AttrNameToString{ + "local_includes": `["."]`, + "suffix": `select({ + "//build/bazel/platforms/arch:arm": "-32", + "//build/bazel/platforms/arch:arm64": "-64", + "//conditions:default": None, + })`, + }}, }, }) } diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go index 024d4e0df..2d4c6da87 100644 --- a/bp2build/cc_library_conversion_test.go +++ b/bp2build/cc_library_conversion_test.go @@ -355,7 +355,7 @@ cc_library { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ "copts": `[ "bothflag", "staticflag", @@ -377,7 +377,7 @@ cc_library { ":whole_and_static_lib_for_both", ":whole_static_lib_for_static", ]`}), - makeBazelTarget("cc_library_shared", "a", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "a", AttrNameToString{ "copts": `[ "bothflag", "sharedflag", @@ -463,7 +463,7 @@ cc_library { simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_both") + simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_both"), ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ "copts": `[ "bothflag", "staticflag", @@ -495,7 +495,7 @@ cc_library { ":whole_static_dep_for_static", ]`, }), - makeBazelTarget("cc_library_shared", "a", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "a", AttrNameToString{ "copts": `[ "bothflag", "sharedflag", @@ -560,13 +560,13 @@ cc_prebuilt_library_static { name: "whole_static_lib_for_both" } }, Blueprint: soongCcLibraryPreamble, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ "whole_archive_deps": `[ ":whole_static_lib_for_both_alwayslink", ":whole_static_lib_for_static_alwayslink", ]`, }), - makeBazelTarget("cc_library_shared", "a", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "a", AttrNameToString{ "whole_archive_deps": `[ ":whole_static_lib_for_both_alwayslink", ":whole_static_lib_for_shared_alwayslink", @@ -654,7 +654,7 @@ cc_library_static { name: "android_dep_for_shared" } }, Blueprint: soongCcLibraryPreamble, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ "copts": `[ "bothflag", "staticflag", @@ -678,7 +678,7 @@ cc_library_static { name: "android_dep_for_shared" } "//conditions:default": [], })`, }), - makeBazelTarget("cc_library_shared", "a", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "a", AttrNameToString{ "copts": `[ "bothflag", "sharedflag", @@ -807,7 +807,7 @@ filegroup { }, Blueprint: soongCcLibraryPreamble, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ "local_includes": `["."]`, "srcs": `[ "both_source.cpp", @@ -832,7 +832,7 @@ filegroup { ":static_filegroup_c_srcs", ]`, }), - makeBazelTarget("cc_library_shared", "a", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "a", AttrNameToString{ "local_includes": `["."]`, "srcs": `[ "both_source.cpp", @@ -1199,6 +1199,40 @@ cc_library { ) } +func TestCcLibraryProductVariablesHeaderLibs(t *testing.T) { + runCcLibraryTestCase(t, Bp2buildTestCase{ + ModuleTypeUnderTest: "cc_library", + ModuleTypeUnderTestFactory: cc.LibraryFactory, + Filesystem: map[string]string{}, + Blueprint: soongCcLibraryStaticPreamble + ` +cc_library { + name: "foo_static", + srcs: ["common.c"], + product_variables: { + malloc_not_svelte: { + header_libs: ["malloc_not_svelte_header_lib"], + }, + }, + include_build_directory: false, +} + +cc_library { + name: "malloc_not_svelte_header_lib", + bazel_module: { bp2build_available: false }, +} +`, + ExpectedBazelTargets: makeCcLibraryTargets("foo_static", AttrNameToString{ + "implementation_deps": `select({ + "//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_header_lib"], + "//conditions:default": [], + })`, + "srcs_c": `["common.c"]`, + "target_compatible_with": `["//build/bazel/platforms/os:android"]`, + }), + }, + ) +} + func TestCCLibraryNoCrtTrue(t *testing.T) { runCcLibraryTestCase(t, Bp2buildTestCase{ Description: "cc_library - nocrt: true emits attribute", @@ -1315,8 +1349,8 @@ func makeCcLibraryTargets(name string, attrs AttrNameToString) []string { staticAttrs[key] = val } } - sharedTarget := makeBazelTarget("cc_library_shared", name, sharedAttrs) - staticTarget := makeBazelTarget("cc_library_static", name+"_bp2build_cc_library_static", staticAttrs) + sharedTarget := MakeBazelTarget("cc_library_shared", name, sharedAttrs) + staticTarget := MakeBazelTarget("cc_library_static", name+"_bp2build_cc_library_static", staticAttrs) return []string{staticTarget, sharedTarget} } @@ -1338,7 +1372,7 @@ func makeCcStubSuiteTargets(name string, attrs AttrNameToString) string { stubSuiteAttrs[STUB_SUITE_ATTRS[key]] = attrs[key] } } - return makeBazelTarget("cc_stub_suite", name+"_stub_libs", stubSuiteAttrs) + return MakeBazelTarget("cc_stub_suite", name+"_stub_libs", stubSuiteAttrs) } func TestCCLibraryNoLibCrtFalse(t *testing.T) { @@ -1649,10 +1683,10 @@ cc_library { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "static_empty_bp2build_cc_library_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "static_empty_bp2build_cc_library_static", AttrNameToString{ "system_dynamic_deps": "[]", }), - makeBazelTarget("cc_library_shared", "static_empty", AttrNameToString{}), + MakeBazelTarget("cc_library_shared", "static_empty", AttrNameToString{}), }, }) } @@ -1672,8 +1706,8 @@ cc_library { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "shared_empty_bp2build_cc_library_static", AttrNameToString{}), - makeBazelTarget("cc_library_shared", "shared_empty", AttrNameToString{ + MakeBazelTarget("cc_library_static", "shared_empty_bp2build_cc_library_static", AttrNameToString{}), + MakeBazelTarget("cc_library_shared", "shared_empty", AttrNameToString{ "system_dynamic_deps": "[]", }), }, @@ -1699,8 +1733,8 @@ cc_library { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "shared_empty_bp2build_cc_library_static", AttrNameToString{}), - makeBazelTarget("cc_library_shared", "shared_empty", AttrNameToString{ + MakeBazelTarget("cc_library_static", "shared_empty_bp2build_cc_library_static", AttrNameToString{}), + MakeBazelTarget("cc_library_shared", "shared_empty", AttrNameToString{ "system_dynamic_deps": "[]", }), }, @@ -1782,10 +1816,10 @@ cc_library { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ "system_dynamic_deps": `[":libc"]`, }), - makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "system_dynamic_deps": `[ ":libc", ":libm", @@ -2000,7 +2034,7 @@ cc_library_static { } `, name_prefix, cppStdProp, cStdProp, gnuExtensionsProp), ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", name_prefix+"_static", attrs), + MakeBazelTarget("cc_library_static", name_prefix+"_static", attrs), }, }) @@ -2019,7 +2053,7 @@ cc_library_shared { } `, name_prefix, cppStdProp, cStdProp, gnuExtensionsProp), ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", name_prefix+"_shared", attrs), + MakeBazelTarget("cc_library_shared", name_prefix+"_shared", attrs), }, }) }) @@ -2036,15 +2070,16 @@ func TestCcLibraryProtoSimple(t *testing.T) { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("proto_library", "foo_proto", AttrNameToString{ + MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{ "srcs": `["foo.proto"]`, - }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ + }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ "deps": `[":foo_proto"]`, - }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + }), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`, "deps": `[":libprotobuf-cpp-lite"]`, - }), makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ - "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`, }), }, }) @@ -2061,16 +2096,17 @@ func TestCcLibraryProtoNoCanonicalPathFromRoot(t *testing.T) { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("proto_library", "foo_proto", AttrNameToString{ + MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{ "srcs": `["foo.proto"]`, "strip_import_prefix": `""`, - }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ + }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ "deps": `[":foo_proto"]`, - }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + }), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`, "deps": `[":libprotobuf-cpp-lite"]`, - }), makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ - "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`, }), }, }) @@ -2087,15 +2123,16 @@ func TestCcLibraryProtoExplicitCanonicalPathFromRoot(t *testing.T) { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("proto_library", "foo_proto", AttrNameToString{ + MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{ "srcs": `["foo.proto"]`, - }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ + }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ "deps": `[":foo_proto"]`, - }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + }), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`, "deps": `[":libprotobuf-cpp-lite"]`, - }), makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ - "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`, }), }, }) @@ -2114,15 +2151,16 @@ func TestCcLibraryProtoFull(t *testing.T) { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("proto_library", "foo_proto", AttrNameToString{ + MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{ "srcs": `["foo.proto"]`, - }), makeBazelTarget("cc_proto_library", "foo_cc_proto", AttrNameToString{ + }), MakeBazelTarget("cc_proto_library", "foo_cc_proto", AttrNameToString{ "deps": `[":foo_proto"]`, - }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + }), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ "implementation_whole_archive_deps": `[":foo_cc_proto"]`, "deps": `[":libprotobuf-cpp-full"]`, - }), makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ - "dynamic_deps": `[":libprotobuf-cpp-full"]`, + }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-full"]`, + "implementation_whole_archive_deps": `[":foo_cc_proto"]`, }), }, }) @@ -2141,15 +2179,16 @@ func TestCcLibraryProtoLite(t *testing.T) { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("proto_library", "foo_proto", AttrNameToString{ + MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{ "srcs": `["foo.proto"]`, - }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ + }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ "deps": `[":foo_proto"]`, - }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + }), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`, "deps": `[":libprotobuf-cpp-lite"]`, - }), makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ - "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + "dynamic_deps": `[":libprotobuf-cpp-lite"]`, + "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`, }), }, }) @@ -2168,14 +2207,14 @@ func TestCcLibraryProtoExportHeaders(t *testing.T) { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("proto_library", "foo_proto", AttrNameToString{ + MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{ "srcs": `["foo.proto"]`, - }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ + }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ "deps": `[":foo_proto"]`, - }), makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + }), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ "deps": `[":libprotobuf-cpp-lite"]`, "whole_archive_deps": `[":foo_cc_proto_lite"]`, - }), makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "dynamic_deps": `[":libprotobuf-cpp-lite"]`, "whole_archive_deps": `[":foo_cc_proto_lite"]`, }), @@ -2183,6 +2222,179 @@ func TestCcLibraryProtoExportHeaders(t *testing.T) { }) } +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", @@ -2228,65 +2440,65 @@ cc_library { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("proto_library", "a_proto", AttrNameToString{ + MakeBazelTarget("proto_library", "a_proto", AttrNameToString{ "srcs": `[":a_fg_proto"]`, - }), makeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", AttrNameToString{ + }), MakeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", AttrNameToString{ "deps": `[":a_proto"]`, - }), makeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ + }), MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{ "deps": `[":libprotobuf-cpp-lite"]`, "whole_archive_deps": `[":a_cc_proto_lite"]`, "srcs": `[":a_fg_proto_cpp_srcs"]`, "srcs_as": `[":a_fg_proto_as_srcs"]`, "srcs_c": `[":a_fg_proto_c_srcs"]`, - }), makeBazelTarget("cc_library_shared", "a", AttrNameToString{ + }), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{ "dynamic_deps": `[":libprotobuf-cpp-lite"]`, "whole_archive_deps": `[":a_cc_proto_lite"]`, "srcs": `[":a_fg_proto_cpp_srcs"]`, "srcs_as": `[":a_fg_proto_as_srcs"]`, "srcs_c": `[":a_fg_proto_c_srcs"]`, - }), makeBazelTarget("proto_library", "b_proto", AttrNameToString{ + }), MakeBazelTarget("proto_library", "b_proto", AttrNameToString{ "srcs": `[":b_protos"]`, - }), makeBazelTarget("cc_lite_proto_library", "b_cc_proto_lite", AttrNameToString{ + }), MakeBazelTarget("cc_lite_proto_library", "b_cc_proto_lite", AttrNameToString{ "deps": `[":b_proto"]`, - }), makeBazelTarget("cc_library_static", "b_bp2build_cc_library_static", AttrNameToString{ + }), MakeBazelTarget("cc_library_static", "b_bp2build_cc_library_static", AttrNameToString{ "deps": `[":libprotobuf-cpp-lite"]`, "whole_archive_deps": `[":b_cc_proto_lite"]`, "srcs": `[":b_protos_cpp_srcs"]`, "srcs_as": `[":b_protos_as_srcs"]`, "srcs_c": `[":b_protos_c_srcs"]`, - }), makeBazelTarget("cc_library_shared", "b", AttrNameToString{ + }), MakeBazelTarget("cc_library_shared", "b", AttrNameToString{ "dynamic_deps": `[":libprotobuf-cpp-lite"]`, "whole_archive_deps": `[":b_cc_proto_lite"]`, "srcs": `[":b_protos_cpp_srcs"]`, "srcs_as": `[":b_protos_as_srcs"]`, "srcs_c": `[":b_protos_c_srcs"]`, - }), makeBazelTarget("proto_library", "c_proto", AttrNameToString{ + }), MakeBazelTarget("proto_library", "c_proto", AttrNameToString{ "srcs": `[":c-proto-srcs"]`, - }), makeBazelTarget("cc_lite_proto_library", "c_cc_proto_lite", AttrNameToString{ + }), MakeBazelTarget("cc_lite_proto_library", "c_cc_proto_lite", AttrNameToString{ "deps": `[":c_proto"]`, - }), makeBazelTarget("cc_library_static", "c_bp2build_cc_library_static", AttrNameToString{ + }), MakeBazelTarget("cc_library_static", "c_bp2build_cc_library_static", AttrNameToString{ "deps": `[":libprotobuf-cpp-lite"]`, "whole_archive_deps": `[":c_cc_proto_lite"]`, "srcs": `[":c-proto-srcs_cpp_srcs"]`, "srcs_as": `[":c-proto-srcs_as_srcs"]`, "srcs_c": `[":c-proto-srcs_c_srcs"]`, - }), makeBazelTarget("cc_library_shared", "c", AttrNameToString{ + }), MakeBazelTarget("cc_library_shared", "c", AttrNameToString{ "dynamic_deps": `[":libprotobuf-cpp-lite"]`, "whole_archive_deps": `[":c_cc_proto_lite"]`, "srcs": `[":c-proto-srcs_cpp_srcs"]`, "srcs_as": `[":c-proto-srcs_as_srcs"]`, "srcs_c": `[":c-proto-srcs_c_srcs"]`, - }), makeBazelTarget("proto_library", "d_proto", AttrNameToString{ + }), MakeBazelTarget("proto_library", "d_proto", AttrNameToString{ "srcs": `[":proto-srcs-d"]`, - }), makeBazelTarget("cc_lite_proto_library", "d_cc_proto_lite", AttrNameToString{ + }), MakeBazelTarget("cc_lite_proto_library", "d_cc_proto_lite", AttrNameToString{ "deps": `[":d_proto"]`, - }), makeBazelTarget("cc_library_static", "d_bp2build_cc_library_static", AttrNameToString{ + }), MakeBazelTarget("cc_library_static", "d_bp2build_cc_library_static", AttrNameToString{ "deps": `[":libprotobuf-cpp-lite"]`, "whole_archive_deps": `[":d_cc_proto_lite"]`, "srcs": `[":proto-srcs-d_cpp_srcs"]`, "srcs_as": `[":proto-srcs-d_as_srcs"]`, "srcs_c": `[":proto-srcs-d_c_srcs"]`, - }), makeBazelTarget("cc_library_shared", "d", AttrNameToString{ + }), MakeBazelTarget("cc_library_shared", "d", AttrNameToString{ "dynamic_deps": `[":libprotobuf-cpp-lite"]`, "whole_archive_deps": `[":d_cc_proto_lite"]`, "srcs": `[":proto-srcs-d_cpp_srcs"]`, @@ -2385,10 +2597,10 @@ func TestCcLibrarySharedDisabled(t *testing.T) { }, include_build_directory: false, }`, - ExpectedBazelTargets: []string{makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + ExpectedBazelTargets: []string{MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ "srcs": `["foo.cpp"]`, "target_compatible_with": `["@platforms//:incompatible"]`, - }), makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "srcs": `["foo.cpp"]`, "target_compatible_with": `select({ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"], @@ -2425,13 +2637,13 @@ func TestCcLibraryStaticDisabledForSomeArch(t *testing.T) { }, include_build_directory: false, }`, - ExpectedBazelTargets: []string{makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + ExpectedBazelTargets: []string{MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ "srcs": `["foo.cpp"]`, "target_compatible_with": `select({ "//build/bazel/platforms/os:windows": ["@platforms//:incompatible"], "//conditions:default": [], })`, - }), makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "srcs": `["foo.cpp"]`, "target_compatible_with": `select({ "//build/bazel/platforms/os_arch:darwin_arm64": [], @@ -2478,6 +2690,40 @@ cc_library { ) } +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", @@ -2513,14 +2759,14 @@ func TestCcLibraryConvertLex(t *testing.T) { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: append([]string{ - makeBazelTarget("genlex", "foo_lib_genlex_l", AttrNameToString{ + MakeBazelTarget("genlex", "foo_lib_genlex_l", AttrNameToString{ "srcs": `[ "foo1.l", "foo2.l", ]`, "lexopts": `["--foo_flags"]`, }), - makeBazelTarget("genlex", "foo_lib_genlex_ll", AttrNameToString{ + MakeBazelTarget("genlex", "foo_lib_genlex_ll", AttrNameToString{ "srcs": `[ "bar1.ll", "bar2.ll", @@ -2552,14 +2798,14 @@ cc_library { runtime_libs: ["foo"], }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", "bar", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "bar", AttrNameToString{ "local_includes": `["."]`, }), - makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ "runtime_deps": `[":foo"]`, "local_includes": `["."]`, }), - makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "runtime_deps": `[":foo"]`, "local_includes": `["."]`, }), @@ -2593,6 +2839,91 @@ func TestCcLibraryWithInstructionSet(t *testing.T) { }) } +func TestCcLibraryEmptySuffix(t *testing.T) { + runCcLibraryTestCase(t, Bp2buildTestCase{ + Description: "cc_library with empty suffix", + ModuleTypeUnderTest: "cc_library", + ModuleTypeUnderTestFactory: cc.LibraryFactory, + Filesystem: map[string]string{ + "foo.c": "", + }, + Blueprint: `cc_library { + name: "foo", + suffix: "", + srcs: ["foo.c"], + include_build_directory: false, +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + "srcs_c": `["foo.c"]`, + }), + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + "srcs_c": `["foo.c"]`, + "suffix": `""`, + }), + }, + }) +} + +func TestCcLibrarySuffix(t *testing.T) { + runCcLibraryTestCase(t, Bp2buildTestCase{ + Description: "cc_library with suffix", + ModuleTypeUnderTest: "cc_library", + ModuleTypeUnderTestFactory: cc.LibraryFactory, + Filesystem: map[string]string{ + "foo.c": "", + }, + Blueprint: `cc_library { + name: "foo", + suffix: "-suf", + srcs: ["foo.c"], + include_build_directory: false, +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + "srcs_c": `["foo.c"]`, + }), + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + "srcs_c": `["foo.c"]`, + "suffix": `"-suf"`, + }), + }, + }) +} + +func TestCcLibraryArchVariantSuffix(t *testing.T) { + runCcLibraryTestCase(t, Bp2buildTestCase{ + Description: "cc_library with arch-variant suffix", + ModuleTypeUnderTest: "cc_library", + ModuleTypeUnderTestFactory: cc.LibraryFactory, + Filesystem: map[string]string{ + "foo.c": "", + }, + Blueprint: `cc_library { + name: "foo", + arch: { + arm64: { suffix: "-64" }, + arm: { suffix: "-32" }, + }, + srcs: ["foo.c"], + include_build_directory: false, +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + "srcs_c": `["foo.c"]`, + }), + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + "srcs_c": `["foo.c"]`, + "suffix": `select({ + "//build/bazel/platforms/arch:arm": "-32", + "//build/bazel/platforms/arch:arm64": "-64", + "//conditions:default": None, + })`, + }), + }, + }) +} + func TestCcLibraryWithAidlSrcs(t *testing.T) { runCcLibraryTestCase(t, Bp2buildTestCase{ Description: "cc_library with aidl srcs", @@ -2616,22 +2947,22 @@ cc_library { "srcs": `["aidl/A.aidl"]`, "strip_import_prefix": `"aidl"`, }), - makeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{ + MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{ "srcs": `["B.aidl"]`, }), - makeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{ + MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{ "deps": `[ ":A_aidl", ":foo_aidl_library", ]`, }), - makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ - "whole_archive_deps": `[":foo_cc_aidl_library"]`, - "local_includes": `["."]`, + 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{ - "whole_archive_deps": `[":foo_cc_aidl_library"]`, - "local_includes": `["."]`, + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`, + "local_includes": `["."]`, }), }, }) @@ -2645,27 +2976,61 @@ func TestCcLibraryWithNonAdjacentAidlFilegroup(t *testing.T) { 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{ + 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{ + 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": `["."]`, }), - makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "whole_archive_deps": `[":foo_cc_aidl_library"]`, "local_includes": `["."]`, }), diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go index 5846f8308..5fa7cac5e 100644 --- a/bp2build/cc_library_headers_conversion_test.go +++ b/bp2build/cc_library_headers_conversion_test.go @@ -106,7 +106,7 @@ cc_library_headers { // TODO: Also support export_header_lib_headers }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ + MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ "export_includes": `[ "dir-1", "dir-2", @@ -183,7 +183,7 @@ cc_library_headers { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ + MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ "deps": `[":base-lib"] + select({ "//build/bazel/platforms/os:android": [":android-lib"], "//build/bazel/platforms/os:darwin": [":darwin-lib"], @@ -223,7 +223,7 @@ cc_library_headers { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ + MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ "deps": `select({ "//build/bazel/platforms/os:android": [":exported-lib"], "//conditions:default": [], @@ -276,7 +276,7 @@ func TestCcLibraryHeadersArchAndTargetExportSystemIncludes(t *testing.T) { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ + MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ "export_system_includes": `["shared_include_dir"] + select({ "//build/bazel/platforms/arch:arm": ["arm_include_dir"], "//build/bazel/platforms/arch:x86_64": ["x86_64_include_dir"], @@ -318,7 +318,7 @@ cc_library_headers { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_headers", "lib-1", AttrNameToString{ + MakeBazelTarget("cc_library_headers", "lib-1", AttrNameToString{ "export_includes": `["lib-1"]`, }), }, @@ -340,7 +340,7 @@ cc_library_headers { } ` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"), ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ + MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ "deps": `[":foo_export"]`, }), }, @@ -362,7 +362,7 @@ cc_library_headers { } ` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"), ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ + MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ "deps": `[":foo_export"]`, }), }, @@ -384,7 +384,7 @@ cc_library_headers { } ` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"), ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ + MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ "deps": `[":foo_export"]`, }), }, @@ -405,7 +405,7 @@ cc_library_headers { } ` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"), ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ + MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ "deps": `[":foo_export"]`, }), }, diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go index 7a44f69a2..4d8e59b30 100644 --- a/bp2build/cc_library_shared_conversion_test.go +++ b/bp2build/cc_library_shared_conversion_test.go @@ -142,7 +142,7 @@ cc_library_shared { // TODO: Also support export_header_lib_headers }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ "absolute_includes": `[ "include_dir_1", "include_dir_2", @@ -202,7 +202,7 @@ cc_library_shared { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ "implementation_dynamic_deps": `select({ "//build/bazel/platforms/arch:arm64": [":shared_dep"], "//conditions:default": [], @@ -231,7 +231,7 @@ cc_library_shared { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ "implementation_dynamic_deps": `select({ "//build/bazel/platforms/os:android": [":shared_dep"], "//conditions:default": [], @@ -266,7 +266,7 @@ cc_library_shared { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ "implementation_dynamic_deps": `[":shared_dep"] + select({ "//build/bazel/platforms/arch:arm64": [":shared_dep3"], "//conditions:default": [], @@ -295,7 +295,7 @@ cc_library_shared { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ "srcs_c": `[ "common.c", "foo-a.c", @@ -322,7 +322,7 @@ cc_library_shared { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ "strip": `{ "all": True, "keep_symbols": False, @@ -351,7 +351,7 @@ cc_library_shared { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ "additional_linker_inputs": `["version_script"]`, "linkopts": `["-Wl,--version-script,$(location version_script)"]`, }), @@ -374,7 +374,7 @@ cc_library_shared { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ "link_crt": `False`, "srcs": `["impl.cpp"]`, }), @@ -397,7 +397,7 @@ cc_library_shared { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ "srcs": `["impl.cpp"]`, }), }, @@ -440,11 +440,11 @@ func TestCcLibrarySharedProto(t *testing.T) { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("proto_library", "foo_proto", AttrNameToString{ + MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{ "srcs": `["foo.proto"]`, - }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ + }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ "deps": `[":foo_proto"]`, - }), makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "dynamic_deps": `[":libprotobuf-cpp-lite"]`, "whole_archive_deps": `[":foo_cc_proto_lite"]`, }), @@ -460,7 +460,7 @@ func TestCcLibrarySharedUseVersionLib(t *testing.T) { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "use_version_lib": "True", }), }, @@ -484,7 +484,7 @@ cc_library_shared { `, }, Blueprint: soongCcLibraryPreamble, - ExpectedBazelTargets: []string{makeBazelTarget("cc_library_shared", "a", AttrNameToString{ + ExpectedBazelTargets: []string{MakeBazelTarget("cc_library_shared", "a", AttrNameToString{ "has_stubs": `True`, }), }, @@ -510,7 +510,7 @@ cc_library_shared { defaults: ["empty_defaults"], } `, - ExpectedBazelTargets: []string{makeBazelTarget("cc_library_shared", "empty", AttrNameToString{ + ExpectedBazelTargets: []string{MakeBazelTarget("cc_library_shared", "empty", AttrNameToString{ "system_dynamic_deps": "[]", })}, }) @@ -537,21 +537,21 @@ func TestCcLibrarySharedConvertLex(t *testing.T) { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("genlex", "foo_lib_genlex_l", AttrNameToString{ + MakeBazelTarget("genlex", "foo_lib_genlex_l", AttrNameToString{ "srcs": `[ "foo1.l", "foo2.l", ]`, "lexopts": `["--foo_flags"]`, }), - makeBazelTarget("genlex", "foo_lib_genlex_ll", AttrNameToString{ + MakeBazelTarget("genlex", "foo_lib_genlex_ll", AttrNameToString{ "srcs": `[ "bar1.ll", "bar2.ll", ]`, "lexopts": `["--foo_flags"]`, }), - makeBazelTarget("cc_library_shared", "foo_lib", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo_lib", AttrNameToString{ "srcs": `[ "bar.cc", ":foo_lib_genlex_ll", @@ -576,7 +576,7 @@ func TestCcLibrarySharedClangUnknownFlags(t *testing.T) { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "conlyflags": `["-a"]`, "copts": `["-b"]`, "cppflags": `["-c"]`, @@ -600,7 +600,7 @@ func TestCCLibraryFlagSpaceSplitting(t *testing.T) { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "additional_linker_inputs": `["version_script"]`, "conlyflags": `[ "-include", @@ -631,13 +631,86 @@ cc_library_shared { runtime_libs: ["foo"], }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", "bar", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "bar", AttrNameToString{ "local_includes": `["."]`, }), - makeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "runtime_deps": `[":foo"]`, "local_includes": `["."]`, }), }, }) } + +func TestCcLibrarySharedEmptySuffix(t *testing.T) { + runCcLibrarySharedTestCase(t, Bp2buildTestCase{ + Description: "cc_library_shared with empty suffix", + Filesystem: map[string]string{ + "foo.c": "", + }, + Blueprint: soongCcLibrarySharedPreamble + ` +cc_library_shared { + name: "foo_shared", + suffix: "", + srcs: ["foo.c"], + include_build_directory: false, +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ + "srcs_c": `["foo.c"]`, + "suffix": `""`, + }), + }, + }) +} + +func TestCcLibrarySharedSuffix(t *testing.T) { + runCcLibrarySharedTestCase(t, Bp2buildTestCase{ + Description: "cc_library_shared with suffix", + Filesystem: map[string]string{ + "foo.c": "", + }, + Blueprint: soongCcLibrarySharedPreamble + ` +cc_library_shared { + name: "foo_shared", + suffix: "-suf", + srcs: ["foo.c"], + include_build_directory: false, +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ + "srcs_c": `["foo.c"]`, + "suffix": `"-suf"`, + }), + }, + }) +} + +func TestCcLibrarySharedArchVariantSuffix(t *testing.T) { + runCcLibrarySharedTestCase(t, Bp2buildTestCase{ + Description: "cc_library_shared with arch-variant suffix", + Filesystem: map[string]string{ + "foo.c": "", + }, + Blueprint: soongCcLibrarySharedPreamble + ` +cc_library_shared { + name: "foo_shared", + arch: { + arm64: { suffix: "-64" }, + arm: { suffix: "-32" }, + }, + srcs: ["foo.c"], + include_build_directory: false, +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{ + "srcs_c": `["foo.c"]`, + "suffix": `select({ + "//build/bazel/platforms/arch:arm": "-32", + "//build/bazel/platforms/arch:arm64": "-64", + "//conditions:default": None, + })`, + }), + }, + }) +} diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go index 1c160ec6a..316fa3e4c 100644 --- a/bp2build/cc_library_static_conversion_test.go +++ b/bp2build/cc_library_static_conversion_test.go @@ -173,7 +173,7 @@ cc_library_static { // TODO: Also support export_header_lib_headers }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "absolute_includes": `[ "include_dir_1", "include_dir_2", @@ -238,7 +238,7 @@ cc_library_static { ], }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "absolute_includes": `["subpackage"]`, "local_includes": `["."]`, }), @@ -262,7 +262,7 @@ cc_library_static { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "export_includes": `["subpackage"]`, }), }, @@ -285,7 +285,7 @@ cc_library_static { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "export_system_includes": `["subpackage"]`, }), }, @@ -320,7 +320,7 @@ cc_library_static { }, Blueprint: soongCcLibraryStaticPreamble, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "absolute_includes": `[ "subpackage/subsubpackage", "subpackage2", @@ -352,7 +352,7 @@ cc_library_static { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "absolute_includes": `["subpackage"]`, "local_includes": `["subpackage2"]`, }), @@ -379,7 +379,7 @@ cc_library_static { include_build_directory: true, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "absolute_includes": `["subpackage"]`, "local_includes": `[ "subpackage2", @@ -409,7 +409,7 @@ cc_library_static { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "implementation_deps": `select({ "//build/bazel/platforms/arch:arm64": [":static_dep"], "//conditions:default": [], @@ -442,7 +442,7 @@ cc_library_static { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "implementation_deps": `select({ "//build/bazel/platforms/os:android": [":static_dep"], "//conditions:default": [], @@ -486,7 +486,7 @@ cc_library_static { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "implementation_deps": `[":static_dep"] + select({ "//build/bazel/platforms/arch:arm64": [":static_dep4"], "//conditions:default": [], @@ -516,7 +516,7 @@ cc_library_static { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "srcs_c": `[ "common.c", "foo-a.c", @@ -541,7 +541,7 @@ cc_library_static { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "srcs_c": `["common.c"] + select({ "//build/bazel/platforms/arch:arm": ["foo-arm.c"], "//conditions:default": [], @@ -571,7 +571,7 @@ cc_library_static { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "srcs_c": `["common.c"] + select({ "//build/bazel/platforms/arch:arm": ["for-arm.c"], "//conditions:default": ["not-for-arm.c"], @@ -603,7 +603,7 @@ cc_library_static { include_build_directory: false, } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "srcs_c": `["common.c"] + select({ "//build/bazel/platforms/arch:arm": [ "not-for-x86.c", @@ -652,7 +652,7 @@ cc_library_static { include_build_directory: false, } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "srcs_c": `["common.c"] + select({ "//build/bazel/platforms/arch:arm": [ "not-for-arm64.c", @@ -709,7 +709,7 @@ cc_library_static { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "srcs": `["common.cc"] + select({ "//build/bazel/platforms/arch:arm": [], "//conditions:default": ["foo-no-arm.cc"], @@ -740,7 +740,7 @@ cc_library_static { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "srcs": `["common.cc"] + select({ "//build/bazel/platforms/arch:arm": [], "//build/bazel/platforms/arch:x86": [ @@ -769,7 +769,7 @@ cc_library_static { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "implementation_deps": `[":static_dep"]`, }), }, @@ -794,7 +794,7 @@ cc_library_static { include_build_directory: false, } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "srcs_c": `["common.c"] + select({ "//build/bazel/platforms/arch:arm": ["for-lib32.c"], "//build/bazel/platforms/arch:x86": ["for-lib32.c"], @@ -826,7 +826,7 @@ cc_library_static { include_build_directory: false, } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "srcs_c": `["common.c"] + select({ "//build/bazel/platforms/arch:arm": [ "not-for-lib64.c", @@ -891,7 +891,7 @@ cc_library_static { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "srcs_c": `["common.c"] + select({ "//build/bazel/platforms/arch:arm": [ "not-for-arm64.c", @@ -962,7 +962,7 @@ cc_library_static { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "export_includes": `["."]`, "local_includes": `["."]`, "hdrs": `[":export_generated_hdr"]`, @@ -1030,7 +1030,7 @@ cc_library_static { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "srcs": `[ "common.cpp", ":generated_src", @@ -1093,7 +1093,7 @@ cc_library_static { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "srcs_c": `select({ "//build/bazel/platforms/os:android": ["android_src.c"], "//conditions:default": [], @@ -1132,7 +1132,7 @@ cc_library_static { include_build_directory: false, } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "copts": `select({ "//build/bazel/product_variables:binder32bit": ["-Wbinder32bit"], "//conditions:default": [], @@ -1192,7 +1192,7 @@ cc_library_static { include_build_directory: false, } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "copts": `select({ "//build/bazel/product_variables:malloc_not_svelte": ["-Wmalloc_not_svelte"], "//conditions:default": [], @@ -1231,7 +1231,7 @@ cc_library_static { include_build_directory: false, } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{ "asflags": `select({ "//build/bazel/product_variables:platform_sdk_version": ["-DPLATFORM_SDK_VERSION=$(Platform_sdk_version)"], "//conditions:default": [], @@ -1253,7 +1253,7 @@ cc_library_static { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "root_empty", AttrNameToString{ + MakeBazelTarget("cc_library_static", "root_empty", AttrNameToString{ "system_dynamic_deps": `[]`, }), }, @@ -1277,7 +1277,7 @@ cc_library_static { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "static_empty", AttrNameToString{ + MakeBazelTarget("cc_library_static", "static_empty", AttrNameToString{ "system_dynamic_deps": `[]`, }), }, @@ -1299,7 +1299,7 @@ cc_library_static { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "target_bionic_empty", AttrNameToString{ + MakeBazelTarget("cc_library_static", "target_bionic_empty", AttrNameToString{ "system_dynamic_deps": `[]`, }), }, @@ -1325,7 +1325,7 @@ cc_library_static { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "target_linux_bionic_empty", AttrNameToString{ + MakeBazelTarget("cc_library_static", "target_linux_bionic_empty", AttrNameToString{ "system_dynamic_deps": `[]`, }), }, @@ -1348,7 +1348,7 @@ cc_library_static { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "target_bionic", AttrNameToString{ + MakeBazelTarget("cc_library_static", "target_bionic", AttrNameToString{ "system_dynamic_deps": `select({ "//build/bazel/platforms/os:android": [":libc"], "//build/bazel/platforms/os:linux_bionic": [":libc"], @@ -1377,7 +1377,7 @@ cc_library_static { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "target_linux_bionic", AttrNameToString{ + MakeBazelTarget("cc_library_static", "target_linux_bionic", AttrNameToString{ "system_dynamic_deps": `[":libc"] + select({ "//build/bazel/platforms/os:linux_bionic": [":libm"], "//conditions:default": [], @@ -1392,6 +1392,16 @@ func TestCcLibrarystatic_SystemSharedLibUsedAsDep(t *testing.T) { 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,23 +1424,38 @@ cc_library_static { 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, } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "all", AttrNameToString{ - "implementation_dynamic_deps": `select({ - "//build/bazel/platforms/os:android": [], - "//build/bazel/platforms/os:linux_bionic": [], - "//conditions:default": [":libc"], - })`, - }), - makeBazelTarget("cc_library_static", "keep_for_empty_system_shared_libs", AttrNameToString{ + MakeBazelTarget("cc_library_static", "all", AttrNameToString{}), + MakeBazelTarget("cc_library_static", "keep_for_empty_system_shared_libs", AttrNameToString{ "implementation_dynamic_deps": `[":libc"]`, "system_dynamic_deps": `[]`, }), - makeBazelTarget("cc_library_static", "used_in_bionic_oses", AttrNameToString{}), + 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{}), }, }) } @@ -1446,11 +1471,11 @@ func TestCcLibraryStaticProto(t *testing.T) { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("proto_library", "foo_proto", AttrNameToString{ + MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{ "srcs": `["foo.proto"]`, - }), makeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ + }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ "deps": `[":foo_proto"]`, - }), makeBazelTarget("cc_library_static", "foo", AttrNameToString{ + }), MakeBazelTarget("cc_library_static", "foo", AttrNameToString{ "deps": `[":libprotobuf-cpp-lite"]`, "whole_archive_deps": `[":foo_cc_proto_lite"]`, }), @@ -1466,7 +1491,7 @@ func TestCcLibraryStaticUseVersionLib(t *testing.T) { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo", AttrNameToString{ "use_version_lib": "True", }), }, @@ -1483,7 +1508,7 @@ func TestCcLibraryStaticStdInFlags(t *testing.T) { include_build_directory: false, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo", AttrNameToString{ "conlyflags": `["-std=conly"]`, "cppflags": `["-std=cpp"]`, }), @@ -1553,7 +1578,7 @@ func TestCcLibraryStaticStl(t *testing.T) { %s }`, tc.prop), ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo", tc.attr), + MakeBazelTarget("cc_library_static", "foo", tc.attr), }, }) }) @@ -1571,10 +1596,10 @@ cc_library_static { runtime_libs: ["foo"], }`, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_shared", "bar", AttrNameToString{ + MakeBazelTarget("cc_library_shared", "bar", AttrNameToString{ "local_includes": `["."]`, }), - makeBazelTarget("cc_library_static", "foo", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo", AttrNameToString{ "runtime_deps": `[":foo"]`, "local_includes": `["."]`, }), diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go index 37d55809a..b8dc690d5 100644 --- a/bp2build/cc_object_conversion_test.go +++ b/bp2build/cc_object_conversion_test.go @@ -60,7 +60,7 @@ func TestCcObjectSimple(t *testing.T) { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_object", "foo", AttrNameToString{ + MakeBazelTarget("cc_object", "foo", AttrNameToString{ "copts": `[ "-fno-addrsig", "-Wno-gcc-compat", @@ -106,7 +106,7 @@ cc_defaults { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_object", "foo", AttrNameToString{ + MakeBazelTarget("cc_object", "foo", AttrNameToString{ "copts": `[ "-Werror", "-fno-addrsig", @@ -141,11 +141,11 @@ cc_object { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_object", "bar", AttrNameToString{ + MakeBazelTarget("cc_object", "bar", AttrNameToString{ "copts": `["-fno-addrsig"]`, "srcs": `["x/y/z.c"]`, "system_dynamic_deps": `[]`, - }), makeBazelTarget("cc_object", "foo", AttrNameToString{ + }), MakeBazelTarget("cc_object", "foo", AttrNameToString{ "copts": `["-fno-addrsig"]`, "deps": `[":bar"]`, "srcs": `["a/b/c.c"]`, @@ -170,7 +170,7 @@ func TestCcObjectIncludeBuildDirFalse(t *testing.T) { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_object", "foo", AttrNameToString{ + MakeBazelTarget("cc_object", "foo", AttrNameToString{ "copts": `["-fno-addrsig"]`, "srcs": `["a/b/c.c"]`, "system_dynamic_deps": `[]`, @@ -195,7 +195,7 @@ func TestCcObjectProductVariable(t *testing.T) { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_object", "foo", AttrNameToString{ + MakeBazelTarget("cc_object", "foo", AttrNameToString{ "asflags": `select({ "//build/bazel/product_variables:platform_sdk_version": ["-DPLATFORM_SDK_VERSION=$(Platform_sdk_version)"], "//conditions:default": [], @@ -227,7 +227,7 @@ func TestCcObjectCflagsOneArch(t *testing.T) { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_object", "foo", AttrNameToString{ + MakeBazelTarget("cc_object", "foo", AttrNameToString{ "copts": `["-fno-addrsig"] + select({ "//build/bazel/platforms/arch:x86": ["-fPIC"], "//conditions:default": [], @@ -271,7 +271,7 @@ func TestCcObjectCflagsFourArch(t *testing.T) { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_object", "foo", AttrNameToString{ + MakeBazelTarget("cc_object", "foo", AttrNameToString{ "copts": `["-fno-addrsig"] + select({ "//build/bazel/platforms/arch:arm": ["-Wall"], "//build/bazel/platforms/arch:arm64": ["-Wall"], @@ -303,7 +303,7 @@ func TestCcObjectLinkerScript(t *testing.T) { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_object", "foo", AttrNameToString{ + MakeBazelTarget("cc_object", "foo", AttrNameToString{ "copts": `["-fno-addrsig"]`, "linker_script": `"bunny.lds"`, "srcs": `["base.cpp"]`, @@ -360,7 +360,7 @@ cc_object { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_object", "foo", AttrNameToString{ + MakeBazelTarget("cc_object", "foo", AttrNameToString{ "copts": `["-fno-addrsig"]`, "deps": `select({ "//build/bazel/platforms/arch:arm": [":arm_obj"], @@ -401,7 +401,7 @@ func TestCcObjectSelectOnLinuxAndBionicArchs(t *testing.T) { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_object", "foo", AttrNameToString{ + MakeBazelTarget("cc_object", "foo", AttrNameToString{ "copts": `["-fno-addrsig"]`, "srcs": `["base.cpp"] + select({ "//build/bazel/platforms/os_arch:android_arm64": [ diff --git a/bp2build/cc_prebuilt_library_conversion_test.go b/bp2build/cc_prebuilt_library_conversion_test.go index 32c3f4d9b..dd217c343 100644 --- a/bp2build/cc_prebuilt_library_conversion_test.go +++ b/bp2build/cc_prebuilt_library_conversion_test.go @@ -21,7 +21,7 @@ import ( ) func TestPrebuiltLibraryStaticAndSharedSimple(t *testing.T) { - runBp2BuildTestCaseSimple(t, + RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{ Description: "prebuilt library static and shared simple", ModuleTypeUnderTest: "cc_prebuilt_library", @@ -36,10 +36,10 @@ cc_prebuilt_library { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{ + MakeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{ "static_library": `"libf.so"`, }), - makeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{ + MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{ "shared_library": `"libf.so"`, }), }, @@ -47,7 +47,7 @@ cc_prebuilt_library { } func TestPrebuiltLibraryWithArchVariance(t *testing.T) { - runBp2BuildTestCaseSimple(t, + RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{ Description: "prebuilt library with arch variance", ModuleTypeUnderTest: "cc_prebuilt_library", @@ -66,14 +66,14 @@ cc_prebuilt_library { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{ + MakeBazelTarget("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("prebuilt_library_shared", "libtest", AttrNameToString{ "shared_library": `select({ "//build/bazel/platforms/arch:arm": "libg.so", "//build/bazel/platforms/arch:arm64": "libf.so", @@ -85,7 +85,7 @@ cc_prebuilt_library { } func TestPrebuiltLibraryAdditionalAttrs(t *testing.T) { - runBp2BuildTestCaseSimple(t, + RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{ Description: "prebuilt library additional attributes", ModuleTypeUnderTest: "cc_prebuilt_library", @@ -104,13 +104,13 @@ cc_prebuilt_library { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{ + MakeBazelTarget("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("prebuilt_library_shared", "libtest", AttrNameToString{ "shared_library": `"libf.so"`, }), }, @@ -118,7 +118,7 @@ cc_prebuilt_library { } func TestPrebuiltLibrarySharedStanzaFails(t *testing.T) { - runBp2BuildTestCaseSimple(t, + RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{ Description: "prebuilt library with shared stanza fails because multiple sources", ModuleTypeUnderTest: "cc_prebuilt_library", @@ -141,7 +141,7 @@ cc_prebuilt_library { } func TestPrebuiltLibraryStaticStanzaFails(t *testing.T) { - runBp2BuildTestCaseSimple(t, + RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{ Description: "prebuilt library with static stanza fails because multiple sources", ModuleTypeUnderTest: "cc_prebuilt_library", @@ -164,7 +164,7 @@ cc_prebuilt_library { } func TestPrebuiltLibrarySharedAndStaticStanzas(t *testing.T) { - runBp2BuildTestCaseSimple(t, + RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{ Description: "prebuilt library with both shared and static stanzas", ModuleTypeUnderTest: "cc_prebuilt_library", @@ -185,10 +185,10 @@ cc_prebuilt_library { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{ + MakeBazelTarget("prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{ "static_library": `"libf.so"`, }), - makeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{ + MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{ "shared_library": `"libg.so"`, }), }, @@ -197,7 +197,7 @@ cc_prebuilt_library { // TODO(b/228623543): When this bug is fixed, enable this test //func TestPrebuiltLibraryOnlyShared(t *testing.T) { -// runBp2BuildTestCaseSimple(t, +// RunBp2BuildTestCaseSimple(t, // bp2buildTestCase{ // description: "prebuilt library shared only", // moduleTypeUnderTest: "cc_prebuilt_library", @@ -224,7 +224,7 @@ cc_prebuilt_library { // TODO(b/228623543): When this bug is fixed, enable this test //func TestPrebuiltLibraryOnlyStatic(t *testing.T) { -// runBp2BuildTestCaseSimple(t, +// RunBp2BuildTestCaseSimple(t, // bp2buildTestCase{ // description: "prebuilt library static only", // moduleTypeUnderTest: "cc_prebuilt_library", diff --git a/bp2build/cc_prebuilt_library_shared_test.go b/bp2build/cc_prebuilt_library_shared_test.go index bcf0ce20a..541ce5e5a 100644 --- a/bp2build/cc_prebuilt_library_shared_test.go +++ b/bp2build/cc_prebuilt_library_shared_test.go @@ -8,7 +8,7 @@ import ( ) func TestSharedPrebuiltLibrary(t *testing.T) { - runBp2BuildTestCaseSimple(t, + RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{ Description: "prebuilt library shared simple", ModuleTypeUnderTest: "cc_prebuilt_library_shared", @@ -23,7 +23,7 @@ cc_prebuilt_library_shared { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{ + MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{ "shared_library": `"libf.so"`, }), }, @@ -31,7 +31,7 @@ cc_prebuilt_library_shared { } func TestSharedPrebuiltLibraryWithArchVariance(t *testing.T) { - runBp2BuildTestCaseSimple(t, + RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{ Description: "prebuilt library shared with arch variance", ModuleTypeUnderTest: "cc_prebuilt_library_shared", @@ -50,7 +50,7 @@ cc_prebuilt_library_shared { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{ + MakeBazelTarget("prebuilt_library_shared", "libtest", AttrNameToString{ "shared_library": `select({ "//build/bazel/platforms/arch:arm": "libg.so", "//build/bazel/platforms/arch:arm64": "libf.so", @@ -62,7 +62,7 @@ cc_prebuilt_library_shared { } func TestSharedPrebuiltLibrarySharedStanzaFails(t *testing.T) { - runBp2BuildTestCaseSimple(t, + RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{ Description: "prebuilt library shared with shared stanza fails because multiple sources", ModuleTypeUnderTest: "cc_prebuilt_library_shared", diff --git a/bp2build/cc_prebuilt_library_static_test.go b/bp2build/cc_prebuilt_library_static_test.go index 489a53d75..69a1b5eb3 100644 --- a/bp2build/cc_prebuilt_library_static_test.go +++ b/bp2build/cc_prebuilt_library_static_test.go @@ -21,7 +21,7 @@ import ( ) func TestStaticPrebuiltLibrary(t *testing.T) { - runBp2BuildTestCaseSimple(t, + RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{ Description: "prebuilt library static simple", ModuleTypeUnderTest: "cc_prebuilt_library_static", @@ -36,7 +36,7 @@ cc_prebuilt_library_static { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("prebuilt_library_static", "libtest", AttrNameToString{ + MakeBazelTarget("prebuilt_library_static", "libtest", AttrNameToString{ "static_library": `"libf.so"`, }), }, @@ -44,7 +44,7 @@ cc_prebuilt_library_static { } func TestStaticPrebuiltLibraryWithArchVariance(t *testing.T) { - runBp2BuildTestCaseSimple(t, + RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{ Description: "prebuilt library static with arch variance", ModuleTypeUnderTest: "cc_prebuilt_library_static", @@ -63,7 +63,7 @@ cc_prebuilt_library_static { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("prebuilt_library_static", "libtest", AttrNameToString{ + MakeBazelTarget("prebuilt_library_static", "libtest", AttrNameToString{ "static_library": `select({ "//build/bazel/platforms/arch:arm": "libg.so", "//build/bazel/platforms/arch:arm64": "libf.so", @@ -75,7 +75,7 @@ cc_prebuilt_library_static { } func TestStaticPrebuiltLibraryStaticStanzaFails(t *testing.T) { - runBp2BuildTestCaseSimple(t, + RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{ Description: "prebuilt library with static stanza fails because multiple sources", ModuleTypeUnderTest: "cc_prebuilt_library_static", @@ -118,21 +118,21 @@ func TestCcLibraryStaticConvertLex(t *testing.T) { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("genlex", "foo_lib_genlex_l", AttrNameToString{ + MakeBazelTarget("genlex", "foo_lib_genlex_l", AttrNameToString{ "srcs": `[ "foo1.l", "foo2.l", ]`, "lexopts": `["--foo_flags"]`, }), - makeBazelTarget("genlex", "foo_lib_genlex_ll", AttrNameToString{ + MakeBazelTarget("genlex", "foo_lib_genlex_ll", AttrNameToString{ "srcs": `[ "bar1.ll", "bar2.ll", ]`, "lexopts": `["--foo_flags"]`, }), - makeBazelTarget("cc_library_static", "foo_lib", AttrNameToString{ + MakeBazelTarget("cc_library_static", "foo_lib", AttrNameToString{ "srcs": `[ "bar.cc", ":foo_lib_genlex_ll", diff --git a/bp2build/cc_test_conversion_test.go b/bp2build/cc_test_conversion_test.go new file mode 100644 index 000000000..9b7748f10 --- /dev/null +++ b/bp2build/cc_test_conversion_test.go @@ -0,0 +1,150 @@ +// 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/android" + "android/soong/cc" + "android/soong/genrule" +) + +type ccTestBp2buildTestCase struct { + description string + blueprint string + targets []testBazelTarget +} + +func registerCcTestModuleTypes(ctx android.RegistrationContext) { + cc.RegisterCCBuildComponents(ctx) + ctx.RegisterModuleType("cc_binary", cc.BinaryFactory) + ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory) + ctx.RegisterModuleType("cc_library", cc.LibraryFactory) + ctx.RegisterModuleType("cc_test_library", cc.TestLibraryFactory) + ctx.RegisterModuleType("genrule", genrule.GenRuleFactory) +} + +func runCcTestTestCase(t *testing.T, testCase ccTestBp2buildTestCase) { + t.Helper() + moduleTypeUnderTest := "cc_test" + + description := fmt.Sprintf("%s %s", moduleTypeUnderTest, testCase.description) + t.Run(description, func(t *testing.T) { + t.Helper() + RunBp2BuildTestCase(t, registerCcTestModuleTypes, Bp2buildTestCase{ + ExpectedBazelTargets: generateBazelTargetsForTest(testCase.targets, android.HostAndDeviceSupported), + ModuleTypeUnderTest: moduleTypeUnderTest, + ModuleTypeUnderTestFactory: cc.TestFactory, + Description: description, + Blueprint: testCase.blueprint, + }) + }) +} + +func TestBasicCcTest(t *testing.T) { + runCcTestTestCase(t, ccTestBp2buildTestCase{ + description: "basic cc_test with commonly used attributes", + blueprint: ` +cc_test { + name: "mytest", + host_supported: true, + srcs: ["test.cpp"], + target: { + android: { + srcs: ["android.cpp"], + shared_libs: ["foolib"], + }, + linux: { + srcs: ["linux.cpp"], + }, + host: { + static_libs: ["hostlib"], + }, + }, + data: [":data_mod", "file.txt"], + data_bins: [":cc_bin"], + data_libs: [":cc_lib"], + cflags: ["-Wall"], +} +` + simpleModuleDoNotConvertBp2build("cc_library", "foolib") + + simpleModuleDoNotConvertBp2build("cc_library_static", "hostlib") + + simpleModuleDoNotConvertBp2build("genrule", "data_mod") + + simpleModuleDoNotConvertBp2build("cc_binary", "cc_bin") + + simpleModuleDoNotConvertBp2build("cc_test_library", "cc_lib"), + targets: []testBazelTarget{ + {"cc_test", "mytest", AttrNameToString{ + "copts": `["-Wall"]`, + "data": `[ + ":data_mod", + "file.txt", + ":cc_bin", + ":cc_lib", + ]`, + "deps": `select({ + "//build/bazel/platforms/os:darwin": [":hostlib"], + "//build/bazel/platforms/os:linux": [":hostlib"], + "//build/bazel/platforms/os:linux_bionic": [":hostlib"], + "//build/bazel/platforms/os:linux_musl": [":hostlib"], + "//build/bazel/platforms/os:windows": [":hostlib"], + "//conditions:default": [], + })`, + "gtest": "True", + "isolated": "True", + "local_includes": `["."]`, + "dynamic_deps": `select({ + "//build/bazel/platforms/os:android": [":foolib"], + "//conditions:default": [], + })`, + "srcs": `["test.cpp"] + select({ + "//build/bazel/platforms/os:android": [ + "linux.cpp", + "android.cpp", + ], + "//build/bazel/platforms/os:linux": ["linux.cpp"], + "//build/bazel/platforms/os:linux_bionic": ["linux.cpp"], + "//build/bazel/platforms/os:linux_musl": ["linux.cpp"], + "//conditions:default": [], + })`, + }, + }, + }, + }) +} + +func TestBasicCcTestGtestIsolatedDisabled(t *testing.T) { + runCcTestTestCase(t, ccTestBp2buildTestCase{ + description: "cc test with disabled gtest and isolated props", + blueprint: ` +cc_test { + name: "mytest", + host_supported: true, + srcs: ["test.cpp"], + gtest: false, + isolated: false, +} +`, + targets: []testBazelTarget{ + {"cc_test", "mytest", AttrNameToString{ + "gtest": "False", + "isolated": "False", + "local_includes": `["."]`, + "srcs": `["test.cpp"]`, + }, + }, + }, + }) +} diff --git a/bp2build/cc_yasm_conversion_test.go b/bp2build/cc_yasm_conversion_test.go index 2a7183499..55d4febf9 100644 --- a/bp2build/cc_yasm_conversion_test.go +++ b/bp2build/cc_yasm_conversion_test.go @@ -48,7 +48,7 @@ cc_library { srcs: ["main.cpp", "myfile.asm"], }`, ExpectedBazelTargets: append([]string{ - makeBazelTarget("yasm", "foo_yasm", map[string]string{ + MakeBazelTarget("yasm", "foo_yasm", map[string]string{ "include_dirs": `["."]`, "srcs": `["myfile.asm"]`, }), @@ -81,7 +81,7 @@ cc_library { srcs: ["main.cpp", "myfile.asm"], }`, ExpectedBazelTargets: append([]string{ - makeBazelTarget("yasm", "foo_yasm", map[string]string{ + MakeBazelTarget("yasm", "foo_yasm", map[string]string{ "include_dirs": `[ "include1/foo", ".", @@ -123,7 +123,7 @@ cc_library { }, }`, ExpectedBazelTargets: append([]string{ - makeBazelTarget("yasm", "foo_yasm", map[string]string{ + MakeBazelTarget("yasm", "foo_yasm", map[string]string{ "include_dirs": `["."]`, "srcs": `select({ "//build/bazel/platforms/arch:x86": ["myfile.asm"], @@ -161,7 +161,7 @@ cc_library { }, }`, ExpectedBazelTargets: append([]string{ - makeBazelTarget("yasm", "foo_yasm", map[string]string{ + MakeBazelTarget("yasm", "foo_yasm", map[string]string{ "include_dirs": `["."]`, "srcs": `["myfile.asm"] + select({ "//build/bazel/platforms/arch:x86": ["mysecondfile.asm"], diff --git a/bp2build/conversion.go b/bp2build/conversion.go index 8cf9beaf4..b6190c695 100644 --- a/bp2build/conversion.go +++ b/bp2build/conversion.go @@ -2,7 +2,6 @@ package bp2build import ( "encoding/json" - "fmt" "reflect" "strings" @@ -80,21 +79,14 @@ func CreateBazelFiles( files = append(files, newFile(bazelRulesSubDir, "soong_module.bzl", generateSoongModuleBzl(ruleShims))) } - files = append(files, createBuildFiles(cfg, buildToTargets, mode)...) + files = append(files, createBuildFiles(buildToTargets, mode)...) return files } -func createBuildFiles(cfg android.Config, buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile { +func createBuildFiles(buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile { files := make([]BazelFile, 0, len(buildToTargets)) - warnNotWriting := cfg.IsEnvTrue("BP2BUILD_VERBOSE") for _, dir := range android.SortedStringKeys(buildToTargets) { - if mode == Bp2Build && android.ShouldKeepExistingBuildFileForDir(dir) { - if warnNotWriting { - fmt.Printf("[bp2build] Not writing generated BUILD file for dir: '%s'\n", dir) - } - continue - } targets := buildToTargets[dir] targets.sort() @@ -104,18 +96,14 @@ func createBuildFiles(cfg android.Config, buildToTargets map[string]BazelTargets # 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. ` - if targets.hasHandcraftedTargets() { - // For BUILD files with both handcrafted and generated targets, - // don't hardcode actual content, like package() declarations. - // Leave that responsibility to the checked-in BUILD file - // instead. - content += `# This file contains generated targets and handcrafted targets that are manually managed in the source tree.` - } else { - // For fully-generated BUILD files, hardcode the default visibility. - content += "package(default_visibility = [\"//visibility:public\"])" - } - content += "\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 } @@ -152,16 +140,17 @@ const ( 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 } ) @@ -175,7 +164,7 @@ func shouldSkipStructField(field reflect.StructField) bool { // 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/filegroup_conversion_test.go b/bp2build/filegroup_conversion_test.go index de09a1787..e978fb319 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 @@ filegroup { ]`}), }}) } + +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/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go index 50ea542b7..86f3d423b 100644 --- a/bp2build/java_binary_host_conversion_test.go +++ b/bp2build/java_binary_host_conversion_test.go @@ -55,7 +55,7 @@ func TestJavaBinaryHost(t *testing.T) { java_version: "8", }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_binary", "java-binary-host-1", AttrNameToString{ + MakeBazelTarget("java_binary", "java-binary-host-1", AttrNameToString{ "srcs": `["a.java"]`, "main_class": `"com.android.test.MainClass"`, "deps": `["//other:jni-lib-1"]`, @@ -91,7 +91,7 @@ java_library { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("java_binary", "java-binary-host-1", AttrNameToString{ + MakeBazelTarget("java_binary", "java-binary-host-1", AttrNameToString{ "main_class": `"com.android.test.MainClass"`, "runtime_deps": `[":java-dep-1"]`, "target_compatible_with": `select({ diff --git a/bp2build/java_import_conversion_test.go b/bp2build/java_import_conversion_test.go index 707ecce91..05d714240 100644 --- a/bp2build/java_import_conversion_test.go +++ b/bp2build/java_import_conversion_test.go @@ -45,7 +45,7 @@ java_import { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("java_import", "example_import", AttrNameToString{ + MakeBazelTarget("java_import", "example_import", AttrNameToString{ "jars": `["import.jar"]`, }), }}) @@ -74,7 +74,7 @@ java_import { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("java_import", "example_import", AttrNameToString{ + MakeBazelTarget("java_import", "example_import", AttrNameToString{ "jars": `select({ "//build/bazel/platforms/os:android": ["android.jar"], "//build/bazel/platforms/os:linux": ["linux.jar"], diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go index f5a59382c..74e2dbd09 100644 --- a/bp2build/java_library_conversion_test.go +++ b/bp2build/java_library_conversion_test.go @@ -51,11 +51,11 @@ java_library { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_library", "java-lib-1", AttrNameToString{ + MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ "srcs": `["a.java"]`, "deps": `[":java-lib-2"]`, }), - makeBazelTarget("java_library", "java-lib-2", AttrNameToString{ + MakeBazelTarget("java_library", "java-lib-2", AttrNameToString{ "srcs": `["b.java"]`, }), }, @@ -84,7 +84,7 @@ java_library { bazel_module: { bp2build_available: false }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_library", "java-lib-1", AttrNameToString{ + MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ "srcs": `["a.java"]`, "deps": `[ ":java-lib-2", @@ -110,7 +110,7 @@ java_library { bazel_module: { bp2build_available: false }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_library", "java-lib-1", AttrNameToString{ + MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ "exports": `[":java-lib-2"]`, }), }, @@ -149,7 +149,7 @@ java_plugin { bazel_module: { bp2build_available: false }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_library", "java-lib-1", AttrNameToString{ + MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ "plugins": `[":java-plugin-1"]`, }), }, @@ -166,7 +166,7 @@ func TestJavaLibraryJavaVersion(t *testing.T) { java_version: "11", }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_library", "java-lib-1", AttrNameToString{ + MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ "srcs": `["a.java"]`, "javacopts": `["-source 11 -target 11"]`, }), @@ -186,7 +186,7 @@ func TestJavaLibraryErrorproneJavacflagsEnabledManually(t *testing.T) { }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_library", "java-lib-1", AttrNameToString{ + MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ "javacopts": `[ "-Xsuper-fast", "-Xep:SpeedLimit:OFF", @@ -208,7 +208,7 @@ func TestJavaLibraryErrorproneJavacflagsErrorproneDisabledByDefault(t *testing.T }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_library", "java-lib-1", AttrNameToString{ + MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ "javacopts": `["-Xsuper-fast"]`, "srcs": `["a.java"]`, }), @@ -228,7 +228,7 @@ func TestJavaLibraryErrorproneJavacflagsErrorproneDisabledManually(t *testing.T) }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_library", "java-lib-1", AttrNameToString{ + MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ "javacopts": `["-Xsuper-fast"]`, "srcs": `["a.java"]`, }), @@ -252,13 +252,13 @@ func TestJavaLibraryLogTags(t *testing.T) { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("event_log_tags", "example_lib_logtags", AttrNameToString{ + MakeBazelTarget("event_log_tags", "example_lib_logtags", AttrNameToString{ "srcs": `[ "a.logtag", "b.logtag", ]`, }), - makeBazelTarget("java_library", "example_lib", AttrNameToString{ + MakeBazelTarget("java_library", "example_lib", AttrNameToString{ "srcs": `[ "a.java", "b.java", @@ -280,7 +280,7 @@ func TestJavaLibraryResources(t *testing.T) { java_resources: ["res/a.res", "res/b.res"], }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_library", "java-lib-1", AttrNameToString{ + MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ "resources": `[ "res/a.res", "res/b.res", @@ -302,7 +302,7 @@ func TestJavaLibraryResourceDirs(t *testing.T) { java_resource_dirs: ["res"], }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_library", "java-lib-1", AttrNameToString{ + MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ "resource_strip_prefix": `"res"`, "resources": `[ "res/a.res", @@ -326,7 +326,7 @@ func TestJavaLibraryResourcesExcludeDir(t *testing.T) { exclude_java_resource_dirs: ["res/exclude"], }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_library", "java-lib-1", AttrNameToString{ + MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ "resource_strip_prefix": `"res"`, "resources": `["res/a.res"]`, }), @@ -347,7 +347,7 @@ func TestJavaLibraryResourcesExcludeFile(t *testing.T) { exclude_java_resources: ["res/dir1/exclude.res"], }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_library", "java-lib-1", AttrNameToString{ + MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{ "resource_strip_prefix": `"res"`, "resources": `[ "res/a.res", @@ -389,16 +389,16 @@ func TestJavaLibraryAidl(t *testing.T) { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("aidl_library", "example_lib_aidl_library", AttrNameToString{ + MakeBazelTarget("aidl_library", "example_lib_aidl_library", AttrNameToString{ "srcs": `[ "a.aidl", "b.aidl", ]`, }), - makeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{ + MakeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{ "deps": `[":example_lib_aidl_library"]`, }), - makeBazelTarget("java_library", "example_lib", AttrNameToString{ + MakeBazelTarget("java_library", "example_lib", AttrNameToString{ "deps": `[":example_lib_java_aidl_library"]`, "exports": `[":example_lib_java_aidl_library"]`, "srcs": `[ @@ -424,13 +424,13 @@ java_library { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("aidl_library", "example_lib_aidl_library", AttrNameToString{ + MakeBazelTarget("aidl_library", "example_lib_aidl_library", AttrNameToString{ "srcs": `["b.aidl"]`, }), - makeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{ + MakeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{ "deps": `[":example_lib_aidl_library"]`, }), - makeBazelTarget("java_library", "example_lib", AttrNameToString{ + MakeBazelTarget("java_library", "example_lib", AttrNameToString{ "deps": `[":example_lib_java_aidl_library"]`, "exports": `[":example_lib_java_aidl_library"]`, "srcs": `["a.java"]`, @@ -478,10 +478,10 @@ java_library { "b.aidl", ]`, }), - makeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{ + MakeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{ "deps": `[":aidl_files"]`, }), - makeBazelTarget("java_library", "example_lib", AttrNameToString{ + MakeBazelTarget("java_library", "example_lib", AttrNameToString{ "deps": `[":example_lib_java_aidl_library"]`, "exports": `[":example_lib_java_aidl_library"]`, "srcs": `[ @@ -501,3 +501,151 @@ java_library { ctx.RegisterModuleType("filegroup", android.FileGroupFactory) }) } + +func TestJavaLibraryAidlNonAdjacentAidlFilegroup(t *testing.T) { + runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{ + Description: "java_library with non adjacent aidl filegroup", + ModuleTypeUnderTest: "java_library", + ModuleTypeUnderTestFactory: java.LibraryFactory, + Filesystem: map[string]string{ + "path/to/A/Android.bp": ` +filegroup { + name: "A_aidl", + srcs: ["aidl/A.aidl"], + path: "aidl", +}`, + }, + Blueprint: ` +java_library { + name: "foo", + srcs: [ + ":A_aidl", + ], +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("java_aidl_library", "foo_java_aidl_library", AttrNameToString{ + "deps": `["//path/to/A:A_aidl"]`, + }), + MakeBazelTarget("java_library", "foo", AttrNameToString{ + "exports": `[":foo_java_aidl_library"]`, + }), + }, + }, func(ctx android.RegistrationContext) { + ctx.RegisterModuleType("filegroup", android.FileGroupFactory) + }) +} + +func TestConvertArmNeonVariant(t *testing.T) { + t.Helper() + RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{ + Description: "Android Library - simple arch feature", + ModuleTypeUnderTest: "android_library", + ModuleTypeUnderTestFactory: java.AndroidLibraryFactory, + Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + ` +android_library { + name: "TestLib", + manifest: "manifest/AndroidManifest.xml", + srcs: ["lib.java"], + arch: { + arm: { + neon: { + srcs: ["arm_neon.java"], + }, + }, + }, +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget( + "android_library", + "TestLib", + AttrNameToString{ + "srcs": `["lib.java"] + select({ + "//build/bazel/platforms/arch/variants:arm-neon": ["arm_neon.java"], + "//conditions:default": [], + })`, + "manifest": `"manifest/AndroidManifest.xml"`, + "resource_files": `[]`, + }), + }}) +} + +func TestConvertMultipleArchFeatures(t *testing.T) { + t.Helper() + RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{ + Description: "Android Library - multiple arch features", + ModuleTypeUnderTest: "android_library", + ModuleTypeUnderTestFactory: java.AndroidLibraryFactory, + Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + ` +android_library { + name: "TestLib", + manifest: "manifest/AndroidManifest.xml", + srcs: ["lib.java"], + arch: { + x86: { + ssse3: { + srcs: ["ssse3.java"], + }, + sse4_1: { + srcs: ["sse4_1.java"], + }, + }, + }, +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget( + "android_library", + "TestLib", + AttrNameToString{ + "srcs": `["lib.java"] + select({ + "//build/bazel/platforms/arch/variants:x86-sse4_1": ["sse4_1.java"], + "//build/bazel/platforms/arch/variants:x86-sse4_1-ssse3": [ + "sse4_1.java", + "ssse3.java", + ], + "//build/bazel/platforms/arch/variants:x86-ssse3": ["ssse3.java"], + "//conditions:default": [], + })`, + "manifest": `"manifest/AndroidManifest.xml"`, + "resource_files": `[]`, + }), + }}) +} + +func TestConvertExcludeSrcsArchFeature(t *testing.T) { + t.Helper() + RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{ + Description: "Android Library - exclude_srcs with arch feature", + ModuleTypeUnderTest: "android_library", + ModuleTypeUnderTestFactory: java.AndroidLibraryFactory, + Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + ` +android_library { + name: "TestLib", + manifest: "manifest/AndroidManifest.xml", + srcs: ["lib.java"], + arch: { + arm: { + srcs: ["arm_non_neon.java"], + neon: { + exclude_srcs: ["arm_non_neon.java"], + }, + }, + }, +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget( + "android_library", + "TestLib", + AttrNameToString{ + "srcs": `["lib.java"] + select({ + "//build/bazel/platforms/arch/variants:arm-neon": [], + "//build/bazel/platforms/arch:arm": ["arm_non_neon.java"], + "//conditions:default": [], + })`, + "manifest": `"manifest/AndroidManifest.xml"`, + "resource_files": `[]`, + }), + }}) +} diff --git a/bp2build/java_library_host_conversion_test.go b/bp2build/java_library_host_conversion_test.go index 1dcf16337..edd8690af 100644 --- a/bp2build/java_library_host_conversion_test.go +++ b/bp2build/java_library_host_conversion_test.go @@ -46,7 +46,7 @@ java_library_host { java_version: "9", }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_library", "java-lib-host-1", AttrNameToString{ + MakeBazelTarget("java_library", "java-lib-host-1", AttrNameToString{ "srcs": `["a.java"]`, "deps": `[":java-lib-host-2"]`, "target_compatible_with": `select({ @@ -54,7 +54,7 @@ java_library_host { "//conditions:default": [], })`, }), - makeBazelTarget("java_library", "java-lib-host-2", AttrNameToString{ + MakeBazelTarget("java_library", "java-lib-host-2", AttrNameToString{ "javacopts": `["-source 1.9 -target 1.9"]`, "srcs": `["c.java"]`, "target_compatible_with": `select({ diff --git a/bp2build/java_plugin_conversion_test.go b/bp2build/java_plugin_conversion_test.go index 2d2e5ff5d..d9049d46b 100644 --- a/bp2build/java_plugin_conversion_test.go +++ b/bp2build/java_plugin_conversion_test.go @@ -54,7 +54,7 @@ java_library { bazel_module: { bp2build_available: false }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_plugin", "java-plug-1", AttrNameToString{ + MakeBazelTarget("java_plugin", "java-plug-1", AttrNameToString{ "target_compatible_with": `select({ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"], "//conditions:default": [], @@ -95,7 +95,7 @@ java_library { bazel_module: { bp2build_available: false }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("java_plugin", "java-plug-1", AttrNameToString{ + MakeBazelTarget("java_plugin", "java-plug-1", AttrNameToString{ "target_compatible_with": `select({ "//build/bazel/platforms/os:android": ["@platforms//:incompatible"], "//conditions:default": [], diff --git a/bp2build/java_proto_conversion_test.go b/bp2build/java_proto_conversion_test.go index 6465641f0..df0df2fee 100644 --- a/bp2build/java_proto_conversion_test.go +++ b/bp2build/java_proto_conversion_test.go @@ -70,7 +70,7 @@ func TestJavaProto(t *testing.T) { srcs: ["a.proto"], }` - protoLibrary := makeBazelTarget("proto_library", "java-protos_proto", AttrNameToString{ + protoLibrary := MakeBazelTarget("proto_library", "java-protos_proto", AttrNameToString{ "srcs": `["a.proto"]`, }) @@ -82,13 +82,13 @@ func TestJavaProto(t *testing.T) { Blueprint: fmt.Sprintf(bp, tc.protoType), ExpectedBazelTargets: []string{ protoLibrary, - makeBazelTarget( + MakeBazelTarget( tc.javaLibraryType, javaLibraryName, AttrNameToString{ "deps": `[":java-protos_proto"]`, }), - makeBazelTarget("java_library", "java-protos", AttrNameToString{ + MakeBazelTarget("java_library", "java-protos", AttrNameToString{ "exports": fmt.Sprintf(`[":%s"]`, javaLibraryName), }), }, @@ -106,16 +106,16 @@ func TestJavaProtoDefault(t *testing.T) { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("proto_library", "java-protos_proto", AttrNameToString{ + MakeBazelTarget("proto_library", "java-protos_proto", AttrNameToString{ "srcs": `["a.proto"]`, }), - makeBazelTarget( + MakeBazelTarget( "java_lite_proto_library", "java-protos_java_proto_lite", AttrNameToString{ "deps": `[":java-protos_proto"]`, }), - makeBazelTarget("java_library", "java-protos", AttrNameToString{ + MakeBazelTarget("java_library", "java-protos", AttrNameToString{ "exports": `[":java-protos_java_proto_lite"]`, "javacopts": `["-source 1.7 -target 1.7"]`, }), diff --git a/bp2build/license_conversion_test.go b/bp2build/license_conversion_test.go new file mode 100644 index 000000000..ea6b27a17 --- /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 000000000..eda116c5a --- /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/linker_config_conversion_test.go b/bp2build/linker_config_conversion_test.go index 3b8a36355..5e7bcd440 100644 --- a/bp2build/linker_config_conversion_test.go +++ b/bp2build/linker_config_conversion_test.go @@ -25,7 +25,7 @@ func runLinkerConfigTestCase(t *testing.T, tc Bp2buildTestCase) { t.Helper() (&tc).ModuleTypeUnderTest = "linker_config" (&tc).ModuleTypeUnderTestFactory = linkerconfig.LinkerConfigFactory - runBp2BuildTestCaseSimple(t, tc) + RunBp2BuildTestCaseSimple(t, tc) } func TestLinkerConfigConvertsSrc(t *testing.T) { @@ -37,7 +37,7 @@ linker_config { src: "a.json", } `, - ExpectedBazelTargets: []string{makeBazelTarget("linker_config", "foo", AttrNameToString{ + ExpectedBazelTargets: []string{MakeBazelTarget("linker_config", "foo", AttrNameToString{ "src": `"a.json"`, })}, }) diff --git a/bp2build/ndk_headers_conversion_test.go b/bp2build/ndk_headers_conversion_test.go new file mode 100644 index 000000000..c7cc6b21a --- /dev/null +++ b/bp2build/ndk_headers_conversion_test.go @@ -0,0 +1,164 @@ +// 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 TestNdkHeaderFilepaths(t *testing.T) { + bpTemplate := ` + ndk_headers { + name: "foo", + srcs: %v, + exclude_srcs: %v, + } + ` + testCases := []struct { + desc string + srcs string + excludeSrcs string + expectedHdrs string + }{ + { + desc: "Single header file", + srcs: `["foo.h"]`, + excludeSrcs: `[]`, + expectedHdrs: `["foo.h"]`, + }, + { + desc: "Multiple header files", + srcs: `["foo.h", "foo_other.h"]`, + excludeSrcs: `[]`, + expectedHdrs: `[ + "foo.h", + "foo_other.h", + ]`, + }, + { + desc: "Multiple header files with excludes", + srcs: `["foo.h", "foo_other.h"]`, + excludeSrcs: `["foo_other.h"]`, + expectedHdrs: `["foo.h"]`, + }, + { + desc: "Multiple header files via Soong-supported globs", + srcs: `["*.h"]`, + excludeSrcs: `[]`, + expectedHdrs: `[ + "foo.h", + "foo_other.h", + ]`, + }, + } + for _, testCase := range testCases { + fs := map[string]string{ + "foo.h": "", + "foo_other.h": "", + } + expectedApiContributionTargetName := "foo.contribution" + expectedBazelTarget := MakeBazelTargetNoRestrictions( + "cc_api_headers", + expectedApiContributionTargetName, + AttrNameToString{ + "hdrs": testCase.expectedHdrs, + }, + ) + RunBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{ + Description: testCase.desc, + Blueprint: fmt.Sprintf(bpTemplate, testCase.srcs, testCase.excludeSrcs), + ExpectedBazelTargets: []string{expectedBazelTarget}, + Filesystem: fs, + }) + } +} + +func TestNdkHeaderIncludeDir(t *testing.T) { + bpTemplate := ` + ndk_headers { + name: "foo", + from: %v, + to: "this/value/is/ignored", + } + ` + testCases := []struct { + desc string + from string + expectedIncludeDir string + }{ + { + desc: "Empty `from` value", + from: `""`, + expectedIncludeDir: `""`, + }, + { + desc: "Non-Empty `from` value", + from: `"include"`, + expectedIncludeDir: `"include"`, + }, + } + for _, testCase := range testCases { + expectedApiContributionTargetName := "foo.contribution" + expectedBazelTarget := MakeBazelTargetNoRestrictions( + "cc_api_headers", + expectedApiContributionTargetName, + AttrNameToString{ + "include_dir": testCase.expectedIncludeDir, + }, + ) + RunBp2BuildTestCase(t, cc.RegisterNdkModuleTypes, Bp2buildTestCase{ + Description: testCase.desc, + Blueprint: fmt.Sprintf(bpTemplate, testCase.from), + ExpectedBazelTargets: []string{expectedBazelTarget}, + }) + } +} + +func TestVersionedNdkHeaderFilepaths(t *testing.T) { + bp := ` + versioned_ndk_headers { + name: "common_libc", + from: "include" + } + ` + fs := map[string]string{ + "include/math.h": "", + "include/stdio.h": "", + "include/arm/arm.h": "", + "include/x86/x86.h": "", + } + expectedApiContributionTargetName := "common_libc.contribution" + expectedBazelTarget := MakeBazelTargetNoRestrictions( + "cc_api_headers", + expectedApiContributionTargetName, + AttrNameToString{ + "include_dir": `"include"`, + "hdrs": `[ + "include/math.h", + "include/stdio.h", + "include/arm/arm.h", + "include/x86/x86.h", + ]`, + }, + ) + RunBp2BuildTestCase(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 000000000..3704b2d7b --- /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 fce4c745b..aa0a5b728 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) { @@ -45,7 +46,7 @@ prebuilt_etc { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{ + MakeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{ "filename": `"tz_version"`, "installable": `False`, "src": `"version/tz_version"`, @@ -75,7 +76,7 @@ prebuilt_etc { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{ + MakeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{ "filename": `"tz_version"`, "installable": `False`, "src": `select({ @@ -114,7 +115,7 @@ prebuilt_etc { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{ + MakeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{ "filename": `"tz_version"`, "installable": `False`, "src": `select({ @@ -128,6 +129,32 @@ prebuilt_etc { "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() @@ -153,7 +180,7 @@ prebuilt_usr_share { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{ + MakeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{ "filename": `"tz_version"`, "installable": `False`, "src": `"version/tz_version"`, @@ -174,10 +201,148 @@ prebuilt_etc { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{ + MakeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{ "filename": `"tz_version"`, "installable": `False`, "src": `"version/tz_version"`, "dir": `"etc"`, })}}) } + +func TestFilenameAsProperty(t *testing.T) { + runPrebuiltEtcTestCase(t, Bp2buildTestCase{ + Description: "prebuilt_etc - filename is specified as a property ", + Filesystem: map[string]string{}, + Blueprint: ` +prebuilt_etc { + name: "foo", + src: "fooSrc", + filename: "fooFileName", +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("prebuilt_file", "foo", AttrNameToString{ + "filename": `"fooFileName"`, + "src": `"fooSrc"`, + "dir": `"etc"`, + })}}) +} + +func TestFileNameFromSrc(t *testing.T) { + runPrebuiltEtcTestCase(t, Bp2buildTestCase{ + Description: "prebuilt_etc - filename_from_src is true ", + Filesystem: map[string]string{}, + Blueprint: ` +prebuilt_etc { + name: "foo", + filename_from_src: true, + src: "fooSrc", +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("prebuilt_file", "foo", AttrNameToString{ + "filename": `"fooSrc"`, + "src": `"fooSrc"`, + "dir": `"etc"`, + })}}) +} + +func TestFileNameFromSrcMultipleSrcs(t *testing.T) { + runPrebuiltEtcTestCase(t, Bp2buildTestCase{ + Description: "prebuilt_etc - filename_from_src is true but there are multiple srcs", + Filesystem: map[string]string{}, + Blueprint: ` +prebuilt_etc { + name: "foo", + filename_from_src: true, + arch: { + arm: { + src: "barSrc", + }, + arm64: { + src: "bazSrc", + }, + } +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("prebuilt_file", "foo", AttrNameToString{ + "filename_from_src": `True`, + "dir": `"etc"`, + "src": `select({ + "//build/bazel/platforms/arch:arm": "barSrc", + "//build/bazel/platforms/arch:arm64": "bazSrc", + "//conditions:default": None, + })`, + })}}) +} + +func TestFilenameFromModuleName(t *testing.T) { + runPrebuiltEtcTestCase(t, Bp2buildTestCase{ + Description: "prebuilt_etc - neither filename nor filename_from_src are specified ", + Filesystem: map[string]string{}, + Blueprint: ` +prebuilt_etc { + name: "foo", +} +`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("prebuilt_file", "foo", AttrNameToString{ + "filename": `"foo"`, + "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 79da5d597..e8b9bc41c 100644 --- a/bp2build/python_binary_conversion_test.go +++ b/bp2build/python_binary_conversion_test.go @@ -42,7 +42,7 @@ func TestPythonBinaryHostSimple(t *testing.T) { bazel_module: { bp2build_available: false }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("py_binary", "foo", AttrNameToString{ + MakeBazelTarget("py_binary", "foo", AttrNameToString{ "data": `["files/data.txt"]`, "deps": `[":bar"]`, "main": `"a.py"`, @@ -62,7 +62,7 @@ func TestPythonBinaryHostSimple(t *testing.T) { } func TestPythonBinaryHostPy2(t *testing.T) { - runBp2BuildTestCaseSimple(t, Bp2buildTestCase{ + RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{ Description: "py2 python_binary_host", ModuleTypeUnderTest: "python_binary_host", ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory, @@ -82,7 +82,7 @@ func TestPythonBinaryHostPy2(t *testing.T) { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("py_binary", "foo", AttrNameToString{ + MakeBazelTarget("py_binary", "foo", AttrNameToString{ "python_version": `"PY2"`, "imports": `["."]`, "srcs": `["a.py"]`, @@ -96,7 +96,7 @@ func TestPythonBinaryHostPy2(t *testing.T) { } func TestPythonBinaryHostPy3(t *testing.T) { - runBp2BuildTestCaseSimple(t, Bp2buildTestCase{ + RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{ Description: "py3 python_binary_host", ModuleTypeUnderTest: "python_binary_host", ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory, @@ -117,7 +117,7 @@ func TestPythonBinaryHostPy3(t *testing.T) { `, ExpectedBazelTargets: []string{ // python_version is PY3 by default. - makeBazelTarget("py_binary", "foo", AttrNameToString{ + MakeBazelTarget("py_binary", "foo", AttrNameToString{ "imports": `["."]`, "srcs": `["a.py"]`, "target_compatible_with": `select({ @@ -130,7 +130,7 @@ func TestPythonBinaryHostPy3(t *testing.T) { } func TestPythonBinaryHostArchVariance(t *testing.T) { - runBp2BuildTestCaseSimple(t, Bp2buildTestCase{ + RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{ Description: "test arch variants", ModuleTypeUnderTest: "python_binary_host", ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory, @@ -150,7 +150,7 @@ func TestPythonBinaryHostArchVariance(t *testing.T) { }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("py_binary", "foo-arm", AttrNameToString{ + MakeBazelTarget("py_binary", "foo-arm", AttrNameToString{ "imports": `["."]`, "srcs": `select({ "//build/bazel/platforms/arch:arm": ["arm.py"], diff --git a/bp2build/python_library_conversion_test.go b/bp2build/python_library_conversion_test.go index 1d6061bf1..a53371d2b 100644 --- a/bp2build/python_library_conversion_test.go +++ b/bp2build/python_library_conversion_test.go @@ -35,7 +35,7 @@ func convertPythonLibTestCaseToBp2build_Host(tc pythonLibBp2BuildTestCase) Bp2bu func convertPythonLibTestCaseToBp2build(tc pythonLibBp2BuildTestCase) Bp2buildTestCase { var bp2BuildTargets []string for _, t := range tc.expectedBazelTargets { - bp2BuildTargets = append(bp2BuildTargets, makeBazelTarget(t.typ, t.name, t.attrs)) + bp2BuildTargets = append(bp2BuildTargets, MakeBazelTarget(t.typ, t.name, t.attrs)) } // Copy the filesystem so that we can change stuff in it later without it // affecting the original pythonLibBp2BuildTestCase @@ -66,7 +66,7 @@ func runPythonLibraryTestCase(t *testing.T, tc pythonLibBp2BuildTestCase) { testCase.ModuleTypeUnderTest = "python_library" testCase.ModuleTypeUnderTestFactory = python.PythonLibraryFactory - runBp2BuildTestCaseSimple(t, testCase) + RunBp2BuildTestCaseSimple(t, testCase) } func runPythonLibraryHostTestCase(t *testing.T, tc pythonLibBp2BuildTestCase) { diff --git a/bp2build/sh_conversion_test.go b/bp2build/sh_conversion_test.go index d8f701d94..92b3a6575 100644 --- a/bp2build/sh_conversion_test.go +++ b/bp2build/sh_conversion_test.go @@ -66,7 +66,7 @@ func TestShBinarySimple(t *testing.T) { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("sh_binary", "foo", AttrNameToString{ + MakeBazelTarget("sh_binary", "foo", AttrNameToString{ "srcs": `["foo.sh"]`, "filename": `"foo.exe"`, "sub_dir": `"sub"`, @@ -85,7 +85,7 @@ func TestShBinaryDefaults(t *testing.T) { bazel_module: { bp2build_available: true }, }`, ExpectedBazelTargets: []string{ - makeBazelTarget("sh_binary", "foo", AttrNameToString{ + MakeBazelTarget("sh_binary", "foo", AttrNameToString{ "srcs": `["foo.sh"]`, })}, }) diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go index 78e7b0e75..023ec9687 100644 --- a/bp2build/symlink_forest.go +++ b/bp2build/symlink_forest.go @@ -1,12 +1,27 @@ +// 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" "fmt" "io/ioutil" "os" "path/filepath" + "regexp" + "android/soong/android" "android/soong/shared" ) @@ -58,6 +73,57 @@ func treeFromExcludePathList(paths []string) *node { return result } +func mergeBuildFiles(output string, srcBuildFile string, generatedBuildFile string, verbose bool) error { + + srcBuildFileContent, err := os.ReadFile(srcBuildFile) + if err != nil { + return err + } + + generatedBuildFileContent, err := os.ReadFile(generatedBuildFile) + if err != nil { + return err + } + + // There can't be a package() call in both the source and generated BUILD files. + // bp2build will generate a package() call for licensing information, but if + // there's no licensing information, it will still generate a package() call + // that just sets default_visibility=public. If the handcrafted build file + // also has a package() call, we'll allow it to override the bp2build + // generated one if it doesn't have any licensing information. If the bp2build + // one has licensing information and the handcrafted one exists, we'll leave + // them both in for bazel to throw an error. + packageRegex := regexp.MustCompile(`(?m)^package\s*\(`) + packageDefaultVisibilityRegex := regexp.MustCompile(`(?m)^package\s*\(\s*default_visibility\s*=\s*\[\s*"//visibility:public",?\s*]\s*\)`) + if packageRegex.Find(srcBuildFileContent) != nil { + if verbose && packageDefaultVisibilityRegex.Find(generatedBuildFileContent) != nil { + fmt.Fprintf(os.Stderr, "Both '%s' and '%s' have a package() target, removing the first one\n", + generatedBuildFile, srcBuildFile) + } + generatedBuildFileContent = packageDefaultVisibilityRegex.ReplaceAll(generatedBuildFileContent, []byte{}) + } + + outFile, err := os.Create(output) + if err != nil { + return err + } + + _, err = outFile.Write(generatedBuildFileContent) + if err != nil { + return err + } + + if generatedBuildFileContent[len(generatedBuildFileContent)-1] != '\n' { + _, err = outFile.WriteString("\n") + if err != nil { + return err + } + } + + _, err = outFile.Write(srcBuildFileContent) + return err +} + // Calls readdir() and returns it as a map from the basename of the files in dir // to os.FileInfo. func readdirToMap(dir string) map[string]os.FileInfo { @@ -125,6 +191,17 @@ func plantSymlinkForestRecursive(cfg android.Config, topdir string, forestDir st srcDirMap := readdirToMap(shared.JoinPath(topdir, srcDir)) buildFilesMap := readdirToMap(shared.JoinPath(topdir, buildFilesDir)) + renamingBuildFile := false + if _, ok := srcDirMap["BUILD"]; ok { + if _, ok := srcDirMap["BUILD.bazel"]; !ok { + if _, ok := buildFilesMap["BUILD.bazel"]; ok { + renamingBuildFile = true + srcDirMap["BUILD.bazel"] = srcDirMap["BUILD"] + delete(srcDirMap, "BUILD") + } + } + } + allEntries := make(map[string]bool) for n := range srcDirMap { allEntries[n] = true @@ -148,21 +225,28 @@ func plantSymlinkForestRecursive(cfg android.Config, topdir string, forestDir st // The full paths of children in the input trees and in the output tree forestChild := shared.JoinPath(forestDir, f) srcChild := shared.JoinPath(srcDir, f) + if f == "BUILD.bazel" && renamingBuildFile { + srcChild = shared.JoinPath(srcDir, "BUILD") + } buildFilesChild := shared.JoinPath(buildFilesDir, f) // Descend in the exclusion tree, if there are any excludes left - var excludeChild *node - if exclude == nil { - excludeChild = nil - } else { - excludeChild = exclude.children[f] + var excludeChild *node = nil + if exclude != nil { + if f == "BUILD.bazel" && renamingBuildFile { + excludeChild = exclude.children["BUILD"] + } else { + excludeChild = exclude.children[f] + } } srcChildEntry, sExists := srcDirMap[f] buildFilesChildEntry, bExists := buildFilesMap[f] - excluded := excludeChild != nil && excludeChild.excluded - if excluded { + if excludeChild != nil && excludeChild.excluded { + if bExists { + symlinkIntoForest(topdir, forestChild, buildFilesChild) + } continue } @@ -198,13 +282,15 @@ func plantSymlinkForestRecursive(cfg android.Config, topdir string, forestDir st // Both are directories. Descend. plantSymlinkForestRecursive(cfg, topdir, forestChild, buildFilesChild, srcChild, excludeChild, acc, okay) } else if !sDir && !bDir { - // Neither is a directory. Prioritize BUILD files generated by bp2build - // over any BUILD file imported into external/. - if cfg.IsEnvTrue("BP2BUILD_VERBOSE") { - fmt.Fprintf(os.Stderr, "Both '%s' and '%s' exist, symlinking the former to '%s'\n", - buildFilesChild, srcChild, forestChild) + // Neither is a directory. Merge them. + srcBuildFile := shared.JoinPath(topdir, srcChild) + generatedBuildFile := shared.JoinPath(topdir, buildFilesChild) + err = mergeBuildFiles(shared.JoinPath(topdir, forestChild), srcBuildFile, generatedBuildFile, cfg.IsEnvTrue("BP2BUILD_VERBOSE")) + if err != nil { + fmt.Fprintf(os.Stderr, "Error merging %s and %s: %s", + srcBuildFile, generatedBuildFile, err) + *okay = false } - symlinkIntoForest(topdir, forestChild, buildFilesChild) } else { // Both exist and one is a file. This is an error. fmt.Fprintf(os.Stderr, diff --git a/bp2build/testing.go b/bp2build/testing.go index 0f321de54..edc5c4a99 100644 --- a/bp2build/testing.go +++ b/bp2build/testing.go @@ -71,7 +71,7 @@ func errored(t *testing.T, tc Bp2buildTestCase, errs []error) bool { return false } -func runBp2BuildTestCaseSimple(t *testing.T, tc Bp2buildTestCase) { +func RunBp2BuildTestCaseSimple(t *testing.T, tc Bp2buildTestCase) { t.Helper() RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc) } @@ -141,7 +141,7 @@ func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.Regi 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 { @@ -384,6 +384,9 @@ func customBp2buildOneToMany(ctx android.TopDownMutatorContext, m *customModule) 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 +429,9 @@ func makeBazelTargetHostOrDevice(typ, name string, attrs AttrNameToString, hod a } 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])) } @@ -444,6 +449,17 @@ func MakeBazelTargetNoRestrictions(typ, name string, attrs AttrNameToString) str // makeBazelTargetNoRestrictions returns bazel target build file definition that is device specific // as this is the most common default in Soong. -func makeBazelTarget(typ, name string, attrs AttrNameToString) string { +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) +} diff --git a/cc/Android.bp b/cc/Android.bp index ce944674b..91a3fb0df 100644 --- a/cc/Android.bp +++ b/cc/Android.bp @@ -45,7 +45,6 @@ bootstrap_go_package { "snapshot_utils.go", "stl.go", "strip.go", - "sysprop.go", "tidy.go", "util.go", "vendor_snapshot.go", @@ -99,10 +98,13 @@ bootstrap_go_package { "library_headers_test.go", "library_stub_test.go", "library_test.go", + "lto_test.go", + "ndk_test.go", "object_test.go", "prebuilt_test.go", "proto_test.go", "sanitize_test.go", + "sdk_test.go", "test_data_test.go", "tidy_test.go", "vendor_public_library_test.go", diff --git a/cc/androidmk.go b/cc/androidmk.go index a95724687..a9ba1a9e6 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -644,6 +644,16 @@ func (a *apiLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *an }) } +func (a *apiHeadersDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { + entries.Class = "HEADER_LIBRARIES" + entries.SubName += multitree.GetApiImportSuffix() + + entries.ExtraEntries = append(entries.ExtraEntries, func(_ android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { + a.libraryDecorator.androidMkWriteExportedFlags(entries) + entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true) + }) +} + func androidMkWriteAllowUndefinedSymbols(linker *baseLinker, entries *android.AndroidMkEntries) { allow := linker.Properties.Allow_undefined_symbols if allow != nil { diff --git a/cc/binary.go b/cc/binary.go index 849aafaaa..3351fd732 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -18,6 +18,7 @@ import ( "path/filepath" "android/soong/bazel/cquery" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -591,7 +592,7 @@ func (handler *ccBinaryBazelHandler) ProcessBazelQueryResponse(ctx android.Modul handler.module.linker.(*binaryDecorator).unstrippedOutputFile = outputFilePath } -func binaryBp2build(ctx android.TopDownMutatorContext, m *Module, typ string) { +func binaryBp2buildAttrs(ctx android.TopDownMutatorContext, m *Module) binaryAttributes { baseAttrs := bp2BuildParseBaseProps(ctx, m) binaryLinkerAttrs := bp2buildBinaryLinkerProps(ctx, m) @@ -601,7 +602,7 @@ func binaryBp2build(ctx android.TopDownMutatorContext, m *Module, typ string) { baseAttrs.implementationDeps.Add(baseAttrs.protoDependency) } - attrs := &binaryAttributes{ + attrs := binaryAttributes{ binaryLinkerAttrs: binaryLinkerAttrs, Srcs: baseAttrs.srcs, @@ -644,12 +645,19 @@ func binaryBp2build(ctx android.TopDownMutatorContext, m *Module, typ string) { sdkAttributes: bp2BuildParseSdkAttributes(m), } + return attrs +} + +func binaryBp2build(ctx android.TopDownMutatorContext, m *Module) { + // shared with cc_test + binaryAttrs := binaryBp2buildAttrs(ctx, m) + ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{ Rule_class: "cc_binary", Bzl_load_location: "//build/bazel/rules/cc:cc_binary.bzl", }, android.CommonAttributes{Name: m.Name()}, - attrs) + &binaryAttrs) } // binaryAttributes contains Bazel attributes corresponding to a cc binary diff --git a/cc/bp2build.go b/cc/bp2build.go index 625e7ce14..63151ad5c 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -36,6 +36,8 @@ const ( cppSrcPartition = "cpp" protoSrcPartition = "proto" aidlSrcPartition = "aidl" + + stubsSuffix = "_stub_libs_current" ) // staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties -- @@ -77,10 +79,10 @@ func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.Lab 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 @@ -339,6 +341,8 @@ type compilerAttributes struct { stubsVersions bazel.StringListAttribute features bazel.StringListAttribute + + suffix bazel.StringAttribute } type filterOutFn func(string) bool @@ -502,19 +506,6 @@ func parseSrcs(ctx android.BazelConversionPathContext, props *BaseCompilerProper 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. @@ -694,6 +685,9 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) compilerAttrs.stubsSymbolFile = libraryProps.Stubs.Symbol_file compilerAttrs.stubsVersions.SetSelectValue(axis, config, libraryProps.Stubs.Versions) } + if suffix := libraryProps.Suffix; suffix != nil { + compilerAttrs.suffix.SetSelectValue(axis, config, suffix) + } } } } @@ -718,15 +712,23 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) (&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) + 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) @@ -744,78 +746,57 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) } } -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, ) *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" + 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, + }, + ) + 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 { @@ -922,7 +903,7 @@ func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversion 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) @@ -932,14 +913,14 @@ func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversion (&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)) } } } @@ -1021,11 +1002,17 @@ func (la *linkerAttributes) convertProductVariables(ctx android.BazelConversionP depResolutionFunc func(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList } + // an intermediate attribute that holds Header_libs info, and will be appended to + // implementationDeps at the end, to solve the confliction that both header_libs + // and static_libs use implementationDeps. + var headerDeps bazel.LabelListAttribute + productVarToDepFields := map[string]productVarDep{ // product variables do not support exclude_shared_libs "Shared_libs": {attribute: &la.implementationDynamicDeps, depResolutionFunc: bazelLabelForSharedDepsExcludes}, "Static_libs": {"Exclude_static_libs", &la.implementationDeps, bazelLabelForStaticDepsExcludes}, "Whole_static_libs": {"Exclude_static_libs", &la.wholeArchiveDeps, bazelLabelForWholeDepsExcludes}, + "Header_libs": {attribute: &headerDeps, depResolutionFunc: bazelLabelForHeaderDepsExcludes}, } for name, dep := range productVarToDepFields { @@ -1067,18 +1054,30 @@ func (la *linkerAttributes) convertProductVariables(ctx android.BazelConversionP ) } } + la.implementationDeps.Append(headerDeps) } func (la *linkerAttributes) finalize(ctx android.BazelConversionPathContext) { // if system dynamic deps have the default value, any use of a system dynamic library used will // result in duplicate library errors for bionic OSes. Here, we explicitly exclude those libraries - // from bionic OSes. + // from bionic OSes and the no config case as these libraries only build for bionic OSes. if la.systemDynamicDeps.IsNil() && len(la.usedSystemDynamicDepAsDynamicDep) > 0 { toRemove := bazelLabelForSharedDeps(ctx, android.SortedStringKeys(la.usedSystemDynamicDepAsDynamicDep)) + la.dynamicDeps.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() @@ -1195,12 +1194,19 @@ func bazelLabelForHeaderDeps(ctx android.BazelConversionPathContext, modules []s return bazelLabelForSharedDeps(ctx, modules) } +func bazelLabelForHeaderDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList { + // This is only used when product_variable header_libs is processed, to follow + // the pattern of depResolutionFunc + return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForSharedModule) +} + func bazelLabelForSharedDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList { return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForSharedModule) } type binaryLinkerAttrs struct { Linkshared *bool + Suffix bazel.StringAttribute } func bp2buildBinaryLinkerProps(ctx android.BazelConversionPathContext, m *Module) binaryLinkerAttrs { @@ -1217,6 +1223,9 @@ func bp2buildBinaryLinkerProps(ctx android.BazelConversionPathContext, m *Module // nonconfigurable attribute. Only 4 AOSP modules use this feature, defer handling ctx.ModuleErrorf("bp2build cannot migrate a module with arch/target-specific static_executable values") } + if suffix := linkerProps.Suffix; suffix != nil { + attrs.Suffix.SetSelectValue(axis, config, suffix) + } }) return attrs diff --git a/cc/builder.go b/cc/builder.go index f3faca801..cb21b1ff4 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -282,7 +282,7 @@ var ( sAbiDiff = pctx.RuleFunc("sAbiDiff", func(ctx android.PackageRuleContext) blueprint.RuleParams { commandStr := "($sAbiDiffer ${extraFlags} -lib ${libName} -arch ${arch} -o ${out} -new ${in} -old ${referenceDump})" - commandStr += "|| (echo 'error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py ${createReferenceDumpFlags} -l ${libName}'" + commandStr += "|| (echo '${errorMessage}'" commandStr += " && (mkdir -p $$DIST_DIR/abidiffs && cp ${out} $$DIST_DIR/abidiffs/)" commandStr += " && exit 1)" return blueprint.RuleParams{ @@ -290,7 +290,7 @@ var ( CommandDeps: []string{"$sAbiDiffer"}, } }, - "extraFlags", "referenceDump", "libName", "arch", "createReferenceDumpFlags") + "extraFlags", "referenceDump", "libName", "arch", "errorMessage") // Rule to unzip a reference abi dump. unzipRefSAbiDump = pctx.AndroidStaticRule("unzipRefSAbiDump", @@ -920,14 +920,14 @@ func unzipRefDump(ctx android.ModuleContext, zippedRefDump android.Path, baseNam // sourceAbiDiff registers a build statement to compare linked sAbi dump files (.lsdump). func sourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceDump android.Path, - baseName, prevVersion, exportedHeaderFlags string, diffFlags []string, + baseName, exportedHeaderFlags string, diffFlags []string, prevVersion int, checkAllApis, isLlndk, isNdk, isVndkExt, previousVersionDiff bool) android.OptionalPath { var outputFile android.ModuleOutPath - if prevVersion == "" { - outputFile = android.PathForModuleOut(ctx, baseName+".abidiff") + if previousVersionDiff { + outputFile = android.PathForModuleOut(ctx, baseName+"."+strconv.Itoa(prevVersion)+".abidiff") } else { - outputFile = android.PathForModuleOut(ctx, baseName+"."+prevVersion+".abidiff") + outputFile = android.PathForModuleOut(ctx, baseName+".abidiff") } libName := strings.TrimSuffix(baseName, filepath.Ext(baseName)) @@ -940,9 +940,18 @@ func sourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceD "-allow-unreferenced-elf-symbol-changes") } - // TODO(b/241496591): Remove -advice-only after b/239792343 and b/239790286 are reolved. + var errorMessage string + // When error occurs in previous version ABI diff, Developers can't just update ABI + // reference but need to follow instructions to ensure ABI backward compatibility. if previousVersionDiff { + // TODO(b/241496591): Remove -advice-only after b/239792343 and b/239790286 are reolved. extraFlags = append(extraFlags, "-advice-only") + errorMessage = "error: Please follow development/vndk/tools/header-checker/README.md to ensure the ABI compatibility between your source code and version " + strconv.Itoa(prevVersion) + "." + sourceVersion := prevVersion + 1 + extraFlags = append(extraFlags, "-target-version", strconv.Itoa(sourceVersion)) + } else { + errorMessage = "error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l " + libName + extraFlags = append(extraFlags, "-target-version", "current") } if isLlndk || isNdk { @@ -961,11 +970,11 @@ func sourceAbiDiff(ctx android.ModuleContext, inputDump android.Path, referenceD Input: inputDump, Implicit: referenceDump, Args: map[string]string{ - "referenceDump": referenceDump.String(), - "libName": libName, - "arch": ctx.Arch().ArchType.Name, - "extraFlags": strings.Join(extraFlags, " "), - "createReferenceDumpFlags": "", + "referenceDump": referenceDump.String(), + "libName": libName, + "arch": ctx.Arch().ArchType.Name, + "extraFlags": strings.Join(extraFlags, " "), + "errorMessage": errorMessage, }, }) return android.OptionalPathForPath(outputFile) @@ -51,7 +51,6 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { 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) { @@ -485,6 +484,7 @@ type ModuleContextIntf interface { static() bool staticBinary() bool testBinary() bool + testLibrary() bool header() bool binary() bool object() bool @@ -1486,6 +1486,10 @@ func (ctx *moduleContextImpl) testBinary() bool { return ctx.mod.testBinary() } +func (ctx *moduleContextImpl) testLibrary() bool { + return ctx.mod.testLibrary() +} + func (ctx *moduleContextImpl) header() bool { return ctx.mod.Header() } @@ -1900,6 +1904,8 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { if c.Properties.Clang != nil && *c.Properties.Clang == false { ctx.PropertyErrorf("clang", "false (GCC) is no longer supported") + } else if c.Properties.Clang != nil && !ctx.DeviceConfig().BuildBrokenClangProperty() { + ctx.PropertyErrorf("clang", "property is deprecated, see Changes.md file") } flags := Flags{ @@ -2300,9 +2306,14 @@ func updateDepsWithApiImports(deps Deps, apiImports multitree.ApiImportInfo) Dep deps.RuntimeLibs[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs) } - for idx, lib := range deps.HeaderLibs { - deps.HeaderLibs[idx] = GetReplaceModuleName(lib, apiImports.HeaderLibs) + for idx, lib := range deps.SystemSharedLibs { + deps.SystemSharedLibs[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs) + } + + for idx, lib := range deps.ReexportSharedLibHeaders { + deps.ReexportSharedLibHeaders[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs) } + return deps } @@ -2346,9 +2357,14 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { depTag.reexportFlags = true } + // Check header lib replacement from API surface first, and then check again with VSDK + lib = GetReplaceModuleName(lib, apiImportInfo.HeaderLibs) lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).HeaderLibs) - if c.IsStubs() { + if c.isNDKStubLibrary() { + // ndk_headers do not have any variations + actx.AddFarVariationDependencies([]blueprint.Variation{}, depTag, lib) + } else if c.IsStubs() && !c.isImportedApiLibrary() { actx.AddFarVariationDependencies(append(ctx.Target().Variations(), c.ImageVariation()), depTag, lib) } else { @@ -2375,18 +2391,8 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { } } - // 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) @@ -2404,10 +2410,6 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { depTag.excludeInApex = true } - if impl, ok := syspropImplLibraries[lib]; ok { - lib = impl - } - lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs) actx.AddVariationDependencies([]blueprint.Variation{ @@ -2437,10 +2439,6 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { depTag.excludeInApex = true } - if impl, ok := syspropImplLibraries[lib]; ok { - lib = impl - } - name, version := StubsLibNameAndVersion(lib) sharedLibNames = append(sharedLibNames, name) @@ -3253,11 +3251,6 @@ func MakeLibName(ctx android.ModuleContext, c LinkableInterface, ccDep LinkableI return baseName + snapshotPrebuilt.SnapshotAndroidMkSuffix() } - - // Remove API import suffix if exists - if _, ok := ccDepModule.linker.(*apiLibraryDecorator); ok { - libName = strings.TrimSuffix(libName, multitree.GetApiImportSuffix()) - } } if ctx.DeviceConfig().VndkUseCoreVariant() && ccDep.IsVndk() && !ccDep.MustUseVendorVariant() && @@ -3369,6 +3362,15 @@ func (c *Module) testBinary() bool { return false } +func (c *Module) testLibrary() bool { + if test, ok := c.linker.(interface { + testLibrary() bool + }); ok { + return test.testLibrary() + } + return false +} + func (c *Module) benchmarkBinary() bool { if b, ok := c.linker.(interface { benchmarkBinary() bool @@ -3593,9 +3595,6 @@ func (c *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, if _, ok := c.linker.(prebuiltLinkerInterface); ok { return nil } - if _, ok := c.linker.(*apiLibraryDecorator); ok { - return nil - } minSdkVersion := c.MinSdkVersion() if minSdkVersion == "apex_inherit" { @@ -3650,13 +3649,25 @@ const ( staticLibrary sharedLibrary headerLibrary + testBin // testBinary already declared ) func (c *Module) typ() moduleType { - if c.Binary() { + if c.testBinary() { + // testBinary is also a binary, so this comes before the c.Binary() + // conditional. A testBinary has additional implicit dependencies and + // other test-only semantics. + return testBin + } else if c.Binary() { return binary } else if c.Object() { return object + } else if c.testLibrary() { + // TODO(b/244431896) properly convert cc_test_library to its own macro. This + // will let them add implicit compile deps on gtest, for example. + // + // For now, treat them as regular shared libraries. + return sharedLibrary } else if c.CcLibrary() { static := false shared := false @@ -3685,7 +3696,11 @@ func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { switch c.typ() { case binary: if !prebuilt { - binaryBp2build(ctx, c, ctx.ModuleType()) + binaryBp2build(ctx, c) + } + case testBin: + if !prebuilt { + testBinaryBp2build(ctx, c) } case object: if !prebuilt { @@ -3776,6 +3791,11 @@ func (c *Module) IsSdkVariant() bool { return c.Properties.IsSdkVariant } +func (c *Module) isImportedApiLibrary() bool { + _, ok := c.linker.(*apiLibraryDecorator) + return ok +} + func kytheExtractAllFactory() android.Singleton { return &kytheExtractAllSingleton{} } diff --git a/cc/cc_test.go b/cc/cc_test.go index f02570020..5d569cc9e 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -4111,7 +4111,7 @@ func TestIncludeDirsExporting(t *testing.T) { name: "libfoo", srcs: [ "foo.c", - "a.sysprop", + "path/to/a.sysprop", "b.aidl", "a.proto", ], @@ -4124,11 +4124,11 @@ func TestIncludeDirsExporting(t *testing.T) { `), expectedSystemIncludeDirs(``), expectedGeneratedHeaders(` - .intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/include/a.sysprop.h + .intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/include/path/to/a.sysprop.h `), expectedOrderOnlyDeps(` - .intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/include/a.sysprop.h - .intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/public/include/a.sysprop.h + .intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/include/path/to/a.sysprop.h + .intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/public/include/path/to/a.sysprop.h `), ) }) @@ -4336,3 +4336,53 @@ func TestIncludeDirectoryOrdering(t *testing.T) { } } + +func TestCcBuildBrokenClangProperty(t *testing.T) { + tests := []struct { + name string + clang bool + BuildBrokenClangProperty bool + err string + }{ + { + name: "error when clang is set to false", + clang: false, + err: "is no longer supported", + }, + { + name: "error when clang is set to true", + clang: true, + err: "property is deprecated, see Changes.md", + }, + { + name: "no error when BuildBrokenClangProperty is explicitly set to true", + clang: true, + BuildBrokenClangProperty: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + bp := fmt.Sprintf(` + cc_library { + name: "foo", + clang: %t, + }`, test.clang) + + if test.err == "" { + android.GroupFixturePreparers( + prepareForCcTest, + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + if test.BuildBrokenClangProperty { + variables.BuildBrokenClangProperty = test.BuildBrokenClangProperty + } + }), + ).RunTestWithBp(t, bp) + } else { + prepareForCcTest. + ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(test.err)). + RunTestWithBp(t, bp) + } + }) + } +} diff --git a/cc/compiler.go b/cc/compiler.go index 3c904b8f9..f9f7b6fd7 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -565,7 +565,7 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps 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/bionic.go b/cc/config/bionic.go index e87f5712b..a1e3851dc 100644 --- a/cc/config/bionic.go +++ b/cc/config/bionic.go @@ -15,6 +15,7 @@ package config type toolchainBionic struct { + toolchainBase } var ( @@ -29,6 +30,12 @@ func (toolchainBionic) Bionic() bool { return true } func (toolchainBionic) DefaultSharedLibraries() []string { return bionicDefaultSharedLibraries } +func (toolchainBionic) ShlibSuffix() string { return ".so" } + +func (toolchainBionic) ExecutableSuffix() string { return "" } + +func (toolchainBionic) AvailableLibraries() []string { return nil } + func (toolchainBionic) CrtBeginStaticBinary() []string { return bionicCrtBeginStaticBinary } func (toolchainBionic) CrtBeginSharedBinary() []string { return bionicCrtBeginSharedBinary } func (toolchainBionic) CrtBeginSharedLibrary() []string { return bionicCrtBeginSharedLibrary } diff --git a/cc/config/darwin_host.go b/cc/config/darwin_host.go index 5e3f7c7d6..01b1e635c 100644 --- a/cc/config/darwin_host.go +++ b/cc/config/darwin_host.go @@ -176,6 +176,8 @@ func getMacTools(ctx android.PathContext) *macPlatformTools { type toolchainDarwin struct { cFlags, ldFlags string toolchain64Bit + toolchainNoCrt + toolchainBase } type toolchainDarwinX86 struct { @@ -254,6 +256,10 @@ func (t *toolchainDarwin) ShlibSuffix() string { return ".dylib" } +func (t *toolchainDarwin) ExecutableSuffix() string { + return "" +} + func (t *toolchainDarwin) AvailableLibraries() []string { return darwinAvailableLibraries } diff --git a/cc/config/global.go b/cc/config/global.go index 357ea4437..a7701b950 100644 --- a/cc/config/global.go +++ b/cc/config/global.go @@ -290,7 +290,12 @@ var ( "-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", @@ -311,9 +316,6 @@ var ( "device/", "vendor/", } - - // Directories with warnings from Android.mk files. - WarningAllowedOldProjects = []string{} ) // BazelCcToolchainVars generates bzl file content containing variables for diff --git a/cc/config/tidy.go b/cc/config/tidy.go index 232e6865c..23bda664c 100644 --- a/cc/config/tidy.go +++ b/cc/config/tidy.go @@ -164,19 +164,21 @@ const tidyExternalVendor = "${config.TidyExternalVendorChecks}" const tidyDefaultNoAnalyzer = "${config.TidyDefaultGlobalChecks},-clang-analyzer-*" // This is a map of local path prefixes to the set of default clang-tidy checks -// to be used. +// to be used. This is like android.IsThirdPartyPath, but with more patterns. // The last matched local_path_prefix should be the most specific to be used. var DefaultLocalTidyChecks = []PathBasedTidyCheck{ {"external/", tidyExternalVendor}, - {"external/google", tidyDefault}, - {"external/webrtc", tidyDefault}, - {"external/googletest/", tidyExternalVendor}, {"frameworks/compile/mclinker/", tidyExternalVendor}, - {"hardware/qcom", tidyExternalVendor}, + {"hardware/", tidyExternalVendor}, + {"hardware/google/", tidyDefault}, + {"hardware/interfaces/", tidyDefault}, + {"hardware/ril/", tidyDefault}, + {"hardware/libhardware", tidyDefault}, // all 'hardware/libhardware*' {"vendor/", tidyExternalVendor}, - {"vendor/google", tidyDefault}, + {"vendor/google", tidyDefault}, // all 'vendor/google*' + {"vendor/google/external/", tidyExternalVendor}, {"vendor/google_arc/libs/org.chromium.arc.mojom", tidyExternalVendor}, - {"vendor/google_devices", tidyExternalVendor}, + {"vendor/google_devices/", tidyExternalVendor}, // many have vendor code } var reversedDefaultLocalTidyChecks = reverseTidyChecks(DefaultLocalTidyChecks) @@ -199,6 +201,13 @@ func TidyChecksForDir(dir string) string { return tidyDefault } +func NoClangTidyForDir(dir string) bool { + // 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 +} + // Returns a globally disabled tidy checks, overriding locally selected checks. func TidyGlobalNoChecks() string { if len(globalNoCheckList) > 0 { diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go index 253bb06d2..d9eaf533f 100644 --- a/cc/config/toolchain.go +++ b/cc/config/toolchain.go @@ -140,14 +140,6 @@ func (toolchainBase) ToolchainLdflags() string { return "" } -func (toolchainBase) ShlibSuffix() string { - return ".so" -} - -func (toolchainBase) ExecutableSuffix() string { - return "" -} - func (toolchainBase) Asflags() string { return "" } @@ -160,16 +152,14 @@ func (toolchainBase) LibclangRuntimeLibraryArch() string { return "" } -func (toolchainBase) AvailableLibraries() []string { - return nil -} +type toolchainNoCrt struct{} -func (toolchainBase) CrtBeginStaticBinary() []string { return nil } -func (toolchainBase) CrtBeginSharedBinary() []string { return nil } -func (toolchainBase) CrtBeginSharedLibrary() []string { return nil } -func (toolchainBase) CrtEndStaticBinary() []string { return nil } -func (toolchainBase) CrtEndSharedBinary() []string { return nil } -func (toolchainBase) CrtEndSharedLibrary() []string { return nil } +func (toolchainNoCrt) CrtBeginStaticBinary() []string { return nil } +func (toolchainNoCrt) CrtBeginSharedBinary() []string { return nil } +func (toolchainNoCrt) CrtBeginSharedLibrary() []string { return nil } +func (toolchainNoCrt) CrtEndStaticBinary() []string { return nil } +func (toolchainNoCrt) CrtEndSharedBinary() []string { return nil } +func (toolchainNoCrt) CrtEndSharedLibrary() []string { return nil } func (toolchainBase) DefaultSharedLibraries() []string { return nil @@ -188,7 +178,6 @@ func (toolchainBase) Musl() bool { } type toolchain64Bit struct { - toolchainBase } func (toolchain64Bit) Is64Bit() bool { @@ -196,7 +185,6 @@ func (toolchain64Bit) Is64Bit() bool { } type toolchain32Bit struct { - toolchainBase } func (toolchain32Bit) Is64Bit() bool { diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go index 4e8fd7752..1b126dea1 100644 --- a/cc/config/x86_linux_host.go +++ b/cc/config/x86_linux_host.go @@ -158,6 +158,7 @@ func init() { } type toolchainLinux struct { + toolchainBase cFlags, ldFlags string } @@ -247,9 +248,18 @@ func (t *toolchainLinux) AvailableLibraries() []string { return linuxAvailableLibraries } +func (toolchainLinux) ShlibSuffix() string { + return ".so" +} + +func (toolchainLinux) ExecutableSuffix() string { + return "" +} + // glibc specialization of the linux toolchain type toolchainGlibc struct { + toolchainNoCrt } func (toolchainGlibc) Glibc() bool { return true } diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go index 2c8321100..a33606f99 100644 --- a/cc/config/x86_windows_host.go +++ b/cc/config/x86_windows_host.go @@ -153,6 +153,8 @@ func init() { type toolchainWindows struct { cFlags, ldFlags string + toolchainBase + toolchainNoCrt } type toolchainWindowsX86 struct { diff --git a/cc/gen_test.go b/cc/gen_test.go index 40a571619..85df33312 100644 --- a/cc/gen_test.go +++ b/cc/gen_test.go @@ -74,4 +74,26 @@ func TestGen(t *testing.T) { }) + t.Run("sysprop", func(t *testing.T) { + ctx := testCc(t, ` + cc_library { + name: "libsysprop", + srcs: [ + "path/to/foo.sysprop", + ], + }`) + + outDir := "out/soong/.intermediates/libsysprop/android_arm64_armv8-a_static/gen" + syspropBuildParams := ctx.ModuleForTests("libsysprop", "android_arm64_armv8-a_static").Rule("sysprop") + + android.AssertStringEquals(t, "header output directory does not match", outDir+"/sysprop/include/path/to", syspropBuildParams.Args["headerOutDir"]) + android.AssertStringEquals(t, "public output directory does not match", outDir+"/sysprop/public/include/path/to", syspropBuildParams.Args["publicOutDir"]) + android.AssertStringEquals(t, "src output directory does not match", outDir+"/sysprop/path/to", syspropBuildParams.Args["srcOutDir"]) + android.AssertStringEquals(t, "output include name does not match", "path/to/foo.sysprop.h", syspropBuildParams.Args["includeName"]) + android.AssertStringEquals(t, "Input file does not match", "path/to/foo.sysprop", syspropBuildParams.Input.String()) + android.AssertStringEquals(t, "Output file does not match", outDir+"/sysprop/path/to/foo.sysprop.cpp", syspropBuildParams.Output.String()) + android.AssertStringListContains(t, "Implicit outputs does not contain header file", syspropBuildParams.ImplicitOutputs.Strings(), outDir+"/sysprop/include/path/to/foo.sysprop.h") + android.AssertStringListContains(t, "Implicit outputs does not contain public header file", syspropBuildParams.ImplicitOutputs.Strings(), outDir+"/sysprop/public/include/path/to/foo.sysprop.h") + android.AssertIntEquals(t, "Implicit outputs contains the incorrect number of elements", 2, len(syspropBuildParams.ImplicitOutputs.Strings())) + }) } diff --git a/cc/library.go b/cc/library.go index fc03fa2fb..93bb26a04 100644 --- a/cc/library.go +++ b/cc/library.go @@ -339,14 +339,15 @@ func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) { 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{ @@ -408,6 +409,8 @@ func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) { sharedTargetAttrs.Has_stubs.SetValue(&hasStubs) } + sharedTargetAttrs.Suffix = compilerAttrs.suffix + for axis, configToProps := range m.GetArchVariantProperties(ctx, &LibraryProperties{}) { for config, props := range configToProps { if props, ok := props.(*LibraryProperties); ok { @@ -1630,13 +1633,48 @@ func (library *libraryDecorator) coverageOutputFilePath() android.OptionalPath { return library.coverageOutputFile } +// pathForVndkRefAbiDump returns an OptionalPath representing the path of the +// reference abi dump for the given module. This is not guaranteed to be valid. +func pathForVndkRefAbiDump(ctx android.ModuleInstallPathContext, version, fileName string, + isNdk, isVndk, isGzip bool) android.OptionalPath { + + currentArchType := ctx.Arch().ArchType + primaryArchType := ctx.Config().DevicePrimaryArchType() + archName := currentArchType.String() + if currentArchType != primaryArchType { + archName += "_" + primaryArchType.String() + } + + var dirName string + if isNdk { + dirName = "ndk" + } else if isVndk { + dirName = "vndk" + } else { + dirName = "platform" // opt-in libs + } + + binderBitness := ctx.DeviceConfig().BinderBitness() + + var ext string + if isGzip { + ext = ".lsdump.gz" + } else { + ext = ".lsdump" + } + + return android.ExistentPathForSource(ctx, "prebuilts", "abi-dumps", dirName, + version, binderBitness, archName, "source-based", + fileName+ext) +} + func getRefAbiDumpFile(ctx ModuleContext, vndkVersion, fileName string) android.Path { // The logic must be consistent with classifySourceAbiDump. isNdk := ctx.isNdk(ctx.Config()) isVndk := ctx.useVndk() && ctx.isVndk() - refAbiDumpTextFile := android.PathForVndkRefAbiDump(ctx, vndkVersion, fileName, isNdk, isVndk, false) - refAbiDumpGzipFile := android.PathForVndkRefAbiDump(ctx, vndkVersion, fileName, isNdk, isVndk, true) + refAbiDumpTextFile := pathForVndkRefAbiDump(ctx, vndkVersion, fileName, isNdk, isVndk, false) + refAbiDumpGzipFile := pathForVndkRefAbiDump(ctx, vndkVersion, fileName, isNdk, isVndk, true) if refAbiDumpTextFile.Valid() { if refAbiDumpGzipFile.Valid() { @@ -1653,12 +1691,12 @@ func getRefAbiDumpFile(ctx ModuleContext, vndkVersion, fileName string) android. return nil } -func prevDumpRefVersion(ctx ModuleContext) string { +func prevDumpRefVersion(ctx ModuleContext) int { sdkVersionInt := ctx.Config().PlatformSdkVersion().FinalInt() sdkVersionStr := ctx.Config().PlatformSdkVersion().String() if ctx.Config().PlatformSdkFinal() { - return strconv.Itoa(sdkVersionInt - 1) + return sdkVersionInt - 1 } else { var dirName string @@ -1674,9 +1712,9 @@ func prevDumpRefVersion(ctx ModuleContext) string { // This situation could be identified by checking the existence of the PLATFORM_SDK_VERION dump directory. refDumpDir := android.ExistentPathForSource(ctx, "prebuilts", "abi-dumps", dirName, sdkVersionStr) if refDumpDir.Valid() { - return sdkVersionStr + return sdkVersionInt } else { - return strconv.Itoa(sdkVersionInt - 1) + return sdkVersionInt - 1 } } } @@ -1684,7 +1722,7 @@ func prevDumpRefVersion(ctx ModuleContext) string { func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objects, fileName string, soFile android.Path) { if library.sabi.shouldCreateSourceAbiDump() { var version string - var prevVersion string + var prevVersion int if ctx.useVndk() { // For modules linking against vndk, follow its vndk version @@ -1716,12 +1754,13 @@ func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objec addLsdumpPath(classifySourceAbiDump(ctx) + ":" + library.sAbiOutputFile.String()) - if prevVersion != "" { - prevRefAbiDumpFile := getRefAbiDumpFile(ctx, prevVersion, fileName) + // If NDK or PLATFORM library, check against previous version ABI. + if !ctx.useVndk() { + prevRefAbiDumpFile := getRefAbiDumpFile(ctx, strconv.Itoa(prevVersion), fileName) if prevRefAbiDumpFile != nil { library.prevSAbiDiff = sourceAbiDiff(ctx, library.sAbiOutputFile.Path(), - prevRefAbiDumpFile, fileName, prevVersion, exportedHeaderFlags, - library.Properties.Header_abi_checker.Diff_flags, + prevRefAbiDumpFile, fileName, exportedHeaderFlags, + library.Properties.Header_abi_checker.Diff_flags, prevVersion, Bool(library.Properties.Header_abi_checker.Check_all_apis), ctx.IsLlndk(), ctx.isNdk(ctx.Config()), ctx.IsVndkExt(), true) } @@ -1730,8 +1769,9 @@ func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objec refAbiDumpFile := getRefAbiDumpFile(ctx, version, fileName) if refAbiDumpFile != nil { library.sAbiDiff = sourceAbiDiff(ctx, library.sAbiOutputFile.Path(), - refAbiDumpFile, fileName, "", exportedHeaderFlags, + refAbiDumpFile, fileName, exportedHeaderFlags, library.Properties.Header_abi_checker.Diff_flags, + /* unused if not previousVersionDiff */ 0, Bool(library.Properties.Header_abi_checker.Check_all_apis), ctx.IsLlndk(), ctx.isNdk(ctx.Config()), ctx.IsVndkExt(), false) } @@ -2647,6 +2687,8 @@ func sharedOrStaticLibraryBp2Build(ctx android.TopDownMutatorContext, module *Mo }, Features: baseAttributes.features, + + Suffix: compilerAttrs.suffix, } if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 { hasStubs := true @@ -2729,6 +2771,8 @@ type bazelCcLibrarySharedAttributes struct { Has_stubs bazel.BoolAttribute Inject_bssl_hash bazel.BoolAttribute + + Suffix bazel.StringAttribute } type bazelCcStubSuiteAttributes struct { diff --git a/cc/library_stub.go b/cc/library_stub.go index fa6c27950..2ebb6efa1 100644 --- a/cc/library_stub.go +++ b/cc/library_stub.go @@ -17,7 +17,6 @@ package cc import ( "android/soong/android" "android/soong/multitree" - "strings" ) func init() { @@ -25,8 +24,10 @@ func init() { } func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) { - // cc_api_stub_library shares a lot of ndk_library, and this will be refactored later 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) } @@ -81,6 +82,14 @@ func (d *apiLibraryDecorator) Name(basename string) string { } func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path { + // Export headers as system include dirs if specified. Mostly for libc + if Bool(d.libraryDecorator.Properties.Llndk.Export_headers_as_system) { + d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs = append( + d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs, + d.libraryDecorator.flagExporter.Properties.Export_include_dirs...) + d.libraryDecorator.flagExporter.Properties.Export_include_dirs = nil + } + // Flags reexported from dependencies. (e.g. vndk_prebuilt_shared) d.libraryDecorator.flagExporter.exportIncludes(ctx) d.libraryDecorator.reexportDirs(deps.ReexportedDirs...) @@ -114,9 +123,51 @@ func (d *apiLibraryDecorator) availableFor(what string) bool { return true } -func (d *apiLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags { - d.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(), multitree.GetApiImportSuffix()) - return d.libraryDecorator.linkerFlags(ctx, flags) +// 'cc_api_headers' is similar with 'cc_api_library', but which replaces +// header libraries. The module will replace any dependencies to existing +// original header libraries. +type apiHeadersDecorator struct { + *libraryDecorator +} + +func CcApiHeadersFactory() android.Module { + module, decorator := NewLibrary(android.DeviceSupported) + apiHeadersDecorator := &apiHeadersDecorator{ + libraryDecorator: decorator, + } + apiHeadersDecorator.HeaderOnly() + + module.stl = nil + module.sanitize = nil + decorator.disableStripping() + + module.compiler = nil + module.linker = apiHeadersDecorator + module.installer = nil + + // Mark module as stub, so APEX would not include this stub in the package. + module.library.setBuildStubs(true) + + // Prevent default system libs (libc, libm, and libdl) from being linked + if apiHeadersDecorator.baseLinker.Properties.System_shared_libs == nil { + apiHeadersDecorator.baseLinker.Properties.System_shared_libs = []string{} + } + + apiHeadersDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true) + apiHeadersDecorator.baseLinker.Properties.Nocrt = BoolPtr(true) + + module.Init() + + return module +} + +func (d *apiHeadersDecorator) Name(basename string) string { + return basename + multitree.GetApiImportSuffix() +} + +func (d *apiHeadersDecorator) availableFor(what string) bool { + // Stub from API surface should be available for any APEX. + return true } func CcApiStubLibraryFactory() android.Module { diff --git a/cc/library_stub_test.go b/cc/library_stub_test.go index c2ac941dd..cd061722e 100644 --- a/cc/library_stub_test.go +++ b/cc/library_stub_test.go @@ -216,3 +216,112 @@ func TestApiLibraryShouldNotReplaceWithoutApiImport(t *testing.T) { android.AssertBoolEquals(t, "original library should be linked", true, hasDirectDependency(t, ctx, libfoo, libbar)) android.AssertBoolEquals(t, "Stub library from API surface should not be linked", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport)) } + +func TestApiHeaderReplacesExistingModule(t *testing.T) { + bp := ` + cc_library { + name: "libfoo", + header_libs: ["libfoo_headers"], + } + + cc_api_library { + name: "libfoo", + header_libs: ["libfoo_headers"], + src: "libfoo.so", + } + + cc_library_headers { + name: "libfoo_headers", + } + + cc_api_headers { + name: "libfoo_headers", + } + + api_imports { + name: "api_imports", + shared_libs: [ + "libfoo", + ], + header_libs: [ + "libfoo_headers", + ], + } + ` + + ctx := prepareForCcTest.RunTestWithBp(t, bp) + + libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module() + libfooApiImport := ctx.ModuleForTests("libfoo.apiimport", "android_arm64_armv8-a_shared").Module() + libfooHeader := ctx.ModuleForTests("libfoo_headers", "android_arm64_armv8-a").Module() + libfooHeaderApiImport := ctx.ModuleForTests("libfoo_headers.apiimport", "android_arm64_armv8-a").Module() + + android.AssertBoolEquals(t, "original header should not be used for original library", false, hasDirectDependency(t, ctx, libfoo, libfooHeader)) + android.AssertBoolEquals(t, "Header from API surface should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport)) + android.AssertBoolEquals(t, "original header should not be used for library imported from API surface", false, hasDirectDependency(t, ctx, libfooApiImport, libfooHeader)) + android.AssertBoolEquals(t, "Header from API surface should be used for library imported from API surface", true, hasDirectDependency(t, ctx, libfooApiImport, libfooHeaderApiImport)) +} + +func TestApiHeadersDoNotRequireOriginalModule(t *testing.T) { + bp := ` + cc_library { + name: "libfoo", + header_libs: ["libfoo_headers"], + } + + cc_api_headers { + name: "libfoo_headers", + } + + api_imports { + name: "api_imports", + shared_libs: [ + "libfoo", + ], + header_libs: [ + "libfoo_headers", + ], + } + ` + + ctx := prepareForCcTest.RunTestWithBp(t, bp) + + libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module() + libfooHeaderApiImport := ctx.ModuleForTests("libfoo_headers.apiimport", "android_arm64_armv8-a").Module() + + android.AssertBoolEquals(t, "Header from API surface should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport)) +} + +func TestApiHeadersShouldNotReplaceWithoutApiImport(t *testing.T) { + bp := ` + cc_library { + name: "libfoo", + header_libs: ["libfoo_headers"], + } + + cc_library_headers { + name: "libfoo_headers", + } + + cc_api_headers { + name: "libfoo_headers", + } + + api_imports { + name: "api_imports", + shared_libs: [ + "libfoo", + ], + header_libs: [], + } + ` + + ctx := prepareForCcTest.RunTestWithBp(t, bp) + + libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module() + libfooHeader := ctx.ModuleForTests("libfoo_headers", "android_arm64_armv8-a").Module() + libfooHeaderApiImport := ctx.ModuleForTests("libfoo_headers.apiimport", "android_arm64_armv8-a").Module() + + android.AssertBoolEquals(t, "original header should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeader)) + android.AssertBoolEquals(t, "Header from API surface should not be used for original library", false, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport)) +} @@ -101,6 +101,7 @@ func (lto *lto) flags(ctx BaseModuleContext, flags Flags) Flags { } 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) @@ -140,12 +141,13 @@ func (lto *lto) DefaultThinLTO(ctx BaseModuleContext) bool { lib32 := ctx.Arch().ArchType.Multilib == "lib32" // CFI enables full LTO. cfi := ctx.isCfi() - // Performance and binary size are less important for host binaries. + // Performance and binary size are less important for host binaries and tests. host := ctx.Host() + test := ctx.testBinary() || ctx.testLibrary() // FIXME: ThinLTO for VNDK produces different output. // b/169217596 vndk := ctx.isVndk() - return GlobalThinLTO(ctx) && !lto.Never() && !lib32 && !cfi && !host && !vndk + return GlobalThinLTO(ctx) && !lto.Never() && !lib32 && !cfi && !host && !test && !vndk } func (lto *lto) FullLTO() bool { diff --git a/cc/lto_test.go b/cc/lto_test.go new file mode 100644 index 000000000..b52f2b6a3 --- /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 815443626..de8a8f21c 100644 --- a/cc/makevars.go +++ b/cc/makevars.go @@ -53,7 +53,6 @@ func makeStringOfKeys(ctx android.MakeVarsContext, key android.OnceKey) string { 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 { diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go index ef38a064a..5e0694880 100644 --- a/cc/ndk_headers.go +++ b/cc/ndk_headers.go @@ -19,8 +19,10 @@ import ( "path/filepath" "github.com/google/blueprint" + "github.com/google/blueprint/proptools" "android/soong/android" + "android/soong/bazel" ) var ( @@ -79,6 +81,7 @@ type headerProperties struct { type headerModule struct { android.ModuleBase + android.BazelModuleBase properties headerProperties @@ -144,6 +147,47 @@ func (m *headerModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { } } +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 + Include_dir *string +} + +func createCcApiHeadersTarget(ctx android.TopDownMutatorContext, includes []string, excludes []string, include_dir *string) { + props := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_api_headers", + Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl", + } + attrs := &bazelCcApiHeadersAttributes{ + Hdrs: bazel.MakeLabelListAttribute( + android.BazelLabelForModuleSrcExcludes( + ctx, + includes, + excludes, + ), + ), + Include_dir: include_dir, + } + ctx.CreateBazelTargetModule(props, android.CommonAttributes{ + Name: apiContributionTargetName(ctx.ModuleName()), + }, attrs) +} + +func (h *headerModule) ConvertWithBp2build(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) +} + // ndk_headers installs the sets of ndk headers defined in the srcs property // to the sysroot base + "usr/include" + to directory + directory component. // ndk_headers requires the license file to be specified. Example: @@ -158,6 +202,7 @@ func ndkHeadersFactory() android.Module { module := &headerModule{} module.AddProperties(&module.properties) android.InitAndroidModule(module) + android.InitBazelModule(module) return module } @@ -190,6 +235,7 @@ type versionedHeaderProperties struct { // Note that this is really only built to handle bionic/libc/include. type versionedHeaderModule struct { android.ModuleBase + android.BazelModuleBase properties versionedHeaderProperties @@ -197,6 +243,11 @@ type versionedHeaderModule struct { licensePath android.Path } +// Return the glob pattern to find all .h files beneath `dir` +func headerGlobPattern(dir string) string { + return filepath.Join(dir, "**", "*.h") +} + func (m *versionedHeaderModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { if String(m.properties.License) == "" { ctx.PropertyErrorf("license", "field is required") @@ -206,7 +257,7 @@ func (m *versionedHeaderModule) GenerateAndroidBuildActions(ctx android.ModuleCo fromSrcPath := android.PathForModuleSrc(ctx, String(m.properties.From)) toOutputPath := getCurrentIncludePath(ctx).Join(ctx, String(m.properties.To)) - srcFiles := ctx.GlobFiles(filepath.Join(fromSrcPath.String(), "**/*.h"), nil) + srcFiles := ctx.GlobFiles(headerGlobPattern(fromSrcPath.String()), nil) var installPaths []android.WritablePath for _, header := range srcFiles { installDir := getHeaderInstallDir(ctx, header, String(m.properties.From), String(m.properties.To)) @@ -222,6 +273,13 @@ func (m *versionedHeaderModule) GenerateAndroidBuildActions(ctx android.ModuleCo processHeadersWithVersioner(ctx, fromSrcPath, toOutputPath, srcFiles, installPaths) } +func (h *versionedHeaderModule) ConvertWithBp2build(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 + createCcApiHeadersTarget(ctx, []string{includePattern}, []string{}, h.properties.From) +} + func processHeadersWithVersioner(ctx android.ModuleContext, srcDir, outDir android.Path, srcFiles android.Paths, installPaths []android.WritablePath) android.Path { // The versioner depends on a dependencies directory to simplify determining include paths @@ -271,16 +329,19 @@ func versionedNdkHeadersFactory() android.Module { module.AddProperties(&module.properties) android.InitAndroidModule(module) + android.InitBazelModule(module) return module } -// preprocessed_ndk_header { -// name: "foo", -// preprocessor: "foo.sh", -// srcs: [...], -// to: "android", -// } +// preprocessed_ndk_header { +// +// name: "foo", +// preprocessor: "foo.sh", +// srcs: [...], +// to: "android", +// +// } // // Will invoke the preprocessor as: // diff --git a/cc/ndk_library.go b/cc/ndk_library.go index 2bbfc4aee..e2b968296 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -84,11 +84,13 @@ var ( // // Example: // -// ndk_library { -// name: "libfoo", -// symbol_file: "libfoo.map.txt", -// first_version: "9", -// } +// ndk_library { +// +// name: "libfoo", +// symbol_file: "libfoo.map.txt", +// first_version: "9", +// +// } type libraryProperties struct { // Relative path to the symbol map. // An example file can be seen here: TODO(danalbert): Make an example. @@ -109,6 +111,9 @@ type libraryProperties struct { // where it is enabled pending a fix for http://b/190554910 (no debug info // for asm implemented symbols). Allow_untyped_symbols *bool + + // Headers presented by this library to the Public API Surface + Export_header_libs []string } type stubDecorator struct { @@ -483,8 +488,11 @@ func (c *stubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) O return objs } +// Add a dependency on the header modules of this ndk_library func (linker *stubDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps { - return Deps{} + return Deps{ + HeaderLibs: linker.properties.Export_header_libs, + } } func (linker *stubDecorator) Name(name string) string { diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go index 6c200f5dd..622558edf 100644 --- a/cc/ndk_sysroot.go +++ b/cc/ndk_sysroot.go @@ -57,15 +57,18 @@ import ( ) func init() { - android.RegisterModuleType("ndk_headers", ndkHeadersFactory) - android.RegisterModuleType("ndk_library", NdkLibraryFactory) - android.RegisterModuleType("versioned_ndk_headers", versionedNdkHeadersFactory) - android.RegisterModuleType("preprocessed_ndk_headers", preprocessedNdkHeadersFactory) - android.RegisterSingletonType("ndk", NdkSingleton) - + RegisterNdkModuleTypes(android.InitRegistrationContext) pctx.Import("android/soong/android") } +func RegisterNdkModuleTypes(ctx android.RegistrationContext) { + ctx.RegisterModuleType("ndk_headers", ndkHeadersFactory) + ctx.RegisterModuleType("ndk_library", NdkLibraryFactory) + ctx.RegisterModuleType("versioned_ndk_headers", versionedNdkHeadersFactory) + ctx.RegisterModuleType("preprocessed_ndk_headers", preprocessedNdkHeadersFactory) + ctx.RegisterSingletonType("ndk", NdkSingleton) +} + func getNdkInstallBase(ctx android.PathContext) android.InstallPath { return android.PathForNdkInstall(ctx) } diff --git a/cc/ndk_test.go b/cc/ndk_test.go new file mode 100644 index 000000000..f20d3c61f --- /dev/null +++ b/cc/ndk_test.go @@ -0,0 +1,56 @@ +// 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 cc + +import ( + "testing" + + "github.com/google/blueprint" + + "android/soong/android" +) + +func TestNdkHeaderDependency(t *testing.T) { + isDep := func(ctx *android.TestResult, from, toExpected android.Module) bool { + foundDep := false + ctx.VisitDirectDeps(from, func(toActual blueprint.Module) { + if toExpected.Name() == toActual.Name() { + foundDep = true + } + }) + return foundDep + } + bp := ` + ndk_library { + name: "libfoo", + first_version: "29", + symbol_file: "libfoo.map.txt", + export_header_libs: ["libfoo_headers"], + } + ndk_headers { + name: "libfoo_headers", + srcs: ["foo.h"], + license: "NOTICE", + } + //This module is needed since Soong creates a dep edge on source + cc_library { + name: "libfoo", + } + ` + ctx := prepareForCcTest.RunTestWithBp(t, bp) + libfoo := ctx.ModuleForTests("libfoo.ndk", "android_arm64_armv8-a_sdk_shared") + libfoo_headers := ctx.ModuleForTests("libfoo_headers", "") + android.AssertBoolEquals(t, "Could not find headers of ndk_library", true, isDep(ctx, libfoo.Module(), libfoo_headers.Module())) +} diff --git a/cc/proto.go b/cc/proto.go index 8e6d5ed5f..cf5ed04f2 100644 --- a/cc/proto.go +++ b/cc/proto.go @@ -178,7 +178,7 @@ func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs baze 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 @@ func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs baze 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 86472a2cc..436b14913 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -77,6 +77,7 @@ var ( "-fno-sanitize-recover=integer,undefined"} hwasanGlobalOptions = []string{"heap_history_size=1023", "stack_history_size=512", "export_memory_stats=0", "max_malloc_fill_size=4096", "malloc_fill_byte=0"} + memtagStackCommonFlags = []string{"-march=armv8-a+memtag"} ) type SanitizerType int @@ -89,6 +90,7 @@ const ( scs Fuzzer Memtag_heap + Memtag_stack cfi // cfi is last to prevent it running before incompatible mutators ) @@ -100,6 +102,7 @@ var Sanitizers = []SanitizerType{ scs, Fuzzer, Memtag_heap, + Memtag_stack, cfi, // cfi is last to prevent it running before incompatible mutators } @@ -120,6 +123,8 @@ func (t SanitizerType) variationName() string { return "scs" case Memtag_heap: return "memtag_heap" + case Memtag_stack: + return "memtag_stack" case Fuzzer: return "fuzzer" default: @@ -136,6 +141,8 @@ func (t SanitizerType) name() string { return "hwaddress" case Memtag_heap: return "memtag_heap" + case Memtag_stack: + return "memtag_stack" case tsan: return "thread" case intOverflow: @@ -157,7 +164,7 @@ func (t SanitizerType) registerMutators(ctx android.RegisterMutatorsContext) { sanitizer := &sanitizerSplitMutator{t} ctx.TopDown(t.variationName()+"_markapexes", sanitizer.markSanitizableApexesMutator) ctx.Transition(t.variationName(), sanitizer) - case Memtag_heap, intOverflow: + case Memtag_heap, Memtag_stack, intOverflow: // do nothing default: panic(fmt.Errorf("unknown SanitizerType %d", t)) @@ -182,6 +189,8 @@ func (*Module) SanitizerSupported(t SanitizerType) bool { return true case Memtag_heap: return true + case Memtag_stack: + return true default: return false } @@ -233,6 +242,9 @@ type SanitizeUserProps struct { // Memory-tagging, only available on arm64 // if diag.memtag unset or false, enables async memory tagging Memtag_heap *bool `android:"arch_variant"` + // Memory-tagging stack instrumentation, only available on arm64 + // Adds instrumentation to detect stack buffer overflows and use-after-scope using MTE. + Memtag_stack *bool `android:"arch_variant"` // A modifier for ASAN and HWASAN for write only instrumentation Writeonly *bool `android:"arch_variant"` @@ -318,7 +330,7 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { return } - // cc_test targets default to SYNC MemTag unless explicitly set to ASYNC (via diag: {memtag_heap}). + // cc_test targets default to SYNC MemTag unless explicitly set to ASYNC (via diag: {memtag_heap: false}). if ctx.testBinary() { if s.Memtag_heap == nil { s.Memtag_heap = proptools.BoolPtr(true) @@ -404,6 +416,10 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { } } + if found, globalSanitizers = removeFromList("memtag_stack", globalSanitizers); found && s.Memtag_stack == nil { + s.Memtag_stack = proptools.BoolPtr(true) + } + if len(globalSanitizers) > 0 { ctx.ModuleErrorf("unknown global sanitizer option %s", globalSanitizers[0]) } @@ -470,14 +486,19 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { } // Memtag_heap is only implemented on AArch64. - if ctx.Arch().ArchType != android.Arm64 || !ctx.toolchain().Bionic() { + // Memtag ABI is Android specific for now, so disable for host. + if ctx.Arch().ArchType != android.Arm64 || !ctx.toolchain().Bionic() || ctx.Host() { s.Memtag_heap = nil + s.Memtag_stack = nil } // Also disable CFI if ASAN is enabled. if Bool(s.Address) || Bool(s.Hwaddress) { s.Cfi = nil s.Diag.Cfi = nil + // HWASAN and ASAN win against MTE. + s.Memtag_heap = nil + s.Memtag_stack = nil } // Disable sanitizers that depend on the UBSan runtime for windows/darwin builds. @@ -534,7 +555,7 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { if ctx.Os() != android.Windows && (Bool(s.All_undefined) || Bool(s.Undefined) || Bool(s.Address) || Bool(s.Thread) || Bool(s.Fuzzer) || Bool(s.Safestack) || Bool(s.Cfi) || Bool(s.Integer_overflow) || len(s.Misc_undefined) > 0 || - Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs) || Bool(s.Memtag_heap)) { + Bool(s.Scudo) || Bool(s.Hwaddress) || Bool(s.Scs) || Bool(s.Memtag_heap) || Bool(s.Memtag_stack)) { sanitize.Properties.SanitizerEnabled = true } @@ -691,6 +712,25 @@ func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags { } } + 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() { + if Bool(sanitize.Properties.Sanitize.Diag.Memtag_heap) { + flags.Local.LdFlags = append(flags.Local.LdFlags, "-fsanitize-memtag-mode=sync") + } else { + flags.Local.LdFlags = append(flags.Local.LdFlags, "-fsanitize-memtag-mode=async") + } + } + if Bool(sanitize.Properties.Sanitize.Integer_overflow) { flags.Local.CFlags = append(flags.Local.CFlags, intOverflowCflags...) } @@ -804,6 +844,8 @@ func (sanitize *sanitize) getSanitizerBoolPtr(t SanitizerType) *bool { return sanitize.Properties.Sanitize.Scs case Memtag_heap: return sanitize.Properties.Sanitize.Memtag_heap + case Memtag_stack: + return sanitize.Properties.Sanitize.Memtag_stack case Fuzzer: return sanitize.Properties.Sanitize.Fuzzer default: @@ -819,6 +861,7 @@ func (sanitize *sanitize) isUnsanitizedVariant() bool { !sanitize.isSanitizerEnabled(cfi) && !sanitize.isSanitizerEnabled(scs) && !sanitize.isSanitizerEnabled(Memtag_heap) && + !sanitize.isSanitizerEnabled(Memtag_stack) && !sanitize.isSanitizerEnabled(Fuzzer) } @@ -850,6 +893,8 @@ func (sanitize *sanitize) SetSanitizer(t SanitizerType, b bool) { sanitize.Properties.Sanitize.Scs = bPtr case Memtag_heap: sanitize.Properties.Sanitize.Memtag_heap = bPtr + case Memtag_stack: + sanitize.Properties.Sanitize.Memtag_stack = bPtr case Fuzzer: sanitize.Properties.Sanitize.Fuzzer = bPtr default: @@ -1311,23 +1356,11 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { } if Bool(c.sanitize.Properties.Sanitize.Memtag_heap) && c.Binary() { - noteDep := "note_memtag_heap_async" - if Bool(c.sanitize.Properties.Sanitize.Diag.Memtag_heap) { - noteDep = "note_memtag_heap_sync" - } - // If we're using snapshots, redirect to snapshot whenever possible - // TODO(b/178470649): clean manual snapshot redirections - snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo) - if lib, ok := snapshot.StaticLibs[noteDep]; ok { - noteDep = lib - } - depTag := StaticDepTag(true) - variations := append(mctx.Target().Variations(), - blueprint.Variation{Mutator: "link", Variation: "static"}) - if c.Device() { - variations = append(variations, c.ImageVariation()) - } - mctx.AddFarVariationDependencies(variations, depTag, noteDep) + sanitizers = append(sanitizers, "memtag-heap") + } + + if Bool(c.sanitize.Properties.Sanitize.Memtag_stack) { + sanitizers = append(sanitizers, "memtag-stack") } if Bool(c.sanitize.Properties.Sanitize.Fuzzer) { diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go index 5d7e7d80a..48ac6507d 100644 --- a/cc/sanitize_test.go +++ b/cc/sanitize_test.go @@ -344,19 +344,13 @@ func (t MemtagNoteType) str() string { func checkHasMemtagNote(t *testing.T, m android.TestingModule, expected MemtagNoteType) { t.Helper() - note_async := "note_memtag_heap_async" - note_sync := "note_memtag_heap_sync" found := None - implicits := m.Rule("ld").Implicits - for _, lib := range implicits { - if strings.Contains(lib.Rel(), note_async) { - found = Async - break - } else if strings.Contains(lib.Rel(), note_sync) { - found = Sync - break - } + ldFlags := m.Rule("ld").Args["ldFlags"] + if strings.Contains(ldFlags, "-fsanitize-memtag-mode=async") { + found = Async + } else if strings.Contains(ldFlags, "-fsanitize-memtag-mode=sync") { + found = Sync } if found != expected { diff --git a/cc/sysprop.go b/cc/sysprop.go deleted file mode 100644 index f578b507a..000000000 --- a/cc/sysprop.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (C) 2019 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 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" -) - -type syspropLibraryInterface interface { - BaseModuleName() string - CcImplementationModuleName() string -} - -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) -} - -// 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() - - // BaseModuleName is the name of sysprop_library - // CcImplementationModuleName is the name of cc_library generated by sysprop_library - syspropImplLibraries[m.BaseModuleName()] = m.CcImplementationModuleName() - } -} diff --git a/cc/test.go b/cc/test.go index f5abc454d..28a0e5ebf 100644 --- a/cc/test.go +++ b/cc/test.go @@ -22,6 +22,7 @@ import ( "github.com/google/blueprint/proptools" "android/soong/android" + "android/soong/bazel" "android/soong/tradefed" ) @@ -133,7 +134,7 @@ func init() { // specific functionality on a device. The executable binary gets an implicit // static_libs dependency on libgtests unless the gtest flag is set to false. func TestFactory() android.Module { - module := NewTest(android.HostAndDeviceSupported) + module := NewTest(android.HostAndDeviceSupported, true) return module.Init() } @@ -156,7 +157,7 @@ func BenchmarkFactory() android.Module { // cc_test_host compiles a test host binary. func TestHostFactory() android.Module { - module := NewTest(android.HostSupported) + module := NewTest(android.HostSupported, true) return module.Init() } @@ -204,6 +205,10 @@ func (test *testBinary) unsetSrc() { test.binaryDecorator.Properties.Stem = StringPtr("") } +func (test *testBinary) testBinary() bool { + return true +} + var _ testPerSrc = (*testBinary)(nil) func TestPerSrcMutator(mctx android.BottomUpMutatorContext) { @@ -257,16 +262,10 @@ func (test *testDecorator) gtest() bool { } func (test *testDecorator) isolated(ctx BaseModuleContext) bool { - if !ctx.Windows() { - return BoolDefault(test.LinkerProperties.Isolated, false) - } return BoolDefault(test.LinkerProperties.Isolated, false) } -func (test *testDecorator) testBinary() bool { - return true -} - +// NOTE: Keep this in sync with cc/cc_test.bzl#gtest_copts func (test *testDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags { if !test.gtest() { return flags @@ -480,8 +479,8 @@ func (test *testBinary) install(ctx ModuleContext, file android.Path) { test.binaryDecorator.baseInstaller.install(ctx, file) } -func NewTest(hod android.HostOrDeviceSupported) *Module { - module, binary := newBinary(hod, false) +func NewTest(hod android.HostOrDeviceSupported, bazelable bool) *Module { + module, binary := newBinary(hod, bazelable) module.multilib = android.MultilibBoth binary.baseInstaller = NewTestInstaller() @@ -504,6 +503,10 @@ type testLibrary struct { *libraryDecorator } +func (test *testLibrary) testLibrary() bool { + return true +} + func (test *testLibrary) linkerProps() []interface{} { var props []interface{} props = append(props, test.testDecorator.linkerProps()...) @@ -543,6 +546,7 @@ func NewTestLibrary(hod android.HostOrDeviceSupported) *Module { } module.linker = test module.installer = test + module.bazelable = true return module } @@ -632,3 +636,60 @@ func NewBenchmark(hod android.HostOrDeviceSupported) *Module { module.installer = benchmark return module } + +// binaryAttributes contains Bazel attributes corresponding to a cc test +type testBinaryAttributes struct { + binaryAttributes + + Gtest bool + Isolated bool +} + +// testBinaryBp2build is the bp2build converter for cc_test modules. A cc_test's +// dependency graph and compilation/linking steps are functionally similar to a +// cc_binary, but has additional dependencies on test deps like gtest, and +// produces additional runfiles like XML plans for Tradefed orchestration +// +// TODO(b/244432609): handle `isolated` property. +// TODO(b/244432134): handle custom runpaths for tests that assume runfile layouts not +// default to bazel. (see linkerInit function) +// TODO(b/244432500): handle test.testConfig generation (see install function) +func testBinaryBp2build(ctx android.TopDownMutatorContext, m *Module) { + var testBinaryAttrs testBinaryAttributes + testBinaryAttrs.binaryAttributes = binaryBp2buildAttrs(ctx, m) + + var data bazel.LabelListAttribute + + testBinaryProps := m.GetArchVariantProperties(ctx, &TestBinaryProperties{}) + for axis, configToProps := range testBinaryProps { + for config, props := range configToProps { + if p, ok := props.(*TestBinaryProperties); ok { + // Combine data, data_bins and data_libs into a single 'data' attribute. + var combinedData bazel.LabelList + combinedData.Append(android.BazelLabelForModuleSrc(ctx, p.Data)) + combinedData.Append(android.BazelLabelForModuleDeps(ctx, p.Data_bins)) + combinedData.Append(android.BazelLabelForModuleDeps(ctx, p.Data_libs)) + data.SetSelectValue(axis, config, combinedData) + } + } + } + + for _, propIntf := range m.GetProperties() { + if testLinkerProps, ok := propIntf.(*TestLinkerProperties); ok { + testBinaryAttrs.Gtest = proptools.BoolDefault(testLinkerProps.Gtest, true) + testBinaryAttrs.Isolated = proptools.BoolDefault(testLinkerProps.Isolated, true) + break + } + } + + ctx.CreateBazelTargetModule( + bazel.BazelTargetModuleProperties{ + Rule_class: "cc_test", + Bzl_load_location: "//build/bazel/rules/cc:cc_test.bzl", + }, + android.CommonAttributes{ + Name: m.Name(), + Data: data, + }, + &testBinaryAttrs) +} diff --git a/cc/testing.go b/cc/testing.go index 44a865d2a..e42b9fab7 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -41,6 +41,7 @@ func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) { ctx.RegisterModuleType("ndk_prebuilt_static_stl", NdkPrebuiltStaticStlFactory) ctx.RegisterModuleType("ndk_prebuilt_object", NdkPrebuiltObjectFactory) ctx.RegisterModuleType("ndk_library", NdkLibraryFactory) + ctx.RegisterModuleType("ndk_headers", ndkHeadersFactory) } func GatherRequiredDepsForTest(oses ...android.OsType) string { diff --git a/cc/tidy.go b/cc/tidy.go index 6b5d5728c..082cf88b3 100644 --- a/cc/tidy.go +++ b/cc/tidy.go @@ -76,7 +76,11 @@ func (tidy *tidyFeature) flags(ctx ModuleContext, flags Flags) Flags { 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) { + return flags + } // If not explicitly disabled, set flags.Tidy to generate .tidy rules. // Note that libraries and binaries will depend on .tidy files ONLY if // the global WITH_TIDY or module 'tidy' property is true. diff --git a/cmd/extract_apks/main.go b/cmd/extract_apks/main.go index 1cf64de8b..c420567e4 100644 --- a/cmd/extract_apks/main.go +++ b/cmd/extract_apks/main.go @@ -29,6 +29,7 @@ import ( "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 @@ func (apkSet *ApkSet) getToc() (Toc, error) { 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 @@ type multiAbiTargetingMatcher struct { *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 @@ func (t multiAbiTargetingMatcher) matches(config TargetConfig) bool { 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 + } + + // 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 highestPriority == 0 { + + 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 f5e40466a..c1d712df4 100644 --- a/cmd/extract_apks/main_test.go +++ b/cmd/extract_apks/main_test.go @@ -420,6 +420,370 @@ bundletool { } } +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/soong_build/main.go b/cmd/soong_build/main.go index 693094357..0b8cc8864 100644 --- a/cmd/soong_build/main.go +++ b/cmd/soong_build/main.go @@ -84,6 +84,8 @@ func init() { 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") + flag.BoolVar(&cmdlineArgs.BazelMode, "bazel-mode", false, "use bazel for analysis of certain modules") + flag.BoolVar(&cmdlineArgs.BazelModeDev, "bazel-mode-dev", false, "use bazel for analysis of a large number of modules (less stable)") // Flags that probably shouldn't be flags of soong_build but we haven't found // the time to remove them yet @@ -131,6 +133,10 @@ func newConfig(availableEnv map[string]string) android.Config { buildMode = android.GenerateModuleGraph } else if docFile != "" { buildMode = android.GenerateDocFile + } else if cmdlineArgs.BazelModeDev { + buildMode = android.BazelDevMode + } else if cmdlineArgs.BazelMode { + buildMode = android.BazelProdMode } else { buildMode = android.AnalysisNoBazel } @@ -234,7 +240,7 @@ func writeDepFile(outputFile string, eventHandler metrics.EventHandler, ninjaDep // doChosenActivity runs Soong for a specific activity, like bp2build, queryview // or the actual Soong build for the build.ninja file. Returns the top level // output file of the specific activity. -func doChosenActivity(ctx *android.Context, configuration android.Config, extraNinjaDeps []string, logDir string) string { +func doChosenActivity(ctx *android.Context, configuration android.Config, extraNinjaDeps []string) string { if configuration.BuildMode == android.Bp2build { // Run the alternate pipeline of bp2build mutators and singleton to convert // Blueprint to BUILD files before everything else. @@ -347,7 +353,7 @@ func main() { ctx := newContext(configuration) ctx.EventHandler.Begin("soong_build") - finalOutputFile := doChosenActivity(ctx, configuration, extraNinjaDeps, logDir) + finalOutputFile := doChosenActivity(ctx, configuration, extraNinjaDeps) ctx.EventHandler.End("soong_build") writeMetrics(configuration, *ctx.EventHandler, logDir) @@ -400,14 +406,10 @@ func touch(path string) { } } -// Find BUILD files in the srcDir which... -// -// - are not on the allow list (android/bazel.go#ShouldKeepExistingBuildFileForDir()) -// -// - won't be overwritten by corresponding bp2build generated files -// -// And return their paths so they can be left out of the Bazel workspace dir (i.e. ignored) -func getPathsToIgnoredBuildFiles(topDir string, generatedRoot string, srcDirBazelFiles []string, verbose bool) []string { +// Find BUILD files in the srcDir which are not in the allowlist +// (android.Bp2BuildConversionAllowlist#ShouldKeepExistingBuildFileForDir) +// and return their paths so they can be left out of the Bazel workspace dir (i.e. ignored) +func getPathsToIgnoredBuildFiles(config android.Bp2BuildConversionAllowlist, topDir string, srcDirBazelFiles []string, verbose bool) []string { paths := make([]string, 0) for _, srcDirBazelFileRelativePath := range srcDirBazelFiles { @@ -422,21 +424,14 @@ func getPathsToIgnoredBuildFiles(topDir string, generatedRoot string, srcDirBaze // Don't ignore entire directories continue } - if !(fileInfo.Name() == "BUILD" || fileInfo.Name() == "BUILD.bazel") { + if fileInfo.Name() != "BUILD" && fileInfo.Name() != "BUILD.bazel" { // Don't ignore this file - it is not a build file continue } - srcDirBazelFileDir := filepath.Dir(srcDirBazelFileRelativePath) - if android.ShouldKeepExistingBuildFileForDir(srcDirBazelFileDir) { + if config.ShouldKeepExistingBuildFileForDir(filepath.Dir(srcDirBazelFileRelativePath)) { // Don't ignore this existing build file continue } - correspondingBp2BuildFile := shared.JoinPath(topDir, generatedRoot, srcDirBazelFileRelativePath) - if _, err := os.Stat(correspondingBp2BuildFile); err == nil { - // If bp2build generated an alternate BUILD file, don't exclude this workspace path - // BUILD file clash resolution happens later in the symlink forest creation - continue - } if verbose { fmt.Fprintf(os.Stderr, "Ignoring existing BUILD file: %s\n", srcDirBazelFileRelativePath) } @@ -547,7 +542,7 @@ func runBp2Build(configuration android.Config, extraNinjaDeps []string) { os.Exit(1) } - pathsToIgnoredBuildFiles := getPathsToIgnoredBuildFiles(topDir, generatedRoot, existingBazelRelatedFiles, configuration.IsEnvTrue("BP2BUILD_VERBOSE")) + pathsToIgnoredBuildFiles := getPathsToIgnoredBuildFiles(configuration.Bp2buildPackageConfig, topDir, existingBazelRelatedFiles, configuration.IsEnvTrue("BP2BUILD_VERBOSE")) excludes = append(excludes, pathsToIgnoredBuildFiles...) excludes = append(excludes, getTemporaryExcludes()...) diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go index cb8563488..b06e4fe73 100644 --- a/cmd/soong_ui/main.go +++ b/cmd/soong_ui/main.go @@ -176,10 +176,6 @@ func main() { build.SetupOutDir(buildCtx, config) - if config.UseBazel() && config.Dist() { - defer populateExternalDistDir(buildCtx, config) - } - // Set up files to be outputted in the log directory. logsDir := config.LogsDir() diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go index d8011d69f..fdfd22e1b 100644 --- a/dexpreopt/dexpreopt.go +++ b/dexpreopt/dexpreopt.go @@ -201,6 +201,11 @@ func GetSystemServerDexLocation(ctx android.PathContext, global *GlobalConfig, l 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 07e4fad01..429b5ff1e 100644 --- a/dexpreopt/dexpreopt_test.go +++ b/dexpreopt/dexpreopt_test.go @@ -59,6 +59,15 @@ func testPlatformSystemServerModuleConfig(ctx android.PathContext, name string) 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 @@ func TestDexPreoptStandaloneSystemServerJars(t *testing.T) { 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 86a27b43f..694dcf135 100644 --- a/docs/perf.md +++ b/docs/perf.md @@ -221,6 +221,18 @@ You'll likely need to cross-reference this data against the build graph in the 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 719771f4c..7520f5875 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -31,6 +31,7 @@ import ( "encoding/json" "fmt" "path/filepath" + "reflect" "strings" "github.com/google/blueprint/proptools" @@ -670,10 +671,11 @@ func generatePrebuiltSnapshot(s snapshot.SnapshotSingleton, ctx android.Singleto // For Bazel / bp2build type bazelPrebuiltFileAttributes struct { - Src bazel.LabelAttribute - Filename string - Dir string - Installable bazel.BoolAttribute + Src bazel.LabelAttribute + Filename bazel.LabelAttribute + Dir string + Installable bazel.BoolAttribute + Filename_from_src bazel.BoolAttribute } // ConvertWithBp2build performs bp2build conversion of PrebuiltEtc @@ -691,11 +693,37 @@ func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext 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 - if module.properties.Filename != nil { - filename = *module.properties.Filename + var filenameFromSrc bool + moduleProps := module.properties + + if moduleProps.Filename != nil && *moduleProps.Filename != "" { + filename = *moduleProps.Filename + } else if moduleProps.Filename_from_src != nil && *moduleProps.Filename_from_src { + if moduleProps.Src != nil { + filename = *moduleProps.Src + } + filenameFromSrc = true + } else { + filename = ctx.ModuleName() } var dir = module.installDirBase @@ -714,11 +742,16 @@ func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext attrs := &bazelPrebuiltFileAttributes{ Src: src, - Filename: filename, Dir: dir, Installable: installable, } + if filename != "" { + attrs.Filename = bazel.LabelAttribute{Value: &bazel.Label{Label: filename}} + } else if filenameFromSrc { + attrs.Filename_from_src = bazel.BoolAttribute{Value: moduleProps.Filename_from_src} + } + props := bazel.BazelTargetModuleProperties{ Rule_class: "prebuilt_file", Bzl_load_location: "//build/bazel/rules:prebuilt_file.bzl", @@ -1,17 +1,13 @@ module android/soong -require ( - google.golang.org/protobuf v0.0.0 - github.com/google/blueprint v0.0.0 - android/soong/aidl v0.0.0 -) +require google.golang.org/protobuf v0.0.0 + +require github.com/google/blueprint v0.0.0 replace google.golang.org/protobuf v0.0.0 => ../../external/golang-protobuf replace github.com/google/blueprint v0.0.0 => ../blueprint -replace android/soong/aidl v0.0.0 => ../../system/tools/aidl/build - // Indirect deps from golang-protobuf exclude github.com/golang/protobuf v1.5.0 diff --git a/java/base.go b/java/base.go index cf3b3d510..23b4d46b3 100644 --- a/java/base.go +++ b/java/base.go @@ -169,6 +169,8 @@ type CommonProperties struct { Output_params []string } + // If true, then jacocoagent is automatically added as a libs dependency so that + // r8 will not strip instrumentation classes out of dexed libraries. Instrument bool `blueprint:"mutated"` // If true, then the module supports statically including the jacocoagent // into the library. @@ -648,6 +650,10 @@ func (j *Module) shouldInstrumentInApex(ctx android.BaseModuleContext) bool { 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)) } @@ -857,7 +863,9 @@ func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.Opt // 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") } @@ -1430,10 +1438,6 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { 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() { diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 93168070e..42a11fb75 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -840,22 +840,7 @@ func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.Modul // 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) diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go index f95c83fe7..2541f14ff 100644 --- a/java/bootclasspath_fragment_test.go +++ b/java/bootclasspath_fragment_test.go @@ -96,11 +96,6 @@ func TestBootclasspathFragmentInconsistentArtConfiguration_ApexMixture(t *testin } func TestBootclasspathFragment_Coverage(t *testing.T) { - prepareForTestWithFrameworkCoverage := android.FixtureMergeEnv(map[string]string{ - "EMMA_INSTRUMENT": "true", - "EMMA_INSTRUMENT_FRAMEWORK": "true", - }) - prepareWithBp := android.FixtureWithRootAndroidBp(` bootclasspath_fragment { name: "myfragment", @@ -179,7 +174,7 @@ func TestBootclasspathFragment_Coverage(t *testing.T) { t.Run("with coverage", func(t *testing.T) { result := android.GroupFixturePreparers( - prepareForTestWithFrameworkCoverage, + prepareForTestWithFrameworkJacocoInstrumentation, preparer, ).RunTest(t) checkContents(t, result, "mybootlib", "coveragelib") @@ -413,22 +408,6 @@ func TestBootclasspathFragment_Test(t *testing.T) { }, } - 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"], @@ -450,12 +429,6 @@ func TestBootclasspathFragment_Test(t *testing.T) { 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 3ca9bad3e..03288fe6a 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -78,7 +78,7 @@ var ( 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 @@ -124,6 +124,10 @@ func init() { // This is set up and guaranteed by soong_ui return ctx.Config().Getenv("ANDROID_JAVA_HOME") }) + pctx.VariableFunc("Java11Home", func(ctx android.PackageVarContext) string { + // This is set up and guaranteed by soong_ui + return ctx.Config().Getenv("ANDROID_JAVA11_HOME") + }) pctx.VariableFunc("JlinkVersion", func(ctx android.PackageVarContext) string { if override := ctx.Config().Getenv("OVERRIDE_JLINK_VERSION_NUMBER"); override != "" { return override @@ -137,18 +141,19 @@ func init() { }) pctx.SourcePathVariable("JavaToolchain", "${JavaHome}/bin") + pctx.SourcePathVariable("Java11Toolchain", "${Java11Home}/bin") pctx.SourcePathVariableWithEnvOverride("JavacCmd", "${JavaToolchain}/javac", "ALTERNATE_JAVAC") pctx.SourcePathVariable("JavaCmd", "${JavaToolchain}/java") pctx.SourcePathVariable("JarCmd", "${JavaToolchain}/jar") - pctx.SourcePathVariable("JavadocCmd", "${JavaToolchain}/javadoc") + pctx.SourcePathVariable("JavadocCmd", "${Java11Toolchain}/javadoc") pctx.SourcePathVariable("JlinkCmd", "${JavaToolchain}/jlink") pctx.SourcePathVariable("JmodCmd", "${JavaToolchain}/jmod") pctx.SourcePathVariable("JrtFsJar", "${JavaHome}/lib/jrt-fs.jar") pctx.SourcePathVariable("JavaKytheExtractorJar", "prebuilts/build-tools/common/framework/javac_extractor.jar") pctx.SourcePathVariable("Ziptime", "prebuilts/build-tools/${hostPrebuiltTag}/bin/ziptime") - pctx.HostBinToolVariable("GenKotlinBuildFileCmd", "gen-kotlin-build-file.py") + pctx.HostBinToolVariable("GenKotlinBuildFileCmd", "gen-kotlin-build-file") pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh") pctx.SourcePathVariable("PackageCheckCmd", "build/soong/scripts/package-check.sh") @@ -267,7 +272,7 @@ func JavaCmd(ctx android.PathContext) android.SourcePath { // JavadocCmd returns a SourcePath object with the path to the java command. func JavadocCmd(ctx android.PathContext) android.SourcePath { - return javaTool(ctx, "javadoc") + return java11Tool(ctx, "javadoc") } func javaTool(ctx android.PathContext, tool string) android.SourcePath { @@ -281,6 +286,17 @@ func javaTool(ctx android.PathContext, tool string) android.SourcePath { } +func java11Tool(ctx android.PathContext, tool string) android.SourcePath { + type javaToolKey string + + key := android.NewCustomOnceKey(javaToolKey(tool)) + + return ctx.Config().OnceSourcePath(key, func() android.SourcePath { + return java11Toolchain(ctx).Join(ctx, tool) + }) + +} + var javaToolchainKey = android.NewOnceKey("javaToolchain") func javaToolchain(ctx android.PathContext) android.SourcePath { @@ -289,6 +305,14 @@ func javaToolchain(ctx android.PathContext) android.SourcePath { }) } +var java11ToolchainKey = android.NewOnceKey("java11Toolchain") + +func java11Toolchain(ctx android.PathContext) android.SourcePath { + return ctx.Config().OnceSourcePath(java11ToolchainKey, func() android.SourcePath { + return java11Home(ctx).Join(ctx, "bin") + }) +} + var javaHomeKey = android.NewOnceKey("javaHome") func javaHome(ctx android.PathContext) android.SourcePath { @@ -297,3 +321,12 @@ func javaHome(ctx android.PathContext) android.SourcePath { return android.PathForSource(ctx, ctx.Config().Getenv("ANDROID_JAVA_HOME")) }) } + +var java11HomeKey = android.NewOnceKey("java11Home") + +func java11Home(ctx android.PathContext) android.SourcePath { + return ctx.Config().OnceSourcePath(java11HomeKey, func() android.SourcePath { + // This is set up and guaranteed by soong_ui + return android.PathForSource(ctx, ctx.Config().Getenv("ANDROID_JAVA11_HOME")) + }) +} diff --git a/java/droiddoc.go b/java/droiddoc.go index 9b1f43b4c..fc95184f1 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -755,6 +755,7 @@ func dokkaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, 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 12590ca50..d9efb408f 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -17,6 +17,7 @@ package java import ( "fmt" "path/filepath" + "regexp" "strings" "github.com/google/blueprint/proptools" @@ -142,6 +143,10 @@ type DroidstubsProperties struct { // 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 @@ func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *an 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) } @@ -445,6 +461,16 @@ func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *an 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 9fdfddeb1..24436921c 100644 --- a/java/droidstubs_test.go +++ b/java/droidstubs_test.go @@ -259,3 +259,33 @@ func checkSystemModulesUseByDroidstubs(t *testing.T, ctx *android.TestContext, m 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/jacoco.go b/java/jacoco.go index e11c2ce69..f8012b852 100644 --- a/java/jacoco.go +++ b/java/jacoco.go @@ -47,6 +47,34 @@ var ( "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 0251b5754..d04e52a2c 100644 --- a/java/java.go +++ b/java/java.go @@ -66,6 +66,8 @@ func registerJavaBuildComponents(ctx android.RegistrationContext) { // 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) diff --git a/java/testing.go b/java/testing.go index 511cc5ddb..1f411913b 100644 --- a/java/testing.go +++ b/java/testing.go @@ -59,11 +59,9 @@ var PrepareForTestWithJavaBuildComponents = android.GroupFixturePreparers( }.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 @@ var PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd = android.GroupFixtu "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 @@ var PrepareForTestWithPrebuiltsOfCurrentApi = FixtureWithPrebuiltApis(map[string "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. // diff --git a/multitree/api_imports.go b/multitree/api_imports.go index 2c4cf80ca..6674d3e57 100644 --- a/multitree/api_imports.go +++ b/multitree/api_imports.go @@ -16,6 +16,7 @@ package multitree import ( "android/soong/android" + "strings" "github.com/google/blueprint" ) @@ -26,6 +27,7 @@ var ( func init() { RegisterApiImportsModule(android.InitRegistrationContext) + android.RegisterMakeVarsProvider(pctx, makeVarsProvider) } func RegisterApiImportsModule(ctx android.RegistrationContext) { @@ -86,3 +88,12 @@ func (imports *ApiImports) DepsMutator(ctx android.BottomUpMutatorContext) { func GetApiImportSuffix() string { return apiImportNameSuffix } + +func makeVarsProvider(ctx android.MakeVarsContext) { + ctx.VisitAllModules(func(m android.Module) { + if i, ok := m.(*ApiImports); ok { + ctx.Strict("API_IMPORTED_SHARED_LIBRARIES", strings.Join(i.properties.Shared_libs, " ")) + ctx.Strict("API_IMPORTED_HEADER_LIBRARIES", strings.Join(i.properties.Header_libs, " ")) + } + }) +} diff --git a/python/scripts/stub_template_host.txt b/python/scripts/stub_template_host.txt index 138404bf3..23897b30b 100644 --- a/python/scripts/stub_template_host.txt +++ b/python/scripts/stub_template_host.txt @@ -81,7 +81,9 @@ def Main(): os.environ.update(new_env) sys.stdout.flush() - retCode = subprocess.call(args) + # close_fds=False so that you can run binaries with files provided on the command line: + # my_python_app --file <(echo foo) + retCode = subprocess.call(args, close_fds=False) sys.exit(retCode) except: raise diff --git a/scripts/Android.bp b/scripts/Android.bp index 814bd5753..b5b588b8d 100644 --- a/scripts/Android.bp +++ b/scripts/Android.bp @@ -168,7 +168,7 @@ python_test_host { } python_binary_host { - name: "gen-kotlin-build-file.py", + name: "gen-kotlin-build-file", main: "gen-kotlin-build-file.py", srcs: [ "gen-kotlin-build-file.py", diff --git a/symbol_inject/cmd/symbol_inject.go b/symbol_inject/cmd/symbol_inject.go index 1397b37b1..89b361907 100644 --- a/symbol_inject/cmd/symbol_inject.go +++ b/symbol_inject/cmd/symbol_inject.go @@ -94,4 +94,13 @@ func main() { os.Remove(*output) os.Exit(5) } + + if file.IsMachoFile { + err = symbol_inject.CodeSignMachoFile(*output) + if err != nil { + fmt.Fprintln(os.Stderr, err.Error()) + os.Remove(*output) + os.Exit(6) + } + } } diff --git a/symbol_inject/macho.go b/symbol_inject/macho.go index 6ee3f4fbd..9946d34af 100644 --- a/symbol_inject/macho.go +++ b/symbol_inject/macho.go @@ -18,6 +18,7 @@ import ( "debug/macho" "fmt" "io" + "os/exec" "sort" "strings" ) @@ -40,7 +41,7 @@ func extractMachoSymbols(machoFile *macho.File) (*File, error) { return symbols[i].Value < symbols[j].Value }) - file := &File{} + file := &File{IsMachoFile: true} for _, section := range machoFile.Sections { file.Sections = append(file.Sections, &Section{ @@ -95,3 +96,8 @@ func dumpMachoSymbols(r io.ReaderAt) error { return nil } + +func CodeSignMachoFile(path string) error { + cmd := exec.Command("/usr/bin/codesign", "--force", "-s", "-", path) + return cmd.Run() +} diff --git a/symbol_inject/symbol_inject.go b/symbol_inject/symbol_inject.go index 2a3d67e6d..77aff6fe3 100644 --- a/symbol_inject/symbol_inject.go +++ b/symbol_inject/symbol_inject.go @@ -161,9 +161,10 @@ func findSymbol(file *File, symbolName string) (uint64, uint64, error) { } type File struct { - r io.ReaderAt - Symbols []*Symbol - Sections []*Section + r io.ReaderAt + Symbols []*Symbol + Sections []*Section + IsMachoFile bool } type Symbol struct { diff --git a/sysprop/Android.bp b/sysprop/Android.bp index 1d5eb3130..e5263fec4 100644 --- a/sysprop/Android.bp +++ b/sysprop/Android.bp @@ -9,6 +9,7 @@ bootstrap_go_package { "blueprint", "soong", "soong-android", + "soong-bp2build", "soong-cc", "soong-java", ], @@ -18,6 +19,7 @@ bootstrap_go_package { ], testSrcs: [ "sysprop_test.go", + "sysprop_library_conversion_test.go", ], pluginFor: ["soong_build"], } diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go index a29d4c3ac..578dc2b7f 100644 --- a/sysprop/sysprop_library.go +++ b/sysprop/sysprop_library.go @@ -23,6 +23,7 @@ import ( "path" "sync" + "android/soong/bazel" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -125,6 +126,7 @@ func syspropJavaGenFactory() android.Module { type syspropLibrary struct { android.ModuleBase android.ApexModuleBase + android.BazelModuleBase properties syspropLibraryProperties @@ -363,7 +365,10 @@ func (m *syspropLibrary) ShouldSupportSdkVersion(ctx android.BaseModuleContext, // 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{} @@ -372,6 +377,7 @@ func syspropLibraryFactory() android.Module { ) android.InitAndroidModule(m) android.InitApexModule(m) + android.InitBazelModule(m) android.AddLoadHook(m, func(ctx android.LoadHookContext) { syspropLibraryHook(ctx, m) }) return m } @@ -403,6 +409,9 @@ type ccLibraryProperties struct { Host_supported *bool Apex_available []string Min_sdk_version *string + Bazel_module struct { + Bp2build_available *bool + } } type javaLibraryProperties struct { @@ -483,6 +492,11 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) { ccProps.Host_supported = m.properties.Host_supported ccProps.Apex_available = m.ApexProperties.Apex_available ccProps.Min_sdk_version = m.properties.Cpp.Min_sdk_version + // A Bazel macro handles this, so this module does not need to be handled + // in bp2build + // TODO(b/237810289) perhaps do something different here so that we aren't + // also disabling these modules in mixed builds + ccProps.Bazel_module.Bp2build_available = proptools.BoolPtr(false) ctx.CreateModule(cc.LibraryFactory, &ccProps) scope := "internal" @@ -557,3 +571,45 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) { *libraries = append(*libraries, "//"+ctx.ModuleDir()+":"+ctx.ModuleName()) } } + +// 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, + } + + 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) +} diff --git a/sysprop/sysprop_library_conversion_test.go b/sysprop/sysprop_library_conversion_test.go new file mode 100644 index 000000000..c72faf3e7 --- /dev/null +++ b/sysprop/sysprop_library_conversion_test.go @@ -0,0 +1,110 @@ +// 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 sysprop + +import ( + "testing" + + "android/soong/bp2build" +) + +func TestSyspropLibrarySimple(t *testing.T) { + bp2build.RunBp2BuildTestCaseSimple(t, bp2build.Bp2buildTestCase{ + Description: "sysprop_library simple", + ModuleTypeUnderTest: "sysprop_library", + ModuleTypeUnderTestFactory: syspropLibraryFactory, + Filesystem: map[string]string{ + "foo.sysprop": "", + "bar.sysprop": "", + }, + Blueprint: ` +sysprop_library { + name: "sysprop_foo", + srcs: [ + "foo.sysprop", + "bar.sysprop", + ], + property_owner: "Platform", +} +`, + ExpectedBazelTargets: []string{ + bp2build.MakeBazelTargetNoRestrictions("sysprop_library", + "sysprop_foo_sysprop_library", + bp2build.AttrNameToString{ + "srcs": `[ + "foo.sysprop", + "bar.sysprop", + ]`, + }), + bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_shared", + "libsysprop_foo", + bp2build.AttrNameToString{ + "dep": `":sysprop_foo_sysprop_library"`, + }), + bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_static", + "libsysprop_foo_bp2build_cc_library_static", + bp2build.AttrNameToString{ + "dep": `":sysprop_foo_sysprop_library"`, + }), + }, + }) +} + +func TestSyspropLibraryCppMinSdkVersion(t *testing.T) { + bp2build.RunBp2BuildTestCaseSimple(t, bp2build.Bp2buildTestCase{ + Description: "sysprop_library with min_sdk_version", + ModuleTypeUnderTest: "sysprop_library", + ModuleTypeUnderTestFactory: syspropLibraryFactory, + Filesystem: map[string]string{ + "foo.sysprop": "", + "bar.sysprop": "", + }, + Blueprint: ` +sysprop_library { + name: "sysprop_foo", + srcs: [ + "foo.sysprop", + "bar.sysprop", + ], + cpp: { + min_sdk_version: "5", + }, + property_owner: "Platform", +} +`, + ExpectedBazelTargets: []string{ + bp2build.MakeBazelTargetNoRestrictions("sysprop_library", + "sysprop_foo_sysprop_library", + bp2build.AttrNameToString{ + "srcs": `[ + "foo.sysprop", + "bar.sysprop", + ]`, + }), + bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_shared", + "libsysprop_foo", + bp2build.AttrNameToString{ + "dep": `":sysprop_foo_sysprop_library"`, + "min_sdk_version": `"5"`, + }), + bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_static", + "libsysprop_foo_bp2build_cc_library_static", + bp2build.AttrNameToString{ + "dep": `":sysprop_foo_sysprop_library"`, + "min_sdk_version": `"5"`, + }), + }, + }) +} diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go index 88ef61524..80b86e059 100644 --- a/sysprop/sysprop_test.go +++ b/sysprop/sysprop_test.go @@ -209,32 +209,32 @@ func TestSyspropLibrary(t *testing.T) { 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 4b2f795de..6bc0165b7 100755 --- a/tests/apex_comparison_tests.sh +++ b/tests/apex_comparison_tests.sh @@ -33,6 +33,10 @@ OUTPUT_DIR="$(mktemp -d)" SOONG_OUTPUT_DIR="$OUTPUT_DIR/soong" BAZEL_OUTPUT_DIR="$OUTPUT_DIR/bazel" +function call_bazel() { + tools/bazel --output_base="$BAZEL_OUTPUT_DIR" $@ +} + function cleanup { # call bazel clean because some bazel outputs don't have w bits. call_bazel clean @@ -54,12 +58,10 @@ packages/modules/common/build/build_unbundled_mainline_module.sh \ ###################### build/soong/soong_ui.bash --make-mode BP2BUILD_VERBOSE=1 --skip-soong-tests bp2build -function call_bazel() { - tools/bazel --output_base="$BAZEL_OUTPUT_DIR" $@ -} BAZEL_OUT="$(call_bazel info 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 @@ -85,7 +87,7 @@ function compare_deapexer_list() { # 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 3cdf6aa36..78af54d4a 100755 --- a/tests/bp2build_bazel_test.sh +++ b/tests/bp2build_bazel_test.sh @@ -103,7 +103,7 @@ EOF 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 @@ -146,10 +146,10 @@ EOF 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 +160,7 @@ EOF #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 643b46ac9..4b4d9085c 100644 --- a/tests/lib.sh +++ b/tests/lib.sh @@ -93,7 +93,6 @@ function create_mock_soong { symlink_directory external/go-cmp symlink_directory external/golang-protobuf symlink_directory external/starlark-go - symlink_directory system/tools/aidl touch "$MOCK_TOP/Android.bp" } @@ -124,6 +123,8 @@ function create_mock_bazel { 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/ui/build/build.go b/ui/build/build.go index f7a2d7b18..ff2d5f28d 100644 --- a/ui/build/build.go +++ b/ui/build/build.go @@ -104,12 +104,24 @@ const ( // Whether to run ninja on the combined ninja. RunNinja = 1 << iota // Whether to run bazel on the combined ninja. - RunBazel = 1 << iota - RunBuildTests = 1 << iota - RunAll = RunProductConfig | RunSoong | RunKati | RunKatiNinja | RunNinja - RunAllWithBazel = RunProductConfig | RunSoong | RunKati | RunKatiNinja | RunBazel + RunBazel = 1 << iota + RunBuildTests = 1 << iota + RunAll = RunProductConfig | RunSoong | RunKati | RunKatiNinja | RunNinja ) +// 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") + } +} + // checkProblematicFiles fails the build if existing Android.mk or CleanSpec.mk files are found at the root of the tree. func checkProblematicFiles(ctx Context) { files := []string{"Android.mk", "CleanSpec.mk"} @@ -221,6 +233,8 @@ func Build(ctx Context, config Config) { defer waitForDist(ctx) + checkBazelMode(ctx, config) + // checkProblematicFiles aborts the build if Android.mk or CleanSpec.mk are found at the root of the tree. checkProblematicFiles(ctx) @@ -236,9 +250,6 @@ func Build(ctx Context, config Config) { SetupPath(ctx, config) what := RunAll - if config.UseBazel() { - what = RunAllWithBazel - } if config.Checkbuild() { what |= RunBuildTests } diff --git a/ui/build/config.go b/ui/build/config.go index e14086712..14a99d080 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -99,11 +99,8 @@ type configImpl struct { pathReplaced bool - useBazel bool - - // During Bazel execution, Bazel cannot write outside OUT_DIR. - // So if DIST_DIR is set to an external dir (outside of OUT_DIR), we need to rig it temporarily and then migrate files at the end of the build. - riggedDistDirForBazel string + bazelProdMode bool + bazelDevMode bool // Set by multiproduct_kati emptyNinjaFile bool @@ -130,18 +127,6 @@ const ( BUILD_MODULES ) -type bazelBuildMode int - -// Bazel-related build modes. -const ( - // Don't use bazel at all. - noBazel bazelBuildMode = iota - - // Generate synthetic build files and incorporate these files into a build which - // partially uses Bazel. Build metadata may come from Android.bp or BUILD files. - mixedBuild -) - // checkTopDir validates that the current directory is at the root directory of the source tree. func checkTopDir(ctx Context) { if _, err := os.Stat(srcDirFileCheck); err != nil { @@ -448,21 +433,6 @@ func NewConfig(ctx Context, args ...string) Config { ctx.Fatalf("Unable to remove bazel profile directory %q: %v", bpd, err) } - ret.useBazel = ret.environ.IsEnvTrue("USE_BAZEL") - - if ret.UseBazel() { - if err := os.MkdirAll(bpd, 0777); err != nil { - ctx.Fatalf("Failed to create bazel profile directory %q: %v", bpd, err) - } - } - - if ret.UseBazel() { - ret.riggedDistDirForBazel = filepath.Join(ret.OutDir(), "dist") - } else { - // Not rigged - ret.riggedDistDirForBazel = ret.distDir - } - c := Config{ret} storeConfigMetrics(ctx, c) return c @@ -495,8 +465,7 @@ func buildConfig(config Config) *smpb.BuildConfig { ForceUseGoma: proto.Bool(config.ForceUseGoma()), UseGoma: proto.Bool(config.UseGoma()), UseRbe: proto.Bool(config.UseRBE()), - BazelAsNinja: proto.Bool(config.UseBazel()), - BazelMixedBuild: proto.Bool(config.bazelBuildMode() == mixedBuild), + BazelMixedBuild: proto.Bool(config.BazelBuildEnabled()), } c.Targets = append(c.Targets, config.arguments...) @@ -747,6 +716,10 @@ func (c *configImpl) parseArgs(ctx Context, args []string) { c.skipSoongTests = true } else if arg == "--mk-metrics" { c.reportMkMetrics = true + } else if arg == "--bazel-mode" { + c.bazelProdMode = true + } else if arg == "--bazel-mode-dev" { + c.bazelDevMode = true } else if len(arg) > 0 && arg[0] == '-' { parseArgNum := func(def int) int { if len(arg) > 2 { @@ -882,11 +855,7 @@ func (c *configImpl) OutDir() string { } func (c *configImpl) DistDir() string { - if c.UseBazel() { - return c.riggedDistDirForBazel - } else { - return c.distDir - } + return c.distDir } func (c *configImpl) RealDistDir() string { @@ -1134,16 +1103,8 @@ func (c *configImpl) UseRBE() bool { return false } -func (c *configImpl) UseBazel() bool { - return c.useBazel -} - -func (c *configImpl) bazelBuildMode() bazelBuildMode { - if c.Environment().IsEnvTrue("USE_BAZEL_ANALYSIS") { - return mixedBuild - } else { - return noBazel - } +func (c *configImpl) BazelBuildEnabled() bool { + return c.bazelProdMode || c.bazelDevMode } func (c *configImpl) StartRBE() bool { diff --git a/ui/build/config_test.go b/ui/build/config_test.go index e29327572..150ec35dc 100644 --- a/ui/build/config_test.go +++ b/ui/build/config_test.go @@ -28,6 +28,7 @@ import ( "android/soong/ui/logger" smpb "android/soong/ui/metrics/metrics_proto" "android/soong/ui/status" + "google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/proto" ) @@ -1005,6 +1006,8 @@ func TestBuildConfig(t *testing.T) { environ Environment arguments []string useBazel bool + bazelDevMode bool + bazelProdMode bool expectedBuildConfig *smpb.BuildConfig }{ { @@ -1014,7 +1017,6 @@ func TestBuildConfig(t *testing.T) { ForceUseGoma: proto.Bool(false), UseGoma: proto.Bool(false), UseRbe: proto.Bool(false), - BazelAsNinja: proto.Bool(false), BazelMixedBuild: proto.Bool(false), }, }, @@ -1025,7 +1027,6 @@ func TestBuildConfig(t *testing.T) { ForceUseGoma: proto.Bool(true), UseGoma: proto.Bool(false), UseRbe: proto.Bool(false), - BazelAsNinja: proto.Bool(false), BazelMixedBuild: proto.Bool(false), }, }, @@ -1036,7 +1037,6 @@ func TestBuildConfig(t *testing.T) { ForceUseGoma: proto.Bool(false), UseGoma: proto.Bool(true), UseRbe: proto.Bool(false), - BazelAsNinja: proto.Bool(false), BazelMixedBuild: proto.Bool(false), }, }, @@ -1047,7 +1047,6 @@ func TestBuildConfig(t *testing.T) { ForceUseGoma: proto.Bool(false), UseGoma: proto.Bool(false), UseRbe: proto.Bool(true), - BazelAsNinja: proto.Bool(false), BazelMixedBuild: proto.Bool(false), }, }, @@ -1059,18 +1058,28 @@ func TestBuildConfig(t *testing.T) { ForceUseGoma: proto.Bool(false), UseGoma: proto.Bool(false), UseRbe: proto.Bool(false), - BazelAsNinja: proto.Bool(true), BazelMixedBuild: proto.Bool(false), }, }, { - name: "bazel mixed build", - environ: Environment{"USE_BAZEL_ANALYSIS=1"}, + name: "bazel mixed build from dev mode", + environ: Environment{}, + bazelDevMode: true, + expectedBuildConfig: &smpb.BuildConfig{ + ForceUseGoma: proto.Bool(false), + UseGoma: proto.Bool(false), + UseRbe: proto.Bool(false), + BazelMixedBuild: proto.Bool(true), + }, + }, + { + name: "bazel mixed build from prod mode", + environ: Environment{}, + bazelProdMode: true, expectedBuildConfig: &smpb.BuildConfig{ ForceUseGoma: proto.Bool(false), UseGoma: proto.Bool(false), UseRbe: proto.Bool(false), - BazelAsNinja: proto.Bool(false), BazelMixedBuild: proto.Bool(true), }, }, @@ -1083,7 +1092,6 @@ func TestBuildConfig(t *testing.T) { ForceUseGoma: proto.Bool(false), UseGoma: proto.Bool(false), UseRbe: proto.Bool(false), - BazelAsNinja: proto.Bool(true), BazelMixedBuild: proto.Bool(false), Targets: []string{"droid", "dist"}, }, @@ -1094,30 +1102,34 @@ func TestBuildConfig(t *testing.T) { "FORCE_USE_GOMA=1", "USE_GOMA=1", "USE_RBE=1", - "USE_BAZEL_ANALYSIS=1", }, - useBazel: true, + useBazel: true, + bazelDevMode: true, expectedBuildConfig: &smpb.BuildConfig{ ForceUseGoma: proto.Bool(true), UseGoma: proto.Bool(true), UseRbe: proto.Bool(true), - BazelAsNinja: proto.Bool(true), BazelMixedBuild: proto.Bool(true), }, }, } + ctx := testContext() for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { c := &configImpl{ - environ: &tc.environ, - useBazel: tc.useBazel, - arguments: tc.arguments, + environ: &tc.environ, + bazelDevMode: tc.bazelDevMode, + bazelProdMode: tc.bazelProdMode, + arguments: tc.arguments, } config := Config{c} + checkBazelMode(ctx, config) actualBuildConfig := buildConfig(config) if expected := tc.expectedBuildConfig; !proto.Equal(expected, actualBuildConfig) { - t.Errorf("Expected build config != actual build config: %#v != %#v", *expected, *actualBuildConfig) + t.Errorf("Build config mismatch.\n"+ + "Expected build config: %#v\n"+ + "Actual build config: %#v", prototext.Format(expected), prototext.Format(actualBuildConfig)) } }) } diff --git a/ui/build/soong.go b/ui/build/soong.go index 3920ddddd..3ef77c7a6 100644 --- a/ui/build/soong.go +++ b/ui/build/soong.go @@ -32,7 +32,6 @@ import ( "github.com/google/blueprint" "github.com/google/blueprint/bootstrap" - "github.com/google/blueprint/deptools" "github.com/google/blueprint/microfactory" "google.golang.org/protobuf/proto" @@ -170,9 +169,8 @@ func primaryBuilderInvocation( commonArgs = append(commonArgs, "-l", filepath.Join(config.FileListDir(), "Android.bp.list")) invocationEnv := make(map[string]string) - debugMode := os.Getenv("SOONG_DELVE") != "" - - if debugMode { + if os.Getenv("SOONG_DELVE") != "" { + //debug mode commonArgs = append(commonArgs, "--delve_listen", os.Getenv("SOONG_DELVE")) commonArgs = append(commonArgs, "--delve_path", shared.ResolveDelveBinary()) // GODEBUG=asyncpreemptoff=1 disables the preemption of goroutines. This @@ -187,7 +185,7 @@ func primaryBuilderInvocation( invocationEnv["GODEBUG"] = "asyncpreemptoff=1" } - allArgs := make([]string, 0, 0) + var allArgs []string allArgs = append(allArgs, specificArgs...) allArgs = append(allArgs, "--globListDir", name, @@ -254,6 +252,12 @@ func bootstrapBlueprint(ctx Context, config Config) { if config.EmptyNinjaFile() { mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--empty-ninja-file") } + if config.bazelProdMode { + mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--bazel-mode") + } + if config.bazelDevMode { + mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--bazel-mode-dev") + } mainSoongBuildInvocation := primaryBuilderInvocation( config, @@ -263,7 +267,7 @@ func bootstrapBlueprint(ctx Context, config Config) { fmt.Sprintf("analyzing Android.bp files and generating ninja file at %s", config.SoongNinjaFile()), ) - if config.bazelBuildMode() == mixedBuild { + if config.BazelBuildEnabled() { // Mixed builds call Bazel from soong_build and they therefore need the // Bazel workspace to be available. Make that so by adding a dependency on // the bp2build marker file to the action that invokes soong_build . @@ -344,12 +348,9 @@ func bootstrapBlueprint(ctx Context, config Config) { 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) { @@ -373,9 +374,6 @@ func runSoong(ctx Context, config Config) { // unused variables were changed? envFile := filepath.Join(config.SoongOutDir(), availableEnvFile) - buildMode := config.bazelBuildMode() - integratedBp2Build := buildMode == mixedBuild - // This is done unconditionally, but does not take a measurable amount of time bootstrapBlueprint(ctx, config) @@ -405,7 +403,7 @@ func runSoong(ctx Context, config Config) { checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(soongBuildTag)) - if integratedBp2Build || config.Bp2Build() { + if config.BazelBuildEnabled() || config.Bp2Build() { checkEnvironmentFile(soongBuildEnv, config.UsedEnvFile(bp2buildTag)) } diff --git a/ui/status/ninja.go b/ui/status/ninja.go index 4d9962153..fc0e21a05 100644 --- a/ui/status/ninja.go +++ b/ui/status/ninja.go @@ -35,8 +35,7 @@ import ( func NewNinjaReader(ctx logger.Logger, status ToolStatus, fifo string) *NinjaReader { os.Remove(fifo) - err := syscall.Mkfifo(fifo, 0666) - if err != nil { + if err := syscall.Mkfifo(fifo, 0666); err != nil { ctx.Fatalf("Failed to mkfifo(%q): %v", fifo, err) } |