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('${NACL_REVISION}', nacl_revision
)
187 # Year/Month/Day Hour:Minute:Second
188 time_format
= '%Y/%m/%d %H:%M:%S'
189 readme_text
= readme_text
.replace('${DATE}',
190 datetime
.datetime
.now().strftime(time_format
))
192 open(os
.path
.join(pepperdir
, 'README'), 'w').write(readme_text
)
195 def BuildStepUntarToolchains(pepperdir
, toolchains
):
196 buildbot_common
.BuildStep('Untar Toolchains')
197 platform
= getos
.GetPlatform()
198 build_platform
= '%s_x86' % platform
199 tmpdir
= os
.path
.join(OUT_DIR
, 'tc_temp')
200 buildbot_common
.RemoveDir(tmpdir
)
201 buildbot_common
.MakeDir(tmpdir
)
203 # Create a list of extract packages tuples, the first part should be
204 # "$PACKAGE_TARGET/$PACKAGE". The second part should be the destination
205 # directory relative to pepperdir/toolchain.
206 extract_packages
= []
207 for toolchain
in toolchains
:
208 toolchain_map
= TOOLCHAIN_PACKAGE_MAP
.get(toolchain
, None)
210 package_name
, tcname
= toolchain_map
211 package_tuple
= (os
.path
.join(build_platform
, package_name
),
212 tcname
% {'platform': platform
})
213 extract_packages
.append(package_tuple
)
216 # Extract all of the packages into the temp directory.
217 package_names
= [package_tuple
[0] for package_tuple
in extract_packages
]
218 buildbot_common
.Run([sys
.executable
, PKGVER
,
219 '--packages', ','.join(package_names
),
220 '--tar-dir', NACL_TOOLCHAINTARS_DIR
,
221 '--dest-dir', tmpdir
,
224 # Move all the packages we extracted to the correct destination.
225 for package_name
, dest_dir
in extract_packages
:
226 full_src_dir
= os
.path
.join(tmpdir
, package_name
)
227 full_dst_dir
= os
.path
.join(pepperdir
, 'toolchain', dest_dir
)
228 buildbot_common
.Move(full_src_dir
, full_dst_dir
)
230 # Cleanup the temporary directory we are no longer using.
231 buildbot_common
.RemoveDir(tmpdir
)
234 # List of toolchain headers to install.
235 # Source is relative to top of Chromium tree, destination is relative
236 # to the toolchain header directory.
239 ('native_client/src/include/nacl/nacl_exception.h', 'nacl/'),
240 ('native_client/src/include/nacl/nacl_minidump.h', 'nacl/'),
241 ('native_client/src/untrusted/irt/irt.h', ''),
242 ('native_client/src/untrusted/irt/irt_dev.h', ''),
243 ('native_client/src/untrusted/nacl/nacl_dyncode.h', 'nacl/'),
244 ('native_client/src/untrusted/nacl/nacl_startup.h', 'nacl/'),
245 ('native_client/src/untrusted/pthread/pthread.h', ''),
246 ('native_client/src/untrusted/pthread/semaphore.h', ''),
247 ('native_client/src/untrusted/valgrind/dynamic_annotations.h', 'nacl/'),
248 ('ppapi/nacl_irt/public/irt_ppapi.h', ''),
251 ('native_client/src/include/nacl/nacl_exception.h', 'nacl/'),
252 ('native_client/src/include/nacl/nacl_minidump.h', 'nacl/'),
253 ('native_client/src/untrusted/irt/irt.h', ''),
254 ('native_client/src/untrusted/irt/irt_dev.h', ''),
255 ('native_client/src/untrusted/nacl/nacl_dyncode.h', 'nacl/'),
256 ('native_client/src/untrusted/nacl/nacl_startup.h', 'nacl/'),
257 ('native_client/src/untrusted/valgrind/dynamic_annotations.h', 'nacl/'),
258 ('ppapi/nacl_irt/public/irt_ppapi.h', ''),
263 def InstallFiles(src_root
, dest_root
, file_list
):
264 """Copy a set of files from src_root to dest_root according
265 to the given mapping. This allows files to be copied from
266 to a location in the destination tree that is different to the
267 location in the source tree.
269 If the destination mapping ends with a '/' then the destination
270 basename is inherited from the the source file.
272 Wildcards can be used in the source list but it is not recommended
273 as this can end up adding things to the SDK unintentionally.
275 for file_spec
in file_list
:
276 # The list of files to install can be a simple list of
277 # strings or a list of pairs, where each pair corresponds
278 # to a mapping from source to destination names.
279 if type(file_spec
) == str:
280 src_file
= dest_file
= file_spec
282 src_file
, dest_file
= file_spec
284 src_file
= os
.path
.join(src_root
, src_file
)
286 # Expand sources files using glob.
287 sources
= glob
.glob(src_file
)
291 if len(sources
) > 1 and not dest_file
.endswith('/'):
292 buildbot_common
.ErrorExit("Target file must end in '/' when "
293 "using globbing to install multiple files")
295 for source
in sources
:
296 if dest_file
.endswith('/'):
297 dest
= os
.path
.join(dest_file
, os
.path
.basename(source
))
300 dest
= os
.path
.join(dest_root
, dest
)
301 if not os
.path
.isdir(os
.path
.dirname(dest
)):
302 buildbot_common
.MakeDir(os
.path
.dirname(dest
))
303 buildbot_common
.CopyFile(source
, dest
)
306 def InstallNaClHeaders(tc_dst_inc
, tc_name
):
307 """Copies NaCl headers to expected locations in the toolchain."""
309 # arm toolchain header should be the same as the x86 newlib
313 InstallFiles(SRC_DIR
, tc_dst_inc
, NACL_HEADER_MAP
[tc_name
])
316 def MakeNinjaRelPath(path
):
317 return os
.path
.join(os
.path
.relpath(OUT_DIR
, SRC_DIR
), path
)
322 'libminidump_generator.a',
324 'libnacl_exception.a',
325 'libnacl_list_mappings.a',
331 'libminidump_generator.a',
334 'libnacl_exception.a',
335 'libnacl_list_mappings.a',
342 'libminidump_generator.a',
343 'libminidump_generator.so',
346 'libnacl_dyncode.so',
347 'libnacl_exception.a',
348 'libnacl_exception.so',
349 'libnacl_list_mappings.a',
350 'libnacl_list_mappings.so',
356 'libminidump_generator.a',
359 'libnacl_exception.a',
360 'libnacl_list_mappings.a',
369 def GypNinjaInstall(pepperdir
, toolchains
):
370 build_dir
= GYPBUILD_DIR
371 ninja_out_dir
= os
.path
.join(OUT_DIR
, build_dir
, 'Release')
373 ['sel_ldr', 'sel_ldr_x86_32'],
374 ['ncval_new', 'ncval'],
375 ['irt_core_newlib_x32.nexe', 'irt_core_x86_32.nexe'],
376 ['irt_core_newlib_x64.nexe', 'irt_core_x86_64.nexe'],
379 platform
= getos
.GetPlatform()
381 # TODO(binji): dump_syms doesn't currently build on Windows. See
382 # http://crbug.com/245456
383 if platform
!= 'win':
385 ['dump_syms', 'dump_syms'],
386 ['minidump_dump', 'minidump_dump'],
387 ['minidump_stackwalk', 'minidump_stackwalk']
390 tools_files
.append(['sel_ldr64', 'sel_ldr_x86_64'])
392 if platform
== 'linux':
393 tools_files
.append(['nacl_helper_bootstrap',
394 'nacl_helper_bootstrap_x86_32'])
395 tools_files
.append(['nacl_helper_bootstrap64',
396 'nacl_helper_bootstrap_x86_64'])
398 buildbot_common
.MakeDir(os
.path
.join(pepperdir
, 'tools'))
400 # Add .exe extensions to all windows tools
401 for pair
in tools_files
:
402 if platform
== 'win' and not pair
[0].endswith('.nexe'):
406 InstallFiles(ninja_out_dir
, os
.path
.join(pepperdir
, 'tools'), tools_files
)
409 if platform
== 'linux' and not options
.no_arm_trusted
:
411 ['irt_core_newlib_arm.nexe', 'irt_core_arm.nexe'],
412 ['irt_core_newlib_arm.nexe', 'irt_core_arm.nexe'],
413 ['sel_ldr', 'sel_ldr_arm'],
414 ['nacl_helper_bootstrap', 'nacl_helper_bootstrap_arm']
416 ninja_out_dir
= os
.path
.join(OUT_DIR
, build_dir
+ '-arm', 'Release')
417 InstallFiles(ninja_out_dir
, os
.path
.join(pepperdir
, 'tools'), tools_files
)
419 for tc
in set(toolchains
) & set(['newlib', 'glibc', 'pnacl']):
423 xarches
= ('arm', '32', '64')
425 for xarch
in xarches
:
426 if tc
== 'glibc' and xarch
== 'arm':
429 src_dir
= GetGypBuiltLib(tc
, xarch
)
430 dst_dir
= GetOutputToolchainLib(pepperdir
, tc
, xarch
)
431 InstallFiles(src_dir
, dst_dir
, TOOLCHAIN_LIBS
[tc
])
433 # Copy ARM newlib components to bionic
434 if tc
== 'newlib' and xarch
== 'arm' and 'bionic' in toolchains
:
435 bionic_dir
= GetOutputToolchainLib(pepperdir
, 'bionic', xarch
)
436 InstallFiles(src_dir
, bionic_dir
, TOOLCHAIN_LIBS
['bionic'])
439 src_dir
= GetGypToolchainLib(tc
, xarch
)
440 InstallFiles(src_dir
, dst_dir
, ['crt1.o'])
443 def GypNinjaBuild_NaCl(rel_out_dir
):
444 gyp_py
= os
.path
.join(NACL_DIR
, 'build', 'gyp_nacl')
445 nacl_core_sdk_gyp
= os
.path
.join(NACL_DIR
, 'build', 'nacl_core_sdk.gyp')
446 all_gyp
= os
.path
.join(NACL_DIR
, 'build', 'all.gyp')
448 out_dir
= MakeNinjaRelPath(rel_out_dir
)
449 out_dir_arm
= MakeNinjaRelPath(rel_out_dir
+ '-arm')
450 GypNinjaBuild('ia32', gyp_py
, nacl_core_sdk_gyp
, 'nacl_core_sdk', out_dir
)
451 GypNinjaBuild('arm', gyp_py
, nacl_core_sdk_gyp
, 'nacl_core_sdk', out_dir_arm
)
452 GypNinjaBuild('ia32', gyp_py
, all_gyp
, 'ncval_new', out_dir
)
454 platform
= getos
.GetPlatform()
455 if platform
== 'win':
456 NinjaBuild('sel_ldr64', out_dir
)
458 out_dir_64
= MakeNinjaRelPath(rel_out_dir
+ '-64')
459 GypNinjaBuild('x64', gyp_py
, nacl_core_sdk_gyp
, 'sel_ldr', out_dir_64
)
461 # We only need sel_ldr from the 64-bit out directory.
462 # sel_ldr needs to be renamed, so we'll call it sel_ldr64.
463 files_to_copy
= [('sel_ldr', 'sel_ldr64')]
464 if platform
== 'linux':
465 files_to_copy
.append(('nacl_helper_bootstrap', 'nacl_helper_bootstrap64'))
467 for src
, dst
in files_to_copy
:
468 buildbot_common
.CopyFile(
469 os
.path
.join(SRC_DIR
, out_dir_64
, 'Release', src
),
470 os
.path
.join(SRC_DIR
, out_dir
, 'Release', dst
))
473 def GypNinjaBuild_Breakpad(rel_out_dir
):
474 # TODO(binji): dump_syms doesn't currently build on Windows. See
475 # http://crbug.com/245456
476 if getos
.GetPlatform() == 'win':
479 gyp_py
= os
.path
.join(SRC_DIR
, 'build', 'gyp_chromium')
480 out_dir
= MakeNinjaRelPath(rel_out_dir
)
481 gyp_file
= os
.path
.join(SRC_DIR
, 'breakpad', 'breakpad.gyp')
482 build_list
= ['dump_syms', 'minidump_dump', 'minidump_stackwalk']
483 GypNinjaBuild('ia32', gyp_py
, gyp_file
, build_list
, out_dir
)
486 def GypNinjaBuild_PPAPI(arch
, rel_out_dir
):
487 gyp_py
= os
.path
.join(SRC_DIR
, 'build', 'gyp_chromium')
488 out_dir
= MakeNinjaRelPath(rel_out_dir
)
489 gyp_file
= os
.path
.join(SRC_DIR
, 'ppapi', 'native_client',
491 GypNinjaBuild(arch
, gyp_py
, gyp_file
, 'ppapi_lib', out_dir
)
494 def GypNinjaBuild_Pnacl(rel_out_dir
, target_arch
):
495 # TODO(binji): This will build the pnacl_irt_shim twice; once as part of the
496 # Chromium build, and once here. When we move more of the SDK build process
497 # to gyp, we can remove this.
498 gyp_py
= os
.path
.join(SRC_DIR
, 'build', 'gyp_chromium')
500 out_dir
= MakeNinjaRelPath(rel_out_dir
)
501 gyp_file
= os
.path
.join(SRC_DIR
, 'ppapi', 'native_client', 'src',
502 'untrusted', 'pnacl_irt_shim', 'pnacl_irt_shim.gyp')
504 GypNinjaBuild(target_arch
, gyp_py
, gyp_file
, targets
, out_dir
, False)
507 def GypNinjaBuild(arch
, gyp_py_script
, gyp_file
, targets
,
508 out_dir
, force_arm_gcc
=True):
509 gyp_env
= dict(os
.environ
)
510 gyp_env
['GYP_GENERATORS'] = 'ninja'
513 gyp_defines
.append('mac_sdk=%s' % options
.mac_sdk
)
515 gyp_defines
.append('target_arch=%s' % arch
)
517 if getos
.GetPlatform() == 'linux':
518 gyp_env
['CC'] = 'arm-linux-gnueabihf-gcc'
519 gyp_env
['CXX'] = 'arm-linux-gnueabihf-g++'
520 gyp_env
['AR'] = 'arm-linux-gnueabihf-ar'
521 gyp_env
['AS'] = 'arm-linux-gnueabihf-as'
522 gyp_env
['CC_host'] = 'cc'
523 gyp_env
['CXX_host'] = 'c++'
524 gyp_defines
+= ['armv7=1', 'arm_thumb=0', 'arm_neon=1',
525 'arm_float_abi=hard']
527 gyp_defines
.append('nacl_enable_arm_gcc=1')
528 if options
.no_arm_trusted
:
529 gyp_defines
.append('disable_cross_trusted=1')
530 if getos
.GetPlatform() == 'mac':
531 gyp_defines
.append('clang=1')
533 gyp_env
['GYP_DEFINES'] = ' '.join(gyp_defines
)
534 for key
in ['GYP_GENERATORS', 'GYP_DEFINES', 'CC']:
535 value
= gyp_env
.get(key
)
536 if value
is not None:
537 print '%s="%s"' % (key
, value
)
538 gyp_generator_flags
= ['-G', 'output_dir=%s' % (out_dir
,)]
539 gyp_depth
= '--depth=.'
541 [sys
.executable
, gyp_py_script
, gyp_file
, gyp_depth
] + \
545 NinjaBuild(targets
, out_dir
)
548 def NinjaBuild(targets
, out_dir
):
549 if type(targets
) is not list:
551 out_config_dir
= os
.path
.join(out_dir
, 'Release')
552 buildbot_common
.Run(['ninja', '-C', out_config_dir
] + targets
, cwd
=SRC_DIR
)
555 def BuildStepBuildToolchains(pepperdir
, toolchains
):
556 buildbot_common
.BuildStep('SDK Items')
558 GypNinjaBuild_NaCl(GYPBUILD_DIR
)
559 GypNinjaBuild_Breakpad(GYPBUILD_DIR
)
561 platform
= getos
.GetPlatform()
562 newlibdir
= os
.path
.join(pepperdir
, 'toolchain', platform
+ '_x86_newlib')
563 glibcdir
= os
.path
.join(pepperdir
, 'toolchain', platform
+ '_x86_glibc')
564 armdir
= os
.path
.join(pepperdir
, 'toolchain', platform
+ '_arm_newlib')
565 pnacldir
= os
.path
.join(pepperdir
, 'toolchain', platform
+ '_pnacl')
567 if set(toolchains
) & set(['glibc', 'newlib']):
568 GypNinjaBuild_PPAPI('ia32', GYPBUILD_DIR
)
570 if 'arm' in toolchains
:
571 GypNinjaBuild_PPAPI('arm', GYPBUILD_DIR
+ '-arm')
573 GypNinjaInstall(pepperdir
, toolchains
)
575 if 'newlib' in toolchains
:
576 InstallNaClHeaders(GetToolchainNaClInclude('newlib', newlibdir
, 'x86'),
579 if 'glibc' in toolchains
:
580 InstallNaClHeaders(GetToolchainNaClInclude('glibc', glibcdir
, 'x86'),
583 if 'arm' in toolchains
:
584 InstallNaClHeaders(GetToolchainNaClInclude('newlib', armdir
, 'arm'),
587 if 'pnacl' in toolchains
:
588 # NOTE: For ia32, gyp builds both x86-32 and x86-64 by default.
589 for arch
in ('ia32', 'arm'):
590 # Fill in the latest native pnacl shim library from the chrome build.
591 build_dir
= GYPBUILD_DIR
+ '-pnacl-' + arch
592 GypNinjaBuild_Pnacl(build_dir
, arch
)
594 nacl_arches
= ['x86-32', 'x86-64']
596 nacl_arches
= ['arm']
598 buildbot_common
.ErrorExit('Unknown architecture: %s' % arch
)
599 for nacl_arch
in nacl_arches
:
600 release_build_dir
= os
.path
.join(OUT_DIR
, build_dir
, 'Release',
601 'gen', 'tc_pnacl_translate',
604 buildbot_common
.CopyFile(
605 os
.path
.join(release_build_dir
, 'libpnacl_irt_shim.a'),
606 GetPNaClNativeLib(pnacldir
, nacl_arch
))
608 InstallNaClHeaders(GetToolchainNaClInclude('pnacl', pnacldir
, 'x86'),
612 def MakeDirectoryOrClobber(pepperdir
, dirname
, clobber
):
613 dirpath
= os
.path
.join(pepperdir
, dirname
)
615 buildbot_common
.RemoveDir(dirpath
)
616 buildbot_common
.MakeDir(dirpath
)
621 def BuildStepUpdateHelpers(pepperdir
, clobber
):
622 buildbot_common
.BuildStep('Update project helpers')
623 build_projects
.UpdateHelpers(pepperdir
, clobber
=clobber
)
626 def BuildStepUpdateUserProjects(pepperdir
, toolchains
,
627 build_experimental
, clobber
):
628 buildbot_common
.BuildStep('Update examples and libraries')
631 if not build_experimental
:
632 filters
['EXPERIMENTAL'] = False
634 toolchains
= toolchains
[:]
636 # arm isn't a valid toolchain for build_projects
637 if 'arm' in toolchains
:
638 toolchains
.remove('arm')
640 if 'host' in toolchains
:
641 toolchains
.remove('host')
642 toolchains
.append(getos
.GetPlatform())
644 filters
['TOOLS'] = toolchains
646 # Update examples and libraries
655 tree
= parse_dsc
.LoadProjectTree(SDK_SRC_DIR
, include
=filters
)
656 build_projects
.UpdateProjects(pepperdir
, tree
, clobber
=clobber
,
657 toolchains
=toolchains
)
660 def BuildStepMakeAll(pepperdir
, directory
, step_name
,
661 deps
=True, clean
=False, config
='Debug', args
=None):
662 buildbot_common
.BuildStep(step_name
)
663 build_projects
.BuildProjectsBranch(pepperdir
, directory
, clean
,
667 def BuildStepBuildLibraries(pepperdir
, directory
):
668 BuildStepMakeAll(pepperdir
, directory
, 'Build Libraries Debug',
669 clean
=True, config
='Debug')
670 BuildStepMakeAll(pepperdir
, directory
, 'Build Libraries Release',
671 clean
=True, config
='Release')
673 # Cleanup .pyc file generated while building libraries. Without
674 # this we would end up shipping the pyc in the SDK tarball.
675 buildbot_common
.RemoveFile(os
.path
.join(pepperdir
, 'tools', '*.pyc'))
678 def GenerateNotice(fileroot
, output_filename
='NOTICE', extra_files
=None):
679 # Look for LICENSE files
680 license_filenames_re
= re
.compile('LICENSE|COPYING|COPYRIGHT')
683 for root
, _
, files
in os
.walk(fileroot
):
684 for filename
in files
:
685 if license_filenames_re
.match(filename
):
686 path
= os
.path
.join(root
, filename
)
687 license_files
.append(path
)
690 license_files
+= [os
.path
.join(fileroot
, f
) for f
in extra_files
]
691 print '\n'.join(license_files
)
693 if not os
.path
.isabs(output_filename
):
694 output_filename
= os
.path
.join(fileroot
, output_filename
)
695 generate_notice
.Generate(output_filename
, fileroot
, license_files
)
698 def BuildStepVerifyFilelist(pepperdir
):
699 buildbot_common
.BuildStep('Verify SDK Files')
700 file_list_path
= os
.path
.join(SCRIPT_DIR
, 'sdk_files.list')
702 verify_filelist
.Verify(file_list_path
, pepperdir
)
704 except verify_filelist
.ParseException
, e
:
705 buildbot_common
.ErrorExit('Parsing sdk_files.list failed:\n\n%s' % e
)
706 except verify_filelist
.VerifyException
, e
:
707 file_list_rel
= os
.path
.relpath(file_list_path
)
708 verify_filelist_py
= os
.path
.splitext(verify_filelist
.__file
__)[0] + '.py'
709 verify_filelist_py
= os
.path
.relpath(verify_filelist_py
)
710 pepperdir_rel
= os
.path
.relpath(pepperdir
)
713 SDK verification failed:
716 Add/remove files from %s to fix.
720 to test.""" % (e
, file_list_rel
, verify_filelist_py
, file_list_rel
,
722 buildbot_common
.ErrorExit(msg
)
725 def BuildStepTarBundle(pepper_ver
, tarfile
):
726 buildbot_common
.BuildStep('Tar Pepper Bundle')
727 buildbot_common
.MakeDir(os
.path
.dirname(tarfile
))
728 buildbot_common
.Run([sys
.executable
, CYGTAR
, '-C', OUT_DIR
, '-cjf', tarfile
,
729 'pepper_' + pepper_ver
], cwd
=NACL_DIR
)
732 def GetManifestBundle(pepper_ver
, chrome_revision
, nacl_revision
, tarfile
,
734 with
open(tarfile
, 'rb') as tarfile_stream
:
735 archive_sha1
, archive_size
= manifest_util
.DownloadAndComputeHash(
738 archive
= manifest_util
.Archive(manifest_util
.GetHostOS())
739 archive
.url
= archive_url
740 archive
.size
= archive_size
741 archive
.checksum
= archive_sha1
743 bundle
= manifest_util
.Bundle('pepper_' + pepper_ver
)
744 bundle
.revision
= int(chrome_revision
)
745 bundle
.repath
= 'pepper_' + pepper_ver
746 bundle
.version
= int(pepper_ver
)
747 bundle
.description
= (
748 'Chrome %s bundle. Chrome revision: %s. NaCl revision: %s' % (
749 pepper_ver
, chrome_revision
, nacl_revision
))
750 bundle
.stability
= 'dev'
751 bundle
.recommended
= 'no'
752 bundle
.archives
= [archive
]
756 def BuildStepArchiveBundle(name
, pepper_ver
, chrome_revision
, nacl_revision
,
758 buildbot_common
.BuildStep('Archive %s' % name
)
759 bucket_path
= 'nativeclient-mirror/nacl/nacl_sdk/%s' % (
760 build_version
.ChromeVersion(),)
761 tarname
= os
.path
.basename(tarfile
)
762 tarfile_dir
= os
.path
.dirname(tarfile
)
763 buildbot_common
.Archive(tarname
, bucket_path
, tarfile_dir
)
765 # generate "manifest snippet" for this archive.
766 archive_url
= GSTORE
+ 'nacl_sdk/%s/%s' % (
767 build_version
.ChromeVersion(), tarname
)
768 bundle
= GetManifestBundle(pepper_ver
, chrome_revision
, nacl_revision
,
769 tarfile
, archive_url
)
771 manifest_snippet_file
= os
.path
.join(OUT_DIR
, tarname
+ '.json')
772 with
open(manifest_snippet_file
, 'wb') as manifest_snippet_stream
:
773 manifest_snippet_stream
.write(bundle
.GetDataAsString())
775 buildbot_common
.Archive(tarname
+ '.json', bucket_path
, OUT_DIR
,
779 def BuildStepArchiveSDKTools():
780 # Only push up sdk_tools.tgz and nacl_sdk.zip on the linux buildbot.
781 builder_name
= os
.getenv('BUILDBOT_BUILDERNAME', '')
782 if builder_name
== 'linux-sdk-multi':
783 buildbot_common
.BuildStep('Build SDK Tools')
784 build_updater
.BuildUpdater(OUT_DIR
)
786 buildbot_common
.BuildStep('Archive SDK Tools')
787 bucket_path
= 'nativeclient-mirror/nacl/nacl_sdk/%s' % (
788 build_version
.ChromeVersion(),)
789 buildbot_common
.Archive('sdk_tools.tgz', bucket_path
, OUT_DIR
,
791 buildbot_common
.Archive('nacl_sdk.zip', bucket_path
, OUT_DIR
,
795 def BuildStepSyncNaClPorts():
796 """Pull the pinned revision of naclports from SVN."""
797 buildbot_common
.BuildStep('Sync naclports')
798 if not os
.path
.exists(NACLPORTS_DIR
):
799 # checkout new copy of naclports
800 cmd
= ['svn', 'checkout', '-q', '-r', str(NACLPORTS_REV
), NACLPORTS_URL
,
802 buildbot_common
.Run(cmd
, cwd
=os
.path
.dirname(NACLPORTS_DIR
))
804 # sync existing copy to pinned revision.
805 cmd
= ['svn', 'update', '-r', str(NACLPORTS_REV
)]
806 buildbot_common
.Run(cmd
, cwd
=NACLPORTS_DIR
)
809 def BuildStepBuildNaClPorts(pepper_ver
, pepperdir
):
810 """Build selected naclports in all configurations."""
811 # TODO(sbc): currently naclports doesn't know anything about
812 # Debug builds so the Debug subfolders are all empty.
814 env
= dict(os
.environ
)
815 env
['NACL_SDK_ROOT'] = pepperdir
816 env
['PEPPER_DIR'] = os
.path
.basename(pepperdir
) # pepper_NN
817 env
['NACLPORTS_NO_ANNOTATE'] = "1"
818 env
['NACLPORTS_NO_UPLOAD'] = "1"
819 env
['BUILDBOT_GOT_REVISION'] = str(NACLPORTS_REV
)
821 build_script
= 'build_tools/buildbot_sdk_bundle.sh'
822 buildbot_common
.BuildStep('Build naclports')
824 bundle_dir
= os
.path
.join(NACLPORTS_DIR
, 'out', 'sdk_bundle')
825 out_dir
= os
.path
.join(bundle_dir
, 'pepper_%s' % pepper_ver
)
827 # Remove the sdk_bundle directory to remove stale files from previous builds.
828 buildbot_common
.RemoveDir(bundle_dir
)
830 buildbot_common
.Run([build_script
], env
=env
, cwd
=NACLPORTS_DIR
)
832 # Some naclports do not include a standalone LICENSE/COPYING file
833 # so we explicitly list those here for inclusion.
834 extra_licenses
= ('tinyxml/readme.txt',
837 src_root
= os
.path
.join(NACLPORTS_DIR
, 'out', 'build')
838 output_license
= os
.path
.join(out_dir
, 'ports', 'LICENSE')
839 GenerateNotice(src_root
, output_license
, extra_licenses
)
840 readme
= os
.path
.join(out_dir
, 'ports', 'README')
841 oshelpers
.Copy(['-v', os
.path
.join(SDK_SRC_DIR
, 'README.naclports'), readme
])
844 def BuildStepTarNaClPorts(pepper_ver
, tarfile
):
845 """Create tar archive containing headers and libs from naclports build."""
846 buildbot_common
.BuildStep('Tar naclports Bundle')
847 buildbot_common
.MakeDir(os
.path
.dirname(tarfile
))
848 pepper_dir
= 'pepper_%s' % pepper_ver
849 archive_dirs
= [os
.path
.join(pepper_dir
, 'ports')]
851 ports_out
= os
.path
.join(NACLPORTS_DIR
, 'out', 'sdk_bundle')
852 cmd
= [sys
.executable
, CYGTAR
, '-C', ports_out
, '-cjf', tarfile
]
854 buildbot_common
.Run(cmd
, cwd
=NACL_DIR
)
857 def BuildStepBuildAppEngine(pepperdir
, chrome_revision
):
858 """Build the projects found in src/gonacl_appengine/src"""
859 buildbot_common
.BuildStep('Build GoNaCl AppEngine Projects')
860 cmd
= ['make', 'upload', 'REVISION=%s' % chrome_revision
]
861 env
= dict(os
.environ
)
862 env
['NACL_SDK_ROOT'] = pepperdir
863 env
['NACLPORTS_NO_ANNOTATE'] = "1"
864 buildbot_common
.Run(cmd
, env
=env
, cwd
=GONACL_APPENGINE_SRC_DIR
)
868 parser
= optparse
.OptionParser(description
=__doc__
)
869 parser
.add_option('--nacl-tree-path',
870 help='Path to native client tree for bionic build.',
871 dest
='nacl_tree_path')
872 parser
.add_option('--qemu', help='Add qemu for ARM.',
874 parser
.add_option('--bionic', help='Add bionic build.',
876 parser
.add_option('--tar', help='Force the tar step.',
878 parser
.add_option('--archive', help='Force the archive step.',
880 parser
.add_option('--release', help='PPAPI release version.',
881 dest
='release', default
=None)
882 parser
.add_option('--build-ports',
883 help='Build naclport bundle.', action
='store_true')
884 parser
.add_option('--build-app-engine',
885 help='Build AppEngine demos.', action
='store_true')
886 parser
.add_option('--experimental',
887 help='build experimental examples and libraries', action
='store_true',
888 dest
='build_experimental')
889 parser
.add_option('--skip-toolchain', help='Skip toolchain untar',
891 parser
.add_option('--mac-sdk',
892 help='Set the mac-sdk (e.g. 10.6) to use when building with ninja.')
893 parser
.add_option('--no-arm-trusted', action
='store_true',
894 help='Disable building of ARM trusted components (sel_ldr, etc).')
896 # To setup bash completion for this command first install optcomplete
897 # and then add this line to your .bashrc:
898 # complete -F _optcomplete build_sdk.py
901 optcomplete
.autocomplete(parser
)
906 options
, args
= parser
.parse_args(args
[1:])
908 parser
.error("Unexpected arguments: %s" % str(args
))
910 if options
.nacl_tree_path
:
911 options
.bionic
= True
912 toolchain_build
= os
.path
.join(options
.nacl_tree_path
, 'toolchain_build')
913 print 'WARNING: Building bionic toolchain from NaCl checkout.'
914 print 'This option builds bionic from the sources currently in the'
915 print 'provided NativeClient checkout, and the results instead of '
916 print 'downloading a toolchain from the builder. This may result in a'
917 print 'NaCl SDK that can not run on ToT chrome.'
918 print 'NOTE: To clobber you will need to run toolchain_build_bionic.py'
919 print 'directly from the NativeClient checkout.'
921 response
= raw_input("Type 'y' and hit enter to continue.\n")
922 if response
!= 'y' and response
!= 'Y':
926 # Get head version of NativeClient tree
927 buildbot_common
.BuildStep('Build bionic toolchain.')
928 buildbot_common
.Run([sys
.executable
, 'toolchain_build_bionic.py', '-f'],
931 toolchain_build
= None
933 if buildbot_common
.IsSDKBuilder():
934 options
.archive
= True
935 options
.build_ports
= True
936 options
.build_app_engine
= True
939 toolchains
= ['newlib', 'glibc', 'arm', 'pnacl', 'host']
941 # Changes for experimental bionic builder
943 toolchains
.append('bionic')
944 options
.build_ports
= False
945 options
.build_app_engine
= False
947 print 'Building: ' + ' '.join(toolchains
)
949 if options
.archive
and not options
.tar
:
950 parser
.error('Incompatible arguments with archive.')
952 chrome_version
= int(build_version
.ChromeMajorVersion())
953 chrome_revision
= build_version
.ChromeRevision()
954 nacl_revision
= build_version
.NaClRevision()
955 pepper_ver
= str(chrome_version
)
956 pepper_old
= str(chrome_version
- 1)
957 pepperdir
= os
.path
.join(OUT_DIR
, 'pepper_' + pepper_ver
)
958 pepperdir_old
= os
.path
.join(OUT_DIR
, 'pepper_' + pepper_old
)
960 tarname
= 'naclsdk_bionic.tar.bz2'
962 tarname
= 'naclsdk_' + getos
.GetPlatform() + '.tar.bz2'
963 tarfile
= os
.path
.join(OUT_DIR
, tarname
)
966 pepper_ver
= options
.release
967 print 'Building PEPPER %s at %s' % (pepper_ver
, chrome_revision
)
969 if 'NACL_SDK_ROOT' in os
.environ
:
970 # We don't want the currently configured NACL_SDK_ROOT to have any effect
972 del os
.environ
['NACL_SDK_ROOT']
974 if not options
.skip_toolchain
:
975 BuildStepCleanPepperDirs(pepperdir
, pepperdir_old
)
976 BuildStepMakePepperDirs(pepperdir
, ['include', 'toolchain', 'tools'])
977 BuildStepDownloadToolchains(toolchains
)
978 if options
.nacl_tree_path
:
979 # Instead of untarring, copy the raw bionic toolchain
980 not_bionic
= [i
for i
in toolchains
if i
!= 'bionic']
981 BuildStepUntarToolchains(pepperdir
, not_bionic
)
982 tcname
= GetToolchainDirName('bionic', 'arm')
983 srcdir
= os
.path
.join(toolchain_build
, 'out', tcname
)
984 bionicdir
= os
.path
.join(pepperdir
, 'toolchain', tcname
)
985 oshelpers
.Copy(['-r', srcdir
, bionicdir
])
987 BuildStepUntarToolchains(pepperdir
, toolchains
)
989 BuildStepBuildToolchains(pepperdir
, toolchains
)
991 BuildStepUpdateHelpers(pepperdir
, True)
992 BuildStepUpdateUserProjects(pepperdir
, toolchains
,
993 options
.build_experimental
, True)
995 BuildStepCopyTextFiles(pepperdir
, pepper_ver
, chrome_revision
, nacl_revision
)
997 # Ship with libraries prebuilt, so run that first.
998 BuildStepBuildLibraries(pepperdir
, 'src')
999 GenerateNotice(pepperdir
)
1001 # Verify the SDK contains what we expect.
1002 if not options
.bionic
:
1003 BuildStepVerifyFilelist(pepperdir
)
1006 BuildStepTarBundle(pepper_ver
, tarfile
)
1008 if options
.build_ports
and getos
.GetPlatform() == 'linux':
1009 ports_tarfile
= os
.path
.join(OUT_DIR
, 'naclports.tar.bz2')
1010 BuildStepSyncNaClPorts()
1011 BuildStepBuildNaClPorts(pepper_ver
, pepperdir
)
1013 BuildStepTarNaClPorts(pepper_ver
, ports_tarfile
)
1015 if options
.build_app_engine
and getos
.GetPlatform() == 'linux':
1016 BuildStepBuildAppEngine(pepperdir
, chrome_revision
)
1019 qemudir
= os
.path
.join(NACL_DIR
, 'toolchain', 'linux_arm-trusted')
1020 oshelpers
.Copy(['-r', qemudir
, pepperdir
])
1022 # Archive on non-trybots.
1024 BuildStepArchiveBundle('build', pepper_ver
, chrome_revision
, nacl_revision
,
1026 if options
.build_ports
and getos
.GetPlatform() == 'linux':
1027 BuildStepArchiveBundle('naclports', pepper_ver
, chrome_revision
,
1028 nacl_revision
, ports_tarfile
)
1029 BuildStepArchiveSDKTools()
1034 if __name__
== '__main__':
1036 sys
.exit(main(sys
.argv
))
1037 except KeyboardInterrupt:
1038 buildbot_common
.ErrorExit('build_sdk: interrupted')