blob: 4cbaea90155c6e4cfb7be9e260f2a2d34f1319c1 [file] [log] [blame]
import os
import json
import collections
import buildbot
import buildbot.process.factory
from buildbot.steps.source import SVN
from buildbot.steps.shell import Configure, SetProperty
from buildbot.steps.shell import ShellCommand, WarningCountingShellCommand
from buildbot.steps.slave import RemoveDirectory
from buildbot.process.properties import WithProperties, Property
from buildbot.steps import trigger
from zorg.buildbot.commands.LitTestCommand import LitTestCommand
from zorg.buildbot.commands.CmakeCommand import CmakeCommand
from zorg.buildbot.conditions.FileConditions import FileDoesNotExist
from zorg.buildbot.builders.Util import getVisualStudioEnvironment
from zorg.buildbot.builders.Util import extractSlaveEnvironment
from zorg.buildbot.process.factory import LLVMBuildFactory
# We *must* checkout at least Clang, LLVM, and LLDB. Also check out LLD since
# it is needed to run the LLDB test suite.
def getLLDBSource(f,llvmTopDir='llvm'):
f.addStep(SVN(name='svn-llvm',
mode='update', baseURL='http://llvm.org/svn/llvm-project/llvm/',
defaultBranch='trunk',
workdir=llvmTopDir))
f.addStep(SVN(name='svn-clang',
mode='update', baseURL='http://llvm.org/svn/llvm-project/cfe/',
defaultBranch='trunk',
workdir='%s/tools/clang' % llvmTopDir))
f.addStep(SVN(name='svn-lld',
mode='update', baseURL='http://llvm.org/svn/llvm-project/lld/',
defaultBranch='trunk',
workdir='%s/tools/lld' % llvmTopDir))
f.addStep(SVN(name='svn-lldb',
mode='update', baseURL='http://llvm.org/svn/llvm-project/lldb/',
defaultBranch='trunk',
workdir='%s/tools/lldb' % llvmTopDir))
return f
# Clean SVN source tree
# SVN doesn't provide build-in commands to remove all untracked files
# List all untracked files, and remove one by one
def cleanSVNSourceTree(f, srcdir='llvm'):
f.addStep(ShellCommand(name='clean svn source %s' % srcdir,
command="svn status --no-ignore | grep '^[I?]' | cut -c 9- | while IFS= read -r f; do echo \"$f\"; rm -rf \"$f\"; done",
description="clean SVN source tree",
workdir='%s' % srcdir))
return f
# CMake builds
def getLLDBCMakeBuildFactory(
clean=False,
jobs="%(jobs)s",
# Source directory containing a built python
python_source_dir=None,
# Default values for VS devenv and build configuration
vs=None,
config='Release',
target_arch='x86',
extra_cmake_args=None,
test=False,
testTimeout=2400,
install=False):
############# PREPARING
# Global configurations
build_dir='build'
f = LLVMBuildFactory(
is_legacy_mode=False,
depends_on_projects=["llvm", "clang", "lldb", "lld"],
obj_dir=build_dir)
# Determine Slave Environment and Set MSVC environment.
if vs:
f.addStep(SetProperty(
command=getVisualStudioEnvironment(vs, target_arch),
extract_fn=extractSlaveEnvironment))
f.addGetSourcecodeSteps()
build_cmd=['ninja']
install_cmd = ['ninja','install']
test_cmd = ['ninja','check-lldb']
if jobs:
build_cmd.append(WithProperties("-j%s" % jobs))
install_cmd.append(WithProperties("-j%s" % jobs))
test_cmd.append(WithProperties("-j%s" % jobs))
############# CLEANING
cleanBuildRequested = lambda step: clean or step.build.getProperty("clean", default=step.build.getProperty("clean_obj"))
f.addStep(RemoveDirectory(name='clean '+build_dir,
dir=build_dir,
haltOnFailure=False,
flunkOnFailure=False,
doStepIf=cleanBuildRequested
))
rel_src_dir = LLVMBuildFactory.pathRelativeToBuild(f.llvm_srcdir, f.obj_dir)
cmake_options = [
"-G", "Ninja",
"-DCMAKE_BUILD_TYPE=" + config,
"-DCMAKE_INSTALL_PREFIX=../install",
"-DLLVM_ENABLE_PROJECTS=%s" % ";".join(f.depends_on_projects),
]
if python_source_dir:
cmake_options.append("-DPYTHON_HOME=" + python_source_dir)
if extra_cmake_args:
cmake_options += extra_cmake_args
f.addStep(CmakeCommand(name="cmake-configure",
description=["cmake configure"],
haltOnFailure=True,
options=cmake_options,
path=rel_src_dir,
env=Property('slave_env'),
workdir=build_dir))
f.addStep(WarningCountingShellCommand(name='build',
command=build_cmd,
haltOnFailure=True,
description='ninja build',
workdir=build_dir,
env=Property('slave_env')))
ignoreInstallFail = bool(install != 'ignoreFail')
f.addStep(ShellCommand(name='install',
command=install_cmd,
flunkOnFailure=ignoreInstallFail,
description='ninja install',
workdir=build_dir,
doStepIf=bool(install),
env=Property('slave_env')))
ignoreTestFail = bool(test != 'ignoreFail')
f.addStep(ShellCommand(name='test',
command=test_cmd,
flunkOnFailure=ignoreTestFail,
timeout=testTimeout,
description='ninja test',
workdir=build_dir,
doStepIf=bool(test),
env=Property('slave_env')))
return f
def getLLDBBuildFactory(
triple,
useTwoStage=False,
make='make',
jobs='%(jobs)s',
extra_configure_args=[],
env={},
*args,
**kwargs):
llvm_srcdir = "llvm.src"
llvm_objdir = "llvm.obj"
f = buildbot.process.factory.BuildFactory()
# Determine the build directory.
f.addStep(SetProperty(name="get_builddir",
command=["pwd"],
property="builddir",
description="set build dir",
workdir="."))
# Find out what version of llvm and clang are needed to build this version
# of lldb. Right now we will assume they use the same version.
# XXX - could this be done directly on the master instead of the slave?
f.addStep(SetProperty(command='svn cat http://llvm.org/svn/llvm-project/lldb/trunk/scripts/build-llvm.pl | grep ^our.*llvm_revision | cut -d \\" -f 2',
property='llvmrev'))
# The SVN build step provides no mechanism to check out a specific revision
# based on a property, so just run the commands directly here.
svn_co = ['svn', 'checkout', '--force']
svn_co += ['--revision', WithProperties('%(llvmrev)s')]
# build llvm svn checkout command
svn_co_llvm = svn_co + \
[WithProperties('http://llvm.org/svn/llvm-project/llvm/trunk@%(llvmrev)s'),
llvm_srcdir]
# build clang svn checkout command
svn_co_clang = svn_co + \
[WithProperties('http://llvm.org/svn/llvm-project/cfe/trunk@%(llvmrev)s'),
'%s/tools/clang' % llvm_srcdir]
f.addStep(ShellCommand(name='svn-llvm',
command=svn_co_llvm,
haltOnFailure=True,
workdir='.'))
f.addStep(ShellCommand(name='svn-clang',
command=svn_co_clang,
haltOnFailure=True,
workdir='.'))
f.addStep(SVN(name='svn-lldb',
mode='update',
baseURL='http://llvm.org/svn/llvm-project/lldb/',
defaultBranch='trunk',
always_purge=True,
workdir='%s/tools/lldb' % llvm_srcdir))
# Run configure
config_args = [WithProperties("%%(builddir)s/%s/configure" % llvm_srcdir),
"--disable-bindings",
"--without-llvmgcc",
"--without-llvmgxx",
]
if triple:
config_args += ['--build=%s' % triple]
config_args += extra_configure_args
f.addStep(Configure(name='configure',
command=config_args,
env=env,
workdir=llvm_objdir))
f.addStep(WarningCountingShellCommand(name="compile",
command=['nice', '-n', '10',
make, WithProperties("-j%s" % jobs)],
env=env,
haltOnFailure=True,
workdir=llvm_objdir))
# Test.
f.addStep(LitTestCommand(name="test lldb",
command=['nice', '-n', '10',
make],
description="test lldb",
env=env,
workdir='%s/tools/lldb/test' % llvm_objdir))
return f
# Add test steps from list of compilers and archs
def getLLDBTestSteps(f,
bindir,
test_archs,
test_compilers,
remote_platform=None,
remote_host=None,
remote_port=None,
remote_dir=None,
env=None):
# Skip test steps if no test compiler or arch is specified
if None in (test_archs, test_compilers):
return f
llvm_srcdir = "llvm"
llvm_builddir = "build"
if env is None:
env = {}
flunkTestFailure = True
extraTestFlag = ''
# TODO: for now, run tests with 8 threads and without mi tests on android
# come back when those issues are addressed
testenv=dict(env)
for compiler in test_compilers:
# find full path for top of tree clang
if compiler=='totclang':
compilerPath=bindir + '/clang'
elif remote_platform is 'android':
compilerPath = os.path.join('%(toolchain_test)s', 'bin', compiler)
else:
compilerPath = compiler
for arch in test_archs:
DOTEST_OPTS=''.join(['--executable ' + bindir + '/lldb ',
'--filecheck ' + bindir + '/FileCheck ',
'-A %s ' % arch,
'-C %s ' % compilerPath,
'-s lldb-test-traces-%s-%s ' % (compiler, arch),
'-u CXXFLAGS ',
'-u CFLAGS ',
'--channel ',
'"gdb-remote packets" ',
'--channel ',
'"lldb all"'])
testname = "local"
if remote_platform is not None:
urlStr='connect://%(remote_host)s:%(remote_port)s'
if remote_platform is 'android':
#i386/x86_64 are the only android archs that are expected to pass at this time
flunkTestFailure = arch in ('i386', 'x86_64')
testenv['LLDB_TEST_THREADS'] = '8'
extraTestFlag = ' -m'
urlStr = 'adb://%(deviceid)s:%(remote_port)s'
# for Android, remove all forwarded ports before running test
# it is noticed that forwarded socket connections were not cleaned for certain crashed tests
# clean it here to avoid too many "LISTEN" ports left on slave
f.addStep(ShellCommand(name="remove port forwarding %s" % arch,
command=['adb',
'forward',
'--remove-all'],
description="Remove port forwarding",
env=env,
haltOnFailure=False,
workdir='%s' % llvm_builddir))
DOTEST_OPTS += ''.join([' --platform-name remote-' + remote_platform,
' --platform-url ' + urlStr,
' --platform-working-dir %(remote_dir)s',
' --env OS=' + remote_platform.title()])
testname = "remote-" + remote_platform
DOTEST_OPTS += extraTestFlag
f.addStep(LitTestCommand(name="test lldb %s (%s-%s)" % (testname, compiler, arch),
command=['../%s/tools/lldb/test/dosep.py' % llvm_srcdir,
'--options',
WithProperties(DOTEST_OPTS)],
description="test lldb",
parseSummaryOnly=True,
flunkOnFailure=flunkTestFailure,
warnOnFailure=flunkTestFailure,
workdir='%s' % llvm_builddir,
timeout=1800,
env=testenv))
f=cleanSVNSourceTree(f, '%s/tools/lldb/test' % llvm_srcdir)
return f
# Define a structure to describe remote target
# For example, RemoteConfig('linux','x86_64',['gcc4.8.2','clang'],['i386'])
RemoteConfig = collections.namedtuple("RemoteConfig", ["platform", "host_arch", "test_compilers", "test_archs"])
# Add steps to run lldb test on remote target
def getLLDBRemoteTestSteps(f,
bindir,
build_type,
remote_config,
env):
if None in (remote_config.test_archs, remote_config.test_compilers):
return f
# only supports linux and android as remote target at this time
if remote_config.platform not in ('linux', 'android'):
return f
llvm_srcdir = "llvm"
llvm_builddir = "build"
stepDesc = remote_config.platform + "-" + remote_config.host_arch
# get hostname
slave_hostname = None
f.addStep(SetProperty(name="get hostname",
command=["hostname"],
property="slave_hostname",
description="set slave hostname",
workdir="."))
# get configuration of remote target
# config file should be placed under builddir on builder machine
# file name: remote_cfg.json
# content: json format with keys [remote_platform]-[remote_arch]
# the value for each key defines "remote_host", "remote_port", "remote_dir", "toolchain", "deviceId"
# example: {"android-i386": {"remote_host":"localhost",
# "remote_port":"5430",
# "remote_dir":"/data/local/tmp/lldb",
# "toolchain_build":"/home/lldb_build/Toolchains/i386-android-toolchain-21",
# "toolchain_test":"/home/lldb_build/Toolchains/i386-android-toolchain-16",
# "deviceid":"XXXXXXX"},
def getRemoteCfg(rc, stdout, stderr):
return json.loads(stdout)[stepDesc]
f.addStep(SetProperty(name="get remote target " + stepDesc,
command="cat remote_cfg.json",
extract_fn=getRemoteCfg,
description="get remote target",
workdir="."))
# rsync
if remote_config.platform is 'linux':
shellcmd = ['ssh',
WithProperties('%(remote_host)s')]
hostname = '%(slave_hostname)s'
launchcmd = shellcmd + ['screen', '-d', '-m']
terminatecmd = shellcmd + ['pkill', 'lldb-server']
cleandircmd = WithProperties('ssh %(remote_host)s rm -r %(remote_dir)s/*')
f.addStep(ShellCommand(name="rsync lldb-server",
command=['rsync',
'-havL',
'bin/lldb-server',
WithProperties('%(remote_host)s:%(remote_dir)s')],
description="rsync lldb-server " + stepDesc,
haltOnFailure=True,
env=env,
workdir='%s' % llvm_builddir))
f.addStep(ShellCommand(name="rsync python2.7",
command=['rsync',
'-havL',
'lib/python2.7',
WithProperties('%(remote_host)s:%(remote_dir)s')],
description="rsync python2.7 " + stepDesc,
haltOnFailure=True,
env=env,
workdir='%s' % llvm_builddir))
elif remote_config.platform is 'android':
shellcmd = ['adb',
'-s',
WithProperties('%(deviceid)s'),
'shell']
hostname = '127.0.0.1'
launchcmd = ['screen', '-d', '-m'] + shellcmd + [WithProperties("TMPDIR=%(remote_dir)s/tmp")]
terminatecmd = 'ps | grep lldb-server | awk \'{print $2}\' | xargs'
terminatecmd = WithProperties('adb -s %(deviceid)s shell ' + terminatecmd + ' adb -s %(deviceid)s shell kill')
cleandircmd = WithProperties('adb -s %(deviceid)s shell rm -rf %(remote_dir)s/*')
# compile lldb-server for target platform
f = getLLDBCmakeAndCompileSteps(f,
'gcc',
build_type,
['lldb-server'],
bindir,
remote_config.platform,
remote_config.host_arch,
env)
f.addStep(ShellCommand(name="adb push lldb-server " + stepDesc,
command=['adb',
'-s',
WithProperties('%(deviceid)s'),
'push',
remote_config.platform+'-' + remote_config.host_arch + '/bin/lldb-server',
WithProperties('%(remote_dir)s/')],
description="lldb-server",
env=env,
haltOnFailure=True,
workdir='%s' % llvm_builddir))
f.addStep(ShellCommand(name="Build fingerprint " + stepDesc,
command=['adb',
'-s',
WithProperties('%(deviceid)s'),
'shell',
'getprop',
'ro.build.fingerprint'],
description="get build fingerprint",
env=env,
haltOnFailure=False,
workdir='%s' % llvm_builddir))
# launch lldb-server
f.addStep(ShellCommand(name="launch lldb-server " + stepDesc,
command=launchcmd +
[WithProperties('%(remote_dir)s/lldb-server'),
'platform',
'--listen',
WithProperties(hostname + ':%(remote_port)s'),
'--server'],
description="launch lldb-server on remote host",
env=env,
haltOnFailure=True,
workdir='%s' % llvm_builddir))
# test steps
f = getLLDBTestSteps(f,
bindir,
remote_config.test_archs,
remote_config.test_compilers,
remote_config.platform,
'%(remote_host)s',
'%(remote_port)s',
'%(remote_dir)s',
env)
# terminate lldb-server on remote host
f.addStep(ShellCommand(name="terminate lldb-server " + stepDesc,
command=terminatecmd,
description="terminate lldb-server",
env=env,
workdir='%s' % llvm_builddir))
# clean remote test directory
f.addStep(ShellCommand(name="clean remote dir " + stepDesc,
command=cleandircmd,
description="clean remote dir",
env=env))
return f
# Cmake bulid on Ubuntu
# Build command sequence - cmake, ninja, ./dosep
# Note: If test_archs or test_compilers is not specified, lldb-test will not be added to build factory
def getLLDBUbuntuCMakeBuildFactory(build_compiler,
build_type,
local_test_archs=None,
local_test_compilers=None,
remote_configs=None,
jobs='%(jobs)s',
env=None):
"""Generate factory steps for ubuntu cmake builder
Arguments:
build_compiler -- string of compile name, example 'clang',
the compiler will be used to build binaries for host platform
build_type -- 'Debug' or 'Release',
used to define build type for host platform as well as remote platform if any
local_test_archs -- list of architectures, example ['i386','x86_64'],
defines architectures to run local tests against, if None, local tests won't be executed
local_test_compiler -- list of compilers, example ['clang','gcc4.8.2'],
definds compilers to run local tests with, if None, local tests won't be executed
remote_configs -- list of RemoteConfig objects, example [RemoteConfig(...)], if None, remote tests won't be executed
jobs -- number of threads for compilation step, example 40
default value is jobs number defined during slave creation
env -- environment variables passed to shell commands
"""
if env is None:
env = {}
llvm_srcdir = "llvm"
llvm_builddir = "build"
bindir='%(builddir)s/' + llvm_builddir + '/bin'
f = buildbot.process.factory.BuildFactory()
# Determine the build directory.
f.addStep(SetProperty(name="get_builddir",
command=["pwd"],
property="builddir",
description="set build dir",
workdir="."))
# Determine the binary directory of *-tblgen.
f.addStep(SetProperty(name="get tblgen dir",
command=["echo", WithProperties(bindir)],
property="tblgen_bindir",
description="set tblgen dir",
workdir="."))
# Get source code
f = getLLDBSource(f,llvm_srcdir)
# Clean Build Folder
f.addStep(ShellCommand(name="clean",
command="rm -rf *",
description="clear build folder",
env=env,
workdir='%s' % llvm_builddir))
f = getLLDBCmakeAndCompileSteps(f,
build_compiler,
build_type,
[],
bindir,
'linux',
'x86_64',
env)
# TODO: it will be good to check that architectures listed in test_archs are compatible with host architecture
# For now, the caller of this function should make sure that each target architecture is supported by builder machine
# Add local test steps
f = getLLDBTestSteps(f,
bindir,
local_test_archs,
local_test_compilers)
# Remote test steps
if remote_configs is not None:
for config in remote_configs:
f = getLLDBRemoteTestSteps(f,
bindir,
build_type,
config,
env)
# archive test traces
f = archiveLLDBTestTraces(f, "build/lldb-test-traces-*")
return f
# zip and upload test traces to google storage
def archiveLLDBTestTraces(f, test_trace):
f.addStep(ShellCommand(name="compress test traces",
command=WithProperties("zip -r build-%(buildnumber)s " + test_trace),
description="zip",
haltOnFailure=False,
flunkOnFailure=False,
workdir='.'))
f.addStep(ShellCommand(name="upload test traces",
command=['gsutil',
'mv',
WithProperties('build-%(buildnumber)s.zip'),
WithProperties('gs://lldb_test_traces/%(buildername)s/')],
description="upload to Google Storage",
haltOnFailure=False,
flunkOnFailure=False,
workdir='.'))
return f
# for cmake and compile
def getLLDBCmakeAndCompileSteps(f,
build_compiler,
build_type,
ninja_target,
bindir,
target_platform,
target_arch,
env=None):
if env is None:
env={}
llvm_builddir = 'build'
if target_platform is 'android':
llvm_builddir = 'build/android-' + target_arch
# Configure
f = getLLDBCMakeStep(f,
build_compiler,
build_type,
bindir,
target_platform,
target_arch,
env)
# Compile
f.addStep(WarningCountingShellCommand(name='ninja-%s-%s'%(target_platform, target_arch),
command=['nice','-n', '10',
'ninja',
WithProperties('-j%(jobs)s')] + ninja_target,
env=env,
haltOnFailure=True,
workdir=llvm_builddir))
return f
def getLLDBCMakeStep(f,
build_compiler,
build_type,
bindir,
target_platform,
target_arch,
env=None):
if target_platform is 'linux':
return getLLDBLinuxCMakeStep(f,
build_compiler,
build_type,
target_arch,
env)
elif target_platform is 'android':
return getLLDBAndroidCMakeStep(f,
build_compiler,
build_type,
bindir,
target_arch,
env)
def getCCompilerCmd(compiler):
if compiler == "clang":
return "clang"
elif compiler == "gcc":
return "gcc"
def getCxxCompilerCmd(compiler):
if compiler == "clang":
return "clang++"
elif compiler == "gcc":
return "g++"
def getLLDBLinuxCMakeStep(f,
build_compiler,
build_type,
target_arch,
env=None):
if env is None:
env = {}
llvm_srcdir = 'llvm'
llvm_builddir = 'build'
# Construct cmake
cmake_args = ["cmake", "-GNinja"]
cmake_args.append(WithProperties("-DCMAKE_BUILD_TYPE=%s" % build_type))
cmake_args.append(WithProperties('%(builddir)s/' + llvm_srcdir))
cmake_args.append("-DCMAKE_C_COMPILER=%s" % getCCompilerCmd(build_compiler))
cmake_args.append("-DCMAKE_CXX_COMPILER=%s" % getCxxCompilerCmd(build_compiler))
f.addStep(Configure(name='cmake-linux-%s' % (target_arch),
command=cmake_args,
env=env,
haltOnFailure=True,
workdir=llvm_builddir))
return f
def getLLDBAndroidCMakeStep(f,
build_compiler,
build_type,
bindir,
target_arch,
env):
if env is None:
env = {}
llvm_srcdir = 'llvm'
llvm_builddir = 'build/android-' + target_arch
abiMap={
'i386':'x86',
'arm':'armeabi',
'aarch64':'aarch64'
}
# Construct cmake
cmake_args = ["cmake", "-GNinja"]
cmake_args.append(WithProperties("-DCMAKE_BUILD_TYPE=%s" % build_type))
cmake_args.append(WithProperties('%(builddir)s/' + llvm_srcdir))
cmake_args.append(WithProperties('-DCMAKE_TOOLCHAIN_FILE=' + '%(builddir)s/' + llvm_srcdir + '/tools/lldb/cmake/platforms/Android.cmake'))
cmake_args.append(WithProperties('-DANDROID_TOOLCHAIN_DIR=' + '%(toolchain_build)s'))
cmake_args.append('-DANDROID_ABI=' + abiMap[target_arch])
cmake_args.append('-DCMAKE_CXX_COMPILER_VERSION=4.9')
cmake_args.append('-DLLVM_TARGET_ARCH=' + target_arch)
cmake_args.append('-DLLVM_HOST_TRIPLE=' + target_arch + '-unknown-linux-android')
cmake_args.append(WithProperties('-DLLVM_TABLEGEN=%(tblgen_bindir)s/llvm-tblgen'))
cmake_args.append(WithProperties('-DCLANG_TABLEGEN=%(tblgen_bindir)s/clang-tblgen'))
f.addStep(Configure(name='cmake-android-%s' % target_arch,
command=cmake_args,
env=env,
haltOnFailure=True,
workdir=llvm_builddir))
return f
# Set symbolic links, so the folder structure will be llvm, llvm/tools/clang, llvm/tools/lldb
def getSymbLinkSteps(f, lldb_srcdir):
f.addStep(ShellCommand(name='set symbolic link clang',
command=['ln', '-nfs',
WithProperties('%(builddir)s/' + lldb_srcdir + '/llvm/tools/clang'),
'clang'],
workdir=WithProperties('%(builddir)s')))
f.addStep(ShellCommand(name='set symbolic link lldb',
command=['ln', '-nfs',
WithProperties('%(builddir)s/' + lldb_srcdir),
lldb_srcdir + '/llvm/tools/lldb'],
workdir=WithProperties('%(builddir)s')))
f.addStep(ShellCommand(name='set symbolic link llvm',
command=['ln', '-nfs',
WithProperties('%(builddir)s/' + lldb_srcdir + '/llvm'),
'llvm'],
workdir=WithProperties('%(builddir)s')))
return f
def getLLDBxcodebuildFactory(use_cc=None,
build_type='Debug',
remote_configs=None,
env=None):
if env is None:
env = {}
f = buildbot.process.factory.BuildFactory()
f.addStep(SetProperty(name='get_builddir',
command=['pwd'],
property='builddir',
description='set build dir',
workdir='.'))
lldb_srcdir = 'lldb'
OBJROOT='%(builddir)s/' + lldb_srcdir + '/build'
f.addStep(SetProperty(name='get_bindir',
command=['echo',
WithProperties('%(builddir)s/' + lldb_srcdir + '/build/' + build_type)],
property='lldb_bindir',
description='set bin dir',
workdir='.'))
# cleaning out the build directory is vital for codesigning.
f.addStep(ShellCommand(name='clean.lldb-buid',
command=['rm', '-rf', WithProperties(OBJROOT)],
haltOnFailure=True,
workdir=WithProperties('%(builddir)s')))
f.addStep(ShellCommand(name='clean.llvm-buid',
command=['rm', '-rf', '%s/llvm-build' % lldb_srcdir ],
haltOnFailure=True,
workdir=WithProperties('%(builddir)s')))
f.addStep(ShellCommand(name='clean.test trace',
command='rm -rf build/*',
haltOnFailure=False,
flunkOnFailure=False,
workdir='.'))
# Remove symbolic link to lldb, otherwise xcodebuild will have circular dependency
f.addStep(ShellCommand(name='remove symbolic link lldb',
command=['rm',
lldb_srcdir + '/llvm/tools/lldb'],
haltOnFailure=False,
flunkOnFailure=False,
workdir=WithProperties('%(builddir)s')))
f.addStep(SVN(name='svn-lldb',
mode='update',
baseURL='http://llvm.org/svn/llvm-project/lldb/',
defaultBranch='trunk',
workdir=lldb_srcdir))
f.addStep(SVN(name='svn-llvm',
mode='update',
baseURL='http://llvm.org/svn/llvm-project/llvm/',
defaultBranch='trunk',
workdir='%s/llvm' % lldb_srcdir))
f.addStep(SVN(name='svn-clang',
mode='update',
baseURL='http://llvm.org/svn/llvm-project/cfe/',
defaultBranch='trunk',
workdir='%s/llvm/tools/clang' % lldb_srcdir))
# setup keychain for codesign
# In order for the codesigning to work inside of buildbot, security must be
# called to unlock the keychain, which requires a password.
# I've set up a special keychain for this purpose, so as to not compromise
# the login password of the buildslave.
# This means I have to set the special keychain as the default and unlock it
# prior to building the sources.
f.addStep(ShellCommand(name='check.keychain',
command=['security', 'default-keychain'],
haltOnFailure=True,
workdir=WithProperties('%(builddir)s')))
f.addStep(ShellCommand(name='find.certificate',
command=['security', 'find-certificate', '-c',
'lldb_codesign'],
haltOnFailure=True,
workdir=WithProperties('%(builddir)s')))
# Building the sources
#
buildcmd = ' '.join(['xcrun',
'xcodebuild',
'-target',
'desktop',
'-configuration',
build_type,
'SYMROOT=' + OBJROOT,
'OBJROOT=' + OBJROOT])
f.addStep(ShellCommand(name='lldb-build',
command=WithProperties(buildcmd + " || " + buildcmd),
haltOnFailure=True,
workdir=lldb_srcdir))
# Testing
#
if not use_cc:
use_cc = '/Applications/Xcode.app/Contents/Developer/Toolchains/'
use_cc += 'XcodeDefault.xctoolchain/usr/bin/clang'
f.addStep(SetProperty(name='set.cc',
command=['xcrun', '-find', 'clang'],
property='use_cc',
description='set cc',
workdir=lldb_srcdir))
else:
f.addStep(SetProperty(name='set.cc',
command=['echo', use_cc],
property='use_cc',
description='set cc',
workdir=lldb_srcdir))
DOTEST_OPTS = ' '.join(['--executable',
'%(lldb_bindir)s/lldb',
'--filecheck',
'%(lldb_bindir)s/FileCheck',
'--framework', '%(lldb_bindir)s/LLDB.framework',
'-A', 'x86_64',
'-C', 'clang',
'-s', '../../build/lldb-test-traces'])
f.addStep(LitTestCommand(name='lldb-test',
command=['./dosep.py',
'--options',
WithProperties(DOTEST_OPTS)],
haltOnFailure=False,
workdir='%s/test' % lldb_srcdir,
env={'DYLD_FRAMEWORK_PATH' : WithProperties('%(lldb_bindir)s')}))
# Remote test steps
if remote_configs is not None:
# Source structure to use cmake command
f.addStep(SetProperty(name='get tblgen bindir',
command=['echo',
WithProperties('%(builddir)s/' + lldb_srcdir + '/llvm-build/Release+Asserts/x86_64/Release+Asserts/bin')],
property='tblgen_bindir',
description='set tblgen binaries dir',
workdir='.'))
f = getSymbLinkSteps(f, lldb_srcdir)
for config in remote_configs:
f = getLLDBRemoteTestSteps(f,
'%(lldb_bindir)s',
build_type,
config,
env={'DYLD_FRAMEWORK_PATH' : WithProperties('%(lldb_bindir)s')})
# Compress and upload test log
f = archiveLLDBTestTraces(f, "build/lldb-test-traces*")
# Results go in a directory coded named according to the date and time of the test run, e.g.:
#
# 2012-10-16-11_26_48/Failure-x86_64-_Applications_Xcode.app_Contents_Developer_Toolchains_XcodeDefault.xctoolchain_usr_bin_clang-TestLogging.LogTestCase.test_with_dsym.log
#
# Possible results are ExpectedFailure, Failure, SkippedTest, UnexpectedSuccess, and Error. return f
return f
def getShellCommandStep(f,
name,
command,
description="",
flunkOnFailure=True,
haltOnFailure=True,
alwaysRun=False,
workdir='scripts',
env=None):
if env is None:
env = {}
f.addStep(ShellCommand(name=name,
command=command,
description=description,
env=env,
flunkOnFailure=flunkOnFailure,
haltOnFailure=haltOnFailure,
alwaysRun=alwaysRun,
workdir=workdir))
# get configuration of tests
# config file should be placed under builddir on builder machine
# file name: test_cfg.json
# content: json format with keys test[num]:target-compiler-architecture
# example: {"test1":"android-gcc4.9-i386",
# "test2":"local-clang-x86",
# "test3":"local-clang-i386"}
def getTestConfig(f):
def getRemoteCfg(rc, stdout, stderr):
return json.loads(stdout)
f.addStep(SetProperty(name="get test config",
command="cat test_cfg.json",
extract_fn=getRemoteCfg,
description="get remote target",
workdir="scripts"))
return f
def getTestSteps(f, scriptExt, pathSep):
# buildbot doesn't support dynamic step creation, so create 9 test steps as place holder
# then each builder will define available tests in test_cfg.json
# if there're less than 9 tests defined on certain builder, extra steps will be skipped and hidden from test details view
# **hide step is not supported by buildbot 0.8.5
# flunkOnFailure only takes boolean value, and cannot take configurable property.
# workaround: don't flunk the last three tests
# put non flunkable tests at the last three, test7, test8, test9
getTestConfig(f)
for x in range(1, 10):
test='test'+str(x)
f.addStep(LitTestCommand(name=test,
command=[pathSep + 'test' + scriptExt,
Property(test)],
description=["testing"],
descriptionDone=[WithProperties('%('+test+':-)s')],
doStepIf=lambda step: step.build.hasProperty(step.name),
flunkOnFailure=(x<7),
warnOnFailure=(x<7),
workdir='scripts'))
def getLLDBScriptCommandsFactory(
downloadBinary=True,
buildAndroid=False,
runTest=True,
scriptExt='.sh',
extra_cmake_args=None,
depends_on_projects=None,
):
if scriptExt is '.bat':
pathSep = '.\\'
else:
pathSep = './'
if extra_cmake_args is None:
extra_cmake_args = []
if depends_on_projects is None:
f = buildbot.process.factory.BuildFactory()
else:
f = LLVMBuildFactory(
depends_on_projects=depends_on_projects)
# Update scripts
getShellCommandStep(f, name='update scripts',
command=['updateScripts' + scriptExt])
# Acquire lock
if downloadBinary:
getShellCommandStep(f, name='acquire lock',
command=[pathSep + 'acquireLock' + scriptExt,
'totBuild'],
description='get')
# Checkout source code
getShellCommandStep(f, name='checkout source code',
command=[pathSep + 'checkoutSource' + scriptExt,
WithProperties('%(revision)s')])
# Set source revision
f.addStep(SetProperty(name="set revision",
command=[pathSep + 'getRevision' + scriptExt],
property="got_revision",
workdir="scripts"))
# Configure
getShellCommandStep(f, name='cmake local',
command=[pathSep + 'cmake' + scriptExt] + extra_cmake_args)
# Build
getShellCommandStep(f, name='ninja build local',
command=[pathSep + 'buildLocal' + scriptExt])
if buildAndroid:
getShellCommandStep(f, name='build android',
command=[pathSep + 'buildAndroid' + scriptExt])
# Get lldb-server binaries
if downloadBinary:
getShellCommandStep(f, name='get lldb-server binaries',
command=[pathSep + 'downloadBinaries' + scriptExt,
WithProperties('%(got_revision)s')])
# Test
if runTest:
f.addStep(LitTestCommand(name="run unit tests",
command=[pathSep + 'testUnit' + scriptExt],
description=["testing"],
descriptionDone=["unit test"],
workdir='scripts'))
getTestSteps(f, scriptExt, pathSep)
# upload test traces
getShellCommandStep(f, name='upload test traces',
command=[pathSep + 'uploadTestTrace' + scriptExt,
WithProperties('%(buildnumber)s'),
WithProperties('%(buildername)s')],
flunkOnFailure=False)
# Upload lldb-server binaries and trigger android builders
if buildAndroid:
getShellCommandStep(f, name='upload lldb-server binaries',
command=[pathSep + 'uploadBinaries' + scriptExt])
f.addStep(trigger.Trigger(schedulerNames=['lldb_android_scheduler'],
updateSourceStamp=False,
waitForFinish=False))
# Release lock
if downloadBinary:
getShellCommandStep(f, name='release lock',
command=[pathSep + 'releaseLock' + scriptExt,
'totBuild'],
description='release',
alwaysRun=True)
return f