Skip to content

Commit 470b634

Browse files
authored
Merge pull request #207 from dylansturg/build_script
Support building swift-format as part of Swift
2 parents 2107603 + 3613bc0 commit 470b634

File tree

5 files changed

+203
-34
lines changed

5 files changed

+203
-34
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
.build/
22
.swiftpm/
33
swift-format.xcodeproj/
4+
Package.resolved
5+

Package.resolved

-25
This file was deleted.

Package.swift

+20-8
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313

1414
import PackageDescription
1515

16+
#if os(Linux)
17+
import Glibc
18+
#else
19+
import Darwin.C
20+
#endif
21+
1622
let package = Package(
1723
name: "swift-format",
1824
products: [
@@ -21,14 +27,6 @@ let package = Package(
2127
.library(name: "SwiftFormatConfiguration", targets: ["SwiftFormatConfiguration"]),
2228
],
2329
dependencies: [
24-
.package(
25-
url: "https://github.com/apple/swift-syntax",
26-
.revision("swift-DEVELOPMENT-SNAPSHOT-2020-04-19-a")
27-
),
28-
.package(
29-
url: "https://github.com/apple/swift-argument-parser.git",
30-
.upToNextMinor(from: "0.0.4")
31-
),
3230
],
3331
targets: [
3432
.target(
@@ -134,3 +132,17 @@ let package = Package(
134132
),
135133
]
136134
)
135+
136+
137+
if getenv("SWIFTCI_USE_LOCAL_DEPS") == nil {
138+
// Building standalone.
139+
package.dependencies += [
140+
.package(url: "https://github.com/apple/swift-syntax", .branch("master")),
141+
.package(url: "https://github.com/apple/swift-argument-parser.git", .branch("master")),
142+
]
143+
} else {
144+
package.dependencies += [
145+
.package(path: "../swift-syntax"),
146+
.package(path: "../swift-argument-parser"),
147+
]
148+
}

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ is also expressed in the `SwiftSyntax` dependency in
2525

2626
| Xcode Release | Swift Version | `swift-format` Branch |
2727
|:-------------:|:---------------------------------------:|:----------------------|
28-
|| swift-DEVELOPMENT-SNAPSHOT-2020-04-19-a | `master` |
28+
|| Swift at `master` | `master` |
2929
| Xcode 11.4 | Swift 5.2 | `swift-5.2-branch` |
3030
| Xcode 11.0 | Swift 5.1 | `swift-5.1-branch` |
3131

build-script-helper.py

+180
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
#!/usr/bin/env python
2+
3+
"""
4+
This source file is part of the Swift.org open source project
5+
Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
6+
Licensed under Apache License v2.0 with Runtime Library Exception
7+
See https://swift.org/LICENSE.txt for license information
8+
See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
9+
------------------------------------------------------------------------------
10+
This is a helper script for the main swift repository's build-script.py that
11+
knows how to build and install the stress tester utilities given a swift
12+
workspace.
13+
"""
14+
15+
from __future__ import print_function
16+
17+
import argparse
18+
import sys
19+
import os, platform
20+
import subprocess
21+
22+
def printerr(message):
23+
print(message, file=sys.stderr)
24+
25+
def main(argv_prefix = []):
26+
args = parse_args(argv_prefix + sys.argv[1:])
27+
run(args)
28+
29+
def parse_args(args):
30+
parser = argparse.ArgumentParser(prog='build-script-helper.py')
31+
32+
parser.add_argument('--package-path', default='')
33+
parser.add_argument('-v', '--verbose', action='store_true', help='log executed commands')
34+
parser.add_argument('--prefix', help='install path')
35+
parser.add_argument('--configuration', default='debug')
36+
parser.add_argument('--build-path', default=None)
37+
parser.add_argument('--multiroot-data-file', help='Path to an Xcode workspace to create a unified build of SwiftSyntax with other projects.')
38+
parser.add_argument('--toolchain', required=True, help='the toolchain to use when building this package')
39+
parser.add_argument('--update', action='store_true', help='update all SwiftPM dependencies')
40+
parser.add_argument('--no-local-deps', action='store_true', help='use normal remote dependencies when building')
41+
parser.add_argument('build_actions', help="Extra actions to perform. Can be any number of the following", choices=['all', 'build', 'test', 'generate-xcodeproj'], nargs="*", default=['build'])
42+
43+
parsed = parser.parse_args(args)
44+
45+
parsed.swift_exec = os.path.join(parsed.toolchain, 'bin', 'swift')
46+
47+
# Convert package_path to absolute path, relative to root of repo.
48+
repo_path = os.path.dirname(__file__)
49+
parsed.package_path = os.path.realpath(
50+
os.path.join(repo_path, parsed.package_path))
51+
52+
if not parsed.build_path:
53+
parsed.build_path = os.path.join(parsed.package_path, '.build')
54+
55+
return parsed
56+
57+
def run(args):
58+
package_name = os.path.basename(args.package_path)
59+
60+
env = dict(os.environ)
61+
# Use local dependencies (i.e. checked out next swift-format).
62+
if not args.no_local_deps:
63+
env['SWIFTCI_USE_LOCAL_DEPS'] = "1"
64+
65+
if args.update:
66+
print("** Updating dependencies of %s **" % package_name)
67+
try:
68+
update_swiftpm_dependencies(package_path=args.package_path,
69+
swift_exec=args.swift_exec,
70+
build_path=args.build_path,
71+
env=env,
72+
verbose=args.verbose)
73+
except subprocess.CalledProcessError as e:
74+
printerr('FAIL: Updating dependencies of %s failed' % package_name)
75+
printerr('Executing: %s' % ' '.join(e.cmd))
76+
sys.exit(1)
77+
78+
# The test action creates its own build. No need to build if we are just testing.
79+
if should_run_action('build', args.build_actions):
80+
print("** Building %s **" % package_name)
81+
try:
82+
invoke_swift(package_path=args.package_path,
83+
swift_exec=args.swift_exec,
84+
action='build',
85+
products=['swift-format'],
86+
build_path=args.build_path,
87+
multiroot_data_file=args.multiroot_data_file,
88+
configuration=args.configuration,
89+
env=env,
90+
verbose=args.verbose)
91+
except subprocess.CalledProcessError as e:
92+
printerr('FAIL: Building %s failed' % package_name)
93+
printerr('Executing: %s' % ' '.join(e.cmd))
94+
sys.exit(1)
95+
96+
output_dir = os.path.realpath(os.path.join(args.build_path, args.configuration))
97+
98+
if should_run_action("generate-xcodeproj", args.build_actions):
99+
print("** Generating Xcode project for %s **" % package_name)
100+
try:
101+
generate_xcodeproj(args.package_path,
102+
swift_exec=args.swift_exec,
103+
env=env,
104+
verbose=args.verbose)
105+
except subprocess.CalledProcessError as e:
106+
printerr('FAIL: Generating the Xcode project failed')
107+
printerr('Executing: %s' % ' '.join(e.cmd))
108+
sys.exit(1)
109+
110+
if should_run_action("test", args.build_actions):
111+
print("** Testing %s **" % package_name)
112+
try:
113+
invoke_swift(package_path=args.package_path,
114+
swift_exec=args.swift_exec,
115+
action='test',
116+
products=['%sPackageTests' % package_name],
117+
build_path=args.build_path,
118+
multiroot_data_file=args.multiroot_data_file,
119+
configuration=args.configuration,
120+
env=env,
121+
verbose=args.verbose)
122+
except subprocess.CalledProcessError as e:
123+
printerr('FAIL: Testing %s failed' % package_name)
124+
printerr('Executing: %s' % ' '.join(e.cmd))
125+
sys.exit(1)
126+
127+
def should_run_action(action_name, selected_actions):
128+
if action_name in selected_actions:
129+
return True
130+
elif "all" in selected_actions:
131+
return True
132+
else:
133+
return False
134+
135+
def update_swiftpm_dependencies(package_path, swift_exec, build_path, env, verbose):
136+
args = [swift_exec, 'package', '--package-path', package_path, '--build-path', build_path, 'update']
137+
check_call(args, env=env, verbose=verbose)
138+
139+
def invoke_swift(package_path, swift_exec, action, products, build_path, multiroot_data_file, configuration, env, verbose):
140+
# Until rdar://53881101 is implemented, we cannot request a build of multiple
141+
# targets simultaneously. For now, just build one product after the other.
142+
for product in products:
143+
invoke_swift_single_product(package_path, swift_exec, action, product, build_path, multiroot_data_file, configuration, env, verbose)
144+
145+
def invoke_swift_single_product(package_path, swift_exec, action, product, build_path, multiroot_data_file, configuration, env, verbose):
146+
args = [swift_exec, action, '--package-path', package_path, '-c', configuration, '--build-path', build_path]
147+
if platform.system() != "Darwin":
148+
args.extend(["--enable-test-discovery"])
149+
if multiroot_data_file:
150+
args.extend(['--multiroot-data-file', multiroot_data_file])
151+
if action == 'test':
152+
args.extend(['--test-product', product])
153+
else:
154+
args.extend(['--product', product])
155+
156+
# Tell SwiftSyntax that we are building in a build-script environment so that
157+
# it does not need to be rebuilt if it has already been built before.
158+
env['SWIFT_BUILD_SCRIPT_ENVIRONMENT'] = '1'
159+
160+
check_call(args, env=env, verbose=verbose)
161+
162+
def generate_xcodeproj(package_path, swift_exec, env, verbose):
163+
package_name = os.path.basename(package_path)
164+
xcodeproj_path = os.path.join(package_path, '%s.xcodeproj' % package_name)
165+
args = [swift_exec, 'package', '--package-path', package_path, 'generate-xcodeproj', '--output', xcodeproj_path]
166+
check_call(args, env=env, verbose=verbose)
167+
168+
def check_call(cmd, verbose, env=os.environ, **kwargs):
169+
if verbose:
170+
print(' '.join([escape_cmd_arg(arg) for arg in cmd]))
171+
return subprocess.check_call(cmd, env=env, stderr=subprocess.STDOUT, **kwargs)
172+
173+
def escape_cmd_arg(arg):
174+
if '"' in arg or ' ' in arg:
175+
return '"%s"' % arg.replace('"', '\\"')
176+
else:
177+
return arg
178+
179+
if __name__ == '__main__':
180+
main()

0 commit comments

Comments
 (0)