Skip to content

Commit a4bbb84

Browse files
luispadronallevato
andauthored
Ensure that PCMs are hermetic on Xcode 16 and higher. (#1575)
Cherry-picks: - 038b5bd - 2767c64 - fa2f3cd Co-authored-by: Tony Allevato <allevato@google.com>
1 parent ac56ae1 commit a4bbb84

File tree

4 files changed

+86
-8
lines changed

4 files changed

+86
-8
lines changed

swift/internal/feature_names.bzl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ SWIFT_FEATURE_FULL_DEBUG_INFO = "swift.full_debug_info"
132132
# Use CodeView debug information, which enables generation of PDBs for debugging.
133133
SWIFT_FEATURE_CODEVIEW_DEBUG_INFO = "swift.codeview_debug_info"
134134

135+
# If enabled, paths embedded into precompiled Clang modules will be relative to
136+
# the workspace, not to the modulemap file location. Paths in the module maps
137+
# themselves will still be treated as modulemap-relative.
138+
SWIFT_FEATURE_MODULE_HOME_IS_CWD = "swift.module_home_is_cwd"
139+
135140
# If enabled, compilation actions and module map generation will assume that the
136141
# header paths in module maps are relative to the current working directory
137142
# (i.e., the workspace root); if disabled, header paths in module maps are

swift/toolchains/config/compile_config.bzl

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ load(
4848
"SWIFT_FEATURE_DISABLE_SWIFT_SANDBOX",
4949
"SWIFT_FEATURE_DISABLE_SYSTEM_INDEX",
5050
"SWIFT_FEATURE_EMIT_BC",
51+
"SWIFT_FEATURE_EMIT_C_MODULE",
5152
"SWIFT_FEATURE_EMIT_PRIVATE_SWIFTINTERFACE",
5253
"SWIFT_FEATURE_EMIT_SWIFTDOC",
5354
"SWIFT_FEATURE_EMIT_SWIFTINTERFACE",
@@ -67,6 +68,7 @@ load(
6768
"SWIFT_FEATURE_INTERNALIZE_AT_LINK",
6869
"SWIFT_FEATURE_LAYERING_CHECK",
6970
"SWIFT_FEATURE_MODULAR_INDEXING",
71+
"SWIFT_FEATURE_MODULE_HOME_IS_CWD",
7072
"SWIFT_FEATURE_MODULE_MAP_HOME_IS_CWD",
7173
"SWIFT_FEATURE_NO_ASAN_VERSION_CHECK",
7274
"SWIFT_FEATURE_OPT",
@@ -646,6 +648,52 @@ def compile_action_configs(
646648
],
647649
),
648650

651+
# Explicitly set the working directory to ensure that the
652+
# `FILE_SYSTEM_OPTIONS` block of PCM files is hermetic.
653+
#
654+
# IMPORTANT: When writing a PCM file, Clang *unconditionally* includes
655+
# the working directory in the `FILE_SYSTEM_OPTIONS` block. Thus, the
656+
# only way to ensure that these files are hermetic is to pass
657+
# `-working-directory=.`. We cannot pass this to Swift, however, because
658+
# the driver unfortunately resolves whatever path is given to it and
659+
# then passes all of the source files as absolute paths to the
660+
# frontend, which makes other outputs non-hermetic. Therefore, we *only*
661+
# pass this flag to Clang. Having the two values not be literally
662+
# identical should still be safe, because we're only passing a value
663+
# here that is *effectively* the same as the default.
664+
ActionConfigInfo(
665+
actions = all_compile_action_names() + [
666+
SWIFT_ACTION_PRECOMPILE_C_MODULE,
667+
],
668+
configurators = [
669+
add_arg("-Xcc", "-working-directory"),
670+
add_arg("-Xcc", "."),
671+
],
672+
features = [[
673+
SWIFT_FEATURE_EMIT_C_MODULE,
674+
SWIFT_FEATURE_USE_C_MODULES,
675+
SWIFT_FEATURE_MODULE_HOME_IS_CWD,
676+
]],
677+
),
678+
# Treat paths embedded into .pcm files as workspace-relative, not
679+
# modulemap-relative.
680+
ActionConfigInfo(
681+
actions = all_compile_action_names() + [
682+
SWIFT_ACTION_COMPILE_MODULE_INTERFACE,
683+
SWIFT_ACTION_PRECOMPILE_C_MODULE,
684+
SWIFT_ACTION_SYMBOL_GRAPH_EXTRACT,
685+
],
686+
configurators = [
687+
add_arg("-Xcc", "-Xclang"),
688+
add_arg("-Xcc", "-fmodule-file-home-is-cwd"),
689+
],
690+
features = [[
691+
SWIFT_FEATURE_EMIT_C_MODULE,
692+
SWIFT_FEATURE_USE_C_MODULES,
693+
SWIFT_FEATURE_MODULE_HOME_IS_CWD,
694+
]],
695+
),
696+
649697
# Treat paths in .modulemap files as workspace-relative, not modulemap-
650698
# relative.
651699
ActionConfigInfo(
@@ -1099,7 +1147,7 @@ def compile_action_configs(
10991147
SWIFT_ACTION_PRECOMPILE_C_MODULE,
11001148
],
11011149
configurators = [
1102-
add_arg("-file-prefix-map", "__BAZEL_XCODE_DEVELOPER_DIR__=DEVELOPER_DIR"),
1150+
add_arg("-file-prefix-map", "__BAZEL_XCODE_DEVELOPER_DIR__=/PLACEHOLDER_DEVELOPER_DIR"),
11031151
],
11041152
features = [SWIFT_FEATURE_FILE_PREFIX_MAP],
11051153
),

swift/toolchains/xcode_swift_toolchain.bzl

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ load(
5656
"SWIFT_FEATURE_DEBUG_PREFIX_MAP",
5757
"SWIFT_FEATURE_DISABLE_SWIFT_SANDBOX",
5858
"SWIFT_FEATURE_FILE_PREFIX_MAP",
59+
"SWIFT_FEATURE_MODULE_HOME_IS_CWD",
5960
"SWIFT_FEATURE_MODULE_MAP_HOME_IS_CWD",
6061
"SWIFT_FEATURE_REMAP_XCODE_PATH",
6162
"SWIFT_FEATURE__SUPPORTS_UPCOMING_FEATURES",
@@ -708,7 +709,16 @@ def _xcode_swift_toolchain_impl(ctx):
708709
requested_features.append(SWIFT_FEATURE_DISABLE_SWIFT_SANDBOX)
709710

710711
if _is_xcode_at_least_version(xcode_config, "16.0"):
711-
requested_features.append(SWIFT_FEATURE__SUPPORTS_V6)
712+
requested_features.extend([
713+
SWIFT_FEATURE__SUPPORTS_V6,
714+
# Ensure hermetic PCM files (no absolute workspace paths). This flag
715+
# is actually supported on Xcode 15.x as well, but it's bugged; a
716+
# `MODULE_DIRECTORY` field remains in the PCM file that has the
717+
# absolute workspace path, so it's not hermetic, and worse, it
718+
# causes other compilation errors in the unfortunately common case
719+
# where two modules contain the same header.
720+
SWIFT_FEATURE_MODULE_HOME_IS_CWD,
721+
])
712722

713723
unsupported_features = ctx.disabled_features + [
714724
SWIFT_FEATURE_MODULE_MAP_HOME_IS_CWD,

tools/worker/swift_runner.cc

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,24 @@ bool SwiftRunner::ProcessArgument(
285285
Iterator &itr, const std::string &arg,
286286
std::function<void(const std::string &)> consumer) {
287287
bool changed = false;
288+
289+
// Helper function for adding path remapping flags that depend on information
290+
// only known at execution time.
291+
auto add_prefix_map_flags = [&](const std::string &flag) {
292+
// Get the actual current working directory (the execution root), which
293+
// we didn't know at analysis time.
294+
consumer(flag);
295+
consumer(std::filesystem::current_path().string() + "=.");
296+
297+
#if __APPLE__
298+
std::string developer_dir = "__BAZEL_XCODE_DEVELOPER_DIR__";
299+
if (bazel_placeholder_substitutions_.Apply(developer_dir)) {
300+
consumer(flag);
301+
consumer(developer_dir + "=/PLACEHOLDER_DEVELOPER_DIR");
302+
}
303+
#endif
304+
};
305+
288306
if (arg[0] == '@') {
289307
changed = ProcessPossibleResponseFile(arg, consumer);
290308
} else {
@@ -293,20 +311,17 @@ bool SwiftRunner::ProcessArgument(
293311
if (new_arg == "-debug-prefix-pwd-is-dot") {
294312
// Replace the $PWD with . to make the paths relative to the workspace
295313
// without breaking hermiticity.
296-
consumer("-debug-prefix-map");
297-
consumer(std::filesystem::current_path().string() + "=.");
314+
add_prefix_map_flags("-debug-prefix-map");
298315
changed = true;
299316
} else if (new_arg == "-coverage-prefix-pwd-is-dot") {
300317
// Replace the $PWD with . to make the paths relative to the workspace
301318
// without breaking hermiticity.
302-
consumer("-coverage-prefix-map");
303-
consumer(std::filesystem::current_path().string() + "=.");
319+
add_prefix_map_flags("-file-prefix-map");
304320
changed = true;
305321
} else if (new_arg == "-file-prefix-pwd-is-dot") {
306322
// Replace the $PWD with . to make the paths relative to the workspace
307323
// without breaking hermiticity.
308-
consumer("-file-prefix-map");
309-
consumer(std::filesystem::current_path().string() + "=.");
324+
add_prefix_map_flags("-file-prefix-map");
310325
changed = true;
311326
} else if (StripPrefix("-macro-expansion-dir=", new_arg)) {
312327
changed = true;

0 commit comments

Comments
 (0)