Skip to content

Commit 8a2fd16

Browse files
committed
Merge pull request #2880 from ddunbar/build-script-compute-targets
[build-script] Compute targets in `build-script`
2 parents 5862883 + d515078 commit 8a2fd16

File tree

4 files changed

+449
-77
lines changed

4 files changed

+449
-77
lines changed

utils/SwiftBuildSupport.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -151,22 +151,22 @@ def get_preset_options(substitutions, preset_file_names, preset_name):
151151
from swift_build_support.targets import StdlibDeploymentTarget
152152
for sdk in sdks_to_configure:
153153
if sdk == "OSX":
154-
tgts += StdlibDeploymentTarget.OSX.allArchs
154+
tgts += StdlibDeploymentTarget.OSX.targets
155155
elif sdk == "IOS":
156-
tgts += StdlibDeploymentTarget.iOS.allArchs
156+
tgts += StdlibDeploymentTarget.iOS.targets
157157
elif sdk == "IOS_SIMULATOR":
158-
tgts += StdlibDeploymentTarget.iOSSimulator.allArchs
158+
tgts += StdlibDeploymentTarget.iOSSimulator.targets
159159
elif sdk == "TVOS":
160-
tgts += StdlibDeploymentTarget.AppleTV.allArchs
160+
tgts += StdlibDeploymentTarget.AppleTV.targets
161161
elif sdk == "TVOS_SIMULATOR":
162-
tgts += StdlibDeploymentTarget.AppleTVSimulator.allArchs
162+
tgts += StdlibDeploymentTarget.AppleTVSimulator.targets
163163
elif sdk == "WATCHOS":
164-
tgts += StdlibDeploymentTarget.AppleWatch.allArchs
164+
tgts += StdlibDeploymentTarget.AppleWatch.targets
165165
elif sdk == "WATCHOS_SIMULATOR":
166-
tgts += StdlibDeploymentTarget.AppleWatchSimulator.allArchs
166+
tgts += StdlibDeploymentTarget.AppleWatchSimulator.targets
167167

168168
build_script_opts.append("--stdlib-deployment-targets=" +
169-
" ".join(tgts))
169+
" ".join([tgt.name for tgt in tgts]))
170170
# Filter the swift-sdks parameter
171171
build_script_impl_opts = [opt for opt in build_script_impl_opts
172172
if not opt.startswith("--swift-sdks")]

utils/build-script

Lines changed: 267 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ from swift_build_support.cmake import CMake # noqa (E402)
5050
import swift_build_support.workspace # noqa (E402)
5151

5252

