Skip to content

Commit c2dc8e3

Browse files
committed
Always build (and use) the new SwiftDriver as the default compiler driver.
This will make sure that compiler developers are using the new driver when they build the compiler locally and use it. - Adds a new build-script product category: before_build_script_impl for products we wish to build before the impl products. - Adds a new EarlySwiftDriver product to that category, which gets built with the host toolchain. - Adds an escape hatch: --skip-early-swift-driver - Adjusts the swift CMake configuration with an additional step: swift_create_early_driver_symlinks which (if one was built) creates symlinks in the swift build bin directory to the EarlySwiftDriver swift-driver and swift-help executables. - Adds a new test subset : only_early_swiftdriver, which will get built into a corresponding CMake test target: check-swift-only_early_swiftdriver-* which runs a small subset of driver-related tests against the Early SwiftDriver. - This subset is run always when the compiler itself is tested (--test is specified) - With an escape disable-switch: --skip-test-early-swift-driver - All tests outside of only_early_swiftdriver are forced to run using the legacy C++ driver (to ensure it gets tested, still). NOTE: SwiftDriver product (no 'Early') is still the main product used to build the driver for toolchain installation into and for executing the product's own tests. This change does not affect that.
1 parent 3f6eb2f commit c2dc8e3

40 files changed

+447
-41
lines changed

cmake/modules/SwiftUtils.cmake

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,35 @@ function(swift_create_post_build_symlink target)
152152
COMMENT "${CS_COMMENT}")
153153
endfunction()
154154

155+
# Once swift-frontend is built, if the standalone (early) swift-driver has been built,
156+
# we create a `swift-driver` symlink adjacent to the `swift` and `swiftc` executables
157+
# to ensure that `swiftc` forwards to the standalone driver when invoked.
158+
function(swift_create_early_driver_symlinks target)
159+
# Early swift-driver is built adjacent to the compiler (swift build dir)
160+
set(driver_bin_dir "${CMAKE_BINARY_DIR}/../earlyswiftdriver-${SWIFT_HOST_VARIANT}-${SWIFT_HOST_VARIANT_ARCH}/release/bin")
161+
set(swift_bin_dir "${SWIFT_RUNTIME_OUTPUT_INTDIR}")
162+
# If early swift-driver wasn't built, nothing to do here.
163+
if(NOT EXISTS "${driver_bin_dir}/swift-driver" OR NOT EXISTS "${driver_bin_dir}/swift-help")
164+
message(STATUS "Skipping creating early SwiftDriver symlinks - no early SwiftDriver build found.")
165+
return()
166+
endif()
167+
168+
message(STATUS "Creating early SwiftDriver symlinks.")
169+
message(STATUS "From: ${driver_bin_dir}/swift-driver")
170+
message(STATUS "To: ${swift_bin_dir}/swift-driver")
171+
swift_create_post_build_symlink(swift-frontend
172+
SOURCE "${driver_bin_dir}/swift-driver"
173+
DESTINATION "${swift_bin_dir}/swift-driver"
174+
COMMENT "Creating early SwiftDriver symlinks: swift-driver")
175+
176+
message(STATUS "From: ${driver_bin_dir}/swift-help")
177+
message(STATUS "To: ${swift_bin_dir}/swift-help")
178+
swift_create_post_build_symlink(swift-frontend
179+
SOURCE "${driver_bin_dir}/swift-help"
180+
DESTINATION "${swift_bin_dir}/swift-help"
181+
COMMENT "Creating early SwiftDriver symlinks: swift-help")
182+
endfunction()
183+
155184
function(dump_swift_vars)
156185
set(SWIFT_STDLIB_GLOBAL_CMAKE_CACHE)
157186
get_cmake_property(variableNames VARIABLES)

test/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ set(TEST_SUBSETS
188188
only_validation
189189
only_long
190190
only_stress
191+
only_early_swiftdriver
191192
)
192193

193194
if(NOT "${COVERAGE_DB}" STREQUAL "")
@@ -353,6 +354,7 @@ foreach(SDK ${SWIFT_SDKS})
353354
(test_subset STREQUAL "validation") OR
354355
(test_subset STREQUAL "only_long") OR
355356
(test_subset STREQUAL "only_stress") OR
357+
(test_subset STREQUAL "only_early_swiftdriver") OR
356358
(test_subset STREQUAL "all"))
357359
list(APPEND directories "${test_bin_dir}")
358360
endif()

