| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/python | |
| 2 # Copyright (c) 2011 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. | |
| 5 | |
| 6 import optparse | |
| 7 import os | |
| 8 import re | |
| 9 import shutil | |
| 10 import subprocess | |
| 11 import sys | |
| 12 | |
| 13 | |
| 14 # Where things are in relation to this script. | |
| 15 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) | |
| 16 SRC_DIR = os.path.dirname(SCRIPT_DIR) | |
| 17 NACL_DIR = os.path.join(SRC_DIR, 'native_client') | |
| 18 | |
| 19 # Pathing to the two command_buffer directories (relative to native_client). | |
| 20 NACL_CMD_BUFFER_DIR = os.path.join('src', 'shared', | |
| 21 'ppapi_proxy', 'command_buffer') | |
| 22 GPU_CMD_BUFFER_DIR = os.path.join('..', 'gpu', 'command_buffer') | |
| 23 | |
| 24 | |
| 25 def RelativePath(path, base): | |
| 26 """Find the relative path. | |
| 27 | |
| 28 Arguments: | |
| 29 path: path we want a relative path to. | |
| 30 base: path we want a relative path from. | |
| 31 Returns: | |
| 32 The relative path from base to path. | |
| 33 """ | |
| 34 path = os.path.abspath(path) | |
| 35 base = os.path.abspath(base) | |
| 36 path_parts = path.split(os.sep) | |
| 37 base_parts = base.split(os.sep) | |
| 38 while path_parts and base_parts and path_parts[0] == base_parts[0]: | |
| 39 path_parts = path_parts[1:] | |
| 40 base_parts = base_parts[1:] | |
| 41 rel_parts = ['..'] * len(base_parts) + path_parts | |
| 42 return os.sep.join(rel_parts) | |
| 43 | |
| 44 | |
| 45 def PrintInputs(platforms): | |
| 46 """Print all the transitive inputs required to build the IRT. | |
| 47 | |
| 48 Arguments: | |
| 49 platforms: list of platform names to build for. | |
| 50 """ | |
| 51 inputs = set() | |
| 52 for platform in platforms: | |
| 53 # Invoke scons to get dependency tree. | |
| 54 cmd = [ | |
| 55 sys.executable, 'scons.py', '-n', '--tree=all', | |
| 56 '--mode=nacl', 'platform=' + platform, | |
| 57 'scons-out/nacl_irt-' + platform + '/staging/irt.nexe', | |
| 58 ] | |
| 59 p = subprocess.Popen(cmd, cwd=NACL_DIR, | |
| 60 stdout=subprocess.PIPE, | |
| 61 stderr=subprocess.PIPE) | |
| 62 (p_stdout, p_stderr) = p.communicate() | |
| 63 # If things fail on windows, try running --help, if that fails, | |
| 64 # emit this script as an input (to satiate gyp), and assume we're being | |
| 65 # run on a test only bot. | |
| 66 # TODO(bradnelson): add plumbing to the buildbots to allow this script | |
| 67 # to know its on a test only bot + make scons return a _particular_ | |
| 68 # return code so we can detect this kind of fail in one step. | |
| 69 if p.returncode != 0 and sys.platform == 'win32': | |
| 70 cmd = [sys.executable, 'scons.py', '--help'] | |
| 71 p = subprocess.Popen(cmd, cwd=NACL_DIR, | |
| 72 stdout=subprocess.PIPE, | |
| 73 stderr=subprocess.PIPE) | |
| 74 (p_stdout, p_stderr) = p.communicate() | |
| 75 if p.returncode !=0: | |
| 76 # If scons can't even run, emit just this script as an input. | |
| 77 # See comment above this one. | |
| 78 print RelativePath(__file__, SCRIPT_DIR).replace(os.sep, '/') | |
| 79 return | |
| 80 if p.returncode != 0: | |
| 81 sys.exit(2) | |
| 82 # Extract unique inputs. | |
| 83 for line in p_stdout.splitlines(): | |
| 84 m = re.match('^[ -+|]*\+\-(.+)', line) | |
| 85 if not m: | |
| 86 continue | |
| 87 filename = m.group(1) | |
| 88 if '[' in filename: | |
| 89 continue | |
| 90 if filename.startswith('scons-out'): | |
| 91 continue | |
| 92 if filename.endswith('.nexe'): | |
| 93 continue | |
| 94 # Apply the underlay of gpu/command_buffer (to match scons). | |
| 95 if filename.startswith(NACL_CMD_BUFFER_DIR + os.sep): | |
| 96 filename = GPU_CMD_BUFFER_DIR + filename[len(NACL_CMD_BUFFER_DIR):] | |
| 97 inputs.add(filename) | |
| 98 # Check that everything exists and make it script relative. | |
| 99 # Exclude things above SRC_DIR. | |
| 100 rel_inputs = set() | |
| 101 for f in inputs: | |
| 102 nf = os.path.join(NACL_DIR, f) | |
| 103 if not os.path.exists(nf): | |
| 104 raise Exception('missing input file "%s"' % nf) | |
| 105 # If the relative path from SRC_DIR to the file starts with ../ ignore it. | |
| 106 # (i.e. the file is outside the client). | |
| 107 if RelativePath(nf, SRC_DIR).startswith('..' + os.sep): | |
| 108 continue | |
| 109 rel_inputs.add(RelativePath(nf, SCRIPT_DIR).replace(os.sep, '/')) | |
| 110 # Print it sorted. | |
| 111 rel_inputs = sorted(list(rel_inputs)) | |
| 112 for f in rel_inputs: | |
| 113 print f | |
| 114 | |
| 115 | |
| 116 def BuildIRT(platforms, out_dir): | |
| 117 """Build the IRT for several platforms. | |
| 118 | |
| 119 Arguments: | |
| 120 platforms: list of platform names to build for. | |
| 121 out_dir: directory to output the IRT to. | |
| 122 """ | |
| 123 # Make out_dir absolute. | |
| 124 out_dir = os.path.abspath(out_dir) | |
| 125 # Clean. | |
| 126 scons_out = os.path.join(NACL_DIR, 'scons-out') | |
| 127 if os.path.exists(scons_out): | |
| 128 shutil.rmtree(scons_out) | |
| 129 # Build for each platform. | |
| 130 for platform in platforms: | |
| 131 cmd = [ | |
| 132 sys.executable, 'scons.py', '--verbose', '-j8', | |
| 133 '--mode=nacl', 'platform=' + platform, | |
| 134 'scons-out/nacl_irt-' + platform + '/staging/irt.nexe', | |
| 135 ] | |
| 136 print 'Running: ' + ' '.join(cmd) | |
| 137 # Work around the fact that python's readline module (used by scons), | |
| 138 # attempts to alter file handle state on stdin in a way that blocks if | |
| 139 # a process is not a member of a foreground job on a tty on OSX. | |
| 140 # e.g. On a Mac: | |
| 141 # | |
| 142 # hydric:test mseaborn$ python -c 'import readline' & | |
| 143 # [1] 67058 | |
| 144 # hydric:test mseaborn$ | |
| 145 # [1]+ Stopped python -c 'import readline' | |
| 146 # | |
| 147 # i.e. the process receives a stop signal when it's a background job. | |
| 148 if sys.platform == 'darwin': | |
| 149 devnull = open(os.devnull, 'r') | |
| 150 else: | |
| 151 devnull = None | |
| 152 p = subprocess.Popen(cmd, cwd=NACL_DIR, stdin=devnull) | |
| 153 p.wait() | |
| 154 if p.returncode != 0: | |
| 155 sys.exit(3) | |
| 156 # Copy out each platform after stripping. | |
| 157 for platform in platforms: | |
| 158 uplatform = platform.replace('-', '_') | |
| 159 platform2 = {'x86-32': 'i686', 'x86-64': 'x86_64'}.get(platform, platform) | |
| 160 cplatform = { | |
| 161 'win32': 'win', | |
| 162 'cygwin': 'win', | |
| 163 'darwin': 'mac', | |
| 164 }.get(sys.platform, 'linux') | |
| 165 nexe = os.path.join(out_dir, 'nacl_irt_' + uplatform + '.nexe') | |
| 166 cmd = [ | |
| 167 '../native_client/toolchain/' + cplatform + '_x86_newlib/bin/' + | |
| 168 platform2 + '-nacl-strip', | |
| 169 '--strip-debug', | |
| 170 '../native_client/scons-out/nacl_irt-' + platform + '/staging/irt.nexe', | |
| 171 '-o', nexe | |
| 172 ] | |
| 173 print 'Running: ' + ' '.join(cmd) | |
| 174 p = subprocess.Popen(cmd, cwd=SCRIPT_DIR) | |
| 175 p.wait() | |
| 176 if p.returncode != 0: | |
| 177 sys.exit(4) | |
| 178 | |
| 179 | |
| 180 def Main(argv): | |
| 181 parser = optparse.OptionParser() | |
| 182 parser.add_option('--inputs', dest='inputs', default=False, | |
| 183 action='store_true', | |
| 184 help='only emit the transitive inputs to the irt build') | |
| 185 parser.add_option('--platform', dest='platforms', action='append', | |
| 186 default=[], | |
| 187 help='add a platform to build for (x86-32|x86-64)') | |
| 188 parser.add_option('--outdir', dest='outdir', | |
| 189 help='directory to out irt to') | |
| 190 (options, args) = parser.parse_args(argv[1:]) | |
| 191 if args or not options.platforms or ( | |
| 192 not options.inputs and not options.outdir): | |
| 193 parser.print_help() | |
| 194 sys.exit(1) | |
| 195 | |
| 196 if options.inputs: | |
| 197 PrintInputs(options.platforms) | |
| 198 else: | |
| 199 BuildIRT(options.platforms, options.outdir) | |
| 200 | |
| 201 | |
| 202 if __name__ == '__main__': | |
| 203 Main(sys.argv) | |
| OLD | NEW |