2222
2323import six
2424
25- from swift_build_support .swift_build_support import build_graph
2625from swift_build_support .swift_build_support import products
2726from swift_build_support .swift_build_support import shell
2827from swift_build_support .swift_build_support import targets
2928from swift_build_support .swift_build_support import workspace
3029from swift_build_support .swift_build_support .cmake import CMake
3130from 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
3334from swift_build_support .swift_build_support .targets \
3435 import StdlibDeploymentTarget
3536from 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,47 @@ 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+ # Once we have performed our last impl pipeline, we no longer
631+ # support cross compilation.
632+ #
633+ # This just maintains current behavior.
634+ if index > last_impl_index :
635+ self ._execute (pipeline , [self .args .host_target ])
636+ else :
637+ self ._execute (pipeline , all_host_names )
655638
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 )
639+ # And then perform the rest of the non-core epilogue actions.
640+
641+ # Extract symbols...
642+ for host_target in all_hosts :
643+ self ._execute_extract_symbols_action (host_target )
644+
645+ # Package...
646+ for host_target in all_hosts :
647+ self ._execute_package_action (host_target )
666648
649+ # Lipo...
650+ self ._execute_merged_host_lipo_action ()
651+
652+ def _execute_impl (self , pipeline , all_hosts , should_run_epilogue_operations ):
667653 # Build...
668654 for host_target in all_hosts :
669655 # FIXME: We should only compute these once.
@@ -681,42 +667,33 @@ def execute(self):
681667 print ("Running Swift benchmarks for: {}" .format (
682668 " " .join (config .swift_benchmark_run_targets )))
683669
684- for product_class in impl_product_classes :
670+ for product_class in pipeline :
685671 self ._execute_build_action (host_target , product_class )
686672
687673 # Test...
688674 for host_target in all_hosts :
689- for product_class in impl_product_classes :
675+ for product_class in pipeline :
690676 self ._execute_test_action (host_target , product_class )
691677
692678 # Install...
693679 for host_target in all_hosts :
694- for product_class in impl_product_classes :
680+ for product_class in pipeline :
695681 self ._execute_install_action (host_target , product_class )
696682
683+ # And then we may be asked to perform several post-processing operations
684+ # on what we have built. If we are not supposed to do so, bail now.
685+ if not should_run_epilogue_operations :
686+ return
687+
697688 # Core Lipo...
698689 self ._execute_merged_host_lipo_core_action ()
699690
700- # Non-build-script-impl products...
701- # 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
691+ def _execute (self , pipeline , all_host_names ):
692+ for host_target in all_host_names :
693+ for product_class in pipeline :
706694 # Execute clean, build, test, install
707695 self .execute_product_build_steps (product_class , host_target )
708696
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-
720697 def _execute_build_action (self , host_target , product_class ):
721698 action_name = "{}-{}-build" .format (host_target .name ,
722699 product_class .product_name ())
0 commit comments