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