blob: f7eecfc86b5633b82522132dfa57d549b511eb70 [file] [log] [blame]
David Greene8b8b4af2011-02-21 19:23:22 +00001#!/usr/bin/python3
2##===- utils/llvmbuild - Build the LLVM project ----------------*-python-*-===##
3#
4# The LLVM Compiler Infrastructure
5#
6# This file is distributed under the University of Illinois Open Source
7# License. See LICENSE.TXT for details.
8#
9##===----------------------------------------------------------------------===##
10#
11# This script builds many different flavors of the LLVM ecosystem. It
David Greene0c6e1772012-01-27 23:01:35 +000012# will build LLVM, Clang and dragonegg as well as run tests on them.
13# This script is convenient to use to check builds and tests before
14# committing changes to the upstream repository
David Greene8b8b4af2011-02-21 19:23:22 +000015#
16# A typical source setup uses three trees and looks like this:
17#
18# official
19# dragonegg
David Greene8b8b4af2011-02-21 19:23:22 +000020# llvm
David Greene0c6e1772012-01-27 23:01:35 +000021# tools
22# clang
David Greene8b8b4af2011-02-21 19:23:22 +000023# staging
24# dragonegg
David Greene8b8b4af2011-02-21 19:23:22 +000025# llvm
David Greene0c6e1772012-01-27 23:01:35 +000026# tools
27# clang
David Greene8b8b4af2011-02-21 19:23:22 +000028# commit
29# dragonegg
David Greene8b8b4af2011-02-21 19:23:22 +000030# llvm
David Greene0c6e1772012-01-27 23:01:35 +000031# tools
32# clang
David Greene8b8b4af2011-02-21 19:23:22 +000033#
34# In a typical workflow, the "official" tree always contains unchanged
35# sources from the main LLVM project repositories. The "staging" tree
36# is where local work is done. A set of changes resides there waiting
37# to be moved upstream. The "commit" tree is where changes from
38# "staging" make their way upstream. Individual incremental changes
39# from "staging" are applied to "commit" and committed upstream after
40# a successful build and test run. A successful build is one in which
41# testing results in no more failures than seen in the testing of the
42# "official" tree.
43#
44# A build may be invoked as such:
45#
David Greene0c6e1772012-01-27 23:01:35 +000046# llvmbuild --src=~/llvm/commit --src=~/llvm/staging --src=~/llvm/official
David Greene8b8b4af2011-02-21 19:23:22 +000047# --build=debug --build=release --build=paranoid
48# --prefix=/home/greened/install --builddir=/home/greened/build
49#
David Greene0c6e1772012-01-27 23:01:35 +000050# This will build the LLVM ecosystem, including LLVM, Clangand
51# dragonegg, putting build results in ~/build and installing tools in
52# ~/install. llvm-compilers-check creates separate build and install
53# directories for each source/build flavor. In the above example,
54# llvmbuild will build debug, release and paranoid (debug+checks)
55# flavors from each source tree (official, staging and commit) for a
56# total of nine builds. All builds will be run in parallel.
David Greene8b8b4af2011-02-21 19:23:22 +000057#
58# The user may control parallelism via the --jobs and --threads
David Greene0c6e1772012-01-27 23:01:35 +000059# switches. --jobs tells llvm-compilers-checl the maximum total
60# number of builds to activate in parallel. The user may think of it
61# as equivalent to the GNU make -j switch. --threads tells
62# llvm-compilers-check how many worker threads to use to accomplish
63# those builds. If --threads is less than --jobs, --threads workers
64# will be launched and each one will pick a source/flavor combination
65# to build. Then llvm-compilers-check will invoke GNU make with -j
66# (--jobs / --threads) to use up the remaining job capacity. Once a
67# worker is finished with a build, it will pick another combination
68# off the list and start building it.
David Greene8b8b4af2011-02-21 19:23:22 +000069#
70##===----------------------------------------------------------------------===##
71
72import optparse
73import os
74import sys
75import threading
76import queue
77import logging
78import traceback
79import subprocess
80import re
81
82# TODO: Use shutil.which when it is available (3.2 or later)
83def find_executable(executable, path=None):
84 """Try to find 'executable' in the directories listed in 'path' (a
85 string listing directories separated by 'os.pathsep'; defaults to
86 os.environ['PATH']). Returns the complete filename or None if not
87 found
88 """
89 if path is None:
90 path = os.environ['PATH']
91 paths = path.split(os.pathsep)
92 extlist = ['']
93 if os.name == 'os2':
94 (base, ext) = os.path.splitext(executable)
95 # executable files on OS/2 can have an arbitrary extension, but
96 # .exe is automatically appended if no dot is present in the name
97 if not ext:
98 executable = executable + ".exe"
99 elif sys.platform == 'win32':
100 pathext = os.environ['PATHEXT'].lower().split(os.pathsep)
101 (base, ext) = os.path.splitext(executable)
102 if ext.lower() not in pathext:
103 extlist = pathext
104 for ext in extlist:
105 execname = executable + ext
106 if os.path.isfile(execname):
107 return execname
108 else:
109 for p in paths:
110 f = os.path.join(p, execname)
111 if os.path.isfile(f):
112 return f
113 else:
114 return None
115
116def is_executable(fpath):
117 return os.path.exists(fpath) and os.access(fpath, os.X_OK)
118
119def add_options(parser):
120 parser.add_option("-v", "--verbose", action="store_true",
121 default=False,
122 help=("Output informational messages"
123 " [default: %default]"))
124 parser.add_option("--src", action="append",
125 help=("Top-level source directory [default: %default]"))
David Greene14a129a2011-02-25 20:51:27 +0000126 parser.add_option("--build", action="append",
David Greene8b8b4af2011-02-21 19:23:22 +0000127 help=("Build types to run [default: %default]"))
David Greene8b8b4af2011-02-21 19:23:22 +0000128 parser.add_option("--cc", default=find_executable("cc"),
129 help=("The C compiler to use [default: %default]"))
130 parser.add_option("--cxx", default=find_executable("c++"),
131 help=("The C++ compiler to use [default: %default]"))
132 parser.add_option("--threads", default=4, type="int",
133 help=("The number of worker threads to use "
134 "[default: %default]"))
135 parser.add_option("--jobs", "-j", default=8, type="int",
136 help=("The number of simultaneous build jobs "
137 "[default: %default]"))
138 parser.add_option("--prefix",
139 help=("Root install directory [default: %default]"))
140 parser.add_option("--builddir",
141 help=("Root build directory [default: %default]"))
David Greene14a129a2011-02-25 20:51:27 +0000142 parser.add_option("--extra-llvm-config-flags", default="",
143 help=("Extra flags to pass to llvm configure [default: %default]"))
David Greene14a129a2011-02-25 20:51:27 +0000144 parser.add_option("--force-configure", default=False, action="store_true",
145 help=("Force reconfigure of all components"))
David Greene0c6e1772012-01-27 23:01:35 +0000146 parser.add_option("--no-dragonegg", default=False, action="store_true",
147 help=("Do not build dragonegg"))
David Greenecdc3fbc2011-10-14 19:12:34 +0000148 parser.add_option("--no-install", default=False, action="store_true",
149 help=("Do not do installs"))
David Greene8b8b4af2011-02-21 19:23:22 +0000150 return
151
152def check_options(parser, options, valid_builds):
153 # See if we're building valid flavors.
154 for build in options.build:
155 if (build not in valid_builds):
156 parser.error("'" + build + "' is not a valid build flavor "
157 + str(valid_builds))
158
159 # See if we can find source directories.
160 for src in options.src:
David Greenee234cd92011-07-06 16:54:14 +0000161 for component in components:
162 component = component.rstrip("2")
David Greene8b8b4af2011-02-21 19:23:22 +0000163 compsrc = src + "/" + component
164 if (not os.path.isdir(compsrc)):
165 parser.error("'" + compsrc + "' does not exist")
David Greene8b8b4af2011-02-21 19:23:22 +0000166
167 # See if we can find the compilers
168 options.cc = find_executable(options.cc)
169 options.cxx = find_executable(options.cxx)
170
171 return
172
173# Find a unique short name for the given set of paths. This searches
174# back through path components until it finds unique component names
175# among all given paths.
176def get_path_abbrevs(paths):
177 # Find the number of common starting characters in the last component
178 # of the paths.
179 unique_paths = list(paths)
180
181 class NotFoundException(Exception): pass
182
183 # Find a unique component of each path.
184 unique_bases = unique_paths[:]
185 found = 0
186 while len(unique_paths) > 0:
187 bases = [os.path.basename(src) for src in unique_paths]
188 components = { c for c in bases }
189 # Account for single entry in paths.
190 if len(components) > 1 or len(components) == len(bases):
191 # We found something unique.
192 for c in components:
193 if bases.count(c) == 1:
194 index = bases.index(c)
195 unique_bases[index] = c
196 # Remove the corresponding path from the set under
197 # consideration.
198 unique_paths[index] = None
199 unique_paths = [ p for p in unique_paths if p is not None ]
200 unique_paths = [os.path.dirname(src) for src in unique_paths]
201
202 if len(unique_paths) > 0:
203 raise NotFoundException()
204
205 abbrevs = dict(zip(paths, [base for base in unique_bases]))
206
207 return abbrevs
208
209# Given a set of unique names, find a short character sequence that
210# uniquely identifies them.
211def get_short_abbrevs(unique_bases):
212 # Find a unique start character for each path base.
213 my_unique_bases = unique_bases[:]
214 unique_char_starts = unique_bases[:]
215 while len(my_unique_bases) > 0:
216 for start, char_tuple in enumerate(zip(*[base
217 for base in my_unique_bases])):
218 chars = { c for c in char_tuple }
219 # Account for single path.
220 if len(chars) > 1 or len(chars) == len(char_tuple):
221 # We found something unique.
222 for c in chars:
223 if char_tuple.count(c) == 1:
224 index = char_tuple.index(c)
225 unique_char_starts[index] = start
226 # Remove the corresponding path from the set under
227 # consideration.
228 my_unique_bases[index] = None
229 my_unique_bases = [ b for b in my_unique_bases
230 if b is not None ]
231 break
232
233 if len(my_unique_bases) > 0:
234 raise NotFoundException()
235
236 abbrevs = [abbrev[start_index:start_index+3]
237 for abbrev, start_index
238 in zip([base for base in unique_bases],
239 [index for index in unique_char_starts])]
240
241 abbrevs = dict(zip(unique_bases, abbrevs))
242
243 return abbrevs
244
245class Builder(threading.Thread):
246 class ExecutableNotFound(Exception): pass
247 class FileNotExecutable(Exception): pass
248
David Greene14a129a2011-02-25 20:51:27 +0000249 def __init__(self, work_queue, jobs,
David Greene0c6e1772012-01-27 23:01:35 +0000250 build_abbrev, source_abbrev,
David Greene14a129a2011-02-25 20:51:27 +0000251 options):
David Greene8b8b4af2011-02-21 19:23:22 +0000252 super().__init__()
253 self.work_queue = work_queue
254 self.jobs = jobs
David Greene14a129a2011-02-25 20:51:27 +0000255 self.cc = options.cc
256 self.cxx = options.cxx
David Greene8b8b4af2011-02-21 19:23:22 +0000257 self.build_abbrev = build_abbrev
258 self.source_abbrev = source_abbrev
David Greene14a129a2011-02-25 20:51:27 +0000259 self.build_prefix = options.builddir
260 self.install_prefix = options.prefix
261 self.options = options
David Greene8b8b4af2011-02-21 19:23:22 +0000262 self.component_abbrev = dict(
263 llvm="llvm",
David Greene0c6e1772012-01-27 23:01:35 +0000264 dragonegg="degg")
David Greene8b8b4af2011-02-21 19:23:22 +0000265 def run(self):
266 while True:
267 try:
David Greene0c6e1772012-01-27 23:01:35 +0000268 source, build = self.work_queue.get()
269 self.dobuild(source, build)
David Greene8b8b4af2011-02-21 19:23:22 +0000270 except:
271 traceback.print_exc()
272 finally:
273 self.work_queue.task_done()
274
275 def execute(self, command, execdir, env, component):
276 prefix = self.component_abbrev[component.replace("-", "_")]
277 pwd = os.getcwd()
278 if not os.path.exists(execdir):
279 os.makedirs(execdir)
280
David Greene8b890c22011-02-22 23:30:45 +0000281 execenv = os.environ.copy()
282
David Greene8b8b4af2011-02-21 19:23:22 +0000283 for key, value in env.items():
David Greene8b890c22011-02-22 23:30:45 +0000284 execenv[key] = value
David Greene8b8b4af2011-02-21 19:23:22 +0000285
286 self.logger.debug("[" + prefix + "] " + "env " + str(env) + " "
287 + " ".join(command));
288
289 try:
290 proc = subprocess.Popen(command,
291 cwd=execdir,
David Greene8b890c22011-02-22 23:30:45 +0000292 env=execenv,
David Greene8b8b4af2011-02-21 19:23:22 +0000293 stdout=subprocess.PIPE,
294 stderr=subprocess.STDOUT)
295
296 line = proc.stdout.readline()
297 while line:
298 self.logger.info("[" + prefix + "] "
299 + str(line, "utf-8").rstrip())
300 line = proc.stdout.readline()
301
302 except:
303 traceback.print_exc()
304
David Greene8b8b4af2011-02-21 19:23:22 +0000305 # Get a list of C++ include directories to pass to clang.
306 def get_includes(self):
307 # Assume we're building with g++ for now.
308 command = [self.cxx]
309 command += ["-v", "-x", "c++", "/dev/null", "-fsyntax-only"]
310 includes = []
311 self.logger.debug(command)
312 try:
313 proc = subprocess.Popen(command,
314 stdout=subprocess.PIPE,
315 stderr=subprocess.STDOUT)
316
317 gather = False
318 line = proc.stdout.readline()
319 while line:
320 self.logger.debug(line)
321 if re.search("End of search list", str(line)) is not None:
322 self.logger.debug("Stop Gather")
323 gather = False
324 if gather:
325 includes.append(str(line, "utf-8").strip())
326 if re.search("#include <...> search starts", str(line)) is not None:
327 self.logger.debug("Start Gather")
328 gather = True
329 line = proc.stdout.readline()
330 except:
331 traceback.print_exc()
332 self.logger.debug(includes)
333 return includes
334
David Greene0c6e1772012-01-27 23:01:35 +0000335 def dobuild(self, source, build):
David Greene8b8b4af2011-02-21 19:23:22 +0000336 build_suffix = ""
337
338 ssabbrev = get_short_abbrevs([ab for ab in self.source_abbrev.values()])
339
David Greene0c6e1772012-01-27 23:01:35 +0000340 prefix = "[" + ssabbrev[self.source_abbrev[source]] + "-" + self.build_abbrev[build] + "]"
341 self.install_prefix += "/" + self.source_abbrev[source] + "/" + build
342 build_suffix += "/" + self.source_abbrev[source] + "/" + build
David Greene8b8b4af2011-02-21 19:23:22 +0000343
344 self.logger = logging.getLogger(prefix)
345
346 self.logger.debug(self.install_prefix)
347
348 # Assume we're building with gcc for now.
349 cxxincludes = self.get_includes()
350 cxxroot = cxxincludes[0]
351 cxxarch = os.path.basename(cxxincludes[1])
352
353 configure_flags = dict(
354 llvm=dict(debug=["--prefix=" + self.install_prefix,
David Greene14a129a2011-02-25 20:51:27 +0000355 "--with-extra-options=-Werror",
David Greenee234cd92011-07-06 16:54:14 +0000356 "--enable-assertions",
357 "--disable-optimized",
David Greene8b8b4af2011-02-21 19:23:22 +0000358 "--with-cxx-include-root=" + cxxroot,
359 "--with-cxx-include-arch=" + cxxarch],
360 release=["--prefix=" + self.install_prefix,
David Greene14a129a2011-02-25 20:51:27 +0000361 "--with-extra-options=-Werror",
David Greene8b8b4af2011-02-21 19:23:22 +0000362 "--enable-optimized",
363 "--with-cxx-include-root=" + cxxroot,
364 "--with-cxx-include-arch=" + cxxarch],
365 paranoid=["--prefix=" + self.install_prefix,
David Greene14a129a2011-02-25 20:51:27 +0000366 "--with-extra-options=-Werror",
David Greenee234cd92011-07-06 16:54:14 +0000367 "--enable-assertions",
David Greene8b8b4af2011-02-21 19:23:22 +0000368 "--enable-expensive-checks",
David Greenee234cd92011-07-06 16:54:14 +0000369 "--disable-optimized",
David Greene8b8b4af2011-02-21 19:23:22 +0000370 "--with-cxx-include-root=" + cxxroot,
371 "--with-cxx-include-arch=" + cxxarch]),
David Greene8b8b4af2011-02-21 19:23:22 +0000372 dragonegg=dict(debug=[],
373 release=[],
374 paranoid=[]))
375
376 configure_env = dict(
377 llvm=dict(debug=dict(CC=self.cc,
378 CXX=self.cxx),
379 release=dict(CC=self.cc,
380 CXX=self.cxx),
381 paranoid=dict(CC=self.cc,
382 CXX=self.cxx)),
David Greene8b8b4af2011-02-21 19:23:22 +0000383 dragonegg=dict(debug=dict(CC=self.cc,
384 CXX=self.cxx),
385 release=dict(CC=self.cc,
386 CXX=self.cxx),
387 paranoid=dict(CC=self.cc,
388 CXX=self.cxx)))
389
390 make_flags = dict(
391 llvm=dict(debug=["-j" + str(self.jobs)],
392 release=["-j" + str(self.jobs)],
393 paranoid=["-j" + str(self.jobs)]),
David Greene8b8b4af2011-02-21 19:23:22 +0000394 dragonegg=dict(debug=["-j" + str(self.jobs)],
395 release=["-j" + str(self.jobs)],
396 paranoid=["-j" + str(self.jobs)]))
397
398 make_env = dict(
399 llvm=dict(debug=dict(),
400 release=dict(),
401 paranoid=dict()),
David Greene0c6e1772012-01-27 23:01:35 +0000402 dragonegg=dict(debug=dict(GCC=self.cc,
David Greene8b8b4af2011-02-21 19:23:22 +0000403 LLVM_CONFIG=self.install_prefix + "/bin/llvm-config"),
David Greene0c6e1772012-01-27 23:01:35 +0000404 release=dict(GCC=self.cc,
David Greene8b8b4af2011-02-21 19:23:22 +0000405 LLVM_CONFIG=self.install_prefix + "/bin/llvm-config"),
David Greene0c6e1772012-01-27 23:01:35 +0000406 paranoid=dict(GCC=self.cc,
David Greene8b8b4af2011-02-21 19:23:22 +0000407 LLVM_CONFIG=self.install_prefix + "/bin/llvm-config")))
408
409 make_install_flags = dict(
410 llvm=dict(debug=["install"],
411 release=["install"],
412 paranoid=["install"]),
David Greene8b8b4af2011-02-21 19:23:22 +0000413 dragonegg=dict(debug=["install"],
414 release=["install"],
415 paranoid=["install"]))
416
417 make_install_env = dict(
418 llvm=dict(debug=dict(),
419 release=dict(),
420 paranoid=dict()),
David Greene8b8b4af2011-02-21 19:23:22 +0000421 dragonegg=dict(debug=dict(),
422 release=dict(),
423 paranoid=dict()))
424
425 make_check_flags = dict(
426 llvm=dict(debug=["check"],
427 release=["check"],
428 paranoid=["check"]),
David Greene8b8b4af2011-02-21 19:23:22 +0000429 dragonegg=dict(debug=["check"],
430 release=["check"],
431 paranoid=["check"]))
432
433 make_check_env = dict(
434 llvm=dict(debug=dict(),
435 release=dict(),
436 paranoid=dict()),
David Greene8b8b4af2011-02-21 19:23:22 +0000437 dragonegg=dict(debug=dict(),
438 release=dict(),
439 paranoid=dict()))
440
David Greenee234cd92011-07-06 16:54:14 +0000441 for component in components:
David Greene8b8b4af2011-02-21 19:23:22 +0000442 comp = component[:]
David Greened17f8132011-10-14 19:12:33 +0000443
David Greene0c6e1772012-01-27 23:01:35 +0000444 if (self.options.no_dragonegg):
445 if (comp == 'dragonegg'):
David Greened17f8132011-10-14 19:12:33 +0000446 self.logger.info("Skipping " + component + " in "
447 + builddir)
448 continue
David Greene8b8b4af2011-02-21 19:23:22 +0000449
450 srcdir = source + "/" + comp.rstrip("2")
451 builddir = self.build_prefix + "/" + comp + "/" + build_suffix
452 installdir = self.install_prefix
453
David Greene14a129a2011-02-25 20:51:27 +0000454 comp_key = comp.replace("-", "_")
455
456 config_args = configure_flags[comp_key][build][:]
457 config_args.extend(getattr(self.options,
David Greenee234cd92011-07-06 16:54:14 +0000458 "extra_" + comp_key.rstrip("2")
David Greene0c6e1772012-01-27 23:01:35 +0000459 + "_config_flags",
460 "").split())
David Greene14a129a2011-02-25 20:51:27 +0000461
David Greene8b8b4af2011-02-21 19:23:22 +0000462 self.logger.info("Configuring " + component + " in " + builddir)
463 self.configure(component, srcdir, builddir,
David Greene14a129a2011-02-25 20:51:27 +0000464 config_args,
465 configure_env[comp_key][build])
David Greene8b8b4af2011-02-21 19:23:22 +0000466
467 self.logger.info("Building " + component + " in " + builddir)
David Greene8e20b942011-10-14 19:12:35 +0000468 self.logger.info("Build: make " + str(make_flags[comp_key][build]))
David Greene8b8b4af2011-02-21 19:23:22 +0000469 self.make(component, srcdir, builddir,
David Greene14a129a2011-02-25 20:51:27 +0000470 make_flags[comp_key][build],
471 make_env[comp_key][build])
David Greene8b8b4af2011-02-21 19:23:22 +0000472
David Greenecdc3fbc2011-10-14 19:12:34 +0000473 if (not self.options.no_install):
474 self.logger.info("Installing " + component + " in " + installdir)
475 self.make(component, srcdir, builddir,
476 make_install_flags[comp_key][build],
477 make_install_env[comp_key][build])
David Greene8b8b4af2011-02-21 19:23:22 +0000478
479 self.logger.info("Testing " + component + " in " + builddir)
David Greene8e20b942011-10-14 19:12:35 +0000480 self.logger.info("Test: make "
481 + str(make_check_flags[comp_key][build]))
David Greene8b8b4af2011-02-21 19:23:22 +0000482 self.make(component, srcdir, builddir,
David Greene14a129a2011-02-25 20:51:27 +0000483 make_check_flags[comp_key][build],
484 make_check_env[comp_key][build])
David Greene8b8b4af2011-02-21 19:23:22 +0000485
486
487 def configure(self, component, srcdir, builddir, flags, env):
David Greeneb1939d52011-03-04 23:02:52 +0000488 self.logger.debug("Configure " + str(flags) + " " + str(srcdir) + " -> "
489 + str(builddir))
David Greene14a129a2011-02-25 20:51:27 +0000490
David Greene8b8b4af2011-02-21 19:23:22 +0000491 configure_files = dict(
492 llvm=[(srcdir + "/configure", builddir + "/Makefile")],
David Greene0c6e1772012-01-27 23:01:35 +0000493 dragonegg=[("","")])
David Greene8b8b4af2011-02-21 19:23:22 +0000494
David Greene14a129a2011-02-25 20:51:27 +0000495
David Greene8b8b4af2011-02-21 19:23:22 +0000496 doconfig = False
497 for conf, mf in configure_files[component.replace("-", "_")]:
David Greene14a129a2011-02-25 20:51:27 +0000498 if not os.path.exists(conf):
499 return
David Greene8b8b4af2011-02-21 19:23:22 +0000500 if os.path.exists(conf) and os.path.exists(mf):
501 confstat = os.stat(conf)
502 makestat = os.stat(mf)
503 if confstat.st_mtime > makestat.st_mtime:
504 doconfig = True
505 break
506 else:
507 doconfig = True
508 break
509
David Greene14a129a2011-02-25 20:51:27 +0000510 if not doconfig and not self.options.force_configure:
David Greene8b8b4af2011-02-21 19:23:22 +0000511 return
512
513 program = srcdir + "/configure"
514 if not is_executable(program):
515 return
516
517 args = [program]
518 args += ["--verbose"]
519 args += flags
520 self.execute(args, builddir, env, component)
521
522 def make(self, component, srcdir, builddir, flags, env):
523 program = find_executable("make")
524 if program is None:
525 raise ExecutableNotFound
526
527 if not is_executable(program):
528 raise FileNotExecutable
529
530 args = [program]
531 args += flags
532 self.execute(args, builddir, env, component)
533
534# Global constants
535build_abbrev = dict(debug="dbg", release="opt", paranoid="par")
David Greene0c6e1772012-01-27 23:01:35 +0000536components = ["llvm", "dragonegg"]
David Greene8b8b4af2011-02-21 19:23:22 +0000537
538# Parse options
539parser = optparse.OptionParser(version="%prog 1.0")
540add_options(parser)
541(options, args) = parser.parse_args()
542check_options(parser, options, build_abbrev.keys());
543
544if options.verbose:
545 logging.basicConfig(level=logging.DEBUG,
546 format='%(name)-13s: %(message)s')
547else:
548 logging.basicConfig(level=logging.INFO,
549 format='%(name)-13s: %(message)s')
550
551source_abbrev = get_path_abbrevs(set(options.src))
David Greenee234cd92011-07-06 16:54:14 +0000552
David Greene8b8b4af2011-02-21 19:23:22 +0000553work_queue = queue.Queue()
554
David Greeneb1939d52011-03-04 23:02:52 +0000555jobs = options.jobs // options.threads
556if jobs == 0:
557 jobs = 1
558
559numthreads = options.threads
David Greenebc5c49b2011-10-14 19:12:37 +0000560
561logging.getLogger().info("Building with " + str(options.jobs) + " jobs and "
562 + str(numthreads) + " threads using " + str(jobs)
563 + " make jobs")
David Greeneb1939d52011-03-04 23:02:52 +0000564
David Greene0c6e1772012-01-27 23:01:35 +0000565logging.getLogger().info("CC = " + str(options.cc))
566logging.getLogger().info("CXX = " + str(options.cxx))
567
David Greeneb1939d52011-03-04 23:02:52 +0000568for t in range(numthreads):
David Greene14a129a2011-02-25 20:51:27 +0000569 builder = Builder(work_queue, jobs,
David Greene0c6e1772012-01-27 23:01:35 +0000570 build_abbrev, source_abbrev,
David Greene14a129a2011-02-25 20:51:27 +0000571 options)
David Greene8b8b4af2011-02-21 19:23:22 +0000572 builder.daemon = True
573 builder.start()
574
575for build in set(options.build):
576 for source in set(options.src):
David Greene0c6e1772012-01-27 23:01:35 +0000577 work_queue.put((source, build))
David Greene8b8b4af2011-02-21 19:23:22 +0000578
579work_queue.join()