53-
def call_without_sleeping(command, dry_run=False):
53+
def call_without_sleeping(command, env=None, dry_run=False):
5454
"""
5555
Execute a command during which system sleep is disabled.
5656
@@ -62,7 +62,119 @@ def call_without_sleeping(command, dry_run=False):
6262
# Don't mutate the caller's copy of the arguments.
6363
command = ["caffeinate"] + list(command)
6464

65-
shell.call(command, dry_run=dry_run, echo=False)
65+
shell.call(command, env=env, dry_run=dry_run)
66+
67+
68+
class HostSpecificConfiguration(object):
69+
"""Configuration information for an individual host."""
70+
71+
def __init__(self, host_target, invocation):
72+
"""Initialize for the given `host_target`."""
73+
74+
# Compute the set of deployment targets to configure/build.
75+
args = invocation.args
76+
if host_target == args.host_target:
77+
# This host is the user's desired product, so honor the requested
78+
# set of targets to configure/build.
79+
stdlib_targets_to_configure = args.stdlib_deployment_targets
80+
if "all" in args.build_stdlib_deployment_targets:
81+
stdlib_targets_to_build = set(stdlib_targets_to_configure)
82+
else:
83+
stdlib_targets_to_build = set(
84+
args.build_stdlib_deployment_targets).intersect(
85+
set(args.stdlib_deployment_targets))
86+
else:
87+
# Otherwise, this is a host we are building as part of
88+
# cross-compiling, so we only need the target itself.
89+
stdlib_targets_to_configure = [host_target]
90+
stdlib_targets_to_build = set(stdlib_targets_to_configure)
91+
92+
# Compute the lists of **CMake** targets for each use case (configure
93+
# vs. build vs. run) and the SDKs to configure with.
94+
self.sdks_to_configure = set()
95+
self.swift_stdlib_build_targets = []
96+
self.swift_test_run_targets = []
97+
self.swift_benchmark_build_targets = []
98+
self.swift_benchmark_run_targets = []
99+
for deployment_target_name in stdlib_targets_to_configure:
100+
# Get the target object.
101+
deployment_target = StdlibDeploymentTarget.get_target_for_name(
102+
deployment_target_name)
103+
if deployment_target is None:
104+
diagnostics.fatal("unknown target: %r" % (
105+
deployment_target_name,))
106+
107+
# Add the SDK to use.
108+
deployment_platform = deployment_target.platform
109+
self.sdks_to_configure.add(deployment_platform.sdk_name)
110+
111+
# If we aren't actually building this target (only configuring
112+
# it), do nothing else.
113+
if deployment_target_name not in stdlib_targets_to_build:
114+
continue
115+
116+
# Compute which actions are desired.
117+
build = (
118+
deployment_platform not in invocation.platforms_to_skip_build)
119+
test = (
120+
deployment_platform not in invocation.platforms_to_skip_test)
121+
test_host_only = None
122+
build_benchmark = build and deployment_target.supports_benchmark
123+
# FIXME: Note, `build-script-impl` computed a property here
124+
# w.r.t. testing, but it was actually unused.
125+
126+
# For platforms which normally require a connected device to
127+
# test, the default behavior is to run tests that only require
128+
# the host (i.e., they do not attempt to execute).
129+
if deployment_platform.is_darwin and \
130+
deployment_platform.is_embedded and \
131+
not deployment_platform.is_simulator:
132+
if deployment_platform not in \
133+
invocation.platforms_to_skip_test_host:
134+
test_host_only = True
135+
test = True
136+
else:
137+
test = False
138+
139+
name = deployment_target.name
140+
if build:
141+
# Validation and long tests require building the full standard
142+
# library, whereas the other targets can build a slightly
143+
# smaller subset which is faster to build.
144+
if args.build_swift_stdlib_unittest_extra or \
145+
args.validation_test or args.long_test:
146+
self.swift_stdlib_build_targets.append(
147+
"swift-stdlib-" + name)
148+
else:
149+
self.swift_stdlib_build_targets.append(
150+
"swift-test-stdlib-" + name)
151+
if build_benchmark:
152+
self.swift_benchmark_build_targets.append(
153+
"swift-benchmark-" + name)
154+
# FIXME: This probably should respect `args.benchmark`, but
155+
# a typo in build-script-impl meant we always would do this.
156+
self.swift_benchmark_run_targets.append(
157+
"check-swift-benchmark-" + name)
158+
if test:
159+
if test_host_only:
160+
suffix = "-non-executable"
161+
else:
162+
suffix = ""
163+
subset_suffix = ""
164+
if args.validation_test and args.long_test:
165+
subset_suffix = "-all"
166+
elif args.validation_test:
167+
subset_suffix = "-validation"
168+
elif args.long_test:
169+
subset_suffix = "-only_long"
170+
else:
171+
subset_suffix = ""
172+
self.swift_test_run_targets.append("check-swift{}{}-{}".format(
173+
subset_suffix, suffix, name))
174+
if args.test_optimized and not test_host_only:
175+
self.swift_test_run_targets.append(
176+
"check-swift{}-optimize-{}".format(
177+
subset_suffix, name))
66178

67179

68180
class BuildScriptInvocation(object):
@@ -291,6 +403,79 @@ class BuildScriptInvocation(object):
291403
source_root=SWIFT_SOURCE_ROOT,
292404
build_root=os.path.join(SWIFT_BUILD_ROOT, args.build_subdir))
293405

406+
# Compute derived information from the arguments.
407+
#
408+
# FIXME: We should move the platform-derived arguments to be entirely
409+
# data driven, so that we can eliminate this code duplication and just
410+
# iterate over all supported platforms.
411+
412+
self.platforms_to_skip_build = set()
413+
if args.skip_build_linux:
414+
self.platforms_to_skip_build.add(StdlibDeploymentTarget.Linux)
415+
if args.skip_build_freebsd:
416+
self.platforms_to_skip_build.add(StdlibDeploymentTarget.FreeBSD)
417+
if args.skip_build_cygwin:
418+
self.platforms_to_skip_build.add(StdlibDeploymentTarget.Cygwin)
419+
if args.skip_build_osx:
420+
self.platforms_to_skip_build.add(StdlibDeploymentTarget.OSX)
421+
if args.skip_build_ios_device:
422+
self.platforms_to_skip_build.add(StdlibDeploymentTarget.iOS)
423+
if args.skip_build_ios_simulator:
424+
self.platforms_to_skip_build.add(
425+
StdlibDeploymentTarget.iOSSimulator)
426+
if args.skip_build_tvos_device:
427+
self.platforms_to_skip_build.add(StdlibDeploymentTarget.AppleTV)
428+
if args.skip_build_tvos_simulator:
429+
self.platforms_to_skip_build.add(
430+
StdlibDeploymentTarget.AppleTVSimulator)
431+
if args.skip_build_watchos_device:
432+
self.platforms_to_skip_build.add(StdlibDeploymentTarget.AppleWatch)
433+
if args.skip_build_watchos_simulator:
434+
self.platforms_to_skip_build.add(
435+
StdlibDeploymentTarget.AppleWatchSimulator)
436+
if args.skip_build_android:
437+
self.platforms_to_skip_build.add(StdlibDeploymentTarget.Android)
438+
439+
self.platforms_to_skip_test = set()
440+
if args.skip_test_linux:
441+
self.platforms_to_skip_test.add(StdlibDeploymentTarget.Linux)
442+
if args.skip_test_freebsd:
443+
self.platforms_to_skip_test.add(StdlibDeploymentTarget.FreeBSD)
444+
if args.skip_test_cygwin:
445+
self.platforms_to_skip_test.add(StdlibDeploymentTarget.Cygwin)
446+
if args.skip_test_osx:
447+
self.platforms_to_skip_test.add(StdlibDeploymentTarget.OSX)
448+
if args.skip_test_ios_host:
449+
self.platforms_to_skip_test.add(StdlibDeploymentTarget.iOS)
450+
if args.skip_test_ios_simulator:
451+
self.platforms_to_skip_test.add(
452+
StdlibDeploymentTarget.iOSSimulator)
453+
if args.skip_test_tvos_host:
454+
self.platforms_to_skip_test.add(StdlibDeploymentTarget.AppleTV)
455+
if args.skip_test_tvos_simulator:
456+
self.platforms_to_skip_test.add(
457+
StdlibDeploymentTarget.AppleTVSimulator)
458+
if args.skip_test_watchos_host:
459+
self.platforms_to_skip_test.add(StdlibDeploymentTarget.AppleWatch)
460+
if args.skip_test_watchos_simulator:
461+
self.platforms_to_skip_test.add(
462+
StdlibDeploymentTarget.AppleWatchSimulator)
463+
# We never allow testing Android, currently.
464+
#
465+
# FIXME: Allow Android host tests to be enabled/disabled by the build
466+
# script.
467+
self.platforms_to_skip_test.add(StdlibDeploymentTarget.Android)
468+
469+
self.platforms_to_skip_test_host = set()
470+
if args.skip_test_ios_host:
471+
self.platforms_to_skip_test_host.add(StdlibDeploymentTarget.iOS)
472+
if args.skip_test_tvos_host:
473+
self.platforms_to_skip_test_host.add(
474+
StdlibDeploymentTarget.AppleTV)
475+
if args.skip_test_watchos_host:
476+
self.platforms_to_skip_test_host.add(
477+
StdlibDeploymentTarget.AppleWatch)
478+
294479
def initialize_runtime_environment(self):
295480
"""Change the program environment for building."""
296481

@@ -322,10 +507,10 @@ class BuildScriptInvocation(object):
322507
self.toolchain.ninja = ninja_build.ninja_bin_path
323508

324509
def convert_to_impl_arguments(self):
325-
"""convert_to_impl_arguments() -> args
510+
"""convert_to_impl_arguments() -> (env, args)
326511
327-
Convert the invocation to a list of arguments suitable for invoking
328-
`build-script-impl`.
512+
Convert the invocation to an environment and list of arguments suitable
513+
for invoking `build-script-impl`.
329514
"""
330515

