Skip to content

Commit ff3b4b6

Browse files
allevatoswiple-rules-gardener
authored andcommitted
Make the actual output of a swift_test target the .xctest bundle (for Xcode toolchains, when the feature is not disabled).
RELNOTES: None. PiperOrigin-RevId: 274055678
1 parent 50712a5 commit ff3b4b6

File tree

2 files changed

+56
-26
lines changed

2 files changed

+56
-26
lines changed

swift/internal/swift_binary_test.bzl

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -266,30 +266,68 @@ def _swift_linking_rule_impl(
266266

267267
return out_bin, providers
268268

269-
def _create_xctest_runner(name, actions, binary, xctest_runner_template):
270-
"""Creates a script that will bundle a test binary and launch `xctest`.
269+
def _create_xctest_bundle(name, actions, binary):
270+
"""Creates an `.xctest` bundle that contains the given binary.
271271
272272
Args:
273273
name: The name of the target being built, which will be used as the
274-
basename of the bundle (followed by the `.xctest` bundle extension).
274+
basename of the bundle (followed by the .xctest bundle extension).
275275
actions: The context's actions object.
276-
binary: The `File` representing the test binary that should be bundled
277-
and executed.
276+
binary: The binary that will be copied into the test bundle.
277+
278+
Returns:
279+
A `File` (tree artifact) representing the `.xctest` bundle.
280+
"""
281+
xctest_bundle = derived_files.xctest_bundle(
282+
actions = actions,
283+
target_name = name,
284+
)
285+
286+
args = actions.args()
287+
args.add(xctest_bundle.path)
288+
args.add(binary)
289+
290+
actions.run_shell(
291+
arguments = [args],
292+
command = (
293+
'mkdir -p "$1/Contents/MacOS" && ' +
294+
'cp "$2" "$1/Contents/MacOS"'
295+
),
296+
inputs = [binary],
297+
mnemonic = "SwiftCreateTestBundle",
298+
outputs = [xctest_bundle],
299+
progress_message = "Creating test bundle for {}".format(name),
300+
)
301+
302+
return xctest_bundle
303+
304+
def _create_xctest_runner(name, actions, bundle, xctest_runner_template):
305+
"""Creates a script that will launch `xctest` with the given test bundle.
306+
307+
Args:
308+
name: The name of the target being built, which will be used as the
309+
basename of the test runner script.
310+
actions: The context's actions object.
311+
bundle: The `File` representing the `.xctest` bundle that should be
312+
executed.
278313
xctest_runner_template: The `File` that will be used as a template to
279314
generate the test runner shell script.
280315
281316
Returns:
282317
A `File` representing the shell script that will launch the test bundle
283318
with the `xctest` tool.
284319
"""
285-
xctest_runner = derived_files.xctest_runner_script(actions, name)
320+
xctest_runner = derived_files.xctest_runner_script(
321+
actions = actions,
322+
target_name = name,
323+
)
286324

287325
actions.expand_template(
288326
is_executable = True,
289327
output = xctest_runner,
290328
template = xctest_runner_template,
291329
substitutions = {
292-
"%binary%": binary.short_path,
330+
"%bundle%": bundle.short_path,
293331
},
294332
)
295333

@@ -335,9 +373,6 @@ def _swift_test_impl(ctx):
335373

336374
# If we need to run the test in an .xctest bundle, the binary must have
337375
# Mach-O type `MH_BUNDLE` instead of `MH_EXECUTE`.
338-
# TODO(allevato): This should really be done in the toolchain's
339-
# linker_opts_producer partial, but it doesn't take the
340-
# feature_configuration as an argument. We should update it to do so.
341376
linkopts = ["-Wl,-bundle"] if is_bundled else []
342377

343378
binary, providers = _swift_linking_rule_impl(
@@ -348,20 +383,22 @@ def _swift_test_impl(ctx):
348383
swift_toolchain = swift_toolchain,
349384
)
350385

351-
# If the tests are to be bundled, create the test runner script as the
352-
# rule's executable and place the binary in runfiles so that it can be
353-
# copied into place. Otherwise, just use the binary itself as the executable
354-
# to launch.
355-
# TODO(b/65413470): Make the output of the rule _itself_ an `.xctest` bundle
356-
# once some limitations of directory artifacts are resolved.
386+
# If the tests are to be bundled, create the bundle and the test runner
387+
# script that launches it via `xctest`. Otherwise, just use the binary
388+
# itself as the executable to launch.
357389
if is_bundled:
358-
xctest_runner = _create_xctest_runner(
390+
xctest_bundle = _create_xctest_bundle(
359391
name = ctx.label.name,
360392
actions = ctx.actions,
361393
binary = binary,
394+
)
395+
xctest_runner = _create_xctest_runner(
396+
name = ctx.label.name,
397+
actions = ctx.actions,
398+
bundle = xctest_bundle,
362399
xctest_runner_template = ctx.file._xctest_runner_template,
363400
)
364-
additional_test_outputs = [binary]
401+
additional_test_outputs = [xctest_bundle]
365402
executable = xctest_runner
366403
else:
367404
additional_test_outputs = []

tools/xctest_runner/xctest_runner.sh.template

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,8 @@ set -eu
2121
# because the test binary is an `MH_BUNDLE` that needs to be loaded dynamically
2222
# and runtime reflection is used to locate the test methods.
2323

24-
# Create the .xctest bundle and copy the binary into it (a requirement of the
25-
# `xctest` tool).
26-
BINARY="$TEST_SRCDIR/$TEST_WORKSPACE/%binary%"
27-
BUNDLE_DIR="$(dirname "$BINARY")/$(basename "$BINARY").xctest"
28-
mkdir -p "$BUNDLE_DIR/Contents/MacOS"
29-
ln -sf "$BINARY" "$BUNDLE_DIR/Contents/MacOS/"
30-
3124
# TODO(allevato): Support Bazel's --test_filter.
32-
exec xcrun xctest -XCTest All "$BUNDLE_DIR"
25+
exec xcrun xctest -XCTest All "%bundle%"
3326

3427
# We should never make it here unless `exec` failed.
3528
exit 2

0 commit comments

Comments
 (0)