Skip to content

Commit 81c5b92

Browse files
allevatoswiple-rules-gardener
authored andcommitted
Add support for generating an indexstore from a .swiftinterface file.
Starting with Swift 6.1 (Xcode 16.3), the frontend correctly generates an indexstore from a `.swiftinterface` file when it is build with `-explicit-interface-module-build` (swiftlang/swift#79485). Collect that indexstore if requested. To do this, the worker has to find the `.swiftinterface` file and extract the flags from it in order to pass them to the frontend. For system frameworks, this is a bit more delicate, because we don't know the path to the actual `.swiftinterface` file at analysis time (it may be a _variant_ of the current architecture, like `arm64e` for `arm64`). So we add logic to the worker that infers the right file given the path to the parent `.swiftmodule` directory, using similar logic to the compiler itself. PiperOrigin-RevId: 742225315
1 parent 4c41849 commit 81c5b92

File tree

12 files changed

+355
-25
lines changed

12 files changed

+355
-25
lines changed

swift/internal/compiling.bzl

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ def compile_module_interface(
9999
swiftinterface_file,
100100
swift_infos,
101101
swift_toolchain,
102-
target_name, # @unused
102+
target_name,
103103
toolchain_type = SWIFT_TOOLCHAIN_TYPE):
104104
"""Compiles a Swift module interface.
105105
@@ -150,7 +150,10 @@ def compile_module_interface(
150150
the indexstore output files created when the feature
151151
`swift.index_while_building` is enabled.
152152
"""
153-
swiftmodule_file = actions.declare_file("{}.swiftmodule".format(module_name))
153+
swiftmodule_file = actions.declare_file(
154+
"{}_outs/{}.swiftmodule".format(target_name, module_name),
155+
)
156+
outputs = [swiftmodule_file]
154157

155158
implicit_swift_infos, implicit_cc_infos = get_swift_implicit_deps(
156159
feature_configuration = feature_configuration,
@@ -201,11 +204,23 @@ def compile_module_interface(
201204
else:
202205
explicit_swift_module_map_file = None
203206

207+
if is_feature_enabled(
208+
feature_configuration = feature_configuration,
209+
feature_name = SWIFT_FEATURE_INDEX_WHILE_BUILDING,
210+
):
211+
indexstore_directory = actions.declare_directory(
212+
"{}.swiftinterface.indexstore".format(target_name),
213+
)
214+
outputs.append(indexstore_directory)
215+
else:
216+
indexstore_directory = None
217+
204218
prerequisites = struct(
205219
bin_dir = feature_configuration._bin_dir,
206220
cc_compilation_context = merged_compilation_context,
207221
explicit_swift_module_map_file = explicit_swift_module_map_file,
208222
genfiles_dir = feature_configuration._genfiles_dir,
223+
indexstore_directory = indexstore_directory,
209224
is_swift = True,
210225
module_name = module_name,
211226
source_files = [swiftinterface_file],
@@ -220,7 +235,7 @@ def compile_module_interface(
220235
action_name = SWIFT_ACTION_COMPILE_MODULE_INTERFACE,
221236
exec_group = exec_group,
222237
feature_configuration = feature_configuration,
223-
outputs = [swiftmodule_file],
238+
outputs = outputs,
224239
prerequisites = prerequisites,
225240
progress_message = "Compiling Swift module {} from textual interface".format(module_name),
226241
swift_toolchain = swift_toolchain,
@@ -248,8 +263,7 @@ def compile_module_interface(
248263
return struct(
249264
module_context = module_context,
250265
supplemental_outputs = struct(
251-
# TODO: b/401305010 - Generate indexstore when requested.
252-
indexstore_directory = None,
266+
indexstore_directory = indexstore_directory,
253267
),
254268
)
255269

swift/internal/feature_names.bzl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,13 @@ SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION = "swift.enable_library_evolution"
196196
# invocation.
197197
SWIFT_FEATURE_EMIT_SWIFTINTERFACE = "swift.emit_swiftinterface"
198198

199+
# If enabled, the `-explicit-module-interface-build` flag should be passed to
200+
# the compiler when compiling a .swiftinterface file. To support this, the
201+
# worker must extract the correct flags from the interface file manually and
202+
# pass them to the compiler.
203+
# TODO: b/401511920 - Make this the default behavior.
204+
SWIFT_FEATURE_EXPLICIT_INTERFACE_BUILD = "swift.explicit_interface_build"
205+
199206
# If enabled, declare `.swiftsourceinfo` files as outputs that Bazel will track.
200207
# Note that at the time of this writing (Swift 5.10), `.swiftsourceinfo` files
201208
# are non-deterministic: they contain absolute paths that are not remapped by

swift/toolchains/config/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ bzl_library(
4343
deps = [
4444
":action_config",
4545
"//swift/internal:action_names",
46+
"//swift/internal:feature_names",
4647
],
4748
)
4849

swift/toolchains/config/compile_config.bzl

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ load(
4242
"SWIFT_FEATURE_ENABLE_LIBRARY_EVOLUTION",
4343
"SWIFT_FEATURE_ENABLE_TESTING",
4444
"SWIFT_FEATURE_ENABLE_V6",
45+
"SWIFT_FEATURE_EXPLICIT_INTERFACE_BUILD",
4546
"SWIFT_FEATURE_FASTBUILD",
4647
"SWIFT_FEATURE_FILE_PREFIX_MAP",
4748
"SWIFT_FEATURE_FULL_DEBUG_INFO",
@@ -775,12 +776,16 @@ def compile_action_configs(
775776

776777
# Configure index-while-building.
777778
ActionConfigInfo(
778-
actions = all_compile_action_names(),
779+
actions = all_compile_action_names() + [
780+
SWIFT_ACTION_COMPILE_MODULE_INTERFACE,
781+
],
779782
configurators = [_index_while_building_configurator],
780783
features = [SWIFT_FEATURE_INDEX_WHILE_BUILDING],
781784
),
782785
ActionConfigInfo(
783-
actions = all_compile_action_names(),
786+
actions = all_compile_action_names() + [
787+
SWIFT_ACTION_COMPILE_MODULE_INTERFACE,
788+
],
784789
configurators = [add_arg("-index-include-locals")],
785790
features = [
786791
SWIFT_FEATURE_INDEX_WHILE_BUILDING,
@@ -850,6 +855,15 @@ def compile_action_configs(
850855
SWIFT_FEATURE_DISABLE_AVAILABILITY_CHECKING,
851856
],
852857
),
858+
ActionConfigInfo(
859+
actions = [
860+
SWIFT_ACTION_COMPILE_MODULE_INTERFACE,
861+
],
862+
configurators = [add_arg("-disable-availability-checking")],
863+
features = [
864+
SWIFT_FEATURE_DISABLE_AVAILABILITY_CHECKING,
865+
],
866+
),
853867
ActionConfigInfo(
854868
actions = all_compile_action_names(),
855869
configurators = [_upcoming_and_experimental_features_configurator],
@@ -918,15 +932,25 @@ def compile_action_configs(
918932
),
919933
)
920934

921-
action_configs.append(
935+
action_configs.extend([
922936
ActionConfigInfo(
923937
actions = all_compile_action_names() + [
924-
SWIFT_ACTION_COMPILE_MODULE_INTERFACE,
925938
SWIFT_ACTION_PRECOMPILE_C_MODULE,
926939
],
927940
configurators = [_source_files_configurator],
928941
),
929-
)
942+
943+
# We don't add the path as a source file if this is an explicit
944+
# interface build, because we let the worker infer it in the event that
945+
# it is a system module.
946+
ActionConfigInfo(
947+
actions = [
948+
SWIFT_ACTION_COMPILE_MODULE_INTERFACE,
949+
],
950+
configurators = [_source_files_configurator],
951+
not_features = [SWIFT_FEATURE_EXPLICIT_INTERFACE_BUILD],
952+
),
953+
])
930954

931955
# Add additional input files to the sandbox (does not modify flags).
932956
action_configs.append(

swift/toolchains/config/compile_module_interface_config.bzl

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ load(
1818
"@build_bazel_rules_swift//swift/internal:action_names.bzl",
1919
"SWIFT_ACTION_COMPILE_MODULE_INTERFACE",
2020
)
21+
load(
22+
"@build_bazel_rules_swift//swift/internal:feature_names.bzl",
23+
"SWIFT_FEATURE_EXPLICIT_INTERFACE_BUILD",
24+
)
2125
load(":action_config.bzl", "ActionConfigInfo", "add_arg")
2226

2327
visibility([
@@ -35,16 +39,34 @@ def compile_module_interface_action_configs():
3539
),
3640
ActionConfigInfo(
3741
actions = [SWIFT_ACTION_COMPILE_MODULE_INTERFACE],
38-
configurators = [_emit_module_path_from_module_interface_configurator],
42+
configurators = [
43+
_emit_module_path_from_module_interface_configurator,
44+
],
3945
),
4046
ActionConfigInfo(
4147
actions = [SWIFT_ACTION_COMPILE_MODULE_INTERFACE],
4248
configurators = [
4349
add_arg("-compile-module-from-interface"),
4450
],
4551
),
52+
ActionConfigInfo(
53+
actions = [SWIFT_ACTION_COMPILE_MODULE_INTERFACE],
54+
configurators = [
55+
_emit_explicit_module_interface_build_configurator,
56+
],
57+
features = [SWIFT_FEATURE_EXPLICIT_INTERFACE_BUILD],
58+
),
4659
]
4760

4861
def _emit_module_path_from_module_interface_configurator(prerequisites, args):
4962
"""Adds the `.swiftmodule` output path to the command line."""
5063
args.add("-o", prerequisites.swiftmodule_file)
64+
65+
def _emit_explicit_module_interface_build_configurator(prerequisites, args):
66+
"""Adds flags to perform an explicit interface build to the command line."""
67+
68+
args.add("-explicit-interface-module-build")
69+
args.add(
70+
prerequisites.source_files[0],
71+
format = "-Xwrapped-swift=-explicit-compile-module-from-interface=%s",
72+
)

tools/common/BUILD

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ cc_library(
6868
],
6969
)
7070

71+
cc_library(
72+
name = "target_triple",
73+
hdrs = ["target_triple.h"],
74+
deps = ["@com_google_absl//absl/strings"],
75+
)
76+
7177
cc_library(
7278
name = "temp_file",
7379
hdrs = ["temp_file.h"],

tools/common/file_system.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,4 +156,10 @@ absl::Status MakeDirs(absl::string_view path, int mode) {
156156
return MakeFailingStatus("unexpected error");
157157
}
158158

159+
bool PathExists(absl::string_view path) {
160+
struct stat stats;
161+
std::string null_terminated_path{path};
162+
return stat(null_terminated_path.c_str(), &stats) == 0;
163+
}
164+
159165
} // namespace bazel_rules_swift

tools/common/file_system.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ absl::Status CopyFile(absl::string_view src, absl::string_view dest);
3232
// don't already exist. Returns true if successful.
3333
absl::Status MakeDirs(absl::string_view path, int mode);
3434

35+
// Returns true if the given path exists.
36+
bool PathExists(absl::string_view path);
37+
3538
} // namespace bazel_rules_swift
3639

3740
#endif // BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_FILE_SYSTEM_H_

tools/common/target_triple.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright 2025 The Bazel Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_TARGET_TRIPLE_H
16+
#define BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_TARGET_TRIPLE_H
17+
18+
#include <optional>
19+
#include <string>
20+
#include <utility>
21+
#include <vector>
22+
23+
#include "absl/strings/str_cat.h"
24+
#include "absl/strings/str_join.h"
25+
#include "absl/strings/str_split.h"
26+
#include "absl/strings/string_view.h"
27+
28+
namespace bazel_rules_swift {
29+
30+
// Represents a target triple as used by LLVM/Swift and provides operations to
31+
// query and modify it.
32+
class TargetTriple {
33+
public:
34+
// Creates a new target triple from the given components.
35+
TargetTriple(absl::string_view arch, absl::string_view vendor,
36+
absl::string_view os, absl::string_view environment)
37+
: arch_(arch),
38+
vendor_(vendor),
39+
os_(os),
40+
environment_(environment) {}
41+
42+
// Parses the given target triple string into its component parts.
43+
static std::optional<TargetTriple> Parse(absl::string_view target_triple) {
44+
std::vector<absl::string_view> components =
45+
absl::StrSplit(target_triple, '-');
46+
if (components.size() < 3) {
47+
return std::nullopt;
48+
}
49+
return TargetTriple(components[0], components[1], components[2],
50+
components.size() > 3 ? components[3] : "");
51+
}
52+
53+
// Returns the architecture component of the target triple.
54+
std::string Arch() const { return arch_; }
55+
56+
// Returns the vendor component of the target triple.
57+
std::string Vendor() const { return vendor_; }
58+
59+
// Returns the OS component of the target triple.
60+
std::string OS() const { return os_; }
61+
62+
// Returns the environment component of the target triple.
63+
std::string Environment() const { return environment_; }
64+
65+
// Returns this target triple as a string.
66+
std::string TripleString() const {
67+
std::string result = absl::StrJoin({arch_, vendor_, os_}, "-");
68+
if (!environment_.empty()) {
69+
absl::StrAppend(&result, "-", environment_);
70+
}
71+
return result;
72+
}
73+
74+
// Returns a copy of this target triple with the version number removed from
75+
// the OS component (if any).
76+
TargetTriple WithoutOSVersion() const {
77+
std::pair<absl::string_view, absl::string_view> os_and_version =
78+
absl::StrSplit(os_, absl::MaxSplits(absl::ByAnyChar("0123456789"), 1));
79+
return TargetTriple(arch_, vendor_, os_and_version.first, environment_);
80+
}
81+
82+
// Returns a copy of this target triple, replacing its architecture with the
83+
// given value.
84+
TargetTriple WithArch(absl::string_view arch) const {
85+
return TargetTriple(arch, vendor_, os_, environment_);
86+
}
87+
88+
private:
89+
std::string arch_;
90+
std::string vendor_;
91+
std::string os_;
92+
std::string environment_;
93+
};
94+
95+
} // namespace bazel_rules_swift
96+
97+
#endif // BUILD_BAZEL_RULES_SWIFT_TOOLS_COMMON_TARGET_TRIPLE_H

tools/worker/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ cc_library(
1010
"//tools/common:file_system",
1111
"//tools/common:path_utils",
1212
"//tools/common:process",
13+
"//tools/common:target_triple",
1314
"//tools/common:temp_file",
15+
"@com_google_absl//absl/base:nullability",
1416
"@com_google_absl//absl/container:btree",
1517
"@com_google_absl//absl/container:flat_hash_map",
1618
"@com_google_absl//absl/container:flat_hash_set",

0 commit comments

Comments
 (0)