Skip to content

Commit 24885e4

Browse files
committed
Merge pull request #2830 from ddunbar/introduce-swift_build_support-diagnostics-module
[utils] Introduce swift_build_support.diagnostics.
2 parents 1e94e3f + ad9f12d commit 24885e4

File tree

6 files changed

+90
-73
lines changed

6 files changed

+90
-73
lines changed

utils/SwiftBuildSupport.py

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,16 @@
1818
import configparser as ConfigParser
1919

2020
import os
21-
import pipes
2221
import platform
2322
import subprocess
2423
import sys
2524

25+
sys.path.append(os.path.join(os.path.dirname(__file__), 'swift_build_support'))
26+
27+
# E402 means module level import not at top of file
28+
from swift_build_support import diagnostics # noqa (E402)
29+
from swift_build_support import shell # noqa (E402)
30+
2631

2732
HOME = os.environ.get("HOME", "/")
2833

@@ -65,15 +70,6 @@ def _get_default_source_root():
6570
"SWIFT_BUILD_ROOT", os.path.join(SWIFT_SOURCE_ROOT, "build"))
6671

6772

68-
def print_with_argv0(message):
69-
print(sys.argv[0] + ": " + message)
70-
sys.stdout.flush()
71-
72-
73-
def quote_shell_command(args):
74-
return " ".join([pipes.quote(a) for a in args])
75-
76-
7773
def check_call(args, print_command=False, verbose=False, disable_sleep=False):
7874
if disable_sleep:
7975
if platform.system() == 'Darwin':
@@ -82,50 +78,41 @@ def check_call(args, print_command=False, verbose=False, disable_sleep=False):
8278
args.insert(0, "caffeinate")
8379

