Skip to content

Commit a86aeb0

Browse files
committed
Add special -parse-as-library handling for swift_binary
This matches the behavior implemented in swiftlang/swift-package-manager#3410 for single file modules.
1 parent b250c3f commit a86aeb0

File tree

8 files changed

+96
-1
lines changed

8 files changed

+96
-1
lines changed

swift/internal/swift_binary_test.bzl

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,25 @@ def _configure_features_for_binary(
140140
unsupported_features = unsupported_features,
141141
)
142142

143+
def _maybe_parse_as_library_copts(srcs):
144+
"""Returns a list of compiler flags depending on `main.swift`'s presence.
145+
146+
Now that the `@main` attribute exists and is becoming more common, in the
147+
case there is a single file not named `main.swift`, we assume that it has a
148+
`@main` annotation, in which case it needs to be parsed as a library, not
149+
as if it has top level code. In the case this is the wrong assumption,
150+
compilation or linking will fail.
151+
152+
Args:
153+
srcs: A list of source files to check for the presence of `main.swift`.
154+
155+
Returns:
156+
A list of compiler flags to add to `copts`
157+
"""
158+
use_parse_as_library = len(srcs) == 1 and \
159+
srcs[0].basename != "main.swift"
160+
return ["-parse-as-library"] if use_parse_as_library else []
161+
143162
def _swift_linking_rule_impl(
144163
ctx,
145164
binary_path,
@@ -184,7 +203,8 @@ def _swift_linking_rule_impl(
184203
if not module_name:
185204
module_name = swift_common.derive_module_name(ctx.label)
186205

187-
copts = expand_locations(ctx, ctx.attr.copts, ctx.attr.swiftc_inputs)
206+
copts = expand_locations(ctx, ctx.attr.copts, ctx.attr.swiftc_inputs) + \
207+
_maybe_parse_as_library_copts(srcs)
188208

189209
module_context, cc_compilation_outputs, other_compilation_outputs = swift_common.compile(
190210
actions = ctx.actions,

test/BUILD

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ load(":debug_settings_tests.bzl", "debug_settings_test_suite")
55
load(":features_tests.bzl", "features_test_suite")
66
load(":generated_header_tests.bzl", "generated_header_test_suite")
77
load(":linking_tests.bzl", "linking_test_suite")
8+
load(":mainattr_tests.bzl", "mainattr_test_suite")
89
load(":module_cache_settings_tests.bzl", "module_cache_settings_test_suite")
910
load(":output_file_map_tests.bzl", "output_file_map_test_suite")
1011
load(":private_deps_tests.bzl", "private_deps_test_suite")
@@ -28,6 +29,8 @@ generated_header_test_suite(name = "generated_header")
2829

2930
linking_test_suite(name = "linking")
3031

32+
mainattr_test_suite(name = "mainattr")
33+
3134
module_cache_settings_test_suite(name = "module_cache_settings")
3235

3336
output_file_map_test_suite(name = "output_file_map")

test/fixtures/mainattr/BUILD

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
load("//swift:swift.bzl", "swift_binary")
2+
3+
package(
4+
default_visibility = ["//test:__subpackages__"],
5+
)
6+
7+
swift_binary(
8+
name = "main",
9+
srcs = ["main.swift"],
10+
)
11+
12+
swift_binary(
13+
name = "custommain",
14+
srcs = ["custommain.swift"],
15+
)
16+
17+
swift_binary(
18+
name = "multiplefiles",
19+
srcs = [
20+
"file1.swift",
21+
"file2.swift",
22+
],
23+
)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@main
2+
struct Foo {
3+
static func main() {
4+
print("Hello, world!")
5+
}
6+
}

test/fixtures/mainattr/file1.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
print(foo())

test/fixtures/mainattr/file2.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
func foo() -> String {
2+
return "foo"
3+
}

test/fixtures/mainattr/main.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
print("hi")

test/mainattr_tests.bzl

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""Tests for validating @main related usage"""
2+
3+
load(
4+
"@build_bazel_rules_swift//test/rules:action_command_line_test.bzl",
5+
"make_action_command_line_test_rule",
6+
)
7+
8+
mainattr_test = make_action_command_line_test_rule()
9+
10+
def mainattr_test_suite(name):
11+
mainattr_test(
12+
name = "{}_single_main".format(name),
13+
not_expected_argv = ["-parse-as-library"],
14+
mnemonic = "SwiftCompile",
15+
tags = [name],
16+
target_under_test = "@build_bazel_rules_swift//test/fixtures/mainattr:main",
17+
)
18+
19+
mainattr_test(
20+
name = "{}_single_custom_main".format(name),
21+
expected_argv = ["-parse-as-library"],
22+
mnemonic = "SwiftCompile",
23+
tags = [name],
24+
target_under_test = "@build_bazel_rules_swift//test/fixtures/mainattr:custommain",
25+
)
26+
27+
mainattr_test(
28+
name = "{}_multiple_files".format(name),
29+
not_expected_argv = ["-parse-as-library"],
30+
mnemonic = "SwiftCompile",
31+
tags = [name],
32+
target_under_test = "@build_bazel_rules_swift//test/fixtures/mainattr:multiplefiles",
33+
)
34+
35+
native.test_suite(
36+
name = name,
37+
tags = [name],
38+
)

0 commit comments

Comments
 (0)