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.
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.
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
)
38 if e
.errno
== errno
.EEXIST
and os
.path
.isdir(path
):
42 @contextlib.contextmanager
44 path
= tempfile
.mkdtemp()
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
)
64 parser
.error('Unrecognized command line arguments: %s.' % ', '.join(args
))
66 logging
.basicConfig(level
=logging
.DEBUG
if options
.verbose
else logging
.ERROR
)
69 build_rel
= os
.path
.join('out', 'Debug')
71 build_rel
= os
.path
.join('out', 'Release')
72 build_root
= os
.path
.join(SRC_ROOT
, build_rel
)
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
:
83 shutil
.copy2(temp_gn
, out_gn
)
85 print 'Building gn using itself to %s...' % build_rel
86 build_gn_with_gn(temp_gn
, build_rel
, options
)
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
)
97 def build_gn_with_ninja_manually(tempdir
, options
):
98 write_ninja(os
.path
.join(tempdir
, 'build.ninja'), options
)
99 cmd
= ['ninja', '-C', tempdir
]
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
]
117 cflags
.extend(['-O0', '-g'])
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'])
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'):
133 if name
.endswith('_unittest.cc'):
135 if name
in ['generate_test_gn_data.cc', 'run_all_unittests.cc']:
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([
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',
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',
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',
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',
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',
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',
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'] = {
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',
280 'cflags': cflags
+ ['-DHAVE_CONFIG_H'],
285 libs
.extend(['-lrt'])
286 ldflags
.extend(['-pthread'])
288 static_libraries
['xdg_user_dirs'] = {
290 'base/third_party/xdg_user_dirs/xdg_user_dir_lookup.cc',
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',
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',
338 template_filename
= 'build_mac.ninja.template'
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'
349 for library
, settings
in static_libraries
.iteritems():
350 for src_file
in settings
['sources']:
352 'build %s: %s %s' % (src_to_obj(src_file
),
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', [])),
360 ' '.join(cflags_cc
+ settings
.get('cflags_cc', [])),
363 ninja_lines
.append(' cc = %s' % cc
)
365 ninja_lines
.append(' cxx = %s' % cxx
)
367 ninja_lines
.append('build %s.a: alink_thin %s' % (
369 ' '.join([src_to_obj(src_file
) for src_file
in settings
['sources']])))
373 '-framework', 'AppKit',
374 '-framework', 'CoreFoundation',
375 '-framework', 'Foundation',
376 '-framework', 'Security',
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
),
386 ninja_lines
.append(' ld = %s' % ld
)
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')
402 cmd
= ['ninja', '-C', build_dir
]
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:]))