8480
if print_command:
85-
print(os.getcwd() + "$ " + quote_shell_command(args))
81+
print(os.getcwd() + "$ " + shell.quote_command(args))
8682
sys.stdout.flush()
8783
try:
8884
return subprocess.check_call(args)
8985
except subprocess.CalledProcessError as e:
90-
print_with_argv0(
86+
diagnostics.fatal(
9187
"command terminated with a non-zero exit status " +
9288
str(e.returncode) + ", aborting")
93-
sys.stdout.flush()
94-
sys.exit(1)
9589
except OSError as e:
96-
print_with_argv0(
97-
"could not execute '" + quote_shell_command(args) +
90+
diagnostics.fatal(
91+
"could not execute '" + shell.quote_command(args) +
9892
"': " + e.strerror)
99-
sys.stdout.flush()
100-
sys.exit(1)
10193

10294

10395
def check_output(args, print_command=False, verbose=False):
10496
if print_command:
105-
print(os.getcwd() + "$ " + quote_shell_command(args))
97+
print(os.getcwd() + "$ " + shell.quote_command(args))
10698
sys.stdout.flush()
10799
try:
108100
return subprocess.check_output(args)
109101
except subprocess.CalledProcessError as e:
110-
print_with_argv0(
102+
diagnostics.fatal(
111103
"command terminated with a non-zero exit status " +
112104
str(e.returncode) + ", aborting")
113-
sys.stdout.flush()
114-
sys.exit(1)
115105
except OSError as e:
116-
print_with_argv0(
117-
"could not execute '" + quote_shell_command(args) +
106+
diagnostics.fatal(
107+
"could not execute '" + shell.quote_command(args) +
118108
"': " + e.strerror)
119-
sys.stdout.flush()
120-
sys.exit(1)
121109

122110

123111
def _load_preset_files_impl(preset_file_names, substitutions={}):
124112
config = ConfigParser.SafeConfigParser(substitutions, allow_no_value=True)
125113
if config.read(preset_file_names) == []:
126-
print_with_argv0(
114+
diagnostics.fatal(
127115
"preset file not found (tried " + str(preset_file_names) + ")")
128-
sys.exit(1)
129116
return config
130117

131118

@@ -190,12 +177,10 @@ def get_preset_options(substitutions, preset_file_names, preset_name):
190177
(build_script_opts, build_script_impl_opts, missing_opts) = \
191178
_get_preset_options_impl(config, substitutions, preset_name)
192179
if not build_script_opts and not build_script_impl_opts:
193-
print_with_argv0("preset '" + preset_name + "' not found")
194-
sys.exit(1)
180+
diagnostics.fatal("preset '" + preset_name + "' not found")
195181
if missing_opts:
196-
print_with_argv0("missing option(s) for preset '" + preset_name +
197-
"': " + ", ".join(missing_opts))
198-
sys.exit(1)
182+
diagnostics.fatal("missing option(s) for preset '" + preset_name +
183+
"': " + ", ".join(missing_opts))
199184

200185
# Migrate 'swift-sdks' parameter to 'stdlib-deployment-targets'
201186
for opt in build_script_impl_opts:

utils/build-script

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,13 @@ from SwiftBuildSupport import (
3131
check_call,
3232
get_all_preset_names,
3333
get_preset_options,
34-
print_with_argv0,
35-
quote_shell_command,
3634
) # noqa (E402 module level import not at top of file)
3735

3836
sys.path.append(os.path.join(os.path.dirname(__file__), 'swift_build_support'))
3937

4038
# E402 means module level import not at top of file
4139
from swift_build_support import arguments # noqa (E402)
40+
from swift_build_support import diagnostics # noqa (E402)
4241
from swift_build_support.toolchain import host_toolchain # noqa (E402)
4342
import swift_build_support.debug # noqa (E402)
4443
from swift_build_support import migration # noqa (E402)
@@ -103,8 +102,7 @@ def main_preset():
103102
return 0
104103

105104
if not args.preset:
106-
print_with_argv0("Missing --preset option")
107-
return 1
105+
diagnostics.fatal("missing --preset option")
108106

109107
args.preset_substitutions = {}
110108

@@ -122,9 +120,9 @@ def main_preset():
122120
if args.distcc:
123121
build_script_args += ["--distcc"]
124122

125-
print_with_argv0(
123+
diagnostics.note(
126124
"using preset '" + args.preset + "', which expands to \n\n" +
127-
quote_shell_command(build_script_args) + "\n")
125+
shell.quote_command(build_script_args) + "\n")
128126

129127
check_call(build_script_args, disable_sleep=True)
130128

@@ -996,27 +994,22 @@ details of the setups of other systems or automated environments.""")
996994
toolchain.cmake = args.cmake
997995

998996
if toolchain.cc is None or toolchain.cxx is None:
999-
print_with_argv0(
1000-
"Can't find clang. Please install clang-3.5 or a later version.")
1001-
return 1
997+
diagnostics.fatal(
998+
"can't find clang (please install clang-3.5 or a later version)")
1002999

10031000
if toolchain.cmake is None:
1004-
print_with_argv0("Can't find CMake. Please install CMake.")
1005-
return 1
1001+
diagnostics.fatal("can't find CMake (please install CMake)")
10061002

10071003
if args.distcc:
10081004
if toolchain.distcc is None:
1009-
print_with_argv0(
1010-
"Can't find distcc. Please install distcc")
1011-
return 1
1005+
diagnostics.fatal(
1006+
"can't find distcc (please install distcc)")
10121007
if toolchain.distcc_pump is None:
1013-
print_with_argv0(
1014-
"Can't find distcc-pump. Please install distcc-pump")
1015-
return 1
1008+
diagnostics.fatal(
1009+
"can't find distcc-pump (please install distcc-pump)")
10161010

10171011
if args.host_target is None or args.stdlib_deployment_targets is None:
1018-
print_with_argv0("Unknown operating system.")
1019-
return 1
1012+
diagnostics.fatal("unknown operating system")
10201013

10211014
if args.symbols_package:
10221015
if not os.path.isabs(args.symbols_package):
@@ -1025,10 +1018,9 @@ details of the setups of other systems or automated environments.""")
10251018
'(was \'{}\')'.format(args.symbols_package))
10261019
return 1
10271020
if not args.install_symroot:
1028-
print_with_argv0(
1021+
diagnostics.fatal(
10291022
"--install-symroot is required when specifying "
10301023
"--symbols-package.")
1031-
return 1
10321024

10331025
if args.android:
10341026
if args.android_ndk is None or \
@@ -1037,12 +1029,11 @@ details of the setups of other systems or automated environments.""")
10371029
args.android_icu_uc_include is None or \
10381030
args.android_icu_i18n is None or \
10391031
args.android_icu_i18n_include is None:
1040-
print_with_argv0("When building for Android, --android-ndk, "
1041-
"--android-ndk-version, --android-icu-uc, "
1042-
"--android-icu-uc-include, --android-icu-i18n, "
1043-
"and --android-icu-i18n-include must be "
1044-
"specified.")
1045-
return 1
1032+
diagnostics.fatal("when building for Android, --android-ndk, "
1033+
"--android-ndk-version, --android-icu-uc, "
1034+
"--android-icu-uc-include, --android-icu-i18n, "
1035+
"and --android-icu-i18n-include must be "
1036+
"specified")
10461037

10471038
# Build cmark if any cmark-related options were specified.
10481039
if (args.cmark_build_variant is not None):
@@ -1214,9 +1205,8 @@ details of the setups of other systems or automated environments.""")
12141205

12151206
if args.build_ninja:
12161207
if not os.path.exists(workspace.source_dir("ninja")):
1217-
print_with_argv0("Can't find source directory for ninja "
1218-
"(tried %s)" % (workspace.source_dir("ninja")))
1219-
return 1
1208+
diagnostics.fatal("can't find source directory for ninja "
1209+
"(tried %s)" % (workspace.source_dir("ninja")))
12201210

12211211
os.umask(0o022)
12221212

@@ -1465,17 +1455,15 @@ details of the setups of other systems or automated environments.""")
14651455

14661456
def main():
14671457
if not SWIFT_SOURCE_ROOT:
1468-
print_with_argv0(
1469-
"Could not infer source root directory. " +
1470-
"Forgot to set $SWIFT_SOURCE_ROOT environment variable?")
1471-
return 1
1458+
diagnostics.fatal(
1459+
"could not infer source root directory " +
1460+
"(forgot to set $SWIFT_SOURCE_ROOT environment variable?)")
14721461

14731462
if not os.path.isdir(SWIFT_SOURCE_ROOT):
1474-
print_with_argv0(
1475-
"Source root directory \'" + SWIFT_SOURCE_ROOT +
1476-
"\' does not exist. " +
1477-
"Forgot to set $SWIFT_SOURCE_ROOT environment variable?")
1478-
return 1
1463+
diagnostics.fatal(
1464+
"source root directory \'" + SWIFT_SOURCE_ROOT +
1465+
"\' does not exist " +
1466+
"(forgot to set $SWIFT_SOURCE_ROOT environment variable?)")
14791467

14801468
# Determine if we are invoked in the preset mode and dispatch accordingly.
14811469
if any([(opt.startswith("--preset") or opt == "--show-presets")

utils/swift_build_support/swift_build_support/arguments.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#
1111
# ----------------------------------------------------------------------------
1212
"""
13-
argparse suppliments
13+
argparse supplements
1414
"""
1515
# ----------------------------------------------------------------------------
1616

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# swift_build_support/diagnostics.py - Diagnostic Utilities -*- python -*-
2+
#
3+
# This source file is part of the Swift.org open source project
4+
#
5+
# Copyright (c) 2016 Apple Inc. and the Swift project authors
6+
# Licensed under Apache License v2.0 with Runtime Library Exception
7+
#
8+
# See http://swift.org/LICENSE.txt for license information
9+
# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
#
11+
# ----------------------------------------------------------------------------
12+
13+
import sys
14+
15+
16+
def note(message):
17+
"""
18+
note(message)
19+
20+
Print a diagnostic notification to the standard output.
21+
"""
22+
print(sys.argv[0] + ": note: " + message)
23+
sys.stdout.flush()
24+
25+
26+
def fatal(message):
27+
"""
28+
fatal(message)
29+
30+
Raise a fatal error.
31+
"""
32+
raise SystemExit(sys.argv[0] + ": fatal error: " + message)

utils/swift_build_support/swift_build_support/shell.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ def _quote(arg):
2929
return pipes.quote(str(arg))
3030

3131

32+
def quote_command(args):
33+
"""
34+
quote_command(args) -> str
35+
36+
Quote the command for passing to a shell.
37+
"""
38+
return ' '.join([_quote(a) for a in args])
39+
40+
3241
def _coerce_dry_run(dry_run_override):
3342
if dry_run_override is None:
3443
return dry_run

utils/swift_build_support/tests/test_shell.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ def tearDown(self):
4242
if os.path.exists(self.tmpdir):
4343
shutil.rmtree(self.tmpdir)
4444

45+
def test_quote_command(self):
46+
self.assertEqual(shell.quote_command(["a b", "", "c"]), "'a b' '' c")
47+
4548
def test_call(self):
4649
shell.dry_run = False
4750
foo_file = os.path.join(self.tmpdir, 'foo.txt')

0 commit comments

Comments
 (0)