331516
# Create local shadows, for convenience.
@@ -374,6 +559,14 @@ class BuildScriptInvocation(object):
374559
pipes.quote(arg) for arg in cmake.build_args()),
375560
]
376561

562+
if args.build_stdlib_deployment_targets:
563+
impl_args += [
564+
"--build-stdlib-deployment-targets", " ".join(
565+
args.build_stdlib_deployment_targets)]
566+
if args.cross_compile_hosts:
567+
impl_args += [
568+
"--cross-compile-hosts", " ".join(args.cross_compile_hosts)]
569+
377570
if toolchain.ninja:
378571
impl_args += ["--ninja-bin=%s" % toolchain.ninja]
379572
if args.distcc:
@@ -415,6 +608,8 @@ class BuildScriptInvocation(object):
415608
impl_args += ["--skip-build-libdispatch"]
416609
if not args.build_swiftpm:
417610
impl_args += ["--skip-build-swiftpm"]
611+
if args.build_swift_stdlib_unittest_extra:
612+
impl_args += ["--build-swift-stdlib-unittest-extra"]
418613

419614
if args.skip_build_linux:
420615
impl_args += ["--skip-build-linux"]
@@ -536,7 +731,48 @@ class BuildScriptInvocation(object):
536731
if args.dry_run:
537732
impl_args += ["--dry-run"]
538733

