1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#!/usr/bin/env python 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Copyright (c) 2013 The Chromium Authors. All rights reserved. 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# found in the LICENSE file. 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 6558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochimport json 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import optparse 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import os 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import re 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import sys 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)if sys.version_info < (2, 6, 0): 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sys.stderr.write("python 2.6 or later is required run this script\n") 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sys.exit(1) 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import buildbot_common 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import build_projects 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)import build_version 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import easy_template 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import parse_dsc 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)from build_paths import SDK_SRC_DIR, OUT_DIR, SDK_RESOURCE_DIR 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)sys.path.append(os.path.join(SDK_SRC_DIR, 'tools')) 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import getos 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import oshelpers 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def RemoveBuildCruft(outdir): 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for root, _, files in os.walk(outdir): 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for f in files: 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) path = os.path.join(root, f) 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ext = os.path.splitext(path)[1] 341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) # Remove unwanted files from the package. Also remove manifest.json files 351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) # (which we usually want). These ones are the manifests of the invidual 361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) # examples, though, which CWS complains about. The master manifest.json 371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) # is generated after we call RemoveBuildCruft. 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (ext in ('.d', '.o') or 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) f == 'dir.stamp' or 401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) f == 'manifest.json' or 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) re.search(r'_unstripped_.*?\.nexe', f)): 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buildbot_common.RemoveFile(path) 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def StripNexes(outdir, platform, pepperdir): 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for root, _, files in os.walk(outdir): 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for f in files: 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) path = os.path.join(root, f) 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) m = re.search(r'lib(32|64).*\.so', path) 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) arch = None 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if m: 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # System .so file. Must be x86, because ARM doesn't support glibc yet. 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) arch = 'x86_' + m.group(1) 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else: 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) basename, ext = os.path.splitext(f) 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if ext in ('.nexe', '.so'): 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # We can get the arch from the filename... 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) valid_arches = ('x86_64', 'x86_32', 'arm') 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for a in valid_arches: 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if basename.endswith(a): 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) arch = a 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) break 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if not arch: 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) continue 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) strip = GetStrip(pepperdir, platform, arch, 'newlib') 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buildbot_common.Run([strip, path]) 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def GetStrip(pepperdir, platform, arch, toolchain): 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base_arch = {'x86_32': 'x86', 'x86_64': 'x86', 'arm': 'arm'}[arch] 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bin_dir = os.path.join(pepperdir, 'toolchain', 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) '%s_%s_%s' % (platform, base_arch, toolchain), 'bin') 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) strip_prefix = {'x86_32': 'i686', 'x86_64': 'x86_64', 'arm': 'arm'}[arch] 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) strip_name = '%s-nacl-strip' % strip_prefix 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return os.path.join(bin_dir, strip_name) 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def main(args): 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) parser = optparse.OptionParser() 811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parser.add_option('-c', '--channel', 821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) help='Channel to display in the name of the package.') 830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) # To setup bash completion for this command first install optcomplete 850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) # and then add this line to your .bashrc: 860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) # complete -F _optcomplete build_app.py 870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) try: 880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) import optcomplete 890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) optcomplete.autocomplete(parser) 900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) except ImportError: 910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) pass 920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) options, args = parser.parse_args(args[1:]) 941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if options.channel: 961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if options.channel not in ('Dev', 'Beta'): 971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) parser.error('Unknown channel: %s' % options.channel) 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) toolchains = ['newlib', 'glibc'] 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) pepper_ver = str(int(build_version.ChromeMajorVersion())) 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pepperdir = os.path.join(OUT_DIR, 'pepper_' + pepper_ver) 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) app_dir = os.path.join(OUT_DIR, 'naclsdk_app') 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) app_examples_dir = os.path.join(app_dir, 'examples') 10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) sdk_resources_dir = SDK_RESOURCE_DIR 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) platform = getos.GetPlatform() 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buildbot_common.RemoveDir(app_dir) 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buildbot_common.MakeDir(app_dir) 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # Add some dummy directories so build_projects doesn't complain... 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buildbot_common.MakeDir(os.path.join(app_dir, 'tools')) 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buildbot_common.MakeDir(os.path.join(app_dir, 'toolchain')) 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) config = 'Release' 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) filters = {} 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) filters['DISABLE_PACKAGE'] = False 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) filters['EXPERIMENTAL'] = False 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) filters['TOOLS'] = toolchains 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) filters['DEST'] = ['examples/api', 'examples/getting_started', 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 'examples/demo', 'examples/tutorial'] 123ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch tree = parse_dsc.LoadProjectTree(SDK_SRC_DIR, include=filters) 124558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch build_projects.UpdateHelpers(app_dir, clobber=True) 125558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch build_projects.UpdateProjects(app_dir, tree, clobber=False, 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) toolchains=toolchains, configs=[config], 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) first_toolchain=True) 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) # Collect permissions from each example, and aggregate them. 130558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch def MergeLists(list1, list2): 131558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return list1 + [x for x in list2 if x not in list1] 13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) all_permissions = [] 133558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch all_socket_permissions = [] 13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) for _, project in parse_dsc.GenerateProjects(tree): 135558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch permissions = project.get('PERMISSIONS', []) 136558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch all_permissions = MergeLists(all_permissions, permissions) 137558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch socket_permissions = project.get('SOCKET_PERMISSIONS', []) 138558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch all_socket_permissions = MergeLists(all_socket_permissions, 139558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch socket_permissions) 140558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if all_socket_permissions: 141558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch all_permissions.append({'socket': all_socket_permissions}) 142558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch pretty_permissions = json.dumps(all_permissions, sort_keys=True, indent=4) 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for filename in ['background.js', 'icon128.png']: 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) buildbot_common.CopyFile(os.path.join(sdk_resources_dir, filename), 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) os.path.join(app_examples_dir, filename)) 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) os.environ['NACL_SDK_ROOT'] = pepperdir 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) build_projects.BuildProjects(app_dir, tree, deps=False, clean=False, 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) config=config) 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) RemoveBuildCruft(app_dir) 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) StripNexes(app_dir, platform, pepperdir) 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) # Add manifest.json after RemoveBuildCruft... that function removes the 1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) # manifest.json files for the individual examples. 1581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) name = 'Native Client SDK' 1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if options.channel: 1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) name += ' (%s)' % options.channel 1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) template_dict = { 1621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 'name': name, 1631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 'channel': options.channel, 1641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 'description': 1651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 'Native Client SDK examples, showing API use and key concepts.', 1661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 'key': False, # manifests with "key" are rejected when uploading to CWS. 1671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 'permissions': pretty_permissions, 1681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 'version': build_version.ChromeVersionNoTrunk() 1691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) easy_template.RunTemplateFile( 1711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) os.path.join(sdk_resources_dir, 'manifest.json.template'), 1721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) os.path.join(app_examples_dir, 'manifest.json'), 1731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) template_dict) 1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) app_zip = os.path.join(app_dir, 'examples.zip') 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) os.chdir(app_examples_dir) 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) oshelpers.Zip([app_zip, '-r', '*']) 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return 0 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)if __name__ == '__main__': 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sys.exit(main(sys.argv)) 184