mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
I've only implemented this for OS X, which comes with the 'caffeinate' command. If anyone would like to implement something similar for Linux, feel free. (Although please make sure that it's signal-safe, i.e. if the build is interrupted the computer's sleep settings return to normal.)
221 lines
6.8 KiB
Python
221 lines
6.8 KiB
Python
# utils/SwiftBuildSupport.py - Utilities for Swift build scripts -*- python -*-
|
|
#
|
|
# This source file is part of the Swift.org open source project
|
|
#
|
|
# Copyright (c) 2014 - 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
|
|
|
|
from __future__ import print_function
|
|
|
|
try:
|
|
# Python 2
|
|
import ConfigParser
|
|
except ImportError:
|
|
# Python 3
|
|
import configparser as ConfigParser
|
|
|
|
import os
|
|
import pipes
|
|
import platform
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
HOME = os.environ.get("HOME", "/")
|
|
|
|
|
|
def _get_default_source_root():
|
|
result = ""
|
|
|
|
# Are we in a Swift checkout? Start from this file and check its parent
|
|
# directories.
|
|
#
|
|
# $SWIFT_SOURCE_ROOT/swift/utils/SwiftBuildSupport.py
|
|
(swift_path, parent_dirname) = os.path.split(os.path.dirname(__file__))
|
|
if parent_dirname != "utils":
|
|
return result
|
|
if not os.path.exists(os.path.join(swift_path, 'CMakeLists.txt')):
|
|
return result
|
|
result = os.path.dirname(swift_path)
|
|
|
|
# Are we in an LLVM checkout? Start from the Swift checkout and check /its/
|
|
# parent directories.
|
|
#
|
|
# $SWIFT_SOURCE_ROOT/llvm/tools/swift/utils/SwiftBuildSupport.py
|
|
(llvm_path, parent_dirname) = os.path.split(result)
|
|
if parent_dirname != "tools":
|
|
return result
|
|
if not os.path.exists(os.path.join(llvm_path, 'CMakeLists.txt')):
|
|
return result
|
|
result = os.path.dirname(llvm_path)
|
|
|
|
return result
|
|
|
|
# Set SWIFT_SOURCE_ROOT in your environment to control where the sources
|
|
# are found.
|
|
SWIFT_SOURCE_ROOT = os.environ.get(
|
|
"SWIFT_SOURCE_ROOT", _get_default_source_root())
|
|
|
|
# Set SWIFT_BUILD_ROOT to a directory that will contain a subdirectory
|
|
# for each build configuration
|
|
SWIFT_BUILD_ROOT = os.environ.get(
|
|
"SWIFT_BUILD_ROOT", os.path.join(SWIFT_SOURCE_ROOT, "build"))
|
|
|
|
|
|
def print_with_argv0(message):
|
|
print(sys.argv[0] + ": " + message)
|
|
|
|
|
|
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':
|
|
# Don't mutate the caller's copy of the arguments.
|
|
args = list(args)
|
|
args.insert(0, "caffeinate")
|
|
|
|
if print_command:
|
|
print(os.getcwd() + "$ " + quote_shell_command(args))
|
|
try:
|
|
return subprocess.check_call(args)
|
|
except subprocess.CalledProcessError as e:
|
|
print_with_argv0(
|
|
"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) +
|
|
"': " + 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))
|
|
try:
|
|
return subprocess.check_output(args)
|
|
except subprocess.CalledProcessError as e:
|
|
print_with_argv0(
|
|
"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) +
|
|
"': " + 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(
|
|
"preset file not found (tried " + str(preset_file_names) + ")")
|
|
sys.exit(1)
|
|
return config
|
|
|
|
|
|
_PRESET_PREFIX = "preset: "
|
|
|
|
|
|
def _get_preset_options_impl(config, substitutions, preset_name):
|
|
section_name = _PRESET_PREFIX + preset_name
|
|
if section_name not in config.sections():
|
|
return (None, None, None)
|
|
|
|
build_script_opts = []
|
|
build_script_impl_opts = []
|
|
missing_opts = []
|
|
dash_dash_seen = False
|
|
|
|
for o in config.options(section_name):
|
|
try:
|
|
a = config.get(section_name, o)
|
|
except ConfigParser.InterpolationMissingOptionError as e:
|
|
# e.reference contains the correctly formatted option
|
|
missing_opts.append(e.reference)
|
|
continue
|
|
|
|
if not a:
|
|
a = ""
|
|
|
|
if o in substitutions:
|
|
continue
|
|
|
|
opt = None
|
|
if o == "mixin-preset":
|
|
# Split on newlines and filter out empty lines.
|
|
mixins = filter(None, [m.strip() for m in a.splitlines()])
|
|
for mixin in mixins:
|
|
(base_build_script_opts,
|
|
base_build_script_impl_opts,
|
|
base_missing_opts) = \
|
|
_get_preset_options_impl(config, substitutions, mixin)
|
|
build_script_opts += base_build_script_opts
|
|
build_script_impl_opts += base_build_script_impl_opts
|
|
missing_opts += base_missing_opts
|
|
elif o == "dash-dash":
|
|
dash_dash_seen = True
|
|
elif a == "":
|
|
opt = "--" + o
|
|
else:
|
|
opt = "--" + o + "=" + a
|
|
|
|
if opt:
|
|
if not dash_dash_seen:
|
|
build_script_opts.append(opt)
|
|
else:
|
|
build_script_impl_opts.append(opt)
|
|
|
|
return (build_script_opts, build_script_impl_opts, missing_opts)
|
|
|
|
|
|
def get_preset_options(substitutions, preset_file_names, preset_name):
|
|
config = _load_preset_files_impl(preset_file_names, substitutions)
|
|
|
|
(build_script_opts, build_script_impl_opts, missing_opts) = \
|
|
_get_preset_options_impl(config, substitutions, preset_name)
|
|
if not build_script_opts:
|
|
print_with_argv0("preset '" + preset_name + "' not found")
|
|
sys.exit(1)
|
|
if missing_opts:
|
|
print_with_argv0("missing option(s) for preset '" + preset_name +
|
|
"': " + ", ".join(missing_opts))
|
|
sys.exit(1)
|
|
|
|
return build_script_opts + ["--"] + build_script_impl_opts
|
|
|
|
|
|
def get_all_preset_names(preset_file_names):
|
|
config = _load_preset_files_impl(preset_file_names)
|
|
return [name[len(_PRESET_PREFIX):] for name in config.sections()
|
|
if name.startswith(_PRESET_PREFIX)]
|
|
|
|
|
|
# A context manager for changing the current working directory.
|
|
#
|
|
# with WorkingDirectory('/tmp'):
|
|
# ... do work in /tmp...
|
|
class WorkingDirectory(object):
|
|
|
|
def __init__(self, new_cwd):
|
|
self.new_cwd = new_cwd
|
|
|
|
def __enter__(self):
|
|
self.old_cwd = os.getcwd()
|
|
os.chdir(self.new_cwd)
|
|
|
|
def __exit__(self, type, value, traceback):
|
|
os.chdir(self.old_cwd)
|