Index: tools/gn/bootstrap/bootstrap.py |
diff --git a/tools/gn/bootstrap/bootstrap.py b/tools/gn/bootstrap/bootstrap.py |
index 72ffd6093d22dfa993f523ed425bcec8d3320b02..b2b8835ed7824ef85eb02ba7df2b346f8def03db 100755 |
--- a/tools/gn/bootstrap/bootstrap.py |
+++ b/tools/gn/bootstrap/bootstrap.py |
@@ -29,12 +29,15 @@ BOOTSTRAP_DIR = os.path.dirname(os.path.abspath(__file__)) |
GN_ROOT = os.path.dirname(BOOTSTRAP_DIR) |
SRC_ROOT = os.path.dirname(os.path.dirname(GN_ROOT)) |
+is_win = sys.platform.startswith('win') |
is_linux = sys.platform.startswith('linux') |
is_mac = sys.platform.startswith('darwin') |
is_posix = is_linux or is_mac |
def check_call(cmd, **kwargs): |
logging.debug('Running: %s', ' '.join(cmd)) |
+ if cmd and cmd[0].endswith('.py'): |
+ cmd.insert(0, sys.executable) |
subprocess.check_call(cmd, cwd=GN_ROOT, **kwargs) |
def mkdir_p(path): |
@@ -66,6 +69,10 @@ def run_build(tempdir, options): |
temp_gn = os.path.join(tempdir, 'gn') |
out_gn = os.path.join(build_root, 'gn') |
+ if is_win: |
+ temp_gn += '.exe' |
+ out_gn += '.exe' |
+ |
if options.no_rebuild: |
mkdir_p(build_root) |
shutil.copy2(temp_gn, out_gn) |
@@ -113,22 +120,33 @@ def main(argv): |
return 1 |
return 0 |
+def write_compiled_message(root_gen_dir, source): |
+ path = os.path.join(root_gen_dir, os.path.dirname(source)) |
+ mkdir_p(path) |
+ check_call([ |
+ 'mc.exe', |
+ '-r', path, '-h', path, |
+ '-u', '-um', |
+ os.path.join(SRC_ROOT, source), |
+ ]) |
def write_buildflag_header_manually(root_gen_dir, header, flags): |
mkdir_p(os.path.join(root_gen_dir, os.path.dirname(header))) |
- with tempfile.NamedTemporaryFile() as f: |
+ |
+ temp_path = os.path.join(root_gen_dir, header + '.tmp') |
brettw
2016/06/13 18:19:43
I don't understand this change. Was the tempfile p
timn
2016/06/13 18:56:30
It "works", but not for our use case here.
write_
|
+ with open(temp_path, 'w') as f: |
f.write('--flags') |
for name,value in flags.items(): |
f.write(' ' + name + '=' + value) |
- f.flush() |
- check_call([ |
- os.path.join(SRC_ROOT, 'build', 'write_buildflag_header.py'), |
- '--output', header, |
- '--gen-dir', root_gen_dir, |
- '--definitions', f.name, |
- ]) |
+ check_call([ |
+ os.path.join(SRC_ROOT, 'build', 'write_buildflag_header.py'), |
+ '--output', header, |
+ '--gen-dir', root_gen_dir, |
+ '--definitions', temp_path, |
+ ]) |
+ os.remove(temp_path) |
def build_gn_with_ninja_manually(tempdir, options): |
root_gen_dir = os.path.join(tempdir, 'gen') |
@@ -150,19 +168,125 @@ def build_gn_with_ninja_manually(tempdir, options): |
'default' |
]) |
- write_ninja(os.path.join(tempdir, 'build.ninja'), root_gen_dir, options) |
+ if is_win: |
+ write_buildflag_header_manually(root_gen_dir, 'base/win/base_features.h', |
+ {'SINGLE_MODULE_MODE_HANDLE_VERIFIER': 'true'}) |
+ |
+ write_compiled_message(root_gen_dir, |
+ 'base/trace_event/etw_manifest/chrome_events_win.man') |
+ |
+ write_gn_ninja(os.path.join(tempdir, 'build.ninja'), |
+ root_gen_dir, options) |
cmd = ['ninja', '-C', tempdir] |
if options.verbose: |
cmd.append('-v') |
- cmd.append('gn') |
+ |
+ if is_win: |
+ cmd.append('gn.exe') |
+ else: |
+ cmd.append('gn') |
+ |
check_call(cmd) |
-def write_ninja(path, root_gen_dir, options): |
- cc = os.environ.get('CC', '') |
- cxx = os.environ.get('CXX', '') |
+def write_ninja(path, static_libraries, executables, |
+ cc, cxx, ar, ld, |
+ cflags=[], cflags_cc=[], ldflags=[], |
+ include_dirs=[], solibs=[]): |
+ ninja_header_lines = [ |
+ 'cc = ' + cc, |
+ 'cxx = ' + cxx, |
+ 'ar = ' + ar, |
+ 'ld = ' + ld, |
+ '', |
+ ] |
+ |
+ if is_win: |
+ template_filename = 'build_vs.ninja.template' |
+ elif is_mac: |
+ template_filename = 'build_mac.ninja.template' |
+ else: |
+ template_filename = 'build.ninja.template' |
+ |
+ with open(os.path.join(GN_ROOT, 'bootstrap', template_filename)) as f: |
+ ninja_template = f.read() |
+ |
+ if is_win: |
+ executable_ext = '.exe' |
+ library_ext = '.lib' |
+ object_ext = '.obj' |
+ else: |
+ executable_ext = '' |
+ library_ext = '.a' |
+ object_ext = '.o' |
+ |
+ def escape_path_ninja(path): |
+ return path.replace('$ ', '$$ ').replace(' ', '$ ').replace(':', '$:') |
+ |
+ def src_to_obj(path): |
+ return escape_path_ninja('%s' % os.path.splitext(path)[0] + object_ext) |
+ |
+ def library_to_a(library): |
+ return '%s%s' % (library, library_ext) |
+ |
+ ninja_lines = [] |
+ def build_source(src_file, settings): |
+ ninja_lines.extend([ |
+ 'build %s: %s %s' % (src_to_obj(src_file), |
+ settings['tool'], |
+ escape_path_ninja( |
+ os.path.join(SRC_ROOT, src_file))), |
+ ' includes = %s' % ' '.join( |
+ ['-I' + escape_path_ninja(dirname) for dirname in |
+ include_dirs + settings.get('include_dirs', [])]), |
+ ' cflags = %s' % ' '.join(cflags + settings.get('cflags', [])), |
+ ' cflags_cc = %s' % |
+ ' '.join(cflags_cc + settings.get('cflags_cc', [])), |
+ ]) |
+ |
+ for library, settings in static_libraries.iteritems(): |
+ for src_file in settings['sources']: |
+ build_source(src_file, settings) |
+ |
+ ninja_lines.append('build %s: alink_thin %s' % ( |
+ library_to_a(library), |
+ ' '.join([src_to_obj(src_file) for src_file in settings['sources']]))) |
+ |
+ for executable, settings in executables.iteritems(): |
+ for src_file in settings['sources']: |
+ build_source(src_file, settings) |
+ |
+ ninja_lines.extend([ |
+ 'build %s%s: link %s | %s' % ( |
+ executable, executable_ext, |
+ ' '.join([src_to_obj(src_file) for src_file in settings['sources']]), |
+ ' '.join([library_to_a(library) for library in settings['libs']])), |
+ ' ldflags = %s' % ' '.join(ldflags), |
+ ' solibs = %s' % ' '.join(solibs), |
+ ' libs = %s' % ' '.join( |
+ [library_to_a(library) for library in settings['libs']]), |
+ ]) |
+ |
+ ninja_lines.append('') # Make sure the file ends with a newline. |
+ |
+ with open(path, 'w') as f: |
+ f.write('\n'.join(ninja_header_lines)) |
+ f.write(ninja_template) |
+ f.write('\n'.join(ninja_lines)) |
+ |
+def write_gn_ninja(path, root_gen_dir, options): |
brettw
2016/06/13 18:19:43
I don't understand the new distinction you're maki
timn
2016/06/13 18:56:30
write_ninja is just a helper method that does the
|
+ if is_win: |
+ cc = os.environ.get('CC', 'cl.exe') |
+ cxx = os.environ.get('CXX', 'cl.exe') |
+ ld = os.environ.get('LD', 'link.exe') |
+ ar = os.environ.get('AR', 'lib.exe') |
+ else: |
+ cc = os.environ.get('CC', 'cc') |
+ cxx = os.environ.get('CXX', 'c++') |
+ ld = os.environ.get('LD', cxx) |
+ ar = os.environ.get('AR', 'ar') |
+ |
cflags = os.environ.get('CFLAGS', '').split() |
cflags_cc = os.environ.get('CXXFLAGS', '').split() |
- ld = os.environ.get('LD', cxx) |
ldflags = os.environ.get('LDFLAGS', '').split() |
include_dirs = [root_gen_dir, SRC_ROOT] |
libs = [] |
@@ -179,16 +303,43 @@ def write_ninja(path, root_gen_dir, options): |
cflags.extend([ |
'-D_FILE_OFFSET_BITS=64', |
+ '-D__STDC_CONSTANT_MACROS', '-D__STDC_FORMAT_MACROS', |
'-pthread', |
'-pipe', |
'-fno-exceptions' |
]) |
cflags_cc.extend(['-std=c++11', '-Wno-c++11-narrowing']) |
+ elif is_win: |
+ if not options.debug: |
+ cflags.extend(['/Ox', '/DNDEBUG', '/GL']) |
+ ldflags.extend(['/LTCG', '/OPT:REF', '/OPT:ICF']) |
+ |
+ cflags.extend([ |
+ '/FS', |
+ '/Gy', |
+ '/W3', '/wd4244', |
+ '/Zi', |
+ '/DWIN32_LEAN_AND_MEAN', '/DNOMINMAX', |
+ '/D_CRT_SECURE_NO_DEPRECATE', '/D_SCL_SECURE_NO_DEPRECATE', |
+ '/D_WIN32_WINNT=0x0A00', '/DWINVER=0x0A00', |
+ '/DUNICODE', '/D_UNICODE', |
+ ]) |
+ cflags_cc.extend([ |
+ '/GR-', |
+ '/D_HAS_EXCEPTIONS=0', |
+ ]) |
+ # TODO(tim): Support for 64bit builds? |
+ ldflags.extend(['/MACHINE:x86', '/DEBUG']) |
static_libraries = { |
'base': {'sources': [], 'tool': 'cxx', 'include_dirs': []}, |
'dynamic_annotations': {'sources': [], 'tool': 'cc', 'include_dirs': []}, |
- 'gn': {'sources': [], 'tool': 'cxx', 'include_dirs': []}, |
+ 'gn_lib': {'sources': [], 'tool': 'cxx', 'include_dirs': []}, |
+ } |
+ |
+ executables = { |
+ 'gn': {'sources': ['tools/gn/gn_main.cc'], |
+ 'tool': 'cxx', 'include_dirs': [], 'libs': []}, |
} |
for name in os.listdir(GN_ROOT): |
@@ -198,8 +349,10 @@ def write_ninja(path, root_gen_dir, options): |
continue |
if name == 'run_all_unittests.cc': |
continue |
+ if name == 'gn_main.cc': |
+ continue |
full_path = os.path.join(GN_ROOT, name) |
- static_libraries['gn']['sources'].append( |
+ static_libraries['gn_lib']['sources'].append( |
os.path.relpath(full_path, SRC_ROOT)) |
static_libraries['dynamic_annotations']['sources'].extend([ |
@@ -272,7 +425,6 @@ def write_ninja(path, root_gen_dir, options): |
'base/sequenced_task_runner.cc', |
'base/sha1.cc', |
'base/strings/pattern.cc', |
- 'base/strings/string16.cc', |
'base/strings/string_number_conversions.cc', |
'base/strings/string_piece.cc', |
'base/strings/string_split.cc', |
@@ -352,6 +504,7 @@ def write_ninja(path, root_gen_dir, options): |
'base/process/process_handle_posix.cc', |
'base/process/process_metrics_posix.cc', |
'base/process/process_posix.cc', |
+ 'base/strings/string16.cc', |
'base/synchronization/condition_variable_posix.cc', |
'base/synchronization/lock_impl_posix.cc', |
'base/synchronization/read_write_lock_posix.cc', |
@@ -386,9 +539,8 @@ def write_ninja(path, root_gen_dir, options): |
'cflags': cflags + ['-DHAVE_CONFIG_H'], |
} |
- |
if is_linux: |
- libs.extend(['-lrt']) |
+ libs.extend(['-lrt', '-latomic']) |
ldflags.extend(['-pthread']) |
static_libraries['xdg_user_dirs'] = { |
@@ -454,65 +606,105 @@ def write_ninja(path, root_gen_dir, options): |
'base/third_party/libevent/kqueue.c', |
]) |
- |
- if is_mac: |
- template_filename = 'build_mac.ninja.template' |
- else: |
- template_filename = 'build.ninja.template' |
- |
- with open(os.path.join(GN_ROOT, 'bootstrap', template_filename)) as f: |
- ninja_template = f.read() |
- |
- def src_to_obj(path): |
- return '%s' % os.path.splitext(path)[0] + '.o' |
- |
- ninja_lines = [] |
- for library, settings in static_libraries.iteritems(): |
- for src_file in settings['sources']: |
- ninja_lines.extend([ |
- 'build %s: %s %s' % (src_to_obj(src_file), |
- settings['tool'], |
- os.path.join(SRC_ROOT, src_file)), |
- ' includes = %s' % ' '.join( |
- ['-I' + dirname for dirname in |
- include_dirs + settings.get('include_dirs', [])]), |
- ' cflags = %s' % ' '.join(cflags + settings.get('cflags', [])), |
- ' cflags_cc = %s' % |
- ' '.join(cflags_cc + settings.get('cflags_cc', [])), |
- ]) |
- if cc: |
- ninja_lines.append(' cc = %s' % cc) |
- if cxx: |
- ninja_lines.append(' cxx = %s' % cxx) |
- |
- ninja_lines.append('build %s.a: alink_thin %s' % ( |
- library, |
- ' '.join([src_to_obj(src_file) for src_file in settings['sources']]))) |
- |
- if is_mac: |
libs.extend([ |
'-framework', 'AppKit', |
'-framework', 'CoreFoundation', |
'-framework', 'Foundation', |
'-framework', 'Security', |
- ]); |
+ ]) |
- ninja_lines.extend([ |
- 'build gn: link %s' % ( |
- ' '.join(['%s.a' % library for library in static_libraries])), |
- ' ldflags = %s' % ' '.join(ldflags), |
- ' libs = %s' % ' '.join(libs), |
- ]) |
- if ld: |
- ninja_lines.append(' ld = %s' % ld) |
- else: |
- ninja_lines.append(' ld = $ldxx') |
+ if is_win: |
+ static_libraries['base']['sources'].extend([ |
+ 'base/base_paths_win.cc', |
+ 'base/cpu.cc', |
+ 'base/debug/close_handle_hook_win.cc', |
+ 'base/debug/debugger.cc', |
+ 'base/debug/debugger_win.cc', |
+ 'base/debug/profiler.cc', |
+ 'base/debug/stack_trace_win.cc', |
+ 'base/file_version_info_win.cc', |
+ 'base/files/file_enumerator_win.cc', |
+ 'base/files/file_path_watcher_win.cc', |
+ 'base/files/file_util_win.cc', |
+ 'base/files/file_win.cc', |
+ 'base/files/memory_mapped_file_win.cc', |
+ 'base/logging_win.cc', |
+ 'base/memory/memory_pressure_monitor_win.cc', |
+ 'base/memory/shared_memory_handle_win.cc', |
+ 'base/memory/shared_memory_win.cc', |
+ 'base/message_loop/message_pump_win.cc', |
+ 'base/native_library_win.cc', |
+ 'base/power_monitor/power_monitor_device_source_win.cc', |
+ 'base/process/kill_win.cc', |
+ 'base/process/launch_win.cc', |
+ 'base/process/memory_win.cc', |
+ 'base/process/process_handle_win.cc', |
+ 'base/process/process_info_win.cc', |
+ 'base/process/process_iterator_win.cc', |
+ 'base/process/process_metrics_win.cc', |
+ 'base/process/process_win.cc', |
+ 'base/profiler/native_stack_sampler_win.cc', |
+ 'base/profiler/win32_stack_frame_unwinder.cc', |
+ 'base/rand_util.cc', |
+ 'base/rand_util_win.cc', |
+ 'base/strings/sys_string_conversions_win.cc', |
+ 'base/sync_socket_win.cc', |
+ 'base/synchronization/condition_variable_win.cc', |
+ 'base/synchronization/lock_impl_win.cc', |
+ 'base/synchronization/read_write_lock_win.cc', |
+ 'base/synchronization/waitable_event_watcher_win.cc', |
+ 'base/synchronization/waitable_event_win.cc', |
+ 'base/sys_info_win.cc', |
+ 'base/threading/platform_thread_win.cc', |
+ 'base/threading/thread_local_storage_win.cc', |
+ 'base/threading/thread_local_win.cc', |
+ 'base/threading/worker_pool_win.cc', |
+ 'base/time/time_win.cc', |
+ 'base/timer/hi_res_timer_manager_win.cc', |
+ 'base/trace_event/heap_profiler_allocation_register_win.cc', |
+ 'base/trace_event/trace_event_etw_export_win.cc', |
+ 'base/trace_event/winheap_dump_provider_win.cc', |
+ 'base/win/enum_variant.cc', |
+ 'base/win/event_trace_controller.cc', |
+ 'base/win/event_trace_provider.cc', |
+ 'base/win/i18n.cc', |
+ 'base/win/iat_patch_function.cc', |
+ 'base/win/iunknown_impl.cc', |
+ 'base/win/message_window.cc', |
+ 'base/win/object_watcher.cc', |
+ 'base/win/pe_image.cc', |
+ 'base/win/process_startup_helper.cc', |
+ 'base/win/registry.cc', |
+ 'base/win/resource_util.cc', |
+ 'base/win/scoped_bstr.cc', |
+ 'base/win/scoped_handle.cc', |
+ 'base/win/scoped_process_information.cc', |
+ 'base/win/scoped_variant.cc', |
+ 'base/win/shortcut.cc', |
+ 'base/win/startup_information.cc', |
+ 'base/win/wait_chain.cc', |
+ 'base/win/win_util.cc', |
+ 'base/win/windows_version.cc', |
+ 'base/win/wrapped_window_proc.cc', |
+ ]) |
- ninja_lines.append('') # Make sure the file ends with a newline. |
+ libs.extend([ |
+ 'kernel32.lib', |
+ 'user32.lib', |
+ 'shell32.lib', |
+ 'ole32.lib', |
+ 'winmm.lib', |
+ 'ws2_32.lib', |
+ 'userenv.lib', |
+ 'version.lib', |
+ 'dbghelp.lib', |
+ ]) |
- with open(path, 'w') as f: |
- f.write(ninja_template + '\n'.join(ninja_lines)) |
+ # we just build static libraries that GN needs |
+ executables['gn']['libs'].extend(static_libraries.keys()) |
+ write_ninja(path, static_libraries, executables, cc, cxx, ar, ld, |
+ cflags, cflags_cc, ldflags, include_dirs, libs) |
def build_gn_with_gn(temp_gn, build_dir, options): |
gn_gen_args = options.gn_gen_args or '' |
@@ -527,7 +719,7 @@ def build_gn_with_gn(temp_gn, build_dir, options): |
cmd.append('gn') |
check_call(cmd) |
- if not options.debug: |
+ if not options.debug and not is_win: |
check_call(['strip', os.path.join(build_dir, 'gn')]) |