buildbot_common.py revision cedac228d2dd51db4b79ea1e72c7f249408ee061
1# Copyright (c) 2012 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""Common utilities for all buildbot scripts that specifically don't rely 6on having a full chromium checkout. 7""" 8 9import os 10import subprocess 11import sys 12 13from build_paths import SDK_SRC_DIR, NACL_DIR 14 15sys.path.append(os.path.join(SDK_SRC_DIR, 'tools')) 16import oshelpers 17import getos 18 19 20verbose = True 21 22 23def IsSDKBuilder(): 24 """Returns True if this script is running on an SDK builder. 25 26 False means it is either running on a trybot, or a user's machine. 27 28 Trybot names: 29 (win|mac|linux)_nacl_sdk 30 31 Build-only Trybot names: 32 (win|mac|linux)_nacl_sdk_build 33 34 Builder names: 35 (windows|mac|linux)-sdk-multi(bionic)(rel)?""" 36 bot = os.getenv('BUILDBOT_BUILDERNAME', '') 37 return '-sdk-multi' in bot or '-sdk-bionic-multi' in bot 38 39 40def IsSDKTrybot(): 41 """Returns True if this script is running on an SDK trybot. 42 43 False means it is either running on an SDK builder, or a user's machine. 44 45 See IsSDKBuilder above for trybot/buildbot names.""" 46 return '_nacl_sdk' in os.getenv('BUILDBOT_BUILDERNAME', '') 47 48 49def ErrorExit(msg): 50 """Write and error to stderr, then exit with 1 signaling failure.""" 51 sys.stderr.write(str(msg) + '\n') 52 sys.exit(1) 53 54 55def Trace(msg): 56 if verbose: 57 sys.stderr.write(str(msg) + '\n') 58 59 60def GetWindowsEnvironment(): 61 sys.path.append(os.path.join(NACL_DIR, 'buildbot')) 62 import buildbot_standard 63 64 # buildbot_standard.SetupWindowsEnvironment expects a "context" object. We'll 65 # fake enough of that here to work. 66 class FakeContext(object): 67 def __init__(self): 68 self.env = os.environ 69 70 def GetEnv(self, key): 71 return self.env[key] 72 73 def __getitem__(self, key): 74 return self.env[key] 75 76 def SetEnv(self, key, value): 77 self.env[key] = value 78 79 def __setitem__(self, key, value): 80 self.env[key] = value 81 82 context = FakeContext() 83 buildbot_standard.SetupWindowsEnvironment(context) 84 85 # buildbot_standard.SetupWindowsEnvironment adds the directory which contains 86 # vcvarsall.bat to the path, but not the directory which contains cl.exe, 87 # link.exe, etc. 88 # Running vcvarsall.bat adds the correct directories to the path, which we 89 # extract below. 90 process = subprocess.Popen('vcvarsall.bat x86 > NUL && set', 91 stdout=subprocess.PIPE, env=context.env, shell=True) 92 stdout, _ = process.communicate() 93 94 # Parse environment from "set" command above. 95 # It looks like this: 96 # KEY1=VALUE1\r\n 97 # KEY2=VALUE2\r\n 98 # ... 99 return dict(line.split('=') for line in stdout.split('\r\n')[:-1]) 100 101 102def BuildStep(name): 103 """Annotate a buildbot build step.""" 104 sys.stdout.flush() 105 sys.stderr.write('\n@@@BUILD_STEP %s@@@\n' % name) 106 107 108def Run(args, cwd=None, env=None, shell=False): 109 """Start a process with the provided arguments. 110 111 Starts a process in the provided directory given the provided arguments. If 112 shell is not False, the process is launched via the shell to provide shell 113 interpretation of the arguments. Shell behavior can differ between platforms 114 so this should be avoided when not using platform dependent shell scripts.""" 115 116 # We need to modify the environment to build host on Windows. 117 if not env and getos.GetPlatform() == 'win': 118 env = GetWindowsEnvironment() 119 120 Trace('Running: ' + ' '.join(args)) 121 sys.stdout.flush() 122 sys.stderr.flush() 123 try: 124 subprocess.check_call(args, cwd=cwd, env=env, shell=shell) 125 except subprocess.CalledProcessError as e: 126 sys.stdout.flush() 127 sys.stderr.flush() 128 ErrorExit('buildbot_common: %s' % e) 129 130 sys.stdout.flush() 131 sys.stderr.flush() 132 133 134def CopyDir(src, dst, excludes=('.svn', '*/.svn')): 135 """Recursively copy a directory using.""" 136 args = ['-r', src, dst] 137 for exc in excludes: 138 args.append('--exclude=' + exc) 139 Trace('cp -r %s %s' % (src, dst)) 140 if os.path.abspath(src) == os.path.abspath(dst): 141 ErrorExit('ERROR: Copying directory onto itself: ' + src) 142 oshelpers.Copy(args) 143 144 145def CopyFile(src, dst): 146 Trace('cp %s %s' % (src, dst)) 147 if os.path.abspath(src) == os.path.abspath(dst): 148 ErrorExit('ERROR: Copying file onto itself: ' + src) 149 args = [src, dst] 150 oshelpers.Copy(args) 151 152 153def RemoveDir(dst): 154 """Remove the provided path.""" 155 Trace('rm -fr ' + dst) 156 oshelpers.Remove(['-fr', dst]) 157 158 159def MakeDir(dst): 160 """Create the path including all parent directories as needed.""" 161 Trace('mkdir -p ' + dst) 162 oshelpers.Mkdir(['-p', dst]) 163 164 165def Move(src, dst): 166 """Move the path src to dst.""" 167 Trace('mv -f %s %s' % (src, dst)) 168 oshelpers.Move(['-f', src, dst]) 169 170 171def RemoveFile(dst): 172 """Remove the provided file.""" 173 Trace('rm ' + dst) 174 oshelpers.Remove(['-f', dst]) 175 176 177BOT_GSUTIL = '/b/build/scripts/slave/gsutil' 178# On Windows, the current working directory may be on a different drive than 179# gsutil. 180WIN_BOT_GSUTIL = 'E:' + BOT_GSUTIL 181LOCAL_GSUTIL = 'gsutil' 182 183 184def GetGsutil(): 185 if os.environ.get('BUILDBOT_BUILDERNAME') \ 186 and not os.environ.get('BUILDBOT_FAKE'): 187 if getos.GetPlatform() == 'win': 188 return WIN_BOT_GSUTIL 189 return BOT_GSUTIL 190 else: 191 return LOCAL_GSUTIL 192 193 194def Archive(filename, bucket_path, cwd=None, step_link=True): 195 """Upload the given filename to Google Store.""" 196 full_dst = 'gs://%s/%s' % (bucket_path, filename) 197 198 # Since GetGsutil() might just return 'gsutil' and expect it to be looked 199 # up in the PATH, we must pass shell=True on windows. 200 # Without shell=True the windows implementation of subprocess.call will not 201 # search the PATH for the executable: http://bugs.python.org/issue8557 202 shell = getos.GetPlatform() == 'win' 203 204 cmd = [GetGsutil(), 'cp', '-a', 'public-read', filename, full_dst] 205 Run(cmd, shell=shell, cwd=cwd) 206 url = 'https://storage.googleapis.com/%s/%s' % (bucket_path, filename) 207 if step_link: 208 sys.stdout.flush() 209 sys.stderr.write('@@@STEP_LINK@download@%s@@@\n' % url) 210