forked from spotify/sourcekit-bazel-bsp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup_sourcekit_bsp.bzl
More file actions
209 lines (201 loc) · 10.3 KB
/
setup_sourcekit_bsp.bzl
File metadata and controls
209 lines (201 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
def _setup_sourcekit_bsp_impl(ctx):
# Config of the BSP itself, a.k.a .bsp/skbsp.json
rendered_bsp_config = ctx.actions.declare_file("skbsp.json")
# Configs for sourcekit-lsp, a.k.a .sourcekit-lsp/config.json
rendered_lsp_config = ctx.actions.declare_file("config.json")
# BSP setup bits
bsp_config_argv = [
".bsp/sourcekit-bazel-bsp",
"serve",
]
for target in ctx.attr.targets:
bsp_config_argv.append("--target")
bsp_config_argv.append(target)
bsp_config_argv.append("--bazel-wrapper")
bsp_config_argv.append(ctx.attr.bazel_wrapper)
if ctx.attr.compile_top_level:
bsp_config_argv.append("--compile-top-level")
for index_flag in ctx.attr.index_flags:
bsp_config_argv.append("--index-flag")
bsp_config_argv.append(index_flag)
for aquery_flag in ctx.attr.aquery_flags:
bsp_config_argv.append("--aquery-flag")
bsp_config_argv.append(aquery_flag)
for query_flag in ctx.attr.query_flags:
bsp_config_argv.append("--query-flag")
bsp_config_argv.append(query_flag)
for top_level_rule in ctx.attr.top_level_rules_to_discover:
bsp_config_argv.append("--top-level-rule-to-discover")
bsp_config_argv.append(top_level_rule)
for dependency_rule in ctx.attr.dependency_rules_to_discover:
bsp_config_argv.append("--dependency-rule-to-discover")
bsp_config_argv.append(dependency_rule)
for target in ctx.attr.top_level_targets_to_exclude:
bsp_config_argv.append("--top-level-target-to-exclude")
bsp_config_argv.append(target)
for target in ctx.attr.dependency_targets_to_exclude:
bsp_config_argv.append("--dependency-target-to-exclude")
bsp_config_argv.append(target)
files_to_watch = ",".join(ctx.attr.files_to_watch)
if files_to_watch:
bsp_config_argv.append("--files-to-watch")
bsp_config_argv.append(files_to_watch)
if ctx.attr.apple_support_repo_name:
bsp_config_argv.append("--apple-support-repo-name")
bsp_config_argv.append(ctx.attr.apple_support_repo_name)
if ctx.attr.experimental_no_extra_output_base:
bsp_config_argv.append("--experimental-no-extra-output-base")
if ctx.attr.experimental_shared_index_store:
bsp_config_argv.append("--experimental-shared-index-store")
ctx.actions.expand_template(
template = ctx.file._bsp_config_template,
output = rendered_bsp_config,
substitutions = {
"%argv%": ",\n ".join(["\"%s\"" % arg for arg in bsp_config_argv]),
},
)
# sourcekit-lsp setup bits
lsp_config_json = {
"backgroundIndexing": True,
"backgroundPreparationMode": "build",
"defaultWorkspaceType": "buildServer",
}
if ctx.attr.index_build_batch_size:
lsp_config_json["preparationBatchingStrategy"] = {
"strategy": "fixedTargetBatchSize",
"batchSize": ctx.attr.index_build_batch_size,
}
if ctx.attr.lsp_timeout:
lsp_config_json["buildServerWorkspaceRequestsTimeout"] = ctx.attr.lsp_timeout
lsp_config_json["buildSettingsTimeout"] = ctx.attr.lsp_timeout
prefixMap = {
"./OUTPUT_PATH_NAME_PLACEHOLDER": "OUTPUT_PATH_PLACEHOLDER",
# Using use_global_index_store causes the index files to be relative to the global index store. We need to re-map those to the execution root as well.
"../OUTPUT_PATH_NAME_PLACEHOLDER": "OUTPUT_PATH_PLACEHOLDER",
"./external": "EXTERNAL_ROOT_PLACEHOLDER",
".": "EXECUTION_ROOT_PLACEHOLDER",
}
lsp_config_json["index"] = {"indexPrefixMap": prefixMap}
ctx.actions.write(rendered_lsp_config, json.encode_indent(lsp_config_json, indent = " "))
merge_lsp_config_env = "1" if ctx.attr.merge_lsp_config else ""
no_extra_output_base_env = "1" if ctx.attr.experimental_no_extra_output_base else ""
# Generating the script that ties everything together
executable = ctx.actions.declare_file("setup_sourcekit_bsp.sh")
ctx.actions.expand_template(
template = ctx.file._setup_sourcekit_bsp_script,
is_executable = True,
output = executable,
substitutions = {
"%bsp_config_path%": rendered_bsp_config.short_path,
"%lsp_config_path%": rendered_lsp_config.short_path,
"%sourcekit_bazel_bsp_path%": ctx.executable.sourcekit_bazel_bsp.short_path,
"%merge_lsp_config_env%": merge_lsp_config_env,
"%bazel_wrapper%": ctx.attr.bazel_wrapper,
"%no_extra_output_base_env%": no_extra_output_base_env
},
)
tools_runfiles = ctx.runfiles(
files = [
ctx.executable.sourcekit_bazel_bsp,
rendered_bsp_config,
rendered_lsp_config,
],
)
return DefaultInfo(
executable = executable,
files = depset(direct = [executable]),
runfiles = tools_runfiles,
)
setup_sourcekit_bsp = rule(
implementation = _setup_sourcekit_bsp_impl,
executable = True,
doc = "Configures sourcekit-bazel-bsp in the current workspace using the provided configuration.",
attrs = {
"_bsp_config_template": attr.label(
doc = "The template for the sourcekit-bazel-bsp configuration.",
default = "//rules:bsp_config.json.tpl",
allow_single_file = True,
),
"_setup_sourcekit_bsp_script": attr.label(
doc = "The script for setting up the sourcekit-bazel-bsp.",
default = "//rules:setup_sourcekit_bsp.sh.tpl",
allow_single_file = True,
),
"sourcekit_bazel_bsp": attr.label(
doc = "The path to the sourcekit-bazel-bsp binary. Will compile from source if not provided.",
default = "//Sources:sourcekit-bazel-bsp",
allow_single_file = True,
cfg = "exec",
executable = True,
),
# We avoid using label_list here to not trigger unnecessary bazel dependency graph checks.
"targets": attr.string_list(
doc = "The *top level* Bazel applications or test targets that this should serve a BSP for. Wildcards are supported (e.g. //foo/...). It's best to keep this list small if possible for performance reasons. If not specified, the server will try to discover top-level targets automatically",
mandatory = True,
),
"bazel_wrapper": attr.string(
doc = "The name of the Bazel CLI to invoke (e.g. 'bazelisk').",
default = "bazel",
),
"index_flags": attr.string_list(
doc = "Flags that should be passed to all indexing-related Bazel invocations. Do not include the -- prefix.",
default = [],
),
"aquery_flags": attr.string_list(
doc = "Flags that should be passed to the aquery invocations used to gather compiler arguments. Do not include the -- prefix.",
default = [],
),
"query_flags": attr.string_list(
doc = "Flags that should be passed to the query invocations used to validate file paths. Do not include the -- prefix.",
default = [],
),
"files_to_watch": attr.string_list(
doc = "A list of file globs to watch for changes.",
default = [],
),
"top_level_rules_to_discover": attr.string_list(
doc = "A list of top-level rule types to discover targets for (e.g. 'ios_application', 'ios_unit_test'). If not specified, all supported top-level rule types will be used for target discovery.",
default = [],
),
"dependency_rules_to_discover": attr.string_list(
doc = "A list of dependency rule types to discover targets for (e.g. 'swift_library', 'objc_library', 'cc_library'). If not specified, all supported dependency rule types will be used for target discovery.",
default = [],
),
"top_level_targets_to_exclude": attr.string_list(
doc = "A list of target patterns to exclude from top-level targets in the cquery. Wildcards are supported (e.g. //foo/...).",
default = [],
),
"dependency_targets_to_exclude": attr.string_list(
doc = "A list of target patterns to exclude from dependency targets in the cquery. Wildcards are supported (e.g. //foo/...).",
default = [],
),
"index_build_batch_size": attr.int(
doc = "The number of targets to prepare in parallel. If not provided, will default to 1.",
mandatory = False,
),
"compile_top_level": attr.bool(
doc = "When enabled, builds entire top-level targets instead of using the aspect-based approach for individual libraries. This is slower but may be needed for certain build configurations. If your project contains build_test targets for your individual libraries and you're passing them as the top-level targets for the BSP, you can use this flag to build those targets directly for better predictability and caching.",
default = False,
),
"lsp_timeout": attr.int(
doc = "A custom timeout value to provide to sourcekit-lsp when waiting for responses from the BSP.",
mandatory = False,
),
"apple_support_repo_name": attr.string(
doc = "The name of the apple_support external repository in your workspace. Change this if using a different name.",
default = "apple_support",
),
"merge_lsp_config": attr.bool(
doc = "If set to true, the generated .sourcekit-lsp/config.json will merge with any existing contents instead of fully overriding the file.",
default = True,
),
"experimental_no_extra_output_base": attr.bool(
doc = "(EXPERIMENTAL) If enabled, the BSP will not create a separate output base for its indexing actions. Can greatly reduce disk usage and improve cache hits at the cost of more pressure on the single Bazel server.",
default = False,
),
"experimental_shared_index_store": attr.bool(
doc = "(EXPERIMENTAL) If enabled, the BSP will create a symlink so that the BSP's output base shares the index store with the main output base. This allows both regular builds and BSP builds to share the same index data. Has no effect if experimental_no_extra_output_base is enabled.",
default = False,
),
},
)