539-
return impl_args
734+
# Compute the set of host-specific variables, which we pass through to
735+
# the build script via environment variables.
736+
host_specific_variables = self.compute_host_specific_variables()
737+
impl_env = {}
738+
for (host_target, options) in host_specific_variables.items():
739+
for (name, value) in options.items():
740+
# We mangle into an environment variable we can easily evaluate
741+
# from the `build-script-impl`.
742+
impl_env["HOST_VARIABLE_{}__{}".format(
743+
host_target.replace("-", "_"), name)] = value
744+
745+
return (impl_env, impl_args)
746+
747+
def compute_host_specific_variables(self):
748+
"""compute_host_specific_variables(args) -> dict
749+
750+
Compute the host-specific options, organized as a dictionary keyed by
751+
host of options.
752+
"""
753+
754+
args = self.args
755+
756+
options = {}
757+
for host_target in [args.host_target] + args.cross_compile_hosts:
758+
# Compute the host specific configuration.
759+
config = HostSpecificConfiguration(host_target, self)
760+
761+
# Convert into `build-script-impl` style variables.
762+
options[host_target] = {
763+
"SWIFT_SDKS": " ".join(sorted(
764+
config.sdks_to_configure)),
765+
"SWIFT_STDLIB_TARGETS": " ".join(
766+
config.swift_stdlib_build_targets),
767+
"SWIFT_BENCHMARK_TARGETS": " ".join(
768+
config.swift_benchmark_build_targets),
769+
"SWIFT_RUN_BENCHMARK_TARGETS": " ".join(
770+
config.swift_benchmark_run_targets),
771+
"SWIFT_TEST_TARGETS": " ".join(
772+
config.swift_test_run_targets),
773+
}
774+
775+
return options
540776

541777

542778
# Main entry point for the preset mode.
@@ -814,13 +1050,27 @@ details of the setups of other systems or automated environments.""")
8141050
help="The host target. LLVM, Clang, and Swift will be built for this "
8151051
"target. The built LLVM and Clang will be used to compile Swift "
8161052
"for the cross-compilation targets.",
817-
default=StdlibDeploymentTarget.host_target())
1053+
default=StdlibDeploymentTarget.host_target().name)
1054+
targets_group.add_argument(
1055+
"--cross-compile-hosts",
1056+
help="A space separated list of targets to cross-compile host Swift "
1057+
"tools for. Can be used multiple times.",
1058+
action=arguments.action.concat, type=arguments.type.shell_split,
1059+
default=[])
1060+
stdlib_targets = StdlibDeploymentTarget.default_stdlib_deployment_targets()
8181061
targets_group.add_argument(
8191062
"--stdlib-deployment-targets",
8201063
help="list of targets to compile or cross-compile the Swift standard "
8211064
"library for. %(default)s by default.",
8221065
nargs="*",
823-
default=StdlibDeploymentTarget.default_stdlib_deployment_targets())
1066+
default=[
1067+
target.name
1068+
for target in stdlib_targets])
1069+
targets_group.add_argument(
1070+
"--build-stdlib-deployment-targets",
1071+
help="A space-separated list that filters which of the configured "
1072+
"targets to build the Swift standard library for, or 'all'.",
1073+
type=arguments.type.shell_split, default=["all"])
8241074

8251075
projects_group = parser.add_argument_group(
8261076
title="Options to select projects")
@@ -1120,6 +1370,10 @@ details of the setups of other systems or automated environments.""")
11201370
help="Use the host compiler, not the self-built one to compile the "
11211371
"Swift runtime",
11221372
action="store_true")
1373+
parser.add_argument(
1374+
"--build-swift-stdlib-unittest-extra",
1375+
help="Build optional StdlibUnittest components",
1376+
action="store_true")
11231377

11241378
run_build_group = parser.add_argument_group(
11251379
title="Run build")
@@ -1480,6 +1734,7 @@ details of the setups of other systems or automated environments.""")
14801734
"--build-jobs",
14811735
"--common-cmake-options",
14821736
"--only-execute",
1737+
"--skip-test-optimized",
14831738
action=arguments.action.unavailable)
14841739

14851740
args = migration.parse_args(parser, sys.argv[1:])
@@ -1541,10 +1796,12 @@ details of the setups of other systems or automated environments.""")
15411796
invocation.build_ninja()
15421797

15431798
# Convert to a build-script-impl invocation.
1544-
build_script_impl_args = invocation.convert_to_impl_arguments()
1799+
(build_script_impl_env, build_script_impl_args) = \
1800+
invocation.convert_to_impl_arguments()
15451801

15461802
# Execute the underlying build script implementation.
1547-
call_without_sleeping([build_script_impl] + build_script_impl_args)
1803+
call_without_sleeping([build_script_impl] + build_script_impl_args,
1804+
env=build_script_impl_env)
15481805

15491806
if args.symbols_package:
15501807
print('--- Creating symbols package ---')

0 commit comments

Comments
 (0)