#===--- SwiftBuildSupport.py - Utilities for Swift build scripts -----------===# # # This source file is part of the Swift.org open source project # # Copyright (c) 2014 - 2015 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 import ConfigParser import os import pipes import subprocess import sys HOME = os.environ["HOME"] def _get_default_source_root(): # Default to ~/src/s for historical reasons. result = os.path.join(HOME, "src", "s") # Are we in a Swift checkout? $SWIFT_SOURCE_ROOT/swift/utils/ (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? $SWIFT_SOURCE_ROOT/llvm/tools/swift/utils/ (llvm_path, root_dirname) = os.path.split(result) if root_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 bad_usage(message): print_with_argv0(message) print("Run '" + pipes.quote(sys.argv[0]) + " --help' for more information.") sys.exit(1) def quote_shell_command(args): return " ".join([ pipes.quote(a) for a in args ]) def check_call(args, print_command=False, verbose=False): if print_command: print(os.getcwd() + "$ " + quote_shell_command(args)) try: return subprocess.check_call(args) except subprocess.CalledProcessError as e: if verbose: print_with_argv0(e.strerror) else: 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: if verbose: print_with_argv0(e.strerror) else: 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) build_script_opts = [] build_script_impl_opts = [] dash_dash_seen = False for o, a in config.items(section_name): 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) = \ _get_preset_options_impl(config, substitutions, mixin) build_script_opts += base_build_script_opts build_script_impl_opts += base_build_script_impl_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) 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) = \ _get_preset_options_impl(config, substitutions, preset_name) if build_script_opts is None: print_with_argv0("preset '" + preset_name + "' not found") 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)