From cec0b742fead1e183e8b2b04a8d1c63b0f0f8048 Mon Sep 17 00:00:00 2001 From: Brentley Jones Date: Tue, 23 Aug 2022 13:00:52 -0500 Subject: [PATCH] Add `apple.swizzle_absolute_xcttestsourcelocation` feature (#878) When this feature is enabled, the `@build_bazel_apple_support//lib:swizzle_absolute_xcttestsourcelocation` target is linked into `swift_test` targets. --- doc/rules.md | 7 ++ swift/internal/BUILD | 140 +++++++++++++++++++++++++++ swift/internal/swift_binary_test.bzl | 29 +++++- 3 files changed, 175 insertions(+), 1 deletion(-) diff --git a/doc/rules.md b/doc/rules.md index 8cccb67a0..b3e93e9e1 100644 --- a/doc/rules.md +++ b/doc/rules.md @@ -491,6 +491,13 @@ swift_test( You can also disable this feature for all the tests in a package by applying it to your BUILD file's `package()` declaration instead of the individual targets. +If integrating with Xcode, the relative paths in test binaries can prevent the +Issue navigator from working for test failures. To work around this, you can +have the paths made absolute via swizzling by enabling the +`"apple.swizzle_absolute_xcttestsourcelocation"` feature. You'll also need to +set the `BAZEL_WORKSPACE_DIRECTORY` environment variable in your scheme to the +root of your workspace (i.e. `$(SRCROOT)`). + **ATTRIBUTES** diff --git a/swift/internal/BUILD b/swift/internal/BUILD index d51edc353..1b4c8016f 100644 --- a/swift/internal/BUILD +++ b/swift/internal/BUILD @@ -1,4 +1,5 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library") +load("@bazel_skylib//lib:selects.bzl", "selects") licenses(["notice"]) @@ -404,6 +405,145 @@ bzl_library( srcs = ["build_settings.bzl"], ) +# `config_setting`s to allow for `swizzle_absolute_xcttestsourcelocation` to +# only resolve to an `objc_library` on Apple platforms + +config_setting( + name = "catalyst_x86_64", + values = {"cpu": "catalyst_x86_64"}, +) + +config_setting( + name = "darwin", + values = {"cpu": "darwin"}, +) + +config_setting( + name = "darwin_x86_64", + values = {"cpu": "darwin_x86_64"}, +) + +config_setting( + name = "darwin_arm64", + values = {"cpu": "darwin_arm64"}, +) + +config_setting( + name = "ios_i386", + values = {"cpu": "ios_i386"}, +) + +config_setting( + name = "ios_x86_64", + values = {"cpu": "ios_x86_64"}, +) + +config_setting( + name = "ios_armv7", + values = {"cpu": "ios_armv7"}, +) + +config_setting( + name = "ios_armv7s", + values = {"cpu": "ios_armv7s"}, +) + +config_setting( + name = "ios_arm64", + values = {"cpu": "ios_arm64"}, +) + +config_setting( + name = "ios_arm64e", + values = {"cpu": "ios_arm64e"}, +) + +config_setting( + name = "ios_sim_arm64", + values = {"cpu": "ios_sim_arm64"}, +) + +config_setting( + name = "watchos_arm64", + values = {"cpu": "watchos_arm64"}, +) + +config_setting( + name = "watchos_arm64_32", + values = {"cpu": "watchos_arm64_32"}, +) + +config_setting( + name = "watchos_armv7k", + values = {"cpu": "watchos_armv7k"}, +) + +config_setting( + name = "watchos_i386", + values = {"cpu": "watchos_i386"}, +) + +config_setting( + name = "watchos_x86_64", + values = {"cpu": "watchos_x86_64"}, +) + +config_setting( + name = "tvos_arm64", + values = {"cpu": "tvos_arm64"}, +) + +config_setting( + name = "tvos_sim_arm64", + values = {"cpu": "tvos_sim_arm64"}, +) + +config_setting( + name = "tvos_x86_64", + values = {"cpu": "tvos_x86_64"}, +) + +selects.config_setting_group( + name = "apple", + match_any = [ + ":catalyst_x86_64", + ":darwin", + ":darwin_arm64", + ":darwin_x86_64", + ":ios_arm64", + ":ios_arm64e", + ":ios_armv7", + ":ios_armv7s", + ":ios_i386", + ":ios_sim_arm64", + ":ios_x86_64", + ":watchos_arm64", + ":watchos_arm64_32", + ":watchos_armv7k", + ":watchos_i386", + ":watchos_x86_64", + ":tvos_arm64", + ":tvos_sim_arm64", + ":tvos_x86_64", + ], +) + +# Indirection needed to prevent using `objc_library` outside of macOS +alias( + name = "swizzle_absolute_xcttestsourcelocation", + actual = select({ + ":apple": ( + "@build_bazel_apple_support//lib:swizzle_absolute_xcttestsourcelocation" + ), + "//conditions:default": ":dummy_swizzle_absolute_xcttestsourcelocation", + }), + visibility = ["//visibility:public"], +) + +cc_library( + name = "dummy_swizzle_absolute_xcttestsourcelocation", +) + # Consumed by Bazel integration tests. filegroup( name = "for_bazel_tests", diff --git a/swift/internal/swift_binary_test.bzl b/swift/internal/swift_binary_test.bzl index 8b203ca1f..cb636fd4d 100644 --- a/swift/internal/swift_binary_test.bzl +++ b/swift/internal/swift_binary_test.bzl @@ -145,6 +145,7 @@ def _swift_linking_rule_impl( binary_path, feature_configuration, swift_toolchain, + extra_link_deps = [], linkopts = []): """The shared implementation function for `swift_{binary,test}`. @@ -155,6 +156,8 @@ def _swift_linking_rule_impl( `swift_common.configure_features`. swift_toolchain: The `SwiftToolchainInfo` provider of the toolchain being used to build the target. + extra_link_deps: Additional dependencies that should be linked into the + binary. linkopts: Additional rule-specific flags that should be passed to the linker. @@ -248,7 +251,7 @@ def _swift_linking_rule_impl( cc_feature_configuration = cc_feature_configuration, # This is already collected from `linking_context`. compilation_outputs = None, - deps = ctx.attr.deps, + deps = ctx.attr.deps + extra_link_deps, grep_includes = ctx.file._grep_includes, name = binary_path, output_type = "executable", @@ -354,9 +357,21 @@ def _swift_test_impl(ctx): xctest_bundle_binary = "{0}.xctest/Contents/MacOS/{0}".format(ctx.label.name) binary_path = xctest_bundle_binary if is_bundled else ctx.label.name + # `swift_common.is_enabled` isn't used, as it requires the prefix of the + # feature to start with `swift.` + swizzle_absolute_xcttestsourcelocation = ( + "apple.swizzle_absolute_xcttestsourcelocation" in + feature_configuration._enabled_features + ) + + extra_link_deps = [] + if swizzle_absolute_xcttestsourcelocation: + extra_link_deps.append(ctx.attr._swizzle_absolute_xcttestsourcelocation) + _, linking_outputs, providers = _swift_linking_rule_impl( ctx, binary_path = binary_path, + extra_link_deps = extra_link_deps, feature_configuration = feature_configuration, linkopts = linkopts, swift_toolchain = swift_toolchain, @@ -438,6 +453,11 @@ swift_test = rule( "@build_bazel_apple_support//tools:coverage_support", ), ), + "_swizzle_absolute_xcttestsourcelocation": attr.label( + default = Label( + "@build_bazel_rules_swift//swift/internal:swizzle_absolute_xcttestsourcelocation", + ), + ), "_xctest_runner_template": attr.label( allow_single_file = True, default = Label( @@ -478,6 +498,13 @@ swift_test( You can also disable this feature for all the tests in a package by applying it to your BUILD file's `package()` declaration instead of the individual targets. + +If integrating with Xcode, the relative paths in test binaries can prevent the +Issue navigator from working for test failures. To work around this, you can +have the paths made absolute via swizzling by enabling the +`"apple.swizzle_absolute_xcttestsourcelocation"` feature. You'll also need to +set the `BAZEL_WORKSPACE_DIRECTORY` environment variable in your scheme to the +root of your workspace (i.e. `$(SRCROOT)`). """, executable = True, fragments = ["cpp"],