+++ /dev/null
-#!/usr/bin/python
-
-from __future__ import print_function
-
-import argparse
-import getpass
-import os
-import os.path
-import re
-import select
-import sys
-import subprocess
-
-_COMMON_SYNC_OPTS = "-avzh --delete"
-_COMMON_EXCLUDE_OPTS = "--exclude=DerivedData --exclude=.svn --exclude=.git --exclude=llvm-build/Release+Asserts"
-
-
-def normalize_configuration(config_text):
- if not config_text:
- return "debug"
-
- config_lower = config_text.lower()
- if config_lower in ["debug", "release"]:
- return config_lower
- else:
- raise Exception("unknown configuration specified: %s" % config_text)
-
-
-def parse_args():
- DEFAULT_REMOTE_ROOT_DIR = "/mnt/ssd/work/macosx.sync"
- DEFAULT_REMOTE_HOSTNAME = "tfiala2.mtv.corp.google.com"
- OPTIONS_FILENAME = ".remote-build.conf"
- DEFAULT_SSH_PORT = "22"
-
- parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
-
- parser.add_argument(
- "--configuration",
- "-c",
- help="specify configuration (Debug, Release)",
- default=normalize_configuration(
- os.environ.get(
- 'CONFIGURATION',
- 'Debug')))
- parser.add_argument(
- "--debug", "-d",
- action="store_true",
- help="help debug the remote-build script by adding extra logging")
- parser.add_argument(
- "--local-lldb-dir", "-l", metavar="DIR",
- help="specify local lldb directory (Xcode layout assumed for llvm/clang)",
- default=os.getcwd())
- parser.add_argument(
- "--port", "-p",
- help="specify the port ssh should use to connect to the remote side",
- default=DEFAULT_SSH_PORT)
- parser.add_argument(
- "--remote-address", "-r", metavar="REMOTE-ADDR",
- help="specify the dns name or ip address of the remote linux system",
- default=DEFAULT_REMOTE_HOSTNAME)
- parser.add_argument(
- "--remote-dir", metavar="DIR",
- help="specify the root of the linux source/build dir",
- default=DEFAULT_REMOTE_ROOT_DIR)
- parser.add_argument(
- "--user", "-u", help="specify the user name for the remote system",
- default=getpass.getuser())
- parser.add_argument(
- "--xcode-action",
- "-x",
- help="$(ACTION) from Xcode",
- nargs='?',
- default=None)
-
- command_line_args = sys.argv[1:]
- if os.path.exists(OPTIONS_FILENAME):
- # Prepend the file so that command line args override the file
- # contents.
- command_line_args.insert(0, "@%s" % OPTIONS_FILENAME)
-
- return parser.parse_args(command_line_args)
-
-
-def maybe_create_remote_root_dir(args):
- commandline = [
- "ssh",
- "-p", args.port,
- "%s@%s" % (args.user, args.remote_address),
- "mkdir",
- "-p",
- args.remote_dir]
- print("create remote root dir command:\n{}".format(commandline))
- return subprocess.call(commandline)
-
-
-def init_with_args(args):
- # Expand any user directory specs in local-side source dir (on MacOSX).
- args.local_lldb_dir = os.path.expanduser(args.local_lldb_dir)
-
- # Append the configuration type to the remote build dir.
- args.configuration = normalize_configuration(args.configuration)
- args.remote_build_dir = os.path.join(
- args.remote_dir,
- "build-%s" % args.configuration)
-
- # We assume the local lldb directory is really named 'lldb'.
- # This is because on the remote end, the local lldb root dir
- # is copied over underneath llvm/tools and will be named there
- # whatever it is named locally. The remote build will assume
- # is is called lldb.
- if os.path.basename(args.local_lldb_dir) != 'lldb':
- raise Exception(
- "local lldb root needs to be called 'lldb' but was {} instead"
- .format(os.path.basename(args.local_lldb_dir)))
-
- args.lldb_dir_relative_regex = re.compile(
- "%s/llvm/tools/lldb/" % args.remote_dir)
- args.llvm_dir_relative_regex = re.compile("%s/" % args.remote_dir)
-
- print("Xcode action:", args.xcode_action)
-
- # Ensure the remote directory exists.
- result = maybe_create_remote_root_dir(args)
- if result == 0:
- print("using remote root dir: %s" % args.remote_dir)
- else:
- print("remote root dir doesn't exist and could not be created, "
- + "error code:", result)
- return False
-
- return True
-
-
-def sync_llvm(args):
- commandline = ["rsync"]
- commandline.extend(_COMMON_SYNC_OPTS.split())
- commandline.extend(_COMMON_EXCLUDE_OPTS.split())
- commandline.append("--exclude=/llvm/tools/lldb")
- commandline.extend(["-e", "ssh -p {}".format(args.port)])
- commandline.extend([
- "%s/llvm" % args.local_lldb_dir,
- "%s@%s:%s" % (args.user, args.remote_address, args.remote_dir)])
- if args.debug:
- print("going to execute llvm sync: {}".format(commandline))
- return subprocess.call(commandline)
-
-
-def sync_lldb(args):
- commandline = ["rsync"]
- commandline.extend(_COMMON_SYNC_OPTS.split())
- commandline.extend(_COMMON_EXCLUDE_OPTS.split())
- commandline.append("--exclude=/lldb/llvm")
- commandline.extend(["-e", "ssh -p {}".format(args.port)])
- commandline.extend([args.local_lldb_dir, "%s@%s:%s/llvm/tools" %
- (args.user, args.remote_address, args.remote_dir)])
- if args.debug:
- print("going to execute lldb sync: {}".format(commandline))
- return subprocess.call(commandline)
-
-
-def build_cmake_command(args):
- # args.remote_build_dir
- # args.configuration in ('release', 'debug')
-
- if args.configuration == 'debug-optimized':
- build_type_name = "RelWithDebInfo"
- elif args.configuration == 'release':
- build_type_name = "Release"
- else:
- build_type_name = "Debug"
-
- ld_flags = "\"-lstdc++ -lm\""
-
- install_dir = os.path.join(
- args.remote_build_dir, "..", "install-{}".format(args.configuration))
-
- command_line = [
- "cmake",
- "-GNinja",
- "-DCMAKE_CXX_COMPILER=clang",
- "-DCMAKE_C_COMPILER=clang",
- # "-DCMAKE_CXX_FLAGS=%s" % cxx_flags,
- "-DCMAKE_SHARED_LINKER_FLAGS=%s" % ld_flags,
- "-DCMAKE_EXE_LINKER_FLAGS=%s" % ld_flags,
- "-DCMAKE_INSTALL_PREFIX:PATH=%s" % install_dir,
- "-DCMAKE_BUILD_TYPE=%s" % build_type_name,
- "-Wno-dev",
- os.path.join("..", "llvm")
- ]
-
- return command_line
-
-
-def maybe_configure(args):
- commandline = [
- "ssh",
- "-p", args.port,
- "%s@%s" % (args.user, args.remote_address),
- "cd", args.remote_dir, "&&",
- "mkdir", "-p", args.remote_build_dir, "&&",
- "cd", args.remote_build_dir, "&&"
- ]
- commandline.extend(build_cmake_command(args))
-
- if args.debug:
- print("configure command: {}".format(commandline))
-
- return subprocess.call(commandline)
-
-
-def filter_build_line(args, line):
- lldb_relative_line = args.lldb_dir_relative_regex.sub('', line)
- if len(lldb_relative_line) != len(line):
- # We substituted - return the modified line
- return lldb_relative_line
-
- # No match on lldb path (longer on linux than llvm path). Try
- # the llvm path match.
- return args.llvm_dir_relative_regex.sub('', line)
-
-
-def run_remote_build_command(args, build_command_list):
- commandline = [
- "ssh",
- "-p", args.port,
- "%s@%s" % (args.user, args.remote_address),
- "cd", args.remote_build_dir, "&&"]
- commandline.extend(build_command_list)
-
- if args.debug:
- print("running remote build command: {}".format(commandline))
-
- proc = subprocess.Popen(
- commandline,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
-
- # Filter stdout/stderr output for file path mapping.
- # We do this to enable Xcode to see filenames relative to the
- # MacOSX-side directory structure.
- while True:
- reads = [proc.stdout.fileno(), proc.stderr.fileno()]
- select_result = select.select(reads, [], [])
-
- for fd in select_result[0]:
- if fd == proc.stdout.fileno():
- line = proc.stdout.readline()
- display_line = filter_build_line(args, line.rstrip())
- if display_line and len(display_line) > 0:
- print(display_line)
- elif fd == proc.stderr.fileno():
- line = proc.stderr.readline()
- display_line = filter_build_line(args, line.rstrip())
- if display_line and len(display_line) > 0:
- print(display_line, file=sys.stderr)
-
- proc_retval = proc.poll()
- if proc_retval is not None:
- # Process stopped. Drain output before finishing up.
-
- # Drain stdout.
- while True:
- line = proc.stdout.readline()
- if line:
- display_line = filter_build_line(args, line.rstrip())
- if display_line and len(display_line) > 0:
- print(display_line)
- else:
- break
-
- # Drain stderr.
- while True:
- line = proc.stderr.readline()
- if line:
- display_line = filter_build_line(args, line.rstrip())
- if display_line and len(display_line) > 0:
- print(display_line, file=sys.stderr)
- else:
- break
-
- return proc_retval
-
-
-def build(args):
- return run_remote_build_command(args, ["time", "ninja"])
-
-
-def clean(args):
- return run_remote_build_command(args, ["ninja", "clean"])
-
-
-if __name__ == "__main__":
- # Handle arg parsing.
- args = parse_args()
-
- # Initialize the system.
- if not init_with_args(args):
- exit(1)
-
- # Sync over llvm and clang source.
- sync_llvm(args)
-
- # Sync over lldb source.
- sync_lldb(args)
-
- # Configure the remote build if it's not already.
- maybe_configure(args)
-
- if args.xcode_action == 'clean':
- exit(clean(args))
- else:
- exit(build(args))