22
22
23
23
import six
24
24
25
- from swift_build_support .swift_build_support import build_graph
26
25
from swift_build_support .swift_build_support import products
27
26
from swift_build_support .swift_build_support import shell
28
27
from swift_build_support .swift_build_support import targets
29
28
from swift_build_support .swift_build_support import workspace
30
29
from swift_build_support .swift_build_support .cmake import CMake
31
30
from swift_build_support .swift_build_support .host_specific_configuration \
32
31
import HostSpecificConfiguration
32
+ from swift_build_support .swift_build_support .productpipeline_list_builder \
33
+ import ProductPipelineListBuilder
33
34
from swift_build_support .swift_build_support .targets \
34
35
import StdlibDeploymentTarget
35
36
from swift_build_support .swift_build_support .utils \
@@ -133,12 +134,12 @@ def convert_to_impl_arguments(self):
133
134
134
135
# Compute any product specific cmake arguments.
135
136
#
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
137
138
# tuple of lists of which the first is the build-script-impl products
138
139
# and the second is the non-build-script-impl-products. It guarantees
139
140
# that when we concatenate these two lists together we get a valid
140
141
# 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 ] ), []):
142
143
if not product_class .is_build_script_impl_product ():
143
144
continue
144
145
@@ -491,15 +492,20 @@ def compute_host_specific_variables(self):
491
492
492
493
return options
493
494
494
- def compute_product_classes (self ):
495
- """compute_product_classes () -> (list, list, list)
495
+ def compute_product_pipelines (self ):
496
+ """compute_product_pipelines () -> [[Product]]
496
497
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.
501
505
"""
502
- before_impl_product_classes = []
506
+ builder = ProductPipelineListBuilder (self .args )
507
+
508
+ builder .begin_pipeline ()
503
509
# If --skip-early-swift-driver is passed in, swift will be built
504
510
# as usual, but relying on its own C++-based (Legacy) driver.
505
511
# Otherwise, we build an "early" swift-driver using the host
@@ -508,120 +514,79 @@ def compute_product_classes(self):
508
514
# in the host toolchain. If the host toolchain is not equpipped with
509
515
# a Swift compiler, a warning is emitted. In the future, it may become
510
516
# 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 )
513
519
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 )
516
522
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 )
520
530
521
531
# If --skip-build-llvm is passed in, LLVM cannot be completely disabled, as
522
532
# Swift still needs a few LLVM targets like tblgen to be built for it to be
523
533
# 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 )
569
578
570
579
# Keep SwiftDriver at last.
571
580
# swift-driver's integration with the build scripts is not fully
572
581
# supported. Using swift-driver to build these products may hit
573
582
# 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 )
625
590
626
591
def execute (self ):
627
592
"""Execute the invocation with the configured arguments."""
@@ -644,26 +609,47 @@ def execute(self):
644
609
all_hosts = [StdlibDeploymentTarget .get_target_for_name (name )
645
610
for name in all_host_names ]
646
611
647
- # Compute the list of product classes to operate on.
612
+ # Compute the list of lists of product classes to operate on.
648
613
#
649
614
# FIXME: This should really be per-host, but the current structure
650
615
# 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 ()
653
617
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 )
655
638
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 )
666
648
649
+ # Lipo...
650
+ self ._execute_merged_host_lipo_action ()
651
+
652
+ def _execute_impl (self , pipeline , all_hosts , should_run_epilogue_operations ):
667
653
# Build...
668
654
for host_target in all_hosts :
669
655
# FIXME: We should only compute these once.
@@ -681,42 +667,33 @@ def execute(self):
681
667
print ("Running Swift benchmarks for: {}" .format (
682
668
" " .join (config .swift_benchmark_run_targets )))
683
669
684
- for product_class in impl_product_classes :
670
+ for product_class in pipeline :
685
671
self ._execute_build_action (host_target , product_class )
686
672
687
673
# Test...
688
674
for host_target in all_hosts :
689
- for product_class in impl_product_classes :
675
+ for product_class in pipeline :
690
676
self ._execute_test_action (host_target , product_class )
691
677
692
678
# Install...
693
679
for host_target in all_hosts :
694
- for product_class in impl_product_classes :
680
+ for product_class in pipeline :
695
681
self ._execute_install_action (host_target , product_class )
696
682
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
+
697
688
# Core Lipo...
698
689
self ._execute_merged_host_lipo_core_action ()
699
690
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 :
706
694
# Execute clean, build, test, install
707
695
self .execute_product_build_steps (product_class , host_target )
708
696
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
-
720
697
def _execute_build_action (self , host_target , product_class ):
721
698
action_name = "{}-{}-build" .format (host_target .name ,
722
699
product_class .product_name ())
0 commit comments