Supervised user whitelists: Cleanup
[chromium-blink-merge.git] / tools / gn / bootstrap / bootstrap.py
blob91cec029fde38afea3515d2d503633d2a9587b62
1 #!/usr/bin/env python
2 # Copyright 2014 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 """Bootstraps gn.
8 It is done by first building it manually in a temporary directory, then building
9 it with its own BUILD.gn to the final destination.
10 """
12 import contextlib
13 import errno
14 import logging
15 import optparse
16 import os
17 import shutil
18 import subprocess
19 import sys
20 import tempfile
22 BOOTSTRAP_DIR = os.path.dirname(os.path.abspath(__file__))
23 GN_ROOT = os.path.dirname(BOOTSTRAP_DIR)
24 SRC_ROOT = os.path.dirname(os.path.dirname(GN_ROOT))
26 is_linux = sys.platform.startswith('linux')
27 is_mac = sys.platform.startswith('darwin')
28 is_posix = is_linux or is_mac
30 def check_call(cmd, **kwargs):
31 logging.debug('Running: %s', ' '.join(cmd))
32 subprocess.check_call(cmd, cwd=GN_ROOT, **kwargs)
34 def mkdir_p(path):
35 try:
36 os.makedirs(path)
37 except OSError as e:
38 if e.errno == errno.EEXIST and os.path.isdir(path):
39 pass
40 else: raise
42 @contextlib.contextmanager
43 def scoped_tempdir():
44 path = tempfile.mkdtemp()
45 try:
46 yield path
47 finally:
48 shutil.rmtree(path)
51 def main(argv):
52 parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
53 parser.add_option('-d', '--debug', action='store_true',
54 help='Do a debug build. Defaults to release build.')
55 parser.add_option('-o', '--output',
56 help='place output in PATH', metavar='PATH')
57 parser.add_option('-s', '--no-rebuild', action='store_true',
58 help='Do not rebuild GN with GN.')
59 parser.add_option('-v', '--verbose', action='store_true',
60 help='Log more details')
61 options, args = parser.parse_args(argv)
63 if args:
64 parser.error('Unrecognized command line arguments: %s.' % ', '.join(args))
66 logging.basicConfig(level=logging.DEBUG if options.verbose else logging.ERROR)
68 if options.debug:
69 build_rel = os.path.join('out', 'Debug')
70 else:
71 build_rel = os.path.join('out', 'Release')
72 build_root = os.path.join(SRC_ROOT, build_rel)
74 try:
75 with scoped_tempdir() as tempdir:
76 print 'Building gn manually in a temporary directory for bootstrapping...'
77 build_gn_with_ninja_manually(tempdir, options)
78 temp_gn = os.path.join(tempdir, 'gn')
79 out_gn = os.path.join(build_root, 'gn')
81 if options.no_rebuild:
82 mkdir_p(build_root)
83 shutil.copy2(temp_gn, out_gn)
84 else:
85 print 'Building gn using itself to %s...' % build_rel
86 build_gn_with_gn(temp_gn, build_rel, options)
88 if options.output:
89 # Preserve the executable permission bit.
90 shutil.copy2(out_gn, options.output)
91 except subprocess.CalledProcessError as e:
92 print >> sys.stderr, str(e)
93 return 1
94 return 0
97 def build_gn_with_ninja_manually(tempdir, options):
98 write_ninja(os.path.join(tempdir, 'build.ninja'), options)
99 cmd = ['ninja', '-C', tempdir]
100 if options.verbose:
101 cmd.append('-v')
102 cmd.append('gn')
103 check_call(cmd)
105 def write_ninja(path, options):
106 cc = os.environ.get('CC', '')
107 cxx = os.environ.get('CXX', '')
108 cflags = os.environ.get('CFLAGS', '').split()
109 cflags_cc = os.environ.get('CXXFLAGS', '').split()
110 ld = os.environ.get('LD', cxx)
111 ldflags = os.environ.get('LDFLAGS', '').split()
112 include_dirs = [SRC_ROOT]
113 libs = []
115 if is_posix:
116 if options.debug:
117 cflags.extend(['-O0', '-g'])
118 else:
119 cflags.extend(['-O2', '-g0'])
121 cflags.extend(['-D_FILE_OFFSET_BITS=64', '-pthread', '-pipe'])
122 cflags_cc.extend(['-std=gnu++11', '-Wno-c++11-narrowing'])
124 static_libraries = {
125 'base': {'sources': [], 'tool': 'cxx'},
126 'dynamic_annotations': {'sources': [], 'tool': 'cc'},
127 'gn': {'sources': [], 'tool': 'cxx'},
130 for name in os.listdir(GN_ROOT):
131 if not name.endswith('.cc'):
132 continue
133 if name.endswith('_unittest.cc'):
134 continue
135 if name in ['generate_test_gn_data.cc', 'run_all_unittests.cc']:
136 continue
137 full_path = os.path.join(GN_ROOT, name)
138 static_libraries['gn']['sources'].append(
139 os.path.relpath(full_path, SRC_ROOT))
141 static_libraries['dynamic_annotations']['sources'].extend([
142 'base/third_party/dynamic_annotations/dynamic_annotations.c',
144 static_libraries['base']['sources'].extend([
145 'base/at_exit.cc',
146 'base/atomicops_internals_x86_gcc.cc',
147 'base/base_paths.cc',
148 'base/base_switches.cc',
149 'base/callback_internal.cc',
150 'base/command_line.cc',
151 'base/debug/alias.cc',
152 'base/debug/stack_trace.cc',
153 'base/debug/task_annotator.cc',
154 'base/environment.cc',
155 'base/files/file.cc',
156 'base/files/file_enumerator.cc',
157 'base/files/file_path.cc',
158 'base/files/file_path_constants.cc',
159 'base/files/file_util.cc',
160 'base/files/scoped_file.cc',
161 'base/json/json_parser.cc',
162 'base/json/json_reader.cc',
163 'base/json/json_string_value_serializer.cc',
164 'base/json/json_writer.cc',
165 'base/json/string_escape.cc',
166 'base/lazy_instance.cc',
167 'base/location.cc',
168 'base/logging.cc',
169 'base/memory/ref_counted.cc',
170 'base/memory/ref_counted_memory.cc',
171 'base/memory/singleton.cc',
172 'base/memory/weak_ptr.cc',
173 'base/message_loop/incoming_task_queue.cc',
174 'base/message_loop/message_loop.cc',
175 'base/message_loop/message_loop_proxy.cc',
176 'base/message_loop/message_loop_proxy_impl.cc',
177 'base/message_loop/message_pump.cc',
178 'base/message_loop/message_pump_default.cc',
179 'base/metrics/bucket_ranges.cc',
180 'base/metrics/histogram.cc',
181 'base/metrics/histogram_base.cc',
182 'base/metrics/histogram_samples.cc',
183 'base/metrics/sample_map.cc',
184 'base/metrics/sample_vector.cc',
185 'base/metrics/sparse_histogram.cc',
186 'base/metrics/statistics_recorder.cc',
187 'base/path_service.cc',
188 'base/pending_task.cc',
189 'base/pickle.cc',
190 'base/process/kill.cc',
191 'base/process/process_iterator.cc',
192 'base/process/process_metrics.cc',
193 'base/profiler/alternate_timer.cc',
194 'base/profiler/tracked_time.cc',
195 'base/run_loop.cc',
196 'base/sequence_checker_impl.cc',
197 'base/sequenced_task_runner.cc',
198 'base/strings/string16.cc',
199 'base/strings/string_number_conversions.cc',
200 'base/strings/string_piece.cc',
201 'base/strings/string_split.cc',
202 'base/strings/string_util.cc',
203 'base/strings/string_util_constants.cc',
204 'base/strings/stringprintf.cc',
205 'base/strings/utf_string_conversion_utils.cc',
206 'base/strings/utf_string_conversions.cc',
207 'base/synchronization/cancellation_flag.cc',
208 'base/synchronization/lock.cc',
209 'base/sys_info.cc',
210 'base/task_runner.cc',
211 'base/third_party/dmg_fp/dtoa_wrapper.cc',
212 'base/third_party/dmg_fp/g_fmt.cc',
213 'base/third_party/icu/icu_utf.cc',
214 'base/third_party/nspr/prtime.cc',
215 'base/thread_task_runner_handle.cc',
216 'base/threading/non_thread_safe_impl.cc',
217 'base/threading/post_task_and_reply_impl.cc',
218 'base/threading/sequenced_worker_pool.cc',
219 'base/threading/simple_thread.cc',
220 'base/threading/thread_checker_impl.cc',
221 'base/threading/thread_collision_warner.cc',
222 'base/threading/thread_id_name_manager.cc',
223 'base/threading/thread_local_storage.cc',
224 'base/threading/thread_restrictions.cc',
225 'base/time/time.cc',
226 'base/timer/elapsed_timer.cc',
227 'base/timer/timer.cc',
228 'base/trace_event/trace_event_impl.cc',
229 'base/trace_event/trace_event_impl_constants.cc',
230 'base/trace_event/trace_event_memory.cc',
231 'base/trace_event/trace_event_synthetic_delay.cc',
232 'base/tracked_objects.cc',
233 'base/tracking_info.cc',
234 'base/values.cc',
235 'base/vlog.cc',
238 if is_posix:
239 static_libraries['base']['sources'].extend([
240 'base/base_paths_posix.cc',
241 'base/debug/debugger_posix.cc',
242 'base/debug/stack_trace_posix.cc',
243 'base/files/file_enumerator_posix.cc',
244 'base/files/file_posix.cc',
245 'base/files/file_util_posix.cc',
246 'base/message_loop/message_pump_libevent.cc',
247 'base/posix/file_descriptor_shuffle.cc',
248 'base/process/kill_posix.cc',
249 'base/process/process_handle_posix.cc',
250 'base/process/process_metrics_posix.cc',
251 'base/process/process_posix.cc',
252 'base/safe_strerror_posix.cc',
253 'base/synchronization/condition_variable_posix.cc',
254 'base/synchronization/lock_impl_posix.cc',
255 'base/synchronization/waitable_event_posix.cc',
256 'base/sys_info_posix.cc',
257 'base/threading/platform_thread_posix.cc',
258 'base/threading/thread_local_posix.cc',
259 'base/threading/thread_local_storage_posix.cc',
260 'base/time/time_posix.cc',
262 static_libraries['libevent'] = {
263 'sources': [
264 'third_party/libevent/buffer.c',
265 'third_party/libevent/evbuffer.c',
266 'third_party/libevent/evdns.c',
267 'third_party/libevent/event.c',
268 'third_party/libevent/event_tagging.c',
269 'third_party/libevent/evrpc.c',
270 'third_party/libevent/evutil.c',
271 'third_party/libevent/http.c',
272 'third_party/libevent/log.c',
273 'third_party/libevent/poll.c',
274 'third_party/libevent/select.c',
275 'third_party/libevent/signal.c',
276 'third_party/libevent/strlcpy.c',
278 'tool': 'cc',
279 'include_dirs': [],
280 'cflags': cflags + ['-DHAVE_CONFIG_H'],
284 if is_linux:
285 libs.extend(['-lrt'])
286 ldflags.extend(['-pthread'])
288 static_libraries['xdg_user_dirs'] = {
289 'sources': [
290 'base/third_party/xdg_user_dirs/xdg_user_dir_lookup.cc',
292 'tool': 'cxx',
294 static_libraries['base']['sources'].extend([
295 'base/nix/xdg_util.cc',
296 'base/process/internal_linux.cc',
297 'base/process/process_handle_linux.cc',
298 'base/process/process_iterator_linux.cc',
299 'base/process/process_linux.cc',
300 'base/process/process_metrics_linux.cc',
301 'base/strings/sys_string_conversions_posix.cc',
302 'base/sys_info_linux.cc',
303 'base/threading/platform_thread_linux.cc',
305 static_libraries['libevent']['include_dirs'].extend([
306 os.path.join(SRC_ROOT, 'third_party', 'libevent', 'linux')
308 static_libraries['libevent']['sources'].extend([
309 'third_party/libevent/epoll.c',
313 if is_mac:
314 static_libraries['base']['sources'].extend([
315 'base/base_paths_mac.mm',
316 'base/files/file_util_mac.mm',
317 'base/mac/bundle_locations.mm',
318 'base/mac/foundation_util.mm',
319 'base/mac/mach_logging.cc',
320 'base/mac/scoped_mach_port.cc',
321 'base/mac/scoped_nsautorelease_pool.mm',
322 'base/message_loop/message_pump_mac.mm',
323 'base/process/process_handle_mac.cc',
324 'base/process/process_iterator_mac.cc',
325 'base/strings/sys_string_conversions_mac.mm',
326 'base/time/time_mac.cc',
327 'base/threading/platform_thread_mac.mm',
329 static_libraries['libevent']['include_dirs'].extend([
330 os.path.join(SRC_ROOT, 'third_party', 'libevent', 'mac')
332 static_libraries['libevent']['sources'].extend([
333 'third_party/libevent/kqueue.c',
337 if is_mac:
338 template_filename = 'build_mac.ninja.template'
339 else:
340 template_filename = 'build.ninja.template'
342 with open(os.path.join(GN_ROOT, 'bootstrap', template_filename)) as f:
343 ninja_template = f.read()
345 def src_to_obj(path):
346 return '%s' % os.path.splitext(path)[0] + '.o'
348 ninja_lines = []
349 for library, settings in static_libraries.iteritems():
350 for src_file in settings['sources']:
351 ninja_lines.extend([
352 'build %s: %s %s' % (src_to_obj(src_file),
353 settings['tool'],
354 os.path.join(SRC_ROOT, src_file)),
355 ' includes = %s' % ' '.join(
356 ['-I' + dirname for dirname in
357 include_dirs + settings.get('include_dirs', [])]),
358 ' cflags = %s' % ' '.join(cflags + settings.get('cflags', [])),
359 ' cflags_cc = %s' %
360 ' '.join(cflags_cc + settings.get('cflags_cc', [])),
362 if cc:
363 ninja_lines.append(' cc = %s' % cc)
364 if cxx:
365 ninja_lines.append(' cxx = %s' % cxx)
367 ninja_lines.append('build %s.a: alink_thin %s' % (
368 library,
369 ' '.join([src_to_obj(src_file) for src_file in settings['sources']])))
371 if is_mac:
372 libs.extend([
373 '-framework', 'AppKit',
374 '-framework', 'CoreFoundation',
375 '-framework', 'Foundation',
376 '-framework', 'Security',
379 ninja_lines.extend([
380 'build gn: link %s' % (
381 ' '.join(['%s.a' % library for library in static_libraries])),
382 ' ldflags = %s' % ' '.join(ldflags),
383 ' libs = %s' % ' '.join(libs),
385 if ld:
386 ninja_lines.append(' ld = %s' % ld)
387 else:
388 ninja_lines.append(' ld = $ldxx')
390 ninja_lines.append('') # Make sure the file ends with a newline.
392 with open(path, 'w') as f:
393 f.write(ninja_template + '\n'.join(ninja_lines))
396 def build_gn_with_gn(temp_gn, build_dir, options):
397 cmd = [temp_gn, 'gen', build_dir]
398 if not options.debug:
399 cmd.append('--args=is_debug=false')
400 check_call(cmd)
402 cmd = ['ninja', '-C', build_dir]
403 if options.verbose:
404 cmd.append('-v')
405 cmd.append('gn')
406 check_call(cmd)
408 if not options.debug:
409 check_call(['strip', os.path.join(build_dir, 'gn')])
412 if __name__ == '__main__':
413 sys.exit(main(sys.argv[1:]))