2 # Copyright (c) 2012 The Native Client Authors. 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.
6 # Enable 'with' statements in Python 2.5
7 from __future__ import with_statement
15 from buildbot_lib import (
16 BuildContext, BuildStatus, Command, EnsureDirectoryExists,
17 ParseStandardCommandLine, RemoveDirectory, RemoveGypBuildDirectories,
18 RemoveSconsBuildDirectories, RunBuild, SCons, Step, StepLink,
19 StepText, TryToCleanContents)
22 # Windows-specific environment manipulation
23 def SetupWindowsEnvironment(context):
24 # Poke around looking for MSVC. We should do something more principled in
27 # The name of Program Files can differ, depending on the bittage of Windows.
28 program_files = r'c:\Program Files (x86)'
29 if not os.path.exists(program_files):
30 program_files = r'c:\Program Files'
31 if not os.path.exists(program_files):
32 raise Exception('Cannot find the Program Files directory!')
34 # The location of MSVC can differ depending on the version.
36 ('Microsoft Visual Studio 12.0', 'VS120COMNTOOLS', '2013'),
37 ('Microsoft Visual Studio 10.0', 'VS100COMNTOOLS', '2010'),
38 ('Microsoft Visual Studio 9.0', 'VS90COMNTOOLS', '2008'),
39 ('Microsoft Visual Studio 8.0', 'VS80COMNTOOLS', '2005'),
42 for dirname, comntools_var, gyp_msvs_version in msvc_locs:
43 msvc = os.path.join(program_files, dirname)
44 context.SetEnv('GYP_MSVS_VERSION', gyp_msvs_version)
45 if os.path.exists(msvc):
48 # The break statement did not execute.
49 raise Exception('Cannot find MSVC!')
51 # Put MSVC in the path.
52 vc = os.path.join(msvc, 'VC')
53 comntools = os.path.join(msvc, 'Common7', 'Tools')
54 perf = os.path.join(msvc, 'Team Tools', 'Performance Tools')
55 context.SetEnv('PATH', os.pathsep.join([
56 context.GetEnv('PATH'),
61 # SCons needs this variable to find vsvars.bat.
62 # The end slash is needed because the batch files expect it.
63 context.SetEnv(comntools_var, comntools + '\\')
65 # This environment variable will SCons to print debug info while it searches
67 context.SetEnv('SCONS_MSCOMMON_DEBUG', '-')
69 # Needed for finding devenv.
70 context['msvc'] = msvc
72 # The context on other systems has GYP_DEFINES set, set it for windows to be
73 # able to save and restore without KeyError.
74 context.SetEnv('GYP_DEFINES', '')
77 def SetupGypDefines(context, extra_vars=[]):
78 context.SetEnv('GYP_DEFINES', ' '.join(context['gyp_vars'] + extra_vars))
81 def SetupLinuxEnvironment(context):
82 SetupGypDefines(context, ['target_arch='+context['gyp_arch']])
85 def SetupMacEnvironment(context):
86 SetupGypDefines(context)
87 context.SetEnv('GYP_GENERATORS', 'ninja')
90 def SetupContextVars(context):
91 # The branch is set to native_client on the main bots, on the trybots it's
92 # set to ''. Otherwise, we should assume a particular branch is being used.
93 context['branch'] = os.environ.get('BUILDBOT_BRANCH', 'native_client')
94 context['off_trunk'] = context['branch'] not in ['native_client', '']
97 def ValidatorTest(context, architecture, validator, warn_only=False):
100 'tests/abi_corpus/validator_regression_test.py',
102 '--validator', validator,
103 '--arch', architecture
106 cmd.append('--warn-only')
107 Command(context, cmd=cmd)
110 def SummarizeCoverage(context):
113 'tools/coverage_summary.py',
114 context['platform'] + '-' + context['default_scons_platform'],
118 def ArchiveCoverage(context):
119 gsutil = '/b/build/third_party/gsutil/gsutil'
120 gsd_url = 'http://gsdview.appspot.com/nativeclient-coverage2/revs'
121 variant_name = ('coverage-' + context['platform'] + '-' +
122 context['default_scons_platform'])
123 coverage_path = variant_name + '/html/index.html'
124 revision = os.environ.get('BUILDBOT_REVISION', 'None')
125 link_url = gsd_url + '/' + revision + '/' + coverage_path
126 gsd_base = 'gs://nativeclient-coverage2/revs'
127 gs_path = gsd_base + '/' + revision + '/' + variant_name
128 cov_dir = 'scons-out/' + variant_name + '/coverage'
131 sys.executable, gsutil,
132 'cp', '-a', 'public-read',
133 cov_dir + '/coverage.lcov',
134 gs_path + '/coverage.lcov',
138 sys.executable, gsutil,
139 'cp', '-R', '-a', 'public-read',
142 print '@@@STEP_LINK@view@%s@@@' % link_url
145 def CommandGypBuild(context):
146 if context.Windows():
149 cmd=[os.path.join(context['msvc'], 'Common7', 'IDE', 'devenv.com'),
151 '/build', context['gyp_mode']])
152 elif context.Linux():
153 Command(context, cmd=['make', '-C', '..', '-k',
154 '-j%d' % context['max_jobs'], 'V=1',
155 'BUILDTYPE=' + context['gyp_mode']])
157 Command(context, cmd=[
158 'ninja', '-k', '0', '-C', '../out/' + context['gyp_mode']])
160 raise Exception('Unknown platform')
163 def CommandGypGenerate(context):
168 'native_client/build/gyp_nacl',
169 'native_client/build/all.gyp',
174 def CommandGclientRunhooks(context):
175 if context.Windows():
176 gclient = 'gclient.bat'
179 print 'Running gclient runhooks...'
180 print 'GYP_DEFINES=' + context.GetEnv('GYP_DEFINES')
181 Command(context, cmd=[gclient, 'runhooks', '--force'])
184 def BuildScript(status, context):
185 inside_toolchain = context['inside_toolchain']
187 # Clean out build directories.
188 with Step('clobber', status):
189 RemoveSconsBuildDirectories()
190 RemoveGypBuildDirectories()
192 with Step('cleanup_temp', status):
193 # Picking out drive letter on which the build is happening so we can use
194 # it for the temp directory.
195 if context.Windows():
196 build_drive = os.path.splitdrive(os.path.abspath(__file__))[0]
197 tmp_dir = os.path.join(build_drive, os.path.sep + 'temp')
198 context.SetEnv('TEMP', tmp_dir)
199 context.SetEnv('TMP', tmp_dir)
202 print 'Making sure %s exists...' % tmp_dir
203 EnsureDirectoryExists(tmp_dir)
204 print 'Cleaning up the contents of %s...' % tmp_dir
205 # Only delete files and directories like:
206 # a) C:\temp\83C4.tmp
207 # b) /tmp/.org.chromium.Chromium.EQrEzl
208 file_name_re = re.compile(
209 r'[\\/]([0-9a-fA-F]+\.tmp|\.org\.chrom\w+\.Chrom\w+\..+)$')
210 file_name_filter = lambda fn: file_name_re.search(fn) is not None
211 TryToCleanContents(tmp_dir, file_name_filter)
213 # Mac has an additional temporary directory; clean it up.
214 # TODO(bradnelson): Fix Mac Chromium so that these temp files are created
215 # with open() + unlink() so that they will not get left behind.
218 "find /var/folders -name '.org.chromium.*' -exec rm -rfv '{}' ';'",
221 "find /var/folders -name '.com.google.Chrome*' -exec rm -rfv '{}' ';'",
224 # Skip over hooks when run inside the toolchain build because
225 # download_toolchains would overwrite the toolchain build.
227 with Step('gyp_generate_only', status):
228 CommandGypGenerate(context)
230 with Step('gclient_runhooks', status):
231 CommandGclientRunhooks(context)
234 with Step('update_clang', status):
235 Command(context, cmd=['../tools/clang/scripts/update.sh'])
237 # Just build both bitages of validator and test for --validator mode.
238 if context['validator']:
239 with Step('build ncval-x86-32', status):
240 SCons(context, platform='x86-32', parallel=True, args=['ncval'])
241 with Step('build ncval-x86-64', status):
242 SCons(context, platform='x86-64', parallel=True, args=['ncval'])
244 with Step('build ragel_validator-32', status):
245 SCons(context, platform='x86-32', parallel=True, args=['ncval_new'])
246 with Step('build ragel_validator-64', status):
247 SCons(context, platform='x86-64', parallel=True, args=['ncval_new'])
249 with Step('predownload validator corpus', status):
252 'tests/abi_corpus/validator_regression_test.py',
255 with Step('validator_regression_test current x86-32', status,
258 context, 'x86-32', 'scons-out/opt-linux-x86-32/staging/ncval')
259 with Step('validator_regression_test current x86-64', status,
262 context, 'x86-64', 'scons-out/opt-linux-x86-64/staging/ncval')
264 with Step('validator_regression_test ragel x86-32', status,
268 'scons-out/opt-linux-x86-32/staging/ncval_new')
269 with Step('validator_regression_test ragel x86-64', status,
273 'scons-out/opt-linux-x86-64/staging/ncval_new')
275 with Step('validator_diff32_tests', status, halt_on_fail=False):
276 SCons(context, platform='x86-32', args=['validator_diff_tests'])
277 with Step('validator_diff64_tests', status, halt_on_fail=False):
278 SCons(context, platform='x86-64', args=['validator_diff_tests'])
281 # Run checkdeps script to vet #includes.
282 with Step('checkdeps', status):
283 Command(context, cmd=[sys.executable, 'tools/checkdeps/checkdeps.py'])
285 # Make sure our Gyp build is working.
286 if not context['no_gyp']:
287 with Step('gyp_compile', status):
288 CommandGypBuild(context)
290 # On a subset of Linux builds, build Breakpad tools for testing.
291 if context['use_breakpad_tools']:
292 with Step('breakpad configure', status):
293 Command(context, cmd=['mkdir', '-p', 'breakpad-out'])
294 Command(context, cwd='breakpad-out',
295 cmd=['bash', '../../breakpad/configure',
296 'CXXFLAGS=-I../..']) # For third_party/lss
297 with Step('breakpad make', status):
298 Command(context, cmd=['make', '-j%d' % context['max_jobs']],
301 # The main compile step.
302 with Step('scons_compile', status):
303 SCons(context, parallel=True, args=[])
305 if context['coverage']:
306 with Step('collect_coverage', status, halt_on_fail=True):
307 SCons(context, args=['coverage'])
308 with Step('summarize_coverage', status, halt_on_fail=False):
309 SummarizeCoverage(context)
310 slave_type = os.environ.get('BUILDBOT_SLAVE_TYPE')
311 if slave_type != 'Trybot' and slave_type is not None:
312 with Step('archive_coverage', status, halt_on_fail=True):
313 ArchiveCoverage(context)
317 with Step('small_tests', status, halt_on_fail=False):
318 SCons(context, args=['small_tests'])
319 with Step('medium_tests', status, halt_on_fail=False):
320 SCons(context, args=['medium_tests'])
321 with Step('large_tests', status, halt_on_fail=False):
322 SCons(context, args=['large_tests'])
324 with Step('compile IRT tests', status):
325 SCons(context, parallel=True, mode=['nacl_irt_test'])
327 with Step('small_tests under IRT', status, halt_on_fail=False):
328 SCons(context, mode=context['default_scons_mode'] + ['nacl_irt_test'],
329 args=['small_tests_irt'])
330 with Step('medium_tests under IRT', status, halt_on_fail=False):
331 SCons(context, mode=context['default_scons_mode'] + ['nacl_irt_test'],
332 args=['medium_tests_irt'])
336 if not context['no_gyp']:
337 # Build with ragel-based validator using GYP.
338 gyp_defines_save = context.GetEnv('GYP_DEFINES')
339 context.SetEnv('GYP_DEFINES',
340 ' '.join([gyp_defines_save, 'nacl_validator_ragel=0']))
341 with Step('gyp_compile_noragel', status):
342 # Clobber GYP build to recompile necessary files with new preprocessor macro
343 # definitions. It is done because some build systems (such as GNU Make,
344 # MSBuild etc.) do not consider compiler arguments as a dependency.
345 RemoveGypBuildDirectories()
346 CommandGypGenerate(context)
347 CommandGypBuild(context)
348 context.SetEnv('GYP_DEFINES', gyp_defines_save)
350 # Build with ragel-based validator using scons.
351 with Step('scons_compile_noragel', status):
352 SCons(context, parallel=True, args=['validator_ragel=0'])
354 # Smoke tests for the R-DFA validator.
355 with Step('validator_noragel_tests', status):
356 args = ['validator_ragel=0',
361 # Add nacl_irt_test mode to be able to run run_hello_world_test_irt that
362 # tests validation of the IRT.
364 mode=context['default_scons_mode'] + ['nacl_irt_test'],
369 # TODO(ncbray) make buildbot scripts composable to support toolchain use case.
370 context = BuildContext()
371 status = BuildStatus(context)
372 ParseStandardCommandLine(context)
373 SetupContextVars(context)
374 if context.Windows():
375 SetupWindowsEnvironment(context)
376 elif context.Linux():
377 SetupLinuxEnvironment(context)
379 SetupMacEnvironment(context)
381 raise Exception("Unsupported platform.")
382 RunBuild(BuildScript, status)
386 start_time = time.time()
390 time_taken = time.time() - start_time
391 print 'RESULT BuildbotTime: total= %.3f minutes' % (time_taken / 60)
394 if __name__ == '__main__':