diff --git a/utils/build-presets.ini b/utils/build-presets.ini
index d8f302ffe4cc1..3aff743954c4f 100644
--- a/utils/build-presets.ini
+++ b/utils/build-presets.ini
@@ -1701,6 +1701,22 @@ assertions
swiftsyntax
swiftsyntax-verify-generated-files
+#===------------------------------------------------------------------------===#
+# Test Swift Format
+#===------------------------------------------------------------------------===#
+
+[preset: buildbot_swiftformat_macos]
+mixin-preset=mixin_swiftpm_package_macos_platform
+release
+assertions
+swiftformat
+
+[preset: buildbot_swiftformat_linux]
+mixin-preset=mixin_swiftpm_package_linux_platform
+release
+assertions
+swiftformat
+
#===------------------------------------------------------------------------===#
# Test Swift Stress Tester
#===------------------------------------------------------------------------===#
diff --git a/utils/build-script b/utils/build-script
index 47ef2165b7766..95f97f8f4ca63 100755
--- a/utils/build-script
+++ b/utils/build-script
@@ -861,6 +861,8 @@ class BuildScriptInvocation(object):
product_classes.append(products.SwiftSyntax)
if self.args.build_skstresstester:
product_classes.append(products.SKStressTester)
+ if self.args.build_swiftformat:
+ product_classes.append(products.SwiftFormat)
if self.args.build_swiftevolve:
product_classes.append(products.SwiftEvolve)
if self.args.build_indexstoredb:
diff --git a/utils/build_swift/build_swift/driver_arguments.py b/utils/build_swift/build_swift/driver_arguments.py
index 04d5eef190834..71733cc817dfd 100644
--- a/utils/build_swift/build_swift/driver_arguments.py
+++ b/utils/build_swift/build_swift/driver_arguments.py
@@ -188,6 +188,7 @@ def _apply_default_arguments(args):
args.test_indexstoredb = False
args.test_sourcekitlsp = False
args.test_skstresstester = False
+ args.test_swiftformat = False
args.test_swiftevolve = False
args.test_toolchainbenchmarks = False
@@ -571,6 +572,9 @@ def create_argument_parser():
option(['--skstresstester'], store_true('build_skstresstester'),
help='build the SourceKit stress tester')
+ option(['--swiftformat'], store_true('build_swiftformat'),
+ help='build swift-format')
+
option(['--swiftevolve'], store_true('build_swiftevolve'),
help='build the swift-evolve tool')
@@ -1020,6 +1024,8 @@ def create_argument_parser():
help='skip testing PlaygroundSupport')
option('--skip-test-skstresstester', toggle_false('test_skstresstester'),
help='skip testing the SourceKit Stress tester')
+ option('--skip-test-swiftformat', toggle_false('test_swiftformat'),
+ help='skip testing swift-format')
option('--skip-test-swiftevolve', toggle_false('test_swiftevolve'),
help='skip testing SwiftEvolve')
option('--skip-test-toolchain-benchmarks',
diff --git a/utils/build_swift/resources/SwiftPM-Unified-Build.xcworkspace/contents.xcworkspacedata b/utils/build_swift/resources/SwiftPM-Unified-Build.xcworkspace/contents.xcworkspacedata
index ef015dfc533d6..92ad6dd28df5b 100644
--- a/utils/build_swift/resources/SwiftPM-Unified-Build.xcworkspace/contents.xcworkspacedata
+++ b/utils/build_swift/resources/SwiftPM-Unified-Build.xcworkspace/contents.xcworkspacedata
@@ -7,6 +7,9 @@
+
+
diff --git a/utils/build_swift/tests/expected_options.py b/utils/build_swift/tests/expected_options.py
index 160fdcd8e2fe5..7681cf3b6a1da 100644
--- a/utils/build_swift/tests/expected_options.py
+++ b/utils/build_swift/tests/expected_options.py
@@ -93,6 +93,7 @@
'build_tensorflow_swift_apis': False,
'build_libparser_only': False,
'build_skstresstester': False,
+ 'build_swiftformat': False,
'build_swiftevolve': False,
'build_indexstoredb': False,
'test_indexstoredb_sanitize_all': False,
@@ -234,6 +235,7 @@
'test_indexstoredb': False,
'test_sourcekitlsp': False,
'test_skstresstester': False,
+ 'test_swiftformat': False,
'test_swiftevolve': False,
'test_toolchainbenchmarks': False,
'tvos': False,
@@ -476,6 +478,7 @@ class BuildScriptImplOption(_BaseOption):
SetTrueOption('--swiftsyntax', dest='build_swiftsyntax'),
SetTrueOption('--build-libparser-only', dest='build_libparser_only'),
SetTrueOption('--skstresstester', dest='build_skstresstester'),
+ SetTrueOption('--swiftformat', dest='build_swiftformat'),
SetTrueOption('--swiftevolve', dest='build_swiftevolve'),
SetTrueOption('-B', dest='benchmark'),
SetTrueOption('-S', dest='skip_build'),
@@ -592,6 +595,7 @@ class BuildScriptImplOption(_BaseOption):
DisableOption('--skip-test-indexstore-db', dest='test_indexstoredb'),
DisableOption('--skip-test-sourcekit-lsp', dest='test_sourcekitlsp'),
DisableOption('--skip-test-skstresstester', dest='test_skstresstester'),
+ DisableOption('--skip-test-swiftformat', dest='test_swiftformat'),
DisableOption('--skip-test-swiftevolve', dest='test_swiftevolve'),
DisableOption('--skip-test-toolchain-benchmarks',
dest='test_toolchainbenchmarks'),
diff --git a/utils/swift_build_support/swift_build_support/products/__init__.py b/utils/swift_build_support/swift_build_support/products/__init__.py
index 18bbd2b3fe9bc..b39d9e5f2cffb 100644
--- a/utils/swift_build_support/swift_build_support/products/__init__.py
+++ b/utils/swift_build_support/swift_build_support/products/__init__.py
@@ -27,6 +27,7 @@
from .sourcekitlsp import SourceKitLSP
from .swift import Swift
from .swiftevolve import SwiftEvolve
+from .swiftformat import SwiftFormat
from .swiftinspect import SwiftInspect
from .swiftpm import SwiftPM
from .swiftsyntax import SwiftSyntax
@@ -48,6 +49,7 @@
'PlaygroundSupport',
'PythonKit',
'Swift',
+ 'SwiftFormat',
'SwiftInspect',
'SwiftPM',
'TensorFlowSwiftAPIs',
diff --git a/utils/swift_build_support/swift_build_support/products/swiftformat.py b/utils/swift_build_support/swift_build_support/products/swiftformat.py
new file mode 100644
index 0000000000000..ae6323cddadf8
--- /dev/null
+++ b/utils/swift_build_support/swift_build_support/products/swiftformat.py
@@ -0,0 +1,100 @@
+# swift_build_support/products/swiftformat.py -----------------*- python -*-
+#
+# This source file is part of the Swift.org open source project
+#
+# Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
+# Licensed under Apache License v2.0 with Runtime Library Exception
+#
+# See https://swift.org/LICENSE.txt for license information
+# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+#
+# ----------------------------------------------------------------------------
+
+import os
+
+from build_swift.build_swift.constants import MULTIROOT_DATA_FILE_PATH
+
+from . import cmark
+from . import foundation
+from . import libcxx
+from . import libdispatch
+from . import libicu
+from . import llbuild
+from . import llvm
+from . import product
+from . import swift
+from . import swiftpm
+from . import swiftsyntax
+from . import xctest
+from .. import shell
+
+
+class SwiftFormat(product.Product):
+ @classmethod
+ def product_source_name(cls):
+ """product_source_name() -> str
+
+ The name of the source code directory of this product.
+ """
+ return "swift-format"
+
+ @classmethod
+ def is_build_script_impl_product(cls):
+ return False
+
+ @classmethod
+ def is_swiftpm_unified_build_product(cls):
+ return True
+
+ def run_build_script_helper(self, action, additional_params=[]):
+ script_path = os.path.join(
+ self.source_dir, 'build-script-helper.py')
+
+ configuration = 'release' if self.is_release() else 'debug'
+
+ helper_cmd = [
+ script_path,
+ action,
+ '--toolchain', self.install_toolchain_path(),
+ '--configuration', configuration,
+ '--build-path', self.build_dir,
+ '--multiroot-data-file', MULTIROOT_DATA_FILE_PATH,
+ # There might have been a Package.resolved created by other builds
+ # or by the package being opened using Xcode. Discard that and
+ # reset the dependencies to be local.
+ '--update'
+ ]
+ if self.args.verbose_build:
+ helper_cmd.append('--verbose')
+ helper_cmd.extend(additional_params)
+
+ shell.call(helper_cmd)
+
+ def should_build(self, host_target):
+ return True
+
+ def build(self, host_target):
+ self.run_build_script_helper('build')
+
+ def should_test(self, host_target):
+ return self.args.test_swiftformat
+
+ def test(self, host_target):
+ self.run_build_script_helper('test')
+
+ def should_install(self, host_target):
+ return False
+
+ @classmethod
+ def get_dependencies(cls):
+ return [cmark.CMark,
+ llvm.LLVM,
+ libcxx.LibCXX,
+ libicu.LibICU,
+ swift.Swift,
+ libdispatch.LibDispatch,
+ foundation.Foundation,
+ xctest.XCTest,
+ llbuild.LLBuild,
+ swiftpm.SwiftPM,
+ swiftsyntax.SwiftSyntax]