Skip to content

Commit 084f5b3

Browse files
authored
Merge pull request #38886 from gottesmm/pr-88e3658ca820cb93dc6145ed8648f17387c3c87e
[build-script] Use a builder to setup pass pipelines that are then scheduled when using --infer
2 parents a3e72f5 + 6d50463 commit 084f5b3

File tree

3 files changed

+336
-146
lines changed

3 files changed

+336
-146
lines changed

utils/swift_build_support/swift_build_support/build_script_invocation.py

Lines changed: 118 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@
2222

2323
import six
2424

25-
from swift_build_support.swift_build_support import build_graph
2625
from swift_build_support.swift_build_support import products
2726
from swift_build_support.swift_build_support import shell
2827
from swift_build_support.swift_build_support import targets
2928
from swift_build_support.swift_build_support import workspace
3029
from swift_build_support.swift_build_support.cmake import CMake
3130
from swift_build_support.swift_build_support.host_specific_configuration \
3231
import HostSpecificConfiguration
32+
from swift_build_support.swift_build_support.productpipeline_list_builder \
33+
import ProductPipelineListBuilder
3334
from swift_build_support.swift_build_support.targets \
3435
import StdlibDeploymentTarget
3536
from swift_build_support.swift_build_support.utils \
@@ -133,12 +134,12 @@ def convert_to_impl_arguments(self):
133134

134135
# Compute any product specific cmake arguments.
135136
#
136-
# NOTE: The sum(list(...)) is b/c compute_product_classes returns a
137+
# NOTE: The sum(list(...)) is b/c compute_product_pipelines returns a
137138
# tuple of lists of which the first is the build-script-impl products
138139
# and the second is the non-build-script-impl-products. It guarantees
139140
# that when we concatenate these two lists together we get a valid
140141
# dependency graph.
141-
for product_class in sum(list(self.compute_product_classes()), []):
142+
for product_class in sum(list(self.compute_product_pipelines()[0]), []):
142143
if not product_class.is_build_script_impl_product():
143144
continue
144145

@@ -491,15 +492,20 @@ def compute_host_specific_variables(self):
491492

492493
return options
493494