test/Unit/lit.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ elif swift_test_subset == 'only_stress':
6363
# Currently those tests are very fast so it doesn't matter much.
6464
pass
6565
else:
66-
lit_config.fatal("Unknown test mode %r" % swift_test_subset)
66+
lit_config.fatal("Unknown test subset %r" % swift_test_subset)
6767

6868
# test_source_root: The root path where tests are located.
6969
# test_exec_root: The root path where tests should be run.

test/lit.cfg

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,10 @@ elif swift_test_subset == 'only_stress':
631631
config.available_features.add("stress_test")
632632
config.limit_to_features.add("stress_test")
633633
config.limit_to_features.discard("executable_test")
634+
elif swift_test_subset == 'only_early_swiftdriver':
635+
# Point this subset at a driver-specific set of tests. These are the known reduced subset
636+
# of tests to verify the basic functionality of the standalone (early) swift-driver.
637+
config.test_source_root = os.path.join(config.test_source_root, 'Driver', 'Dependencies')
634638
else:
635639
lit_config.fatal("Unknown test mode %r" % swift_test_subset)
636640

@@ -640,6 +644,13 @@ if 'swift_evolve' in lit_config.params:
640644
if not 'swift_driver' in lit_config.params:
641645
config.available_features.add("cplusplus_driver")
642646

647+
# Check if we need to run lit tests using the legacy driver or the new driver
648+
# The default for existing test runs is to use the legacy driver.
649+
# The new driver is tested separately.
650+
if swift_test_subset != 'only_early_swiftdriver' and\
651+
os.environ.get('SWIFT_FORCE_TEST_NEW_DRIVER') is None:
652+
config.environment['SWIFT_USE_OLD_DRIVER'] = '1'
653+
643654
# Enable benchmark testing when the binary is found (has fully qualified path).
644655
if config.benchmark_o != 'Benchmark_O':
645656
config.available_features.add('benchmark')

tools/driver/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ target_link_libraries(swift-frontend
1616
swiftSymbolGraphGen
1717
LLVMBitstreamReader)
1818

