| set -euo pipefail | |
| source "$(rlocation rules_cc/tests/test_utils.sh)" | |
| source "$(rlocation rules_cc/tests/unittest.bash)" | |
| # Verify that cc_shared_library doesn't cause runtime libraries linked from | |
| # toolchains to be pruned from the final binary. | |
| function setup_tests() { | |
| mkdir -p foo | |
| cat > foo/shared_lib.cc << EOF | |
| #include "runtime_lib.h" | |
| void shared_lib() { runtime_lib(); } | |
| EOF | |
| cat > foo/shared_lib.h << EOF | |
| void shared_lib(); | |
| EOF | |
| cat > foo/runtime_lib.cc << EOF | |
| #include <cstdio> | |
| void runtime_lib() { printf("calling runtime_lib"); } | |
| EOF | |
| cat > foo/runtime_lib.h << EOF | |
| void runtime_lib(); | |
| EOF | |
| cat > foo/main_direct.cc << EOF | |
| #include "runtime_lib.h" | |
| int main() { runtime_lib(); return 0; } | |
| EOF | |
| cat > foo/main_indirect.cc << EOF | |
| #include "shared_lib.h" | |
| int main() { shared_lib(); return 0; } | |
| EOF | |
| cat > foo/misc.cc << EOF | |
| void misc() { } | |
| EOF | |
| cat > foo/toolchain.bzl << EOF | |
| load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") | |
| def _runtimes_toolchain_impl(ctx): | |
| return [platform_common.ToolchainInfo(info = SampleToolchainInfo(runtime = ctx.attr.runtime_lib))] | |
| SampleToolchainInfo = provider( | |
| doc = "Provides a runtime.", | |
| fields = { | |
| "runtime": "The runtime.", | |
| }, | |
| ) | |
| runtimes_toolchain = rule( | |
| implementation = _runtimes_toolchain_impl, | |
| attrs = { | |
| "runtime_lib": attr.label(default = ":runtime_lib"), | |
| }, | |
| provides = [platform_common.ToolchainInfo], | |
| ) | |
| def _toolchain_using_rule_impl(ctx): | |
| runtime = ctx.toolchains["//foo:toolchain_type"].info.runtime | |
| return [runtime[CcInfo], runtime[DefaultInfo]] | |
| toolchain_using_rule = rule( | |
| implementation = _toolchain_using_rule_impl, | |
| provides = [CcInfo], | |
| toolchains = ["//foo:toolchain_type"], | |
| attrs = { | |
| "deps": attr.label_list(default = []), | |
| }, | |
| ) | |
| EOF | |
| cat > foo/BUILD << EOF | |
| load("@rules_cc//cc:cc_shared_library.bzl", "cc_shared_library") | |
| load("@rules_cc//cc:cc_library.bzl", "cc_library") | |
| load("@rules_cc//cc:cc_binary.bzl", "cc_binary") | |
| load("//foo:toolchain.bzl", "runtimes_toolchain", "toolchain_using_rule") | |
| cc_library( | |
| name = "runtime_lib", | |
| srcs = ["runtime_lib.cc"], | |
| hdrs = ["runtime_lib.h"], | |
| ) | |
| runtimes_toolchain( | |
| name = "runtimes_toolchain", | |
| runtime_lib = ":runtime_lib", | |
| ) | |
| toolchain_type(name = "toolchain_type") | |
| toolchain( | |
| name = "toolchain", | |
| toolchain = ":runtimes_toolchain", | |
| toolchain_type = "toolchain_type", | |
| ) | |
| toolchain_using_rule( | |
| name = "toolchain_using_rule", | |
| ) | |
| cc_library( | |
| name = "shared_lib_base", | |
| alwayslink = True, | |
| ) | |
| cc_shared_library( | |
| name = "shared_lib", | |
| deps = [":shared_lib_base"], | |
| ) | |
| cc_binary( | |
| name = "static_dependency", | |
| srcs = ["main_direct.cc", "runtime_lib.h"], | |
| deps = [":toolchain_using_rule"], | |
| dynamic_deps = [":shared_lib"], | |
| ) | |
| cc_library( | |
| name = "shared_lib_with_runtime_deps_base", | |
| srcs = ["shared_lib.cc"], | |
| hdrs = ["shared_lib.h", "runtime_lib.h"], | |
| alwayslink = True, | |
| deps = [":toolchain_using_rule"], | |
| ) | |
| cc_shared_library( | |
| name = "shared_with_runtime_deps", | |
| deps = [":shared_lib_with_runtime_deps_base"], | |
| ) | |
| cc_library( | |
| name = "misc", | |
| srcs = ["misc.cc"], | |
| alwayslink = True, | |
| ) | |
| cc_library( | |
| name = "shared_lib_with_runtime_deps_toolchainless_base", | |
| srcs = ["shared_lib.cc"], | |
| hdrs = ["shared_lib.h"], | |
| deps = [":runtime_lib"], | |
| alwayslink = True, | |
| ) | |
| cc_shared_library( | |
| name = "shared_with_runtime_deps_toolchainless", | |
| deps = [":shared_lib_with_runtime_deps_toolchainless_base"], | |
| ) | |
| cc_binary( | |
| name = "dynamic_dependency", | |
| srcs = ["main_indirect.cc", "shared_lib.h"], | |
| dynamic_deps = [":shared_with_runtime_deps_toolchainless"], | |
| ) | |
| cc_binary( | |
| name = "dynamic_dependency_toolchain", | |
| srcs = ["main_indirect.cc", "shared_lib.h"], | |
| deps = [":misc"], | |
| dynamic_deps = [":shared_with_runtime_deps"], | |
| ) | |
| EOF | |
| } | |
| # Test basic usage of cc_shared_library. | |
| # | |
| # :dynamic_dependency depends on a shared library that depends | |
| # on :runtime_lib, and calls the shared_lib which calls runtime_lib. | |
| function test_dynamic_dependency() { | |
| setup_tests | |
| bazel run \ | |
| //foo:dynamic_dependency >& "${TEST_log}" || fail "Expected build to succeed" | |
| expect_log "calling runtime_lib" | |
| } | |
| # Test cc_shared_library with a toolchain. | |
| # | |
| # :dynamic_dependency_toolchain depends on a shared library that depends on | |
| # :toolchain_using_rule, and calls shared_lib which calls runtime_lib. | |
| function test_dynamic_dependency_toolchain() { | |
| setup_tests | |
| bazel build \ | |
| //foo:dynamic_dependency_toolchain >& "${TEST_log}" && fail "Expected build to fail without toolchain" | |
| bazel run \ | |
| --extra_toolchains=//foo:toolchain \ | |
| //foo:dynamic_dependency_toolchain >& "${TEST_log}" || fail "Expected build to succeed" | |
| expect_log "calling runtime_lib" | |
| } | |
| # Test cc_shared_libary side-effects. | |
| # | |
| # :static_dependency directly depends on :toolchain_using_rule, and calls runtime_lib | |
| # A dynamic library is present, triggering cc_shared_library pruning. | |
| function test_direct_dependency() { | |
| setup_tests | |
| bazel build \ | |
| //foo:static_dependency >& "${TEST_log}" && fail "Expected build to fail without toolchain" | |
| bazel run \ | |
| --extra_toolchains=//foo:toolchain \ | |
| //foo:static_dependency >& "${TEST_log}" || fail "Expected build to succeed" | |
| expect_log "calling runtime_lib" | |
| } | |
| run_suite "Integration tests for cc_shared_library" |