Home | History | Annotate | Download | only in buildbot
      1 #!/usr/bin/env python
      2 # Copyright (c) 2012 Google Inc. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 
      7 """Argument-less script to select what to run on the buildbots."""
      8 
      9 
     10 import os
     11 import shutil
     12 import subprocess
     13 import sys
     14 
     15 
     16 if sys.platform in ['win32', 'cygwin']:
     17   EXE_SUFFIX = '.exe'
     18 else:
     19   EXE_SUFFIX = ''
     20 
     21 
     22 BUILDBOT_DIR = os.path.dirname(os.path.abspath(__file__))
     23 TRUNK_DIR = os.path.dirname(BUILDBOT_DIR)
     24 ROOT_DIR = os.path.dirname(TRUNK_DIR)
     25 ANDROID_DIR = os.path.join(ROOT_DIR, 'android')
     26 CMAKE_DIR = os.path.join(ROOT_DIR, 'cmake')
     27 CMAKE_BIN_DIR = os.path.join(CMAKE_DIR, 'bin')
     28 OUT_DIR = os.path.join(TRUNK_DIR, 'out')
     29 
     30 
     31 def CallSubProcess(*args, **kwargs):
     32   """Wrapper around subprocess.call which treats errors as build exceptions."""
     33   retcode = subprocess.call(*args, **kwargs)
     34   if retcode != 0:
     35     print '@@@STEP_EXCEPTION@@@'
     36     sys.exit(1)
     37 
     38 
     39 def PrepareCmake():
     40   """Build CMake 2.8.8 since the version in Precise is 2.8.7."""
     41   if os.environ['BUILDBOT_CLOBBER'] == '1':
     42     print '@@@BUILD_STEP Clobber CMake checkout@@@'
     43     shutil.rmtree(CMAKE_DIR)
     44 
     45   # We always build CMake 2.8.8, so no need to do anything
     46   # if the directory already exists.
     47   if os.path.isdir(CMAKE_DIR):
     48     return
     49 
     50   print '@@@BUILD_STEP Initialize CMake checkout@@@'
     51   os.mkdir(CMAKE_DIR)
     52   CallSubProcess(['git', 'config', '--global', 'user.name', 'trybot'])
     53   CallSubProcess(['git', 'config', '--global',
     54                   'user.email', 'chrome-bot (at] google.com'])
     55   CallSubProcess(['git', 'config', '--global', 'color.ui', 'false'])
     56 
     57   print '@@@BUILD_STEP Sync CMake@@@'
     58   CallSubProcess(
     59       ['git', 'clone',
     60        '--depth', '1',
     61        '--single-branch',
     62        '--branch', 'v2.8.8',
     63        '--',
     64        'git://cmake.org/cmake.git',
     65        CMAKE_DIR],
     66       cwd=CMAKE_DIR)
     67 
     68   print '@@@BUILD_STEP Build CMake@@@'
     69   CallSubProcess(
     70       ['/bin/bash', 'bootstrap', '--prefix=%s' % CMAKE_DIR],
     71       cwd=CMAKE_DIR)
     72 
     73   CallSubProcess( ['make', 'cmake'], cwd=CMAKE_DIR)
     74 
     75 
     76 def PrepareAndroidTree():
     77   """Prepare an Android tree to run 'android' format tests."""
     78   if os.environ['BUILDBOT_CLOBBER'] == '1':
     79     print '@@@BUILD_STEP Clobber Android checkout@@@'
     80     shutil.rmtree(ANDROID_DIR)
     81 
     82   # The release of Android we use is static, so there's no need to do anything
     83   # if the directory already exists.
     84   if os.path.isdir(ANDROID_DIR):
     85     return
     86 
     87   print '@@@BUILD_STEP Initialize Android checkout@@@'
     88   os.mkdir(ANDROID_DIR)
     89   CallSubProcess(['git', 'config', '--global', 'user.name', 'trybot'])
     90   CallSubProcess(['git', 'config', '--global',
     91                   'user.email', 'chrome-bot (at] google.com'])
     92   CallSubProcess(['git', 'config', '--global', 'color.ui', 'false'])
     93   CallSubProcess(
     94       ['repo', 'init',
     95        '-u', 'https://android.googlesource.com/platform/manifest',
     96        '-b', 'android-4.2.1_r1',
     97        '-g', 'all,-notdefault,-device,-darwin,-mips,-x86'],
     98       cwd=ANDROID_DIR)
     99 
    100   print '@@@BUILD_STEP Sync Android@@@'
    101   CallSubProcess(['repo', 'sync', '-j4'], cwd=ANDROID_DIR)
    102 
    103   print '@@@BUILD_STEP Build Android@@@'
    104   CallSubProcess(
    105       ['/bin/bash',
    106        '-c', 'source build/envsetup.sh && lunch full-eng && make -j4'],
    107       cwd=ANDROID_DIR)
    108 
    109 
    110 def GypTestFormat(title, format=None, msvs_version=None):
    111   """Run the gyp tests for a given format, emitting annotator tags.
    112 
    113   See annotator docs at:
    114     https://sites.google.com/a/chromium.org/dev/developers/testing/chromium-build-infrastructure/buildbot-annotations
    115   Args:
    116     format: gyp format to test.
    117   Returns:
    118     0 for sucesss, 1 for failure.
    119   """
    120   if not format:
    121     format = title
    122 
    123   print '@@@BUILD_STEP ' + title + '@@@'
    124   sys.stdout.flush()
    125   env = os.environ.copy()
    126   if msvs_version:
    127     env['GYP_MSVS_VERSION'] = msvs_version
    128   command = ' '.join(
    129       [sys.executable, 'trunk/gyptest.py',
    130        '--all',
    131        '--passed',
    132        '--format', format,
    133        '--path', CMAKE_BIN_DIR,
    134        '--chdir', 'trunk'])
    135   if format == 'android':
    136     # gyptest needs the environment setup from envsetup/lunch in order to build
    137     # using the 'android' backend, so this is done in a single shell.
    138     retcode = subprocess.call(
    139         ['/bin/bash',
    140          '-c', 'source build/envsetup.sh && lunch full-eng && cd %s && %s'
    141          % (ROOT_DIR, command)],
    142         cwd=ANDROID_DIR, env=env)
    143   else:
    144     retcode = subprocess.call(command, cwd=ROOT_DIR, env=env, shell=True)
    145   if retcode:
    146     # Emit failure tag, and keep going.
    147     print '@@@STEP_FAILURE@@@'
    148     return 1
    149   return 0
    150 
    151 
    152 def GypBuild():
    153   # Dump out/ directory.
    154   print '@@@BUILD_STEP cleanup@@@'
    155   print 'Removing %s...' % OUT_DIR
    156   shutil.rmtree(OUT_DIR, ignore_errors=True)
    157   print 'Done.'
    158 
    159   retcode = 0
    160   # The Android gyp bot runs on linux so this must be tested first.
    161   if os.environ['BUILDBOT_BUILDERNAME'] == 'gyp-android':
    162     PrepareAndroidTree()
    163     retcode += GypTestFormat('android')
    164   elif sys.platform.startswith('linux'):
    165     retcode += GypTestFormat('ninja')
    166     retcode += GypTestFormat('make')
    167     PrepareCmake()
    168     retcode += GypTestFormat('cmake')
    169   elif sys.platform == 'darwin':
    170     retcode += GypTestFormat('ninja')
    171     retcode += GypTestFormat('xcode')
    172     retcode += GypTestFormat('make')
    173   elif sys.platform == 'win32':
    174     retcode += GypTestFormat('ninja')
    175     if os.environ['BUILDBOT_BUILDERNAME'] == 'gyp-win64':
    176       retcode += GypTestFormat('msvs-2010', format='msvs', msvs_version='2010')
    177       retcode += GypTestFormat('msvs-2012', format='msvs', msvs_version='2012')
    178   else:
    179     raise Exception('Unknown platform')
    180   if retcode:
    181     # TODO(bradnelson): once the annotator supports a postscript (section for
    182     #     after the build proper that could be used for cumulative failures),
    183     #     use that instead of this. This isolates the final return value so
    184     #     that it isn't misattributed to the last stage.
    185     print '@@@BUILD_STEP failures@@@'
    186     sys.exit(retcode)
    187 
    188 
    189 if __name__ == '__main__':
    190   GypBuild()
    191