19+
# Create a `swift-driver` symlinks adjacent to the `swift-frontend` executable
20+
# to ensure that `swiftc` forwards to the standalone driver when invoked.
21+
swift_create_early_driver_symlinks(swift-frontend)
22+
1923
swift_create_post_build_symlink(swift-frontend
2024
SOURCE "swift-frontend${CMAKE_EXECUTABLE_SUFFIX}"
2125
DESTINATION "swift${CMAKE_EXECUTABLE_SUFFIX}"

utils/build-script

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -848,14 +848,24 @@ class BuildScriptInvocation(object):
848848
return options
849849

850850
def compute_product_classes(self):
851-
"""compute_product_classes() -> (list, list)
852-
853-
Compute the list first of all build-script-impl products and then all
854-
non-build-script-impl products. It is assumed that concatenating the two
855-
lists together will result in a valid dependency graph for the
856-
compilation.
851+
"""compute_product_classes() -> (list, list, list)
857852
853+
Compute the list first of all pre-build-script-impl products, then all
854+
build-script-impl products and then all non-build-script-impl products.
855+
It is assumed that concatenating the three lists together will result in a
856+
valid dependency graph for the compilation.
858857
"""
858+
before_impl_product_classes = []
859+
# If --skip-early-swift-driver is passed in, swift will be built
860+
# as usual, but relying on its own C++-based (Legacy) driver.
861+
# Otherwise, we build an "early" swift-driver using the host
862+
# toolchain, which the later-built compiler will forward
863+
# `swiftc` invocations to. That is, if we find a Swift compiler
864+
# in the host toolchain. If the host toolchain is not equpipped with
865+
# a Swift compiler, a warning is emitted. In the future, it may become
866+
# mandatory that the host toolchain come with its own `swiftc`.
867+
if self.args.build_early_swift_driver:
868+
before_impl_product_classes.append(products.EarlySwiftDriver)
859869

860870
# FIXME: This is a weird division (returning a list of class objects),
861871
# but it matches the existing structure of the `build-script-impl`.
@@ -940,6 +950,7 @@ class BuildScriptInvocation(object):
940950
# non-build-script-impl products. Otherwise, it would be unsafe to
941951
# re-order build-script-impl products in front of non
942952
# build-script-impl products.
953+
before_impl_product_classes = []
943954
impl_product_classes = []
944955
product_classes = []
945956
is_darwin = platform.system() == 'Darwin'
@@ -950,15 +961,19 @@ class BuildScriptInvocation(object):
950961

951962
if p.is_build_script_impl_product():
952963
impl_product_classes.append(p)
964+
elif p.is_before_build_script_impl_product():
965+
before_impl_product_classes.append(p)
953966
else:
954967
product_classes.append(p)
955968
if self.args.verbose_build:
956969
print("Final Build Order:")
970+
for p in before_impl_product_classes:
971+
print(" {}".format(p.product_name()))
957972
for p in impl_product_classes:
958973
print(" {}".format(p.product_name()))
959974
for p in product_classes:
960975
print(" {}".format(p.product_name()))
961-
return (impl_product_classes, product_classes)
976+
return (before_impl_product_classes, impl_product_classes, product_classes)
962977

963978
def execute(self):
964979
"""Execute the invocation with the configured arguments."""
@@ -975,7 +990,6 @@ class BuildScriptInvocation(object):
975990
return
976991

977992
# Otherwise, we compute and execute the individual actions ourselves.
978-
979993
# Compute the list of hosts to operate on.
980994
all_host_names = [
981995
self.args.host_target] + self.args.cross_compile_hosts
@@ -986,10 +1000,22 @@ class BuildScriptInvocation(object):
9861000
#
9871001
# FIXME: This should really be per-host, but the current structure
9881002
# matches that of `build-script-impl`.
989-
(impl_product_classes, product_classes) = self.compute_product_classes()
1003+
(before_impl_product_classes, impl_product_classes, product_classes) =\
1004+
self.compute_product_classes()
9901005

9911006
# Execute each "pass".
9921007

1008+
# Pre-build-script-impl products...
1009+
# Note: currently only supports building for the host.
1010+
for host_target in [self.args.host_target]:
1011+
for product_class in before_impl_product_classes:
1012+
if product_class.is_build_script_impl_product():
1013+
continue
1014+
if not product_class.is_before_build_script_impl_product():
1015+
continue
1016+
# Execute clean, build, test, install
1017+
self.execute_product_build_steps(product_class, host_target)
1018+
9931019
# Build...
9941020
for host_target in all_hosts:
9951021
# FIXME: We should only compute these once.
@@ -1029,33 +1055,8 @@ class BuildScriptInvocation(object):
10291055
for product_class in product_classes:
10301056
if product_class.is_build_script_impl_product():
10311057
continue
1032-
product_source = product_class.product_source_name()
1033-
product_name = product_class.product_name()
1034-
if product_class.is_swiftpm_unified_build_product():
1035-
build_dir = self.workspace.swiftpm_unified_build_dir(
1036-
host_target)
1037-
else:
1038-
build_dir = self.workspace.build_dir(
1039-
host_target, product_name)
1040-
product = product_class(
1041-
args=self.args,
1042-
toolchain=self.toolchain,
1043-
source_dir=self.workspace.source_dir(product_source),
1044-
build_dir=build_dir)
1045-
if product.should_clean(host_target):
1046-
print("--- Cleaning %s ---" % product_name)
1047-
product.clean(host_target)
1048-
if product.should_build(host_target):
1049-
print("--- Building %s ---" % product_name)
1050-
product.build(host_target)
1051-
if product.should_test(host_target):
1052-
print("--- Running tests for %s ---" % product_name)
1053-
product.test(host_target)
1054-
print("--- Finished tests for %s ---" % product_name)
1055-
if product.should_install(host_target) or \
1056-
(self.install_all and product.should_build(host_target)):
1057-
print("--- Installing %s ---" % product_name)
1058-
product.install(host_target)
1058+
# Execute clean, build, test, install
1059+
self.execute_product_build_steps(product_class, host_target)
10591060

10601061
# Extract symbols...
10611062
for host_target in all_hosts:
@@ -1103,6 +1104,35 @@ class BuildScriptInvocation(object):
11031104
["--only-execute", action_name],
11041105
env=self.impl_env, echo=self.args.verbose_build)
11051106

1107+
def execute_product_build_steps(self, product_class, host_target):
1108+
product_source = product_class.product_source_name()
1109+
product_name = product_class.product_name()
1110+
if product_class.is_swiftpm_unified_build_product():
1111+
build_dir = self.workspace.swiftpm_unified_build_dir(
1112+
host_target)
1113+
else:
1114+
build_dir = self.workspace.build_dir(
1115+
host_target, product_name)
1116+
product = product_class(
1117+
args=self.args,
1118+
toolchain=self.toolchain,
1119+
source_dir=self.workspace.source_dir(product_source),
1120+
build_dir=build_dir)
1121+
if product.should_clean(host_target):
1122+
print("--- Cleaning %s ---" % product_name)
1123+
product.clean(host_target)
1124+
if product.should_build(host_target):
1125+
print("--- Building %s ---" % product_name)
1126+
product.build(host_target)
1127+
if product.should_test(host_target):
1128+
print("--- Running tests for %s ---" % product_name)
1129+
product.test(host_target)
1130+
print("--- Finished tests for %s ---" % product_name)
1131+
if product.should_install(host_target) or \
1132+
(self.install_all and product.should_build(host_target)):
1133+
print("--- Installing %s ---" % product_name)
1134+
product.install(host_target)
1135+
11061136

11071137
# -----------------------------------------------------------------------------
11081138
# Main (preset)

utils/build_swift/build_swift/driver_arguments.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,12 @@ def _apply_default_arguments(args):
193193
args.test_swiftevolve = False
194194
args.test_toolchainbenchmarks = False
195195

196+
# --test implies --test-early-swift-driver
197+
# (unless explicitly skipped with `--skip-test-early-swift-driver`)
198+
if args.test and (args.build_early_swift_driver and
199+
args.test_early_swift_driver is None):
200+
args.test_early_swift_driver = True
201+
196202
# --skip-test-ios is merely a shorthand for host and simulator tests.
197203
if not args.test_ios:
198204
args.test_ios_host = False
@@ -610,6 +616,9 @@ def create_argument_parser():
610616
option(['--swift-driver'], toggle_true('build_swift_driver'),
611617
help='build swift-driver')
612618

619+
option(['--skip-early-swift-driver'], toggle_false('build_early_swift_driver'),
620+
help='skip building the early swift-driver')
621+
613622
option(['--indexstore-db'], toggle_true('build_indexstoredb'),
614623
help='build IndexStoreDB')
615624
option('--test-indexstore-db-sanitize-all',
@@ -1036,9 +1045,13 @@ def create_argument_parser():
10361045
toggle_false('test_android_host'),
10371046
help='skip testing Android device targets on the host machine (the '
10381047
'phone itself)')
1039-
10401048
option('--skip-clean-llbuild', toggle_false('clean_llbuild'),
10411049
help='skip cleaning up llbuild')
1050+
option('--clean-early-swift-driver', toggle_true('clean_early_swift_driver'),
1051+
help='Clean up the early SwiftDriver')
1052+
option('--skip-test-early-swift-driver',
1053+
store('test_early_swift_driver', const=False),
1054+
help='Test the early SwiftDriver against the host toolchain')
10421055
option('--skip-clean-swiftpm', toggle_false('clean_swiftpm'),
10431056
help='skip cleaning up swiftpm')
10441057
option('--skip-clean-swift-driver', toggle_false('clean_swift_driver'),

utils/build_swift/tests/build_swift/test_driver_arguments.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,14 @@ def test_implied_defaults_test_optimize_for_size(self):
586586
namespace = self.parse_default_args(['--test-optimize-for-size'])
587587
self.assertTrue(namespace.test)
588588

589+
def test_implied_defaults_test_early_swift_driver(self):
590+
namespace = self.parse_default_args(['--test'])
591+
self.assertTrue(namespace.test_early_swift_driver)
592+
593+
def test_implied_defaults_test_no_early_swift_driver(self):
594+
namespace = self.parse_default_args(['--test --skip-early-swift-driver'])
595+
self.assertTrue(namespace.test_early_swift_driver is None)
596+
589597
def test_implied_defaults_test_optimize_none_with_implicit_dynamic(self):
590598
namespace = self.parse_default_args(
591599
['--test-optimize-none-with-implicit-dynamic'])

utils/build_swift/tests/expected_options.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
'build_swift_stdlib_unittest_extra': False,
9090
'build_swiftpm': False,
9191
'build_swift_driver': False,
92+
'build_early_swift_driver': True,
9293
'build_swiftsyntax': False,
9394
'build_libparser_only': False,
9495
'build_skstresstester': False,
@@ -99,8 +100,8 @@
99100
'test_sourcekitlsp_sanitize_all': False,
100101
'build_sourcekitlsp': False,
101102
'install_swiftpm': False,
102-
'install_swift_driver': False,
103103
'install_swiftsyntax': False,
104+
'install_swift_driver': False,
104105
'swiftsyntax_verify_generated_files': False,
105106
'install_playgroundsupport': False,
106107
'install_sourcekitlsp': False,
@@ -215,7 +216,9 @@
215216
'clean_llbuild': True,
216217
'clean_swiftpm': True,
217218
'clean_swift_driver': True,
219+
'clean_early_swift_driver': False,
218220
'test': None,
221+
'test_early_swift_driver': None,
219222
'test_android': False,
220223
'test_android_host': False,
221224
'test_cygwin': False,
@@ -461,6 +464,8 @@ class BuildScriptImplOption(_BaseOption):
461464
SetOption('--skip-ios', dest='ios', value=False),
462465
SetOption('--skip-tvos', dest='tvos', value=False),
463466
SetOption('--skip-watchos', dest='watchos', value=False),
467+
SetOption('--skip-test-early-swift-driver',
468+
dest='test_early_swift_driver', value=False),
464469

465470
SetTrueOption('--benchmark'),
466471
SetTrueOption('--clean'),
@@ -555,6 +560,7 @@ class BuildScriptImplOption(_BaseOption):
555560
EnableOption('--watchos'),
556561
EnableOption('--xctest', dest='build_xctest'),
557562
EnableOption('--swift-disable-dead-stripping'),
563+
EnableOption('--clean-early-swift-driver', dest='clean_early_swift_driver'),
558564

559565
DisableOption('--skip-build-cmark', dest='build_cmark'),
560566
DisableOption('--skip-build-llvm', dest='build_llvm'),
@@ -580,6 +586,7 @@ class BuildScriptImplOption(_BaseOption):
580586
DisableOption('--skip-build-watchos-simulator',
581587
dest='build_watchos_simulator'),
582588
DisableOption('--skip-clean-llbuild', dest='clean_llbuild'),
589+
DisableOption('--skip-early-swift-driver', dest='build_early_swift_driver'),
583590
DisableOption('--skip-clean-swiftpm', dest='clean_swiftpm'),
584591
DisableOption('--skip-clean-swift-driver', dest='clean_swift_driver'),
585592
DisableOption('--skip-test-android', dest='test_android'),

utils/run-test

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ TEST_SUBSETS = [
3737
'only_validation',
3838
'only_long',
3939
'only_stress',
40+
'only_early_swiftdriver'
4041
]
4142

4243
SWIFT_SOURCE_DIR = os.path.join(SWIFT_SOURCE_ROOT, 'swift')

utils/swift_build_support/swift_build_support/host_specific_configuration.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,14 @@ def __init__(self, host_target, args):
167167
else:
168168
subset_suffix = ""
169169

170+
# If the compiler is being tested after being built to use the
171+
# standalone swift-driver, we build a test-target to
172+
# run a reduced set of lit-tests that verify the early swift-driver.
173+
if getattr(args, 'test_early_swift_driver', False) and\
174+
not test_host_only:
175+
self.swift_test_run_targets.append(
176+
"check-swift-only_early_swiftdriver-{}".format(name))
177+
170178
# Support for running the macCatalyst tests with
171179
# the iOS-like target triple.
172180
macosx_platform_match = re.search("macosx-(.*)", name)
@@ -180,6 +188,7 @@ def __init__(self, host_target, args):
180188
(self.swift_test_run_targets
181189
.append("check-swift{}{}-{}".format(
182190
subset_suffix, suffix, name)))
191+
183192
if args.test_optimized and not test_host_only:
184193
self.swift_test_run_targets.append(
185194
"check-swift{}-optimize-{}".format(

0 commit comments

Comments
 (0)