Skip to content

Commit ac269f8

Browse files
committed
Implement additional_linker_inputs attr
1 parent 532d7ea commit ac269f8

File tree

6 files changed

+145
-4
lines changed

6 files changed

+145
-4
lines changed

swift/internal/binary_attrs.bzl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@ def binary_rule_attrs(
5959
requires_srcs = False,
6060
),
6161
{
62+
"additional_linker_inputs": attr.label_list(
63+
allow_files = True,
64+
doc = """\
65+
List of additional files needed by the linker.
66+
67+
These files will be passed to the linker when linking the binary target.
68+
Typically, these are linker scripts or other files referenced by `linkopts`.
69+
""",
70+
mandatory = False,
71+
),
6272
"linkopts": attr.string_list(
6373
doc = """\
6474
Additional linker options that should be passed to `clang`. These strings are

swift/swift_binary.bzl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def _swift_binary_impl(ctx):
157157
binary_link_flags = expand_locations(
158158
ctx,
159159
ctx.attr.linkopts,
160-
ctx.attr.swiftc_inputs,
160+
ctx.attr.swiftc_inputs + ctx.attr.additional_linker_inputs,
161161
) + ctx.fragments.cpp.linkopts
162162

163163
# When linking the binary, make sure we use the correct entry point name.
@@ -178,7 +178,7 @@ def _swift_binary_impl(ctx):
178178

179179
linking_outputs = register_link_binary_action(
180180
actions = ctx.actions,
181-
additional_inputs = ctx.files.swiftc_inputs,
181+
additional_inputs = ctx.files.swiftc_inputs + ctx.files.additional_linker_inputs,
182182
additional_linking_contexts = additional_linking_contexts,
183183
additional_outputs = additional_debug_outputs,
184184
feature_configuration = feature_configuration,
@@ -228,7 +228,7 @@ def _swift_binary_impl(ctx):
228228
environment = expand_locations(
229229
ctx,
230230
ctx.attr.env,
231-
ctx.attr.swiftc_inputs,
231+
ctx.attr.swiftc_inputs + ctx.attr.additional_linker_inputs,
232232
),
233233
),
234234
]
@@ -240,7 +240,7 @@ def _swift_binary_impl(ctx):
240240
linking_context, _ = (
241241
create_linking_context_from_compilation_outputs(
242242
actions = ctx.actions,
243-
additional_inputs = ctx.files.swiftc_inputs,
243+
additional_inputs = ctx.files.swiftc_inputs + ctx.files.additional_linker_inputs,
244244
alwayslink = True,
245245
compilation_outputs = compilation_outputs,
246246
feature_configuration = feature_configuration,

test/BUILD

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
2+
load(":additional_linker_inputs_tests.bzl", "additional_linker_inputs_test_suite")
23
load(":ast_file_tests.bzl", "ast_file_test_suite")
34
load(":bzl_test.bzl", "bzl_test")
45
load(":cc_library_tests.bzl", "cc_library_test_suite")
@@ -30,6 +31,8 @@ load(":xctest_runner_tests.bzl", "xctest_runner_test_suite")
3031

3132
licenses(["notice"])
3233

34+
additional_linker_inputs_test_suite(name = "additional_linker_inputs")
35+
3336
ast_file_test_suite(name = "ast_file")
3437

3538
cc_library_test_suite(name = "cc_library")
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
"""Tests for swift_binary's additional_linker_inputs attribute."""
2+
3+
load("@bazel_skylib//lib:unittest.bzl", "analysistest", "unittest")
4+
5+
def _swift_binary_additional_linker_inputs_test_impl(ctx):
6+
env = analysistest.begin(ctx)
7+
8+
actions = analysistest.target_actions(env)
9+
link_actions = [
10+
action
11+
for action in actions
12+
if action.mnemonic == "CppLink"
13+
]
14+
15+
if not link_actions:
16+
unittest.fail(
17+
env,
18+
"Expected to find a CppLink action but found none. Available actions: {}".format(
19+
[action.mnemonic for action in actions],
20+
),
21+
)
22+
return analysistest.end(env)
23+
24+
if len(link_actions) != 1:
25+
unittest.fail(
26+
env,
27+
"Expected exactly one CppLink action, but found {}".format(len(link_actions)),
28+
)
29+
return analysistest.end(env)
30+
31+
link_action = link_actions[0]
32+
33+
expected_inputs = ctx.attr.expected_additional_inputs
34+
expected_linkopts = ctx.attr.expected_linkopts
35+
36+
action_input_paths = set([input.short_path for input in link_action.inputs.to_list()])
37+
38+
if expected_inputs:
39+
missing_inputs = set(expected_inputs) - action_input_paths
40+
if missing_inputs:
41+
unittest.fail(
42+
env,
43+
"Missing expected additional linker inputs: {}. Available inputs: {}".format(
44+
sorted(missing_inputs),
45+
sorted(action_input_paths),
46+
),
47+
)
48+
49+
if expected_linkopts:
50+
missing_linkopts = []
51+
for expected_linkopt in expected_linkopts:
52+
# Use substring match since -Wl, options may be grouped with other flags
53+
found = False
54+
for arg in link_action.argv:
55+
if expected_linkopt in arg:
56+
found = True
57+
break
58+
if not found:
59+
missing_linkopts.append(expected_linkopt)
60+
61+
if missing_linkopts:
62+
unittest.fail(
63+
env,
64+
"Missing expected linkopts: {}. Link arguments were: {}".format(
65+
missing_linkopts,
66+
link_action.argv,
67+
),
68+
)
69+
70+
return analysistest.end(env)
71+
72+
swift_binary_additional_linker_inputs_test = analysistest.make(
73+
_swift_binary_additional_linker_inputs_test_impl,
74+
attrs = {
75+
"expected_additional_inputs": attr.string_list(
76+
),
77+
"expected_linkopts": attr.string_list(
78+
),
79+
},
80+
)
81+
82+
def additional_linker_inputs_test_suite(name, tags = []):
83+
all_tags = [name] + tags
84+
85+
swift_binary_additional_linker_inputs_test(
86+
name = "{}_with_additional_inputs".format(name),
87+
target_under_test = "//test/fixtures/linking:bin_with_additional_linker_inputs",
88+
expected_additional_inputs = ["test/fixtures/linking/test_data.bin"],
89+
expected_linkopts = ["-Wl,-sectcreate,__TEXT,__test_section"],
90+
tags = all_tags,
91+
)
92+
93+
swift_binary_additional_linker_inputs_test(
94+
name = "{}_without_additional_inputs".format(name),
95+
target_under_test = "//test/fixtures/linking:bin_without_additional_linker_inputs",
96+
expected_additional_inputs = [],
97+
expected_linkopts = [],
98+
tags = all_tags,
99+
)
100+
101+
native.test_suite(
102+
name = name,
103+
tags = all_tags,
104+
)

test/fixtures/linking/BUILD

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,29 @@ cc_binary(
3434
deps = [":lib"],
3535
)
3636

37+
swift_binary(
38+
name = "bin_with_additional_linker_inputs",
39+
srcs = ["main.swift"],
40+
additional_linker_inputs = ["test_data.bin"],
41+
linkopts = [
42+
"-Wl,-sectcreate,__TEXT,__test_section,$(execpath test_data.bin)",
43+
],
44+
tags = FIXTURE_TAGS,
45+
)
46+
47+
swift_binary(
48+
name = "bin_with_empty_additional_linker_inputs",
49+
srcs = ["main.swift"],
50+
additional_linker_inputs = [],
51+
tags = FIXTURE_TAGS,
52+
)
53+
54+
swift_binary(
55+
name = "bin_without_additional_linker_inputs",
56+
srcs = ["main.swift"],
57+
tags = FIXTURE_TAGS,
58+
)
59+
3760
bzl_library(
3861
name = "fake_framework",
3962
srcs = ["fake_framework.bzl"],
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TEST_DATA_FOR_ADDITIONAL_LINKER_INPUTS

0 commit comments

Comments
 (0)