blob: 2f8b1a4fb66b96765aed5c22331f1254185ebc44 [file] [log] [blame]
#!/usr/bin/python
# Copyright (c) 2013 The Native Client Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import argparse
import logging
import os
import platform
import subprocess
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import pynacl.platform
import pynacl.file_tools
import buildbot_lib
import packages
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
NACL_DIR = os.path.dirname(SCRIPT_DIR)
TOOLCHAIN_BUILD_DIR = os.path.join(NACL_DIR, 'toolchain_build')
TOOLCHAIN_BUILD_OUT_DIR = os.path.join(TOOLCHAIN_BUILD_DIR, 'out')
TEMP_PACKAGES_FILE = os.path.join(TOOLCHAIN_BUILD_OUT_DIR, 'packages.txt')
BUILD_DIR = os.path.join(NACL_DIR, 'build')
PACKAGE_VERSION_DIR = os.path.join(BUILD_DIR, 'package_version')
PACKAGE_VERSION_SCRIPT = os.path.join(PACKAGE_VERSION_DIR, 'package_version.py')
# As this is a buildbot script, we want verbose logging. Note however, that
# toolchain_build has its own log settings, controlled by its CLI flags.
logging.getLogger().setLevel(logging.DEBUG)
parser = argparse.ArgumentParser(description='PNaCl toolchain buildbot script')
group = parser.add_mutually_exclusive_group()
group.add_argument('--buildbot', action='store_true',
help='Buildbot mode (build and archive the toolchain)')
group.add_argument('--trybot', action='store_true',
help='Trybot mode (build but do not archove the toolchain)')
parser.add_argument('--tests-arch', choices=['x86-32', 'x86-64'],
default='x86-64',
help='Host architecture for tests in buildbot_pnacl.sh')
parser.add_argument('--skip-tests', action='store_true',
help='Skip running tests after toolchain built')
# Note: LLVM's tablegen doesn't run when built with the memory sanitizer.
# TODO(kschimp): Add thread, memory, and undefined sanitizers once bugs fixed.
parser.add_argument('--sanitize', choices=['address'
#, 'thread', 'memory', 'undefined'
],
help='Build with corresponding sanitizer')
args = parser.parse_args()
host_os = buildbot_lib.GetHostPlatform()
if args.sanitize:
if host_os != 'linux' or args.tests_arch != 'x86-64':
raise Exception("Error: Can't run sanitize bot unless linux x86-64")
# This is a minimal context, not useful for running tests yet, but enough for
# basic Step handling.
context = buildbot_lib.BuildContext()
buildbot_lib.SetDefaultContextAttributes(context)
context['pnacl'] = True
status = buildbot_lib.BuildStatus(context)
toolchain_install_dir = os.path.join(
NACL_DIR,
'toolchain',
'%s_%s' % (host_os, pynacl.platform.GetArch()),
'pnacl_newlib')
def ToolchainBuildCmd(sync=False, extra_flags=[]):
sync_flag = ['--sync'] if sync else []
executable_args = [os.path.join('toolchain_build','toolchain_build_pnacl.py'),
'--verbose', '--clobber',
'--packages-file', TEMP_PACKAGES_FILE]
if pynacl.platform.IsLinux64():
executable_args.append('--build-sbtc')
if args.sanitize:
executable_args.append('--sanitize')
executable_args.append(args.sanitize)
executable_args.append('--cmake')
executable_args.append('llvm_x86_64_linux')
if args.buildbot:
executable_args.append('--buildbot')
elif args.trybot:
executable_args.append('--trybot')
# Enabling LLVM assertions have a higher cost on Windows, particularly in the
# presence of threads. So disable them on windows but leave them on elsewhere
# to get the extra error checking.
# See https://code.google.com/p/nativeclient/issues/detail?id=3830
if host_os == 'win':
executable_args.append('--disable-llvm-assertions')
return [sys.executable] + executable_args + sync_flag + extra_flags
def RunWithLog(cmd):
logging.info('Running: ' + ' '.join(cmd))
subprocess.check_call(cmd)
sys.stdout.flush()
# Clean out any installed toolchain parts that were built by previous bot runs.
with buildbot_lib.Step('Clobber TC install dir', status):
print 'Removing', toolchain_install_dir
pynacl.file_tools.RemoveDirectoryIfPresent(toolchain_install_dir)
# Run checkdeps so that the PNaCl toolchain trybots catch mistakes that would
# cause the normal NaCl bots to fail.
with buildbot_lib.Step('checkdeps', status):
buildbot_lib.Command(
context,
[sys.executable,
os.path.join(NACL_DIR, 'tools', 'checkdeps', 'checkdeps.py')])
if host_os != 'win':
with buildbot_lib.Step('update clang', status):
buildbot_lib.Command(
context,
[sys.executable,
os.path.join(
NACL_DIR, '..', 'tools', 'clang', 'scripts', 'update.py')])
# toolchain_build outputs its own buildbot annotations, so don't use
# buildbot_lib.Step to run it here.
# The package_version tools don't have a way to distinguish canonical packages
# (i.e. those we want to upload) from non-canonical ones; they only know how to
# process all the archives that are present. We can't just leave out the
# the non-canonical packages entirely because they are extracted by the
# package_version tool.
# First build only the packages that will be uploaded, and upload them.
RunWithLog(ToolchainBuildCmd(sync=True, extra_flags=['--canonical-only']))
if args.skip_tests:
sys.exit(0)
if args.buildbot or args.trybot:
# Don't upload packages from the 32-bit linux bot to avoid racing on
# uploading the same packages as the 64-bit linux bot
if host_os != 'linux' or pynacl.platform.IsArch64Bit():
packages.UploadPackages(TEMP_PACKAGES_FILE, args.trybot, args.sanitize)
# Since windows bots don't build target libraries or run tests yet, Run a basic
# sanity check that tests the host components (LLVM, binutils, gold plugin).
# Then exit, since the rest of this file is just test running.
# For now full test coverage is only achieved on the main waterfall bots.
if host_os == 'win':
packages.ExtractPackages(TEMP_PACKAGES_FILE, overlay_packages=False)
with buildbot_lib.Step('Test host binaries and gold plugin', status,
halt_on_fail=False):
buildbot_lib.Command(
context,
[sys.executable,
os.path.join('tests', 'gold_plugin', 'gold_plugin_test.py'),
'--toolchaindir', toolchain_install_dir])
else:
# We need to run the LLVM regression tests after the first toolchain_build
# run, while the LLVM build directory is still there. Otherwise it gets
# deleted on the next toolchain_build run.
# TODO(dschuff): Fix windows regression test runner (upstream in the LLVM
# codebase or locally in the way we build LLVM) ASAP
with buildbot_lib.Step('LLVM Regression', status,
halt_on_fail=False):
llvm_test = [sys.executable,
os.path.join(NACL_DIR, 'pnacl', 'scripts', 'llvm-test.py'),
'--llvm-regression',
'--verbose']
buildbot_lib.Command(context, llvm_test)
sys.stdout.flush()
# Now build all the packages (including the non-canonical ones) and extract
# them for local testing.
RunWithLog(ToolchainBuildCmd())
packages.ExtractPackages(TEMP_PACKAGES_FILE, overlay_packages=False)
sys.stdout.flush()
for arch in ['x86-32', 'x86-64', 'arm']:
with buildbot_lib.Step('driver tests ' + arch, status, halt_on_fail=False):
buildbot_lib.Command(
context,
[sys.executable,
os.path.join('pnacl', 'driver', 'tests', 'driver_tests.py'),
'--platform=' + arch])
if host_os == 'win':
sys.exit(status.ReturnValue())
sys.stdout.flush()
# On Linux we build all toolchain components (driven from this script), and then
# call buildbot_pnacl.sh which builds the sandboxed translator and runs tests
# for all the components.
# On Mac we build the toolchain but not the sandboxed translator, and run the
# same tests as the main waterfall bot (which also does not run the sandboxed
# translator: see https://code.google.com/p/nativeclient/issues/detail?id=3856 )
if host_os == 'mac':
subprocess.check_call([sys.executable,
os.path.join(NACL_DIR, 'buildbot','buildbot_pnacl.py'),
'opt', '64', 'pnacl'])
else:
# Now we run the PNaCl buildbot script. It in turn runs the PNaCl build.sh
# script (currently only for the sandboxed translator) and runs scons tests.
# TODO(dschuff): re-implement the test-running portion of buildbot_pnacl.sh
# using buildbot_lib, and use them here and in the non-toolchain builder.
buildbot_shell = os.path.join(NACL_DIR, 'buildbot', 'buildbot_pnacl.sh')
# Generate flags for buildbot_pnacl.sh
arch = 'x8664' if args.tests_arch == 'x86-64' else 'x8632'
if args.buildbot:
trybot_mode = 'false'
else:
trybot_mode = 'true'
platform_arg = 'mode-buildbot-tc-' + arch + '-linux'
command = ['bash', buildbot_shell, platform_arg, trybot_mode]
RunWithLog(command)