2 # Copyright (c) 2012 The Chromium 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 """Entry point for both build and try bots.
8 This script is invoked from XXX, usually without arguments
9 to package an SDK. It automatically determines whether
10 this SDK is for mac, win, linux.
12 The script inspects the following environment variables:
14 BUILDBOT_BUILDERNAME to determine whether the script is run locally
15 and whether it should upload an SDK to file storage (GSTORE)
18 # pylint: disable=W0621
28 if sys.version_info < (2, 6, 0):
29 sys.stderr.write("python 2.6 or later is required run this script\n")
33 import buildbot_common
37 import generate_notice
40 import verify_filelist
42 from build_paths import SCRIPT_DIR, SDK_SRC_DIR, SRC_DIR, NACL_DIR, OUT_DIR
43 from build_paths import NACLPORTS_DIR, GSTORE, GONACL_APPENGINE_SRC_DIR
45 # Add SDK make tools scripts to the python path.
46 sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))
47 sys.path.append(os.path.join(NACL_DIR, 'build'))
52 BUILD_DIR = os.path.join(NACL_DIR, 'build')
53 NACL_TOOLCHAIN_DIR = os.path.join(NACL_DIR, 'toolchain')
54 NACL_TOOLCHAINTARS_DIR = os.path.join(NACL_TOOLCHAIN_DIR, '.tars')
56 CYGTAR = os.path.join(BUILD_DIR, 'cygtar.py')
57 PKGVER = os.path.join(BUILD_DIR, 'package_version', 'package_version.py')
59 NACLPORTS_URL = 'https://naclports.googlecode.com/svn/trunk/src'
62 GYPBUILD_DIR = 'gypbuild'
66 # Map of: ToolchainName: (PackageName, SDKDir).
67 TOOLCHAIN_PACKAGE_MAP = {
68 'newlib': ('nacl_x86_newlib', '%(platform)s_x86_newlib'),
69 'bionic': ('nacl_arm_bionic', '%(platform)s_arm_bionic'),
70 'arm': ('nacl_arm_newlib', '%(platform)s_arm_newlib'),
71 'glibc': ('nacl_x86_glibc', '%(platform)s_x86_glibc'),
72 'pnacl': ('pnacl_newlib', '%(platform)s_pnacl')
76 def GetToolchainNaClInclude(tcname, tcpath, arch):
79 return os.path.join(tcpath, 'sdk', 'include')
80 return os.path.join(tcpath, 'x86_64-nacl', 'include')
82 return os.path.join(tcpath, 'arm-nacl', 'include')
84 buildbot_common.ErrorExit('Unknown architecture: %s' % arch)
87 def GetGypGenDir(xarch):
89 build_dir = GYPBUILD_DIR + '-arm'
91 build_dir = GYPBUILD_DIR
92 return os.path.join(OUT_DIR, build_dir, 'Release', 'gen')
95 def GetGypBuiltLib(tcname, xarch=None):
97 tcname = 'pnacl_newlib'
100 return os.path.join(GetGypGenDir(xarch), 'tc_' + tcname, 'lib' + xarch)
103 def GetToolchainNaClLib(tcname, tcpath, xarch):
104 if tcname == 'pnacl':
105 return os.path.join(tcpath, 'sdk', 'lib')
107 return os.path.join(tcpath, 'x86_64-nacl', 'lib32')
109 return os.path.join(tcpath, 'x86_64-nacl', 'lib')
111 return os.path.join(tcpath, 'arm-nacl', 'lib')
114 def GetToolchainDirName(tcname, xarch):
115 if tcname == 'pnacl':
116 return '%s_%s' % (getos.GetPlatform(), tcname)
118 return '%s_arm_%s' % (getos.GetPlatform(), tcname)
120 return '%s_x86_%s' % (getos.GetPlatform(), tcname)
123 def GetGypToolchainLib(tcname, xarch):
129 tcpath = os.path.join(GetGypGenDir(xarch), 'sdk',
130 '%s_x86' % getos.GetPlatform(),
131 TOOLCHAIN_PACKAGE_MAP[toolchain][0])
132 return GetToolchainNaClLib(tcname, tcpath, xarch)
135 def GetOutputToolchainLib(pepperdir, tcname, xarch):
136 tcpath = os.path.join(pepperdir, 'toolchain',
137 GetToolchainDirName(tcname, xarch))
138 return GetToolchainNaClLib(tcname, tcpath, xarch)
141 def GetPNaClNativeLib(tcpath, arch):
142 if arch not in ['arm', 'x86-32', 'x86-64']:
143 buildbot_common.ErrorExit('Unknown architecture %s.' % arch)
144 return os.path.join(tcpath, 'lib-' + arch)
147 def BuildStepDownloadToolchains(toolchains):
148 buildbot_common.BuildStep('Running package_version.py')
149 args = [sys.executable, PKGVER, '--exclude', 'arm_trusted']
150 if 'bionic' in toolchains:
151 build_platform = '%s_x86' % getos.GetPlatform()
152 args.extend(['--append', os.path.join(build_platform, 'nacl_arm_bionic')])
154 buildbot_common.Run(args, cwd=NACL_DIR)
157 def BuildStepCleanPepperDirs(pepperdir, pepperdir_old):
158 buildbot_common.BuildStep('Clean Pepper Dirs')
159 buildbot_common.RemoveDir(pepperdir_old)
160 buildbot_common.RemoveDir(pepperdir)
161 buildbot_common.MakeDir(pepperdir)
164 def BuildStepMakePepperDirs(pepperdir, subdirs):
165 for subdir in subdirs:
166 buildbot_common.MakeDir(os.path.join(pepperdir, subdir))
173 'getting_started/README',
176 def BuildStepCopyTextFiles(pepperdir, pepper_ver, chrome_revision,
178 buildbot_common.BuildStep('Add Text Files')
179 InstallFiles(SDK_SRC_DIR, pepperdir, TEXT_FILES)
181 # Replace a few placeholders in README
182 readme_text = open(os.path.join(SDK_SRC_DIR, 'README')).read()
183 readme_text = readme_text.replace('${VERSION}', pepper_ver)
184 readme_text = readme_text.replace('${CHROME_REVISION}', chrome_revision)
185 readme_text = readme_text.replace('${CHROME_COMMIT_POSITION}',
186 build_version.ChromeCommitPosition())
187 readme_text = readme_text.replace('${NACL_REVISION}', nacl_revision)
189 # Year/Month/Day Hour:Minute:Second
190 time_format = '%Y/%m/%d %H:%M:%S'
191 readme_text = readme_text.replace('${DATE}',
192 datetime.datetime.now().strftime(time_format))
194 open(os.path.join(pepperdir, 'README'), 'w').write(readme_text)
197 def BuildStepUntarToolchains(pepperdir, toolchains):
198 buildbot_common.BuildStep('Untar Toolchains')
199 platform = getos.GetPlatform()
200 build_platform = '%s_x86' % platform
201 tmpdir = os.path.join(OUT_DIR, 'tc_temp')
202 buildbot_common.RemoveDir(tmpdir)
203 buildbot_common.MakeDir(tmpdir)
205 # Create a list of extract packages tuples, the first part should be
206 # "$PACKAGE_TARGET/$PACKAGE". The second part should be the destination
207 # directory relative to pepperdir/toolchain.
208 extract_packages = []
209 for toolchain in toolchains:
210 toolchain_map = TOOLCHAIN_PACKAGE_MAP.get(toolchain, None)
212 package_name, tcname = toolchain_map
213 package_tuple = (os.path.join(build_platform, package_name),
214 tcname % {'platform': platform})
215 extract_packages.append(package_tuple)
218 # Extract all of the packages into the temp directory.
219 package_names = [package_tuple[0] for package_tuple in extract_packages]
220 buildbot_common.Run([sys.executable, PKGVER,
221 '--packages', ','.join(package_names),
222 '--tar-dir', NACL_TOOLCHAINTARS_DIR,
223 '--dest-dir', tmpdir,
226 # Move all the packages we extracted to the correct destination.
227 for package_name, dest_dir in extract_packages:
228 full_src_dir = os.path.join(tmpdir, package_name)
229 full_dst_dir = os.path.join(pepperdir, 'toolchain', dest_dir)
230 buildbot_common.Move(full_src_dir, full_dst_dir)
232 # Cleanup the temporary directory we are no longer using.
233 buildbot_common.RemoveDir(tmpdir)
236 # List of toolchain headers to install.
237 # Source is relative to top of Chromium tree, destination is relative
238 # to the toolchain header directory.
241 ('native_client/src/include/nacl/nacl_exception.h', 'nacl/'),
242 ('native_client/src/include/nacl/nacl_minidump.h', 'nacl/'),
243 ('native_client/src/untrusted/irt/irt.h', ''),
244 ('native_client/src/untrusted/irt/irt_dev.h', ''),
245 ('native_client/src/untrusted/nacl/nacl_dyncode.h', 'nacl/'),
246 ('native_client/src/untrusted/nacl/nacl_startup.h', 'nacl/'),
247 ('native_client/src/untrusted/pthread/pthread.h', ''),
248 ('native_client/src/untrusted/pthread/semaphore.h', ''),
249 ('native_client/src/untrusted/valgrind/dynamic_annotations.h', 'nacl/'),
250 ('ppapi/nacl_irt/public/irt_ppapi.h', ''),
253 ('native_client/src/include/nacl/nacl_exception.h', 'nacl/'),
254 ('native_client/src/include/nacl/nacl_minidump.h', 'nacl/'),
255 ('native_client/src/untrusted/irt/irt.h', ''),
256 ('native_client/src/untrusted/irt/irt_dev.h', ''),
257 ('native_client/src/untrusted/nacl/nacl_dyncode.h', 'nacl/'),
258 ('native_client/src/untrusted/nacl/nacl_startup.h', 'nacl/'),
259 ('native_client/src/untrusted/valgrind/dynamic_annotations.h', 'nacl/'),
260 ('ppapi/nacl_irt/public/irt_ppapi.h', ''),
265 def InstallFiles(src_root, dest_root, file_list):
266 """Copy a set of files from src_root to dest_root according
267 to the given mapping. This allows files to be copied from
268 to a location in the destination tree that is different to the
269 location in the source tree.
271 If the destination mapping ends with a '/' then the destination
272 basename is inherited from the the source file.
274 Wildcards can be used in the source list but it is not recommended
275 as this can end up adding things to the SDK unintentionally.
277 for file_spec in file_list:
278 # The list of files to install can be a simple list of
279 # strings or a list of pairs, where each pair corresponds
280 # to a mapping from source to destination names.
281 if type(file_spec) == str:
282 src_file = dest_file = file_spec
284 src_file, dest_file = file_spec
286 src_file = os.path.join(src_root, src_file)
288 # Expand sources files using glob.
289 sources = glob.glob(src_file)
293 if len(sources) > 1 and not dest_file.endswith('/'):
294 buildbot_common.ErrorExit("Target file must end in '/' when "
295 "using globbing to install multiple files")
297 for source in sources:
298 if dest_file.endswith('/'):
299 dest = os.path.join(dest_file, os.path.basename(source))
302 dest = os.path.join(dest_root, dest)
303 if not os.path.isdir(os.path.dirname(dest)):
304 buildbot_common.MakeDir(os.path.dirname(dest))
305 buildbot_common.CopyFile(source, dest)
308 def InstallNaClHeaders(tc_dst_inc, tc_name):
309 """Copies NaCl headers to expected locations in the toolchain."""
311 # arm toolchain header should be the same as the x86 newlib
315 InstallFiles(SRC_DIR, tc_dst_inc, NACL_HEADER_MAP[tc_name])
318 def MakeNinjaRelPath(path):
319 return os.path.join(os.path.relpath(OUT_DIR, SRC_DIR), path)
324 'libminidump_generator.a',
326 'libnacl_exception.a',
327 'libnacl_list_mappings.a',
333 'libminidump_generator.a',
336 'libnacl_exception.a',
337 'libnacl_list_mappings.a',
344 'libminidump_generator.a',
345 'libminidump_generator.so',
348 'libnacl_dyncode.so',
349 'libnacl_exception.a',
350 'libnacl_exception.so',
351 'libnacl_list_mappings.a',
352 'libnacl_list_mappings.so',
358 'libminidump_generator.a',
361 'libnacl_exception.a',
362 'libnacl_list_mappings.a',
371 def GypNinjaInstall(pepperdir, toolchains):
372 build_dir = GYPBUILD_DIR
373 ninja_out_dir = os.path.join(OUT_DIR, build_dir, 'Release')
375 ['sel_ldr', 'sel_ldr_x86_32'],
376 ['ncval_new', 'ncval'],
377 ['irt_core_newlib_x32.nexe', 'irt_core_x86_32.nexe'],
378 ['irt_core_newlib_x64.nexe', 'irt_core_x86_64.nexe'],
381 platform = getos.GetPlatform()
383 # TODO(binji): dump_syms doesn't currently build on Windows. See
384 # http://crbug.com/245456
385 if platform != 'win':
387 ['dump_syms', 'dump_syms'],
388 ['minidump_dump', 'minidump_dump'],
389 ['minidump_stackwalk', 'minidump_stackwalk']
392 tools_files.append(['sel_ldr64', 'sel_ldr_x86_64'])
394 if platform == 'linux':
395 tools_files.append(['nacl_helper_bootstrap',
396 'nacl_helper_bootstrap_x86_32'])
397 tools_files.append(['nacl_helper_bootstrap64',
398 'nacl_helper_bootstrap_x86_64'])
400 buildbot_common.MakeDir(os.path.join(pepperdir, 'tools'))
402 # Add .exe extensions to all windows tools
403 for pair in tools_files:
404 if platform == 'win' and not pair[0].endswith('.nexe'):
408 InstallFiles(ninja_out_dir, os.path.join(pepperdir, 'tools'), tools_files)
411 if platform == 'linux' and not options.no_arm_trusted:
413 ['irt_core_newlib_arm.nexe', 'irt_core_arm.nexe'],
414 ['irt_core_newlib_arm.nexe', 'irt_core_arm.nexe'],
415 ['sel_ldr', 'sel_ldr_arm'],
416 ['nacl_helper_bootstrap', 'nacl_helper_bootstrap_arm']
418 ninja_out_dir = os.path.join(OUT_DIR, build_dir + '-arm', 'Release')
419 InstallFiles(ninja_out_dir, os.path.join(pepperdir, 'tools'), tools_files)
421 for tc in set(toolchains) & set(['newlib', 'glibc', 'pnacl']):
425 xarches = ('arm', '32', '64')
427 for xarch in xarches:
428 if tc == 'glibc' and xarch == 'arm':
431 src_dir = GetGypBuiltLib(tc, xarch)
432 dst_dir = GetOutputToolchainLib(pepperdir, tc, xarch)
433 InstallFiles(src_dir, dst_dir, TOOLCHAIN_LIBS[tc])
435 # Copy ARM newlib components to bionic
436 if tc == 'newlib' and xarch == 'arm' and 'bionic' in toolchains:
437 bionic_dir = GetOutputToolchainLib(pepperdir, 'bionic', xarch)
438 InstallFiles(src_dir, bionic_dir, TOOLCHAIN_LIBS['bionic'])
441 src_dir = GetGypToolchainLib(tc, xarch)
442 InstallFiles(src_dir, dst_dir, ['crt1.o'])
445 def GypNinjaBuild_NaCl(rel_out_dir):
446 gyp_py = os.path.join(NACL_DIR, 'build', 'gyp_nacl')
447 nacl_core_sdk_gyp = os.path.join(NACL_DIR, 'build', 'nacl_core_sdk.gyp')
448 all_gyp = os.path.join(NACL_DIR, 'build', 'all.gyp')
450 out_dir = MakeNinjaRelPath(rel_out_dir)
451 out_dir_arm = MakeNinjaRelPath(rel_out_dir + '-arm')
452 GypNinjaBuild('ia32', gyp_py, nacl_core_sdk_gyp, 'nacl_core_sdk', out_dir)
453 GypNinjaBuild('arm', gyp_py, nacl_core_sdk_gyp, 'nacl_core_sdk', out_dir_arm)
454 GypNinjaBuild('ia32', gyp_py, all_gyp, 'ncval_new', out_dir)
456 platform = getos.GetPlatform()
457 if platform == 'win':
458 NinjaBuild('sel_ldr64', out_dir)
460 out_dir_64 = MakeNinjaRelPath(rel_out_dir + '-64')
461 GypNinjaBuild('x64', gyp_py, nacl_core_sdk_gyp, 'sel_ldr', out_dir_64)
463 # We only need sel_ldr from the 64-bit out directory.
464 # sel_ldr needs to be renamed, so we'll call it sel_ldr64.
465 files_to_copy = [('sel_ldr', 'sel_ldr64')]
466 if platform == 'linux':
467 files_to_copy.append(('nacl_helper_bootstrap', 'nacl_helper_bootstrap64'))
469 for src, dst in files_to_copy:
470 buildbot_common.CopyFile(
471 os.path.join(SRC_DIR, out_dir_64, 'Release', src),
472 os.path.join(SRC_DIR, out_dir, 'Release', dst))
475 def GypNinjaBuild_Breakpad(rel_out_dir):
476 # TODO(binji): dump_syms doesn't currently build on Windows. See
477 # http://crbug.com/245456
478 if getos.GetPlatform() == 'win':
481 gyp_py = os.path.join(SRC_DIR, 'build', 'gyp_chromium')
482 out_dir = MakeNinjaRelPath(rel_out_dir)
483 gyp_file = os.path.join(SRC_DIR, 'breakpad', 'breakpad.gyp')
484 build_list = ['dump_syms', 'minidump_dump', 'minidump_stackwalk']
485 GypNinjaBuild('ia32', gyp_py, gyp_file, build_list, out_dir)
488 def GypNinjaBuild_PPAPI(arch, rel_out_dir):
489 gyp_py = os.path.join(SRC_DIR, 'build', 'gyp_chromium')
490 out_dir = MakeNinjaRelPath(rel_out_dir)
491 gyp_file = os.path.join(SRC_DIR, 'ppapi', 'native_client',
493 GypNinjaBuild(arch, gyp_py, gyp_file, 'ppapi_lib', out_dir)
496 def GypNinjaBuild_Pnacl(rel_out_dir, target_arch):
497 # TODO(binji): This will build the pnacl_irt_shim twice; once as part of the
498 # Chromium build, and once here. When we move more of the SDK build process
499 # to gyp, we can remove this.
500 gyp_py = os.path.join(SRC_DIR, 'build', 'gyp_chromium')
502 out_dir = MakeNinjaRelPath(rel_out_dir)
503 gyp_file = os.path.join(SRC_DIR, 'ppapi', 'native_client', 'src',
504 'untrusted', 'pnacl_irt_shim', 'pnacl_irt_shim.gyp')
506 GypNinjaBuild(target_arch, gyp_py, gyp_file, targets, out_dir, False)
509 def GypNinjaBuild(arch, gyp_py_script, gyp_file, targets,
510 out_dir, force_arm_gcc=True):
511 gyp_env = dict(os.environ)
512 gyp_env['GYP_GENERATORS'] = 'ninja'
515 gyp_defines.append('mac_sdk=%s' % options.mac_sdk)
517 gyp_defines.append('target_arch=%s' % arch)
519 if getos.GetPlatform() == 'linux':
520 gyp_env['CC'] = 'arm-linux-gnueabihf-gcc'
521 gyp_env['CXX'] = 'arm-linux-gnueabihf-g++'
522 gyp_env['AR'] = 'arm-linux-gnueabihf-ar'
523 gyp_env['AS'] = 'arm-linux-gnueabihf-as'
524 gyp_env['CC_host'] = 'cc'
525 gyp_env['CXX_host'] = 'c++'
526 gyp_defines += ['armv7=1', 'arm_thumb=0', 'arm_neon=1',
527 'arm_float_abi=hard']
529 gyp_defines.append('nacl_enable_arm_gcc=1')
530 if options.no_arm_trusted:
531 gyp_defines.append('disable_cross_trusted=1')
532 if getos.GetPlatform() == 'mac':
533 gyp_defines.append('clang=1')
535 gyp_env['GYP_DEFINES'] = ' '.join(gyp_defines)
536 for key in ['GYP_GENERATORS', 'GYP_DEFINES', 'CC']:
537 value = gyp_env.get(key)
538 if value is not None:
539 print '%s="%s"' % (key, value)
540 gyp_generator_flags = ['-G', 'output_dir=%s' % (out_dir,)]
541 gyp_depth = '--depth=.'
543 [sys.executable, gyp_py_script, gyp_file, gyp_depth] + \
547 NinjaBuild(targets, out_dir)
550 def NinjaBuild(targets, out_dir):
551 if type(targets) is not list:
553 out_config_dir = os.path.join(out_dir, 'Release')
554 buildbot_common.Run(['ninja', '-C', out_config_dir] + targets, cwd=SRC_DIR)
557 def BuildStepBuildToolchains(pepperdir, toolchains):
558 buildbot_common.BuildStep('SDK Items')
560 GypNinjaBuild_NaCl(GYPBUILD_DIR)
561 GypNinjaBuild_Breakpad(GYPBUILD_DIR)
563 platform = getos.GetPlatform()
564 newlibdir = os.path.join(pepperdir, 'toolchain', platform + '_x86_newlib')
565 glibcdir = os.path.join(pepperdir, 'toolchain', platform + '_x86_glibc')
566 armdir = os.path.join(pepperdir, 'toolchain', platform + '_arm_newlib')
567 pnacldir = os.path.join(pepperdir, 'toolchain', platform + '_pnacl')
569 if set(toolchains) & set(['glibc', 'newlib']):
570 GypNinjaBuild_PPAPI('ia32', GYPBUILD_DIR)
572 if 'arm' in toolchains:
573 GypNinjaBuild_PPAPI('arm', GYPBUILD_DIR + '-arm')
575 GypNinjaInstall(pepperdir, toolchains)
577 if 'newlib' in toolchains:
578 InstallNaClHeaders(GetToolchainNaClInclude('newlib', newlibdir, 'x86'),
581 if 'glibc' in toolchains:
582 InstallNaClHeaders(GetToolchainNaClInclude('glibc', glibcdir, 'x86'),
585 if 'arm' in toolchains:
586 InstallNaClHeaders(GetToolchainNaClInclude('newlib', armdir, 'arm'),
589 if 'pnacl' in toolchains:
590 # NOTE: For ia32, gyp builds both x86-32 and x86-64 by default.
591 for arch in ('ia32', 'arm'):
592 # Fill in the latest native pnacl shim library from the chrome build.
593 build_dir = GYPBUILD_DIR + '-pnacl-' + arch
594 GypNinjaBuild_Pnacl(build_dir, arch)
596 nacl_arches = ['x86-32', 'x86-64']
598 nacl_arches = ['arm']
600 buildbot_common.ErrorExit('Unknown architecture: %s' % arch)
601 for nacl_arch in nacl_arches:
602 release_build_dir = os.path.join(OUT_DIR, build_dir, 'Release',
603 'gen', 'tc_pnacl_translate',
606 buildbot_common.CopyFile(
607 os.path.join(release_build_dir, 'libpnacl_irt_shim.a'),
608 GetPNaClNativeLib(pnacldir, nacl_arch))
610 InstallNaClHeaders(GetToolchainNaClInclude('pnacl', pnacldir, 'x86'),
614 def MakeDirectoryOrClobber(pepperdir, dirname, clobber):
615 dirpath = os.path.join(pepperdir, dirname)
617 buildbot_common.RemoveDir(dirpath)
618 buildbot_common.MakeDir(dirpath)
623 def BuildStepUpdateHelpers(pepperdir, clobber):
624 buildbot_common.BuildStep('Update project helpers')
625 build_projects.UpdateHelpers(pepperdir, clobber=clobber)
628 def BuildStepUpdateUserProjects(pepperdir, toolchains,
629 build_experimental, clobber):
630 buildbot_common.BuildStep('Update examples and libraries')
633 if not build_experimental:
634 filters['EXPERIMENTAL'] = False
636 toolchains = toolchains[:]
638 # arm isn't a valid toolchain for build_projects
639 if 'arm' in toolchains:
640 toolchains.remove('arm')
642 if 'host' in toolchains:
643 toolchains.remove('host')
644 toolchains.append(getos.GetPlatform())
646 filters['TOOLS'] = toolchains
648 # Update examples and libraries
657 tree = parse_dsc.LoadProjectTree(SDK_SRC_DIR, include=filters)
658 build_projects.UpdateProjects(pepperdir, tree, clobber=clobber,
659 toolchains=toolchains)
662 def BuildStepMakeAll(pepperdir, directory, step_name,
663 deps=True, clean=False, config='Debug', args=None):
664 buildbot_common.BuildStep(step_name)
665 build_projects.BuildProjectsBranch(pepperdir, directory, clean,
669 def BuildStepBuildLibraries(pepperdir, directory):
670 BuildStepMakeAll(pepperdir, directory, 'Build Libraries Debug',
671 clean=True, config='Debug')
672 BuildStepMakeAll(pepperdir, directory, 'Build Libraries Release',
673 clean=True, config='Release')
675 # Cleanup .pyc file generated while building libraries. Without
676 # this we would end up shipping the pyc in the SDK tarball.
677 buildbot_common.RemoveFile(os.path.join(pepperdir, 'tools', '*.pyc'))
680 def GenerateNotice(fileroot, output_filename='NOTICE', extra_files=None):
681 # Look for LICENSE files
682 license_filenames_re = re.compile('LICENSE|COPYING|COPYRIGHT')
685 for root, _, files in os.walk(fileroot):
686 for filename in files:
687 if license_filenames_re.match(filename):
688 path = os.path.join(root, filename)
689 license_files.append(path)
692 license_files += [os.path.join(fileroot, f) for f in extra_files]
693 print '\n'.join(license_files)
695 if not os.path.isabs(output_filename):
696 output_filename = os.path.join(fileroot, output_filename)
697 generate_notice.Generate(output_filename, fileroot, license_files)
700 def BuildStepVerifyFilelist(pepperdir):
701 buildbot_common.BuildStep('Verify SDK Files')
702 file_list_path = os.path.join(SCRIPT_DIR, 'sdk_files.list')
704 verify_filelist.Verify(file_list_path, pepperdir)
706 except verify_filelist.ParseException, e:
707 buildbot_common.ErrorExit('Parsing sdk_files.list failed:\n\n%s' % e)
708 except verify_filelist.VerifyException, e:
709 file_list_rel = os.path.relpath(file_list_path)
710 verify_filelist_py = os.path.splitext(verify_filelist.__file__)[0] + '.py'
711 verify_filelist_py = os.path.relpath(verify_filelist_py)
712 pepperdir_rel = os.path.relpath(pepperdir)
715 SDK verification failed:
718 Add/remove files from %s to fix.
722 to test.""" % (e, file_list_rel, verify_filelist_py, file_list_rel,
724 buildbot_common.ErrorExit(msg)
727 def BuildStepTarBundle(pepper_ver, tarfile):
728 buildbot_common.BuildStep('Tar Pepper Bundle')
729 buildbot_common.MakeDir(os.path.dirname(tarfile))
730 buildbot_common.Run([sys.executable, CYGTAR, '-C', OUT_DIR, '-cjf', tarfile,
731 'pepper_' + pepper_ver], cwd=NACL_DIR)
734 def GetManifestBundle(pepper_ver, chrome_revision, nacl_revision, tarfile,
736 with open(tarfile, 'rb') as tarfile_stream:
737 archive_sha1, archive_size = manifest_util.DownloadAndComputeHash(
740 archive = manifest_util.Archive(manifest_util.GetHostOS())
741 archive.url = archive_url
742 archive.size = archive_size
743 archive.checksum = archive_sha1
745 bundle = manifest_util.Bundle('pepper_' + pepper_ver)
746 bundle.revision = int(chrome_revision)
747 bundle.repath = 'pepper_' + pepper_ver
748 bundle.version = int(pepper_ver)
749 bundle.description = (
750 'Chrome %s bundle. Chrome revision: %s. NaCl revision: %s' % (
751 pepper_ver, chrome_revision, nacl_revision))
752 bundle.stability = 'dev'
753 bundle.recommended = 'no'
754 bundle.archives = [archive]
758 def BuildStepArchiveBundle(name, pepper_ver, chrome_revision, nacl_revision,
760 buildbot_common.BuildStep('Archive %s' % name)
761 bucket_path = 'nativeclient-mirror/nacl/nacl_sdk/%s' % (
762 build_version.ChromeVersion(),)
763 tarname = os.path.basename(tarfile)
764 tarfile_dir = os.path.dirname(tarfile)
765 buildbot_common.Archive(tarname, bucket_path, tarfile_dir)
767 # generate "manifest snippet" for this archive.
768 archive_url = GSTORE + 'nacl_sdk/%s/%s' % (
769 build_version.ChromeVersion(), tarname)
770 bundle = GetManifestBundle(pepper_ver, chrome_revision, nacl_revision,
771 tarfile, archive_url)
773 manifest_snippet_file = os.path.join(OUT_DIR, tarname + '.json')
774 with open(manifest_snippet_file, 'wb') as manifest_snippet_stream:
775 manifest_snippet_stream.write(bundle.GetDataAsString())
777 buildbot_common.Archive(tarname + '.json', bucket_path, OUT_DIR,
781 def BuildStepArchiveSDKTools():
782 # Only push up sdk_tools.tgz and nacl_sdk.zip on the linux buildbot.
783 builder_name = os.getenv('BUILDBOT_BUILDERNAME', '')
784 if builder_name == 'linux-sdk-multi':
785 buildbot_common.BuildStep('Build SDK Tools')
786 build_updater.BuildUpdater(OUT_DIR)
788 buildbot_common.BuildStep('Archive SDK Tools')
789 bucket_path = 'nativeclient-mirror/nacl/nacl_sdk/%s' % (
790 build_version.ChromeVersion(),)
791 buildbot_common.Archive('sdk_tools.tgz', bucket_path, OUT_DIR,
793 buildbot_common.Archive('nacl_sdk.zip', bucket_path, OUT_DIR,
797 def BuildStepSyncNaClPorts():
798 """Pull the pinned revision of naclports from SVN."""
799 buildbot_common.BuildStep('Sync naclports')
800 if not os.path.exists(NACLPORTS_DIR):
801 # checkout new copy of naclports
802 cmd = ['svn', 'checkout', '-q', '-r', str(NACLPORTS_REV), NACLPORTS_URL,
804 buildbot_common.Run(cmd, cwd=os.path.dirname(NACLPORTS_DIR))
806 # sync existing copy to pinned revision.
807 cmd = ['svn', 'update', '-r', str(NACLPORTS_REV)]
808 buildbot_common.Run(cmd, cwd=NACLPORTS_DIR)
811 def BuildStepBuildNaClPorts(pepper_ver, pepperdir):
812 """Build selected naclports in all configurations."""
813 # TODO(sbc): currently naclports doesn't know anything about
814 # Debug builds so the Debug subfolders are all empty.
816 env = dict(os.environ)
817 env['NACL_SDK_ROOT'] = pepperdir
818 env['PEPPER_DIR'] = os.path.basename(pepperdir) # pepper_NN
819 env['NACLPORTS_NO_ANNOTATE'] = "1"
820 env['NACLPORTS_NO_UPLOAD'] = "1"
821 env['BUILDBOT_GOT_REVISION'] = str(NACLPORTS_REV)
823 build_script = 'build_tools/buildbot_sdk_bundle.sh'
824 buildbot_common.BuildStep('Build naclports')
826 bundle_dir = os.path.join(NACLPORTS_DIR, 'out', 'sdk_bundle')
827 out_dir = os.path.join(bundle_dir, 'pepper_%s' % pepper_ver)
829 # Remove the sdk_bundle directory to remove stale files from previous builds.
830 buildbot_common.RemoveDir(bundle_dir)
832 buildbot_common.Run([build_script], env=env, cwd=NACLPORTS_DIR)
834 # Some naclports do not include a standalone LICENSE/COPYING file
835 # so we explicitly list those here for inclusion.
836 extra_licenses = ('tinyxml/readme.txt',
839 src_root = os.path.join(NACLPORTS_DIR, 'out', 'build')
840 output_license = os.path.join(out_dir, 'ports', 'LICENSE')
841 GenerateNotice(src_root , output_license, extra_licenses)
842 readme = os.path.join(out_dir, 'ports', 'README')
843 oshelpers.Copy(['-v', os.path.join(SDK_SRC_DIR, 'README.naclports'), readme])
846 def BuildStepTarNaClPorts(pepper_ver, tarfile):
847 """Create tar archive containing headers and libs from naclports build."""
848 buildbot_common.BuildStep('Tar naclports Bundle')
849 buildbot_common.MakeDir(os.path.dirname(tarfile))
850 pepper_dir = 'pepper_%s' % pepper_ver
851 archive_dirs = [os.path.join(pepper_dir, 'ports')]
853 ports_out = os.path.join(NACLPORTS_DIR, 'out', 'sdk_bundle')
854 cmd = [sys.executable, CYGTAR, '-C', ports_out, '-cjf', tarfile]
856 buildbot_common.Run(cmd, cwd=NACL_DIR)
859 def BuildStepBuildAppEngine(pepperdir, chrome_revision):
860 """Build the projects found in src/gonacl_appengine/src"""
861 buildbot_common.BuildStep('Build GoNaCl AppEngine Projects')
862 cmd = ['make', 'upload', 'REVISION=%s' % chrome_revision]
863 env = dict(os.environ)
864 env['NACL_SDK_ROOT'] = pepperdir
865 env['NACLPORTS_NO_ANNOTATE'] = "1"
866 buildbot_common.Run(cmd, env=env, cwd=GONACL_APPENGINE_SRC_DIR)
870 parser = optparse.OptionParser(description=__doc__)
871 parser.add_option('--nacl-tree-path',
872 help='Path to native client tree for bionic build.',
873 dest='nacl_tree_path')
874 parser.add_option('--qemu', help='Add qemu for ARM.',
876 parser.add_option('--bionic', help='Add bionic build.',
878 parser.add_option('--tar', help='Force the tar step.',
880 parser.add_option('--archive', help='Force the archive step.',
882 parser.add_option('--release', help='PPAPI release version.',
883 dest='release', default=None)
884 parser.add_option('--build-ports',
885 help='Build naclport bundle.', action='store_true')
886 parser.add_option('--build-app-engine',
887 help='Build AppEngine demos.', action='store_true')
888 parser.add_option('--experimental',
889 help='build experimental examples and libraries', action='store_true',
890 dest='build_experimental')
891 parser.add_option('--skip-toolchain', help='Skip toolchain untar',
893 parser.add_option('--mac-sdk',
894 help='Set the mac-sdk (e.g. 10.6) to use when building with ninja.')
895 parser.add_option('--no-arm-trusted', action='store_true',
896 help='Disable building of ARM trusted components (sel_ldr, etc).')
898 # To setup bash completion for this command first install optcomplete
899 # and then add this line to your .bashrc:
900 # complete -F _optcomplete build_sdk.py
903 optcomplete.autocomplete(parser)
908 options, args = parser.parse_args(args[1:])
910 parser.error("Unexpected arguments: %s" % str(args))
912 if options.nacl_tree_path:
913 options.bionic = True
914 toolchain_build = os.path.join(options.nacl_tree_path, 'toolchain_build')
915 print 'WARNING: Building bionic toolchain from NaCl checkout.'
916 print 'This option builds bionic from the sources currently in the'
917 print 'provided NativeClient checkout, and the results instead of '
918 print 'downloading a toolchain from the builder. This may result in a'
919 print 'NaCl SDK that can not run on ToT chrome.'
920 print 'NOTE: To clobber you will need to run toolchain_build_bionic.py'
921 print 'directly from the NativeClient checkout.'
923 response = raw_input("Type 'y' and hit enter to continue.\n")
924 if response != 'y' and response != 'Y':
928 # Get head version of NativeClient tree
929 buildbot_common.BuildStep('Build bionic toolchain.')
930 buildbot_common.Run([sys.executable, 'toolchain_build_bionic.py', '-f'],
933 toolchain_build = None
935 if buildbot_common.IsSDKBuilder():
936 options.archive = True
937 options.build_ports = True
938 options.build_app_engine = True
941 toolchains = ['newlib', 'glibc', 'arm', 'pnacl', 'host']
943 # Changes for experimental bionic builder
945 toolchains.append('bionic')
946 options.build_ports = False
947 options.build_app_engine = False
949 print 'Building: ' + ' '.join(toolchains)
951 if options.archive and not options.tar:
952 parser.error('Incompatible arguments with archive.')
954 chrome_version = int(build_version.ChromeMajorVersion())
955 chrome_revision = build_version.ChromeRevision()
956 nacl_revision = build_version.NaClRevision()
957 pepper_ver = str(chrome_version)
958 pepper_old = str(chrome_version - 1)
959 pepperdir = os.path.join(OUT_DIR, 'pepper_' + pepper_ver)
960 pepperdir_old = os.path.join(OUT_DIR, 'pepper_' + pepper_old)
962 tarname = 'naclsdk_bionic.tar.bz2'
964 tarname = 'naclsdk_' + getos.GetPlatform() + '.tar.bz2'
965 tarfile = os.path.join(OUT_DIR, tarname)
968 pepper_ver = options.release
969 print 'Building PEPPER %s at %s' % (pepper_ver, chrome_revision)
971 if 'NACL_SDK_ROOT' in os.environ:
972 # We don't want the currently configured NACL_SDK_ROOT to have any effect
974 del os.environ['NACL_SDK_ROOT']
976 if not options.skip_toolchain:
977 BuildStepCleanPepperDirs(pepperdir, pepperdir_old)
978 BuildStepMakePepperDirs(pepperdir, ['include', 'toolchain', 'tools'])
979 BuildStepDownloadToolchains(toolchains)
980 if options.nacl_tree_path:
981 # Instead of untarring, copy the raw bionic toolchain
982 not_bionic = [i for i in toolchains if i != 'bionic']
983 BuildStepUntarToolchains(pepperdir, not_bionic)
984 tcname = GetToolchainDirName('bionic', 'arm')
985 srcdir = os.path.join(toolchain_build, 'out', tcname)
986 bionicdir = os.path.join(pepperdir, 'toolchain', tcname)
987 oshelpers.Copy(['-r', srcdir, bionicdir])
989 BuildStepUntarToolchains(pepperdir, toolchains)
991 BuildStepBuildToolchains(pepperdir, toolchains)
993 BuildStepUpdateHelpers(pepperdir, True)
994 BuildStepUpdateUserProjects(pepperdir, toolchains,
995 options.build_experimental, True)
997 BuildStepCopyTextFiles(pepperdir, pepper_ver, chrome_revision, nacl_revision)
999 # Ship with libraries prebuilt, so run that first.
1000 BuildStepBuildLibraries(pepperdir, 'src')
1001 GenerateNotice(pepperdir)
1003 # Verify the SDK contains what we expect.
1004 if not options.bionic:
1005 BuildStepVerifyFilelist(pepperdir)
1008 BuildStepTarBundle(pepper_ver, tarfile)
1010 if options.build_ports and getos.GetPlatform() == 'linux':
1011 ports_tarfile = os.path.join(OUT_DIR, 'naclports.tar.bz2')
1012 BuildStepSyncNaClPorts()
1013 BuildStepBuildNaClPorts(pepper_ver, pepperdir)
1015 BuildStepTarNaClPorts(pepper_ver, ports_tarfile)
1017 if options.build_app_engine and getos.GetPlatform() == 'linux':
1018 BuildStepBuildAppEngine(pepperdir, chrome_revision)
1021 qemudir = os.path.join(NACL_DIR, 'toolchain', 'linux_arm-trusted')
1022 oshelpers.Copy(['-r', qemudir, pepperdir])
1024 # Archive on non-trybots.
1026 BuildStepArchiveBundle('build', pepper_ver, chrome_revision, nacl_revision,
1028 if options.build_ports and getos.GetPlatform() == 'linux':
1029 BuildStepArchiveBundle('naclports', pepper_ver, chrome_revision,
1030 nacl_revision, ports_tarfile)
1031 BuildStepArchiveSDKTools()
1036 if __name__ == '__main__':
1038 sys.exit(main(sys.argv))
1039 except KeyboardInterrupt:
1040 buildbot_common.ErrorExit('build_sdk: interrupted')