diff options
112 files changed, 4460 insertions, 1122 deletions
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go index 85b9c4dbd..bcf335f36 100644 --- a/android/allowlists/allowlists.go +++ b/android/allowlists/allowlists.go @@ -46,19 +46,16 @@ var ( "bionic": Bp2BuildDefaultTrueRecursively, "bootable/recovery/tools/recovery_l10n": Bp2BuildDefaultTrue, - "build/bazel/examples/apex/minimal": Bp2BuildDefaultTrueRecursively, - "build/bazel/examples/soong_config_variables": Bp2BuildDefaultTrueRecursively, - "build/bazel/examples/python": Bp2BuildDefaultTrueRecursively, - "build/bazel/examples/gensrcs": Bp2BuildDefaultTrueRecursively, - "build/make/target/product/security": Bp2BuildDefaultTrue, - "build/make/tools/signapk": Bp2BuildDefaultTrue, - "build/make/tools/zipalign": Bp2BuildDefaultTrueRecursively, - "build/soong": Bp2BuildDefaultTrue, - "build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir - "build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue, - "build/soong/cc/symbolfile": Bp2BuildDefaultTrue, - "build/soong/linkerconfig": Bp2BuildDefaultTrueRecursively, - "build/soong/scripts": Bp2BuildDefaultTrueRecursively, + "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/linkerconfig": Bp2BuildDefaultTrueRecursively, + "build/soong/scripts": Bp2BuildDefaultTrueRecursively, "cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively, "development/apps/DevelopmentSettings": Bp2BuildDefaultTrue, @@ -137,10 +134,12 @@ var ( "external/libjpeg-turbo": Bp2BuildDefaultTrueRecursively, "external/libmpeg2": Bp2BuildDefaultTrueRecursively, "external/libpng": 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, @@ -148,6 +147,7 @@ var ( "external/scudo": Bp2BuildDefaultTrueRecursively, "external/selinux/libselinux": Bp2BuildDefaultTrueRecursively, "external/selinux/libsepol": Bp2BuildDefaultTrueRecursively, + "external/speex": Bp2BuildDefaultTrueRecursively, "external/toybox": Bp2BuildDefaultTrueRecursively, "external/zlib": Bp2BuildDefaultTrueRecursively, "external/zopfli": Bp2BuildDefaultTrueRecursively, @@ -157,11 +157,15 @@ var ( "frameworks/av/media/liberror": Bp2BuildDefaultTrueRecursively, "frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively, "frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue, + "frameworks/base/services/tests/servicestests/aidl": Bp2BuildDefaultTrue, "frameworks/base/startop/apps/test": Bp2BuildDefaultTrue, "frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively, "frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively, "frameworks/native/libs/arect": Bp2BuildDefaultTrueRecursively, "frameworks/native/libs/math": Bp2BuildDefaultTrueRecursively, + "hardware/interfaces/common/aidl": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/common/aidl": Bp2BuildDefaultTrue, + "hardware/interfaces/neuralnetworks/aidl": Bp2BuildDefaultTrue, "frameworks/native/libs/nativebase": Bp2BuildDefaultTrueRecursively, "frameworks/native/opengl/tests/gl2_cameraeye": Bp2BuildDefaultTrue, "frameworks/native/opengl/tests/gl2_java": Bp2BuildDefaultTrue, @@ -170,7 +174,35 @@ var ( "frameworks/native/opengl/tests/testViewport": Bp2BuildDefaultTrue, "frameworks/proto_logging/stats/stats_log_api_gen": Bp2BuildDefaultTrueRecursively, - "libnativehelper": Bp2BuildDefaultTrueRecursively, + "hardware/interfaces": Bp2BuildDefaultTrue, + "hardware/interfaces/configstore/1.0": Bp2BuildDefaultTrue, + "hardware/interfaces/configstore/1.1": Bp2BuildDefaultTrue, + "hardware/interfaces/configstore/utils": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/allocator/2.0": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/allocator/3.0": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/allocator/4.0": Bp2BuildDefaultTrue, + "hardware/interfaces/graphics/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/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, + + "libnativehelper": Bp2BuildDefaultTrueRecursively, + "packages/apps/DevCamera": Bp2BuildDefaultTrue, "packages/apps/HTMLViewer": Bp2BuildDefaultTrue, "packages/apps/Protips": Bp2BuildDefaultTrue, @@ -194,6 +226,8 @@ var ( "prebuilts/sdk/current/support": Bp2BuildDefaultTrue, "prebuilts/tools/common/m2": Bp2BuildDefaultTrue, + "platform_testing/tests/example": Bp2BuildDefaultTrueRecursively, + "system/apex": Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures "system/apex/apexer": Bp2BuildDefaultTrue, "system/apex/libs": Bp2BuildDefaultTrueRecursively, @@ -209,6 +243,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, @@ -216,18 +251,28 @@ 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/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, @@ -242,23 +287,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/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,6 +300,7 @@ var ( "external/bazel-skylib":/* recursive = */ true, "external/guava":/* recursive = */ true, "external/jsr305":/* recursive = */ true, + "external/protobuf":/* recursive = */ false, "frameworks/ex/common":/* recursive = */ true, "packages/apps/Music":/* recursive = */ true, @@ -278,6 +308,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, @@ -306,7 +337,9 @@ var ( "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", "libbluetooth-types-header", @@ -328,6 +361,8 @@ var ( "libpdx_headers", "libprocpartition", "libruy_static", + "libandroidio", + "libandroidio_srcs", "libserviceutils", "libstagefright_enc_common", "libstagefright_foundation_headers", @@ -392,23 +427,50 @@ var ( //system/libhidl // needed by cc_hidl_library "libhidlbase", + + //frameworks/native + "framework_native_aidl_binder", + "framework_native_aidl_gui", + + //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", } Bp2buildModuleTypeAlwaysConvertList = []string{ "linker_config", "java_import", "java_import_host", + "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 + "gen-kotlin-build-file.py", + "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 "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 @@ -475,7 +537,6 @@ 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 "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 @@ -487,8 +548,6 @@ var ( "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 - "libdexfile", // depends on unconverted modules: dexfile_operator_srcs, libartbase, libartpalette, - "libdexfile_static", // depends on unconverted modules: libartbase, libdexfile "libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette "libfastdeploy_host", // depends on unconverted modules: libandroidfw, libusb, AdbWinApi "libgmock_main_ndk", // depends on unconverted modules: libgtest_ndk_c++ @@ -496,7 +555,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 @@ -510,12 +569,468 @@ 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", + + // 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", + "adb_crypto_test", + "adb_pairing_auth_test", + "adb_pairing_connection_test", + "adb_tls_connection_test", + "adbd_test", // depends on unconverted modules: libusb + "avcdec", + "avcenc", + "bionic-benchmarks-tests", + "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 + "libavservices_minijail_unittest", + "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", + // "zlib_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{} @@ -537,30 +1052,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 @@ -576,5 +1069,20 @@ var ( "prebuilt_android-support-annotations-nodeps", "prebuilt_android-arch-paging-common-nodeps", "prebuilt_android-arch-room-common-nodeps", + // TODO(b/217750501) exclude_dirs property not supported + "prebuilt_kotlin-reflect", + "prebuilt_kotlin-stdlib", + "prebuilt_kotlin-stdlib-jdk7", + "prebuilt_kotlin-stdlib-jdk8", + "prebuilt_kotlin-test", + // TODO(b/217750501) exclude_files property not supported + "prebuilt_platform-robolectric-4.4-prebuilt", + "prebuilt_platform-robolectric-4.5.1-prebuilt", + "prebuilt_currysrc_org.eclipse", + } + + ProdMixedBuildsEnabledList = []string{ + // This list left intentionally empty for now. Add specific module names + // to have them built by Bazel in Prod Mixed Builds mode. } ) diff --git a/android/apex.go b/android/apex.go index b583be309..00b724137 100644 --- a/android/apex.go +++ b/android/apex.go @@ -454,7 +454,8 @@ 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)) || + (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 a0895edf8..1952b1716 100644 --- a/android/arch.go +++ b/android/arch.go @@ -619,6 +619,12 @@ func archMutator(bpctx blueprint.BottomUpMutatorContext) { mctx.ModuleErrorf("%s", err.Error()) } + // If there are no supported targets disable the module. + if len(targets) == 0 { + base.Disable() + return + } + // If the module is using extraMultilib, decode the extraMultilib selection into // a separate list of Targets. var multiTargets []Target @@ -627,6 +633,7 @@ func archMutator(bpctx blueprint.BottomUpMutatorContext) { if err != nil { mctx.ModuleErrorf("%s", err.Error()) } + multiTargets = filterHostCross(multiTargets, targets[0].HostCross) } // Recovery is always the primary architecture, filter out any other architectures. @@ -763,6 +770,18 @@ func filterToArch(targets []Target, archs ...ArchType) []Target { return targets } +// filterHostCross takes a list of Targets and a hostCross value, and returns a modified list +// that contains only Targets that have the specified HostCross. +func filterHostCross(targets []Target, hostCross bool) []Target { + for i := 0; i < len(targets); i++ { + if targets[i].HostCross != hostCross { + targets = append(targets[:i], targets[i+1:]...) + i-- + } + } + return targets +} + // archPropRoot is a struct type used as the top level of the arch-specific properties. It // contains the "arch", "multilib", and "target" property structs. It is used to split up the // property structs to limit how much is allocated when a single arch-specific property group is @@ -1795,20 +1814,23 @@ func getCommonTargets(targets []Target) []Target { } // FirstTarget takes a list of Targets and a list of multilib values and returns a list of Targets -// that contains zero or one Target for each OsType, selecting the one that matches the earliest -// filter. +// that contains zero or one Target for each OsType and HostCross, selecting the one that matches +// the earliest filter. func FirstTarget(targets []Target, filters ...string) []Target { // find the first target from each OS var ret []Target - hasHost := false - set := make(map[OsType]bool) + type osHostCross struct { + os OsType + hostCross bool + } + set := make(map[osHostCross]bool) for _, filter := range filters { buildTargets := filterMultilibTargets(targets, filter) for _, t := range buildTargets { - if _, found := set[t.Os]; !found { - hasHost = hasHost || (t.Os.Class == Host) - set[t.Os] = true + key := osHostCross{t.Os, t.HostCross} + if _, found := set[key]; !found { + set[key] = true ret = append(ret, t) } } diff --git a/android/arch_test.go b/android/arch_test.go index ad2076d4d..6814f8a7d 100644 --- a/android/arch_test.go +++ b/android/arch_test.go @@ -259,6 +259,27 @@ type archTestModule struct { } } +func (m *archTestMultiTargetsModule) GenerateAndroidBuildActions(ctx ModuleContext) { +} + +func (m *archTestMultiTargetsModule) DepsMutator(ctx BottomUpMutatorContext) { + ctx.AddDependency(ctx.Module(), nil, m.props.Deps...) +} + +func archTestMultiTargetsModuleFactory() Module { + m := &archTestMultiTargetsModule{} + m.AddProperties(&m.props) + InitAndroidMultiTargetsArchModule(m, HostAndDeviceSupported, MultilibCommon) + return m +} + +type archTestMultiTargetsModule struct { + ModuleBase + props struct { + Deps []string + } +} + func (m *archTestModule) GenerateAndroidBuildActions(ctx ModuleContext) { } @@ -277,19 +298,27 @@ var prepareForArchTest = GroupFixturePreparers( PrepareForTestWithArchMutator, FixtureRegisterWithContext(func(ctx RegistrationContext) { ctx.RegisterModuleType("module", archTestModuleFactory) + ctx.RegisterModuleType("multi_targets_module", archTestMultiTargetsModuleFactory) }), ) func TestArchMutator(t *testing.T) { var buildOSVariants []string + var buildOS64Variants []string var buildOS32Variants []string + var buildOSCommonVariant string + switch runtime.GOOS { case "linux": buildOSVariants = []string{"linux_glibc_x86_64", "linux_glibc_x86"} + buildOS64Variants = []string{"linux_glibc_x86_64"} buildOS32Variants = []string{"linux_glibc_x86"} + buildOSCommonVariant = "linux_glibc_common" case "darwin": buildOSVariants = []string{"darwin_x86_64"} + buildOS64Variants = []string{"darwin_x86_64"} buildOS32Variants = nil + buildOSCommonVariant = "darwin_common" } bp := ` @@ -312,24 +341,46 @@ func TestArchMutator(t *testing.T) { host_supported: true, compile_multilib: "32", } + + module { + name: "first", + host_supported: true, + compile_multilib: "first", + } + + multi_targets_module { + name: "multi_targets", + host_supported: true, + } ` testCases := []struct { - name string - preparer FixturePreparer - fooVariants []string - barVariants []string - bazVariants []string - quxVariants []string + name string + preparer FixturePreparer + fooVariants []string + barVariants []string + bazVariants []string + quxVariants []string + firstVariants []string + + multiTargetVariants []string + multiTargetVariantsMap map[string][]string + + goOS string }{ { - name: "normal", - preparer: nil, - fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"}, - barVariants: append(buildOSVariants, "android_arm64_armv8-a", "android_arm_armv7-a-neon"), - bazVariants: nil, - quxVariants: append(buildOS32Variants, "android_arm_armv7-a-neon"), - }, + name: "normal", + preparer: nil, + fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"}, + barVariants: append(buildOSVariants, "android_arm64_armv8-a", "android_arm_armv7-a-neon"), + bazVariants: nil, + quxVariants: append(buildOS32Variants, "android_arm_armv7-a-neon"), + firstVariants: append(buildOS64Variants, "android_arm64_armv8-a"), + multiTargetVariants: []string{buildOSCommonVariant, "android_common"}, + multiTargetVariantsMap: map[string][]string{ + buildOSCommonVariant: buildOS64Variants, + "android_common": {"android_arm64_armv8-a"}, + }}, { name: "host-only", preparer: FixtureModifyConfig(func(config Config) { @@ -337,10 +388,33 @@ func TestArchMutator(t *testing.T) { config.BuildOSCommonTarget = Target{} config.Targets[Android] = nil }), - fooVariants: nil, - barVariants: buildOSVariants, - bazVariants: nil, - quxVariants: buildOS32Variants, + fooVariants: nil, + barVariants: buildOSVariants, + bazVariants: nil, + quxVariants: buildOS32Variants, + firstVariants: buildOS64Variants, + multiTargetVariants: []string{buildOSCommonVariant}, + multiTargetVariantsMap: map[string][]string{ + buildOSCommonVariant: buildOS64Variants, + }, + }, + { + name: "same arch host and host cross", + preparer: FixtureModifyConfig(func(config Config) { + modifyTestConfigForMusl(config) + modifyTestConfigForMuslArm64HostCross(config) + }), + fooVariants: []string{"android_arm64_armv8-a", "android_arm_armv7-a-neon"}, + barVariants: []string{"linux_musl_x86_64", "linux_musl_arm64", "linux_musl_x86", "android_arm64_armv8-a", "android_arm_armv7-a-neon"}, + bazVariants: nil, + quxVariants: []string{"linux_musl_x86", "android_arm_armv7-a-neon"}, + firstVariants: []string{"linux_musl_x86_64", "linux_musl_arm64", "android_arm64_armv8-a"}, + multiTargetVariants: []string{"linux_musl_common", "android_common"}, + multiTargetVariantsMap: map[string][]string{ + "linux_musl_common": {"linux_musl_x86_64"}, + "android_common": {"android_arm64_armv8-a"}, + }, + goOS: "linux", }, } @@ -356,8 +430,21 @@ func TestArchMutator(t *testing.T) { return ret } + moduleMultiTargets := func(ctx *TestContext, name string, variant string) []string { + var ret []string + targets := ctx.ModuleForTests(name, variant).Module().MultiTargets() + for _, t := range targets { + ret = append(ret, t.String()) + } + return ret + } + for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) { + if tt.goOS != runtime.GOOS { + t.Skipf("requries runtime.GOOS %s", tt.goOS) + } + result := GroupFixturePreparers( prepareForArchTest, // Test specific preparer @@ -381,6 +468,20 @@ func TestArchMutator(t *testing.T) { if g, w := enabledVariants(ctx, "qux"), tt.quxVariants; !reflect.DeepEqual(w, g) { t.Errorf("want qux variants:\n%q\ngot:\n%q\n", w, g) } + if g, w := enabledVariants(ctx, "first"), tt.firstVariants; !reflect.DeepEqual(w, g) { + t.Errorf("want first variants:\n%q\ngot:\n%q\n", w, g) + } + + if g, w := enabledVariants(ctx, "multi_targets"), tt.multiTargetVariants; !reflect.DeepEqual(w, g) { + t.Fatalf("want multi_target variants:\n%q\ngot:\n%q\n", w, g) + } + + for _, variant := range tt.multiTargetVariants { + targets := moduleMultiTargets(ctx, "multi_targets", variant) + if g, w := targets, tt.multiTargetVariantsMap[variant]; !reflect.DeepEqual(w, g) { + t.Errorf("want ctx.MultiTarget() for %q:\n%q\ngot:\n%q\n", variant, w, g) + } + } }) } } diff --git a/android/bazel.go b/android/bazel.go index 183a2f324..27ec92bd1 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,6 +32,12 @@ const ( Bp2BuildTopLevel = "." ) +// Bp2buildAidlLibrary describes a filegroup module that are converted to aidl_library +type Bp2buildAidlLibrary interface { + ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) bool + GetAidlLibraryLabel(ctx BazelConversionPathContext) string +} + type BazelConversionStatus struct { // Information about _all_ bp2build targets generated by this module. Multiple targets are // supported as Soong handles some things within a single target that we may choose to split into @@ -111,7 +114,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 @@ -205,7 +207,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 @@ -213,46 +215,47 @@ 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 both bp2build and mixed builds. + // Per-module denylist to always opt modules out of bp2build conversion. moduleDoNotConvert map[string]bool // Per-module denylist of cc_library modules to only generate the static // variant if their shared variant isn't ready or buildable by Bazel. ccLibraryStaticOnly map[string]bool +} - // Per-module denylist to opt modules out of mixed builds. Such modules will - // still be generated via bp2build. - mixedBuildsDisabled map[string]bool +// 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 { + 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{}, map[string]bool{}, map[string]bool{}, map[string]bool{}, - map[string]bool{}, } } // 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{} } @@ -264,7 +267,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{} } @@ -276,7 +279,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{} } @@ -288,7 +291,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{} } @@ -300,7 +303,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{} } @@ -312,7 +315,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{} } @@ -323,52 +326,15 @@ func (a bp2BuildConversionAllowlist) SetCcLibraryStaticOnlyList(ccLibraryStaticO return a } -// SetMixedBuildsDisabledList copies the entries from mixedBuildsDisabled into the allowlist -func (a bp2BuildConversionAllowlist) SetMixedBuildsDisabledList(mixedBuildsDisabled []string) bp2BuildConversionAllowlist { - if a.mixedBuildsDisabled == nil { - a.mixedBuildsDisabled = map[string]bool{} - } - for _, m := range mixedBuildsDisabled { - a.mixedBuildsDisabled[m] = true - } - - 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). - SetMixedBuildsDisabledList(allowlists.MixedBuildsDisabledList) - }).(bp2BuildConversionAllowlist) -} - -// GenerateCcLibraryStaticOnly returns whether a cc_library module should only -// generate a static version of itself based on the current global configuration. -func GenerateCcLibraryStaticOnly(moduleName string) bool { - return getBp2BuildAllowList().ccLibraryStaticOnly[moduleName] -} - // 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 @@ -379,6 +345,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 @@ -399,20 +379,10 @@ func mixedBuildPossible(ctx BaseModuleContext) bool { if !ctx.Module().Enabled() { return false } - if !ctx.Config().BazelContext.BazelEnabled() { - return false - } if !convertedToBazel(ctx, ctx.Module()) { return false } - - if GenerateCcLibraryStaticOnly(ctx.Module().Name()) { - // 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. - return false - } - return !getBp2BuildAllowList().mixedBuildsDisabled[ctx.Module().Name()] + return ctx.Config().BazelContext.BazelAllowlisted(ctx.Module().Name()) } // ConvertedToBazel returns whether this module has been converted (with bp2build or manually) to Bazel. @@ -453,7 +423,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 @@ -469,14 +439,6 @@ 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 { @@ -532,28 +494,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 a5fa04322..93b677930 100644 --- a/android/bazel_handler.go +++ b/android/bazel_handler.go @@ -27,6 +27,7 @@ import ( "strings" "sync" + "android/soong/android/allowlists" "android/soong/bazel/cquery" "android/soong/shared" @@ -142,8 +143,11 @@ type BazelContext interface { // queued in the BazelContext. InvokeBazel(config Config) error - // Returns true if bazel is enabled for the given configuration. - BazelEnabled() bool + // Returns true if Bazel handling is enabled for the module with the given name. + // Note that this only implies "bazel mixed build" allowlisting. The caller + // should independently verify the module is eligible for Bazel handling + // (for example, that it is MixedBuildBuildable). + BazelAllowlisted(moduleName string) bool // Returns the bazel output base (the root directory for all bazel intermediate outputs). OutputBase() string @@ -183,6 +187,17 @@ type bazelContext struct { // Depsets which should be used for Bazel's build statements. depsets []bazel.AqueryDepset + + // Per-module allowlist/denylist functionality to control whether analysis of + // modules are handled by Bazel. For modules which do not have a Bazel definition + // (or do not sufficiently support bazel handling via MixedBuildBuildable), + // this allowlist will have no effect, even if the module is explicitly allowlisted here. + // Per-module denylist to opt modules out of bazel handling. + bazelDisabledModules map[string]bool + // Per-module allowlist to opt modules in to bazel handling. + bazelEnabledModules map[string]bool + // If true, modules are bazel-enabled by default, unless present in bazelDisabledModules. + modulesDefaultToBazel bool } var _ BazelContext = &bazelContext{} @@ -229,7 +244,7 @@ func (m MockBazelContext) InvokeBazel(_ Config) error { panic("unimplemented") } -func (m MockBazelContext) BazelEnabled() bool { +func (m MockBazelContext) BazelAllowlisted(moduleName string) bool { return true } @@ -315,7 +330,7 @@ func (m noopBazelContext) OutputBase() string { return "" } -func (n noopBazelContext) BazelEnabled() bool { +func (n noopBazelContext) BazelAllowlisted(moduleName string) bool { return false } @@ -328,9 +343,30 @@ func (m noopBazelContext) AqueryDepsets() []bazel.AqueryDepset { } func NewBazelContext(c *config) (BazelContext, error) { - // TODO(cparsons): Assess USE_BAZEL=1 instead once "mixed Soong/Bazel builds" - // are production ready. - if !c.IsEnvTrue("USE_BAZEL_ANALYSIS") { + 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 } @@ -338,10 +374,14 @@ func NewBazelContext(c *config) (BazelContext, error) { if err != nil { return nil, err } + return &bazelContext{ - bazelRunner: &builtinBazelRunner{}, - paths: p, - requests: make(map[cqueryKey]bool), + bazelRunner: &builtinBazelRunner{}, + paths: p, + requests: make(map[cqueryKey]bool), + modulesDefaultToBazel: modulesDefaultToBazel, + bazelEnabledModules: enabledModules, + bazelDisabledModules: disabledModules, }, nil } @@ -386,8 +426,14 @@ func (p *bazelPaths) BazelMetricsDir() string { return p.metricsDir } -func (context *bazelContext) BazelEnabled() bool { - return true +func (context *bazelContext) BazelAllowlisted(moduleName string) bool { + if context.bazelDisabledModules[moduleName] { + return false + } + if context.bazelEnabledModules[moduleName] { + return true + } + return context.modulesDefaultToBazel } func pwdPrefix() string { @@ -851,7 +897,7 @@ type bazelSingleton struct{} func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) { // bazelSingleton is a no-op if mixed-soong-bazel-builds are disabled. - if !ctx.Config().BazelContext.BazelEnabled() { + if !ctx.Config().IsMixedBuildsEnabled() { return } diff --git a/android/bazel_test.go b/android/bazel_test.go index da4a9156d..b578cca04 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,27 +264,6 @@ 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'"}, @@ -296,7 +275,7 @@ func TestBp2BuildAllowlist(t *testing.T) { }, BazelModuleBase: bazelableBazelModuleBase, }, - allowlist: bp2BuildConversionAllowlist{ + allowlist: Bp2BuildConversionAllowlist{ moduleAlwaysConvert: map[string]bool{ "foo": true, }, @@ -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, }, @@ -389,7 +368,7 @@ func TestBp2BuildAllowlist(t *testing.T) { } func TestBp2buildAllowList(t *testing.T) { - allowlist := getBp2BuildAllowList() + allowlist := GetBp2BuildAllowList() for k, v := range allowlists.Bp2buildDefaultConfig { if allowlist.defaultConfig[k] != v { t.Errorf("bp2build default config of %s: expected: %v, got: %v", k, v, allowlist.defaultConfig[k]) @@ -415,9 +394,4 @@ func TestBp2buildAllowList(t *testing.T) { t.Errorf("bp2build cc library static only of %s: expected: true, got: %v", k, allowlist.ccLibraryStaticOnly[k]) } } - for _, k := range allowlists.MixedBuildsDisabledList { - if !allowlist.mixedBuildsDisabled[k] { - t.Errorf("bp2build mix build disabled of %s: expected: true, got: %v", k, allowlist.mixedBuildsDisabled[k]) - } - } } diff --git a/android/config.go b/android/config.go index d3f8ab463..745410f1e 100644 --- a/android/config.go +++ b/android/config.go @@ -68,6 +68,37 @@ type Config struct { *config } +type SoongBuildMode int + +// Build modes that soong_build can run as. +const ( + // Don't use bazel at all during module analysis. + AnalysisNoBazel SoongBuildMode = iota + + // Bp2build mode: Generate BUILD files from blueprint files and exit. + Bp2build + + // Generate BUILD files which faithfully represent the dependency graph of + // blueprint modules. Individual BUILD targets will not, however, faitfhully + // express build semantics. + GenerateQueryView + + // Create a JSON representation of the module graph and exit. + GenerateModuleGraph + + // Generate a documentation file for module type definitions and exit. + GenerateDocFile + + // Use bazel during analysis of many allowlisted build modules. The allowlist + // is considered a "developer mode" allowlist, as some modules may be + // allowlisted on an experimental basis. + BazelDevMode + + // Use bazel during analysis of build modules from an allowlist carefully + // curated by the build team to be proven stable. + BazelProdMode +) + // SoongOutDir returns the build output directory for the configuration. func (c Config) SoongOutDir() string { return c.soongOutDir @@ -157,8 +188,8 @@ type config struct { fs pathtools.FileSystem mockBpList string - runningAsBp2Build bool - bp2buildPackageConfig bp2BuildConversionAllowlist + BuildMode SoongBuildMode + Bp2buildPackageConfig Bp2BuildConversionAllowlist Bp2buildSoongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions // If testAllowNonExistentPaths is true then PathForSource and PathForModuleSrc won't error @@ -171,6 +202,12 @@ type config struct { OncePer + // These fields are only used for metrics collection. A module should be added + // to these maps only if its implementation supports Bazel handling in mixed + // builds. A module being in the "enabled" list indicates that there is a + // variant of that module for which bazel-handling actually took place. + // A module being in the "disabled" list indicates that there is a variant of + // that module for which bazel-handling was denied. mixedBuildsLock sync.Mutex mixedBuildEnabledModules map[string]struct{} mixedBuildDisabledModules map[string]struct{} @@ -346,7 +383,7 @@ func NullConfig(outDir, soongOutDir string) Config { // NewConfig creates a new Config object. The srcDir argument specifies the path // to the root source directory. It also loads the config file, if found. -func NewConfig(moduleListFile string, runGoTests bool, outDir, soongOutDir string, availableEnv map[string]string) (Config, error) { +func NewConfig(moduleListFile string, buildMode SoongBuildMode, runGoTests bool, outDir, soongOutDir string, availableEnv map[string]string) (Config, error) { // Make a config with default options. config := &config{ ProductVariablesFileName: filepath.Join(soongOutDir, productVariablesFileName), @@ -443,8 +480,9 @@ func NewConfig(moduleListFile string, runGoTests bool, outDir, soongOutDir strin config.AndroidFirstDeviceTarget = FirstTarget(config.Targets[Android], "lib64", "lib32")[0] } + config.BuildMode = buildMode config.BazelContext, err = NewBazelContext(config) - config.bp2buildPackageConfig = getBp2BuildAllowList() + config.Bp2buildPackageConfig = GetBp2BuildAllowList() return Config{config}, err } @@ -479,6 +517,12 @@ func (c *config) mockFileSystem(bp string, fs map[string][]byte) { c.mockBpList = blueprint.MockModuleListFile } +// Returns true if "Bazel builds" is enabled. In this mode, part of build +// analysis is handled by Bazel. +func (c *config) IsMixedBuildsEnabled() bool { + return c.BuildMode == BazelProdMode || c.BuildMode == BazelDevMode +} + func (c *config) SetAllowMissingDependencies() { c.productVariables.Allow_missing_dependencies = proptools.BoolPtr(true) } @@ -625,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 } @@ -689,7 +731,7 @@ func (c *config) PlatformVersionKnownCodenames() string { } func (c *config) MinSupportedSdkVersion() ApiLevel { - return uncheckedFinalApiLevel(19) + return uncheckedFinalApiLevel(21) } func (c *config) FinalApiLevels() []ApiLevel { @@ -1577,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/defaults.go b/android/defaults.go index 03b2efbac..7906e946c 100644 --- a/android/defaults.go +++ b/android/defaults.go @@ -448,7 +448,7 @@ func (defaultable *DefaultableModuleBase) applyDefaults(ctx TopDownMutatorContex } for _, defaults := range defaultsList { - if ctx.Config().runningAsBp2Build { + if ctx.Config().BuildMode == Bp2build { applyNamespacedVariableDefaults(defaults, ctx) } diff --git a/android/filegroup.go b/android/filegroup.go index 504223de9..e609f6362 100644 --- a/android/filegroup.go +++ b/android/filegroup.go @@ -16,6 +16,7 @@ package android import ( "path/filepath" + "regexp" "strings" "android/soong/bazel" @@ -37,11 +38,44 @@ func IsFilegroup(ctx bazel.OtherModuleContext, m blueprint.Module) bool { return ctx.OtherModuleType(m) == "filegroup" } +var ( + // ignoring case, checks for proto or protos as an independent word in the name, whether at the + // beginning, end, or middle. e.g. "proto.foo", "bar-protos", "baz_proto_srcs" would all match + filegroupLikelyProtoPattern = regexp.MustCompile("(?i)(^|[^a-z])proto(s)?([^a-z]|$)") + filegroupLikelyAidlPattern = regexp.MustCompile("(?i)(^|[^a-z])aidl([^a-z]|$)") + + ProtoSrcLabelPartition = bazel.LabelPartition{ + Extensions: []string{".proto"}, + LabelMapper: isFilegroupWithPattern(filegroupLikelyProtoPattern), + } + AidlSrcLabelPartition = bazel.LabelPartition{ + Extensions: []string{".aidl"}, + LabelMapper: isFilegroupWithPattern(filegroupLikelyAidlPattern), + } +) + +func isFilegroupWithPattern(pattern *regexp.Regexp) bazel.LabelMapper { + return func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) { + m, exists := ctx.ModuleFromName(label.OriginalModuleName) + labelStr := label.Label + if !exists || !IsFilegroup(ctx, m) { + return labelStr, false + } + likelyMatched := pattern.MatchString(label.OriginalModuleName) + return labelStr, likelyMatched + } +} + // https://docs.bazel.build/versions/master/be/general.html#filegroup type bazelFilegroupAttributes struct { Srcs bazel.LabelListAttribute } +type bazelAidlLibraryAttributes struct { + Srcs bazel.LabelListAttribute + Strip_import_prefix *string +} + // ConvertWithBp2build performs bp2build conversion of filegroup func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) { srcs := bazel.MakeLabelListAttribute( @@ -67,16 +101,33 @@ func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) { } } - attrs := &bazelFilegroupAttributes{ - Srcs: srcs, - } + // Convert module that has only AIDL files to aidl_library + // If the module has a mixed bag of AIDL and non-AIDL files, split the filegroup manually + // and then convert + if fg.ShouldConvertToAidlLibrary(ctx) { + attrs := &bazelAidlLibraryAttributes{ + Srcs: srcs, + Strip_import_prefix: fg.properties.Path, + } - props := bazel.BazelTargetModuleProperties{ - Rule_class: "filegroup", - Bzl_load_location: "//build/bazel/rules:filegroup.bzl", - } + props := bazel.BazelTargetModuleProperties{ + Rule_class: "aidl_library", + Bzl_load_location: "//build/bazel/rules/aidl:library.bzl", + } + + ctx.CreateBazelTargetModule(props, CommonAttributes{Name: fg.Name()}, attrs) + } else { + attrs := &bazelFilegroupAttributes{ + Srcs: srcs, + } - ctx.CreateBazelTargetModule(props, CommonAttributes{Name: fg.Name()}, attrs) + props := bazel.BazelTargetModuleProperties{ + Rule_class: "filegroup", + Bzl_load_location: "//build/bazel/rules:filegroup.bzl", + } + + ctx.CreateBazelTargetModule(props, CommonAttributes{Name: fg.Name()}, attrs) + } } type fileGroupProperties struct { @@ -99,12 +150,14 @@ type fileGroupProperties struct { type fileGroup struct { ModuleBase BazelModuleBase + Bp2buildAidlLibrary properties fileGroupProperties srcs Paths } var _ MixedBuildBuildable = (*fileGroup)(nil) var _ SourceFileProducer = (*fileGroup)(nil) +var _ Bp2buildAidlLibrary = (*fileGroup)(nil) // filegroup contains a list of files that are referenced by other modules // properties (such as "srcs") using the syntax ":<name>". filegroup are @@ -188,3 +241,36 @@ func (fg *fileGroup) ProcessBazelQueryResponse(ctx ModuleContext) { } fg.srcs = bazelOuts } + +func (fg *fileGroup) ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) bool { + if len(fg.properties.Srcs) == 0 || !fg.ShouldConvertWithBp2build(ctx) { + return false + } + for _, src := range fg.properties.Srcs { + if !strings.HasSuffix(src, ".aidl") { + return false + } + } + return true +} + +func (fg *fileGroup) GetAidlLibraryLabel(ctx BazelConversionPathContext) string { + if ctx.OtherModuleDir(fg.module) == ctx.ModuleDir() { + return ":" + fg.Name() + } else { + return fg.GetBazelLabel(ctx, fg) + } +} + +// 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 module, ok := ctx.ModuleFromName(name); ok { + if IsFilegroup(ctx, module) { + if fg, ok := module.(Bp2buildAidlLibrary); ok { + return fg.ShouldConvertToAidlLibrary(ctx) + } + } + } + return false +} diff --git a/android/fixture.go b/android/fixture.go index f71893571..f33e7189d 100644 --- a/android/fixture.go +++ b/android/fixture.go @@ -642,6 +642,20 @@ type TestResult struct { NinjaDeps []string } +type TestPathContext struct { + *TestResult +} + +var _ PathContext = &TestPathContext{} + +func (t *TestPathContext) Config() Config { + return t.TestResult.Config +} + +func (t *TestPathContext) AddNinjaFileDeps(deps ...string) { + panic("unimplemented") +} + func createFixture(t *testing.T, buildDir string, preparers []*simpleFixturePreparer) Fixture { config := TestConfig(buildDir, nil, "", nil) ctx := NewTestContext(config) diff --git a/android/module.go b/android/module.go index bf62080a3..5908233a2 100644 --- a/android/module.go +++ b/android/module.go @@ -942,12 +942,19 @@ type CommonTestOptions struct { // If the test is a hostside (no device required) unittest that shall be run // during presubmit check. Unit_test *bool + + // Tags provide additional metadata to customize test execution by downstream + // test runners. The tags have no special meaning to Soong. + Tags []string } // SetAndroidMkEntries sets AndroidMkEntries according to the value of base // `test_options`. func (t *CommonTestOptions) SetAndroidMkEntries(entries *AndroidMkEntries) { entries.SetBoolIfTrue("LOCAL_IS_UNIT_TEST", Bool(t.Unit_test)) + if len(t.Tags) > 0 { + entries.AddStrings("LOCAL_TEST_OPTIONS_TAGS", t.Tags...) + } } // The key to use in TaggedDistFiles when a Dist structure does not specify a @@ -2367,9 +2374,6 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) } func (m *ModuleBase) isHandledByBazel(ctx ModuleContext) (MixedBuildBuildable, bool) { - if !ctx.Config().BazelContext.BazelEnabled() { - return nil, false - } if mixedBuildMod, ok := m.module.(MixedBuildBuildable); ok { if mixedBuildMod.IsMixedBuildSupported(ctx) && MixedBuildsEnabled(ctx) { return mixedBuildMod, true diff --git a/android/module_test.go b/android/module_test.go index 835ab4c7c..0580bef24 100644 --- a/android/module_test.go +++ b/android/module_test.go @@ -912,7 +912,7 @@ func TestSortedUniqueNamedPaths(t *testing.T) { } } -func TestProcessCommonTestOptions(t *testing.T) { +func TestSetAndroidMkEntriesWithTestOptions(t *testing.T) { tests := []struct { name string testOptions CommonTestOptions @@ -939,6 +939,31 @@ func TestProcessCommonTestOptions(t *testing.T) { }, expected: map[string][]string{}, }, + { + name: "empty tag", + testOptions: CommonTestOptions{ + Tags: []string{}, + }, + expected: map[string][]string{}, + }, + { + name: "single tag", + testOptions: CommonTestOptions{ + Tags: []string{"tag1"}, + }, + expected: map[string][]string{ + "LOCAL_TEST_OPTIONS_TAGS": []string{"tag1"}, + }, + }, + { + name: "multiple tag", + testOptions: CommonTestOptions{ + Tags: []string{"tag1", "tag2", "tag3"}, + }, + expected: map[string][]string{ + "LOCAL_TEST_OPTIONS_TAGS": []string{"tag1", "tag2", "tag3"}, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/android/paths.go b/android/paths.go index 74d9f13f4..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 { @@ -1978,6 +1943,18 @@ func PathForTesting(paths ...string) Path { return testPath{basePath{path: p, rel: p}} } +func PathForTestingWithRel(path, rel string) Path { + p, err := validateSafePath(path, rel) + if err != nil { + panic(err) + } + r, err := validatePath(rel) + if err != nil { + panic(err) + } + return testPath{basePath{path: p, rel: r}} +} + // PathsForTesting returns a Path constructed from each element in strs. It should only be used from within tests. func PathsForTesting(strs ...string) Paths { p := make(Paths, len(strs)) diff --git a/android/proto.go b/android/proto.go index c3759f8ad..8ad16a6a3 100644 --- a/android/proto.go +++ b/android/proto.go @@ -16,7 +16,6 @@ package android import ( "android/soong/bazel" - "regexp" "strings" "github.com/google/blueprint" @@ -27,14 +26,6 @@ const ( canonicalPathFromRootDefault = true ) -var ( - // ignoring case, checks for proto or protos as an independent word in the name, whether at the - // beginning, end, or middle. e.g. "proto.foo", "bar-protos", "baz_proto_srcs" would all match - filegroupLikelyProtoPattern = regexp.MustCompile("(?i)(^|[^a-z])proto(s)?([^a-z]|$)") - - ProtoSrcLabelPartition = bazel.LabelPartition{Extensions: []string{".proto"}, LabelMapper: isProtoFilegroup} -) - // TODO(ccross): protos are often used to communicate between multiple modules. If the only // way to convert a proto to source is to reference it as a source file, and external modules cannot // reference source files in other modules, then every module that owns a proto file will need to @@ -213,13 +204,3 @@ func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, m *ModuleBase, srcs baz return info, true } - -func isProtoFilegroup(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) { - m, exists := ctx.ModuleFromName(label.OriginalModuleName) - labelStr := label.Label - if !exists || !IsFilegroup(ctx, m) { - return labelStr, false - } - likelyProtos := filegroupLikelyProtoPattern.MatchString(label.OriginalModuleName) - return labelStr, likelyProtos -} diff --git a/android/register.go b/android/register.go index 5832b1bba..d4ce5f166 100644 --- a/android/register.go +++ b/android/register.go @@ -164,10 +164,6 @@ func NewContext(config Config) *Context { return ctx } -func (ctx *Context) SetRunningAsBp2build() { - ctx.config.runningAsBp2Build = true -} - // RegisterForBazelConversion registers an alternate shadow pipeline of // singletons, module types and mutators to register for converting Blueprint // files to semantically equivalent BUILD files. diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go index b25f24891..cd36ae066 100644 --- a/android/soong_config_modules.go +++ b/android/soong_config_modules.go @@ -382,7 +382,7 @@ func loadSoongConfigModuleTypeDefinition(ctx LoadHookContext, from string) map[s defer r.Close() mtDef, errs := soongconfig.Parse(r, from) - if ctx.Config().runningAsBp2Build { + if ctx.Config().BuildMode == Bp2build { ctx.Config().Bp2buildSoongConfigDefinitions.AddVars(*mtDef) } @@ -398,7 +398,7 @@ func loadSoongConfigModuleTypeDefinition(ctx LoadHookContext, from string) map[s for name, moduleType := range mtDef.ModuleTypes { factory := globalModuleTypes[moduleType.BaseModuleType] if factory != nil { - factories[name] = configModuleFactory(factory, moduleType, ctx.Config().runningAsBp2Build) + factories[name] = configModuleFactory(factory, moduleType, ctx.Config().BuildMode == Bp2build) } else { reportErrors(ctx, from, fmt.Errorf("missing global module type factory for %q", moduleType.BaseModuleType)) diff --git a/android/test_config.go b/android/test_config.go index f36e8ba6a..0f88d5164 100644 --- a/android/test_config.go +++ b/android/test_config.go @@ -118,6 +118,11 @@ func modifyTestConfigForMusl(config Config) { config.BuildOSCommonTarget = getCommonTargets(config.Targets[config.BuildOS])[0] } +func modifyTestConfigForMuslArm64HostCross(config Config) { + config.Targets[LinuxMusl] = append(config.Targets[LinuxMusl], + Target{config.BuildOS, Arch{ArchType: Arm64}, NativeBridgeDisabled, "", "", true}) +} + // TestArchConfig returns a Config object suitable for using for tests that // need to run the arch mutator. func TestArchConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config { diff --git a/android/testing.go b/android/testing.go index b4429ca91..37085011b 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 @@ -457,7 +457,7 @@ func (ctx *TestContext) Register() { // RegisterForBazelConversion prepares a test context for bp2build conversion. func (ctx *TestContext) RegisterForBazelConversion() { - ctx.SetRunningAsBp2build() + ctx.config.BuildMode = Bp2build RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch) } diff --git a/android/variable.go b/android/variable.go index 2d7b0bf8e..7a080fef7 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"` diff --git a/apex/apex.go b/apex/apex.go index b391a6cca..949809ad9 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -192,6 +192,10 @@ type apexBundleProperties struct { // with the tool to sign payload contents. Custom_sign_tool *string + // Whether this is a dynamic common lib apex, if so the native shared libs will be placed + // in a special way that include the digest of the lib file under /lib(64)? + Dynamic_common_lib_apex *bool + // Canonical name of this APEX bundle. Used to determine the path to the // activated APEX on device (i.e. /apex/<apexVariationName>), and used for the // apex mutator variations. For override_apex modules, this is the name of the @@ -1472,6 +1476,11 @@ func (a *apexBundle) testOnlyShouldForceCompression() bool { return proptools.Bool(a.properties.Test_only_force_compression) } +// See the dynamic_common_lib_apex property +func (a *apexBundle) dynamic_common_lib_apex() bool { + return proptools.BoolDefault(a.properties.Dynamic_common_lib_apex, false) +} + // These functions are interfacing with cc/sanitizer.go. The entire APEX (along with all of its // members) can be sanitized, either forcibly, or by the global configuration. For some of the // sanitizers, extra dependencies can be forcibly added as well. diff --git a/apex/builder.go b/apex/builder.go index f1b14484e..b95b3bdfd 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -39,6 +39,7 @@ func init() { pctx.Import("android/soong/cc/config") pctx.Import("android/soong/java") pctx.HostBinToolVariable("apexer", "apexer") + pctx.HostBinToolVariable("apexer_with_DCLA_preprocessing", "apexer_with_DCLA_preprocessing") // ART minimal builds (using the master-art manifest) do not have the "frameworks/base" // projects, and hence cannot build 'aapt2'. Use the SDK prebuilt instead. hostBinToolVariableWithPrebuilt := func(name, prebuiltDir, tool string) { @@ -115,7 +116,35 @@ var ( Rspfile: "${out}.copy_commands", RspfileContent: "${copy_commands}", Description: "APEX ${image_dir} => ${out}", - }, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", "opt_flags", "manifest", "payload_fs_type") + }, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", + "opt_flags", "manifest") + + DCLAApexRule = pctx.StaticRule("DCLAApexRule", blueprint.RuleParams{ + Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` + + `(. ${out}.copy_commands) && ` + + `APEXER_TOOL_PATH=${tool_path} ` + + `${apexer_with_DCLA_preprocessing} ` + + `--apexer ${apexer} ` + + `--canned_fs_config ${canned_fs_config} ` + + `${image_dir} ` + + `${out} ` + + `-- ` + + `--include_build_info ` + + `--force ` + + `--payload_type image ` + + `--key ${key} ` + + `--file_contexts ${file_contexts} ` + + `--manifest ${manifest} ` + + `${opt_flags} `, + CommandDeps: []string{"${apexer_with_DCLA_preprocessing}", "${apexer}", "${avbtool}", "${e2fsdroid}", + "${merge_zips}", "${mke2fs}", "${resize2fs}", "${sefcontext_compile}", "${make_f2fs}", + "${sload_f2fs}", "${make_erofs}", "${soong_zip}", "${zipalign}", "${aapt2}", + "prebuilts/sdk/current/public/android.jar"}, + Rspfile: "${out}.copy_commands", + RspfileContent: "${copy_commands}", + Description: "APEX ${image_dir} => ${out}", + }, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", + "opt_flags", "manifest", "is_DCLA") zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{ Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` + @@ -662,22 +691,41 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { optFlags = append(optFlags, "--payload_fs_type "+a.payloadFsType.string()) - ctx.Build(pctx, android.BuildParams{ - Rule: apexRule, - Implicits: implicitInputs, - Output: unsignedOutputFile, - Description: "apex (" + apexType.name() + ")", - Args: map[string]string{ - "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir, - "image_dir": imageDir.String(), - "copy_commands": strings.Join(copyCommands, " && "), - "manifest": a.manifestPbOut.String(), - "file_contexts": fileContexts.String(), - "canned_fs_config": cannedFsConfig.String(), - "key": a.privateKeyFile.String(), - "opt_flags": strings.Join(optFlags, " "), - }, - }) + if a.dynamic_common_lib_apex() { + ctx.Build(pctx, android.BuildParams{ + Rule: DCLAApexRule, + Implicits: implicitInputs, + Output: unsignedOutputFile, + Description: "apex (" + apexType.name() + ")", + Args: map[string]string{ + "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir, + "image_dir": imageDir.String(), + "copy_commands": strings.Join(copyCommands, " && "), + "manifest": a.manifestPbOut.String(), + "file_contexts": fileContexts.String(), + "canned_fs_config": cannedFsConfig.String(), + "key": a.privateKeyFile.String(), + "opt_flags": strings.Join(optFlags, " "), + }, + }) + } else { + ctx.Build(pctx, android.BuildParams{ + Rule: apexRule, + Implicits: implicitInputs, + Output: unsignedOutputFile, + Description: "apex (" + apexType.name() + ")", + Args: map[string]string{ + "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir, + "image_dir": imageDir.String(), + "copy_commands": strings.Join(copyCommands, " && "), + "manifest": a.manifestPbOut.String(), + "file_contexts": fileContexts.String(), + "canned_fs_config": cannedFsConfig.String(), + "key": a.privateKeyFile.String(), + "opt_flags": strings.Join(optFlags, " "), + }, + }) + } // TODO(jiyong): make the two rules below as separate functions apexProtoFile := android.PathForModuleOut(ctx, a.Name()+".pb"+suffix) diff --git a/bazel/configurability.go b/bazel/configurability.go index 0ab49eb12..d9b0a12b4 100644 --- a/bazel/configurability.go +++ b/bazel/configurability.go @@ -27,7 +27,7 @@ const ( archX86_64 = "x86_64" // OsType names in arch.go - osAndroid = "android" + OsAndroid = "android" osDarwin = "darwin" osLinux = "linux_glibc" osLinuxMusl = "linux_musl" @@ -64,6 +64,9 @@ const ( ConditionsDefaultSelectKey = "//conditions:default" productVariableBazelPackage = "//build/bazel/product_variables" + + AndroidAndInApex = "android-in_apex" + AndroidAndNonApex = "android-non_apex" ) var ( @@ -85,7 +88,7 @@ var ( // A map of target operating systems to the Bazel label of the // constraint_value for the @platforms//os:os constraint_setting platformOsMap = map[string]string{ - osAndroid: "//build/bazel/platforms/os:android", + OsAndroid: "//build/bazel/platforms/os:android", osDarwin: "//build/bazel/platforms/os:darwin", osLinux: "//build/bazel/platforms/os:linux", osLinuxMusl: "//build/bazel/platforms/os:linux_musl", @@ -120,7 +123,7 @@ var ( // TODO(cparsons): Source from arch.go; this task is nontrivial, as it currently results // in a cyclic dependency. osToArchMap = map[string][]string{ - osAndroid: {archArm, archArm64, archX86, archX86_64}, + OsAndroid: {archArm, archArm64, archX86, archX86_64}, osLinux: {archX86, archX86_64}, osLinuxMusl: {archX86, archX86_64}, osDarwin: {archArm64, archX86_64}, @@ -128,6 +131,12 @@ var ( // TODO(cparsons): According to arch.go, this should contain archArm, archArm64, as well. osWindows: {archX86, archX86_64}, } + + osAndInApexMap = map[string]string{ + AndroidAndInApex: "//build/bazel/rules/apex:android-in_apex", + AndroidAndNonApex: "//build/bazel/rules/apex:android-non_apex", + ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, + } ) // basic configuration types @@ -139,6 +148,7 @@ const ( os osArch productVariables + osAndInApex ) func osArchString(os string, arch string) string { @@ -152,6 +162,7 @@ func (ct configurationType) String() string { os: "os", osArch: "arch_os", productVariables: "product_variables", + osAndInApex: "os_in_apex", }[ct] } @@ -175,6 +186,10 @@ func (ct configurationType) validateConfig(config string) { } case productVariables: // do nothing + case osAndInApex: + if _, ok := osAndInApexMap[config]; !ok { + panic(fmt.Errorf("Unknown os+in_apex config: %s", config)) + } default: panic(fmt.Errorf("Unrecognized ConfigurationType %d", ct)) } @@ -198,6 +213,8 @@ func (ca ConfigurationAxis) SelectKey(config string) string { return ConditionsDefaultSelectKey } return fmt.Sprintf("%s:%s", productVariableBazelPackage, config) + case osAndInApex: + return osAndInApexMap[config] default: panic(fmt.Errorf("Unrecognized ConfigurationType %d", ca.configurationType)) } @@ -212,6 +229,8 @@ var ( OsConfigurationAxis = ConfigurationAxis{configurationType: os} // An axis for arch+os-specific configurations OsArchConfigurationAxis = ConfigurationAxis{configurationType: osArch} + // An axis for os+in_apex-specific configurations + OsAndInApexAxis = ConfigurationAxis{configurationType: osAndInApex} ) // ProductVariableConfigurationAxis returns an axis for the given product variable diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go index d32e61969..5cee6acf8 100644 --- a/bazel/cquery/request_type.go +++ b/bazel/cquery/request_type.go @@ -134,13 +134,13 @@ else: sharedLibraries = [] rootSharedLibraries = [] -shared_info_tag = "@_builtins//:common/cc/experimental_cc_shared_library.bzl%CcSharedLibraryInfo" +shared_info_tag = "//build/bazel/rules/cc:cc_library_shared.bzl%CcSharedLibraryOutputInfo" + if shared_info_tag in providers(target): shared_info = providers(target)[shared_info_tag] - for lib in shared_info.linker_input.libraries: - path = lib.dynamic_library.path - rootSharedLibraries += [path] - sharedLibraries.append(path) + path = shared_info.output_file.path + sharedLibraries.append(path) + rootSharedLibraries += [path] else: for linker_input in linker_inputs: for library in linker_input.libraries: diff --git a/bazel/properties.go b/bazel/properties.go index 963e27bdd..13e36b582 100644 --- a/bazel/properties.go +++ b/bazel/properties.go @@ -119,7 +119,7 @@ func (ll *LabelList) uniqueParentDirectories() []string { return dirs } -// Add inserts the label Label at the end of the LabelList. +// Add inserts the label Label at the end of the LabelList.Includes. func (ll *LabelList) Add(label *Label) { if label == nil { return @@ -127,6 +127,14 @@ func (ll *LabelList) Add(label *Label) { ll.Includes = append(ll.Includes, *label) } +// AddExclude inserts the label Label at the end of the LabelList.Excludes. +func (ll *LabelList) AddExclude(label *Label) { + if label == nil { + return + } + ll.Excludes = append(ll.Excludes, *label) +} + // Append appends the fields of other labelList to the corresponding fields of ll. func (ll *LabelList) Append(other LabelList) { if len(ll.Includes) > 0 || len(other.Includes) > 0 { @@ -137,6 +145,30 @@ func (ll *LabelList) Append(other LabelList) { } } +// Partition splits a LabelList into two LabelLists depending on the return value +// of the predicate. +// This function preserves the Includes and Excludes, but it does not provide +// that information to the partition function. +func (ll *LabelList) Partition(predicate func(label Label) bool) (LabelList, LabelList) { + predicated := LabelList{} + unpredicated := LabelList{} + for _, include := range ll.Includes { + if predicate(include) { + predicated.Add(&include) + } else { + unpredicated.Add(&include) + } + } + for _, exclude := range ll.Excludes { + if predicate(exclude) { + predicated.AddExclude(&exclude) + } else { + unpredicated.AddExclude(&exclude) + } + } + return predicated, unpredicated +} + // UniqueSortedBazelLabels takes a []Label and deduplicates the labels, and returns // the slice in a sorted order. func UniqueSortedBazelLabels(originalLabels []Label) []Label { @@ -332,7 +364,7 @@ func (la *LabelAttribute) SetSelectValue(axis ConfigurationAxis, config string, switch axis.configurationType { case noConfig: la.Value = &value - case arch, os, osArch, productVariables: + case arch, os, osArch, productVariables, osAndInApex: if la.ConfigurableValues == nil { la.ConfigurableValues = make(configurableLabels) } @@ -348,7 +380,7 @@ func (la *LabelAttribute) SelectValue(axis ConfigurationAxis, config string) *La switch axis.configurationType { case noConfig: return la.Value - case arch, os, osArch, productVariables: + case arch, os, osArch, productVariables, osAndInApex: return la.ConfigurableValues[axis][config] default: panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis)) @@ -424,7 +456,7 @@ func (ba *BoolAttribute) SetSelectValue(axis ConfigurationAxis, config string, v switch axis.configurationType { case noConfig: ba.Value = value - case arch, os, osArch, productVariables: + case arch, os, osArch, productVariables, osAndInApex: if ba.ConfigurableValues == nil { ba.ConfigurableValues = make(configurableBools) } @@ -540,7 +572,7 @@ func (ba BoolAttribute) SelectValue(axis ConfigurationAxis, config string) *bool switch axis.configurationType { case noConfig: return ba.Value - case arch, os, osArch, productVariables: + case arch, os, osArch, productVariables, osAndInApex: if v, ok := ba.ConfigurableValues[axis][config]; ok { return &v } else { @@ -676,7 +708,7 @@ func (lla *LabelListAttribute) SetSelectValue(axis ConfigurationAxis, config str switch axis.configurationType { case noConfig: lla.Value = list - case arch, os, osArch, productVariables: + case arch, os, osArch, productVariables, osAndInApex: if lla.ConfigurableValues == nil { lla.ConfigurableValues = make(configurableLabelLists) } @@ -692,8 +724,8 @@ func (lla *LabelListAttribute) SelectValue(axis ConfigurationAxis, config string switch axis.configurationType { case noConfig: return lla.Value - case arch, os, osArch, productVariables: - return lla.ConfigurableValues[axis][config] + case arch, os, osArch, productVariables, osAndInApex: + return (lla.ConfigurableValues[axis][config]) default: panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis)) } @@ -822,6 +854,29 @@ func (lla *LabelListAttribute) ResolveExcludes() { } } +// Partition splits a LabelListAttribute into two LabelListAttributes depending +// on the return value of the predicate. +// This function preserves the Includes and Excludes, but it does not provide +// that information to the partition function. +func (lla LabelListAttribute) Partition(predicate func(label Label) bool) (LabelListAttribute, LabelListAttribute) { + predicated := LabelListAttribute{} + unpredicated := LabelListAttribute{} + + valuePartitionTrue, valuePartitionFalse := lla.Value.Partition(predicate) + predicated.SetValue(valuePartitionTrue) + unpredicated.SetValue(valuePartitionFalse) + + for axis, selectValueLabelLists := range lla.ConfigurableValues { + for config, labelList := range selectValueLabelLists { + configPredicated, configUnpredicated := labelList.Partition(predicate) + predicated.SetSelectValue(axis, config, configPredicated) + unpredicated.SetSelectValue(axis, config, configUnpredicated) + } + } + + return predicated, unpredicated +} + // OtherModuleContext is a limited context that has methods with information about other modules. type OtherModuleContext interface { ModuleFromName(name string) (blueprint.Module, bool) @@ -1189,7 +1244,7 @@ func (sla *StringListAttribute) SetSelectValue(axis ConfigurationAxis, config st switch axis.configurationType { case noConfig: sla.Value = list - case arch, os, osArch, productVariables: + case arch, os, osArch, productVariables, osAndInApex: if sla.ConfigurableValues == nil { sla.ConfigurableValues = make(configurableStringLists) } @@ -1205,7 +1260,7 @@ func (sla *StringListAttribute) SelectValue(axis ConfigurationAxis, config strin switch axis.configurationType { case noConfig: return sla.Value - case arch, os, osArch, productVariables: + case arch, os, osArch, productVariables, osAndInApex: return sla.ConfigurableValues[axis][config] default: panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis)) diff --git a/bazel/properties_test.go b/bazel/properties_test.go index 7b76b747b..dc4d5b0f5 100644 --- a/bazel/properties_test.go +++ b/bazel/properties_test.go @@ -310,6 +310,134 @@ func TestResolveExcludes(t *testing.T) { } } +func TestLabelListAttributePartition(t *testing.T) { + testCases := []struct { + name string + input LabelListAttribute + predicated LabelListAttribute + unpredicated LabelListAttribute + predicate func(label Label) bool + }{ + { + name: "move all to predicated partition", + input: MakeLabelListAttribute(makeLabelList( + []string{"keep1", "throw1", "keep2", "throw2"}, + []string{"keep1", "throw1", "keep2", "throw2"}, + )), + predicated: MakeLabelListAttribute(makeLabelList( + []string{"keep1", "throw1", "keep2", "throw2"}, + []string{"keep1", "throw1", "keep2", "throw2"}, + )), + unpredicated: LabelListAttribute{}, + predicate: func(label Label) bool { + return true + }, + }, + { + name: "move all to unpredicated partition", + input: MakeLabelListAttribute(makeLabelList( + []string{"keep1", "throw1", "keep2", "throw2"}, + []string{"keep1", "throw1", "keep2", "throw2"}, + )), + predicated: LabelListAttribute{}, + unpredicated: MakeLabelListAttribute(makeLabelList( + []string{"keep1", "throw1", "keep2", "throw2"}, + []string{"keep1", "throw1", "keep2", "throw2"}, + )), + predicate: func(label Label) bool { + return false + }, + }, + { + name: "partition includes and excludes", + input: MakeLabelListAttribute(makeLabelList( + []string{"keep1", "throw1", "keep2", "throw2"}, + []string{"keep1", "throw1", "keep2", "throw2"}, + )), + predicated: MakeLabelListAttribute(makeLabelList( + []string{"keep1", "keep2"}, + []string{"keep1", "keep2"}, + )), + unpredicated: MakeLabelListAttribute(makeLabelList( + []string{"throw1", "throw2"}, + []string{"throw1", "throw2"}, + )), + predicate: func(label Label) bool { + return strings.HasPrefix(label.Label, "keep") + }, + }, + { + name: "partition excludes only", + input: MakeLabelListAttribute(makeLabelList( + []string{}, + []string{"keep1", "throw1", "keep2", "throw2"}, + )), + predicated: MakeLabelListAttribute(makeLabelList( + []string{}, + []string{"keep1", "keep2"}, + )), + unpredicated: MakeLabelListAttribute(makeLabelList( + []string{}, + []string{"throw1", "throw2"}, + )), + predicate: func(label Label) bool { + return strings.HasPrefix(label.Label, "keep") + }, + }, + { + name: "partition includes only", + input: MakeLabelListAttribute(makeLabelList( + []string{"keep1", "throw1", "keep2", "throw2"}, + []string{}, + )), + predicated: MakeLabelListAttribute(makeLabelList( + []string{"keep1", "keep2"}, + []string{}, + )), + unpredicated: MakeLabelListAttribute(makeLabelList( + []string{"throw1", "throw2"}, + []string{}, + )), + predicate: func(label Label) bool { + return strings.HasPrefix(label.Label, "keep") + }, + }, + { + name: "empty partition", + input: MakeLabelListAttribute(makeLabelList([]string{}, []string{})), + predicated: LabelListAttribute{}, + unpredicated: LabelListAttribute{}, + predicate: func(label Label) bool { + return true + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + predicated, unpredicated := tc.input.Partition(tc.predicate) + if !predicated.Value.Equals(tc.predicated.Value) { + t.Errorf("expected predicated labels to be %v; got %v", tc.predicated, predicated) + } + for axis, configs := range predicated.ConfigurableValues { + tcConfigs, ok := tc.predicated.ConfigurableValues[axis] + if !ok || !reflect.DeepEqual(configs, tcConfigs) { + t.Errorf("expected predicated labels to be %v; got %v", tc.predicated, predicated) + } + } + if !unpredicated.Value.Equals(tc.unpredicated.Value) { + t.Errorf("expected unpredicated labels to be %v; got %v", tc.unpredicated, unpredicated) + } + for axis, configs := range unpredicated.ConfigurableValues { + tcConfigs, ok := tc.unpredicated.ConfigurableValues[axis] + if !ok || !reflect.DeepEqual(configs, tcConfigs) { + t.Errorf("expected unpredicated labels to be %v; got %v", tc.unpredicated, unpredicated) + } + } + }) + } +} + // labelAddSuffixForTypeMapper returns a LabelMapper that adds suffix to label name for modules of // typ func labelAddSuffixForTypeMapper(suffix, typ string) LabelMapper { diff --git a/bp2build/Android.bp b/bp2build/Android.bp index cb25627b2..3d9fc5a2b 100644 --- a/bp2build/Android.bp +++ b/bp2build/Android.bp @@ -51,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", @@ -63,6 +64,7 @@ bootstrap_go_package { "java_plugin_conversion_test.go", "java_proto_conversion_test.go", "linker_config_conversion_test.go", + "ndk_headers_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/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/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..cf465335b 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,9 @@ 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 { - for _, target := range targets { - if target.handcrafted { - return true - } - } - return false -} - -// sort a list of BazelTargets in-place, by name, and by generated/handcrafted types. +// sort a list of BazelTargets in-place by name 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,18 +77,6 @@ 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" - } - res += target.content if i != len(targets)-1 { res += "\n\n" @@ -256,7 +227,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 +258,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. @@ -373,6 +323,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,29 +347,6 @@ 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 { var targets []BazelTarget for _, m := range m.Bp2buildTargets() { @@ -453,7 +389,6 @@ func generateBazelTarget(ctx bpToBuildContext, m bp2buildModule) BazelTarget { targetName, attributes, ), - handcrafted: false, } } diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go index 1ac7518a8..587b8d90c 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"`, }), }, @@ -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] @@ -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", diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go index 95869dd87..67d4a1c96 100644 --- a/bp2build/cc_binary_conversion_test.go +++ b/bp2build/cc_binary_conversion_test.go @@ -543,3 +543,129 @@ func TestCcBinaryConvertLex(t *testing.T) { }, }) } + +func TestCcBinaryRuntimeLibs(t *testing.T) { + runCcBinaryTests(t, ccBinaryBp2buildTestCase{ + description: "cc_binary with runtime libs", + blueprint: ` +cc_library { + name: "bar", + srcs: ["b.cc"], +} + +{rule_name} { + name: "foo", + srcs: ["a.cc"], + runtime_libs: ["bar"], +} +`, + targets: []testBazelTarget{ + {"cc_library_static", "bar_bp2build_cc_library_static", AttrNameToString{ + "local_includes": `["."]`, + "srcs": `["b.cc"]`, + "target_compatible_with": `["//build/bazel/platforms/os:android"]`, + }, + }, + {"cc_library_shared", "bar", AttrNameToString{ + "local_includes": `["."]`, + "srcs": `["b.cc"]`, + "target_compatible_with": `["//build/bazel/platforms/os:android"]`, + }, + }, + {"cc_binary", "foo", AttrNameToString{ + "local_includes": `["."]`, + "srcs": `["a.cc"]`, + "runtime_deps": `[":bar"]`, + }, + }, + }, + }) +} + +func TestCcBinaryWithInstructionSet(t *testing.T) { + runCcBinaryTests(t, ccBinaryBp2buildTestCase{ + description: "instruction set", + blueprint: ` +{rule_name} { + name: "foo", + arch: { + arm: { + instruction_set: "arm", + } + } +} +`, + targets: []testBazelTarget{ + {"cc_binary", "foo", AttrNameToString{ + "features": `select({ + "//build/bazel/platforms/arch:arm": [ + "arm_isa_arm", + "-arm_isa_thumb", + ], + "//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 e1b7b574f..5117c625e 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", @@ -1335,10 +1335,10 @@ func makeCcLibraryTargets(name string, attrs AttrNameToString) []string { "additional_linker_inputs": true, "linkopts": true, "strip": true, - "stubs_symbol_file": true, - "stubs_versions": true, "inject_bssl_hash": true, + "has_stubs": true, } + sharedAttrs := AttrNameToString{} staticAttrs := AttrNameToString{} for key, val := range attrs { @@ -1349,12 +1349,32 @@ 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} } +func makeCcStubSuiteTargets(name string, attrs AttrNameToString) string { + if _, hasStubs := attrs["stubs_symbol_file"]; !hasStubs { + return "" + } + STUB_SUITE_ATTRS := map[string]string{ + "stubs_symbol_file": "symbol_file", + "stubs_versions": "versions", + "soname": "soname", + "source_library": "source_library", + } + + stubSuiteAttrs := AttrNameToString{} + for key, _ := range attrs { + if _, stubSuiteAttr := STUB_SUITE_ATTRS[key]; stubSuiteAttr { + stubSuiteAttrs[STUB_SUITE_ATTRS[key]] = attrs[key] + } + } + return MakeBazelTarget("cc_stub_suite", name+"_stub_libs", stubSuiteAttrs) +} + func TestCCLibraryNoLibCrtFalse(t *testing.T) { runCcLibraryTestCase(t, Bp2buildTestCase{ ModuleTypeUnderTest: "cc_library", @@ -1663,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{}), }, }) } @@ -1686,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": "[]", }), }, @@ -1713,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": "[]", }), }, @@ -1796,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", @@ -2014,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), }, }) @@ -2033,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), }, }) }) @@ -2050,14 +2070,14 @@ 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{ + }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "dynamic_deps": `[":libprotobuf-cpp-lite"]`, }), }, @@ -2075,15 +2095,15 @@ 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{ + }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "dynamic_deps": `[":libprotobuf-cpp-lite"]`, }), }, @@ -2101,14 +2121,14 @@ 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{ + }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "dynamic_deps": `[":libprotobuf-cpp-lite"]`, }), }, @@ -2128,14 +2148,14 @@ 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{ + }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "dynamic_deps": `[":libprotobuf-cpp-full"]`, }), }, @@ -2155,14 +2175,14 @@ 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{ + }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ "dynamic_deps": `[":libprotobuf-cpp-lite"]`, }), }, @@ -2182,14 +2202,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"]`, }), @@ -2242,65 +2262,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"]`, @@ -2399,10 +2419,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"], @@ -2439,13 +2459,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": [], @@ -2458,6 +2478,19 @@ func TestCcLibraryStaticDisabledForSomeArch(t *testing.T) { } func TestCcLibraryStubs(t *testing.T) { + expectedBazelTargets := makeCcLibraryTargets("a", AttrNameToString{ + "has_stubs": `True`, + }) + expectedBazelTargets = append(expectedBazelTargets, makeCcStubSuiteTargets("a", AttrNameToString{ + "soname": `"a.so"`, + "source_library": `":a"`, + "stubs_symbol_file": `"a.map.txt"`, + "stubs_versions": `[ + "28", + "29", + "current", + ]`, + })) runCcLibraryTestCase(t, Bp2buildTestCase{ Description: "cc_library stubs", ModuleTypeUnderTest: "cc_library", @@ -2473,15 +2506,8 @@ cc_library { } `, }, - Blueprint: soongCcLibraryPreamble, - ExpectedBazelTargets: makeCcLibraryTargets("a", AttrNameToString{ - "stubs_symbol_file": `"a.map.txt"`, - "stubs_versions": `[ - "28", - "29", - "current", - ]`, - }), + Blueprint: soongCcLibraryPreamble, + ExpectedBazelTargets: expectedBazelTargets, }, ) } @@ -2521,14 +2547,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", @@ -2548,3 +2574,220 @@ func TestCcLibraryConvertLex(t *testing.T) { })...), }) } + +func TestCCLibraryRuntimeDeps(t *testing.T) { + runCcLibrarySharedTestCase(t, Bp2buildTestCase{ + Blueprint: `cc_library_shared { + name: "bar", +} + +cc_library { + name: "foo", + runtime_libs: ["foo"], +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_shared", "bar", AttrNameToString{ + "local_includes": `["."]`, + }), + MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + "runtime_deps": `[":foo"]`, + "local_includes": `["."]`, + }), + MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{ + "runtime_deps": `[":foo"]`, + "local_includes": `["."]`, + }), + }, + }) +} + +func TestCcLibraryWithInstructionSet(t *testing.T) { + runCcLibraryTestCase(t, Bp2buildTestCase{ + ModuleTypeUnderTest: "cc_library", + ModuleTypeUnderTestFactory: cc.LibraryFactory, + Blueprint: `cc_library { + name: "foo", + arch: { + arm: { + instruction_set: "arm", + } + } +} +`, + ExpectedBazelTargets: makeCcLibraryTargets("foo", AttrNameToString{ + "features": `select({ + "//build/bazel/platforms/arch:arm": [ + "arm_isa_arm", + "-arm_isa_thumb", + ], + "//conditions:default": [], + })`, + "local_includes": `["."]`, + }), + }) +} + +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", + ModuleTypeUnderTest: "cc_library", + ModuleTypeUnderTestFactory: cc.LibraryFactory, + Blueprint: ` +filegroup { + name: "A_aidl", + srcs: ["aidl/A.aidl"], + path: "aidl", +} +cc_library { + name: "foo", + srcs: [ + ":A_aidl", + "B.aidl", + ], +}`, + ExpectedBazelTargets: []string{ + MakeBazelTargetNoRestrictions("aidl_library", "A_aidl", AttrNameToString{ + "srcs": `["aidl/A.aidl"]`, + "strip_import_prefix": `"aidl"`, + }), + MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{ + "srcs": `["B.aidl"]`, + }), + 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_shared", "foo", AttrNameToString{ + "whole_archive_deps": `[":foo_cc_aidl_library"]`, + "local_includes": `["."]`, + }), + }, + }) +} + +func TestCcLibraryWithNonAdjacentAidlFilegroup(t *testing.T) { + runCcLibraryTestCase(t, Bp2buildTestCase{ + Description: "cc_library with non aidl filegroup", + ModuleTypeUnderTest: "cc_library", + ModuleTypeUnderTestFactory: cc.LibraryFactory, + Filesystem: map[string]string{ + "path/to/A/Android.bp": ` +filegroup { + name: "A_aidl", + srcs: ["aidl/A.aidl"], + path: "aidl", +}`, + }, + Blueprint: ` +cc_library { + name: "foo", + srcs: [ + ":A_aidl", + ], +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{ + "deps": `["//path/to/A:A_aidl"]`, + }), + MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{ + "whole_archive_deps": `[":foo_cc_aidl_library"]`, + "local_includes": `["."]`, + }), + 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 bb59c63e8..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,28 @@ 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"]`, + }), + }, + }) +} + +func TestCcLibraryHeadersWholeStaticLibsReexported(t *testing.T) { + runCcLibraryHeadersTestCase(t, Bp2buildTestCase{ + Description: "cc_library_headers whole_static_libs is reexported", + ModuleTypeUnderTest: "cc_library_headers", + ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory, + Filesystem: map[string]string{}, + Blueprint: soongCcLibraryHeadersPreamble + ` +cc_library_headers { + name: "foo_headers", + whole_static_libs: ["foo_export"], + bazel_module: { bp2build_available: true }, +} +` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"), + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{ "deps": `[":foo_export"]`, }), }, diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go index 6a4786254..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,13 +484,8 @@ cc_library_shared { `, }, Blueprint: soongCcLibraryPreamble, - ExpectedBazelTargets: []string{makeBazelTarget("cc_library_shared", "a", AttrNameToString{ - "stubs_symbol_file": `"a.map.txt"`, - "stubs_versions": `[ - "28", - "29", - "current", - ]`, + ExpectedBazelTargets: []string{MakeBazelTarget("cc_library_shared", "a", AttrNameToString{ + "has_stubs": `True`, }), }, }, @@ -515,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": "[]", })}, }) @@ -542,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", @@ -581,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"]`, @@ -605,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", @@ -624,3 +619,98 @@ func TestCCLibraryFlagSpaceSplitting(t *testing.T) { }, }) } + +func TestCCLibrarySharedRuntimeDeps(t *testing.T) { + runCcLibrarySharedTestCase(t, Bp2buildTestCase{ + Blueprint: `cc_library_shared { + name: "bar", +} + +cc_library_shared { + name: "foo", + runtime_libs: ["foo"], +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_shared", "bar", AttrNameToString{ + "local_includes": `["."]`, + }), + 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 ddb7bf94b..0e47ee816 100644 --- a/bp2build/cc_library_static_conversion_test.go +++ b/bp2build/cc_library_static_conversion_test.go @@ -15,12 +15,12 @@ package bp2build import ( + "fmt" + "testing" + "android/soong/android" "android/soong/cc" "android/soong/genrule" - "fmt" - - "testing" ) const ( @@ -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": [], @@ -1419,18 +1419,18 @@ cc_library_static { } `, ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "all", AttrNameToString{ + 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", "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", "used_in_bionic_oses", AttrNameToString{}), }, }) } @@ -1446,11 +1446,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 +1466,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 +1483,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,9 +1553,31 @@ func TestCcLibraryStaticStl(t *testing.T) { %s }`, tc.prop), ExpectedBazelTargets: []string{ - makeBazelTarget("cc_library_static", "foo", tc.attr), + MakeBazelTarget("cc_library_static", "foo", tc.attr), }, }) }) } } + +func TestCCLibraryStaticRuntimeDeps(t *testing.T) { + runCcLibrarySharedTestCase(t, Bp2buildTestCase{ + Blueprint: `cc_library_shared { + name: "bar", +} + +cc_library_static { + name: "foo", + runtime_libs: ["foo"], +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("cc_library_shared", "bar", AttrNameToString{ + "local_includes": `["."]`, + }), + 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..9d91e40ba 100644 --- a/bp2build/cc_prebuilt_library_conversion_test.go +++ b/bp2build/cc_prebuilt_library_conversion_test.go @@ -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"`, }), }, @@ -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", @@ -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"`, }), }, @@ -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"`, }), }, diff --git a/bp2build/cc_prebuilt_library_shared_test.go b/bp2build/cc_prebuilt_library_shared_test.go index bcf0ce20a..9cee2dde5 100644 --- a/bp2build/cc_prebuilt_library_shared_test.go +++ b/bp2build/cc_prebuilt_library_shared_test.go @@ -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"`, }), }, @@ -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", diff --git a/bp2build/cc_prebuilt_library_static_test.go b/bp2build/cc_prebuilt_library_static_test.go index 489a53d75..7c224f14c 100644 --- a/bp2build/cc_prebuilt_library_static_test.go +++ b/bp2build/cc_prebuilt_library_static_test.go @@ -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"`, }), }, @@ -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", @@ -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..6fb28236b 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,17 +96,9 @@ 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" + + // Hardcode the default visibility. + content += "package(default_visibility = [\"//visibility:public\"])\n" content += targets.LoadStatements() } else if mode == QueryView { content = soongModuleLoad diff --git a/bp2build/filegroup_conversion_test.go b/bp2build/filegroup_conversion_test.go index b598b855e..de09a1787 100644 --- a/bp2build/filegroup_conversion_test.go +++ b/bp2build/filegroup_conversion_test.go @@ -56,3 +56,68 @@ filegroup { ExpectedErr: fmt.Errorf("filegroup 'foo' cannot contain a file with the same name"), }) } + +func TestFilegroupWithAidlSrcs(t *testing.T) { + testcases := []struct { + name string + bp string + expectedBazelAttrs AttrNameToString + }{ + { + name: "filegroup with only aidl srcs", + bp: ` + filegroup { + name: "foo", + srcs: ["aidl/foo.aidl"], + path: "aidl", + }`, + expectedBazelAttrs: AttrNameToString{ + "srcs": `["aidl/foo.aidl"]`, + "strip_import_prefix": `"aidl"`, + }, + }, + { + name: "filegroup without path", + bp: ` + filegroup { + name: "foo", + srcs: ["aidl/foo.aidl"], + }`, + expectedBazelAttrs: AttrNameToString{ + "srcs": `["aidl/foo.aidl"]`, + }, + }, + } + + for _, test := range testcases { + expectedBazelTargets := []string{ + MakeBazelTargetNoRestrictions("aidl_library", "foo", test.expectedBazelAttrs), + } + runFilegroupTestCase(t, Bp2buildTestCase{ + Description: test.name, + Blueprint: test.bp, + ExpectedBazelTargets: expectedBazelTargets, + }) + } +} + +func TestFilegroupWithAidlAndNonAidlSrcs(t *testing.T) { + runFilegroupTestCase(t, Bp2buildTestCase{ + Description: "filegroup with aidl and non-aidl srcs", + Filesystem: map[string]string{}, + Blueprint: ` +filegroup { + name: "foo", + srcs: [ + "aidl/foo.aidl", + "buf.proto", + ], +}`, + ExpectedBazelTargets: []string{ + MakeBazelTargetNoRestrictions("filegroup", "foo", AttrNameToString{ + "srcs": `[ + "aidl/foo.aidl", + "buf.proto", + ]`}), + }}) +} 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 7fa19d950..4a4da18d0 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", @@ -372,3 +372,165 @@ func TestJavaLibraryResourcesFailsWithMultipleDirs(t *testing.T) { ExpectedBazelTargets: []string{}, }) } + +func TestJavaLibraryAidl(t *testing.T) { + runJavaLibraryTestCase(t, Bp2buildTestCase{ + Description: "Java library - aidl creates separate dependency", + ModuleTypeUnderTest: "java_library", + ModuleTypeUnderTestFactory: java.LibraryFactory, + Blueprint: `java_library { + name: "example_lib", + srcs: [ + "a.java", + "b.java", + "a.aidl", + "b.aidl", + ], + bazel_module: { bp2build_available: true }, +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("aidl_library", "example_lib_aidl_library", AttrNameToString{ + "srcs": `[ + "a.aidl", + "b.aidl", + ]`, + }), + MakeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{ + "deps": `[":example_lib_aidl_library"]`, + }), + MakeBazelTarget("java_library", "example_lib", AttrNameToString{ + "deps": `[":example_lib_java_aidl_library"]`, + "exports": `[":example_lib_java_aidl_library"]`, + "srcs": `[ + "a.java", + "b.java", + ]`, + }), + }}) +} + +func TestJavaLibraryAidlSrcsNoFileGroup(t *testing.T) { + runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{ + Description: "Java library - aidl filegroup is parsed", + ModuleTypeUnderTest: "java_library", + ModuleTypeUnderTestFactory: java.LibraryFactory, + Blueprint: ` +java_library { + name: "example_lib", + srcs: [ + "a.java", + "b.aidl", + ], + bazel_module: { bp2build_available: true }, +}`, + ExpectedBazelTargets: []string{ + MakeBazelTarget("aidl_library", "example_lib_aidl_library", AttrNameToString{ + "srcs": `["b.aidl"]`, + }), + MakeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{ + "deps": `[":example_lib_aidl_library"]`, + }), + MakeBazelTarget("java_library", "example_lib", AttrNameToString{ + "deps": `[":example_lib_java_aidl_library"]`, + "exports": `[":example_lib_java_aidl_library"]`, + "srcs": `["a.java"]`, + }), + }, + }, func(ctx android.RegistrationContext) { + ctx.RegisterModuleType("filegroup", android.FileGroupFactory) + }) +} + +func TestJavaLibraryAidlFilegroup(t *testing.T) { + runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{ + Description: "Java library - aidl filegroup is parsed", + ModuleTypeUnderTest: "java_library", + ModuleTypeUnderTestFactory: java.LibraryFactory, + Blueprint: ` +filegroup { + name: "random_other_files", + srcs: [ + "a.java", + "b.java", + ], +} +filegroup { + name: "aidl_files", + srcs: [ + "a.aidl", + "b.aidl", + ], +} +java_library { + name: "example_lib", + srcs: [ + "a.java", + "b.java", + ":aidl_files", + ":random_other_files", + ], + bazel_module: { bp2build_available: true }, +}`, + ExpectedBazelTargets: []string{ + MakeBazelTargetNoRestrictions("aidl_library", "aidl_files", AttrNameToString{ + "srcs": `[ + "a.aidl", + "b.aidl", + ]`, + }), + MakeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{ + "deps": `[":aidl_files"]`, + }), + MakeBazelTarget("java_library", "example_lib", AttrNameToString{ + "deps": `[":example_lib_java_aidl_library"]`, + "exports": `[":example_lib_java_aidl_library"]`, + "srcs": `[ + "a.java", + "b.java", + ":random_other_files", + ]`, + }), + MakeBazelTargetNoRestrictions("filegroup", "random_other_files", AttrNameToString{ + "srcs": `[ + "a.java", + "b.java", + ]`, + }), + }, + }, func(ctx android.RegistrationContext) { + 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) + }) +} 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/linker_config_conversion_test.go b/bp2build/linker_config_conversion_test.go index 3b8a36355..c4c4d8774 100644 --- a/bp2build/linker_config_conversion_test.go +++ b/bp2build/linker_config_conversion_test.go @@ -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/prebuilt_etc_conversion_test.go b/bp2build/prebuilt_etc_conversion_test.go index fce4c745b..6738b4bcb 100644 --- a/bp2build/prebuilt_etc_conversion_test.go +++ b/bp2build/prebuilt_etc_conversion_test.go @@ -45,7 +45,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 +75,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 +114,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({ @@ -153,7 +153,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,7 +174,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"`, diff --git a/bp2build/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go index 79da5d597..59055aa25 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"`, @@ -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"]`, @@ -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({ @@ -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..58587a698 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 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..b64678d27 100644 --- a/bp2build/testing.go +++ b/bp2build/testing.go @@ -444,6 +444,6 @@ 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) } diff --git a/cc/Android.bp b/cc/Android.bp index ce944674b..2963c77b5 100644 --- a/cc/Android.bp +++ b/cc/Android.bp @@ -99,10 +99,12 @@ bootstrap_go_package { "library_headers_test.go", "library_stub_test.go", "library_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 779160c5d..a9ba1a9e6 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -23,6 +23,7 @@ import ( "strings" "android/soong/android" + "android/soong/multitree" ) var ( @@ -625,6 +626,34 @@ func (p *prebuiltBinaryLinker) AndroidMkEntries(ctx AndroidMkContext, entries *a androidMkWriteAllowUndefinedSymbols(p.baseLinker, entries) } +func (a *apiLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { + entries.Class = "SHARED_LIBRARIES" + entries.SubName += multitree.GetApiImportSuffix() + + entries.ExtraEntries = append(entries.ExtraEntries, func(_ android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { + a.libraryDecorator.androidMkWriteExportedFlags(entries) + src := *a.properties.Src + path, file := filepath.Split(src) + stem, suffix, ext := android.SplitFileExt(file) + entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext) + entries.SetString("LOCAL_MODULE_SUFFIX", suffix) + entries.SetString("LOCAL_MODULE_STEM", stem) + entries.SetString("LOCAL_MODULE_PATH", path) + entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true) + entries.SetString("LOCAL_SOONG_TOC", a.toc().String()) + }) +} + +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 b2f248282..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, @@ -617,6 +618,7 @@ func binaryBp2build(ctx android.TopDownMutatorContext, m *Module, typ string) { Dynamic_deps: baseAttrs.implementationDynamicDeps, Whole_archive_deps: baseAttrs.wholeArchiveDeps, System_deps: baseAttrs.systemDynamicDeps, + Runtime_deps: baseAttrs.runtimeDeps, Local_includes: baseAttrs.localIncludes, Absolute_includes: baseAttrs.absoluteIncludes, @@ -643,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 @@ -667,6 +676,7 @@ type binaryAttributes struct { Dynamic_deps bazel.LabelListAttribute Whole_archive_deps bazel.LabelListAttribute System_deps bazel.LabelListAttribute + Runtime_deps bazel.LabelListAttribute Local_includes bazel.StringListAttribute Absolute_includes bazel.StringListAttribute diff --git a/cc/bp2build.go b/cc/bp2build.go index ffbcc0f22..8fb86f802 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -35,16 +35,18 @@ const ( llSrcPartition = "ll" cppSrcPartition = "cpp" protoSrcPartition = "proto" + aidlSrcPartition = "aidl" ) // staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties -- // properties which apply to either the shared or static version of a cc_library module. type staticOrSharedAttributes struct { - Srcs bazel.LabelListAttribute - Srcs_c bazel.LabelListAttribute - Srcs_as bazel.LabelListAttribute - Hdrs bazel.LabelListAttribute - Copts bazel.StringListAttribute + Srcs bazel.LabelListAttribute + Srcs_c bazel.LabelListAttribute + Srcs_as bazel.LabelListAttribute + Srcs_aidl bazel.LabelListAttribute + Hdrs bazel.LabelListAttribute + Copts bazel.StringListAttribute Deps bazel.LabelListAttribute Implementation_deps bazel.LabelListAttribute @@ -52,6 +54,7 @@ type staticOrSharedAttributes struct { Implementation_dynamic_deps bazel.LabelListAttribute Whole_archive_deps bazel.LabelListAttribute Implementation_whole_archive_deps bazel.LabelListAttribute + Runtime_deps bazel.LabelListAttribute System_dynamic_deps bazel.LabelListAttribute @@ -67,10 +70,17 @@ func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.Lab // Convert filegroup dependencies into extension-specific filegroups filtered in the filegroup.bzl // macro. addSuffixForFilegroup := func(suffix string) bazel.LabelMapper { - return func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) { - m, exists := ctx.ModuleFromName(label.OriginalModuleName) + return func(otherModuleCtx bazel.OtherModuleContext, label bazel.Label) (string, bool) { + + m, exists := otherModuleCtx.ModuleFromName(label.OriginalModuleName) labelStr := label.Label - if !exists || !android.IsFilegroup(ctx, m) { + 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) { return labelStr, false } return labelStr + suffix, true @@ -83,6 +93,7 @@ func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.Lab cSrcPartition: bazel.LabelPartition{Extensions: []string{".c"}, LabelMapper: addSuffixForFilegroup("_c_srcs")}, asSrcPartition: bazel.LabelPartition{Extensions: []string{".s", ".S"}, LabelMapper: addSuffixForFilegroup("_as_srcs")}, asmSrcPartition: bazel.LabelPartition{Extensions: []string{".asm"}}, + aidlSrcPartition: android.AidlSrcLabelPartition, // TODO(http://b/231968910): If there is ever a filegroup target that // contains .l or .ll files we will need to find a way to add a // LabelMapper for these that identifies these filegroups and @@ -281,7 +292,10 @@ type baseAttributes struct { compilerAttributes linkerAttributes + // A combination of compilerAttributes.features and linkerAttributes.features + features bazel.StringListAttribute protoDependency *bazel.LabelAttribute + aidlDependency *bazel.LabelAttribute } // Convenience struct to hold all attributes parsed from compiler properties. @@ -319,9 +333,14 @@ type compilerAttributes struct { includes BazelIncludes protoSrcs bazel.LabelListAttribute + aidlSrcs bazel.LabelListAttribute stubsSymbolFile *string stubsVersions bazel.StringListAttribute + + features bazel.StringListAttribute + + suffix bazel.StringAttribute } type filterOutFn func(string) bool @@ -385,6 +404,13 @@ func (ca *compilerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversi ca.absoluteIncludes.SetSelectValue(axis, config, props.Include_dirs) ca.localIncludes.SetSelectValue(axis, config, localIncludeDirs) + instructionSet := proptools.StringDefault(props.Instruction_set, "") + if instructionSet == "arm" { + ca.features.SetSelectValue(axis, config, []string{"arm_isa_arm", "-arm_isa_thumb"}) + } else if instructionSet != "" && instructionSet != "thumb" { + ctx.ModuleErrorf("Unknown value for instruction_set: %s", instructionSet) + } + // In Soong, cflags occur on the command line before -std=<val> flag, resulting in the value being // overridden. In Bazel we always allow overriding, via flags; however, this can cause // incompatibilities, so we remove "-std=" flags from Cflag properties while leaving it in other @@ -437,6 +463,7 @@ func (ca *compilerAttributes) finalize(ctx android.BazelConversionPathContext, i partitionedSrcs := groupSrcsByExtension(ctx, ca.srcs) ca.protoSrcs = partitionedSrcs[protoSrcPartition] + ca.aidlSrcs = partitionedSrcs[aidlSrcPartition] for p, lla := range partitionedSrcs { // if there are no sources, there is no need for headers @@ -469,12 +496,27 @@ func parseSrcs(ctx android.BazelConversionPathContext, props *BaseCompilerProper } allSrcsLabelList := android.BazelLabelForModuleSrcExcludes(ctx, props.Srcs, props.Exclude_srcs) + if len(props.Srcs) > 0 || len(props.Exclude_srcs) > 0 { anySrcs = true } + 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. @@ -641,9 +683,12 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) includes, absoluteIncludes := includesFromLabelList(headers.implementation) currAbsoluteIncludes := compilerAttrs.absoluteIncludes.SelectValue(axis, config) currAbsoluteIncludes = android.FirstUniqueStrings(append(currAbsoluteIncludes, absoluteIncludes...)) + compilerAttrs.absoluteIncludes.SetSelectValue(axis, config, currAbsoluteIncludes) + currIncludes := compilerAttrs.localIncludes.SelectValue(axis, config) currIncludes = android.FirstUniqueStrings(append(currIncludes, includes...)) + compilerAttrs.localIncludes.SetSelectValue(axis, config, currIncludes) if libraryProps, ok := archVariantLibraryProperties[axis][config].(*LibraryProperties); ok { @@ -651,9 +696,13 @@ 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) + } } } } + compilerAttrs.convertStlProps(ctx, module) (&linkerAttrs).convertStripProps(ctx, module) @@ -674,24 +723,106 @@ 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) convertedLSrcs := bp2BuildLex(ctx, module.Name(), compilerAttrs) (&compilerAttrs).srcs.Add(&convertedLSrcs.srcName) (&compilerAttrs).cSrcs.Add(&convertedLSrcs.cSrcName) + features := compilerAttrs.features.Clone().Append(linkerAttrs.features) + features.DeduplicateAxesFromBase() + return baseAttributes{ compilerAttrs, linkerAttrs, + *features, protoDep.protoDep, + aidlDep, } } +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, +) *bazel.LabelAttribute { + suffix := "_cc_aidl_library" + ccAidlLibrarylabel := m.Name() + suffix + + aidlLibraries := bp2buildAidlLibraries(ctx, m, aidlSrcs) + + if aidlLibraries.IsEmpty() { + return nil + } + + 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 +} + func bp2BuildParseSdkAttributes(module *Module) sdkAttributes { return sdkAttributes{ Sdk_version: module.Properties.Sdk_version, @@ -710,6 +841,7 @@ type linkerAttributes struct { implementationDeps bazel.LabelListAttribute dynamicDeps bazel.LabelListAttribute implementationDynamicDeps bazel.LabelListAttribute + runtimeDeps bazel.LabelListAttribute wholeArchiveDeps bazel.LabelListAttribute implementationWholeArchiveDeps bazel.LabelListAttribute systemDynamicDeps bazel.LabelListAttribute @@ -777,6 +909,45 @@ func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversion sharedDeps := maybePartitionExportedAndImplementationsDepsExcludes(ctx, !isBinary, sharedLibs, props.Exclude_shared_libs, props.Export_shared_lib_headers, bazelLabelForSharedDepsExcludes) la.dynamicDeps.SetSelectValue(axis, config, sharedDeps.export) la.implementationDynamicDeps.SetSelectValue(axis, config, sharedDeps.implementation) + if axis == bazel.NoConfigAxis || (axis == bazel.OsConfigurationAxis && config == bazel.OsAndroid) { + // If a dependency in la.implementationDynamicDeps has stubs, its stub variant should be + // used when the dependency is linked in a APEX. The dependencies in NoConfigAxis and + // OsConfigurationAxis/OsAndroid are grouped by having stubs or not, so Bazel select() + // statement can be used to choose source/stub variants of them. + depsWithStubs := []bazel.Label{} + for _, l := range sharedDeps.implementation.Includes { + dep, _ := ctx.ModuleFromName(l.OriginalModuleName) + if m, ok := dep.(*Module); ok && m.HasStubsVariants() { + depsWithStubs = append(depsWithStubs, l) + } + } + if len(depsWithStubs) > 0 { + implDynamicDeps := bazel.SubtractBazelLabelList(sharedDeps.implementation, bazel.MakeLabelList(depsWithStubs)) + la.implementationDynamicDeps.SetSelectValue(axis, config, implDynamicDeps) + + stubLibLabels := []bazel.Label{} + for _, l := range depsWithStubs { + l.Label = l.Label + "_stub_libs_current" + stubLibLabels = append(stubLibLabels, l) + } + inApexSelectValue := la.implementationDynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndInApex) + nonApexSelectValue := la.implementationDynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.AndroidAndNonApex) + defaultSelectValue := la.implementationDynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey) + if axis == bazel.NoConfigAxis { + (&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) + } 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) + } + } + } if !BoolDefault(props.Pack_relocations, packRelocationsDefault) { axisFeatures = append(axisFeatures, "disable_pack_relocations") @@ -825,6 +996,11 @@ func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversion if axisFeatures != nil { la.features.SetSelectValue(axis, config, axisFeatures) } + + runtimeDeps := android.BazelLabelForModuleDepsExcludes(ctx, props.Runtime_libs, props.Exclude_runtime_libs) + if !runtimeDeps.IsEmpty() { + la.runtimeDeps.SetSelectValue(axis, config, runtimeDeps) + } } func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) { @@ -983,7 +1159,7 @@ func bp2BuildParseExportedIncludes(ctx android.BazelConversionPathContext, modul func bazelLabelForStaticModule(ctx android.BazelConversionPathContext, m blueprint.Module) string { label := android.BazelModuleLabel(ctx, m) - if ccModule, ok := m.(*Module); ok && ccModule.typ() == fullLibrary && !android.GenerateCcLibraryStaticOnly(m.Name()) { + if ccModule, ok := m.(*Module); ok && ccModule.typ() == fullLibrary && !android.GetBp2BuildAllowList().GenerateCcLibraryStaticOnly(m.Name()) { label += "_bp2build_cc_library_static" } return label @@ -1043,6 +1219,7 @@ func bazelLabelForSharedDepsExcludes(ctx android.BazelConversionPathContext, mod type binaryLinkerAttrs struct { Linkshared *bool + Suffix bazel.StringAttribute } func bp2buildBinaryLinkerProps(ctx android.BazelConversionPathContext, m *Module) binaryLinkerAttrs { @@ -1059,6 +1236,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 c289cbde2..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", @@ -702,8 +702,10 @@ func transformSourceToObj(ctx ModuleContext, subdir string, srcFiles, noTidySrcs sAbiDumpFile := android.ObjPathWithExt(ctx, subdir, srcFile, "sdump") sAbiDumpFiles = append(sAbiDumpFiles, sAbiDumpFile) - // TODO(b/226497964): dumpRule = sAbiDumpRE if USE_RBE and RBE_ABI_DUMPER are true. dumpRule := sAbiDump + if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_ABI_DUMPER") { + dumpRule = sAbiDumpRE + } ctx.Build(pctx, android.BuildParams{ Rule: dumpRule, Description: "header-abi-dumper " + srcFile.Rel(), @@ -918,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)) @@ -938,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 { @@ -959,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) @@ -514,6 +514,7 @@ type ModuleContextIntf interface { getVndkExtendsModuleName() string isAfdoCompile() bool isPgoCompile() bool + isCfi() bool isNDKStubLibrary() bool useClangLld(actx ModuleContext) bool isForPlatform() bool @@ -1314,6 +1315,13 @@ func (c *Module) isPgoCompile() bool { return false } +func (c *Module) isCfi() bool { + if sanitize := c.sanitize; sanitize != nil { + return Bool(sanitize.Properties.Sanitize.Cfi) + } + return false +} + func (c *Module) isNDKStubLibrary() bool { if _, ok := c.compiler.(*stubDecorator); ok { return true @@ -1592,6 +1600,10 @@ func (ctx *moduleContextImpl) isPgoCompile() bool { return ctx.mod.isPgoCompile() } +func (ctx *moduleContextImpl) isCfi() bool { + return ctx.mod.isCfi() +} + func (ctx *moduleContextImpl) isNDKStubLibrary() bool { return ctx.mod.isNDKStubLibrary() } @@ -1888,6 +1900,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{ @@ -2288,9 +2302,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 } @@ -2334,9 +2353,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 { @@ -3241,11 +3265,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() && @@ -3357,6 +3376,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 @@ -3581,9 +3609,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" { @@ -3638,13 +3663,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 @@ -3673,7 +3710,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 { @@ -3764,6 +3805,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 792a8e044..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 `), ) }) @@ -4145,7 +4145,7 @@ func TestIncludeDirectoryOrdering(t *testing.T) { "${config.ArmArmv7ANeonCflags}", "${config.ArmGenericCflags}", "-target", - "armv7a-linux-androideabi20", + "armv7a-linux-androideabi21", } expectedIncludes := []string{ @@ -4176,7 +4176,6 @@ func TestIncludeDirectoryOrdering(t *testing.T) { "external/foo/lib32", "external/foo/libandroid_arm", "defaults/cc/common/ndk_libc++_shared", - "defaults/cc/common/ndk_libandroid_support", } conly := []string{"-fPIC", "${config.CommonGlobalConlyflags}"} @@ -4269,20 +4268,20 @@ func TestIncludeDirectoryOrdering(t *testing.T) { }, }, stl: "libc++", - sdk_version: "20", + sdk_version: "minimum", } cc_library_headers { name: "libheader1", export_include_dirs: ["libheader1"], - sdk_version: "20", + sdk_version: "minimum", stl: "none", } cc_library_headers { name: "libheader2", export_include_dirs: ["libheader2"], - sdk_version: "20", + sdk_version: "minimum", stl: "none", } `, tc.src) @@ -4306,7 +4305,7 @@ func TestIncludeDirectoryOrdering(t *testing.T) { cc_library { name: "%s", export_include_dirs: ["%s"], - sdk_version: "20", + sdk_version: "minimum", stl: "none", } `, lib, lib) @@ -4337,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/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 897b57261..8804bbb8f 100644 --- a/cc/library.go +++ b/cc/library.go @@ -270,6 +270,15 @@ type bazelCcLibraryAttributes struct { Features bazel.StringListAttribute } +type aidlLibraryAttributes struct { + Srcs bazel.LabelListAttribute + Include_dir *string +} + +type ccAidlLibraryAttributes struct { + Deps bazel.LabelListAttribute +} + type stripAttributes struct { Keep_symbols bazel.BoolAttribute Keep_symbols_and_debug_frame bazel.BoolAttribute @@ -282,7 +291,7 @@ func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) { // For some cc_library modules, their static variants are ready to be // converted, but not their shared variants. For these modules, delegate to // the cc_library_static bp2build converter temporarily instead. - if android.GenerateCcLibraryStaticOnly(ctx.Module().Name()) { + if android.GetBp2BuildAllowList().GenerateCcLibraryStaticOnly(ctx.Module().Name()) { sharedOrStaticLibraryBp2Build(ctx, m, true) return } @@ -319,6 +328,7 @@ func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) { Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps, Whole_archive_deps: *linkerAttrs.wholeArchiveDeps.Clone().Append(staticAttrs.Whole_archive_deps), System_dynamic_deps: *linkerAttrs.systemDynamicDeps.Clone().Append(staticAttrs.System_dynamic_deps), + Runtime_deps: linkerAttrs.runtimeDeps, sdkAttributes: bp2BuildParseSdkAttributes(m), } @@ -335,6 +345,7 @@ func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) { 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), } @@ -357,7 +368,7 @@ func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) { C_std: compilerAttrs.cStd, Use_version_lib: linkerAttrs.useVersionLib, - Features: linkerAttrs.features, + Features: baseAttributes.features, } sharedTargetAttrs := &bazelCcLibrarySharedAttributes{ @@ -389,12 +400,16 @@ func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) { All: linkerAttrs.stripAll, None: linkerAttrs.stripNone, }, - Features: linkerAttrs.features, + Features: baseAttributes.features, + } - Stubs_symbol_file: compilerAttrs.stubsSymbolFile, - Stubs_versions: compilerAttrs.stubsVersions, + if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 { + hasStubs := true + 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 { @@ -425,6 +440,25 @@ func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) { ctx.CreateBazelTargetModuleWithRestrictions(sharedProps, android.CommonAttributes{Name: m.Name()}, sharedTargetAttrs, sharedAttrs.Enabled) + + if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 { + stubSuitesProps := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_stub_suite", + Bzl_load_location: "//build/bazel/rules/cc:cc_stub_library.bzl", + } + soname := m.Name() + ".so" + stubSuitesAttrs := &bazelCcStubSuiteAttributes{ + Symbol_file: compilerAttrs.stubsSymbolFile, + Versions: compilerAttrs.stubsVersions, + Export_includes: exportedIncludes.Includes, + Soname: &soname, + Source_library: *bazel.MakeLabelAttribute(":" + m.Name()), + Deps: baseAttributes.deps, + } + ctx.CreateBazelTargetModule(stubSuitesProps, + android.CommonAttributes{Name: m.Name() + "_stub_libs"}, + stubSuitesAttrs) + } } // cc_library creates both static and/or shared libraries for a device and/or @@ -1048,9 +1082,7 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa if ctx.Module().(android.ApexModule).NotInPlatform() { flag = "--apex" } else { - // TODO(b/239274367) drop --apex when #apex is replaced with #systemapi - // in the map.txt files of platform libraries - flag = "--systemapi --apex" + flag = "--systemapi" } nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile, android.ApiLevelOrPanic(ctx, library.MutatedProperties.StubsVersion), flag) @@ -1600,13 +1632,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() { @@ -1623,12 +1690,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 @@ -1644,9 +1711,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 } } } @@ -1654,7 +1721,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 @@ -1686,12 +1753,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) } @@ -1700,8 +1768,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) } @@ -2552,6 +2621,7 @@ func sharedOrStaticLibraryBp2Build(ctx android.TopDownMutatorContext, module *Mo Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps, System_dynamic_deps: linkerAttrs.systemDynamicDeps, sdkAttributes: bp2BuildParseSdkAttributes(module), + Runtime_deps: linkerAttrs.runtimeDeps, } var attrs interface{} @@ -2578,12 +2648,12 @@ func sharedOrStaticLibraryBp2Build(ctx android.TopDownMutatorContext, module *Mo Conlyflags: compilerAttrs.conlyFlags, Asflags: asFlags, - Features: linkerAttrs.features, + Features: baseAttributes.features, } } else { commonAttrs.Dynamic_deps.Add(baseAttributes.protoDependency) - attrs = &bazelCcLibrarySharedAttributes{ + sharedLibAttrs := &bazelCcLibrarySharedAttributes{ staticOrSharedAttributes: commonAttrs, Cppflags: compilerAttrs.cppFlags, @@ -2615,11 +2685,15 @@ func sharedOrStaticLibraryBp2Build(ctx android.TopDownMutatorContext, module *Mo None: linkerAttrs.stripNone, }, - Features: linkerAttrs.features, + Features: baseAttributes.features, - Stubs_symbol_file: compilerAttrs.stubsSymbolFile, - Stubs_versions: compilerAttrs.stubsVersions, + Suffix: compilerAttrs.suffix, + } + if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 { + hasStubs := true + sharedLibAttrs.Has_stubs.SetValue(&hasStubs) } + attrs = sharedLibAttrs } var modType string @@ -2693,7 +2767,18 @@ type bazelCcLibrarySharedAttributes struct { Features bazel.StringListAttribute - Stubs_symbol_file *string - Stubs_versions bazel.StringListAttribute - Inject_bssl_hash bazel.BoolAttribute + Has_stubs bazel.BoolAttribute + + Inject_bssl_hash bazel.BoolAttribute + + Suffix bazel.StringAttribute +} + +type bazelCcStubSuiteAttributes struct { + Symbol_file *string + Versions bazel.StringListAttribute + Export_includes bazel.StringListAttribute + Source_library bazel.LabelAttribute + Soname *string + Deps bazel.LabelListAttribute } diff --git a/cc/library_headers.go b/cc/library_headers.go index 970d8d1a6..a683f58df 100644 --- a/cc/library_headers.go +++ b/cc/library_headers.go @@ -126,6 +126,7 @@ func libraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) { exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, &baseAttributes.includes) linkerAttrs := baseAttributes.linkerAttributes (&linkerAttrs.deps).Append(linkerAttrs.dynamicDeps) + (&linkerAttrs.deps).Append(linkerAttrs.wholeArchiveDeps) attrs := &bazelCcLibraryHeadersAttributes{ Export_includes: exportedIncludes.Includes, diff --git a/cc/library_stub.go b/cc/library_stub.go index 14d1b963a..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) } @@ -68,6 +69,9 @@ func CcApiLibraryFactory() android.Module { apiLibraryDecorator.baseLinker.Properties.System_shared_libs = []string{} } + apiLibraryDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true) + apiLibraryDecorator.baseLinker.Properties.Nocrt = BoolPtr(true) + module.Init() return module @@ -78,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...) @@ -111,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)) +} @@ -136,10 +136,16 @@ func (lto *lto) LTO(ctx BaseModuleContext) bool { } func (lto *lto) DefaultThinLTO(ctx BaseModuleContext) bool { + // LP32 has many subtle issues and less test coverage. lib32 := ctx.Arch().ArchType.Multilib == "lib32" + // CFI enables full LTO. + cfi := ctx.isCfi() + // Performance and binary size are less important for host binaries. host := ctx.Host() - vndk := ctx.isVndk() // b/169217596 - return GlobalThinLTO(ctx) && !lto.Never() && !lib32 && !host && !vndk + // FIXME: ThinLTO for VNDK produces different output. + // b/169217596 + vndk := ctx.isVndk() + return GlobalThinLTO(ctx) && !lto.Never() && !lib32 && !cfi && !host && !vndk } func (lto *lto) FullLTO() bool { 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/prebuilt.go b/cc/prebuilt.go index a2d450332..867c36cf4 100644 --- a/cc/prebuilt.go +++ b/cc/prebuilt.go @@ -51,6 +51,9 @@ type prebuiltLinkerProperties struct { // symbols, etc), default true. Check_elf_files *bool + // if set, add an extra objcopy --prefix-symbols= step + Prefix_symbols *string + // Optionally provide an import library if this is a Windows PE DLL prebuilt. // This is needed only if this library is linked by other modules in build time. // Only makes sense for the Windows target. @@ -130,6 +133,13 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext, in := android.PathForModuleSrc(ctx, srcs[0]) + if String(p.prebuiltLinker.properties.Prefix_symbols) != "" { + prefixed := android.PathForModuleOut(ctx, "prefixed", srcs[0]) + transformBinaryPrefixSymbols(ctx, String(p.prebuiltLinker.properties.Prefix_symbols), + in, flagsToBuilderFlags(flags), prefixed) + in = prefixed + } + if p.static() { depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(in).Build() ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{ diff --git a/cc/sanitize.go b/cc/sanitize.go index 86472a2cc..edff05973 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,20 @@ func (sanitize *sanitize) flags(ctx ModuleContext, flags Flags) Flags { } } + if Bool(sanitize.Properties.Sanitize.Memtag_stack) { + flags.Local.CFlags = append(flags.Local.CFlags, memtagStackCommonFlags...) + flags.Local.AsFlags = append(flags.Local.AsFlags, memtagStackCommonFlags...) + flags.Local.LdFlags = append(flags.Local.LdFlags, memtagStackCommonFlags...) + } + + 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 +839,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 +856,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 +888,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 +1351,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/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/cmd/soong_build/main.go b/cmd/soong_build/main.go index 53422cd6c..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 @@ -121,7 +123,25 @@ func newContext(configuration android.Config) *android.Context { } func newConfig(availableEnv map[string]string) android.Config { - configuration, err := android.NewConfig(cmdlineArgs.ModuleListFile, runGoTests, outDir, soongOutDir, availableEnv) + var buildMode android.SoongBuildMode + + if bp2buildMarker != "" { + buildMode = android.Bp2build + } else if bazelQueryViewDir != "" { + buildMode = android.GenerateQueryView + } else if moduleGraphFile != "" { + 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 + } + + configuration, err := android.NewConfig(cmdlineArgs.ModuleListFile, buildMode, runGoTests, outDir, soongOutDir, availableEnv) if err != nil { fmt.Fprintf(os.Stderr, "%s", err) os.Exit(1) @@ -220,53 +240,41 @@ 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 { - mixedModeBuild := configuration.BazelContext.BazelEnabled() - generateBazelWorkspace := bp2buildMarker != "" - generateQueryView := bazelQueryViewDir != "" - generateModuleGraphFile := moduleGraphFile != "" - generateDocFile := docFile != "" - - if generateBazelWorkspace { +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. runBp2Build(configuration, extraNinjaDeps) return bp2buildMarker - } - - blueprintArgs := cmdlineArgs - - if mixedModeBuild { + } else if configuration.IsMixedBuildsEnabled() { runMixedModeBuild(configuration, ctx, extraNinjaDeps) } else { var stopBefore bootstrap.StopBefore - if generateModuleGraphFile { + if configuration.BuildMode == android.GenerateModuleGraph { stopBefore = bootstrap.StopBeforeWriteNinja - } else if generateQueryView { - stopBefore = bootstrap.StopBeforePrepareBuildActions - } else if generateDocFile { + } else if configuration.BuildMode == android.GenerateQueryView || configuration.BuildMode == android.GenerateDocFile { stopBefore = bootstrap.StopBeforePrepareBuildActions } else { stopBefore = bootstrap.DoEverything } - ninjaDeps := bootstrap.RunBlueprint(blueprintArgs, stopBefore, ctx.Context, configuration) + ninjaDeps := bootstrap.RunBlueprint(cmdlineArgs, stopBefore, ctx.Context, configuration) ninjaDeps = append(ninjaDeps, extraNinjaDeps...) globListFiles := writeBuildGlobsNinjaFile(ctx, configuration.SoongOutDir(), configuration) ninjaDeps = append(ninjaDeps, globListFiles...) // Convert the Soong module graph into Bazel BUILD files. - if generateQueryView { + if configuration.BuildMode == android.GenerateQueryView { queryviewMarkerFile := bazelQueryViewDir + ".marker" runQueryView(bazelQueryViewDir, queryviewMarkerFile, configuration, ctx) writeDepFile(queryviewMarkerFile, *ctx.EventHandler, ninjaDeps) return queryviewMarkerFile - } else if generateModuleGraphFile { + } else if configuration.BuildMode == android.GenerateModuleGraph { writeJsonModuleGraphAndActions(ctx, moduleGraphFile, moduleActionsFile) writeDepFile(moduleGraphFile, *ctx.EventHandler, ninjaDeps) return moduleGraphFile - } else if generateDocFile { + } else if configuration.BuildMode == android.GenerateDocFile { // TODO: we could make writeDocs() return the list of documentation files // written and add them to the .d file. Then soong_docs would be re-run // whenever one is deleted. @@ -345,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) @@ -398,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 { @@ -420,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) } @@ -491,11 +488,6 @@ func runBp2Build(configuration android.Config, extraNinjaDeps []string) { // conversion for Bazel conversion. bp2buildCtx := android.NewContext(configuration) - // Soong internals like LoadHooks behave differently when running as - // bp2build. This is the bit to differentiate between Soong-as-Soong and - // Soong-as-bp2build. - bp2buildCtx.SetRunningAsBp2build() - // Propagate "allow misssing dependencies" bit. This is normally set in // newContext(), but we create bp2buildCtx without calling that method. bp2buildCtx.SetAllowMissingDependencies(configuration.AllowMissingDependencies()) @@ -550,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/genrule/genrule.go b/genrule/genrule.go index 6686c8717..7a0dac333 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -26,6 +26,7 @@ import ( "strings" "android/soong/bazel/cquery" + "github.com/google/blueprint" "github.com/google/blueprint/bootstrap" "github.com/google/blueprint/proptools" @@ -468,6 +469,7 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { return "SOONG_ERROR", nil } + // Apply shell escape to each cases to prevent source file paths containing $ from being evaluated in shell switch name { case "location": if len(g.properties.Tools) == 0 && len(g.properties.Tool_files) == 0 { @@ -481,15 +483,15 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { return reportError("default label %q has multiple files, use $(locations %s) to reference it", firstLabel, firstLabel) } - return paths[0], nil + return proptools.ShellEscape(paths[0]), nil case "in": - return strings.Join(cmd.PathsForInputs(srcFiles), " "), nil + return strings.Join(proptools.ShellEscapeList(cmd.PathsForInputs(srcFiles)), " "), nil case "out": var sandboxOuts []string for _, out := range task.out { sandboxOuts = append(sandboxOuts, cmd.PathForOutput(out)) } - return strings.Join(sandboxOuts, " "), nil + return strings.Join(proptools.ShellEscapeList(sandboxOuts), " "), nil case "depfile": referencedDepfile = true if !Bool(g.properties.Depfile) { @@ -497,7 +499,7 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { } return "__SBOX_DEPFILE__", nil case "genDir": - return cmd.PathForOutput(task.genDir), nil + return proptools.ShellEscape(cmd.PathForOutput(task.genDir)), nil default: if strings.HasPrefix(name, "location ") { label := strings.TrimSpace(strings.TrimPrefix(name, "location ")) @@ -509,7 +511,7 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { return reportError("label %q has multiple files, use $(locations %s) to reference it", label, label) } - return paths[0], nil + return proptools.ShellEscape(paths[0]), nil } else { return reportError("unknown location label %q is not in srcs, out, tools or tool_files.", label) } @@ -520,7 +522,7 @@ func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) { if len(paths) == 0 { return reportError("label %q has no files", label) } - return strings.Join(paths, " "), nil + return proptools.ShellEscape(strings.Join(paths, " ")), nil } else { return reportError("unknown locations label %q is not in srcs, out, tools or tool_files.", label) } diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go index b9be1f70f..cd941ccbc 100644 --- a/genrule/genrule_test.go +++ b/genrule/genrule_test.go @@ -422,7 +422,7 @@ func TestGenruleCmd(t *testing.T) { allowMissingDependencies: true, - expect: "cat ***missing srcs :missing*** > __SBOX_SANDBOX_DIR__/out/out", + expect: "cat '***missing srcs :missing***' > __SBOX_SANDBOX_DIR__/out/out", }, { name: "tool allow missing dependencies", @@ -434,7 +434,7 @@ func TestGenruleCmd(t *testing.T) { allowMissingDependencies: true, - expect: "***missing tool :missing*** > __SBOX_SANDBOX_DIR__/out/out", + expect: "'***missing tool :missing***' > __SBOX_SANDBOX_DIR__/out/out", }, } @@ -878,6 +878,92 @@ func TestGenruleWithBazel(t *testing.T) { android.AssertDeepEquals(t, "output deps", expectedOutputFiles, gen.outputDeps.Strings()) } +func TestGenruleWithGlobPaths(t *testing.T) { + testcases := []struct { + name string + bp string + additionalFiles android.MockFS + expectedCmd string + }{ + { + name: "single file in directory with $ sign", + bp: ` + genrule { + name: "gen", + srcs: ["inn*.txt"], + out: ["out.txt"], + cmd: "cp $(in) $(out)", + } + `, + additionalFiles: android.MockFS{"inn$1.txt": nil}, + expectedCmd: "cp 'inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt", + }, + { + name: "multiple file in directory with $ sign", + bp: ` + genrule { + name: "gen", + srcs: ["inn*.txt"], + out: ["."], + cmd: "cp $(in) $(out)", + } + `, + additionalFiles: android.MockFS{"inn$1.txt": nil, "inn$2.txt": nil}, + expectedCmd: "cp 'inn$1.txt' 'inn$2.txt' __SBOX_SANDBOX_DIR__/out", + }, + { + name: "file in directory with other shell unsafe character", + bp: ` + genrule { + name: "gen", + srcs: ["inn*.txt"], + out: ["out.txt"], + cmd: "cp $(in) $(out)", + } + `, + additionalFiles: android.MockFS{"inn@1.txt": nil}, + expectedCmd: "cp 'inn@1.txt' __SBOX_SANDBOX_DIR__/out/out.txt", + }, + { + name: "glob location param with filepath containing $", + bp: ` + genrule { + name: "gen", + srcs: ["**/inn*"], + out: ["."], + cmd: "cp $(in) $(location **/inn*)", + } + `, + additionalFiles: android.MockFS{"a/inn$1.txt": nil}, + expectedCmd: "cp 'a/inn$1.txt' 'a/inn$1.txt'", + }, + { + name: "glob locations param with filepath containing $", + bp: ` + genrule { + name: "gen", + tool_files: ["**/inn*"], + out: ["out.txt"], + cmd: "cp $(locations **/inn*) $(out)", + } + `, + additionalFiles: android.MockFS{"a/inn$1.txt": nil}, + expectedCmd: "cp '__SBOX_SANDBOX_DIR__/tools/src/a/inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt", + }, + } + + for _, test := range testcases { + t.Run(test.name, func(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForGenRuleTest, + android.FixtureMergeMockFs(test.additionalFiles), + ).RunTestWithBp(t, test.bp) + gen := result.Module("gen", "").(*Module) + android.AssertStringEquals(t, "command", test.expectedCmd, gen.rawCommands[0]) + }) + } +} + type testTool struct { android.ModuleBase outputFile android.Path diff --git a/java/base.go b/java/base.go index 94daf37fc..cf3b3d510 100644 --- a/java/base.go +++ b/java/base.go @@ -267,6 +267,9 @@ type DeviceProperties struct { // Only for libraries created by a sysprop_library module, SyspropPublicStub is the name of the // public stubs library. SyspropPublicStub string `blueprint:"mutated"` + + HiddenAPIPackageProperties + HiddenAPIFlagFileProperties } // Device properties that can be overridden by overriding module (e.g. override_android_app) @@ -564,6 +567,20 @@ func (j *Module) addHostAndDeviceProperties() { ) } +// provideHiddenAPIPropertyInfo populates a HiddenAPIPropertyInfo from hidden API properties and +// makes it available through the hiddenAPIPropertyInfoProvider. +func (j *Module) provideHiddenAPIPropertyInfo(ctx android.ModuleContext) { + hiddenAPIInfo := newHiddenAPIPropertyInfo() + + // Populate with flag file paths from the properties. + hiddenAPIInfo.extractFlagFilesFromProperties(ctx, &j.deviceProperties.HiddenAPIFlagFileProperties) + + // Populate with package rules from the properties. + hiddenAPIInfo.extractPackageRulesFromProperties(&j.deviceProperties.HiddenAPIPackageProperties) + + ctx.SetProvider(hiddenAPIPropertyInfoProvider, hiddenAPIInfo) +} + func (j *Module) OutputFiles(tag string) (android.Paths, error) { switch tag { case "": @@ -803,7 +820,7 @@ func (j *Module) individualAidlFlags(ctx android.ModuleContext, aidlFile android } func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath, - aidlIncludeDirs android.Paths) (string, android.Paths) { + aidlIncludeDirs android.Paths, aidlSrcs android.Paths) (string, android.Paths) { aidlIncludes := android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Local_include_dirs) aidlIncludes = append(aidlIncludes, @@ -813,6 +830,7 @@ func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.Opt var flags []string var deps android.Paths + var includeDirs android.Paths flags = append(flags, j.deviceProperties.Aidl.Flags...) @@ -820,21 +838,24 @@ func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.Opt flags = append(flags, "-p"+aidlPreprocess.String()) deps = append(deps, aidlPreprocess.Path()) } else if len(aidlIncludeDirs) > 0 { - flags = append(flags, android.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I")) + includeDirs = append(includeDirs, aidlIncludeDirs...) } if len(j.exportAidlIncludeDirs) > 0 { - flags = append(flags, android.JoinWithPrefix(j.exportAidlIncludeDirs.Strings(), "-I")) + includeDirs = append(includeDirs, j.exportAidlIncludeDirs...) } if len(aidlIncludes) > 0 { - flags = append(flags, android.JoinWithPrefix(aidlIncludes.Strings(), "-I")) + includeDirs = append(includeDirs, aidlIncludes...) } - flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String()) + includeDirs = append(includeDirs, android.PathForModuleSrc(ctx)) if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() { - flags = append(flags, "-I"+src.String()) + includeDirs = append(includeDirs, src.Path()) } + flags = append(flags, android.JoinWithPrefix(includeDirs.Strings(), "-I")) + // 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) { flags = append(flags, "-t") @@ -918,9 +939,6 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB // systemModules flags.systemModules = deps.systemModules - // aidl flags. - flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs) - return flags } @@ -1029,6 +1047,9 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { ctx.PropertyErrorf("common_srcs", "common_srcs must be .kt files") } + aidlSrcs := srcFiles.FilterByExt(".aidl") + flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs, aidlSrcs) + nonGeneratedSrcJars := srcFiles.FilterByExt(".srcjar") srcFiles = j.genSources(ctx, srcFiles, flags) @@ -1178,12 +1199,21 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { } } if len(uniqueSrcFiles) > 0 || len(srcJars) > 0 { + hasErrorproneableFiles := false + for _, ext := range j.sourceExtensions { + if ext != ".proto" && ext != ".aidl" { + // Skip running errorprone on pure proto or pure aidl modules. Some modules take a long time to + // compile, and it's not useful to have warnings on these generated sources. + hasErrorproneableFiles = true + break + } + } var extraJarDeps android.Paths if Bool(j.properties.Errorprone.Enabled) { // If error-prone is enabled, enable errorprone flags on the regular // build. flags = enableErrorproneFlags(flags) - } else if ctx.Config().RunErrorProne() && j.properties.Errorprone.Enabled == nil { + } else if hasErrorproneableFiles && ctx.Config().RunErrorProne() && j.properties.Errorprone.Enabled == nil { // Otherwise, if the RUN_ERROR_PRONE environment variable is set, create // a new jar file just for compiling with the errorprone compiler to. // This is because we don't want to cause the java files to get completely diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 7580352d0..93168070e 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -830,6 +830,8 @@ func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.Modul // Populate with package rules from the properties. input.extractPackageRulesFromProperties(&b.sourceOnlyProperties.HiddenAPIPackageProperties) + input.gatherPropertyInfo(ctx, contents) + // Add the stub dex jars from this module's fragment dependencies. input.DependencyStubDexJarsByScope.addStubDexJarsByModule(dependencyHiddenApiInfo.TransitiveStubDexJarsByScope) diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go index 83beb6d23..f95c83fe7 100644 --- a/java/bootclasspath_fragment_test.go +++ b/java/bootclasspath_fragment_test.go @@ -15,6 +15,7 @@ package java import ( + "strings" "testing" "android/soong/android" @@ -285,6 +286,119 @@ func TestBootclasspathFragment_StubLibs(t *testing.T) { android.AssertPathsRelativeToTopEquals(t, "widest dex stubs jar", expectedWidestPaths, info.TransitiveStubDexJarsByScope.StubDexJarsForWidestAPIScope()) } +func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForTestWithBootclasspathFragment, + PrepareForTestWithJavaSdkLibraryFiles, + FixtureWithLastReleaseApis("mysdklibrary", "mynewlibrary"), + FixtureConfigureApexBootJars("myapex:mybootlib", "myapex:mynewlibrary"), + android.MockFS{ + "my-blocked.txt": nil, + "my-max-target-o-low-priority.txt": nil, + "my-max-target-p.txt": nil, + "my-max-target-q.txt": nil, + "my-max-target-r-low-priority.txt": nil, + "my-removed.txt": nil, + "my-unsupported-packages.txt": nil, + "my-unsupported.txt": nil, + "my-new-max-target-q.txt": nil, + }.AddToFixture(), + android.FixtureWithRootAndroidBp(` + bootclasspath_fragment { + name: "mybootclasspathfragment", + apex_available: ["myapex"], + contents: ["mybootlib", "mynewlibrary"], + hidden_api: { + unsupported: [ + "my-unsupported.txt", + ], + removed: [ + "my-removed.txt", + ], + max_target_r_low_priority: [ + "my-max-target-r-low-priority.txt", + ], + max_target_q: [ + "my-max-target-q.txt", + ], + max_target_p: [ + "my-max-target-p.txt", + ], + max_target_o_low_priority: [ + "my-max-target-o-low-priority.txt", + ], + blocked: [ + "my-blocked.txt", + ], + unsupported_packages: [ + "my-unsupported-packages.txt", + ], + split_packages: ["sdklibrary"], + package_prefixes: ["sdklibrary.all.mine"], + single_packages: ["sdklibrary.mine"], + }, + } + + java_library { + name: "mybootlib", + apex_available: ["myapex"], + srcs: ["Test.java"], + system_modules: "none", + sdk_version: "none", + min_sdk_version: "1", + compile_dex: true, + permitted_packages: ["mybootlib"], + } + + java_sdk_library { + name: "mynewlibrary", + apex_available: ["myapex"], + srcs: ["Test.java"], + min_sdk_version: "10", + compile_dex: true, + public: {enabled: true}, + permitted_packages: ["mysdklibrary"], + hidden_api: { + max_target_q: [ + "my-new-max-target-q.txt", + ], + split_packages: ["sdklibrary", "newlibrary"], + package_prefixes: ["newlibrary.all.mine"], + single_packages: ["newlibrary.mine"], + }, + } + `), + ).RunTest(t) + + // Make sure that the library exports hidden API properties for use by the bootclasspath_fragment. + library := result.Module("mynewlibrary", "android_common") + info := result.ModuleProvider(library, hiddenAPIPropertyInfoProvider).(HiddenAPIPropertyInfo) + android.AssertArrayString(t, "split packages", []string{"sdklibrary", "newlibrary"}, info.SplitPackages) + android.AssertArrayString(t, "package prefixes", []string{"newlibrary.all.mine"}, info.PackagePrefixes) + android.AssertArrayString(t, "single packages", []string{"newlibrary.mine"}, info.SinglePackages) + for _, c := range HiddenAPIFlagFileCategories { + expectedMaxTargetQPaths := []string(nil) + if c.PropertyName == "max_target_q" { + expectedMaxTargetQPaths = []string{"my-new-max-target-q.txt"} + } + android.AssertPathsRelativeToTopEquals(t, c.PropertyName, expectedMaxTargetQPaths, info.FlagFilesByCategory[c]) + } + + // Make sure that the signature-patterns.csv is passed all the appropriate package properties + // from the bootclasspath_fragment and its contents. + fragment := result.ModuleForTests("mybootclasspathfragment", "android_common") + rule := fragment.Output("modular-hiddenapi/signature-patterns.csv") + expectedCommand := strings.Join([]string{ + "--split-package newlibrary", + "--split-package sdklibrary", + "--package-prefix newlibrary.all.mine", + "--package-prefix sdklibrary.all.mine", + "--single-package newlibrary.mine", + "--single-package sdklibrary", + }, " ") + android.AssertStringDoesContain(t, "signature patterns command", rule.RuleParams.Command, expectedCommand) +} + func TestBootclasspathFragment_Test(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithBootclasspathFragment, diff --git a/java/config/config.go b/java/config/config.go index 3ca9bad3e..422f86002 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -148,7 +148,7 @@ func init() { 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") diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp index 513c6061b..bfd5cf8b1 100644 --- a/java/core-libraries/Android.bp +++ b/java/core-libraries/Android.bp @@ -84,12 +84,36 @@ java_library { ], } +// Same as core-current-stubs-for-system-modules, but android annotations are +// stripped. +java_library { + name: "core-current-stubs-for-system-modules-no-annotations", + visibility: ["//development/sdk"], + static_libs: [ + "core-current-stubs-for-system-modules", + ], + sdk_version: "none", + system_modules: "none", + dists: [ + { + // Legacy dist location for the public file. + dest: "core-for-system-modules-no-annotations.jar", + targets: dist_targets, + }, + { + dest: "system-modules/public/core-for-system-modules-no-annotations.jar", + targets: dist_targets, + }, + ], + jarjar_rules: "jarjar-strip-annotations-rules.txt", +} + // Used when compiling higher-level code against core.current.stubs. java_system_modules { name: "core-public-stubs-system-modules", visibility: ["//visibility:public"], libs: [ - "core-current-stubs-for-system-modules", + "core-current-stubs-for-system-modules-no-annotations", ], } diff --git a/java/droiddoc.go b/java/droiddoc.go index 901419cba..9b1f43b4c 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -314,7 +314,7 @@ func (j *Javadoc) genSources(ctx android.ModuleContext, srcFiles android.Paths, outSrcFiles := make(android.Paths, 0, len(srcFiles)) var aidlSrcs android.Paths - aidlIncludeFlags := genAidlIncludeFlags(srcFiles) + aidlIncludeFlags := genAidlIncludeFlags(ctx, srcFiles, android.Paths{}) for _, srcFile := range srcFiles { switch srcFile.Ext() { diff --git a/java/gen.go b/java/gen.go index 1572bf00a..638da255a 100644 --- a/java/gen.go +++ b/java/gen.go @@ -15,6 +15,7 @@ package java import ( + "path/filepath" "strconv" "strings" @@ -116,12 +117,31 @@ func genLogtags(ctx android.ModuleContext, logtagsFile android.Path) android.Pat return javaFile } -func genAidlIncludeFlags(srcFiles android.Paths) string { +// genAidlIncludeFlags returns additional include flags based on the relative path +// of each .aidl file passed in srcFiles. excludeDirs is a list of paths relative to +// the Android checkout root that should not be included in the returned flags. +func genAidlIncludeFlags(ctx android.PathContext, srcFiles android.Paths, excludeDirs android.Paths) string { var baseDirs []string + excludeDirsStrings := excludeDirs.Strings() for _, srcFile := range srcFiles { if srcFile.Ext() == ".aidl" { baseDir := strings.TrimSuffix(srcFile.String(), srcFile.Rel()) - if baseDir != "" && !android.InList(baseDir, baseDirs) { + baseDir = filepath.Clean(baseDir) + baseDirSeen := android.InList(baseDir, baseDirs) || android.InList(baseDir, excludeDirsStrings) + + // For go/bp2build mixed builds, a file may be listed under a + // directory in the Bazel output tree that is symlinked to a + // directory under the android source tree. We should only + // include one copy of this directory so that the AIDL tool + // doesn't find multiple definitions of the same AIDL class. + // This code comes into effect when filegroups are used in mixed builds. + bazelPathPrefix := android.PathForBazelOut(ctx, "").String() + bazelBaseDir, err := filepath.Rel(bazelPathPrefix, baseDir) + bazelBaseDirSeen := err == nil && + android.InList(bazelBaseDir, baseDirs) || + android.InList(bazelBaseDir, excludeDirsStrings) + + if baseDir != "" && !baseDirSeen && !bazelBaseDirSeen { baseDirs = append(baseDirs, baseDir) } } @@ -136,8 +156,6 @@ func (j *Module) genSources(ctx android.ModuleContext, srcFiles android.Paths, var protoSrcs android.Paths var aidlSrcs android.Paths - aidlIncludeFlags := genAidlIncludeFlags(srcFiles) - for _, srcFile := range srcFiles { switch srcFile.Ext() { case ".aidl": @@ -168,7 +186,7 @@ func (j *Module) genSources(ctx android.ModuleContext, srcFiles android.Paths, individualFlags[aidlSrc.String()] = flags } } - srcJarFiles := genAidl(ctx, aidlSrcs, flags.aidlFlags+aidlIncludeFlags, individualFlags, flags.aidlDeps) + srcJarFiles := genAidl(ctx, aidlSrcs, flags.aidlFlags, individualFlags, flags.aidlDeps) outSrcFiles = append(outSrcFiles, srcJarFiles...) } diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go index 3a58675ec..7b678037c 100644 --- a/java/hiddenapi_modular.go +++ b/java/hiddenapi_modular.go @@ -440,7 +440,18 @@ var hiddenAPIRemovedFlagFileCategory = &hiddenAPIFlagFileCategory{ }, } -var HiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{ +type hiddenAPIFlagFileCategories []*hiddenAPIFlagFileCategory + +func (c hiddenAPIFlagFileCategories) byProperty(name string) *hiddenAPIFlagFileCategory { + for _, category := range c { + if category.PropertyName == name { + return category + } + } + panic(fmt.Errorf("no category exists with property name %q in %v", name, c)) +} + +var HiddenAPIFlagFileCategories = hiddenAPIFlagFileCategories{ // See HiddenAPIFlagFileProperties.Unsupported { PropertyName: "unsupported", @@ -517,13 +528,20 @@ var HiddenAPIFlagFileCategories = []*hiddenAPIFlagFileCategory{ // FlagFilesByCategory maps a hiddenAPIFlagFileCategory to the paths to the files in that category. type FlagFilesByCategory map[*hiddenAPIFlagFileCategory]android.Paths -// append appends the supplied flags files to the corresponding category in this map. +// append the supplied flags files to the corresponding category in this map. func (s FlagFilesByCategory) append(other FlagFilesByCategory) { for _, category := range HiddenAPIFlagFileCategories { s[category] = append(s[category], other[category]...) } } +// sort the paths for each category in this map. +func (s FlagFilesByCategory) sort() { + for category, value := range s { + s[category] = android.SortedUniquePaths(value) + } +} + // HiddenAPIInfo contains information provided by the hidden API processing. // // That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API @@ -706,6 +724,8 @@ type HiddenAPIPropertyInfo struct { SplitPackages []string } +var hiddenAPIPropertyInfoProvider = blueprint.NewProvider(HiddenAPIPropertyInfo{}) + // newHiddenAPIPropertyInfo creates a new initialized HiddenAPIPropertyInfo struct. func newHiddenAPIPropertyInfo() HiddenAPIPropertyInfo { return HiddenAPIPropertyInfo{ @@ -730,6 +750,24 @@ func (i *HiddenAPIPropertyInfo) extractPackageRulesFromProperties(p *HiddenAPIPa i.SplitPackages = p.Hidden_api.Split_packages } +func (i *HiddenAPIPropertyInfo) gatherPropertyInfo(ctx android.ModuleContext, contents []android.Module) { + for _, module := range contents { + if ctx.OtherModuleHasProvider(module, hiddenAPIPropertyInfoProvider) { + info := ctx.OtherModuleProvider(module, hiddenAPIPropertyInfoProvider).(HiddenAPIPropertyInfo) + i.FlagFilesByCategory.append(info.FlagFilesByCategory) + i.PackagePrefixes = append(i.PackagePrefixes, info.PackagePrefixes...) + i.SinglePackages = append(i.SinglePackages, info.SinglePackages...) + i.SplitPackages = append(i.SplitPackages, info.SplitPackages...) + } + } + + // Dedup and sort the information to ensure consistent builds. + i.FlagFilesByCategory.sort() + i.PackagePrefixes = android.SortedUniqueStrings(i.PackagePrefixes) + i.SinglePackages = android.SortedUniqueStrings(i.SinglePackages) + i.SplitPackages = android.SortedUniqueStrings(i.SplitPackages) +} + // HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are // needed for hidden API flag generation. type HiddenAPIFlagInput struct { diff --git a/java/java.go b/java/java.go index 6b7ac7501..0251b5754 100644 --- a/java/java.go +++ b/java/java.go @@ -629,6 +629,9 @@ func setUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter, dexer } func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { + + j.provideHiddenAPIPropertyInfo(ctx) + j.sdkVersion = j.SdkVersion(ctx) j.minSdkVersion = j.MinSdkVersion(ctx) j.maxSdkVersion = j.MaxSdkVersion(ctx) @@ -2256,16 +2259,27 @@ type javaDependencyLabels struct { StaticDeps bazel.LabelListAttribute } -// convertLibraryAttrsBp2Build converts a few shared attributes from java_* modules -// and also separates dependencies into dynamic dependencies and static dependencies. -// Each corresponding Bazel target type, can have a different method for handling -// dynamic vs. static dependencies, and so these are returned to the calling function. type eventLogTagsAttributes struct { Srcs bazel.LabelListAttribute } +type aidlLibraryAttributes struct { + Srcs bazel.LabelListAttribute +} + +type javaAidlLibraryAttributes struct { + Deps bazel.LabelListAttribute +} + +// convertLibraryAttrsBp2Build converts a few shared attributes from java_* modules +// and also separates dependencies into dynamic dependencies and static dependencies. +// Each corresponding Bazel target type, can have a different method for handling +// dynamic vs. static dependencies, and so these are returned to the calling function. func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *javaDependencyLabels) { var srcs bazel.LabelListAttribute + var deps bazel.LabelList + var staticDeps bazel.LabelList + archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{}) for axis, configToProps := range archVariantProps { for config, _props := range configToProps { @@ -2279,18 +2293,18 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) javaSrcPartition := "java" protoSrcPartition := "proto" logtagSrcPartition := "logtag" + aidlSrcPartition := "aidl" srcPartitions := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{ javaSrcPartition: bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true}, logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}}, protoSrcPartition: android.ProtoSrcLabelPartition, + aidlSrcPartition: android.AidlSrcLabelPartition, }) javaSrcs := srcPartitions[javaSrcPartition] - var logtagsSrcs bazel.LabelList if !srcPartitions[logtagSrcPartition].IsEmpty() { logtagsLibName := m.Name() + "_logtags" - logtagsSrcs = bazel.MakeLabelList([]bazel.Label{{Label: ":" + logtagsLibName}}) ctx.CreateBazelTargetModule( bazel.BazelTargetModuleProperties{ Rule_class: "event_log_tags", @@ -2301,8 +2315,45 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) Srcs: srcPartitions[logtagSrcPartition], }, ) + + logtagsSrcs := bazel.MakeLabelList([]bazel.Label{{Label: ":" + logtagsLibName}}) + javaSrcs.Append(bazel.MakeLabelListAttribute(logtagsSrcs)) + } + + if !srcPartitions[aidlSrcPartition].IsEmpty() { + aidlLibs, aidlSrcs := srcPartitions[aidlSrcPartition].Partition(func(src bazel.Label) bool { + return android.IsConvertedToAidlLibrary(ctx, src.OriginalModuleName) + }) + + 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}}) + } + + javaAidlLibName := m.Name() + "_java_aidl_library" + ctx.CreateBazelTargetModule( + bazel.BazelTargetModuleProperties{ + Rule_class: "java_aidl_library", + Bzl_load_location: "//build/bazel/rules/java:aidl_library.bzl", + }, + android.CommonAttributes{Name: javaAidlLibName}, + &javaAidlLibraryAttributes{ + Deps: aidlLibs, + }, + ) + + staticDeps.Add(&bazel.Label{Label: ":" + javaAidlLibName}) } - javaSrcs.Append(bazel.MakeLabelListAttribute(logtagsSrcs)) var javacopts []string if m.properties.Javacflags != nil { @@ -2328,14 +2379,10 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) Javacopts: bazel.MakeStringListAttribute(javacopts), } - depLabels := &javaDependencyLabels{} - - var deps bazel.LabelList if m.properties.Libs != nil { deps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Libs)))) } - var staticDeps bazel.LabelList if m.properties.Static_libs != nil { staticDeps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Static_libs)))) } @@ -2349,6 +2396,7 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) // and so this should be a static dependency. staticDeps.Add(protoDepLabel) + depLabels := &javaDependencyLabels{} depLabels.Deps = bazel.MakeLabelListAttribute(deps) depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps) @@ -2373,7 +2421,7 @@ func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { // TODO(b/220869005) remove forced dependency on current public android.jar deps.Add(bazel.MakeLabelAttribute("//prebuilts/sdk:public_current_android_sdk_java_import")) } - } else if !depLabels.Deps.IsEmpty() { + } else if !deps.IsEmpty() { ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.") } diff --git a/java/java_test.go b/java/java_test.go index bfd97eb0d..7f0cea718 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -1747,3 +1747,37 @@ func TestImportMixedBuild(t *testing.T) { android.AssertDeepEquals(t, "Implementation/Resources JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationAndResourcesJars)) android.AssertDeepEquals(t, "Implementation JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationJars)) } + +func TestGenAidlIncludeFlagsForMixedBuilds(t *testing.T) { + bazelOutputBaseDir := filepath.Join("out", "bazel") + result := android.GroupFixturePreparers( + PrepareForIntegrationTestWithJava, + android.FixtureModifyConfig(func(config android.Config) { + config.BazelContext = android.MockBazelContext{ + OutputBaseDir: bazelOutputBaseDir, + } + }), + ).RunTest(t) + + ctx := &android.TestPathContext{TestResult: result} + + srcDirectory := filepath.Join("frameworks", "base") + srcDirectoryAlreadyIncluded := filepath.Join("frameworks", "base", "core", "java") + bazelSrcDirectory := android.PathForBazelOut(ctx, srcDirectory) + bazelSrcDirectoryAlreadyIncluded := android.PathForBazelOut(ctx, srcDirectoryAlreadyIncluded) + srcs := android.Paths{ + android.PathForTestingWithRel(bazelSrcDirectory.String(), "bazelAidl.aidl"), + android.PathForTestingWithRel(bazelSrcDirectory.String(), "bazelAidl2.aidl"), + android.PathForTestingWithRel(bazelSrcDirectoryAlreadyIncluded.String(), "bazelAidlExclude.aidl"), + android.PathForTestingWithRel(bazelSrcDirectoryAlreadyIncluded.String(), "bazelAidl2Exclude.aidl"), + } + dirsAlreadyIncluded := android.Paths{ + android.PathForTesting(srcDirectoryAlreadyIncluded), + } + + expectedFlags := " -Iout/bazel/execroot/__main__/frameworks/base" + flags := genAidlIncludeFlags(ctx, srcs, dirsAlreadyIncluded) + if flags != expectedFlags { + t.Errorf("expected flags to be %q; was %q", expectedFlags, flags) + } +} diff --git a/rust/config/global.go b/rust/config/global.go index 9acbfb355..e67683786 100644 --- a/rust/config/global.go +++ b/rust/config/global.go @@ -24,7 +24,7 @@ import ( var pctx = android.NewPackageContext("android/soong/rust/config") var ( - RustDefaultVersion = "1.62.0.p1" + RustDefaultVersion = "1.63.0" RustDefaultBase = "prebuilts/rust/" DefaultEdition = "2021" Stdlibs = []string{ 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/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go index 13ddbe768..c93055a51 100644 --- a/sdk/bootclasspath_fragment_sdk_test.go +++ b/sdk/bootclasspath_fragment_sdk_test.go @@ -675,8 +675,8 @@ func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) { prepareForSdkTestWithJava, java.PrepareForTestWithJavaDefaultModules, java.PrepareForTestWithJavaSdkLibraryFiles, - java.FixtureWithLastReleaseApis("mysdklibrary"), - java.FixtureConfigureApexBootJars("myapex:mybootlib"), + java.FixtureWithLastReleaseApis("mysdklibrary", "mynewlibrary"), + java.FixtureConfigureApexBootJars("myapex:mybootlib", "myapex:mynewlibrary"), prepareForSdkTestWithApex, // Add a platform_bootclasspath that depends on the fragment. @@ -691,6 +691,7 @@ func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) { "my-removed.txt": nil, "my-unsupported-packages.txt": nil, "my-unsupported.txt": nil, + "my-new-max-target-q.txt": nil, }.AddToFixture(), android.FixtureWithRootAndroidBp(` sdk { @@ -708,7 +709,7 @@ func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) { bootclasspath_fragment { name: "mybootclasspathfragment", apex_available: ["myapex"], - contents: ["mybootlib"], + contents: ["mybootlib", "mynewlibrary"], api: { stub_libs: ["mysdklibrary"], }, @@ -737,7 +738,9 @@ func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) { unsupported_packages: [ "my-unsupported-packages.txt", ], - split_packages: ["*"], + split_packages: ["sdklibrary"], + package_prefixes: ["sdklibrary.all.mine"], + single_packages: ["sdklibrary.mine"], }, } @@ -759,6 +762,24 @@ func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) { public: {enabled: true}, permitted_packages: ["mysdklibrary"], } + + java_sdk_library { + name: "mynewlibrary", + apex_available: ["myapex"], + srcs: ["Test.java"], + min_sdk_version: "10", + compile_dex: true, + public: {enabled: true}, + permitted_packages: ["mysdklibrary"], + hidden_api: { + max_target_q: [ + "my-new-max-target-q.txt", + ], + split_packages: ["sdklibrary", "newlibrary"], + package_prefixes: ["newlibrary.all.mine"], + single_packages: ["newlibrary.mine"], + }, + } `), ).RunTest(t) @@ -774,7 +795,10 @@ prebuilt_bootclasspath_fragment { prefer: false, visibility: ["//visibility:public"], apex_available: ["myapex"], - contents: ["mybootlib"], + contents: [ + "mybootlib", + "mynewlibrary", + ], api: { stub_libs: ["mysdklibrary"], }, @@ -782,7 +806,10 @@ prebuilt_bootclasspath_fragment { unsupported: ["hiddenapi/my-unsupported.txt"], removed: ["hiddenapi/my-removed.txt"], max_target_r_low_priority: ["hiddenapi/my-max-target-r-low-priority.txt"], - max_target_q: ["hiddenapi/my-max-target-q.txt"], + max_target_q: [ + "hiddenapi/my-max-target-q.txt", + "hiddenapi/my-new-max-target-q.txt", + ], max_target_p: ["hiddenapi/my-max-target-p.txt"], max_target_o_low_priority: ["hiddenapi/my-max-target-o-low-priority.txt"], blocked: ["hiddenapi/my-blocked.txt"], @@ -806,6 +833,23 @@ java_import { } java_sdk_library_import { + name: "mynewlibrary", + prefer: false, + visibility: ["//visibility:public"], + apex_available: ["myapex"], + shared_library: true, + compile_dex: true, + permitted_packages: ["mysdklibrary"], + public: { + jars: ["sdk_library/public/mynewlibrary-stubs.jar"], + stub_srcs: ["sdk_library/public/mynewlibrary_stub_sources"], + current_api: "sdk_library/public/mynewlibrary.txt", + removed_api: "sdk_library/public/mynewlibrary-removed.txt", + sdk_version: "current", + }, +} + +java_sdk_library_import { name: "mysdklibrary", prefer: false, visibility: ["//visibility:public"], @@ -827,6 +871,7 @@ my-unsupported.txt -> hiddenapi/my-unsupported.txt my-removed.txt -> hiddenapi/my-removed.txt my-max-target-r-low-priority.txt -> hiddenapi/my-max-target-r-low-priority.txt my-max-target-q.txt -> hiddenapi/my-max-target-q.txt +my-new-max-target-q.txt -> hiddenapi/my-new-max-target-q.txt my-max-target-p.txt -> hiddenapi/my-max-target-p.txt my-max-target-o-low-priority.txt -> hiddenapi/my-max-target-o-low-priority.txt my-blocked.txt -> hiddenapi/my-blocked.txt @@ -838,6 +883,9 @@ my-unsupported-packages.txt -> hiddenapi/my-unsupported-packages.txt .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv .intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar +.intermediates/mynewlibrary.stubs/android_common/javac/mynewlibrary.stubs.jar -> sdk_library/public/mynewlibrary-stubs.jar +.intermediates/mynewlibrary.stubs.source/android_common/metalava/mynewlibrary.stubs.source_api.txt -> sdk_library/public/mynewlibrary.txt +.intermediates/mynewlibrary.stubs.source/android_common/metalava/mynewlibrary.stubs.source_removed.txt -> sdk_library/public/mynewlibrary-removed.txt .intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar .intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt .intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt diff --git a/sdk/build_release.go b/sdk/build_release.go index 20b33d6aa..ac57a3279 100644 --- a/sdk/build_release.go +++ b/sdk/build_release.go @@ -16,6 +16,7 @@ package sdk import ( "fmt" + "math" "reflect" "strings" ) @@ -29,7 +30,10 @@ type buildRelease struct { // The name of the release, e.g. S, Tiramisu, etc. name string - // The index of this structure within the buildReleases list. + // The index of this structure within the dessertBuildReleases list. + // + // The buildReleaseCurrent does not appear in the dessertBuildReleases list as it has an ordinal value + // that is larger than the size of the dessertBuildReleases. ordinal int } @@ -56,7 +60,7 @@ func (s *buildReleaseSet) addItem(release *buildRelease) { // addRange adds all the build releases from start (inclusive) to end (inclusive). func (s *buildReleaseSet) addRange(start *buildRelease, end *buildRelease) { for i := start.ordinal; i <= end.ordinal; i += 1 { - s.addItem(buildReleases[i]) + s.addItem(dessertBuildReleases[i]) } } @@ -69,11 +73,17 @@ func (s *buildReleaseSet) contains(release *buildRelease) bool { // String returns a string representation of the set, sorted from earliest to latest release. func (s *buildReleaseSet) String() string { list := []string{} - for _, release := range buildReleases { + addRelease := func(release *buildRelease) { if _, ok := s.contents[release]; ok { list = append(list, release.name) } } + // Add the names of the build releases in this set in the order in which they were created. + for _, release := range dessertBuildReleases { + addRelease(release) + } + // Always add "current" to the list of names last if it is present in the set. + addRelease(buildReleaseCurrent) return fmt.Sprintf("[%s]", strings.Join(list, ",")) } @@ -81,30 +91,46 @@ var ( // nameToBuildRelease contains a map from name to build release. nameToBuildRelease = map[string]*buildRelease{} - // buildReleases lists all the available build releases. - buildReleases = []*buildRelease{} + // dessertBuildReleases lists all the available dessert build releases, i.e. excluding current. + dessertBuildReleases = []*buildRelease{} // allBuildReleaseSet is the set of all build releases. allBuildReleaseSet = &buildReleaseSet{contents: map[*buildRelease]struct{}{}} - // Add the build releases from oldest to newest. + // Add the dessert build releases from oldest to newest. buildReleaseS = initBuildRelease("S") buildReleaseT = initBuildRelease("Tiramisu") + + // Add the current build release which is always treated as being more recent than any other + // build release, including those added in tests. + buildReleaseCurrent = initBuildRelease("current") ) // initBuildRelease creates a new build release with the specified name. func initBuildRelease(name string) *buildRelease { - ordinal := len(nameToBuildRelease) + ordinal := len(dessertBuildReleases) + if name == "current" { + // The current build release is more recent than all other build releases, including those + // created in tests so use the max int value. It cannot just rely on being created after all + // the other build releases as some are created in tests which run after the current build + // release has been created. + ordinal = math.MaxInt + } release := &buildRelease{name: name, ordinal: ordinal} nameToBuildRelease[name] = release - buildReleases = append(buildReleases, release) allBuildReleaseSet.addItem(release) + if name != "current" { + // As the current build release has an ordinal value that does not correspond to its position + // in the dessertBuildReleases list do not add it to the list. + dessertBuildReleases = append(dessertBuildReleases, release) + } return release } -// latestBuildRelease returns the latest build release, i.e. the last one added. -func latestBuildRelease() *buildRelease { - return buildReleases[len(buildReleases)-1] +// latestDessertBuildRelease returns the latest dessert release build name, i.e. the last dessert +// release added to the list, which does not include current. +func latestDessertBuildRelease() *buildRelease { + return dessertBuildReleases[len(dessertBuildReleases)-1] } // nameToRelease maps from build release name to the corresponding build release (if it exists) or @@ -134,8 +160,10 @@ func parseBuildReleaseSet(specification string) (*buildReleaseSet, error) { if err != nil { return nil, err } - end := latestBuildRelease() + end := latestDessertBuildRelease() set.addRange(start, end) + // An open-ended range always includes the current release. + set.addItem(buildReleaseCurrent) } else if strings.Contains(specification, "-") { limits := strings.SplitN(specification, "-", 2) start, err := nameToRelease(limits[0]) diff --git a/sdk/build_release_test.go b/sdk/build_release_test.go index 6f1ef9e30..13730cbca 100644 --- a/sdk/build_release_test.go +++ b/sdk/build_release_test.go @@ -42,7 +42,7 @@ func TestNameToRelease(t *testing.T) { android.AssertDeepEquals(t, "release", (*buildRelease)(nil), release) // Uses a wildcard in the error message to allow for additional build releases to be added to // the supported set without breaking this test. - android.FailIfNoMatchingErrors(t, `unknown release "A", expected one of \[S,T.*,F1,F2\]`, []error{err}) + android.FailIfNoMatchingErrors(t, `unknown release "A", expected one of \[S,Tiramisu,F1,F2,current\]`, []error{err}) }) } @@ -55,7 +55,7 @@ func TestParseBuildReleaseSet(t *testing.T) { t.Run("open range", func(t *testing.T) { set, err := parseBuildReleaseSet("F1+") android.AssertDeepEquals(t, "errors", nil, err) - android.AssertStringEquals(t, "set", "[F1,F2]", set.String()) + android.AssertStringEquals(t, "set", "[F1,F2,current]", set.String()) }) t.Run("closed range", func(t *testing.T) { set, err := parseBuildReleaseSet("S-F1") diff --git a/sdk/testing.go b/sdk/testing.go index bed11b27d..f4e2b031b 100644 --- a/sdk/testing.go +++ b/sdk/testing.go @@ -262,8 +262,7 @@ func CheckSnapshot(t *testing.T, result *android.TestResult, name string, dir st // If the generated snapshot builders not for the current release then it cannot be loaded by // the current release. - currentBuildRelease := latestBuildRelease() - if snapshotBuildInfo.targetBuildRelease != currentBuildRelease { + if snapshotBuildInfo.targetBuildRelease != buildReleaseCurrent { return } diff --git a/sdk/update.go b/sdk/update.go index c555ddc7a..5c9376b5d 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -387,12 +387,11 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) { // Always add -current to the end snapshotFileSuffix := "-current" - currentBuildRelease := latestBuildRelease() - targetBuildReleaseEnv := config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", currentBuildRelease.name) + targetBuildReleaseEnv := config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", buildReleaseCurrent.name) targetBuildRelease, err := nameToRelease(targetBuildReleaseEnv) if err != nil { ctx.ModuleErrorf("invalid SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE: %s", err) - targetBuildRelease = currentBuildRelease + targetBuildRelease = buildReleaseCurrent } builder := &snapshotBuilder{ @@ -472,7 +471,7 @@ be unnecessary as every module in the sdk already has its own licenses property. contents := bp.content.String() // If the snapshot is being generated for the current build release then check the syntax to make // sure that it is compatible. - if targetBuildRelease == currentBuildRelease { + if targetBuildRelease == buildReleaseCurrent { syntaxCheckSnapshotBpFile(ctx, contents) } 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/tests/apex_comparison_tests.sh b/tests/apex_comparison_tests.sh index 4b2f795de..ac3c177ba 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,9 +58,6 @@ 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 \ diff --git a/ui/build/build.go b/ui/build/build.go index f7a2d7b18..ecf11ccd6 100644 --- a/ui/build/build.go +++ b/ui/build/build.go @@ -104,12 +104,29 @@ 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) { + // TODO(cparsons): Remove USE_BAZEL_ANALYSIS handling. + if config.Environment().IsEnvTrue("USE_BAZEL_ANALYSIS") { + if config.bazelProdMode || config.bazelDevMode { + ctx.Fatalf("USE_BAZEL_ANALYSIS is deprecated.\n" + + "Unset USE_BAZEL_ANALYSIS when using --bazel-mode or --bazel-mode-dev.") + } else { + config.bazelDevMode = true + } + } + if config.bazelProdMode && config.bazelDevMode { + ctx.Fatalf("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 +238,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 +255,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 cbf198641..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 { @@ -1326,6 +1287,10 @@ func (c *configImpl) KatiPackageNinjaFile() string { return filepath.Join(c.OutDir(), "build"+c.KatiSuffix()+katiPackageSuffix+".ninja") } +func (c *configImpl) SoongVarsFile() string { + return filepath.Join(c.SoongOutDir(), "soong.variables") +} + func (c *configImpl) SoongNinjaFile() string { return filepath.Join(c.SoongOutDir(), "build.ninja") } diff --git a/ui/build/config_test.go b/ui/build/config_test.go index e29327572..2887f59a6 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,38 @@ 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", + name: "bazel mixed build from env", environ: Environment{"USE_BAZEL_ANALYSIS=1"}, expectedBuildConfig: &smpb.BuildConfig{ ForceUseGoma: proto.Bool(false), UseGoma: proto.Bool(false), UseRbe: proto.Bool(false), - BazelAsNinja: proto.Bool(false), + BazelMixedBuild: proto.Bool(true), + }, + }, + { + 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), BazelMixedBuild: proto.Bool(true), }, }, @@ -1083,7 +1102,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 +1112,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/dumpvars.go b/ui/build/dumpvars.go index f56964c80..adc56acc7 100644 --- a/ui/build/dumpvars.go +++ b/ui/build/dumpvars.go @@ -141,7 +141,6 @@ var BannerVars = []string{ "PLATFORM_VERSION", "TARGET_PRODUCT", "TARGET_BUILD_VARIANT", - "TARGET_BUILD_TYPE", "TARGET_BUILD_APPS", "TARGET_BUILD_UNBUNDLED", "TARGET_ARCH", @@ -150,18 +149,11 @@ var BannerVars = []string{ "TARGET_2ND_ARCH", "TARGET_2ND_ARCH_VARIANT", "TARGET_2ND_CPU_VARIANT", - "HOST_ARCH", - "HOST_2ND_ARCH", "HOST_OS", "HOST_OS_EXTRA", "HOST_CROSS_OS", - "HOST_CROSS_ARCH", - "HOST_CROSS_2ND_ARCH", - "HOST_BUILD_TYPE", "BUILD_ID", "OUT_DIR", - "AUX_OS_VARIANT_LIST", - "PRODUCT_SOONG_NAMESPACES", "SOONG_SDK_SNAPSHOT_PREFER", "SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", "SOONG_SDK_SNAPSHOT_USE_SOURCE_CONFIG_VAR", @@ -236,6 +228,13 @@ func runMakeProductConfig(ctx Context, config Config) { // Not used, but useful to be in the soong.log "BOARD_VNDK_VERSION", + "TARGET_BUILD_TYPE", + "HOST_ARCH", + "HOST_2ND_ARCH", + "HOST_CROSS_ARCH", + "HOST_CROSS_2ND_ARCH", + "HOST_BUILD_TYPE", + "PRODUCT_SOONG_NAMESPACES", "DEFAULT_WARNING_BUILD_MODULE_TYPES", "DEFAULT_ERROR_BUILD_MODULE_TYPES", diff --git a/ui/build/soong.go b/ui/build/soong.go index 29c3b65c9..ff6d68f48 100644 --- a/ui/build/soong.go +++ b/ui/build/soong.go @@ -22,6 +22,7 @@ import ( "os" "path/filepath" "strconv" + "strings" "android/soong/ui/metrics" soong_metrics_proto "android/soong/ui/metrics/metrics_proto" @@ -169,9 +170,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 @@ -186,7 +186,7 @@ func primaryBuilderInvocation( invocationEnv["GODEBUG"] = "asyncpreemptoff=1" } - allArgs := make([]string, 0, 0) + var allArgs []string allArgs = append(allArgs, specificArgs...) allArgs = append(allArgs, "--globListDir", name, @@ -253,6 +253,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, @@ -262,7 +268,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 . @@ -372,9 +378,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) @@ -404,7 +407,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)) } @@ -445,6 +448,11 @@ func runSoong(ctx Context, config Config) { "-f", filepath.Join(config.SoongOutDir(), ninjaFile), } + if extra, ok := config.Environment().Get("SOONG_UI_NINJA_ARGS"); ok { + ctx.Printf(`CAUTION: arguments in $SOONG_UI_NINJA_ARGS=%q, e.g. "-n", can make soong_build FAIL or INCORRECT`, extra) + ninjaArgs = append(ninjaArgs, strings.Fields(extra)...) + } + ninjaArgs = append(ninjaArgs, targets...) cmd := Command(ctx, config, "soong "+name, config.PrebuiltBuildTool("ninja"), ninjaArgs...) @@ -496,6 +504,7 @@ func runSoong(ctx Context, config Config) { } distGzipFile(ctx, config, config.SoongNinjaFile(), "soong") + distFile(ctx, config, config.SoongVarsFile(), "soong") if !config.SkipKati() { distGzipFile(ctx, config, config.SoongAndroidMk(), "soong") 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) } |