From df4b8416a7365278a5c41d76a720a92c76d3793d Mon Sep 17 00:00:00 2001 From: Aaron Sky Date: Tue, 2 Dec 2025 20:23:45 -0500 Subject: [PATCH 1/2] Enable code coverage in Xcode --- swift/internal/feature_names.bzl | 10 ++++++++++ swift/toolchains/config/compile_config.bzl | 12 ++++++++++++ tools/worker/swift_runner.cc | 18 +++++++++++++++--- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/swift/internal/feature_names.bzl b/swift/internal/feature_names.bzl index 05dd43836..82bbc9c70 100644 --- a/swift/internal/feature_names.bzl +++ b/swift/internal/feature_names.bzl @@ -69,6 +69,16 @@ SWIFT_FEATURE_DEBUG_PREFIX_MAP = "swift.debug_prefix_map" # of remote builds. SWIFT_FEATURE_COVERAGE_PREFIX_MAP = "swift.coverage_prefix_map" +# If enabled, coverage builds will use the `-coverage-prefix-map` feature to +# remap the current working directory to a canonical location, which permits +# coverage representation in non-sandboxed builds with tools that expect +# absolute paths such as Xcode. +# +# This feature should only be used with non-sandboxed builds inside of Xcode, +# and enabling it effectively breaks Bazel's ability to rely on the remote cache +# those builds. +SWIFT_FEATURE_COVERAGE_PREFIX_MAP_CANONICAL_NON_HERMETIC = "swift.coverage_prefix_map_canonical_non_hermetic" + # If enabled, C and Objective-C libraries that are direct or transitive # dependencies of a Swift library will emit explicit precompiled modules that # are compatible with Swift's ClangImporter and propagate them up the build diff --git a/swift/toolchains/config/compile_config.bzl b/swift/toolchains/config/compile_config.bzl index 4d67b77cf..295fd71fe 100644 --- a/swift/toolchains/config/compile_config.bzl +++ b/swift/toolchains/config/compile_config.bzl @@ -40,6 +40,7 @@ load( "SWIFT_FEATURE_CODEVIEW_DEBUG_INFO", "SWIFT_FEATURE_COVERAGE", "SWIFT_FEATURE_COVERAGE_PREFIX_MAP", + "SWIFT_FEATURE_COVERAGE_PREFIX_MAP_CANONICAL_NON_HERMETIC", "SWIFT_FEATURE_DBG", "SWIFT_FEATURE_DEBUG_PREFIX_MAP", "SWIFT_FEATURE_DECLARE_SWIFTSOURCEINFO", @@ -558,6 +559,17 @@ def compile_action_configs( features = [ [SWIFT_FEATURE_COVERAGE_PREFIX_MAP, SWIFT_FEATURE_COVERAGE], ], + not_features = [SWIFT_FEATURE_COVERAGE_PREFIX_MAP_CANONICAL_NON_HERMETIC], + ), + ActionConfigInfo( + actions = all_compile_action_names(), + configurators = [ + add_arg("-Xwrapped-swift=-coverage-prefix-pwd-is-canonical"), + ], + features = [ + [SWIFT_FEATURE_COVERAGE_PREFIX_MAP_CANONICAL_NON_HERMETIC, SWIFT_FEATURE_COVERAGE], + ], + not_features = [SWIFT_FEATURE_COVERAGE_PREFIX_MAP, SWIFT_FEATURE_FILE_PREFIX_MAP], ), # Ensure that .swiftsourceinfo files are tracked and not deleted by the worker diff --git a/tools/worker/swift_runner.cc b/tools/worker/swift_runner.cc index 6610e589e..86e70fc20 100644 --- a/tools/worker/swift_runner.cc +++ b/tools/worker/swift_runner.cc @@ -288,11 +288,12 @@ bool SwiftRunner::ProcessArgument( // Helper function for adding path remapping flags that depend on information // only known at execution time. - auto add_prefix_map_flags = [&](const std::string &flag) { + auto add_prefix_map_flags = [&](const std::string &flag, + const std::string &new_path = ".") { // Get the actual current working directory (the execution root), which // we didn't know at analysis time. consumer(flag); - consumer(std::filesystem::current_path().string() + "=."); + consumer(std::filesystem::current_path().string() + "=" + new_path); #if __APPLE__ std::string developer_dir = "__BAZEL_XCODE_DEVELOPER_DIR__"; @@ -316,7 +317,18 @@ bool SwiftRunner::ProcessArgument( } else if (new_arg == "-coverage-prefix-pwd-is-dot") { // Replace the $PWD with . to make the paths relative to the workspace // without breaking hermiticity. - add_prefix_map_flags("-file-prefix-map"); + add_prefix_map_flags("-coverage-prefix-map"); + changed = true; + } else if (new_arg == "-coverage-prefix-pwd-is-canonical") { + // Replace the $PWD with . to make the paths relative to the workspace + // without breaking hermiticity. + auto cwd = std::filesystem::current_path(); + // The bazel execroot is a normal directory, but inside of it there are + // symlinks to our source tree. This fetches the true path of a known + // directory in order to get the actual source root of the project. This + // should only work with sandboxing disabled. + auto target_path = std::filesystem::canonical(cwd / "BUILD.bazel").parent_path(); + add_prefix_map_flags("-coverage-prefix-map", target_path.string()); changed = true; } else if (new_arg == "-file-prefix-pwd-is-dot") { // Replace the $PWD with . to make the paths relative to the workspace From 3fff8bb4ae908e7d2891bd03a9ee29754b5e4bc7 Mon Sep 17 00:00:00 2001 From: Aaron Sky Date: Wed, 3 Dec 2025 13:08:40 -0500 Subject: [PATCH 2/2] rename feature, make it scarier --- swift/internal/feature_names.bzl | 14 ++++++++------ swift/toolchains/config/compile_config.bzl | 6 +++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/swift/internal/feature_names.bzl b/swift/internal/feature_names.bzl index 82bbc9c70..adc818fbd 100644 --- a/swift/internal/feature_names.bzl +++ b/swift/internal/feature_names.bzl @@ -69,15 +69,17 @@ SWIFT_FEATURE_DEBUG_PREFIX_MAP = "swift.debug_prefix_map" # of remote builds. SWIFT_FEATURE_COVERAGE_PREFIX_MAP = "swift.coverage_prefix_map" -# If enabled, coverage builds will use the `-coverage-prefix-map` feature to -# remap the current working directory to a canonical location, which permits +# A private feature that is used to embed absolute source paths in coverage builds. +# +# If enabled, coverage builds will use a `-coverage-prefix-map` that remaps +# the current working directory to a canonical location, which permits # coverage representation in non-sandboxed builds with tools that expect # absolute paths such as Xcode. # -# This feature should only be used with non-sandboxed builds inside of Xcode, -# and enabling it effectively breaks Bazel's ability to rely on the remote cache -# those builds. -SWIFT_FEATURE_COVERAGE_PREFIX_MAP_CANONICAL_NON_HERMETIC = "swift.coverage_prefix_map_canonical_non_hermetic" +# This feature should only be used with non-sandboxed builds inside tools such as +# Xcode, and enabling it effectively breaks Bazel's ability to rely on the +# remote cache those builds. It should not be enabled by users of the toolchain. +SWIFT_FEATURE__COVERAGE_PREFIX_MAP_ABSOLUTE_SOURCES_NON_HERMETIC = "swift._coverage_prefix_map_absolute_sources_non_hermetic" # If enabled, C and Objective-C libraries that are direct or transitive # dependencies of a Swift library will emit explicit precompiled modules that diff --git a/swift/toolchains/config/compile_config.bzl b/swift/toolchains/config/compile_config.bzl index 295fd71fe..f91271c74 100644 --- a/swift/toolchains/config/compile_config.bzl +++ b/swift/toolchains/config/compile_config.bzl @@ -40,7 +40,6 @@ load( "SWIFT_FEATURE_CODEVIEW_DEBUG_INFO", "SWIFT_FEATURE_COVERAGE", "SWIFT_FEATURE_COVERAGE_PREFIX_MAP", - "SWIFT_FEATURE_COVERAGE_PREFIX_MAP_CANONICAL_NON_HERMETIC", "SWIFT_FEATURE_DBG", "SWIFT_FEATURE_DEBUG_PREFIX_MAP", "SWIFT_FEATURE_DECLARE_SWIFTSOURCEINFO", @@ -91,6 +90,7 @@ load( "SWIFT_FEATURE_USE_GLOBAL_MODULE_CACHE", "SWIFT_FEATURE_USE_PCH_OUTPUT_DIR", "SWIFT_FEATURE_VFSOVERLAY", + "SWIFT_FEATURE__COVERAGE_PREFIX_MAP_ABSOLUTE_SOURCES_NON_HERMETIC", "SWIFT_FEATURE__NUM_THREADS_0_IN_SWIFTCOPTS", "SWIFT_FEATURE__SUPPORTS_UPCOMING_FEATURES", "SWIFT_FEATURE__SUPPORTS_V6", @@ -559,7 +559,7 @@ def compile_action_configs( features = [ [SWIFT_FEATURE_COVERAGE_PREFIX_MAP, SWIFT_FEATURE_COVERAGE], ], - not_features = [SWIFT_FEATURE_COVERAGE_PREFIX_MAP_CANONICAL_NON_HERMETIC], + not_features = [SWIFT_FEATURE__COVERAGE_PREFIX_MAP_ABSOLUTE_SOURCES_NON_HERMETIC], ), ActionConfigInfo( actions = all_compile_action_names(), @@ -567,7 +567,7 @@ def compile_action_configs( add_arg("-Xwrapped-swift=-coverage-prefix-pwd-is-canonical"), ], features = [ - [SWIFT_FEATURE_COVERAGE_PREFIX_MAP_CANONICAL_NON_HERMETIC, SWIFT_FEATURE_COVERAGE], + [SWIFT_FEATURE__COVERAGE_PREFIX_MAP_ABSOLUTE_SOURCES_NON_HERMETIC, SWIFT_FEATURE_COVERAGE], ], not_features = [SWIFT_FEATURE_COVERAGE_PREFIX_MAP, SWIFT_FEATURE_FILE_PREFIX_MAP], ),