blob: 06bce837b94ecd3a670e2a445b1cebeb690dc587 [file] [log] [blame]
# TODO: Change WithProperties to Interpolate
# TODO: Consider setting codebase to llvm-project.
from collections import OrderedDict
from buildbot.process.factory import BuildFactory
from buildbot.plugins import util, steps
_all_runtimes = frozenset([
"compiler-rt",
"libc",
"libcxx",
"libcxxabi",
"libunwind",
"openmp",
])
class LLVMBuildFactory(BuildFactory):
"""
TODO: Document
depends_on_projects is a list of LLVM projects a produced builder
depends on. If None, it gets discovered depending on other params.
enable_runtimes is a list of enabled runtimes. If None,
it gets discovered based on the depends_on_projects list.
"""
def __init__(self, steps=None, depends_on_projects=None, **kwargs):
# Cannot use "super" here as BuildFactory is an old style class.
BuildFactory.__init__(self, steps)
# Handle the dependencies.
if depends_on_projects is None:
# llvm project is always included.
self.depends_on_projects = set(['llvm'])
else:
self.depends_on_projects = frozenset(depends_on_projects)
enable_runtimes = kwargs.pop('enable_runtimes', None)
# If specified, we either got a givem list of
# enabled runtimes, or "auto", or "all".
if enable_runtimes is None:
# For the backward compatibility, we do not use
# enable_runtimes unless it is requested explicitly.
self.enable_runtimes = frozenset([])
elif enable_runtimes == "auto":
# Let's build the list of runtimes based on the given
# depends_on_projects list.
self.enable_runtimes = \
self.depends_on_projects.intersection(_all_runtimes)
else:
if enable_runtimes == "all":
# Let's replace the "all" placeholder by
# the actual list of all runtimes.
self.enable_runtimes = frozenset(_all_runtimes)
else:
# Let's just use the given list, no need to discover.
self.enable_runtimes = frozenset(enable_runtimes)
# Update the list of dependencies.
if depends_on_projects is None:
self.depends_on_projects.update(self.enable_runtimes)
# Build the list of projects to enable.
self.enable_projects = \
self.depends_on_projects.difference(self.enable_runtimes)
# Directories.
self.monorepo_dir = kwargs.pop('llvm_srcdir', None)
self.src_to_build_dir = kwargs.pop('src_to_build_dir', None)
self.obj_dir = kwargs.pop('obj_dir', None)
self.install_dir = kwargs.pop('install_dir', None)
# Preserve the rest of the given extra attributes if any, so we could
# expand the factory later.
for k,v in kwargs.items():
setattr(self, k, v)
self.monorepo_dir = self.monorepo_dir or "llvm-project"
self.src_to_build_dir = self.src_to_build_dir or 'llvm'
self.llvm_srcdir = \
"{}/{}".format(self.monorepo_dir, self.src_to_build_dir)
self.obj_dir = \
self.obj_dir or "build"
# Repourl_prefix could be specified per builder. Otherwise we use github.
self.repourl_prefix = kwargs.pop('repourl_prefix', 'https://github.com/llvm/')
@staticmethod
def pathRelativeTo(path, basePath):
if path.startswith('/'):
# The path is absolute. Don't touch it.
return path
else:
# Remove "current dir" placeholders if any.
path_nodes = list(filter(lambda x: x != ".", path.split('/')))
basePath_nodes = list(filter(lambda x: x != ".", basePath.split('/')))
# Handle edge cases.
if len(basePath_nodes) == 0:
return "/".join(path_nodes)
if len(path_nodes) == 0:
return "."
# Skip a common part of the two paths.
for i in range(0, min(len(path_nodes), len(basePath_nodes))):
if path_nodes[i] != basePath_nodes[i]:
rel_path = \
"../" * (len(basePath_nodes) - i) + \
"/".join(path_nodes[i:])
break
else:
# Everything matches.
rel_path = '.'
return rel_path
def addGetSourcecodeSteps(self, **kwargs):
# Checkout the monorepo.
# Documentation: http://docs.buildbot.net/current/manual/configuration/buildsteps.html#git
self.addStep(steps.Git(
name='Checkout the source code',
repourl=self.repourl_prefix + "llvm-project.git",
progress=True,
workdir=util.WithProperties(self.monorepo_dir),
retryFetch=True,
clobberOnFailure=True,
**kwargs))
# Checkout a given LLVM project to the given directory.
# TODO: Handle clean property and self.clean attribute.
def addGetSourcecodeForProject(self, project, name=None, src_dir=None, **kwargs):
# project contains a repo name which is not a part of the monorepo.
# We do not enforce it here, though.
_repourl = kwargs.pop('repourl', None)
if not _repourl:
_repourl = self.repourl_prefix + "llvm-%s.git" % project
if not name:
name = 'Checkout %s' % project
# Check out to the given directory if any.
# Otherwise this is a part of the unified source tree.
if src_dir is None:
src_dir = 'llvm-%s' % project
# Ignore workdir if given. We check out to src_dir.
kwargs.pop('workdir', None)
self.addStep(steps.Git(
name=name,
repourl=_repourl,
progress=True,
workdir=util.WithProperties(src_dir),
retryFetch=True,
clobberOnFailure=True,
**kwargs))