494-
def compute_product_classes(self):
495-
"""compute_product_classes() -> (list, list, list)
495+
def compute_product_pipelines(self):
496+
"""compute_product_pipelines() -> [[Product]]
496497
497-
Compute the list first of all pre-build-script-impl products, then all
498-
build-script-impl products and then all non-build-script-impl products.
499-
It is assumed that concatenating the three lists together will result in a
500-
valid dependency graph for the compilation.
498+
A list of lists of products.
499+
500+
Compute lists of product pipelines that we should run. It is guaranteed
501+
that all product pipeline lists consist of solely build-script-impl
502+
products or build-script products. So one can always check the first
503+
element to know if a pipeline returned from the builder is an impl
504+
product or not.
501505
"""
502-
before_impl_product_classes = []
506+
builder = ProductPipelineListBuilder(self.args)
507+
508+
builder.begin_pipeline()
503509
# If --skip-early-swift-driver is passed in, swift will be built
504510
# as usual, but relying on its own C++-based (Legacy) driver.
505511
# Otherwise, we build an "early" swift-driver using the host
@@ -508,120 +514,79 @@ def compute_product_classes(self):
508514
# in the host toolchain. If the host toolchain is not equpipped with
509515
# a Swift compiler, a warning is emitted. In the future, it may become
510516
# mandatory that the host toolchain come with its own `swiftc`.
511-
if self.args.build_early_swift_driver:
512-
before_impl_product_classes.append(products.EarlySwiftDriver)
517+
builder.add_product(products.EarlySwiftDriver,
518+
is_enabled=self.args.build_early_swift_driver)
513519

514-
if self.args.build_cmark:
515-
before_impl_product_classes.append(products.CMark)
520+
builder.add_product(products.CMark,
521+
is_enabled=self.args.build_cmark)
516522

517-
# FIXME: This is a weird division (returning a list of class objects),
518-
# but it matches the existing structure of the `build-script-impl`.
519-
impl_product_classes = []
523+
# Begin a build-script-impl pipeline for handling the compiler toolchain
524+
# and a subset of the tools that we build. We build these in this manner
525+
# to preserve current build-script-impl run behavior as we transition
526+
# the build-script code base. The main difference is that these are all
527+
# build, tested, and installed all at once instead of performing build,
528+
# test, install like a normal build-script product.
529+
builder.begin_impl_pipeline(should_run_epilogue_operations=True)
520530

521531
# If --skip-build-llvm is passed in, LLVM cannot be completely disabled, as
522532
# Swift still needs a few LLVM targets like tblgen to be built for it to be
523533
# configured. Instead, handle this in build-script-impl for now.
524-
impl_product_classes.append(products.LLVM)
525-
if self.args.build_libcxx:
526-
impl_product_classes.append(products.LibCXX)
527-
if self.args.build_libicu:
528-
impl_product_classes.append(products.LibICU)
529-
if self.args.build_swift:
530-
impl_product_classes.append(products.Swift)
531-
if self.args.build_lldb:
532-
impl_product_classes.append(products.LLDB)
533-
if self.args.build_libdispatch:
534-
impl_product_classes.append(products.LibDispatch)
535-
if self.args.build_foundation:
536-
impl_product_classes.append(products.Foundation)
537-
if self.args.build_xctest:
538-
impl_product_classes.append(products.XCTest)
539-
if self.args.build_llbuild:
540-
impl_product_classes.append(products.LLBuild)
541-
# Sanity check that all of our impl classes are actually
542-
# build_script_impl products.
543-
for prod in impl_product_classes:
544-
assert(prod.is_build_script_impl_product())
545-
546-
product_classes = []
547-
if self.args.build_swiftpm:
548-
product_classes.append(products.SwiftPM)
549-
if self.args.build_swiftsyntax:
550-
product_classes.append(products.SwiftSyntax)
551-
if self.args.build_skstresstester:
552-
product_classes.append(products.SKStressTester)
553-
if self.args.build_swiftformat:
554-
product_classes.append(products.SwiftFormat)
555-
if self.args.build_swiftevolve:
556-
product_classes.append(products.SwiftEvolve)
557-
if self.args.build_indexstoredb:
558-
product_classes.append(products.IndexStoreDB)
559-
if self.args.build_playgroundsupport:
560-
product_classes.append(products.PlaygroundSupport)
561-
if self.args.build_sourcekitlsp:
562-
product_classes.append(products.SourceKitLSP)
563-
if self.args.build_toolchainbenchmarks:
564-
product_classes.append(products.Benchmarks)
565-
if self.args.build_swift_inspect:
566-
product_classes.append(products.SwiftInspect)
567-
if self.args.tsan_libdispatch_test:
568-
product_classes.append(products.TSanLibDispatch)
534+
builder.add_impl_product(products.LLVM,
535+
is_enabled=True)
536+
builder.add_impl_product(products.LibCXX,
537+
is_enabled=self.args.build_libcxx)
538+
builder.add_impl_product(products.LibICU,
539+
is_enabled=self.args.build_libicu)
540+
builder.add_impl_product(products.Swift,
541+
is_enabled=self.args.build_swift)
542+
builder.add_impl_product(products.LLDB,
543+
is_enabled=self.args.build_lldb)
544+
builder.add_impl_product(products.LibDispatch,
545+
is_enabled=self.args.build_libdispatch)
546+
builder.add_impl_product(products.Foundation,
547+
is_enabled=self.args.build_foundation)
548+
builder.add_impl_product(products.XCTest,
549+
is_enabled=self.args.build_xctest)
550+
builder.add_impl_product(products.LLBuild,
551+
is_enabled=self.args.build_llbuild)
552+
553+
# Begin the post build-script-impl build phase.
554+
builder.begin_pipeline()
555+
556+
builder.add_product(products.SwiftPM,
557+
is_enabled=self.args.build_swiftpm)
558+
builder.add_product(products.SwiftSyntax,
559+
is_enabled=self.args.build_swiftsyntax)
560+
builder.add_product(products.SKStressTester,
561+
is_enabled=self.args.build_skstresstester)
562+
builder.add_product(products.SwiftFormat,
563+
is_enabled=self.args.build_swiftformat)
564+
builder.add_product(products.SwiftEvolve,
565+
is_enabled=self.args.build_swiftevolve)
566+
builder.add_product(products.IndexStoreDB,
567+
is_enabled=self.args.build_indexstoredb)
568+
builder.add_product(products.PlaygroundSupport,
569+
is_enabled=self.args.build_playgroundsupport)
570+
builder.add_product(products.SourceKitLSP,
571+
is_enabled=self.args.build_sourcekitlsp)
572+
builder.add_product(products.Benchmarks,
573+
is_enabled=self.args.build_toolchainbenchmarks)
574+
builder.add_product(products.SwiftInspect,
575+
is_enabled=self.args.build_swift_inspect)
576+
builder.add_product(products.TSanLibDispatch,
577+
is_enabled=self.args.tsan_libdispatch_test)
569578

570579
# Keep SwiftDriver at last.
571580
# swift-driver's integration with the build scripts is not fully
572581
# supported. Using swift-driver to build these products may hit
573582
# failures.
574-
if self.args.build_swift_driver or self.args.install_swift_driver:
575-
product_classes.append(products.SwiftDriver)
576-
# Sanity check that all of our non-impl classes are actually
577-
# not build_script_impl products.
578-
for prod in product_classes:
579-
assert(not prod.is_build_script_impl_product())
580-
581-
# Now that we have our two lists of product_classes, if we are asked to
582-
# infer dependencies, infer the dependencies now and then re-split the
583-
# list.
584-
if self.args.infer_dependencies:
585-
combined_classes = before_impl_product_classes +\
586-
impl_product_classes +\
587-
product_classes
588-
if self.args.verbose_build:
589-
print("-- Build Graph Inference --")
590-
print("Initial Product List:")
591-
for p in combined_classes:
592-
print(" {}".format(p.product_name()))
593-
594-
# Now that we have produced the schedule, resplit. We require our
595-
# dependencies to respect our build-script-impl property. This means
596-
# that no build-script-impl products can have dependencies on
597-
# non-build-script-impl products. Otherwise, it would be unsafe to
598-
# re-order build-script-impl products in front of non
599-
# build-script-impl products.
600-
before_impl_product_classes = []
601-
impl_product_classes = []
602-
product_classes = []
603-
is_darwin = platform.system() == 'Darwin'
604-
final_schedule =\
605-
build_graph.produce_scheduled_build(combined_classes)[0]
606-
for p in final_schedule:
607-
if is_darwin and p.is_nondarwin_only_build_product():
608-
continue
609-
if p.is_build_script_impl_product():
610-
impl_product_classes.append(p)
611-
elif p.is_before_build_script_impl_product():
612-
before_impl_product_classes.append(p)
613-
else:
614-
product_classes.append(p)
615-
616-
if self.args.verbose_build:
617-
print("Final Build Order:")
618-
for p in before_impl_product_classes:
619-
print(" {}".format(p.product_name()))
620-
for p in impl_product_classes:
621-
print(" {}".format(p.product_name()))
622-
for p in product_classes:
623-
print(" {}".format(p.product_name()))
624-
return (before_impl_product_classes, impl_product_classes, product_classes)
583+
builder.add_product(products.SwiftDriver,
584+
is_enabled=self.args.build_swift_driver
585+
or self.args.install_swift_driver)
586+
587+
# Now that we have constructed our pass pipelines using our builder, get
588+
# the final schedule and finalize the builder.
589+
return builder.finalize(shouldInfer=self.args.infer_dependencies)
625590

626591
def execute(self):
627592
"""Execute the invocation with the configured arguments."""
@@ -644,26 +609,40 @@ def execute(self):
644609
all_hosts = [StdlibDeploymentTarget.get_target_for_name(name)
645610
for name in all_host_names]
646611

647-
# Compute the list of product classes to operate on.
612+
# Compute the list of lists of product classes to operate on.
648613
#
649614
# FIXME: This should really be per-host, but the current structure
650615
# matches that of `build-script-impl`.
651-
(before_impl_product_classes, impl_product_classes, product_classes) =\
652-
self.compute_product_classes()
616+
(product_pipelines, last_impl_index) = self.compute_product_pipelines()
653617

654-
# Execute each "pass".
618+
# Execute each "product pipeline".
619+
for index in range(len(product_pipelines)):
620+
pipeline = product_pipelines[index]
621+
# Skip empty pipelines.
622+
if len(pipeline) == 0:
623+
continue
624+
is_impl = pipeline[0].is_build_script_impl_product()
625+
if is_impl:
626+
perform_epilogue_opts = last_impl_index == index
627+
self._execute_impl(pipeline, all_hosts, perform_epilogue_opts)
628+
else:
629+
assert(index != last_impl_index)
630+
self._execute(pipeline, all_host_names)
655631

656-
# Pre-build-script-impl products...
657-
# Note: currently only supports building for the host.
658-
for host_target in all_host_names:
659-
for product_class in before_impl_product_classes:
660-
if product_class.is_build_script_impl_product():
661-
continue
662-
if not product_class.is_before_build_script_impl_product():
663-
continue
664-
# Execute clean, build, test, install
665-
self.execute_product_build_steps(product_class, host_target)
632+
# And then perform the rest of the non-core epilogue actions.
666633

634+
# Extract symbols...
635+
for host_target in all_hosts:
636+
self._execute_extract_symbols_action(host_target)
637+
638+
# Package...
639+
for host_target in all_hosts:
640+
self._execute_package_action(host_target)
641+
642+
# Lipo...
643+
self._execute_merged_host_lipo_action()
644+
645+
def _execute_impl(self, pipeline, all_hosts, should_run_epilogue_operations):
667646
# Build...
668647
for host_target in all_hosts:
669648
# FIXME: We should only compute these once.
@@ -681,42 +660,35 @@ def execute(self):
681660
print("Running Swift benchmarks for: {}".format(
682661
" ".join(config.swift_benchmark_run_targets)))
683662

684-
for product_class in impl_product_classes:
663+
for product_class in pipeline:
685664
self._execute_build_action(host_target, product_class)
686665

687666
# Test...
688667
for host_target in all_hosts:
689-
for product_class in impl_product_classes:
668+
for product_class in pipeline:
690669
self._execute_test_action(host_target, product_class)
691670

692671
# Install...
693672
for host_target in all_hosts:
694-
for product_class in impl_product_classes:
673+
for product_class in pipeline:
695674
self._execute_install_action(host_target, product_class)
696675

676+
# And then we may be asked to perform several post-processing operations
677+
# on what we have built. If we are not supposed to do so, bail now.
678+
if not should_run_epilogue_operations:
679+
return
680+
697681
# Core Lipo...
698682
self._execute_merged_host_lipo_core_action()
699683

700-
# Non-build-script-impl products...
684+
def _execute(self, pipeline, all_host_names):
685+
# Pre-build-script-impl products...
701686
# Note: currently only supports building for the host.
702-
for host_target in [self.args.host_target]:
703-
for product_class in product_classes:
704-
if product_class.is_build_script_impl_product():
705-
continue
687+
for host_target in all_host_names:
688+
for product_class in pipeline:
706689
# Execute clean, build, test, install
707690
self.execute_product_build_steps(product_class, host_target)
708691

709-
# Extract symbols...
710-
for host_target in all_hosts:
711-
self._execute_extract_symbols_action(host_target)
712-
713-
# Package...
714-
for host_target in all_hosts:
715-
self._execute_package_action(host_target)
716-
717-
# Lipo...
718-
self._execute_merged_host_lipo_action()
719-
720692
def _execute_build_action(self, host_target, product_class):
721693
action_name = "{}-{}-build".format(host_target.name,
722694
product_class.product_name())

0 commit comments

Comments
 (0)