Skip to content

[utils] Introduce swift_build_support.diagnostics. #2830

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 18 additions & 33 deletions utils/SwiftBuildSupport.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@
import configparser as ConfigParser

import os
import pipes
import platform
import subprocess
import sys

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

# E402 means module level import not at top of file
from swift_build_support import diagnostics # noqa (E402)
from swift_build_support import shell # noqa (E402)


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

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


def print_with_argv0(message):
print(sys.argv[0] + ": " + message)
sys.stdout.flush()


def quote_shell_command(args):
return " ".join([pipes.quote(a) for a in args])


def check_call(args, print_command=False, verbose=False, disable_sleep=False):
if disable_sleep:
if platform.system() == 'Darwin':
Expand All @@ -82,50 +78,41 @@ def check_call(args, print_command=False, verbose=False, disable_sleep=False):
args.insert(0, "caffeinate")

if print_command:
print(os.getcwd() + "$ " + quote_shell_command(args))
print(os.getcwd() + "$ " + shell.quote_command(args))
sys.stdout.flush()
try:
return subprocess.check_call(args)
except subprocess.CalledProcessError as e:
print_with_argv0(
diagnostics.fatal(
"command terminated with a non-zero exit status " +
str(e.returncode) + ", aborting")
sys.stdout.flush()
sys.exit(1)
except OSError as e:
print_with_argv0(
"could not execute '" + quote_shell_command(args) +
diagnostics.fatal(
"could not execute '" + shell.quote_command(args) +
"': " + e.strerror)
sys.stdout.flush()
sys.exit(1)


def check_output(args, print_command=False, verbose=False):
if print_command:
print(os.getcwd() + "$ " + quote_shell_command(args))
print(os.getcwd() + "$ " + shell.quote_command(args))
sys.stdout.flush()
try:
return subprocess.check_output(args)
except subprocess.CalledProcessError as e:
print_with_argv0(
diagnostics.fatal(
"command terminated with a non-zero exit status " +
str(e.returncode) + ", aborting")
sys.stdout.flush()
sys.exit(1)
except OSError as e:
print_with_argv0(
"could not execute '" + quote_shell_command(args) +
diagnostics.fatal(
"could not execute '" + shell.quote_command(args) +
"': " + e.strerror)
sys.stdout.flush()
sys.exit(1)


def _load_preset_files_impl(preset_file_names, substitutions={}):
config = ConfigParser.SafeConfigParser(substitutions, allow_no_value=True)
if config.read(preset_file_names) == []:
print_with_argv0(
diagnostics.fatal(
"preset file not found (tried " + str(preset_file_names) + ")")
sys.exit(1)
return config


Expand Down Expand Up @@ -190,12 +177,10 @@ def get_preset_options(substitutions, preset_file_names, preset_name):
(build_script_opts, build_script_impl_opts, missing_opts) = \
_get_preset_options_impl(config, substitutions, preset_name)
if not build_script_opts and not build_script_impl_opts:
print_with_argv0("preset '" + preset_name + "' not found")
sys.exit(1)
diagnostics.fatal("preset '" + preset_name + "' not found")
if missing_opts:
print_with_argv0("missing option(s) for preset '" + preset_name +
"': " + ", ".join(missing_opts))
sys.exit(1)
diagnostics.fatal("missing option(s) for preset '" + preset_name +
"': " + ", ".join(missing_opts))

# Migrate 'swift-sdks' parameter to 'stdlib-deployment-targets'
for opt in build_script_impl_opts:
Expand Down
66 changes: 27 additions & 39 deletions utils/build-script
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,13 @@ from SwiftBuildSupport import (
check_call,
get_all_preset_names,
get_preset_options,
print_with_argv0,
quote_shell_command,
) # noqa (E402 module level import not at top of file)

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

# E402 means module level import not at top of file
from swift_build_support import arguments # noqa (E402)
from swift_build_support import diagnostics # noqa (E402)
from swift_build_support.toolchain import host_toolchain # noqa (E402)
import swift_build_support.debug # noqa (E402)
from swift_build_support import migration # noqa (E402)
Expand Down Expand Up @@ -103,8 +102,7 @@ def main_preset():
return 0

if not args.preset:
print_with_argv0("Missing --preset option")
return 1
diagnostics.fatal("missing --preset option")

args.preset_substitutions = {}

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

print_with_argv0(
diagnostics.note(
"using preset '" + args.preset + "', which expands to \n\n" +
quote_shell_command(build_script_args) + "\n")
shell.quote_command(build_script_args) + "\n")

check_call(build_script_args, disable_sleep=True)

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

if toolchain.cc is None or toolchain.cxx is None:
print_with_argv0(
"Can't find clang. Please install clang-3.5 or a later version.")
return 1
diagnostics.fatal(
"can't find clang (please install clang-3.5 or a later version)")

if toolchain.cmake is None:
print_with_argv0("Can't find CMake. Please install CMake.")
return 1
diagnostics.fatal("can't find CMake (please install CMake)")

if args.distcc:
if toolchain.distcc is None:
print_with_argv0(
"Can't find distcc. Please install distcc")
return 1
diagnostics.fatal(
"can't find distcc (please install distcc)")
if toolchain.distcc_pump is None:
print_with_argv0(
"Can't find distcc-pump. Please install distcc-pump")
return 1
diagnostics.fatal(
"can't find distcc-pump (please install distcc-pump)")

if args.host_target is None or args.stdlib_deployment_targets is None:
print_with_argv0("Unknown operating system.")
return 1
diagnostics.fatal("unknown operating system")

if args.symbols_package:
if not os.path.isabs(args.symbols_package):
Expand All @@ -1025,10 +1018,9 @@ details of the setups of other systems or automated environments.""")
'(was \'{}\')'.format(args.symbols_package))
return 1
if not args.install_symroot:
print_with_argv0(
diagnostics.fatal(
"--install-symroot is required when specifying "
"--symbols-package.")
return 1

if args.android:
if args.android_ndk is None or \
Expand All @@ -1037,12 +1029,11 @@ details of the setups of other systems or automated environments.""")
args.android_icu_uc_include is None or \
args.android_icu_i18n is None or \
args.android_icu_i18n_include is None:
print_with_argv0("When building for Android, --android-ndk, "
"--android-ndk-version, --android-icu-uc, "
"--android-icu-uc-include, --android-icu-i18n, "
"and --android-icu-i18n-include must be "
"specified.")
return 1
diagnostics.fatal("when building for Android, --android-ndk, "
"--android-ndk-version, --android-icu-uc, "
"--android-icu-uc-include, --android-icu-i18n, "
"and --android-icu-i18n-include must be "
"specified")

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

if args.build_ninja:
if not os.path.exists(workspace.source_dir("ninja")):
print_with_argv0("Can't find source directory for ninja "
"(tried %s)" % (workspace.source_dir("ninja")))
return 1
diagnostics.fatal("can't find source directory for ninja "
"(tried %s)" % (workspace.source_dir("ninja")))

os.umask(0o022)

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

def main():
if not SWIFT_SOURCE_ROOT:
print_with_argv0(
"Could not infer source root directory. " +
"Forgot to set $SWIFT_SOURCE_ROOT environment variable?")
return 1
diagnostics.fatal(
"could not infer source root directory " +
"(forgot to set $SWIFT_SOURCE_ROOT environment variable?)")

if not os.path.isdir(SWIFT_SOURCE_ROOT):
print_with_argv0(
"Source root directory \'" + SWIFT_SOURCE_ROOT +
"\' does not exist. " +
"Forgot to set $SWIFT_SOURCE_ROOT environment variable?")
return 1
diagnostics.fatal(
"source root directory \'" + SWIFT_SOURCE_ROOT +
"\' does not exist " +
"(forgot to set $SWIFT_SOURCE_ROOT environment variable?)")

# Determine if we are invoked in the preset mode and dispatch accordingly.
if any([(opt.startswith("--preset") or opt == "--show-presets")
Expand Down
2 changes: 1 addition & 1 deletion utils/swift_build_support/swift_build_support/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# ----------------------------------------------------------------------------
"""
argparse suppliments
argparse supplements
"""
# ----------------------------------------------------------------------------

Expand Down
32 changes: 32 additions & 0 deletions utils/swift_build_support/swift_build_support/diagnostics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# swift_build_support/diagnostics.py - Diagnostic Utilities -*- python -*-
#
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2016 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See http://swift.org/LICENSE.txt for license information
# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
#
# ----------------------------------------------------------------------------

import sys


def note(message):
"""
note(message)

Print a diagnostic notification to the standard output.
"""
print(sys.argv[0] + ": note: " + message)
sys.stdout.flush()


def fatal(message):
"""
fatal(message)

Raise a fatal error.
"""
raise SystemExit(sys.argv[0] + ": fatal error: " + message)
9 changes: 9 additions & 0 deletions utils/swift_build_support/swift_build_support/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ def _quote(arg):
return pipes.quote(str(arg))


def quote_command(args):
"""
quote_command(args) -> str

Quote the command for passing to a shell.
"""
return ' '.join([_quote(a) for a in args])


def _coerce_dry_run(dry_run_override):
if dry_run_override is None:
return dry_run
Expand Down
3 changes: 3 additions & 0 deletions utils/swift_build_support/tests/test_shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ def tearDown(self):
if os.path.exists(self.tmpdir):
shutil.rmtree(self.tmpdir)

def test_quote_command(self):
self.assertEqual(shell.quote_command(["a b", "", "c"]), "'a b' '' c")

def test_call(self):
shell.dry_run = False
foo_file = os.path.join(self.tmpdir, 'foo.txt')
Expand Down