From fc4ef192ae875d979365513a03c9f8312f9ba75e Mon Sep 17 00:00:00 2001 From: Artem Chikin Date: Thu, 20 Aug 2020 11:10:55 -0700 Subject: [PATCH] [build-script] Add a default-enabled "clean" step for swift-driver and swiftpm Along with options to disable the mandatory clean using: `--skip-clean-swift-driver` and `--skip-clean-swiftpm`. This will ensure that every invocation of build-script will, by default, clean up all build artifacts of these projects and re-build them from scratch. This is needed for all builds because today arbitrary changes to the compiler can lead to us being unable to incrementally build components that are themselves written in Swift. This causes now-frequent failures in incremental build bots, and is a scenario that is encountered by developers. (For example see: rdar://65006593) The proper long-term solution is to enable library evolution for these projects. Until this is done, the only safe thing to do is to always rebuild them. Resolves rdar://65006593 --- utils/build-script | 3 +++ utils/build_swift/build_swift/driver_arguments.py | 4 ++++ utils/build_swift/tests/expected_options.py | 4 ++++ .../swift_build_support/products/product.py | 14 ++++++++++++++ .../swift_build_support/products/swiftdriver.py | 7 +++++++ .../swift_build_support/products/swiftpm.py | 11 +++++++++++ 6 files changed, 43 insertions(+) diff --git a/utils/build-script b/utils/build-script index 84417ed56153a..10ee8f7efd235 100755 --- a/utils/build-script +++ b/utils/build-script @@ -964,6 +964,9 @@ class BuildScriptInvocation(object): toolchain=self.toolchain, source_dir=self.workspace.source_dir(product_source), build_dir=build_dir) + if product.should_clean(host_target): + print("--- Cleaning %s ---" % product_name) + product.clean(host_target) if product.should_build(host_target): print("--- Building %s ---" % product_name) product.build(host_target) diff --git a/utils/build_swift/build_swift/driver_arguments.py b/utils/build_swift/build_swift/driver_arguments.py index 838aa5afa84ff..acf339a22c277 100644 --- a/utils/build_swift/build_swift/driver_arguments.py +++ b/utils/build_swift/build_swift/driver_arguments.py @@ -1008,6 +1008,10 @@ def create_argument_parser(): help='skip testing Android device targets on the host machine (the ' 'phone itself)') + option('--skip-clean-swiftpm', toggle_false('clean_swiftpm'), + help='skip cleaning up swiftpm') + option('--skip-clean-swift-driver', toggle_false('clean_swift_driver'), + help='skip cleaning up Swift driver') option('--skip-test-swiftpm', toggle_false('test_swiftpm'), help='skip testing swiftpm') option('--skip-test-swift-driver', toggle_false('test_swift_driver'), diff --git a/utils/build_swift/tests/expected_options.py b/utils/build_swift/tests/expected_options.py index 9864063b6e7bb..e0381cb842fc2 100644 --- a/utils/build_swift/tests/expected_options.py +++ b/utils/build_swift/tests/expected_options.py @@ -205,6 +205,8 @@ defaults.SWIFT_MAX_PARALLEL_LTO_LINK_JOBS, 'swift_user_visible_version': defaults.SWIFT_USER_VISIBLE_VERSION, 'symbols_package': None, + 'clean_swiftpm': True, + 'clean_swift_driver': True, 'test': None, 'test_android': False, 'test_android_host': False, @@ -567,6 +569,8 @@ class BuildScriptImplOption(_BaseOption): dest='build_watchos_device'), DisableOption('--skip-build-watchos-simulator', dest='build_watchos_simulator'), + DisableOption('--skip-clean-swiftpm', dest='clean_swiftpm'), + DisableOption('--skip-clean-swift-driver', dest='clean_swift_driver'), DisableOption('--skip-test-android', dest='test_android'), DisableOption('--skip-test-android-host', dest='test_android_host'), DisableOption('--skip-test-cygwin', dest='test_cygwin'), diff --git a/utils/swift_build_support/swift_build_support/products/product.py b/utils/swift_build_support/swift_build_support/products/product.py index ed4c944bc008e..5ccfa48283e88 100644 --- a/utils/swift_build_support/swift_build_support/products/product.py +++ b/utils/swift_build_support/swift_build_support/products/product.py @@ -78,6 +78,20 @@ def get_dependencies(cls): """Return a list of products that this product depends upon""" raise NotImplementedError + def should_clean(self, host_target): + """should_clean() -> Bool + + Whether or not this product should be cleaned before being built + """ + return False + + def clean(self, host_target): + """clean() -> void + + Perform the clean, for a non-build-script-impl product. + """ + raise NotImplementedError + def should_build(self, host_target): """should_build() -> Bool diff --git a/utils/swift_build_support/swift_build_support/products/swiftdriver.py b/utils/swift_build_support/swift_build_support/products/swiftdriver.py index 52ca78d4c00a9..5eca23c888086 100644 --- a/utils/swift_build_support/swift_build_support/products/swiftdriver.py +++ b/utils/swift_build_support/swift_build_support/products/swiftdriver.py @@ -47,6 +47,13 @@ def get_dependencies(cls): xctest.XCTest, llbuild.LLBuild] + def should_clean(self, host_target): + return self.args.clean_swift_driver + + def clean(self, host_target): + indexstoredb.run_build_script_helper( + 'clean', host_target, self, self.args) + def build(self, host_target): indexstoredb.run_build_script_helper( 'build', host_target, self, self.args) diff --git a/utils/swift_build_support/swift_build_support/products/swiftpm.py b/utils/swift_build_support/swift_build_support/products/swiftpm.py index 48c18256629b5..412dc52814f5c 100644 --- a/utils/swift_build_support/swift_build_support/products/swiftpm.py +++ b/utils/swift_build_support/swift_build_support/products/swiftpm.py @@ -51,6 +51,11 @@ def run_bootstrap_script(self, action, host_target, additional_params=[]): helper_cmd = [script_path, action] + if action == 'clean': + helper_cmd += ["--build-dir", self.build_dir] + shell.call(helper_cmd) + return + if self.is_release(): helper_cmd.append("--release") @@ -94,6 +99,12 @@ def should_test(self, host_target): def test(self, host_target): self.run_bootstrap_script('test', host_target) + def should_clean(self, host_target): + return self.args.clean_swiftpm + + def clean(self, host_target): + self.run_bootstrap_script('clean', host_target) + def should_install(self, host_target): return self.args.install_swiftpm