1*9880d681SAndroid Build Coastguard Worker#!/usr/bin/python3 2*9880d681SAndroid Build Coastguard Worker##===- utils/llvmbuild - Build the LLVM project ----------------*-python-*-===## 3*9880d681SAndroid Build Coastguard Worker# 4*9880d681SAndroid Build Coastguard Worker# The LLVM Compiler Infrastructure 5*9880d681SAndroid Build Coastguard Worker# 6*9880d681SAndroid Build Coastguard Worker# This file is distributed under the University of Illinois Open Source 7*9880d681SAndroid Build Coastguard Worker# License. See LICENSE.TXT for details. 8*9880d681SAndroid Build Coastguard Worker# 9*9880d681SAndroid Build Coastguard Worker##===----------------------------------------------------------------------===## 10*9880d681SAndroid Build Coastguard Worker# 11*9880d681SAndroid Build Coastguard Worker# This script builds many different flavors of the LLVM ecosystem. It 12*9880d681SAndroid Build Coastguard Worker# will build LLVM, Clang and dragonegg as well as run tests on them. 13*9880d681SAndroid Build Coastguard Worker# This script is convenient to use to check builds and tests before 14*9880d681SAndroid Build Coastguard Worker# committing changes to the upstream repository 15*9880d681SAndroid Build Coastguard Worker# 16*9880d681SAndroid Build Coastguard Worker# A typical source setup uses three trees and looks like this: 17*9880d681SAndroid Build Coastguard Worker# 18*9880d681SAndroid Build Coastguard Worker# official 19*9880d681SAndroid Build Coastguard Worker# dragonegg 20*9880d681SAndroid Build Coastguard Worker# llvm 21*9880d681SAndroid Build Coastguard Worker# tools 22*9880d681SAndroid Build Coastguard Worker# clang 23*9880d681SAndroid Build Coastguard Worker# staging 24*9880d681SAndroid Build Coastguard Worker# dragonegg 25*9880d681SAndroid Build Coastguard Worker# llvm 26*9880d681SAndroid Build Coastguard Worker# tools 27*9880d681SAndroid Build Coastguard Worker# clang 28*9880d681SAndroid Build Coastguard Worker# commit 29*9880d681SAndroid Build Coastguard Worker# dragonegg 30*9880d681SAndroid Build Coastguard Worker# llvm 31*9880d681SAndroid Build Coastguard Worker# tools 32*9880d681SAndroid Build Coastguard Worker# clang 33*9880d681SAndroid Build Coastguard Worker# 34*9880d681SAndroid Build Coastguard Worker# In a typical workflow, the "official" tree always contains unchanged 35*9880d681SAndroid Build Coastguard Worker# sources from the main LLVM project repositories. The "staging" tree 36*9880d681SAndroid Build Coastguard Worker# is where local work is done. A set of changes resides there waiting 37*9880d681SAndroid Build Coastguard Worker# to be moved upstream. The "commit" tree is where changes from 38*9880d681SAndroid Build Coastguard Worker# "staging" make their way upstream. Individual incremental changes 39*9880d681SAndroid Build Coastguard Worker# from "staging" are applied to "commit" and committed upstream after 40*9880d681SAndroid Build Coastguard Worker# a successful build and test run. A successful build is one in which 41*9880d681SAndroid Build Coastguard Worker# testing results in no more failures than seen in the testing of the 42*9880d681SAndroid Build Coastguard Worker# "official" tree. 43*9880d681SAndroid Build Coastguard Worker# 44*9880d681SAndroid Build Coastguard Worker# A build may be invoked as such: 45*9880d681SAndroid Build Coastguard Worker# 46*9880d681SAndroid Build Coastguard Worker# llvmbuild --src=~/llvm/commit --src=~/llvm/staging --src=~/llvm/official 47*9880d681SAndroid Build Coastguard Worker# --build=debug --build=release --build=paranoid 48*9880d681SAndroid Build Coastguard Worker# --prefix=/home/greened/install --builddir=/home/greened/build 49*9880d681SAndroid Build Coastguard Worker# 50*9880d681SAndroid Build Coastguard Worker# This will build the LLVM ecosystem, including LLVM, Clangand 51*9880d681SAndroid Build Coastguard Worker# dragonegg, putting build results in ~/build and installing tools in 52*9880d681SAndroid Build Coastguard Worker# ~/install. llvm-compilers-check creates separate build and install 53*9880d681SAndroid Build Coastguard Worker# directories for each source/build flavor. In the above example, 54*9880d681SAndroid Build Coastguard Worker# llvmbuild will build debug, release and paranoid (debug+checks) 55*9880d681SAndroid Build Coastguard Worker# flavors from each source tree (official, staging and commit) for a 56*9880d681SAndroid Build Coastguard Worker# total of nine builds. All builds will be run in parallel. 57*9880d681SAndroid Build Coastguard Worker# 58*9880d681SAndroid Build Coastguard Worker# The user may control parallelism via the --jobs and --threads 59*9880d681SAndroid Build Coastguard Worker# switches. --jobs tells llvm-compilers-checl the maximum total 60*9880d681SAndroid Build Coastguard Worker# number of builds to activate in parallel. The user may think of it 61*9880d681SAndroid Build Coastguard Worker# as equivalent to the GNU make -j switch. --threads tells 62*9880d681SAndroid Build Coastguard Worker# llvm-compilers-check how many worker threads to use to accomplish 63*9880d681SAndroid Build Coastguard Worker# those builds. If --threads is less than --jobs, --threads workers 64*9880d681SAndroid Build Coastguard Worker# will be launched and each one will pick a source/flavor combination 65*9880d681SAndroid Build Coastguard Worker# to build. Then llvm-compilers-check will invoke GNU make with -j 66*9880d681SAndroid Build Coastguard Worker# (--jobs / --threads) to use up the remaining job capacity. Once a 67*9880d681SAndroid Build Coastguard Worker# worker is finished with a build, it will pick another combination 68*9880d681SAndroid Build Coastguard Worker# off the list and start building it. 69*9880d681SAndroid Build Coastguard Worker# 70*9880d681SAndroid Build Coastguard Worker##===----------------------------------------------------------------------===## 71*9880d681SAndroid Build Coastguard Worker 72*9880d681SAndroid Build Coastguard Workerimport optparse 73*9880d681SAndroid Build Coastguard Workerimport os 74*9880d681SAndroid Build Coastguard Workerimport sys 75*9880d681SAndroid Build Coastguard Workerimport threading 76*9880d681SAndroid Build Coastguard Workerimport queue 77*9880d681SAndroid Build Coastguard Workerimport logging 78*9880d681SAndroid Build Coastguard Workerimport traceback 79*9880d681SAndroid Build Coastguard Workerimport subprocess 80*9880d681SAndroid Build Coastguard Workerimport re 81*9880d681SAndroid Build Coastguard Worker 82*9880d681SAndroid Build Coastguard Worker# TODO: Use shutil.which when it is available (3.2 or later) 83*9880d681SAndroid Build Coastguard Workerdef find_executable(executable, path=None): 84*9880d681SAndroid Build Coastguard Worker """Try to find 'executable' in the directories listed in 'path' (a 85*9880d681SAndroid Build Coastguard Worker string listing directories separated by 'os.pathsep'; defaults to 86*9880d681SAndroid Build Coastguard Worker os.environ['PATH']). Returns the complete filename or None if not 87*9880d681SAndroid Build Coastguard Worker found 88*9880d681SAndroid Build Coastguard Worker """ 89*9880d681SAndroid Build Coastguard Worker if path is None: 90*9880d681SAndroid Build Coastguard Worker path = os.environ['PATH'] 91*9880d681SAndroid Build Coastguard Worker paths = path.split(os.pathsep) 92*9880d681SAndroid Build Coastguard Worker extlist = [''] 93*9880d681SAndroid Build Coastguard Worker if os.name == 'os2': 94*9880d681SAndroid Build Coastguard Worker (base, ext) = os.path.splitext(executable) 95*9880d681SAndroid Build Coastguard Worker # executable files on OS/2 can have an arbitrary extension, but 96*9880d681SAndroid Build Coastguard Worker # .exe is automatically appended if no dot is present in the name 97*9880d681SAndroid Build Coastguard Worker if not ext: 98*9880d681SAndroid Build Coastguard Worker executable = executable + ".exe" 99*9880d681SAndroid Build Coastguard Worker elif sys.platform == 'win32': 100*9880d681SAndroid Build Coastguard Worker pathext = os.environ['PATHEXT'].lower().split(os.pathsep) 101*9880d681SAndroid Build Coastguard Worker (base, ext) = os.path.splitext(executable) 102*9880d681SAndroid Build Coastguard Worker if ext.lower() not in pathext: 103*9880d681SAndroid Build Coastguard Worker extlist = pathext 104*9880d681SAndroid Build Coastguard Worker for ext in extlist: 105*9880d681SAndroid Build Coastguard Worker execname = executable + ext 106*9880d681SAndroid Build Coastguard Worker if os.path.isfile(execname): 107*9880d681SAndroid Build Coastguard Worker return execname 108*9880d681SAndroid Build Coastguard Worker else: 109*9880d681SAndroid Build Coastguard Worker for p in paths: 110*9880d681SAndroid Build Coastguard Worker f = os.path.join(p, execname) 111*9880d681SAndroid Build Coastguard Worker if os.path.isfile(f): 112*9880d681SAndroid Build Coastguard Worker return f 113*9880d681SAndroid Build Coastguard Worker else: 114*9880d681SAndroid Build Coastguard Worker return None 115*9880d681SAndroid Build Coastguard Worker 116*9880d681SAndroid Build Coastguard Workerdef is_executable(fpath): 117*9880d681SAndroid Build Coastguard Worker return os.path.exists(fpath) and os.access(fpath, os.X_OK) 118*9880d681SAndroid Build Coastguard Worker 119*9880d681SAndroid Build Coastguard Workerdef add_options(parser): 120*9880d681SAndroid Build Coastguard Worker parser.add_option("-v", "--verbose", action="store_true", 121*9880d681SAndroid Build Coastguard Worker default=False, 122*9880d681SAndroid Build Coastguard Worker help=("Output informational messages" 123*9880d681SAndroid Build Coastguard Worker " [default: %default]")) 124*9880d681SAndroid Build Coastguard Worker parser.add_option("--src", action="append", 125*9880d681SAndroid Build Coastguard Worker help=("Top-level source directory [default: %default]")) 126*9880d681SAndroid Build Coastguard Worker parser.add_option("--build", action="append", 127*9880d681SAndroid Build Coastguard Worker help=("Build types to run [default: %default]")) 128*9880d681SAndroid Build Coastguard Worker parser.add_option("--cc", default=find_executable("cc"), 129*9880d681SAndroid Build Coastguard Worker help=("The C compiler to use [default: %default]")) 130*9880d681SAndroid Build Coastguard Worker parser.add_option("--cxx", default=find_executable("c++"), 131*9880d681SAndroid Build Coastguard Worker help=("The C++ compiler to use [default: %default]")) 132*9880d681SAndroid Build Coastguard Worker parser.add_option("--threads", default=4, type="int", 133*9880d681SAndroid Build Coastguard Worker help=("The number of worker threads to use " 134*9880d681SAndroid Build Coastguard Worker "[default: %default]")) 135*9880d681SAndroid Build Coastguard Worker parser.add_option("--jobs", "-j", default=8, type="int", 136*9880d681SAndroid Build Coastguard Worker help=("The number of simultaneous build jobs " 137*9880d681SAndroid Build Coastguard Worker "[default: %default]")) 138*9880d681SAndroid Build Coastguard Worker parser.add_option("--prefix", 139*9880d681SAndroid Build Coastguard Worker help=("Root install directory [default: %default]")) 140*9880d681SAndroid Build Coastguard Worker parser.add_option("--builddir", 141*9880d681SAndroid Build Coastguard Worker help=("Root build directory [default: %default]")) 142*9880d681SAndroid Build Coastguard Worker parser.add_option("--extra-llvm-config-flags", default="", 143*9880d681SAndroid Build Coastguard Worker help=("Extra flags to pass to llvm configure [default: %default]")) 144*9880d681SAndroid Build Coastguard Worker parser.add_option("--force-configure", default=False, action="store_true", 145*9880d681SAndroid Build Coastguard Worker help=("Force reconfigure of all components")) 146*9880d681SAndroid Build Coastguard Worker parser.add_option("--no-dragonegg", default=False, action="store_true", 147*9880d681SAndroid Build Coastguard Worker help=("Do not build dragonegg")) 148*9880d681SAndroid Build Coastguard Worker parser.add_option("--no-install", default=False, action="store_true", 149*9880d681SAndroid Build Coastguard Worker help=("Do not do installs")) 150*9880d681SAndroid Build Coastguard Worker parser.add_option("--keep-going", default=False, action="store_true", 151*9880d681SAndroid Build Coastguard Worker help=("Keep going after failures")) 152*9880d681SAndroid Build Coastguard Worker parser.add_option("--no-flavor-prefix", default=False, action="store_true", 153*9880d681SAndroid Build Coastguard Worker help=("Do not append the build flavor to the install path")) 154*9880d681SAndroid Build Coastguard Worker parser.add_option("--enable-werror", default=False, action="store_true", 155*9880d681SAndroid Build Coastguard Worker help=("Build with -Werror")) 156*9880d681SAndroid Build Coastguard Worker return 157*9880d681SAndroid Build Coastguard Worker 158*9880d681SAndroid Build Coastguard Workerdef check_options(parser, options, valid_builds): 159*9880d681SAndroid Build Coastguard Worker # See if we're building valid flavors. 160*9880d681SAndroid Build Coastguard Worker for build in options.build: 161*9880d681SAndroid Build Coastguard Worker if (build not in valid_builds): 162*9880d681SAndroid Build Coastguard Worker parser.error("'" + build + "' is not a valid build flavor " 163*9880d681SAndroid Build Coastguard Worker + str(valid_builds)) 164*9880d681SAndroid Build Coastguard Worker 165*9880d681SAndroid Build Coastguard Worker # See if we can find source directories. 166*9880d681SAndroid Build Coastguard Worker for src in options.src: 167*9880d681SAndroid Build Coastguard Worker for component in components: 168*9880d681SAndroid Build Coastguard Worker component = component.rstrip("2") 169*9880d681SAndroid Build Coastguard Worker compsrc = src + "/" + component 170*9880d681SAndroid Build Coastguard Worker if (not os.path.isdir(compsrc)): 171*9880d681SAndroid Build Coastguard Worker parser.error("'" + compsrc + "' does not exist") 172*9880d681SAndroid Build Coastguard Worker 173*9880d681SAndroid Build Coastguard Worker # See if we can find the compilers 174*9880d681SAndroid Build Coastguard Worker options.cc = find_executable(options.cc) 175*9880d681SAndroid Build Coastguard Worker options.cxx = find_executable(options.cxx) 176*9880d681SAndroid Build Coastguard Worker 177*9880d681SAndroid Build Coastguard Worker return 178*9880d681SAndroid Build Coastguard Worker 179*9880d681SAndroid Build Coastguard Worker# Find a unique short name for the given set of paths. This searches 180*9880d681SAndroid Build Coastguard Worker# back through path components until it finds unique component names 181*9880d681SAndroid Build Coastguard Worker# among all given paths. 182*9880d681SAndroid Build Coastguard Workerdef get_path_abbrevs(paths): 183*9880d681SAndroid Build Coastguard Worker # Find the number of common starting characters in the last component 184*9880d681SAndroid Build Coastguard Worker # of the paths. 185*9880d681SAndroid Build Coastguard Worker unique_paths = list(paths) 186*9880d681SAndroid Build Coastguard Worker 187*9880d681SAndroid Build Coastguard Worker class NotFoundException(Exception): pass 188*9880d681SAndroid Build Coastguard Worker 189*9880d681SAndroid Build Coastguard Worker # Find a unique component of each path. 190*9880d681SAndroid Build Coastguard Worker unique_bases = unique_paths[:] 191*9880d681SAndroid Build Coastguard Worker found = 0 192*9880d681SAndroid Build Coastguard Worker while len(unique_paths) > 0: 193*9880d681SAndroid Build Coastguard Worker bases = [os.path.basename(src) for src in unique_paths] 194*9880d681SAndroid Build Coastguard Worker components = { c for c in bases } 195*9880d681SAndroid Build Coastguard Worker # Account for single entry in paths. 196*9880d681SAndroid Build Coastguard Worker if len(components) > 1 or len(components) == len(bases): 197*9880d681SAndroid Build Coastguard Worker # We found something unique. 198*9880d681SAndroid Build Coastguard Worker for c in components: 199*9880d681SAndroid Build Coastguard Worker if bases.count(c) == 1: 200*9880d681SAndroid Build Coastguard Worker index = bases.index(c) 201*9880d681SAndroid Build Coastguard Worker unique_bases[index] = c 202*9880d681SAndroid Build Coastguard Worker # Remove the corresponding path from the set under 203*9880d681SAndroid Build Coastguard Worker # consideration. 204*9880d681SAndroid Build Coastguard Worker unique_paths[index] = None 205*9880d681SAndroid Build Coastguard Worker unique_paths = [ p for p in unique_paths if p is not None ] 206*9880d681SAndroid Build Coastguard Worker unique_paths = [os.path.dirname(src) for src in unique_paths] 207*9880d681SAndroid Build Coastguard Worker 208*9880d681SAndroid Build Coastguard Worker if len(unique_paths) > 0: 209*9880d681SAndroid Build Coastguard Worker raise NotFoundException() 210*9880d681SAndroid Build Coastguard Worker 211*9880d681SAndroid Build Coastguard Worker abbrevs = dict(zip(paths, [base for base in unique_bases])) 212*9880d681SAndroid Build Coastguard Worker 213*9880d681SAndroid Build Coastguard Worker return abbrevs 214*9880d681SAndroid Build Coastguard Worker 215*9880d681SAndroid Build Coastguard Worker# Given a set of unique names, find a short character sequence that 216*9880d681SAndroid Build Coastguard Worker# uniquely identifies them. 217*9880d681SAndroid Build Coastguard Workerdef get_short_abbrevs(unique_bases): 218*9880d681SAndroid Build Coastguard Worker # Find a unique start character for each path base. 219*9880d681SAndroid Build Coastguard Worker my_unique_bases = unique_bases[:] 220*9880d681SAndroid Build Coastguard Worker unique_char_starts = unique_bases[:] 221*9880d681SAndroid Build Coastguard Worker while len(my_unique_bases) > 0: 222*9880d681SAndroid Build Coastguard Worker for start, char_tuple in enumerate(zip(*[base 223*9880d681SAndroid Build Coastguard Worker for base in my_unique_bases])): 224*9880d681SAndroid Build Coastguard Worker chars = { c for c in char_tuple } 225*9880d681SAndroid Build Coastguard Worker # Account for single path. 226*9880d681SAndroid Build Coastguard Worker if len(chars) > 1 or len(chars) == len(char_tuple): 227*9880d681SAndroid Build Coastguard Worker # We found something unique. 228*9880d681SAndroid Build Coastguard Worker for c in chars: 229*9880d681SAndroid Build Coastguard Worker if char_tuple.count(c) == 1: 230*9880d681SAndroid Build Coastguard Worker index = char_tuple.index(c) 231*9880d681SAndroid Build Coastguard Worker unique_char_starts[index] = start 232*9880d681SAndroid Build Coastguard Worker # Remove the corresponding path from the set under 233*9880d681SAndroid Build Coastguard Worker # consideration. 234*9880d681SAndroid Build Coastguard Worker my_unique_bases[index] = None 235*9880d681SAndroid Build Coastguard Worker my_unique_bases = [ b for b in my_unique_bases 236*9880d681SAndroid Build Coastguard Worker if b is not None ] 237*9880d681SAndroid Build Coastguard Worker break 238*9880d681SAndroid Build Coastguard Worker 239*9880d681SAndroid Build Coastguard Worker if len(my_unique_bases) > 0: 240*9880d681SAndroid Build Coastguard Worker raise NotFoundException() 241*9880d681SAndroid Build Coastguard Worker 242*9880d681SAndroid Build Coastguard Worker abbrevs = [abbrev[start_index:start_index+3] 243*9880d681SAndroid Build Coastguard Worker for abbrev, start_index 244*9880d681SAndroid Build Coastguard Worker in zip([base for base in unique_bases], 245*9880d681SAndroid Build Coastguard Worker [index for index in unique_char_starts])] 246*9880d681SAndroid Build Coastguard Worker 247*9880d681SAndroid Build Coastguard Worker abbrevs = dict(zip(unique_bases, abbrevs)) 248*9880d681SAndroid Build Coastguard Worker 249*9880d681SAndroid Build Coastguard Worker return abbrevs 250*9880d681SAndroid Build Coastguard Worker 251*9880d681SAndroid Build Coastguard Workerclass Builder(threading.Thread): 252*9880d681SAndroid Build Coastguard Worker class ExecutableNotFound(Exception): pass 253*9880d681SAndroid Build Coastguard Worker class FileNotExecutable(Exception): pass 254*9880d681SAndroid Build Coastguard Worker 255*9880d681SAndroid Build Coastguard Worker def __init__(self, work_queue, jobs, 256*9880d681SAndroid Build Coastguard Worker build_abbrev, source_abbrev, 257*9880d681SAndroid Build Coastguard Worker options): 258*9880d681SAndroid Build Coastguard Worker super().__init__() 259*9880d681SAndroid Build Coastguard Worker self.work_queue = work_queue 260*9880d681SAndroid Build Coastguard Worker self.jobs = jobs 261*9880d681SAndroid Build Coastguard Worker self.cc = options.cc 262*9880d681SAndroid Build Coastguard Worker self.cxx = options.cxx 263*9880d681SAndroid Build Coastguard Worker self.build_abbrev = build_abbrev 264*9880d681SAndroid Build Coastguard Worker self.source_abbrev = source_abbrev 265*9880d681SAndroid Build Coastguard Worker self.build_prefix = options.builddir 266*9880d681SAndroid Build Coastguard Worker self.install_prefix = options.prefix 267*9880d681SAndroid Build Coastguard Worker self.options = options 268*9880d681SAndroid Build Coastguard Worker self.component_abbrev = dict( 269*9880d681SAndroid Build Coastguard Worker llvm="llvm", 270*9880d681SAndroid Build Coastguard Worker dragonegg="degg") 271*9880d681SAndroid Build Coastguard Worker def run(self): 272*9880d681SAndroid Build Coastguard Worker while True: 273*9880d681SAndroid Build Coastguard Worker try: 274*9880d681SAndroid Build Coastguard Worker source, build = self.work_queue.get() 275*9880d681SAndroid Build Coastguard Worker self.dobuild(source, build) 276*9880d681SAndroid Build Coastguard Worker except: 277*9880d681SAndroid Build Coastguard Worker traceback.print_exc() 278*9880d681SAndroid Build Coastguard Worker finally: 279*9880d681SAndroid Build Coastguard Worker self.work_queue.task_done() 280*9880d681SAndroid Build Coastguard Worker 281*9880d681SAndroid Build Coastguard Worker def execute(self, command, execdir, env, component): 282*9880d681SAndroid Build Coastguard Worker prefix = self.component_abbrev[component.replace("-", "_")] 283*9880d681SAndroid Build Coastguard Worker pwd = os.getcwd() 284*9880d681SAndroid Build Coastguard Worker if not os.path.exists(execdir): 285*9880d681SAndroid Build Coastguard Worker os.makedirs(execdir) 286*9880d681SAndroid Build Coastguard Worker 287*9880d681SAndroid Build Coastguard Worker execenv = os.environ.copy() 288*9880d681SAndroid Build Coastguard Worker 289*9880d681SAndroid Build Coastguard Worker for key, value in env.items(): 290*9880d681SAndroid Build Coastguard Worker execenv[key] = value 291*9880d681SAndroid Build Coastguard Worker 292*9880d681SAndroid Build Coastguard Worker self.logger.debug("[" + prefix + "] " + "env " + str(env) + " " 293*9880d681SAndroid Build Coastguard Worker + " ".join(command)); 294*9880d681SAndroid Build Coastguard Worker 295*9880d681SAndroid Build Coastguard Worker try: 296*9880d681SAndroid Build Coastguard Worker proc = subprocess.Popen(command, 297*9880d681SAndroid Build Coastguard Worker cwd=execdir, 298*9880d681SAndroid Build Coastguard Worker env=execenv, 299*9880d681SAndroid Build Coastguard Worker stdout=subprocess.PIPE, 300*9880d681SAndroid Build Coastguard Worker stderr=subprocess.STDOUT) 301*9880d681SAndroid Build Coastguard Worker 302*9880d681SAndroid Build Coastguard Worker line = proc.stdout.readline() 303*9880d681SAndroid Build Coastguard Worker while line: 304*9880d681SAndroid Build Coastguard Worker self.logger.info("[" + prefix + "] " 305*9880d681SAndroid Build Coastguard Worker + str(line, "utf-8").rstrip()) 306*9880d681SAndroid Build Coastguard Worker line = proc.stdout.readline() 307*9880d681SAndroid Build Coastguard Worker 308*9880d681SAndroid Build Coastguard Worker (stdoutdata, stderrdata) = proc.communicate() 309*9880d681SAndroid Build Coastguard Worker retcode = proc.wait() 310*9880d681SAndroid Build Coastguard Worker 311*9880d681SAndroid Build Coastguard Worker return retcode 312*9880d681SAndroid Build Coastguard Worker 313*9880d681SAndroid Build Coastguard Worker except: 314*9880d681SAndroid Build Coastguard Worker traceback.print_exc() 315*9880d681SAndroid Build Coastguard Worker 316*9880d681SAndroid Build Coastguard Worker # Get a list of C++ include directories to pass to clang. 317*9880d681SAndroid Build Coastguard Worker def get_includes(self): 318*9880d681SAndroid Build Coastguard Worker # Assume we're building with g++ for now. 319*9880d681SAndroid Build Coastguard Worker command = [self.cxx] 320*9880d681SAndroid Build Coastguard Worker command += ["-v", "-x", "c++", "/dev/null", "-fsyntax-only"] 321*9880d681SAndroid Build Coastguard Worker includes = [] 322*9880d681SAndroid Build Coastguard Worker self.logger.debug(command) 323*9880d681SAndroid Build Coastguard Worker try: 324*9880d681SAndroid Build Coastguard Worker proc = subprocess.Popen(command, 325*9880d681SAndroid Build Coastguard Worker stdout=subprocess.PIPE, 326*9880d681SAndroid Build Coastguard Worker stderr=subprocess.STDOUT) 327*9880d681SAndroid Build Coastguard Worker 328*9880d681SAndroid Build Coastguard Worker gather = False 329*9880d681SAndroid Build Coastguard Worker line = proc.stdout.readline() 330*9880d681SAndroid Build Coastguard Worker while line: 331*9880d681SAndroid Build Coastguard Worker self.logger.debug(line) 332*9880d681SAndroid Build Coastguard Worker if re.search("End of search list", str(line)) is not None: 333*9880d681SAndroid Build Coastguard Worker self.logger.debug("Stop Gather") 334*9880d681SAndroid Build Coastguard Worker gather = False 335*9880d681SAndroid Build Coastguard Worker if gather: 336*9880d681SAndroid Build Coastguard Worker includes.append(str(line, "utf-8").strip()) 337*9880d681SAndroid Build Coastguard Worker if re.search("#include <...> search starts", str(line)) is not None: 338*9880d681SAndroid Build Coastguard Worker self.logger.debug("Start Gather") 339*9880d681SAndroid Build Coastguard Worker gather = True 340*9880d681SAndroid Build Coastguard Worker line = proc.stdout.readline() 341*9880d681SAndroid Build Coastguard Worker 342*9880d681SAndroid Build Coastguard Worker except: 343*9880d681SAndroid Build Coastguard Worker traceback.print_exc() 344*9880d681SAndroid Build Coastguard Worker self.logger.debug(includes) 345*9880d681SAndroid Build Coastguard Worker return includes 346*9880d681SAndroid Build Coastguard Worker 347*9880d681SAndroid Build Coastguard Worker def dobuild(self, source, build): 348*9880d681SAndroid Build Coastguard Worker build_suffix = "" 349*9880d681SAndroid Build Coastguard Worker 350*9880d681SAndroid Build Coastguard Worker ssabbrev = get_short_abbrevs([ab for ab in self.source_abbrev.values()]) 351*9880d681SAndroid Build Coastguard Worker 352*9880d681SAndroid Build Coastguard Worker prefix = "[" + ssabbrev[self.source_abbrev[source]] + "-" + self.build_abbrev[build] + "]" 353*9880d681SAndroid Build Coastguard Worker if (not self.options.no_flavor_prefix): 354*9880d681SAndroid Build Coastguard Worker self.install_prefix += "/" + self.source_abbrev[source] + "/" + build 355*9880d681SAndroid Build Coastguard Worker 356*9880d681SAndroid Build Coastguard Worker build_suffix += "/" + self.source_abbrev[source] + "/" + build 357*9880d681SAndroid Build Coastguard Worker 358*9880d681SAndroid Build Coastguard Worker self.logger = logging.getLogger(prefix) 359*9880d681SAndroid Build Coastguard Worker 360*9880d681SAndroid Build Coastguard Worker self.logger.debug(self.install_prefix) 361*9880d681SAndroid Build Coastguard Worker 362*9880d681SAndroid Build Coastguard Worker # Assume we're building with gcc for now. 363*9880d681SAndroid Build Coastguard Worker cxxincludes = self.get_includes() 364*9880d681SAndroid Build Coastguard Worker cxxroot = os.path.dirname(cxxincludes[0]) # Remove the version 365*9880d681SAndroid Build Coastguard Worker cxxroot = os.path.dirname(cxxroot) # Remove the c++ 366*9880d681SAndroid Build Coastguard Worker cxxroot = os.path.dirname(cxxroot) # Remove the include 367*9880d681SAndroid Build Coastguard Worker 368*9880d681SAndroid Build Coastguard Worker configure_flags = dict( 369*9880d681SAndroid Build Coastguard Worker llvm=dict(debug=["--prefix=" + self.install_prefix, 370*9880d681SAndroid Build Coastguard Worker "--enable-assertions", 371*9880d681SAndroid Build Coastguard Worker "--disable-optimized", 372*9880d681SAndroid Build Coastguard Worker "--with-gcc-toolchain=" + cxxroot], 373*9880d681SAndroid Build Coastguard Worker release=["--prefix=" + self.install_prefix, 374*9880d681SAndroid Build Coastguard Worker "--enable-optimized", 375*9880d681SAndroid Build Coastguard Worker "--with-gcc-toolchain=" + cxxroot], 376*9880d681SAndroid Build Coastguard Worker paranoid=["--prefix=" + self.install_prefix, 377*9880d681SAndroid Build Coastguard Worker "--enable-assertions", 378*9880d681SAndroid Build Coastguard Worker "--enable-expensive-checks", 379*9880d681SAndroid Build Coastguard Worker "--disable-optimized", 380*9880d681SAndroid Build Coastguard Worker "--with-gcc-toolchain=" + cxxroot]), 381*9880d681SAndroid Build Coastguard Worker dragonegg=dict(debug=[], 382*9880d681SAndroid Build Coastguard Worker release=[], 383*9880d681SAndroid Build Coastguard Worker paranoid=[])) 384*9880d681SAndroid Build Coastguard Worker 385*9880d681SAndroid Build Coastguard Worker if (self.options.enable_werror): 386*9880d681SAndroid Build Coastguard Worker configure_flags["llvm"]["debug"].append("--enable-werror") 387*9880d681SAndroid Build Coastguard Worker configure_flags["llvm"]["release"].append("--enable-werror") 388*9880d681SAndroid Build Coastguard Worker configure_flags["llvm"]["paranoid"].append("--enable-werror") 389*9880d681SAndroid Build Coastguard Worker 390*9880d681SAndroid Build Coastguard Worker configure_env = dict( 391*9880d681SAndroid Build Coastguard Worker llvm=dict(debug=dict(CC=self.cc, 392*9880d681SAndroid Build Coastguard Worker CXX=self.cxx), 393*9880d681SAndroid Build Coastguard Worker release=dict(CC=self.cc, 394*9880d681SAndroid Build Coastguard Worker CXX=self.cxx), 395*9880d681SAndroid Build Coastguard Worker paranoid=dict(CC=self.cc, 396*9880d681SAndroid Build Coastguard Worker CXX=self.cxx)), 397*9880d681SAndroid Build Coastguard Worker dragonegg=dict(debug=dict(CC=self.cc, 398*9880d681SAndroid Build Coastguard Worker CXX=self.cxx), 399*9880d681SAndroid Build Coastguard Worker release=dict(CC=self.cc, 400*9880d681SAndroid Build Coastguard Worker CXX=self.cxx), 401*9880d681SAndroid Build Coastguard Worker paranoid=dict(CC=self.cc, 402*9880d681SAndroid Build Coastguard Worker CXX=self.cxx))) 403*9880d681SAndroid Build Coastguard Worker 404*9880d681SAndroid Build Coastguard Worker make_flags = dict( 405*9880d681SAndroid Build Coastguard Worker llvm=dict(debug=["-j" + str(self.jobs)], 406*9880d681SAndroid Build Coastguard Worker release=["-j" + str(self.jobs)], 407*9880d681SAndroid Build Coastguard Worker paranoid=["-j" + str(self.jobs)]), 408*9880d681SAndroid Build Coastguard Worker dragonegg=dict(debug=["-j" + str(self.jobs)], 409*9880d681SAndroid Build Coastguard Worker release=["-j" + str(self.jobs)], 410*9880d681SAndroid Build Coastguard Worker paranoid=["-j" + str(self.jobs)])) 411*9880d681SAndroid Build Coastguard Worker 412*9880d681SAndroid Build Coastguard Worker make_env = dict( 413*9880d681SAndroid Build Coastguard Worker llvm=dict(debug=dict(), 414*9880d681SAndroid Build Coastguard Worker release=dict(), 415*9880d681SAndroid Build Coastguard Worker paranoid=dict()), 416*9880d681SAndroid Build Coastguard Worker dragonegg=dict(debug=dict(GCC=self.cc, 417*9880d681SAndroid Build Coastguard Worker LLVM_CONFIG=self.install_prefix + "/bin/llvm-config"), 418*9880d681SAndroid Build Coastguard Worker release=dict(GCC=self.cc, 419*9880d681SAndroid Build Coastguard Worker LLVM_CONFIG=self.install_prefix + "/bin/llvm-config"), 420*9880d681SAndroid Build Coastguard Worker paranoid=dict(GCC=self.cc, 421*9880d681SAndroid Build Coastguard Worker LLVM_CONFIG=self.install_prefix + "/bin/llvm-config"))) 422*9880d681SAndroid Build Coastguard Worker 423*9880d681SAndroid Build Coastguard Worker make_install_flags = dict( 424*9880d681SAndroid Build Coastguard Worker llvm=dict(debug=["install"], 425*9880d681SAndroid Build Coastguard Worker release=["install"], 426*9880d681SAndroid Build Coastguard Worker paranoid=["install"]), 427*9880d681SAndroid Build Coastguard Worker dragonegg=dict(debug=["install"], 428*9880d681SAndroid Build Coastguard Worker release=["install"], 429*9880d681SAndroid Build Coastguard Worker paranoid=["install"])) 430*9880d681SAndroid Build Coastguard Worker 431*9880d681SAndroid Build Coastguard Worker make_install_env = dict( 432*9880d681SAndroid Build Coastguard Worker llvm=dict(debug=dict(), 433*9880d681SAndroid Build Coastguard Worker release=dict(), 434*9880d681SAndroid Build Coastguard Worker paranoid=dict()), 435*9880d681SAndroid Build Coastguard Worker dragonegg=dict(debug=dict(), 436*9880d681SAndroid Build Coastguard Worker release=dict(), 437*9880d681SAndroid Build Coastguard Worker paranoid=dict())) 438*9880d681SAndroid Build Coastguard Worker 439*9880d681SAndroid Build Coastguard Worker make_check_flags = dict( 440*9880d681SAndroid Build Coastguard Worker llvm=dict(debug=["check"], 441*9880d681SAndroid Build Coastguard Worker release=["check"], 442*9880d681SAndroid Build Coastguard Worker paranoid=["check"]), 443*9880d681SAndroid Build Coastguard Worker dragonegg=dict(debug=["check"], 444*9880d681SAndroid Build Coastguard Worker release=["check"], 445*9880d681SAndroid Build Coastguard Worker paranoid=["check"])) 446*9880d681SAndroid Build Coastguard Worker 447*9880d681SAndroid Build Coastguard Worker make_check_env = dict( 448*9880d681SAndroid Build Coastguard Worker llvm=dict(debug=dict(), 449*9880d681SAndroid Build Coastguard Worker release=dict(), 450*9880d681SAndroid Build Coastguard Worker paranoid=dict()), 451*9880d681SAndroid Build Coastguard Worker dragonegg=dict(debug=dict(), 452*9880d681SAndroid Build Coastguard Worker release=dict(), 453*9880d681SAndroid Build Coastguard Worker paranoid=dict())) 454*9880d681SAndroid Build Coastguard Worker 455*9880d681SAndroid Build Coastguard Worker for component in components: 456*9880d681SAndroid Build Coastguard Worker comp = component[:] 457*9880d681SAndroid Build Coastguard Worker 458*9880d681SAndroid Build Coastguard Worker if (self.options.no_dragonegg): 459*9880d681SAndroid Build Coastguard Worker if (comp == 'dragonegg'): 460*9880d681SAndroid Build Coastguard Worker self.logger.info("Skipping " + component + " in " 461*9880d681SAndroid Build Coastguard Worker + builddir) 462*9880d681SAndroid Build Coastguard Worker continue 463*9880d681SAndroid Build Coastguard Worker 464*9880d681SAndroid Build Coastguard Worker srcdir = source + "/" + comp.rstrip("2") 465*9880d681SAndroid Build Coastguard Worker builddir = self.build_prefix + "/" + comp + "/" + build_suffix 466*9880d681SAndroid Build Coastguard Worker installdir = self.install_prefix 467*9880d681SAndroid Build Coastguard Worker 468*9880d681SAndroid Build Coastguard Worker comp_key = comp.replace("-", "_") 469*9880d681SAndroid Build Coastguard Worker 470*9880d681SAndroid Build Coastguard Worker config_args = configure_flags[comp_key][build][:] 471*9880d681SAndroid Build Coastguard Worker config_args.extend(getattr(self.options, 472*9880d681SAndroid Build Coastguard Worker "extra_" + comp_key.rstrip("2") 473*9880d681SAndroid Build Coastguard Worker + "_config_flags", 474*9880d681SAndroid Build Coastguard Worker "").split()) 475*9880d681SAndroid Build Coastguard Worker 476*9880d681SAndroid Build Coastguard Worker self.logger.info("Configuring " + component + " in " + builddir) 477*9880d681SAndroid Build Coastguard Worker configrc = self.configure(component, srcdir, builddir, 478*9880d681SAndroid Build Coastguard Worker config_args, 479*9880d681SAndroid Build Coastguard Worker configure_env[comp_key][build]) 480*9880d681SAndroid Build Coastguard Worker 481*9880d681SAndroid Build Coastguard Worker if (configrc == None) : 482*9880d681SAndroid Build Coastguard Worker self.logger.info("[None] Failed to configure " + component + " in " + installdir) 483*9880d681SAndroid Build Coastguard Worker 484*9880d681SAndroid Build Coastguard Worker if (configrc == 0 or self.options.keep_going) : 485*9880d681SAndroid Build Coastguard Worker self.logger.info("Building " + component + " in " + builddir) 486*9880d681SAndroid Build Coastguard Worker self.logger.info("Build: make " + str(make_flags[comp_key][build])) 487*9880d681SAndroid Build Coastguard Worker buildrc = self.make(component, srcdir, builddir, 488*9880d681SAndroid Build Coastguard Worker make_flags[comp_key][build], 489*9880d681SAndroid Build Coastguard Worker make_env[comp_key][build]) 490*9880d681SAndroid Build Coastguard Worker 491*9880d681SAndroid Build Coastguard Worker if (buildrc == None) : 492*9880d681SAndroid Build Coastguard Worker self.logger.info("[None] Failed to build " + component + " in " + installdir) 493*9880d681SAndroid Build Coastguard Worker 494*9880d681SAndroid Build Coastguard Worker if (buildrc == 0 or self.options.keep_going) : 495*9880d681SAndroid Build Coastguard Worker self.logger.info("Testing " + component + " in " + builddir) 496*9880d681SAndroid Build Coastguard Worker self.logger.info("Test: make " 497*9880d681SAndroid Build Coastguard Worker + str(make_check_flags[comp_key][build])) 498*9880d681SAndroid Build Coastguard Worker testrc = self.make(component, srcdir, builddir, 499*9880d681SAndroid Build Coastguard Worker make_check_flags[comp_key][build], 500*9880d681SAndroid Build Coastguard Worker make_check_env[comp_key][build]) 501*9880d681SAndroid Build Coastguard Worker 502*9880d681SAndroid Build Coastguard Worker if (testrc == None) : 503*9880d681SAndroid Build Coastguard Worker self.logger.info("[None] Failed to test " + component + " in " + installdir) 504*9880d681SAndroid Build Coastguard Worker 505*9880d681SAndroid Build Coastguard Worker if ((testrc == 0 or self.options.keep_going) 506*9880d681SAndroid Build Coastguard Worker and not self.options.no_install): 507*9880d681SAndroid Build Coastguard Worker self.logger.info("Installing " + component + " in " + installdir) 508*9880d681SAndroid Build Coastguard Worker self.make(component, srcdir, builddir, 509*9880d681SAndroid Build Coastguard Worker make_install_flags[comp_key][build], 510*9880d681SAndroid Build Coastguard Worker make_install_env[comp_key][build]) 511*9880d681SAndroid Build Coastguard Worker else : 512*9880d681SAndroid Build Coastguard Worker self.logger.info("Failed testing " + component + " in " + installdir) 513*9880d681SAndroid Build Coastguard Worker 514*9880d681SAndroid Build Coastguard Worker else : 515*9880d681SAndroid Build Coastguard Worker self.logger.info("Failed to build " + component + " in " + installdir) 516*9880d681SAndroid Build Coastguard Worker 517*9880d681SAndroid Build Coastguard Worker else : 518*9880d681SAndroid Build Coastguard Worker self.logger.info("Failed to configure " + component + " in " + installdir) 519*9880d681SAndroid Build Coastguard Worker 520*9880d681SAndroid Build Coastguard Worker def configure(self, component, srcdir, builddir, flags, env): 521*9880d681SAndroid Build Coastguard Worker prefix = self.component_abbrev[component.replace("-", "_")] 522*9880d681SAndroid Build Coastguard Worker 523*9880d681SAndroid Build Coastguard Worker self.logger.debug("Configure " + str(flags) + " " + str(srcdir) + " -> " 524*9880d681SAndroid Build Coastguard Worker + str(builddir)) 525*9880d681SAndroid Build Coastguard Worker 526*9880d681SAndroid Build Coastguard Worker configure_files = dict( 527*9880d681SAndroid Build Coastguard Worker llvm=[(srcdir + "/configure", builddir + "/Makefile")], 528*9880d681SAndroid Build Coastguard Worker dragonegg=[(None,None)]) 529*9880d681SAndroid Build Coastguard Worker 530*9880d681SAndroid Build Coastguard Worker 531*9880d681SAndroid Build Coastguard Worker doconfig = False 532*9880d681SAndroid Build Coastguard Worker for conf, mf in configure_files[component.replace("-", "_")]: 533*9880d681SAndroid Build Coastguard Worker if conf is None: 534*9880d681SAndroid Build Coastguard Worker # No configure necessary 535*9880d681SAndroid Build Coastguard Worker return 0 536*9880d681SAndroid Build Coastguard Worker 537*9880d681SAndroid Build Coastguard Worker if not os.path.exists(conf): 538*9880d681SAndroid Build Coastguard Worker self.logger.info("[" + prefix + "] Configure failed, no configure script " + conf) 539*9880d681SAndroid Build Coastguard Worker return -1 540*9880d681SAndroid Build Coastguard Worker 541*9880d681SAndroid Build Coastguard Worker if os.path.exists(conf) and os.path.exists(mf): 542*9880d681SAndroid Build Coastguard Worker confstat = os.stat(conf) 543*9880d681SAndroid Build Coastguard Worker makestat = os.stat(mf) 544*9880d681SAndroid Build Coastguard Worker if confstat.st_mtime > makestat.st_mtime: 545*9880d681SAndroid Build Coastguard Worker doconfig = True 546*9880d681SAndroid Build Coastguard Worker break 547*9880d681SAndroid Build Coastguard Worker else: 548*9880d681SAndroid Build Coastguard Worker doconfig = True 549*9880d681SAndroid Build Coastguard Worker break 550*9880d681SAndroid Build Coastguard Worker 551*9880d681SAndroid Build Coastguard Worker if not doconfig and not self.options.force_configure: 552*9880d681SAndroid Build Coastguard Worker return 0 553*9880d681SAndroid Build Coastguard Worker 554*9880d681SAndroid Build Coastguard Worker program = srcdir + "/configure" 555*9880d681SAndroid Build Coastguard Worker if not is_executable(program): 556*9880d681SAndroid Build Coastguard Worker self.logger.info("[" + prefix + "] Configure failed, cannot execute " + program) 557*9880d681SAndroid Build Coastguard Worker return -1 558*9880d681SAndroid Build Coastguard Worker 559*9880d681SAndroid Build Coastguard Worker args = [program] 560*9880d681SAndroid Build Coastguard Worker args += ["--verbose"] 561*9880d681SAndroid Build Coastguard Worker args += flags 562*9880d681SAndroid Build Coastguard Worker return self.execute(args, builddir, env, component) 563*9880d681SAndroid Build Coastguard Worker 564*9880d681SAndroid Build Coastguard Worker def make(self, component, srcdir, builddir, flags, env): 565*9880d681SAndroid Build Coastguard Worker program = find_executable("make") 566*9880d681SAndroid Build Coastguard Worker if program is None: 567*9880d681SAndroid Build Coastguard Worker raise ExecutableNotFound 568*9880d681SAndroid Build Coastguard Worker 569*9880d681SAndroid Build Coastguard Worker if not is_executable(program): 570*9880d681SAndroid Build Coastguard Worker raise FileNotExecutable 571*9880d681SAndroid Build Coastguard Worker 572*9880d681SAndroid Build Coastguard Worker args = [program] 573*9880d681SAndroid Build Coastguard Worker args += flags 574*9880d681SAndroid Build Coastguard Worker return self.execute(args, builddir, env, component) 575*9880d681SAndroid Build Coastguard Worker 576*9880d681SAndroid Build Coastguard Worker# Global constants 577*9880d681SAndroid Build Coastguard Workerbuild_abbrev = dict(debug="dbg", release="opt", paranoid="par") 578*9880d681SAndroid Build Coastguard Workercomponents = ["llvm", "dragonegg"] 579*9880d681SAndroid Build Coastguard Worker 580*9880d681SAndroid Build Coastguard Worker# Parse options 581*9880d681SAndroid Build Coastguard Workerparser = optparse.OptionParser(version="%prog 1.0") 582*9880d681SAndroid Build Coastguard Workeradd_options(parser) 583*9880d681SAndroid Build Coastguard Worker(options, args) = parser.parse_args() 584*9880d681SAndroid Build Coastguard Workercheck_options(parser, options, build_abbrev.keys()); 585*9880d681SAndroid Build Coastguard Worker 586*9880d681SAndroid Build Coastguard Workerif options.verbose: 587*9880d681SAndroid Build Coastguard Worker logging.basicConfig(level=logging.DEBUG, 588*9880d681SAndroid Build Coastguard Worker format='%(name)-13s: %(message)s') 589*9880d681SAndroid Build Coastguard Workerelse: 590*9880d681SAndroid Build Coastguard Worker logging.basicConfig(level=logging.INFO, 591*9880d681SAndroid Build Coastguard Worker format='%(name)-13s: %(message)s') 592*9880d681SAndroid Build Coastguard Worker 593*9880d681SAndroid Build Coastguard Workersource_abbrev = get_path_abbrevs(set(options.src)) 594*9880d681SAndroid Build Coastguard Worker 595*9880d681SAndroid Build Coastguard Workerwork_queue = queue.Queue() 596*9880d681SAndroid Build Coastguard Worker 597*9880d681SAndroid Build Coastguard Workerjobs = options.jobs // options.threads 598*9880d681SAndroid Build Coastguard Workerif jobs == 0: 599*9880d681SAndroid Build Coastguard Worker jobs = 1 600*9880d681SAndroid Build Coastguard Worker 601*9880d681SAndroid Build Coastguard Workernumthreads = options.threads 602*9880d681SAndroid Build Coastguard Worker 603*9880d681SAndroid Build Coastguard Workerlogging.getLogger().info("Building with " + str(options.jobs) + " jobs and " 604*9880d681SAndroid Build Coastguard Worker + str(numthreads) + " threads using " + str(jobs) 605*9880d681SAndroid Build Coastguard Worker + " make jobs") 606*9880d681SAndroid Build Coastguard Worker 607*9880d681SAndroid Build Coastguard Workerlogging.getLogger().info("CC = " + str(options.cc)) 608*9880d681SAndroid Build Coastguard Workerlogging.getLogger().info("CXX = " + str(options.cxx)) 609*9880d681SAndroid Build Coastguard Worker 610*9880d681SAndroid Build Coastguard Workerfor t in range(numthreads): 611*9880d681SAndroid Build Coastguard Worker builder = Builder(work_queue, jobs, 612*9880d681SAndroid Build Coastguard Worker build_abbrev, source_abbrev, 613*9880d681SAndroid Build Coastguard Worker options) 614*9880d681SAndroid Build Coastguard Worker builder.daemon = True 615*9880d681SAndroid Build Coastguard Worker builder.start() 616*9880d681SAndroid Build Coastguard Worker 617*9880d681SAndroid Build Coastguard Workerfor build in set(options.build): 618*9880d681SAndroid Build Coastguard Worker for source in set(options.src): 619*9880d681SAndroid Build Coastguard Worker work_queue.put((source, build)) 620*9880d681SAndroid Build Coastguard Worker 621*9880d681SAndroid Build Coastguard Workerwork_queue.join() 622