This repository has been archived by the owner on Jan 25, 2024. It is now read-only.
forked from bazelbuild/rules_swift
/
attrs.bzl
377 lines (329 loc) · 15.4 KB
/
attrs.bzl
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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
# Copyright 2018 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Common attributes used by multiple Swift build rules."""
load("@bazel_skylib//lib:dicts.bzl", "dicts")
load(":providers.bzl", "SwiftInfo", "SwiftToolchainInfo")
def swift_common_rule_attrs(additional_deps_aspects = []):
return {
"data": attr.label_list(
allow_files = True,
doc = """\
The list of files needed by this target at runtime.
Files and targets named in the `data` attribute will appear in the `*.runfiles`
area of this target, if it has one. This may include data files needed by a
binary or library, or other programs needed by it.
""",
),
"deps": swift_deps_attr(
aspects = additional_deps_aspects,
doc = """\
A list of targets that are dependencies of the target being built, which will be
linked into that target.
If the Swift toolchain supports implementation-only imports (`private_deps` on
`swift_library`), then targets in `deps` are treated as regular
(non-implementation-only) imports that are propagated both to their direct and
indirect (transitive) dependents.
""",
),
# Deprecated, but Starlark rules do not inherit `licenses` by default
# (see b/169635467).
"licenses": attr.license(), # buildifier: disable=attr-license
}
def swift_compilation_attrs(
additional_deps_aspects = [],
requires_srcs = True):
"""Returns an attribute dictionary for rules that compile Swift code.
The returned dictionary contains the subset of attributes that are shared by
the `swift_binary`, `swift_library`, and `swift_test` rules that deal with
inputs and options for compilation. Users who are authoring custom rules
that compile Swift code but not as a library can add this dictionary to
their own rule's attributes to give it a familiar API.
Do note, however, that it is the responsibility of the rule implementation
to retrieve the values of those attributes and pass them correctly to the
other `swift_common` APIs.
There is a hierarchy to the attribute sets offered by the `swift_common`
API:
1. If you only need access to the toolchain for its tools and libraries but
are not doing any compilation, use `toolchain_attrs`.
2. If you need to invoke compilation actions but are not making the
resulting object files into a static or shared library, use
`compilation_attrs`.
3. If you want to provide a rule interface that is suitable as a drop-in
replacement for `swift_library`, use `library_rule_attrs`.
Each of the attribute functions in the list above also contains the
attributes from the earlier items in the list.
Args:
additional_deps_aspects: A list of additional aspects that should be
applied to `deps`. Defaults to the empty list. These must be passed
by the individual rules to avoid potential circular dependencies
between the API and the aspects; the API loaded the aspects
directly, then those aspects would not be able to load the API.
requires_srcs: Indicates whether the `srcs` attribute should be marked
as mandatory and non-empty. Defaults to `True`.
Returns:
A new attribute dictionary that can be added to the attributes of a
custom build rule to provide a similar interface to `swift_binary`,
`swift_library`, and `swift_test`.
"""
return dicts.add(
swift_common_rule_attrs(
additional_deps_aspects = additional_deps_aspects,
),
swift_toolchain_attrs(),
{
"srcs": attr.label_list(
allow_empty = not requires_srcs,
allow_files = ["swift"],
doc = """\
A list of `.swift` source files that will be compiled into the library.
""",
flags = ["DIRECT_COMPILE_TIME_INPUT"],
mandatory = requires_srcs,
),
"copts": attr.string_list(
doc = """\
Additional compiler options that should be passed to `swiftc`. These strings are
subject to `$(location ...)` expansion.
""",
),
"defines": attr.string_list(
doc = """\
A list of defines to add to the compilation command line.
Note that unlike C-family languages, Swift defines do not have values; they are
simply identifiers that are either defined or undefined. So strings in this list
should be simple identifiers, **not** `name=value` pairs.
Each string is prepended with `-D` and added to the command line. Unlike
`copts`, these flags are added for the target and every target that depends on
it, so use this attribute with caution. It is preferred that you add defines
directly to `copts`, only using this feature in the rare case that a library
needs to propagate a symbol up to those that depend on it.
""",
),
"module_name": attr.string(
doc = """\
The name of the Swift module being built.
If left unspecified, the module name will be computed based on the target's
build label, by stripping the leading `//` and replacing `/`, `:`, and other
non-identifier characters with underscores.
""",
),
"swiftc_inputs": attr.label_list(
allow_files = True,
doc = """\
Additional files that are referenced using `$(location ...)` in attributes that
support location expansion.
""",
),
},
)
def swift_config_attrs():
"""Returns the Starlark configuration flags and settings attributes.
Returns:
A dictionary of configuration attributes to be added to rules that read
configuration settings.
"""
return {
"_config_emit_swiftinterface": attr.label(
default = "@build_bazel_rules_swift//swift:emit_swiftinterface",
),
}
def swift_deps_attr(doc, **kwargs):
"""Returns an attribute suitable for representing Swift rule dependencies.
The returned attribute will be configured to accept targets that propagate
`CcInfo`, `SwiftInfo`, or `apple_common.Objc` providers.
Args:
doc: A string containing a summary description of the purpose of the
attribute. This string will be followed by additional text that
lists the permitted kinds of targets that may go in this attribute.
**kwargs: Additional arguments that are passed to `attr.label_list`
unmodified.
Returns:
A rule attribute.
"""
return attr.label_list(
doc = doc + """\
Allowed kinds of dependencies are:
* `swift_c_module`, `swift_import` and `swift_library` (or anything
propagating `SwiftInfo`)
* `cc_library` (or anything propagating `CcInfo`)
Additionally, on platforms that support Objective-C interop, `objc_library`
targets (or anything propagating the `apple_common.Objc` provider) are allowed
as dependencies. On platforms that do not support Objective-C interop (such as
Linux), those dependencies will be **ignored.**
""",
providers = [
[CcInfo],
[SwiftInfo],
[apple_common.Objc],
],
**kwargs
)
def swift_library_rule_attrs(
additional_deps_aspects = [],
requires_srcs = True):
"""Returns an attribute dictionary for `swift_library`-like rules.
The returned dictionary contains the same attributes that are defined by the
`swift_library` rule (including the private `_toolchain` attribute that
specifies the toolchain dependency). Users who are authoring custom rules
can use this dictionary verbatim or add other custom attributes to it in
order to make their rule a drop-in replacement for `swift_library` (for
example, if writing a custom rule that does some preprocessing or generation
of sources and then compiles them).
Do note, however, that it is the responsibility of the rule implementation
to retrieve the values of those attributes and pass them correctly to the
other `swift_common` APIs.
There is a hierarchy to the attribute sets offered by the `swift_common`
API:
1. If you only need access to the toolchain for its tools and libraries but
are not doing any compilation, use `toolchain_attrs`.
2. If you need to invoke compilation actions but are not making the
resulting object files into a static or shared library, use
`compilation_attrs`.
3. If you want to provide a rule interface that is suitable as a drop-in
replacement for `swift_library`, use `library_rule_attrs`.
Each of the attribute functions in the list above also contains the
attributes from the earlier items in the list.
Args:
additional_deps_aspects: A list of additional aspects that should be
applied to `deps`. Defaults to the empty list. These must be passed
by the individual rules to avoid potential circular dependencies
between the API and the aspects; the API loaded the aspects
directly, then those aspects would not be able to load the API.
requires_srcs: Indicates whether the `srcs` attribute should be marked
as mandatory and non-empty. Defaults to `True`.
Returns:
A new attribute dictionary that can be added to the attributes of a
custom build rule to provide the same interface as `swift_library`.
"""
return dicts.add(
swift_compilation_attrs(
additional_deps_aspects = additional_deps_aspects,
requires_srcs = requires_srcs,
),
swift_config_attrs(),
{
"linkopts": attr.string_list(
doc = """\
Additional linker options that should be passed to the linker for the binary
that depends on this target. These strings are subject to `$(location ...)`
expansion.
""",
),
"alwayslink": attr.bool(
default = False,
doc = """\
If true, any binary that depends (directly or indirectly) on this Swift module
will link in all the object files for the files listed in `srcs`, even if some
contain no symbols referenced by the binary. This is useful if your code isn't
explicitly called by code in the binary; for example, if you rely on runtime
checks for protocol conformances added in extensions in the library but do not
directly reference any other symbols in the object file that adds that
conformance.
""",
),
"generated_header_name": attr.string(
doc = """\
The name of the generated Objective-C interface header. This name must end with
a `.h` extension and cannot contain any path separators.
If this attribute is not specified, then the default behavior is to name the
header `${target_name}-Swift.h`.
It is an error to specify a value for this attribute when `generates_header` is
False.
""",
mandatory = False,
),
"generates_header": attr.bool(
default = False,
doc = """\
If True, an Objective-C header will be generated for this target, in the same
build package where the target is defined. By default, the name of the header is
`${target_name}-Swift.h`; this can be changed using the `generated_header_name`
attribute.
Targets should only set this attribute to True if they export Objective-C APIs.
A header generated for a target that does not export Objective-C APIs will be
effectively empty (except for a large amount of prologue and epilogue code) and
this is generally wasteful because the extra file needs to be propagated in the
build graph and, when explicit modules are enabled, extra actions must be
executed to compile the Objective-C module for the generated header.
""",
mandatory = False,
),
},
)
def swift_toolchain_attrs(toolchain_attr_name = "_toolchain"):
"""Returns an attribute dictionary for toolchain users.
The returned dictionary contains a key with the name specified by the
argument `toolchain_attr_name` (which defaults to the value `"_toolchain"`),
the value of which is a BUILD API `attr.label` that references the default
Swift toolchain. Users who are authoring custom rules can add this
dictionary to the attributes of their own rule in order to depend on the
toolchain and access its `SwiftToolchainInfo` provider to pass it to other
`swift_common` functions.
There is a hierarchy to the attribute sets offered by the `swift_common`
API:
1. If you only need access to the toolchain for its tools and libraries but
are not doing any compilation, use `toolchain_attrs`.
2. If you need to invoke compilation actions but are not making the
resulting object files into a static or shared library, use
`compilation_attrs`.
3. If you want to provide a rule interface that is suitable as a drop-in
replacement for `swift_library`, use `library_rule_attrs`.
Each of the attribute functions in the list above also contains the
attributes from the earlier items in the list.
Args:
toolchain_attr_name: The name of the attribute that should be created
that points to the toolchain. This defaults to `_toolchain`, which
is sufficient for most rules; it is customizable for certain aspects
where having an attribute with the same name but different values
applied to a particular target causes a build crash.
Returns:
A new attribute dictionary that can be added to the attributes of a
custom build rule to provide access to the Swift toolchain.
"""
return {
toolchain_attr_name: attr.label(
default = Label("@build_bazel_rules_swift_local_config//:toolchain"),
providers = [[SwiftToolchainInfo]],
),
}
def swift_toolchain_driver_attrs():
"""Returns attributes used to attach custom drivers to toolchains.
These attributes are useful for compiler development alongside Bazel. The
public attribute (`swift_executable`) lets a custom driver be permanently
associated with a particular toolchain instance. If not specified, the
private default is associated with a command-line option that can be used to
provide a custom driver at build time.
Returns:
A dictionary of attributes that should be added to a toolchain rule.
"""
return {
"swift_executable": attr.label(
allow_single_file = True,
cfg = "exec",
doc = """\
A replacement Swift driver executable.
If this is empty, the default Swift driver in the toolchain will be used.
Otherwise, this binary will be used and `--driver-mode` will be passed to ensure
that it is invoked in the correct mode (i.e., `swift`, `swiftc`,
`swift-autolink-extract`, etc.).
""",
),
"_default_swift_executable": attr.label(
allow_files = True,
cfg = "exec",
default = Label(
"@build_bazel_rules_swift//swift:default_swift_executable",
),
),
}