1a497eec67cb0ed918e7eaef070b02349114837f9jochen@chromium.org# Copyright (c) 2013 Google Inc. All rights reserved.
2df8224662e615bd36cf8bebae8e58c017201f998sgk@chromium.org# Use of this source code is governed by a BSD-style license that can be
3df8224662e615bd36cf8bebae8e58c017201f998sgk@chromium.org# found in the LICENSE file.
4df8224662e615bd36cf8bebae8e58c017201f998sgk@chromium.org
5bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# Notes:
697d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.org#
7bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# This is all roughly based on the Makefile system used by the Linux
88dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# kernel, but is a non-recursive make -- we put the entire dependency
98dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# graph in front of make and let it figure it out.
1097d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.org#
11bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# The code below generates a separate .mk file for each target, but
12bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# all are sourced by the top-level Makefile.  This means that all
13bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# variables in .mk-files clobber one another.  Be careful to use :=
148dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# where appropriate for immediate evaluation, and similarly to watch
158dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# that you're not relying on a variable value to last beween different
168dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# .mk files.
178dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org#
188dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# TODOs:
1997d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.org#
20bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# Global settings and utility functions are currently stuffed in the
21bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# toplevel Makefile.  It may make sense to generate some .mk files on
22bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# the side to keep the the files readable.
2397d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.org
2454d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.orgimport os
2554d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.orgimport re
2654d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.orgimport sys
2708fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.orgimport subprocess
2897d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.orgimport gyp
29cde8a116ef5754c45a27835daf1f3d0db0fc79d7sgk@chromium.orgimport gyp.common
300839e68998d2c8e8f10ff21e648136f220fddd26thakis@chromium.orgimport gyp.xcode_emulation
3154d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.orgfrom gyp.common import GetEnvironFallback
321c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.orgfrom gyp.common import GypError
338dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
3497d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.orggenerator_default_variables = {
35566665e8b48bfd0b449acb2e7b55e6029422c85aevan@chromium.org  'EXECUTABLE_PREFIX': '',
36566665e8b48bfd0b449acb2e7b55e6029422c85aevan@chromium.org  'EXECUTABLE_SUFFIX': '',
37d813fe1dcf7ab60f4ab729d1e32199598059b7bfbradnelson@google.com  'STATIC_LIB_PREFIX': 'lib',
38d813fe1dcf7ab60f4ab729d1e32199598059b7bfbradnelson@google.com  'SHARED_LIB_PREFIX': 'lib',
39d813fe1dcf7ab60f4ab729d1e32199598059b7bfbradnelson@google.com  'STATIC_LIB_SUFFIX': '.a',
40023d71b91d502f776f67c9fced435601070a4349evan@chromium.org  'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/$(TARGET)/geni',
41ee5f7892e6c4d3fea34e973727624d88cdc8e3b2thakis@chromium.org  'SHARED_INTERMEDIATE_DIR': '$(obj)/gen',
4286531b60fd9c5beb5265e7d61a2ad5bdf97c95ceevan@chromium.org  'PRODUCT_DIR': '$(builddir)',
438dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org  'RULE_INPUT_ROOT': '%(INPUT_ROOT)s',  # This gets expanded by Python.
44cdaa7e6d2e12c7d592265333396c6d1307632e22scr@chromium.org  'RULE_INPUT_DIRNAME': '%(INPUT_DIRNAME)s',  # This gets expanded by Python.
458e2ab1cd9cc50f54d97914eef6295b041de21571mmoss@chromium.org  'RULE_INPUT_PATH': '$(abspath $<)',
460c391ffe6d7c2264f8e237aaf2cee6ad7178e8e7sgk@chromium.org  'RULE_INPUT_EXT': '$(suffix $<)',
470c391ffe6d7c2264f8e237aaf2cee6ad7178e8e7sgk@chromium.org  'RULE_INPUT_NAME': '$(notdir $<)',
482c9e8675a425664fcc6fa1038c20dae9f2138af3bradnelson@google.com  'CONFIGURATION_NAME': '$(BUILDTYPE)',
4997d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.org}
5097d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.org
51821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com# Make supports multiple toolsets
52821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.comgenerator_supports_multiple_toolsets = True
53bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org
54b0d2ddb2fa0248f384d5264b19e22fd4fd13d14emark@chromium.org# Request sorted dependencies in the order from dependents to dependencies.
55b0d2ddb2fa0248f384d5264b19e22fd4fd13d14emark@chromium.orggenerator_wants_sorted_dependencies = False
56b0d2ddb2fa0248f384d5264b19e22fd4fd13d14emark@chromium.org
5769c5522a3dc3d0906ab836350f53dae34a9897d3bradnelson@google.com# Placates pylint.
5869c5522a3dc3d0906ab836350f53dae34a9897d3bradnelson@google.comgenerator_additional_non_configuration_keys = []
5969c5522a3dc3d0906ab836350f53dae34a9897d3bradnelson@google.comgenerator_additional_path_sections = []
6069c5522a3dc3d0906ab836350f53dae34a9897d3bradnelson@google.comgenerator_extra_sources_for_rules = []
61e5a492a8502b2df01a73dc2e6d6a04b22a63384ethakis@chromium.orggenerator_filelist_paths = None
6269c5522a3dc3d0906ab836350f53dae34a9897d3bradnelson@google.com
63c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
64c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.orgdef CalculateVariables(default_variables, params):
65c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org  """Calculate additional variables for use in the build (called by gyp)."""
661911d51eee5277f2e1ba9e13a6dbad77b544283cthakis@chromium.org  flavor = gyp.common.GetFlavor(params)
670c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org  if flavor == 'mac':
68c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    default_variables.setdefault('OS', 'mac')
69c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib')
709ab39383c23368ab17e6f7bd7d6d0a6181a32710thakis@chromium.org    default_variables.setdefault('SHARED_LIB_DIR',
719ab39383c23368ab17e6f7bd7d6d0a6181a32710thakis@chromium.org                                 generator_default_variables['PRODUCT_DIR'])
727824cd9bea470b5d7e763fc40eed9b79a5f4d534thakis@chromium.org    default_variables.setdefault('LIB_DIR',
737824cd9bea470b5d7e763fc40eed9b79a5f4d534thakis@chromium.org                                 generator_default_variables['PRODUCT_DIR'])
74c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
75c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    # Copy additional generator configuration data from Xcode, which is shared
76c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    # by the Mac Make generator.
77c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    import gyp.generator.xcode as xcode_generator
78c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    global generator_additional_non_configuration_keys
79c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    generator_additional_non_configuration_keys = getattr(xcode_generator,
80c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org        'generator_additional_non_configuration_keys', [])
81c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    global generator_additional_path_sections
82c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    generator_additional_path_sections = getattr(xcode_generator,
83c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org        'generator_additional_path_sections', [])
84c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    global generator_extra_sources_for_rules
85c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    generator_extra_sources_for_rules = getattr(xcode_generator,
86c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org        'generator_extra_sources_for_rules', [])
8766e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org    COMPILABLE_EXTENSIONS.update({'.m': 'objc', '.mm' : 'objcxx'})
88c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org  else:
890c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org    operating_system = flavor
900c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org    if flavor == 'android':
910c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org      operating_system = 'linux'  # Keep this legacy behavior for now.
920c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org    default_variables.setdefault('OS', operating_system)
93c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    default_variables.setdefault('SHARED_LIB_SUFFIX', '.so')
94023d71b91d502f776f67c9fced435601070a4349evan@chromium.org    default_variables.setdefault('SHARED_LIB_DIR','$(builddir)/lib.$(TOOLSET)')
95023d71b91d502f776f67c9fced435601070a4349evan@chromium.org    default_variables.setdefault('LIB_DIR', '$(obj).$(TOOLSET)')
96c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
97c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
98c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.orgdef CalculateGeneratorInputInfo(params):
99c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org  """Calculate the generator specific info that gets fed to input (called by
100c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org  gyp)."""
101c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org  generator_flags = params.get('generator_flags', {})
102c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org  android_ndk_version = generator_flags.get('android_ndk_version', None)
103c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org  # Android NDK requires a strict link order.
104c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org  if android_ndk_version:
105c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    global generator_wants_sorted_dependencies
106c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    generator_wants_sorted_dependencies = True
107c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
108e5a492a8502b2df01a73dc2e6d6a04b22a63384ethakis@chromium.org  output_dir = params['options'].generator_output or \
109e5a492a8502b2df01a73dc2e6d6a04b22a63384ethakis@chromium.org               params['options'].toplevel_dir
110e5a492a8502b2df01a73dc2e6d6a04b22a63384ethakis@chromium.org  builddir_name = generator_flags.get('output_dir', 'out')
111e5a492a8502b2df01a73dc2e6d6a04b22a63384ethakis@chromium.org  qualified_out_dir = os.path.normpath(os.path.join(
112e5a492a8502b2df01a73dc2e6d6a04b22a63384ethakis@chromium.org    output_dir, builddir_name, 'gypfiles'))
113e5a492a8502b2df01a73dc2e6d6a04b22a63384ethakis@chromium.org
114e5a492a8502b2df01a73dc2e6d6a04b22a63384ethakis@chromium.org  global generator_filelist_paths
115e5a492a8502b2df01a73dc2e6d6a04b22a63384ethakis@chromium.org  generator_filelist_paths = {
116e5a492a8502b2df01a73dc2e6d6a04b22a63384ethakis@chromium.org    'toplevel': params['options'].toplevel_dir,
117e5a492a8502b2df01a73dc2e6d6a04b22a63384ethakis@chromium.org    'qualified_out_dir': qualified_out_dir,
118e5a492a8502b2df01a73dc2e6d6a04b22a63384ethakis@chromium.org  }
119e5a492a8502b2df01a73dc2e6d6a04b22a63384ethakis@chromium.org
120c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
1219a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# The .d checking code below uses these functions:
1229a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# wildcard, sort, foreach, shell, wordlist
1239a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# wildcard can handle spaces, the rest can't.
1249a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# Since I could find no way to make foreach work with spaces in filenames
1259a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# correctly, the .d files have spaces replaced with another character. The .d
1269a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# file for
1279a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org#     Chromium\ Framework.framework/foo
1289a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# is for example
1299a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org#     out/Release/.deps/out/Release/Chromium?Framework.framework/foo
1309a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# This is the replacement character.
1319a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.orgSPACE_REPLACEMENT = '?'
1329a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org
1339a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org
134c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.orgLINK_COMMANDS_LINUX = """\
135023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_alink = AR($(TOOLSET)) $@
136012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.orgcmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^)
137012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org
138012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.orgquiet_cmd_alink_thin = AR($(TOOLSET)) $@
139012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.orgcmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^)
140651b7dc9cd5a02cde1e2087bf7364ae5c97d0da2thakis@chromium.org
141c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# Due to circular dependencies between libraries :(, we wrap the
142c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# special "figure out circular dependencies" flags around the entire
143c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# input list during linking.
144023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_link = LINK($(TOOLSET)) $@
145023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
146c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
147c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# We support two kinds of shared objects (.so):
148c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# 1) shared_library, which is just bundling together many dependent libraries
149c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# into a link line.
150c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# 2) loadable_module, which is generating a module intended for dlopen().
151c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org#
152c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# They differ only slightly:
153c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# In the former case, we want to package all dependent code into the .so.
154c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# In the latter case, we want to package just the API exposed by the
155c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# outermost module.
156c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# This means shared_library uses --whole-archive, while loadable_module doesn't.
157c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# (Note that --whole-archive is incompatible with the --start-group used in
158c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# normal linking.)
159c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
160c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# Other shared-object link notes:
161c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# - Set SONAME to the library filename so our binaries don't reference
162c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org# the local, absolute paths used on the link command-line.
163023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_solink = SOLINK($(TOOLSET)) $@
164023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
165c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
166023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
167023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
168c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org"""
169c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
170c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.orgLINK_COMMANDS_MAC = """\
171651b7dc9cd5a02cde1e2087bf7364ae5c97d0da2thakis@chromium.orgquiet_cmd_alink = LIBTOOL-STATIC $@
1725c809bab10c272ab2e34289a2505fc19ccd1da2cthakis@chromium.orgcmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool $(GYP_LIBTOOLFLAGS) -static -o $@ $(filter %.o,$^)
173651b7dc9cd5a02cde1e2087bf7364ae5c97d0da2thakis@chromium.org
174023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_link = LINK($(TOOLSET)) $@
175023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
176c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
177023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_solink = SOLINK($(TOOLSET)) $@
178023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
179c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
180023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
1815b29b370c07c612c1f1201f8a1fd549c6288d17ethakis@chromium.orgcmd_solink_module = $(LINK.$(TOOLSET)) -bundle $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
182c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org"""
183c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
184ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.orgLINK_COMMANDS_ANDROID = """\
185023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_alink = AR($(TOOLSET)) $@
186012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.orgcmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^)
187012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org
188012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.orgquiet_cmd_alink_thin = AR($(TOOLSET)) $@
189012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.orgcmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^)
190ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org
191ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org# Due to circular dependencies between libraries :(, we wrap the
192ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org# special "figure out circular dependencies" flags around the entire
193ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org# input list during linking.
194023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_link = LINK($(TOOLSET)) $@
195023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_link_host = LINK($(TOOLSET)) $@
196023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
197023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_link_host = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS)
198ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org
199ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org# Other shared-object link notes:
200ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org# - Set SONAME to the library filename so our binaries don't reference
201ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org# the local, absolute paths used on the link command-line.
202023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_solink = SOLINK($(TOOLSET)) $@
203023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
204ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org
205023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
206023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
207023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_solink_module_host = SOLINK_MODULE($(TOOLSET)) $@
208023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_solink_module_host = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
209ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org"""
210ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org
211ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org
212b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.orgLINK_COMMANDS_AIX = """\
213b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.orgquiet_cmd_alink = AR($(TOOLSET)) $@
214b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.orgcmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^)
215b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.org
216b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.orgquiet_cmd_alink_thin = AR($(TOOLSET)) $@
217b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.orgcmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^)
218b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.org
219b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.orgquiet_cmd_link = LINK($(TOOLSET)) $@
220b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.orgcmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS)
221b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.org
222b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.orgquiet_cmd_solink = SOLINK($(TOOLSET)) $@
223b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.orgcmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS)
224b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.org
225b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.orgquiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
226b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.orgcmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
227b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.org"""
228b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.org
229b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.org
230bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# Header of toplevel Makefile.
231bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# This should go into the build tree, but it's easier to keep it here for now.
232bb0fb30d25fc36568d3e453ca2d942f6ea83977cevan@chromium.orgSHARED_HEADER = ("""\
233bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# We borrow heavily from the kernel build setup, though we are simpler since
234bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# we don't have Kconfig tweaking settings on us.
235bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org
2368dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# The implicit make rules have it looking for RCS files, among other things.
2378dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# We instead explicitly write all the rules we care about.
2388dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# It's even quicker (saves ~200ms) to pass -r on the command line.
2398dafdc96be95b51813d58a68213457925520bc8bevan@chromium.orgMAKEFLAGS=-r
2408dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
241f078f3438886f62b056557b4b7ed7cf88a8c080cevan@chromium.org# The source directory tree.
242f078f3438886f62b056557b4b7ed7cf88a8c080cevan@chromium.orgsrcdir := %(srcdir)s
24306bb1b70edfe30b4959b6e34d64de671379a10ffthakis@chromium.orgabs_srcdir := $(abspath $(srcdir))
244f078f3438886f62b056557b4b7ed7cf88a8c080cevan@chromium.org
245f078f3438886f62b056557b4b7ed7cf88a8c080cevan@chromium.org# The name of the builddir.
246f078f3438886f62b056557b4b7ed7cf88a8c080cevan@chromium.orgbuilddir_name ?= %(builddir)s
247f078f3438886f62b056557b4b7ed7cf88a8c080cevan@chromium.org
248bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# The V=1 flag on command line makes us verbosely print command lines.
249bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.orgifdef V
250bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org  quiet=
251bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.orgelse
252bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org  quiet=quiet_
253bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.orgendif
254bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org
2557d8441dfa244206546f1fc8e1c15e0b4840ccc20evan@chromium.org# Specify BUILDTYPE=Release on the command line for a release build.
256f078f3438886f62b056557b4b7ed7cf88a8c080cevan@chromium.orgBUILDTYPE ?= %(default_configuration)s
2577d8441dfa244206546f1fc8e1c15e0b4840ccc20evan@chromium.org
25886531b60fd9c5beb5265e7d61a2ad5bdf97c95ceevan@chromium.org# Directory all our build output goes into.
25986531b60fd9c5beb5265e7d61a2ad5bdf97c95ceevan@chromium.org# Note that this must be two directories beneath src/ for unit tests to pass,
26086531b60fd9c5beb5265e7d61a2ad5bdf97c95ceevan@chromium.org# as they reach into the src/ directory for data with relative paths.
26158abd1795068b1ec2800790ea337480773d54ef0thestig@chromium.orgbuilddir ?= $(builddir_name)/$(BUILDTYPE)
26258abd1795068b1ec2800790ea337480773d54ef0thestig@chromium.orgabs_builddir := $(abspath $(builddir))
2630b39bcb204e7529ad49870fcd823c19d6b462e28mmoss@chromium.orgdepsdir := $(builddir)/.deps
26486531b60fd9c5beb5265e7d61a2ad5bdf97c95ceevan@chromium.org
26586531b60fd9c5beb5265e7d61a2ad5bdf97c95ceevan@chromium.org# Object output directory.
26686531b60fd9c5beb5265e7d61a2ad5bdf97c95ceevan@chromium.orgobj := $(builddir)/obj
2676009df71af8265c57676984165e9547b467a8f98evan@chromium.orgabs_obj := $(abspath $(obj))
26886531b60fd9c5beb5265e7d61a2ad5bdf97c95ceevan@chromium.org
26903f47b7c86543b4d1170c8bf18028b227f0af9d4piman@chromium.org# We build up a list of every single one of the targets so we can slurp in the
27003f47b7c86543b4d1170c8bf18028b227f0af9d4piman@chromium.org# generated dependency rule Makefiles in one pass.
27103f47b7c86543b4d1170c8bf18028b227f0af9d4piman@chromium.orgall_deps :=
27203f47b7c86543b4d1170c8bf18028b227f0af9d4piman@chromium.org
273af7b54928188f369d0f225cab0ce98dcf4520db3evan@chromium.org%(make_global_settings)s
274af7b54928188f369d0f225cab0ce98dcf4520db3evan@chromium.org
27544c1a6c35b0c9762c1066afff961068be4808423thakis@chromium.orgCC.target ?= %(CC.target)s
27644c1a6c35b0c9762c1066afff961068be4808423thakis@chromium.orgCFLAGS.target ?= $(CFLAGS)
27744c1a6c35b0c9762c1066afff961068be4808423thakis@chromium.orgCXX.target ?= %(CXX.target)s
27844c1a6c35b0c9762c1066afff961068be4808423thakis@chromium.orgCXXFLAGS.target ?= $(CXXFLAGS)
27944c1a6c35b0c9762c1066afff961068be4808423thakis@chromium.orgLINK.target ?= %(LINK.target)s
28044c1a6c35b0c9762c1066afff961068be4808423thakis@chromium.orgLDFLAGS.target ?= $(LDFLAGS)
28144c1a6c35b0c9762c1066afff961068be4808423thakis@chromium.orgAR.target ?= $(AR)
28244c1a6c35b0c9762c1066afff961068be4808423thakis@chromium.org
28302ae6281123f667d1d5e6f96474c89c3b862c313evan@chromium.org# C++ apps need to be linked with g++.
2845fd5403043db7021bce9568a0faa37d027b425c6ajwong@chromium.org#
28502ae6281123f667d1d5e6f96474c89c3b862c313evan@chromium.org# Note: flock is used to seralize linking. Linking is a memory-intensive
2865fd5403043db7021bce9568a0faa37d027b425c6ajwong@chromium.org# process so running parallel links can often lead to thrashing.  To disable
28702ae6281123f667d1d5e6f96474c89c3b862c313evan@chromium.org# the serialization, override LINK via an envrionment variable as follows:
2885fd5403043db7021bce9568a0faa37d027b425c6ajwong@chromium.org#
28902ae6281123f667d1d5e6f96474c89c3b862c313evan@chromium.org#   export LINK=g++
2905fd5403043db7021bce9568a0faa37d027b425c6ajwong@chromium.org#
2915fd5403043db7021bce9568a0faa37d027b425c6ajwong@chromium.org# This will allow make to invoke N linker processes as specified in -jN.
2923ae45ea0689cdd8777d13f943ac3b73d87c6c0e7sbc@chromium.orgLINK ?= %(flock)s $(builddir)/linker.lock $(CXX.target)
293821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com
29430dbad1010474d58abd9432759eb4eac0c158644evan@chromium.org# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
29530dbad1010474d58abd9432759eb4eac0c158644evan@chromium.org# to replicate this environment fallback in make as well.
29654d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.orgCC.host ?= %(CC.host)s
297d8d013c58f6b0a313b1f17e79aea635735604026piman@chromium.orgCFLAGS.host ?=
29854d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.orgCXX.host ?= %(CXX.host)s
299d8d013c58f6b0a313b1f17e79aea635735604026piman@chromium.orgCXXFLAGS.host ?=
30054d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.orgLINK.host ?= %(LINK.host)s
301d8d013c58f6b0a313b1f17e79aea635735604026piman@chromium.orgLDFLAGS.host ?=
30254d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.orgAR.host ?= %(AR.host)s
303bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org
3049a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# Define a dir function that can handle spaces.
3059a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
3069a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# "leading spaces cannot appear in the text of the first argument as written.
3079a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# These characters can be put into the argument value by variable substitution."
3089a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.orgempty :=
3099a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.orgspace := $(empty) $(empty)
3109a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org
3119a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
3129a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.orgreplace_spaces = $(subst $(space),""" + SPACE_REPLACEMENT + """,$1)
3139a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.orgunreplace_spaces = $(subst """ + SPACE_REPLACEMENT + """,$(space),$1)
3149a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.orgdirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
3159a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org
3168dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# Flags to make gcc output dependency info.  Note that you need to be
3178dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# careful here to use the flags that ccache and distcc can understand.
31886cb25510f5f7bb256a32f6f50778adec457f441evan@chromium.org# We write to a dep file on the side first and then rename at the end
3198dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# so we can't end up with a broken dep file.
3209a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.orgdepfile = $(depsdir)/$(call replace_spaces,$@).d
32186cb25510f5f7bb256a32f6f50778adec457f441evan@chromium.orgDEPFLAGS = -MMD -MF $(depfile).raw
3228dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
323bb0fb30d25fc36568d3e453ca2d942f6ea83977cevan@chromium.org# We have to fixup the deps output in a few ways.
32486cb25510f5f7bb256a32f6f50778adec457f441evan@chromium.org# (1) the file output should mention the proper .o file.
3258dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# ccache or distcc lose the path to the target, so we convert a rule of
3268dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# the form:
3278dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org#   foobar.o: DEP1 DEP2
3288dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# into
3298dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org#   path/to/foobar.o: DEP1 DEP2
33086cb25510f5f7bb256a32f6f50778adec457f441evan@chromium.org# (2) we want missing files not to cause us to fail to build.
33186cb25510f5f7bb256a32f6f50778adec457f441evan@chromium.org# We want to rewrite
3324c55d78ac2120e948aa9d3d21b02037e507a4418evan@chromium.org#   foobar.o: DEP1 DEP2 \\
333bb0fb30d25fc36568d3e453ca2d942f6ea83977cevan@chromium.org#               DEP3
334bb0fb30d25fc36568d3e453ca2d942f6ea83977cevan@chromium.org# to
33565f9b50705f8026437bd6fe3e379d87ccf3d09d8thestig@chromium.org#   DEP1:
33665f9b50705f8026437bd6fe3e379d87ccf3d09d8thestig@chromium.org#   DEP2:
337bb0fb30d25fc36568d3e453ca2d942f6ea83977cevan@chromium.org#   DEP3:
338bb0fb30d25fc36568d3e453ca2d942f6ea83977cevan@chromium.org# so if the files are missing, they're just considered phony rules.
339bb0fb30d25fc36568d3e453ca2d942f6ea83977cevan@chromium.org# We have to do some pretty insane escaping to get those backslashes
3409a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# and dollar signs past make, the shell, and sed at the same time.
3419a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# Doesn't work with spaces, but that's fine: .d files have spaces in
3429a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# their names replaced with other characters."""
343bb0fb30d25fc36568d3e453ca2d942f6ea83977cevan@chromium.orgr"""
344bb0fb30d25fc36568d3e453ca2d942f6ea83977cevan@chromium.orgdefine fixup_dep
345ccc29369f9f057849eeabd306ce9166ceeea1934evan@chromium.org# The depfile may not exist if the input file didn't have any #includes.
346ccc29369f9f057849eeabd306ce9166ceeea1934evan@chromium.orgtouch $(depfile).raw
34786cb25510f5f7bb256a32f6f50778adec457f441evan@chromium.org# Fixup path as in (1).
34865f9b50705f8026437bd6fe3e379d87ccf3d09d8thestig@chromium.orgsed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
34965f9b50705f8026437bd6fe3e379d87ccf3d09d8thestig@chromium.org# Add extra rules as in (2).
35065f9b50705f8026437bd6fe3e379d87ccf3d09d8thestig@chromium.org# We remove slashes and replace spaces with new lines;
35165f9b50705f8026437bd6fe3e379d87ccf3d09d8thestig@chromium.org# remove blank lines;
35265f9b50705f8026437bd6fe3e379d87ccf3d09d8thestig@chromium.org# delete the first line and append a colon to the remaining lines.
353cd53ec0d06adcd7c6e4e08d28e43f64e56e48920evan@chromium.orgsed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
354cd53ec0d06adcd7c6e4e08d28e43f64e56e48920evan@chromium.org  grep -v '^$$'                             |\
355cd53ec0d06adcd7c6e4e08d28e43f64e56e48920evan@chromium.org  sed -e 1d -e 's|$$|:|'                     \
35665f9b50705f8026437bd6fe3e379d87ccf3d09d8thestig@chromium.org    >> $(depfile)
35765f9b50705f8026437bd6fe3e379d87ccf3d09d8thestig@chromium.orgrm $(depfile).raw
358bb0fb30d25fc36568d3e453ca2d942f6ea83977cevan@chromium.orgendef
359bb0fb30d25fc36568d3e453ca2d942f6ea83977cevan@chromium.org"""
360bb0fb30d25fc36568d3e453ca2d942f6ea83977cevan@chromium.org"""
361bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# Command definitions:
362bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# - cmd_foo is the actual command to run;
363bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org# - quiet_cmd_foo is the brief-output summary of the command.
364bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org
365023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_cc = CC($(TOOLSET)) $@
366023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
367bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org
368023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_cxx = CXX($(TOOLSET)) $@
369023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
3700c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org%(extra_commands)s
3718dafdc96be95b51813d58a68213457925520bc8bevan@chromium.orgquiet_cmd_touch = TOUCH $@
3728dafdc96be95b51813d58a68213457925520bc8bevan@chromium.orgcmd_touch = touch $@
3738dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
3748dafdc96be95b51813d58a68213457925520bc8bevan@chromium.orgquiet_cmd_copy = COPY $@
37516549223553781ae675c6e45d998ae6cd5365e99mmoss@chromium.org# send stderr to /dev/null to ignore messages when linking directories.
37673d2a4436feed9412fd067377d705aeb2397e354thakis@chromium.orgcmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
3778dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
378c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org%(link_commands)s
379ab2b8f0793e3b10ab1301c0a98aa44e1be6f076cevan@chromium.org"""
380afa3616bae66f1b500fe9c481cd9436a607f4546evan@chromium.org
381ab2b8f0793e3b10ab1301c0a98aa44e1be6f076cevan@chromium.orgr"""
382ab2b8f0793e3b10ab1301c0a98aa44e1be6f076cevan@chromium.org# Define an escape_quotes function to escape single quotes.
383ab2b8f0793e3b10ab1301c0a98aa44e1be6f076cevan@chromium.org# This allows us to handle quotes properly as long as we always use
384ab2b8f0793e3b10ab1301c0a98aa44e1be6f076cevan@chromium.org# use single quotes and escape_quotes.
385ab2b8f0793e3b10ab1301c0a98aa44e1be6f076cevan@chromium.orgescape_quotes = $(subst ','\'',$(1))
386ab2b8f0793e3b10ab1301c0a98aa44e1be6f076cevan@chromium.org# This comment is here just to include a ' to unconfuse syntax highlighting.
387afd208980b73e15a5b4bc9b1848428c6f76ab67bmmoss@chromium.org# Define an escape_vars function to escape '$' variable syntax.
388e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org# This allows us to read/write command lines with shell variables (e.g.
389afd208980b73e15a5b4bc9b1848428c6f76ab67bmmoss@chromium.org# $LD_LIBRARY_PATH), without triggering make substitution.
390afd208980b73e15a5b4bc9b1848428c6f76ab67bmmoss@chromium.orgescape_vars = $(subst $$,$$$$,$(1))
391e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org# Helper that expands to a shell command to echo a string exactly as it is in
392e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org# make. This uses printf instead of echo because printf's behaviour with respect
393e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org# to escape sequences is more portable than echo's across different shells
394e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org# (e.g., dash, bash).
395f078f3438886f62b056557b4b7ed7cf88a8c080cevan@chromium.orgexact_echo = printf '%%s\n' '$(call escape_quotes,$(1))'
396ab2b8f0793e3b10ab1301c0a98aa44e1be6f076cevan@chromium.org"""
397ab2b8f0793e3b10ab1301c0a98aa44e1be6f076cevan@chromium.org"""
39824cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org# Helper to compare the command we're about to run against the command
39924cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org# we logged the last time we ran the command.  Produces an empty
40024cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org# string (false) when the commands match.
40124cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org# Tricky point: Make has no string-equality test function.
40224cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org# The kernel uses the following, but it seems like it would have false
40324cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org# positives, where one string reordered its arguments.
40424cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org#   arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \\
40524cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org#                       $(filter-out $(cmd_$@), $(cmd_$(1))))
40624cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org# We instead substitute each for the empty string into the other, and
40724cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org# say they're equal if both substitutions produce the empty string.
4089a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# .d files contain """ + SPACE_REPLACEMENT + \
4099a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org                   """ instead of spaces, take that into account.
4109a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.orgcommand_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\\
4119a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org                       $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
41224cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org
41324cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org# Helper that is non-empty when a prerequisite changes.
41424cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org# Normally make does this implicitly, but we force rules to always run
41524cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org# so we can check their command lines.
41624cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org#   $? -- new prerequisites
41724cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org#   $| -- order-only dependencies
41814a7d79834370ace1e2a08d1a6cd13cc65ba4f72tony@chromium.orgprereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
41924cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org
420fbc898019b1a500324a0ad89894a2b8b366ec8c2thakis@chromium.org# Helper that executes all postbuilds until one fails.
4212013ec6b77b9f4ce80b7c0d7fafd187e7b3e3f9fthakis@chromium.orgdefine do_postbuilds
4222013ec6b77b9f4ce80b7c0d7fafd187e7b3e3f9fthakis@chromium.org  @E=0;\\
4232013ec6b77b9f4ce80b7c0d7fafd187e7b3e3f9fthakis@chromium.org  for p in $(POSTBUILDS); do\\
4242013ec6b77b9f4ce80b7c0d7fafd187e7b3e3f9fthakis@chromium.org    eval $$p;\\
425fbc898019b1a500324a0ad89894a2b8b366ec8c2thakis@chromium.org    E=$$?;\\
426fbc898019b1a500324a0ad89894a2b8b366ec8c2thakis@chromium.org    if [ $$E -ne 0 ]; then\\
427fbc898019b1a500324a0ad89894a2b8b366ec8c2thakis@chromium.org      break;\\
4282013ec6b77b9f4ce80b7c0d7fafd187e7b3e3f9fthakis@chromium.org    fi;\\
4292013ec6b77b9f4ce80b7c0d7fafd187e7b3e3f9fthakis@chromium.org  done;\\
4302013ec6b77b9f4ce80b7c0d7fafd187e7b3e3f9fthakis@chromium.org  if [ $$E -ne 0 ]; then\\
4312013ec6b77b9f4ce80b7c0d7fafd187e7b3e3f9fthakis@chromium.org    rm -rf "$@";\\
4322013ec6b77b9f4ce80b7c0d7fafd187e7b3e3f9fthakis@chromium.org    exit $$E;\\
4332013ec6b77b9f4ce80b7c0d7fafd187e7b3e3f9fthakis@chromium.org  fi
4342013ec6b77b9f4ce80b7c0d7fafd187e7b3e3f9fthakis@chromium.orgendef
4352013ec6b77b9f4ce80b7c0d7fafd187e7b3e3f9fthakis@chromium.org
43624cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org# do_cmd: run a command via the above cmd_foo names, if necessary.
43724cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org# Should always run for a given target to handle command-line changes.
438e6c5e749c677515d7dfddf66ef69d88d0bfedd1aevan@chromium.org# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
4393c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org# Third argument, if non-zero, makes it do POSTBUILDS processing.
4409a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# Note: We intentionally do NOT call dirx for depfile, since it contains """ + \
4419a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org                                                     SPACE_REPLACEMENT + """ for
4429a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# spaces already and dirx strips the """ + SPACE_REPLACEMENT + \
4439a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org                                     """ characters.
44424cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.orgdefine do_cmd
44524cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org$(if $(or $(command_changed),$(prereq_changed)),
446e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org  @$(call exact_echo,  $($(quiet)cmd_$(1)))
4479a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org  @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
448c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org  $(if $(findstring flock,$(word %(flock_index)d,$(cmd_$1))),
449d3d868e99f9dd5fb78a2d53c4230661a747cb26bmmoss@chromium.org    @$(cmd_$(1))
450d3d868e99f9dd5fb78a2d53c4230661a747cb26bmmoss@chromium.org    @echo "  $(quiet_cmd_$(1)): Finished",
451d3d868e99f9dd5fb78a2d53c4230661a747cb26bmmoss@chromium.org    @$(cmd_$(1))
452d3d868e99f9dd5fb78a2d53c4230661a747cb26bmmoss@chromium.org  )
4539a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org  @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
45424cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org  @$(if $(2),$(fixup_dep))
4553c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org  $(if $(and $(3), $(POSTBUILDS)),
4562013ec6b77b9f4ce80b7c0d7fafd187e7b3e3f9fthakis@chromium.org    $(call do_postbuilds)
4573c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org  )
45824cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org)
45924cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.orgendef
46024cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org
4610fc3814647116a3c363d479ae476512b4e60571ejrg@chromium.org# Declare the "%(default_target)s" target first so it is the default,
4620fc3814647116a3c363d479ae476512b4e60571ejrg@chromium.org# even though we don't have the deps yet.
4630fc3814647116a3c363d479ae476512b4e60571ejrg@chromium.org.PHONY: %(default_target)s
4640fc3814647116a3c363d479ae476512b4e60571ejrg@chromium.org%(default_target)s:
465a12a9556125cf18f0c09b77a7721097e26d200d4sgk@chromium.org
4663c02308fe834c7af49f1557ac3d56be58a9b1fc7tony@chromium.org# make looks for ways to re-generate included makefiles, but in our case, we
4673c02308fe834c7af49f1557ac3d56be58a9b1fc7tony@chromium.org# don't have a direct way. Explicitly telling make that it has nothing to do
4683c02308fe834c7af49f1557ac3d56be58a9b1fc7tony@chromium.org# for them makes it go faster.
4693c02308fe834c7af49f1557ac3d56be58a9b1fc7tony@chromium.org%%.d: ;
4703c02308fe834c7af49f1557ac3d56be58a9b1fc7tony@chromium.org
47124cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org# Use FORCE_DO_CMD to force a target to run.  Should be coupled with
47224cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org# do_cmd.
47324cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org.PHONY: FORCE_DO_CMD
47424cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.orgFORCE_DO_CMD:
475bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org
476821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com""")
477821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com
4788347e3181c4b66aeb0a2e86c551f609b645f806dthakis@chromium.orgSHARED_HEADER_MAC_COMMANDS = """
479023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_objc = CXX($(TOOLSET)) $@
480023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
481d7a0093b8f5623ee54c5aaff2855742af9b657e1mmoss@chromium.org
482023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_objcxx = CXX($(TOOLSET)) $@
483023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
4848347e3181c4b66aeb0a2e86c551f609b645f806dthakis@chromium.org
4858347e3181c4b66aeb0a2e86c551f609b645f806dthakis@chromium.org# Commands for precompiled header files.
486023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_pch_c = CXX($(TOOLSET)) $@
487023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
488023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_pch_cc = CXX($(TOOLSET)) $@
489023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
490023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_pch_m = CXX($(TOOLSET)) $@
491023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
492023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgquiet_cmd_pch_mm = CXX($(TOOLSET)) $@
493023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
494ff1f8350a0f82afbd184ea2eca6fb26588e494d6thakis@chromium.org
495ff1f8350a0f82afbd184ea2eca6fb26588e494d6thakis@chromium.org# gyp-mac-tool is written next to the root Makefile by gyp.
4963c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd
4973c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org# already.
4983c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.orgquiet_cmd_mac_tool = MACTOOL $(4) $<
4993c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.orgcmd_mac_tool = ./gyp-mac-tool $(4) $< "$@"
500f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org
501f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.orgquiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@
5023c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.orgcmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4)
5036702555b550f751911ec601c8313515ecdb551e0rsesek@chromium.org
5046702555b550f751911ec601c8313515ecdb551e0rsesek@chromium.orgquiet_cmd_infoplist = INFOPLIST $@
505023d71b91d502f776f67c9fced435601070a4349evan@chromium.orgcmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@"
50666e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org"""
50766e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org
50866e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org
50966e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.orgdef WriteRootHeaderSuffixRules(writer):
51066e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org  extensions = sorted(COMPILABLE_EXTENSIONS.keys(), key=str.lower)
51166e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org
51266e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org  writer.write('# Suffix rules, putting all outputs into $(obj).\n')
51366e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org  for ext in extensions:
514023d71b91d502f776f67c9fced435601070a4349evan@chromium.org    writer.write('$(obj).$(TOOLSET)/%%.o: $(srcdir)/%%%s FORCE_DO_CMD\n' % ext)
51566e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org    writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext])
51666e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org
51766e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org  writer.write('\n# Try building from generated source, too.\n')
51866e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org  for ext in extensions:
51966e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org    writer.write(
520023d71b91d502f776f67c9fced435601070a4349evan@chromium.org        '$(obj).$(TOOLSET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD\n' % ext)
52166e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org    writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext])
52266e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org  writer.write('\n')
52366e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org  for ext in extensions:
524023d71b91d502f776f67c9fced435601070a4349evan@chromium.org    writer.write('$(obj).$(TOOLSET)/%%.o: $(obj)/%%%s FORCE_DO_CMD\n' % ext)
52566e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org    writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext])
52666e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org  writer.write('\n')
527d7a0093b8f5623ee54c5aaff2855742af9b657e1mmoss@chromium.org
528d7a0093b8f5623ee54c5aaff2855742af9b657e1mmoss@chromium.org
5292861b6b6fed0f0d5e7a5e8dfae4f9e4604906a6ethestig@chromium.orgSHARED_HEADER_SUFFIX_RULES_COMMENT1 = ("""\
5308dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# Suffix rules, putting all outputs into $(obj).
5312861b6b6fed0f0d5e7a5e8dfae4f9e4604906a6ethestig@chromium.org""")
5322861b6b6fed0f0d5e7a5e8dfae4f9e4604906a6ethestig@chromium.org
5338dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
5342861b6b6fed0f0d5e7a5e8dfae4f9e4604906a6ethestig@chromium.orgSHARED_HEADER_SUFFIX_RULES_COMMENT2 = ("""\
5358dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# Try building from generated source, too.
5362861b6b6fed0f0d5e7a5e8dfae4f9e4604906a6ethestig@chromium.org""")
5372861b6b6fed0f0d5e7a5e8dfae4f9e4604906a6ethestig@chromium.org
5382861b6b6fed0f0d5e7a5e8dfae4f9e4604906a6ethestig@chromium.org
5398dafdc96be95b51813d58a68213457925520bc8bevan@chromium.orgSHARED_FOOTER = """\
540af505fc205d556ae109fcdfb058eefff43de3a8dmmoss@chromium.org# "all" is a concatenation of the "all" targets from all the included
541af505fc205d556ae109fcdfb058eefff43de3a8dmmoss@chromium.org# sub-makefiles. This is just here to clarify.
542af505fc205d556ae109fcdfb058eefff43de3a8dmmoss@chromium.orgall:
5436009df71af8265c57676984165e9547b467a8f98evan@chromium.org
54403f47b7c86543b4d1170c8bf18028b227f0af9d4piman@chromium.org# Add in dependency-tracking rules.  $(all_deps) is the list of every single
5459a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org# target in our tree. Only consider the ones with .d (dependency) info:
5460b39bcb204e7529ad49870fcd823c19d6b462e28mmoss@chromium.orgd_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
5478dafdc96be95b51813d58a68213457925520bc8bevan@chromium.orgifneq ($(d_files),)
5483c02308fe834c7af49f1557ac3d56be58a9b1fc7tony@chromium.org  include $(d_files)
5498dafdc96be95b51813d58a68213457925520bc8bevan@chromium.orgendif
5508dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org"""
5518dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
55297d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.orgheader = """\
5538dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# This file is generated by gyp; do not edit.
55497d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.org
55597d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.org"""
55697d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.org
55766e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org# Maps every compilable file extension to the do_cmd that compiles it.
55866e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.orgCOMPILABLE_EXTENSIONS = {
55966e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org  '.c': 'cc',
56066e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org  '.cc': 'cxx',
56166e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org  '.cpp': 'cxx',
56266e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org  '.cxx': 'cxx',
56366e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org  '.s': 'cc',
56466e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org  '.S': 'cc',
56566e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org}
566bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org
567bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.orgdef Compilable(filename):
568bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org  """Return true if the file is compilable (should be in OBJS)."""
56966e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org  for res in (filename.endswith(e) for e in COMPILABLE_EXTENSIONS):
570a54d88790b76151b535afff679b3d7e08c10cbf5mmoss@chromium.org    if res:
571a54d88790b76151b535afff679b3d7e08c10cbf5mmoss@chromium.org      return True
572a54d88790b76151b535afff679b3d7e08c10cbf5mmoss@chromium.org  return False
573bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org
574bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org
57545b37dde770ebc775202a675c6a42a50c72d2a07evan@chromium.orgdef Linkable(filename):
57645b37dde770ebc775202a675c6a42a50c72d2a07evan@chromium.org  """Return true if the file is linkable (should be on the link line)."""
57745b37dde770ebc775202a675c6a42a50c72d2a07evan@chromium.org  return filename.endswith('.o')
57845b37dde770ebc775202a675c6a42a50c72d2a07evan@chromium.org
57945b37dde770ebc775202a675c6a42a50c72d2a07evan@chromium.org
580bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.orgdef Target(filename):
581bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org  """Translate a compilable filename to its .o target."""
582bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org  return os.path.splitext(filename)[0] + '.o'
583bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org
584bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org
585e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.orgdef EscapeShellArgument(s):
586e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org  """Quotes an argument so that it will be interpreted literally by a POSIX
587e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org     shell. Taken from
588e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org     http://stackoverflow.com/questions/35817/whats-the-best-way-to-escape-ossystem-calls-in-python
589e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org     """
590e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org  return "'" + s.replace("'", "'\\''") + "'"
591e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org
592e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org
593e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.orgdef EscapeMakeVariableExpansion(s):
594e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org  """Make has its own variable expansion syntax using $. We must escape it for
595e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org     string to be interpreted literally."""
596e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org  return s.replace('$', '$$')
597e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org
598e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org
599e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.orgdef EscapeCppDefine(s):
600e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org  """Escapes a CPP define so that it will reach the compiler unaltered."""
601e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org  s = EscapeShellArgument(s)
602e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org  s = EscapeMakeVariableExpansion(s)
60363c3cfb35a2f1bdfc0362b626f2b2375804188bethakis@chromium.org  # '#' characters must be escaped even embedded in a string, else Make will
60463c3cfb35a2f1bdfc0362b626f2b2375804188bethakis@chromium.org  # treat it as the start of a comment.
60563c3cfb35a2f1bdfc0362b626f2b2375804188bethakis@chromium.org  return s.replace('#', r'\#')
606e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org
607e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org
6088dafdc96be95b51813d58a68213457925520bc8bevan@chromium.orgdef QuoteIfNecessary(string):
609e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org  """TODO: Should this ideally be replaced with one or more of the above
610e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org     functions?"""
6118dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org  if '"' in string:
6128dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org    string = '"' + string.replace('"', '\\"') + '"'
6138dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org  return string
6148dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
6158dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
6162dd4a7ac7ab6c06d18f65f74854b289a6db5f364evan@chromium.orgdef StringToMakefileVariable(string):
6172dd4a7ac7ab6c06d18f65f74854b289a6db5f364evan@chromium.org  """Convert a string to a value that is acceptable as a make variable name."""
618e7771c0907843e73a75222a2bde44c0cdfe3f6a7thakis@chromium.org  return re.sub('[^a-zA-Z0-9_]', '_', string)
6192dd4a7ac7ab6c06d18f65f74854b289a6db5f364evan@chromium.org
6202dd4a7ac7ab6c06d18f65f74854b289a6db5f364evan@chromium.org
621bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.orgsrcdir_prefix = ''
622bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.orgdef Sourceify(path):
623bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org  """Convert a path to its source directory form."""
624bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org  if '$(' in path:
625bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org    return path
62607b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org  if os.path.isabs(path):
62707b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org    return path
628bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org  return srcdir_prefix + path
629bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org
63097d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.org
631abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.orgdef QuoteSpaces(s, quote=r'\ '):
632abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org  return s.replace(' ', quote)
6339a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org
6349a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org
6351c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org# TODO: Avoid code duplication with _ValidateSourcesForMSVSProject in msvs.py.
6361c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.orgdef _ValidateSourcesForOSX(spec, all_sources):
6371c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  """Makes sure if duplicate basenames are not specified in the source list.
6381c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org
6391c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  Arguments:
6401c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org    spec: The target dictionary containing the properties of the target.
6411c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  """
6421c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  if spec.get('type', None) != 'static_library':
6431c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org    return
6441c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org
6451c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  basenames = {}
6461c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  for source in all_sources:
6471c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org    name, ext = os.path.splitext(source)
6481c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org    is_compiled_file = ext in [
6491c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org        '.c', '.cc', '.cpp', '.cxx', '.m', '.mm', '.s', '.S']
6501c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org    if not is_compiled_file:
6511c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org      continue
6521c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org    basename = os.path.basename(name)  # Don't include extension.
6531c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org    basenames.setdefault(basename, []).append(source)
6541c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org
6551c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  error = ''
6561c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  for basename, files in basenames.iteritems():
6571c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org    if len(files) > 1:
6581c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org      error += '  %s: %s\n' % (basename, ' '.join(files))
6591c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org
6601c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org  if error:
6611c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org    print('static library %s has several files with the same basename:\n' %
6621c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org          spec['target_name'] + error + 'libtool on OS X will generate' +
6631c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org          ' warnings for them.')
6641c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org    raise GypError('Duplicate basenames in sources section, see list above')
6651c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org
6661c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org
6678dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# Map from qualified target to path to output.
6688dafdc96be95b51813d58a68213457925520bc8bevan@chromium.orgtarget_outputs = {}
669afa3616bae66f1b500fe9c481cd9436a607f4546evan@chromium.org# Map from qualified target to any linkable output.  A subset
670afa3616bae66f1b500fe9c481cd9436a607f4546evan@chromium.org# of target_outputs.  E.g. when mybinary depends on liba, we want to
671afa3616bae66f1b500fe9c481cd9436a607f4546evan@chromium.org# include liba in the linker line; when otherbinary depends on
672afa3616bae66f1b500fe9c481cd9436a607f4546evan@chromium.org# mybinary, we just want to build mybinary first.
673f7c521353bb53562927effc6f87a42d216bf3973evan@chromium.orgtarget_link_deps = {}
674f7c521353bb53562927effc6f87a42d216bf3973evan@chromium.org
675bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org
6760a445a124e9b7e1069bc405746036256bc515f17evan@chromium.orgclass MakefileWriter:
6777a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org  """MakefileWriter packages up the writing of one target-specific foobar.mk.
6787a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org
6797a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org  Its only real entry point is Write(), and is mostly used for namespacing.
6807a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org  """
6817a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org
682c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org  def __init__(self, generator_flags, flavor):
683bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    self.generator_flags = generator_flags
684c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    self.flavor = flavor
6856997374fe9106a1bd5986b80deb898f06cfe59c9tony@chromium.org
6867510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org    self.suffix_rules_srcdir = {}
6877510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org    self.suffix_rules_objdir1 = {}
6887510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org    self.suffix_rules_objdir2 = {}
6897510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org
6907510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org    # Generate suffix rules for all compilable extensions.
6917510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org    for ext in COMPILABLE_EXTENSIONS.keys():
6927510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org      # Suffix rules for source folder.
6937510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org      self.suffix_rules_srcdir.update({ext: ("""\
694023d71b91d502f776f67c9fced435601070a4349evan@chromium.org$(obj).$(TOOLSET)/$(TARGET)/%%.o: $(srcdir)/%%%s FORCE_DO_CMD
6957510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org	@$(call do_cmd,%s,1)
6967510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org""" % (ext, COMPILABLE_EXTENSIONS[ext]))})
6977510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org
6987510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org      # Suffix rules for generated source files.
6997510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org      self.suffix_rules_objdir1.update({ext: ("""\
700023d71b91d502f776f67c9fced435601070a4349evan@chromium.org$(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD
7017510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org	@$(call do_cmd,%s,1)
7027510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org""" % (ext, COMPILABLE_EXTENSIONS[ext]))})
7037510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org      self.suffix_rules_objdir2.update({ext: ("""\
704023d71b91d502f776f67c9fced435601070a4349evan@chromium.org$(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
7057510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org	@$(call do_cmd,%s,1)
7067510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org""" % (ext, COMPILABLE_EXTENSIONS[ext]))})
7077510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org
7086997374fe9106a1bd5986b80deb898f06cfe59c9tony@chromium.org
709b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com  def Write(self, qualified_target, base_path, output_filename, spec, configs,
710b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com            part_of_all):
711bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org    """The main entry point: writes a .mk file for a single target.
712bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org
713bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org    Arguments:
714bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org      qualified_target: target we're generating
7150a7b25b553ea0b2519ea5d24289e7c1542ddaeb0mmoss@chromium.org      base_path: path relative to source root we're building in, used to resolve
716bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org                 target-relative paths
717bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org      output_filename: output .mk file name to write
718bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org      spec, configs: gyp info
719b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com      part_of_all: flag indicating this target is part of 'all'
720bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org    """
721b5a494899379867f5445f29db21fb2b8e5e8e03ethakis@chromium.org    gyp.common.EnsureDirExists(output_filename)
722bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org
7230a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    self.fp = open(output_filename, 'w')
724566665e8b48bfd0b449acb2e7b55e6029422c85aevan@chromium.org
7250a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    self.fp.write(header)
726566665e8b48bfd0b449acb2e7b55e6029422c85aevan@chromium.org
727159fe3f09a7398b3bf48200855888596c1b95110steveblock@chromium.org    self.qualified_target = qualified_target
728bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org    self.path = base_path
7290a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    self.target = spec['target_name']
7308df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    self.type = spec['type']
731821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com    self.toolset = spec['toolset']
732566665e8b48bfd0b449acb2e7b55e6029422c85aevan@chromium.org
733defcefd76cbddf093d849932c8e22f303335900dthakis@chromium.org    self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec)
73428ba6ec3471076cb3b19404b1990bef8b5833579thakis@chromium.org    if self.flavor == 'mac':
7350839e68998d2c8e8f10ff21e648136f220fddd26thakis@chromium.org      self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec)
736a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org    else:
737a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      self.xcode_settings = None
73828ba6ec3471076cb3b19404b1990bef8b5833579thakis@chromium.org
7398df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    deps, link_deps = self.ComputeDeps(spec)
7408df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org
7418df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    # Some of the generation below can add extra output, sources, or
7428df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    # link dependencies.  All of the out params of the functions that
7438df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    # follow use names like extra_foo.
7440a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    extra_outputs = []
7450a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    extra_sources = []
7468df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    extra_link_deps = []
7471ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org    extra_mac_bundle_resources = []
7481ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org    mac_bundle_deps = []
749566665e8b48bfd0b449acb2e7b55e6029422c85aevan@chromium.org
750f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org    if self.is_mac_bundle:
751f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      self.output = self.ComputeMacBundleOutput(spec)
752f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      self.output_binary = self.ComputeMacBundleBinaryOutput(spec)
753f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org    else:
754f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      self.output = self.output_binary = self.ComputeOutput(spec)
755f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org
756012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org    self.is_standalone_static_library = bool(
757012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org        spec.get('standalone_static_library', 0))
75813379d1679cf70f1425b6e741146b5f16963b265mmoss@chromium.org    self._INSTALLABLE_TARGETS = ('executable', 'loadable_module',
75913379d1679cf70f1425b6e741146b5f16963b265mmoss@chromium.org                                 'shared_library')
760012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org    if (self.is_standalone_static_library or
761012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org        self.type in self._INSTALLABLE_TARGETS):
762ab7c2dc35ce946ca57160d40607d4a5c8cc107c4thestig@chromium.org      self.alias = os.path.basename(self.output)
763f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org      install_path = self._InstallableTargetInstallPath()
764ab7c2dc35ce946ca57160d40607d4a5c8cc107c4thestig@chromium.org    else:
765ab7c2dc35ce946ca57160d40607d4a5c8cc107c4thestig@chromium.org      self.alias = self.output
766f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org      install_path = self.output
7678dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
768023d71b91d502f776f67c9fced435601070a4349evan@chromium.org    self.WriteLn("TOOLSET := " + self.toolset)
76987be65c3b2317afa26563f0cf0ab7431646c2657mmoss@chromium.org    self.WriteLn("TARGET := " + self.target)
7702861b6b6fed0f0d5e7a5e8dfae4f9e4604906a6ethestig@chromium.org
7710a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    # Actions must come first, since they can generate more OBJs for use below.
7720a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    if 'actions' in spec:
773b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com      self.WriteActions(spec['actions'], extra_sources, extra_outputs,
77426afc55b55209b530f56b79693c52be4e8ff1ecdthakis@chromium.org                        extra_mac_bundle_resources, part_of_all)
7758dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
7760a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    # Rules must be early like actions.
7770a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    if 'rules' in spec:
7781ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org      self.WriteRules(spec['rules'], extra_sources, extra_outputs,
7791ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org                      extra_mac_bundle_resources, part_of_all)
7808dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
7810a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    if 'copies' in spec:
78226afc55b55209b530f56b79693c52be4e8ff1ecdthakis@chromium.org      self.WriteCopies(spec['copies'], extra_outputs, part_of_all)
783566665e8b48bfd0b449acb2e7b55e6029422c85aevan@chromium.org
7841ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org    # Bundle resources.
78528ba6ec3471076cb3b19404b1990bef8b5833579thakis@chromium.org    if self.is_mac_bundle:
78628ba6ec3471076cb3b19404b1990bef8b5833579thakis@chromium.org      all_mac_bundle_resources = (
78728ba6ec3471076cb3b19404b1990bef8b5833579thakis@chromium.org          spec.get('mac_bundle_resources', []) + extra_mac_bundle_resources)
78826afc55b55209b530f56b79693c52be4e8ff1ecdthakis@chromium.org      self.WriteMacBundleResources(all_mac_bundle_resources, mac_bundle_deps)
78926afc55b55209b530f56b79693c52be4e8ff1ecdthakis@chromium.org      self.WriteMacInfoPlist(mac_bundle_deps)
7901ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org
7918347e3181c4b66aeb0a2e86c551f609b645f806dthakis@chromium.org    # Sources.
792aa7a2b2719790ca50ac51b8a5b47f460090f7e22piman@chromium.org    all_sources = spec.get('sources', []) + extra_sources
793aa7a2b2719790ca50ac51b8a5b47f460090f7e22piman@chromium.org    if all_sources:
7941c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org      if self.flavor == 'mac':
7951c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org        # libtool on OS X generates warnings for duplicate basenames in the same
7961c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org        # target.
7971c4be478a439eaaf11fba83e4a35f4926a21a1b9yukawa@chromium.org        _ValidateSourcesForOSX(spec, all_sources)
7988347e3181c4b66aeb0a2e86c551f609b645f806dthakis@chromium.org      self.WriteSources(
7998347e3181c4b66aeb0a2e86c551f609b645f806dthakis@chromium.org          configs, deps, all_sources, extra_outputs,
800a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org          extra_link_deps, part_of_all,
801a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org          gyp.xcode_emulation.MacPrefixHeader(
8024d8ab8c5c273662a250ebae3efea2c0368558f32thakis@chromium.org              self.xcode_settings, lambda p: Sourceify(self.Absolutify(p)),
8034d8ab8c5c273662a250ebae3efea2c0368558f32thakis@chromium.org              self.Pchify))
804aa7a2b2719790ca50ac51b8a5b47f460090f7e22piman@chromium.org      sources = filter(Compilable, all_sources)
805aa7a2b2719790ca50ac51b8a5b47f460090f7e22piman@chromium.org      if sources:
806aa7a2b2719790ca50ac51b8a5b47f460090f7e22piman@chromium.org        self.WriteLn(SHARED_HEADER_SUFFIX_RULES_COMMENT1)
807aa7a2b2719790ca50ac51b8a5b47f460090f7e22piman@chromium.org        extensions = set([os.path.splitext(s)[1] for s in sources])
808aa7a2b2719790ca50ac51b8a5b47f460090f7e22piman@chromium.org        for ext in extensions:
8097510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org          if ext in self.suffix_rules_srcdir:
8107510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org            self.WriteLn(self.suffix_rules_srcdir[ext])
811aa7a2b2719790ca50ac51b8a5b47f460090f7e22piman@chromium.org        self.WriteLn(SHARED_HEADER_SUFFIX_RULES_COMMENT2)
812aa7a2b2719790ca50ac51b8a5b47f460090f7e22piman@chromium.org        for ext in extensions:
8137510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org          if ext in self.suffix_rules_objdir1:
8147510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org            self.WriteLn(self.suffix_rules_objdir1[ext])
815aa7a2b2719790ca50ac51b8a5b47f460090f7e22piman@chromium.org        for ext in extensions:
8167510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org          if ext in self.suffix_rules_objdir2:
8177510724f34edeb0f2ecdbff383bc273147b82ad4hclam@chromium.org            self.WriteLn(self.suffix_rules_objdir2[ext])
818aa7a2b2719790ca50ac51b8a5b47f460090f7e22piman@chromium.org        self.WriteLn('# End of this set of suffix rules')
819aa7a2b2719790ca50ac51b8a5b47f460090f7e22piman@chromium.org
820f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org        # Add dependency from bundle to bundle binary.
821f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org        if self.is_mac_bundle:
822f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org          mac_bundle_deps.append(self.output_binary)
823f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org
824f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org    self.WriteTarget(spec, configs, deps, extra_link_deps + link_deps,
825f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org                     mac_bundle_deps, extra_outputs, part_of_all)
82697d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.org
8278df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    # Update global list of target outputs, used in dependency tracking.
828f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org    target_outputs[qualified_target] = install_path
82997d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.org
8308df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    # Update global list of link dependencies.
831afa3616bae66f1b500fe9c481cd9436a607f4546evan@chromium.org    if self.type in ('static_library', 'shared_library'):
832f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      target_link_deps[qualified_target] = self.output_binary
8338df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org
834c182bea2df1ac9c9375e486e48a2ddeabb299b02evan@chromium.org    # Currently any versions have the same effect, but in future the behavior
835c182bea2df1ac9c9375e486e48a2ddeabb299b02evan@chromium.org    # could be different.
836c182bea2df1ac9c9375e486e48a2ddeabb299b02evan@chromium.org    if self.generator_flags.get('android_ndk_version', None):
837c182bea2df1ac9c9375e486e48a2ddeabb299b02evan@chromium.org      self.WriteAndroidNdkModuleRule(self.target, all_sources, link_deps)
838c182bea2df1ac9c9375e486e48a2ddeabb299b02evan@chromium.org
8398df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    self.fp.close()
8408dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
8418dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
842b9cd14d164cfa90a6da1808b103f4717e353044fmmoss@chromium.org  def WriteSubMake(self, output_filename, makefile_path, targets, build_dir):
8438f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    """Write a "sub-project" Makefile.
8448f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org
8458f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    This is a small, wrapper Makefile that calls the top-level Makefile to build
8468f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    the targets from a single gyp file (i.e. a sub-project).
8478f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org
8488f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    Arguments:
8498f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org      output_filename: sub-project Makefile name to write
8508f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org      makefile_path: path to the top-level Makefile
8518f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org      targets: list of "all" targets for this sub-project
852b9cd14d164cfa90a6da1808b103f4717e353044fmmoss@chromium.org      build_dir: build output directory, relative to the sub-project
8538f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    """
854b5a494899379867f5445f29db21fb2b8e5e8e03ethakis@chromium.org    gyp.common.EnsureDirExists(output_filename)
8558f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    self.fp = open(output_filename, 'w')
8568f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    self.fp.write(header)
857b9cd14d164cfa90a6da1808b103f4717e353044fmmoss@chromium.org    # For consistency with other builders, put sub-project build output in the
858b9cd14d164cfa90a6da1808b103f4717e353044fmmoss@chromium.org    # sub-project dir (see test/subdirectory/gyptest-subdir-all.py).
859b9cd14d164cfa90a6da1808b103f4717e353044fmmoss@chromium.org    self.WriteLn('export builddir_name ?= %s' %
860b9cd14d164cfa90a6da1808b103f4717e353044fmmoss@chromium.org                 os.path.join(os.path.dirname(output_filename), build_dir))
8618f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    self.WriteLn('.PHONY: all')
8628f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    self.WriteLn('all:')
8638f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    if makefile_path:
8648f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org      makefile_path = ' -C ' + makefile_path
8658f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    self.WriteLn('\t$(MAKE)%s %s' % (makefile_path, ' '.join(targets)))
8668f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    self.fp.close()
8678f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org
8688f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org
8691ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org  def WriteActions(self, actions, extra_sources, extra_outputs,
87026afc55b55209b530f56b79693c52be4e8ff1ecdthakis@chromium.org                   extra_mac_bundle_resources, part_of_all):
8717a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """Write Makefile code for any 'actions' from the gyp input.
8727a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org
8737a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    extra_sources: a list that will be filled in with newly generated source
8747a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org                   files, if any
8757a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    extra_outputs: a list that will be filled in with any outputs of these
8767a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org                   actions (used to make other pieces dependent on these
8777a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org                   actions)
878b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com    part_of_all: flag indicating this target is part of 'all'
8797a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """
8807d3e822ae6077e22879aa1c937f53e02bf035a23thakis@chromium.org    env = self.GetSortedXcodeEnv()
8810a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    for action in actions:
882159fe3f09a7398b3bf48200855888596c1b95110steveblock@chromium.org      name = StringToMakefileVariable('%s_%s' % (self.qualified_target,
883159fe3f09a7398b3bf48200855888596c1b95110steveblock@chromium.org                                                 action['action_name']))
8840a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      self.WriteLn('### Rules for action "%s":' % action['action_name'])
88575a14aafd47250072bfabc17dd4ca75dd4d1be8bagl@chromium.org      inputs = action['inputs']
88675a14aafd47250072bfabc17dd4ca75dd4d1be8bagl@chromium.org      outputs = action['outputs']
8878dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
8888dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org      # Build up a list of outputs.
8898dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org      # Collect the output dirs we'll need.
8908dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org      dirs = set()
8916de9a38e7fe077206c13d9c16302156778552f49thestig@chromium.org      for out in outputs:
8926009df71af8265c57676984165e9547b467a8f98evan@chromium.org        dir = os.path.split(out)[0]
8936009df71af8265c57676984165e9547b467a8f98evan@chromium.org        if dir:
8946009df71af8265c57676984165e9547b467a8f98evan@chromium.org          dirs.add(dir)
895ca359a77c83539ba95896309f9aacc0ba6180868mark@chromium.org      if int(action.get('process_outputs_as_sources', False)):
8968dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org        extra_sources += outputs
8971ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org      if int(action.get('process_outputs_as_mac_bundle_resources', False)):
8981925f1101c823ce43ee2e55b9a6c7b897feb2479thakis@chromium.org        extra_mac_bundle_resources += outputs
8998dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
9008dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org      # Write the actual command.
9017d3e822ae6077e22879aa1c937f53e02bf035a23thakis@chromium.org      action_commands = action['action']
9027d3e822ae6077e22879aa1c937f53e02bf035a23thakis@chromium.org      if self.flavor == 'mac':
9037d3e822ae6077e22879aa1c937f53e02bf035a23thakis@chromium.org        action_commands = [gyp.xcode_emulation.ExpandEnvVars(command, env)
9047d3e822ae6077e22879aa1c937f53e02bf035a23thakis@chromium.org                          for command in action_commands]
9057d3e822ae6077e22879aa1c937f53e02bf035a23thakis@chromium.org      command = gyp.common.EncodePOSIXShellList(action_commands)
9068dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org      if 'message' in action:
9070a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org        self.WriteLn('quiet_cmd_%s = ACTION %s $@' % (name, action['message']))
9088dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org      else:
9090a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org        self.WriteLn('quiet_cmd_%s = ACTION %s $@' % (name, name))
9108dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org      if len(dirs) > 0:
9118dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org        command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command
91240b0efc2e5b475b4a3ef715fb307eda31e8f4132evan@chromium.org
91340b0efc2e5b475b4a3ef715fb307eda31e8f4132evan@chromium.org      cd_action = 'cd %s; ' % Sourceify(self.path or '.')
91440b0efc2e5b475b4a3ef715fb307eda31e8f4132evan@chromium.org
915fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org      # command and cd_action get written to a toplevel variable called
916fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org      # cmd_foo. Toplevel variables can't handle things that change per
917fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org      # makefile like $(TARGET), so hardcode the target.
918fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org      command = command.replace('$(TARGET)', self.target)
919fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org      cd_action = cd_action.replace('$(TARGET)', self.target)
920fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org
92113379d1679cf70f1425b6e741146b5f16963b265mmoss@chromium.org      # Set LD_LIBRARY_PATH in case the action runs an executable from this
92213379d1679cf70f1425b6e741146b5f16963b265mmoss@chromium.org      # build which links to shared libs from this build.
92310fa6d18d83a0a74ac080734eaa5fedbb9360320piman@chromium.org      # actions run on the host, so they should in theory only use host
92410fa6d18d83a0a74ac080734eaa5fedbb9360320piman@chromium.org      # libraries, but until everything is made cross-compile safe, also use
92510fa6d18d83a0a74ac080734eaa5fedbb9360320piman@chromium.org      # target libraries.
92610fa6d18d83a0a74ac080734eaa5fedbb9360320piman@chromium.org      # TODO(piman): when everything is cross-compile safe, remove lib.target
927ca1535abf2e29d97b0f9ec47aa40dbae7e548e7atony@chromium.org      self.WriteLn('cmd_%s = LD_LIBRARY_PATH=$(builddir)/lib.host:'
928ca1535abf2e29d97b0f9ec47aa40dbae7e548e7atony@chromium.org                   '$(builddir)/lib.target:$$LD_LIBRARY_PATH; '
929ca1535abf2e29d97b0f9ec47aa40dbae7e548e7atony@chromium.org                   'export LD_LIBRARY_PATH; '
930ca1535abf2e29d97b0f9ec47aa40dbae7e548e7atony@chromium.org                   '%s%s'
93158abd1795068b1ec2800790ea337480773d54ef0thestig@chromium.org                   % (name, cd_action, command))
9320a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      self.WriteLn()
9336009df71af8265c57676984165e9547b467a8f98evan@chromium.org      outputs = map(self.Absolutify, outputs)
9346009df71af8265c57676984165e9547b467a8f98evan@chromium.org      # The makefile rules are all relative to the top dir, but the gyp actions
9356009df71af8265c57676984165e9547b467a8f98evan@chromium.org      # are defined relative to their containing dir.  This replaces the obj
9366009df71af8265c57676984165e9547b467a8f98evan@chromium.org      # variable for the action rule with an absolute version so that the output
9376009df71af8265c57676984165e9547b467a8f98evan@chromium.org      # goes in the right place.
9384155edc7a92a7ea77fdcc74dfe54e3c9d445553cmmoss@chromium.org      # Only write the 'obj' and 'builddir' rules for the "primary" output (:1);
9394155edc7a92a7ea77fdcc74dfe54e3c9d445553cmmoss@chromium.org      # it's superfluous for the "extra outputs", and this avoids accidentally
9404155edc7a92a7ea77fdcc74dfe54e3c9d445553cmmoss@chromium.org      # writing duplicate dummy rules for those outputs.
9416377b5422801f251819bfcf4761e60a6391a8522thakis@chromium.org      # Same for environment.
942abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org      self.WriteLn("%s: obj := $(abs_obj)" % QuoteSpaces(outputs[0]))
943abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org      self.WriteLn("%s: builddir := $(abs_builddir)" % QuoteSpaces(outputs[0]))
944477539a34ba23693c5d7ca49d212d9e99e058c02thakis@chromium.org      self.WriteSortedXcodeEnv(outputs[0], self.GetSortedXcodeEnv())
9459a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org
9469a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org      for input in inputs:
9479a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org        assert ' ' not in input, (
9489a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org            "Spaces in action input filenames not supported (%s)"  % input)
9499a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org      for output in outputs:
9509a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org        assert ' ' not in output, (
9519a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org            "Spaces in action output filenames not supported (%s)"  % output)
9529a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org
953c57a88ebac3dddc5bbd496078896b8ec77b1a0f0thakis@chromium.org      # See the comment in WriteCopies about expanding env vars.
9547f8f660af88e9db3860560bce4da85201294350athakis@chromium.org      outputs = [gyp.xcode_emulation.ExpandEnvVars(o, env) for o in outputs]
9557f8f660af88e9db3860560bce4da85201294350athakis@chromium.org      inputs = [gyp.xcode_emulation.ExpandEnvVars(i, env) for i in inputs]
956b69d8712f968628199d5cf927657661b11d05e8bthakis@chromium.org
9570a7b25b553ea0b2519ea5d24289e7c1542ddaeb0mmoss@chromium.org      self.WriteDoCmd(outputs, map(Sourceify, map(self.Absolutify, inputs)),
958b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com                      part_of_all=part_of_all, command=name)
9590a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
9600a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      # Stuff the outputs in a variable so we can refer to them later.
9610a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      outputs_variable = 'action_%s_outputs' % name
96258abd1795068b1ec2800790ea337480773d54ef0thestig@chromium.org      self.WriteLn('%s := %s' % (outputs_variable, ' '.join(outputs)))
9630a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      extra_outputs.append('$(%s)' % outputs_variable)
96424cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org      self.WriteLn()
9650a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
9660a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    self.WriteLn()
9670a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
9680a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
9691ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org  def WriteRules(self, rules, extra_sources, extra_outputs,
9701ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org                 extra_mac_bundle_resources, part_of_all):
9717a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """Write Makefile code for any 'rules' from the gyp input.
9727a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org
9737a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    extra_sources: a list that will be filled in with newly generated source
9747a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org                   files, if any
9757a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    extra_outputs: a list that will be filled in with any outputs of these
9767a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org                   rules (used to make other pieces dependent on these rules)
977b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com    part_of_all: flag indicating this target is part of 'all'
9787a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """
979ca4d672bb96a8ae94f2b4c80168e236ef6bc80edthakis@chromium.org    env = self.GetSortedXcodeEnv()
9800a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    for rule in rules:
981159fe3f09a7398b3bf48200855888596c1b95110steveblock@chromium.org      name = StringToMakefileVariable('%s_%s' % (self.qualified_target,
982159fe3f09a7398b3bf48200855888596c1b95110steveblock@chromium.org                                                 rule['rule_name']))
9835fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org      count = 0
9840a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      self.WriteLn('### Generated for rule %s:' % name)
9858dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
9868dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org      all_outputs = []
9878dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
9885bff43ab0cb11dfc9be2f7a1f8da961c5ff35c92bradnelson@google.com      for rule_source in rule.get('rule_sources', []):
9895fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org        dirs = set()
990cdaa7e6d2e12c7d592265333396c6d1307632e22scr@chromium.org        (rule_source_dirname, rule_source_basename) = os.path.split(rule_source)
9918dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org        (rule_source_root, rule_source_ext) = \
9928dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org            os.path.splitext(rule_source_basename)
9938dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
994cdaa7e6d2e12c7d592265333396c6d1307632e22scr@chromium.org        outputs = [self.ExpandInputRoot(out, rule_source_root,
995cdaa7e6d2e12c7d592265333396c6d1307632e22scr@chromium.org                                        rule_source_dirname)
9965fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org                   for out in rule['outputs']]
99724ab002e4da1a23547cfe42ff4d7145c1537d1c0thakis@chromium.org
9988dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org        for out in outputs:
9995fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org          dir = os.path.dirname(out)
10005fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org          if dir:
10015fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org            dirs.add(dir)
10021925f1101c823ce43ee2e55b9a6c7b897feb2479thakis@chromium.org        if int(rule.get('process_outputs_as_sources', False)):
10031925f1101c823ce43ee2e55b9a6c7b897feb2479thakis@chromium.org          extra_sources += outputs
10041925f1101c823ce43ee2e55b9a6c7b897feb2479thakis@chromium.org        if int(rule.get('process_outputs_as_mac_bundle_resources', False)):
10051925f1101c823ce43ee2e55b9a6c7b897feb2479thakis@chromium.org          extra_mac_bundle_resources += outputs
10068e2ab1cd9cc50f54d97914eef6295b041de21571mmoss@chromium.org        inputs = map(Sourceify, map(self.Absolutify, [rule_source] +
10078e2ab1cd9cc50f54d97914eef6295b041de21571mmoss@chromium.org                                    rule.get('inputs', [])))
10085fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org        actions = ['$(call do_cmd,%s_%d)' % (name, count)]
10090a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
10107fe09eea54741b72acf682c5fcc78b72448ca8ceevan@chromium.org        if name == 'resources_grit':
10117fe09eea54741b72acf682c5fcc78b72448ca8ceevan@chromium.org          # HACK: This is ugly.  Grit intentionally doesn't touch the
10127fe09eea54741b72acf682c5fcc78b72448ca8ceevan@chromium.org          # timestamp of its output file when the file doesn't change,
10137fe09eea54741b72acf682c5fcc78b72448ca8ceevan@chromium.org          # which is fine in hash-based dependency systems like scons
10147fe09eea54741b72acf682c5fcc78b72448ca8ceevan@chromium.org          # and forge, but not kosher in the make world.  After some
10157fe09eea54741b72acf682c5fcc78b72448ca8ceevan@chromium.org          # discussion, hacking around it here seems like the least
10167fe09eea54741b72acf682c5fcc78b72448ca8ceevan@chromium.org          # amount of pain.
10170a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org          actions += ['@touch --no-create $@']
10180a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
1019ca4d672bb96a8ae94f2b4c80168e236ef6bc80edthakis@chromium.org        # See the comment in WriteCopies about expanding env vars.
1020ca4d672bb96a8ae94f2b4c80168e236ef6bc80edthakis@chromium.org        outputs = [gyp.xcode_emulation.ExpandEnvVars(o, env) for o in outputs]
1021ca4d672bb96a8ae94f2b4c80168e236ef6bc80edthakis@chromium.org        inputs = [gyp.xcode_emulation.ExpandEnvVars(i, env) for i in inputs]
1022ca4d672bb96a8ae94f2b4c80168e236ef6bc80edthakis@chromium.org
1023ba7d1a2a10920fe6675bc61dd4b4237f39ba7493thakis@chromium.org        outputs = map(self.Absolutify, outputs)
1024ba7d1a2a10920fe6675bc61dd4b4237f39ba7493thakis@chromium.org        all_outputs += outputs
10254155edc7a92a7ea77fdcc74dfe54e3c9d445553cmmoss@chromium.org        # Only write the 'obj' and 'builddir' rules for the "primary" output
10264155edc7a92a7ea77fdcc74dfe54e3c9d445553cmmoss@chromium.org        # (:1); it's superfluous for the "extra outputs", and this avoids
10274155edc7a92a7ea77fdcc74dfe54e3c9d445553cmmoss@chromium.org        # accidentally writing duplicate dummy rules for those outputs.
1028abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org        self.WriteLn('%s: obj := $(abs_obj)' % outputs[0])
1029abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org        self.WriteLn('%s: builddir := $(abs_builddir)' % outputs[0])
103024cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org        self.WriteMakeRule(outputs, inputs + ['FORCE_DO_CMD'], actions)
103110ee636f7e461c819a6d23dac93c4bfe871ee8debungeman@chromium.org        # Spaces in rule filenames are not supported, but rule variables have
103210ee636f7e461c819a6d23dac93c4bfe871ee8debungeman@chromium.org        # spaces in them (e.g. RULE_INPUT_PATH expands to '$(abspath $<)').
103310ee636f7e461c819a6d23dac93c4bfe871ee8debungeman@chromium.org        # The spaces within the variables are valid, so remove the variables
103410ee636f7e461c819a6d23dac93c4bfe871ee8debungeman@chromium.org        # before checking.
103510ee636f7e461c819a6d23dac93c4bfe871ee8debungeman@chromium.org        variables_with_spaces = re.compile(r'\$\([^ ]* \$<\)')
10369a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org        for output in outputs:
103710ee636f7e461c819a6d23dac93c4bfe871ee8debungeman@chromium.org          output = re.sub(variables_with_spaces, '', output)
10389a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org          assert ' ' not in output, (
10399a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org              "Spaces in rule filenames not yet supported (%s)"  % output)
104003f47b7c86543b4d1170c8bf18028b227f0af9d4piman@chromium.org        self.WriteLn('all_deps += %s' % ' '.join(outputs))
10418dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
1042cdaa7e6d2e12c7d592265333396c6d1307632e22scr@chromium.org        action = [self.ExpandInputRoot(ac, rule_source_root,
1043cdaa7e6d2e12c7d592265333396c6d1307632e22scr@chromium.org                                       rule_source_dirname)
10445fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org                  for ac in rule['action']]
10455fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org        mkdirs = ''
10465fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org        if len(dirs) > 0:
10475fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org          mkdirs = 'mkdir -p %s; ' % ' '.join(dirs)
104840b0efc2e5b475b4a3ef715fb307eda31e8f4132evan@chromium.org        cd_action = 'cd %s; ' % Sourceify(self.path or '.')
1049fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org
1050fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org        # action, cd_action, and mkdirs get written to a toplevel variable
1051fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org        # called cmd_foo. Toplevel variables can't handle things that change
1052fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org        # per makefile like $(TARGET), so hardcode the target.
1053ca4d672bb96a8ae94f2b4c80168e236ef6bc80edthakis@chromium.org        if self.flavor == 'mac':
1054ca4d672bb96a8ae94f2b4c80168e236ef6bc80edthakis@chromium.org          action = [gyp.xcode_emulation.ExpandEnvVars(command, env)
1055ca4d672bb96a8ae94f2b4c80168e236ef6bc80edthakis@chromium.org                    for command in action]
1056fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org        action = gyp.common.EncodePOSIXShellList(action)
1057fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org        action = action.replace('$(TARGET)', self.target)
1058fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org        cd_action = cd_action.replace('$(TARGET)', self.target)
1059fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org        mkdirs = mkdirs.replace('$(TARGET)', self.target)
1060fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org
1061c71318854e624daa273f4ea793b6c052122acad3mmoss@chromium.org        # Set LD_LIBRARY_PATH in case the rule runs an executable from this
1062c71318854e624daa273f4ea793b6c052122acad3mmoss@chromium.org        # build which links to shared libs from this build.
1063c71318854e624daa273f4ea793b6c052122acad3mmoss@chromium.org        # rules run on the host, so they should in theory only use host
1064c71318854e624daa273f4ea793b6c052122acad3mmoss@chromium.org        # libraries, but until everything is made cross-compile safe, also use
1065c71318854e624daa273f4ea793b6c052122acad3mmoss@chromium.org        # target libraries.
1066c71318854e624daa273f4ea793b6c052122acad3mmoss@chromium.org        # TODO(piman): when everything is cross-compile safe, remove lib.target
1067a54d88790b76151b535afff679b3d7e08c10cbf5mmoss@chromium.org        self.WriteLn(
1068ca1535abf2e29d97b0f9ec47aa40dbae7e548e7atony@chromium.org            "cmd_%(name)s_%(count)d = LD_LIBRARY_PATH="
1069c71318854e624daa273f4ea793b6c052122acad3mmoss@chromium.org              "$(builddir)/lib.host:$(builddir)/lib.target:$$LD_LIBRARY_PATH; "
1070ca1535abf2e29d97b0f9ec47aa40dbae7e548e7atony@chromium.org              "export LD_LIBRARY_PATH; "
1071c71318854e624daa273f4ea793b6c052122acad3mmoss@chromium.org              "%(cd_action)s%(mkdirs)s%(action)s" % {
1072fbcd968877bac98d0d6f5f61847c0232939562f4thakis@chromium.org          'action': action,
10738e2ab1cd9cc50f54d97914eef6295b041de21571mmoss@chromium.org          'cd_action': cd_action,
10745fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org          'count': count,
10755fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org          'mkdirs': mkdirs,
10765fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org          'name': name,
10775fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org        })
10785fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org        self.WriteLn(
10795fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org            'quiet_cmd_%(name)s_%(count)d = RULE %(name)s_%(count)d $@' % {
10805fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org          'count': count,
10815fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org          'name': name,
10825fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org        })
10835fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org        self.WriteLn()
10845fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org        count += 1
10858dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
10868dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org      outputs_variable = 'rule_%s_outputs' % name
10870a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      self.WriteList(all_outputs, outputs_variable)
10880a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      extra_outputs.append('$(%s)' % outputs_variable)
10898dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
10905fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org      self.WriteLn('### Finished generating for rule: %s' % name)
10910a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      self.WriteLn()
10925fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org    self.WriteLn('### Finished generating for all rules')
10935fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org    self.WriteLn('')
10948dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
10958dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
109626afc55b55209b530f56b79693c52be4e8ff1ecdthakis@chromium.org  def WriteCopies(self, copies, extra_outputs, part_of_all):
10977a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """Write Makefile code for any 'copies' from the gyp input.
10987a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org
10997a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    extra_outputs: a list that will be filled in with any outputs of this action
1100bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org                   (used to make other pieces dependent on this action)
1101b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com    part_of_all: flag indicating this target is part of 'all'
11027a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """
11030a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    self.WriteLn('### Generated for copy rule.')
11040a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
1105159fe3f09a7398b3bf48200855888596c1b95110steveblock@chromium.org    variable = StringToMakefileVariable(self.qualified_target + '_copies')
11068dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org    outputs = []
11070a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    for copy in copies:
11088dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org      for path in copy['files']:
11091a0fd49a725699cc439ca58aa5aca6c3baa76372thakis@chromium.org        # Absolutify() may call normpath, and will strip trailing slashes.
1110bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org        path = Sourceify(self.Absolutify(path))
11118dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org        filename = os.path.split(path)[1]
11120a7b25b553ea0b2519ea5d24289e7c1542ddaeb0mmoss@chromium.org        output = Sourceify(self.Absolutify(os.path.join(copy['destination'],
11130a7b25b553ea0b2519ea5d24289e7c1542ddaeb0mmoss@chromium.org                                                        filename)))
11149a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org
11156377b5422801f251819bfcf4761e60a6391a8522thakis@chromium.org        # If the output path has variables in it, which happens in practice for
11166377b5422801f251819bfcf4761e60a6391a8522thakis@chromium.org        # 'copies', writing the environment as target-local doesn't work,
11176377b5422801f251819bfcf4761e60a6391a8522thakis@chromium.org        # because the variables are already needed for the target name.
11186377b5422801f251819bfcf4761e60a6391a8522thakis@chromium.org        # Copying the environment variables into global make variables doesn't
11196377b5422801f251819bfcf4761e60a6391a8522thakis@chromium.org        # work either, because then the .d files will potentially contain spaces
11206377b5422801f251819bfcf4761e60a6391a8522thakis@chromium.org        # after variable expansion, and .d file handling cannot handle spaces.
11216377b5422801f251819bfcf4761e60a6391a8522thakis@chromium.org        # As a workaround, manually expand variables at gyp time. Since 'copies'
11226377b5422801f251819bfcf4761e60a6391a8522thakis@chromium.org        # can't run scripts, there's no need to write the env then.
11236377b5422801f251819bfcf4761e60a6391a8522thakis@chromium.org        # WriteDoCmd() will escape spaces for .d files.
1124477539a34ba23693c5d7ca49d212d9e99e058c02thakis@chromium.org        env = self.GetSortedXcodeEnv()
1125b69d8712f968628199d5cf927657661b11d05e8bthakis@chromium.org        output = gyp.xcode_emulation.ExpandEnvVars(output, env)
1126b69d8712f968628199d5cf927657661b11d05e8bthakis@chromium.org        path = gyp.xcode_emulation.ExpandEnvVars(path, env)
1127b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com        self.WriteDoCmd([output], [path], 'copy', part_of_all)
11288dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org        outputs.append(output)
1129abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org    self.WriteLn('%s = %s' % (variable, ' '.join(map(QuoteSpaces, outputs))))
11300a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    extra_outputs.append('$(%s)' % variable)
11310a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    self.WriteLn()
11320a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
11330a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
113426afc55b55209b530f56b79693c52be4e8ff1ecdthakis@chromium.org  def WriteMacBundleResources(self, resources, bundle_deps):
11351ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org    """Writes Makefile code for 'mac_bundle_resources'."""
11361ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org    self.WriteLn('### Generated for mac_bundle_resources')
1137defcefd76cbddf093d849932c8e22f303335900dthakis@chromium.org
1138defcefd76cbddf093d849932c8e22f303335900dthakis@chromium.org    for output, res in gyp.xcode_emulation.GetMacBundleResources(
1139defcefd76cbddf093d849932c8e22f303335900dthakis@chromium.org        generator_default_variables['PRODUCT_DIR'], self.xcode_settings,
1140defcefd76cbddf093d849932c8e22f303335900dthakis@chromium.org        map(Sourceify, map(self.Absolutify, resources))):
1141defcefd76cbddf093d849932c8e22f303335900dthakis@chromium.org      self.WriteDoCmd([output], [res], 'mac_tool,,,copy-bundle-resource',
11421ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org                      part_of_all=True)
11431ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org      bundle_deps.append(output)
11441ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org
11451ab1ae40a3f391ce073f803793053f27f329eebdthakis@chromium.org
114626afc55b55209b530f56b79693c52be4e8ff1ecdthakis@chromium.org  def WriteMacInfoPlist(self, bundle_deps):
11478083225084fd179e1e6357c09b1f4b4260ad86dbthakis@chromium.org    """Write Makefile code for bundle Info.plist files."""
11484143358985fabc41e9220e0ca415a1e9d858fa92thakis@chromium.org    info_plist, out, defines, extra_env = gyp.xcode_emulation.GetMacInfoPlist(
11494143358985fabc41e9220e0ca415a1e9d858fa92thakis@chromium.org        generator_default_variables['PRODUCT_DIR'], self.xcode_settings,
11504d8ab8c5c273662a250ebae3efea2c0368558f32thakis@chromium.org        lambda p: Sourceify(self.Absolutify(p)))
11514143358985fabc41e9220e0ca415a1e9d858fa92thakis@chromium.org    if not info_plist:
11524143358985fabc41e9220e0ca415a1e9d858fa92thakis@chromium.org      return
11534143358985fabc41e9220e0ca415a1e9d858fa92thakis@chromium.org    if defines:
11544143358985fabc41e9220e0ca415a1e9d858fa92thakis@chromium.org      # Create an intermediate file to store preprocessed results.
1155023d71b91d502f776f67c9fced435601070a4349evan@chromium.org      intermediate_plist = ('$(obj).$(TOOLSET)/$(TARGET)/' +
11566702555b550f751911ec601c8313515ecdb551e0rsesek@chromium.org          os.path.basename(info_plist))
11579180bce76fe181f91e333db46ef78b329058eb40rsesek@chromium.org      self.WriteList(defines, intermediate_plist + ': INFOPLIST_DEFINES', '-D',
11589180bce76fe181f91e333db46ef78b329058eb40rsesek@chromium.org          quoter=EscapeCppDefine)
11596702555b550f751911ec601c8313515ecdb551e0rsesek@chromium.org      self.WriteMakeRule([intermediate_plist], [info_plist],
11606702555b550f751911ec601c8313515ecdb551e0rsesek@chromium.org          ['$(call do_cmd,infoplist)',
11616702555b550f751911ec601c8313515ecdb551e0rsesek@chromium.org           # "Convert" the plist so that any weird whitespace changes from the
11626702555b550f751911ec601c8313515ecdb551e0rsesek@chromium.org           # preprocessor do not affect the XML parser in mac_tool.
11636702555b550f751911ec601c8313515ecdb551e0rsesek@chromium.org           '@plutil -convert xml1 $@ $@'])
11646702555b550f751911ec601c8313515ecdb551e0rsesek@chromium.org      info_plist = intermediate_plist
11654143358985fabc41e9220e0ca415a1e9d858fa92thakis@chromium.org    # plists can contain envvars and substitute them into the file.
1166477539a34ba23693c5d7ca49d212d9e99e058c02thakis@chromium.org    self.WriteSortedXcodeEnv(
1167477539a34ba23693c5d7ca49d212d9e99e058c02thakis@chromium.org        out, self.GetSortedXcodeEnv(additional_settings=extra_env))
11684143358985fabc41e9220e0ca415a1e9d858fa92thakis@chromium.org    self.WriteDoCmd([out], [info_plist], 'mac_tool,,,copy-info-plist',
11698083225084fd179e1e6357c09b1f4b4260ad86dbthakis@chromium.org                    part_of_all=True)
11704143358985fabc41e9220e0ca415a1e9d858fa92thakis@chromium.org    bundle_deps.append(out)
11718083225084fd179e1e6357c09b1f4b4260ad86dbthakis@chromium.org
11728083225084fd179e1e6357c09b1f4b4260ad86dbthakis@chromium.org
11738df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org  def WriteSources(self, configs, deps, sources,
1174b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com                   extra_outputs, extra_link_deps,
11758347e3181c4b66aeb0a2e86c551f609b645f806dthakis@chromium.org                   part_of_all, precompiled_header):
11767a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """Write Makefile code for any 'sources' from the gyp input.
11777a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    These are source files necessary to build the current target.
11787a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org
11797a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    configs, deps, sources: input from gyp.
11807a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    extra_outputs: a list of extra outputs this action should be dependent on;
11817a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org                   used to serialize action/rules before compilation
11827a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    extra_link_deps: a list that will be filled in with any outputs of
11837a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org                     compilation (to be used in link lines)
1184b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com    part_of_all: flag indicating this target is part of 'all'
11857a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """
11867a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org
11870a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    # Write configuration-specific variables for CFLAGS, etc.
11880a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    for configname in sorted(configs.keys()):
11890a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      config = configs[configname]
1190e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org      self.WriteList(config.get('defines'), 'DEFS_%s' % configname, prefix='-D',
1191e604b70501586dd3396720641f652da55e5930aftschmelcher@chromium.org          quoter=EscapeCppDefine)
119266e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org
1193de9a78bf4f4300c34c6dad8c3c00ad2b41dbcae0thakis@chromium.org      if self.flavor == 'mac':
119428ba6ec3471076cb3b19404b1990bef8b5833579thakis@chromium.org        cflags = self.xcode_settings.GetCflags(configname)
119528ba6ec3471076cb3b19404b1990bef8b5833579thakis@chromium.org        cflags_c = self.xcode_settings.GetCflagsC(configname)
119628ba6ec3471076cb3b19404b1990bef8b5833579thakis@chromium.org        cflags_cc = self.xcode_settings.GetCflagsCC(configname)
119728ba6ec3471076cb3b19404b1990bef8b5833579thakis@chromium.org        cflags_objc = self.xcode_settings.GetCflagsObjC(configname)
119828ba6ec3471076cb3b19404b1990bef8b5833579thakis@chromium.org        cflags_objcc = self.xcode_settings.GetCflagsObjCC(configname)
1199de9a78bf4f4300c34c6dad8c3c00ad2b41dbcae0thakis@chromium.org      else:
1200de9a78bf4f4300c34c6dad8c3c00ad2b41dbcae0thakis@chromium.org        cflags = config.get('cflags')
1201de9a78bf4f4300c34c6dad8c3c00ad2b41dbcae0thakis@chromium.org        cflags_c = config.get('cflags_c')
1202de9a78bf4f4300c34c6dad8c3c00ad2b41dbcae0thakis@chromium.org        cflags_cc = config.get('cflags_cc')
120366e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org
120466e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org      self.WriteLn("# Flags passed to all source files.");
120566e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org      self.WriteList(cflags, 'CFLAGS_%s' % configname)
120666e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org      self.WriteLn("# Flags passed to only C files.");
120766e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org      self.WriteList(cflags_c, 'CFLAGS_C_%s' % configname)
120866e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org      self.WriteLn("# Flags passed to only C++ files.");
120966e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org      self.WriteList(cflags_cc, 'CFLAGS_CC_%s' % configname)
121066e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org      if self.flavor == 'mac':
121166e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org        self.WriteLn("# Flags passed to only ObjC files.");
121266e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org        self.WriteList(cflags_objc, 'CFLAGS_OBJC_%s' % configname)
121366e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org        self.WriteLn("# Flags passed to only ObjC++ files.");
121466e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org        self.WriteList(cflags_objcc, 'CFLAGS_OBJCC_%s' % configname)
12150a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      includes = config.get('include_dirs')
12160a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      if includes:
1217bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org        includes = map(Sourceify, map(self.Absolutify, includes))
12180a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      self.WriteList(includes, 'INCS_%s' % configname, prefix='-I')
12190a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
122045b37dde770ebc775202a675c6a42a50c72d2a07evan@chromium.org    compilable = filter(Compilable, sources)
122145b37dde770ebc775202a675c6a42a50c72d2a07evan@chromium.org    objs = map(self.Objectify, map(self.Absolutify, map(Target, compilable)))
12220a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    self.WriteList(objs, 'OBJS')
12230a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
12249a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org    for obj in objs:
12259a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org      assert ' ' not in obj, (
12269a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org          "Spaces in object filenames not supported (%s)"  % obj)
122703f47b7c86543b4d1170c8bf18028b227f0af9d4piman@chromium.org    self.WriteLn('# Add to the list of files we specially track '
122803f47b7c86543b4d1170c8bf18028b227f0af9d4piman@chromium.org                 'dependencies for.')
122903f47b7c86543b4d1170c8bf18028b227f0af9d4piman@chromium.org    self.WriteLn('all_deps += $(OBJS)')
123003f47b7c86543b4d1170c8bf18028b227f0af9d4piman@chromium.org    self.WriteLn()
123103f47b7c86543b4d1170c8bf18028b227f0af9d4piman@chromium.org
123206a9a48311d204fc582c76c668959dd85463aed1evan@chromium.org    # Make sure our dependencies are built first.
12330a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    if deps:
12348df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org      self.WriteMakeRule(['$(OBJS)'], deps,
12350a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org                         comment = 'Make sure our dependencies are built '
12368df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org                                   'before any of us.',
12378df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org                         order_only = True)
12380a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
123906a9a48311d204fc582c76c668959dd85463aed1evan@chromium.org    # Make sure the actions and rules run first.
12408df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    # If they generate any extra headers etc., the per-.o file dep tracking
12418df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    # will catch the proper rebuilds, so order only is still ok here.
1242623f6665978d7f799825bdea08b36b32b7304d3bevan@chromium.org    if extra_outputs:
124306a9a48311d204fc582c76c668959dd85463aed1evan@chromium.org      self.WriteMakeRule(['$(OBJS)'], extra_outputs,
124406a9a48311d204fc582c76c668959dd85463aed1evan@chromium.org                         comment = 'Make sure our actions/rules run '
12458df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org                                   'before any of us.',
12468df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org                         order_only = True)
124706a9a48311d204fc582c76c668959dd85463aed1evan@chromium.org
1248a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org    pchdeps = precompiled_header.GetObjDependencies(compilable, objs )
1249a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org    if pchdeps:
1250a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      self.WriteLn('# Dependencies from obj files to their precompiled headers')
1251a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      for source, obj, gch in pchdeps:
1252a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org        self.WriteLn('%s: %s' % (obj, gch))
1253a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      self.WriteLn('# End precompiled header dependencies')
12548347e3181c4b66aeb0a2e86c551f609b645f806dthakis@chromium.org
12550a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    if objs:
12568df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org      extra_link_deps.append('$(OBJS)')
12570a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      self.WriteLn("""\
12588dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org# CFLAGS et al overrides must be target-local.
12590a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org# See "Target-specific Variable Values" in the GNU Make manual.""")
1260821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com      self.WriteLn("$(OBJS): TOOLSET := $(TOOLSET)")
1261cd53ec0d06adcd7c6e4e08d28e43f64e56e48920evan@chromium.org      self.WriteLn("$(OBJS): GYP_CFLAGS := "
1262cd53ec0d06adcd7c6e4e08d28e43f64e56e48920evan@chromium.org                   "$(DEFS_$(BUILDTYPE)) "
1263cd53ec0d06adcd7c6e4e08d28e43f64e56e48920evan@chromium.org                   "$(INCS_$(BUILDTYPE)) "
1264a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org                   "%s " % precompiled_header.GetInclude('c') +
1265cd53ec0d06adcd7c6e4e08d28e43f64e56e48920evan@chromium.org                   "$(CFLAGS_$(BUILDTYPE)) "
1266cd53ec0d06adcd7c6e4e08d28e43f64e56e48920evan@chromium.org                   "$(CFLAGS_C_$(BUILDTYPE))")
1267cd53ec0d06adcd7c6e4e08d28e43f64e56e48920evan@chromium.org      self.WriteLn("$(OBJS): GYP_CXXFLAGS := "
1268cd53ec0d06adcd7c6e4e08d28e43f64e56e48920evan@chromium.org                   "$(DEFS_$(BUILDTYPE)) "
1269cd53ec0d06adcd7c6e4e08d28e43f64e56e48920evan@chromium.org                   "$(INCS_$(BUILDTYPE)) "
1270a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org                   "%s " % precompiled_header.GetInclude('cc') +
1271cd53ec0d06adcd7c6e4e08d28e43f64e56e48920evan@chromium.org                   "$(CFLAGS_$(BUILDTYPE)) "
1272cd53ec0d06adcd7c6e4e08d28e43f64e56e48920evan@chromium.org                   "$(CFLAGS_CC_$(BUILDTYPE))")
127366e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org      if self.flavor == 'mac':
127466e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org        self.WriteLn("$(OBJS): GYP_OBJCFLAGS := "
127566e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org                     "$(DEFS_$(BUILDTYPE)) "
127666e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org                     "$(INCS_$(BUILDTYPE)) "
1277a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org                     "%s " % precompiled_header.GetInclude('m') +
127866e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org                     "$(CFLAGS_$(BUILDTYPE)) "
1279de9a78bf4f4300c34c6dad8c3c00ad2b41dbcae0thakis@chromium.org                     "$(CFLAGS_C_$(BUILDTYPE)) "
128066e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org                     "$(CFLAGS_OBJC_$(BUILDTYPE))")
128166e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org        self.WriteLn("$(OBJS): GYP_OBJCXXFLAGS := "
128266e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org                     "$(DEFS_$(BUILDTYPE)) "
128366e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org                     "$(INCS_$(BUILDTYPE)) "
1284a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org                     "%s " % precompiled_header.GetInclude('mm') +
128566e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org                     "$(CFLAGS_$(BUILDTYPE)) "
1286de9a78bf4f4300c34c6dad8c3c00ad2b41dbcae0thakis@chromium.org                     "$(CFLAGS_CC_$(BUILDTYPE)) "
128766e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org                     "$(CFLAGS_OBJCC_$(BUILDTYPE))")
12888df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org
12890ce03407c6be23855228b47338365a1fc038de25scottmg@chromium.org    self.WritePchTargets(precompiled_header.GetPchBuildCommands())
12908347e3181c4b66aeb0a2e86c551f609b645f806dthakis@chromium.org
129145b37dde770ebc775202a675c6a42a50c72d2a07evan@chromium.org    # If there are any object files in our input file list, link them into our
129245b37dde770ebc775202a675c6a42a50c72d2a07evan@chromium.org    # output.
129345b37dde770ebc775202a675c6a42a50c72d2a07evan@chromium.org    extra_link_deps += filter(Linkable, sources)
129445b37dde770ebc775202a675c6a42a50c72d2a07evan@chromium.org
12958df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    self.WriteLn()
12960a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
1297a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org  def WritePchTargets(self, pch_commands):
1298a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org    """Writes make rules to compile prefix headers."""
1299a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org    if not pch_commands:
1300a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      return
1301a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org
1302a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org    for gch, lang_flag, lang, input in pch_commands:
1303a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      extra_flags = {
1304a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org        'c': '$(CFLAGS_C_$(BUILDTYPE))',
1305a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org        'cc': '$(CFLAGS_CC_$(BUILDTYPE))',
1306a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org        'm': '$(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))',
1307a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org        'mm': '$(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))',
1308a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      }[lang]
1309a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      var_name = {
1310a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org        'c': 'GYP_PCH_CFLAGS',
1311a8a33e272f6ea391b59b9073878642620bab3933thakis@chromium.org        'cc': 'GYP_PCH_CXXFLAGS',
1312a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org        'm': 'GYP_PCH_OBJCFLAGS',
1313a8a33e272f6ea391b59b9073878642620bab3933thakis@chromium.org        'mm': 'GYP_PCH_OBJCXXFLAGS',
1314a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      }[lang]
1315a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      self.WriteLn("%s: %s := %s " % (gch, var_name, lang_flag) +
1316a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org                   "$(DEFS_$(BUILDTYPE)) "
1317a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org                   "$(INCS_$(BUILDTYPE)) "
1318a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org                   "$(CFLAGS_$(BUILDTYPE)) " +
1319a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org                   extra_flags)
1320a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org
1321a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      self.WriteLn('%s: %s FORCE_DO_CMD' % (gch, input))
1322a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      self.WriteLn('\t@$(call do_cmd,pch_%s,1)' % lang)
1323a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      self.WriteLn('')
1324a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      assert ' ' not in gch, (
1325a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org          "Spaces in gch filenames not supported (%s)"  % gch)
1326a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      self.WriteLn('all_deps += %s' % gch)
1327a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org      self.WriteLn('')
1328a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org
132997d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.org
1330a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org  def ComputeOutputBasename(self, spec):
1331a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org    """Return the 'output basename' of a gyp spec.
13327a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org
13337a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    E.g., the loadable module 'foobar' in directory 'baz' will produce
1334a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org      'libfoobar.so'
13357a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """
1336f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org    assert not self.is_mac_bundle
1337f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org
1338a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org    if self.flavor == 'mac' and self.type in (
1339a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org        'static_library', 'executable', 'shared_library', 'loadable_module'):
1340a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org      return self.xcode_settings.GetExecutablePath()
1341a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org
13420a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    target = spec['target_name']
13434433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com    target_prefix = ''
13444433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com    target_ext = ''
13458df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    if self.type == 'static_library':
13464433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com      if target[:3] == 'lib':
13474433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com        target = target[3:]
13484433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com      target_prefix = 'lib'
13494433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com      target_ext = '.a'
13508df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    elif self.type in ('loadable_module', 'shared_library'):
13514433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com      if target[:3] == 'lib':
13524433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com        target = target[3:]
13534433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com      target_prefix = 'lib'
13544433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com      target_ext = '.so'
13558df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    elif self.type == 'none':
13560a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      target = '%s.stamp' % target
1357a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org    elif self.type != 'executable':
1358fbb339dfacf879d2466a66da2e224561d7d31af5evan@chromium.org      print ("ERROR: What output file should be generated?",
135966e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org             "type", self.type, "target", target)
1360b36f4e4101e3f1d3fe9233c9dcde6130e2680bceevan@chromium.org
13614433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com    target_prefix = spec.get('product_prefix', target_prefix)
13624433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com    target = spec.get('product_name', target)
13634433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com    product_ext = spec.get('product_extension')
13644433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com    if product_ext:
13654433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com      target_ext = '.' + product_ext
13664433ceec4876f3db8aa845a5fe08aa8e0bae2b1cbradnelson@google.com
1367a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org    return target_prefix + target + target_ext
1368a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org
1369a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org
13707824cd9bea470b5d7e763fc40eed9b79a5f4d534thakis@chromium.org  def _InstallImmediately(self):
13717824cd9bea470b5d7e763fc40eed9b79a5f4d534thakis@chromium.org    return self.toolset == 'target' and self.flavor == 'mac' and self.type in (
13727824cd9bea470b5d7e763fc40eed9b79a5f4d534thakis@chromium.org          'static_library', 'executable', 'shared_library', 'loadable_module')
13737824cd9bea470b5d7e763fc40eed9b79a5f4d534thakis@chromium.org
13747824cd9bea470b5d7e763fc40eed9b79a5f4d534thakis@chromium.org
1375a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org  def ComputeOutput(self, spec):
1376a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org    """Return the 'output' (full output path) of a gyp spec.
1377a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org
1378a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org    E.g., the loadable module 'foobar' in directory 'baz' will produce
1379a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org      '$(obj)/baz/libfoobar.so'
1380a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org    """
1381a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org    assert not self.is_mac_bundle
1382a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org
1383023d71b91d502f776f67c9fced435601070a4349evan@chromium.org    path = os.path.join('$(obj).' + self.toolset, self.path)
13847824cd9bea470b5d7e763fc40eed9b79a5f4d534thakis@chromium.org    if self.type == 'executable' or self._InstallImmediately():
1385a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org      path = '$(builddir)'
1386a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org    path = spec.get('product_dir', path)
1387a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org    return os.path.join(path, self.ComputeOutputBasename(spec))
13880a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
13890a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
1390f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org  def ComputeMacBundleOutput(self, spec):
1391f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org    """Return the 'output' (full output path) to a bundle output directory."""
1392f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org    assert self.is_mac_bundle
1393f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org    path = generator_default_variables['PRODUCT_DIR']
1394a5b864e7fd02395095297856d649ae63372ef392thakis@chromium.org    return os.path.join(path, self.xcode_settings.GetWrapperName())
1395f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org
1396f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org
1397f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org  def ComputeMacBundleBinaryOutput(self, spec):
1398f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org    """Return the 'output' (full output path) to the binary in a bundle."""
1399ebba0b9cb08b21f0360197c04bfebdbaf81ecad3thakis@chromium.org    path = generator_default_variables['PRODUCT_DIR']
1400a32043cac827125b8220076842117c9eb6db66e8thakis@chromium.org    return os.path.join(path, self.xcode_settings.GetExecutablePath())
1401f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org
1402f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org
14030a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org  def ComputeDeps(self, spec):
14047a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """Compute the dependencies of a gyp spec.
14057a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org
14067a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    Returns a tuple (deps, link_deps), where each is a list of
14077a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    filenames that will need to be put in front of make for either
14087a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    building (deps) or linking (link_deps).
14097a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """
1410b06ffce92c3e2a37af13f1c35cb098b735c0f1f7sgk@chromium.org    deps = []
1411b06ffce92c3e2a37af13f1c35cb098b735c0f1f7sgk@chromium.org    link_deps = []
14120a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    if 'dependencies' in spec:
1413b06ffce92c3e2a37af13f1c35cb098b735c0f1f7sgk@chromium.org      deps.extend([target_outputs[dep] for dep in spec['dependencies']
14140a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org                   if target_outputs[dep]])
14158df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org      for dep in spec['dependencies']:
14168df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org        if dep in target_link_deps:
1417afa3616bae66f1b500fe9c481cd9436a607f4546evan@chromium.org          link_deps.append(target_link_deps[dep])
1418b06ffce92c3e2a37af13f1c35cb098b735c0f1f7sgk@chromium.org      deps.extend(link_deps)
14198df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org      # TODO: It seems we need to transitively link in libraries (e.g. -lfoo)?
14208df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org      # This hack makes it work:
14218df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org      # link_deps.extend(spec.get('libraries', []))
1422b06ffce92c3e2a37af13f1c35cb098b735c0f1f7sgk@chromium.org    return (gyp.common.uniquer(deps), gyp.common.uniquer(link_deps))
14230a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
14240a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
1425f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org  def WriteDependencyOnExtraOutputs(self, target, extra_outputs):
1426f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org    self.WriteMakeRule([self.output_binary], extra_outputs,
1427f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org                       comment = 'Build our special outputs first.',
1428f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org                       order_only = True)
1429f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org
1430f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org
1431f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org  def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps,
1432f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org                  extra_outputs, part_of_all):
14337a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """Write Makefile code to produce the final target of the gyp spec.
14347a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org
14357a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    spec, configs: input from gyp.
14367a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    deps, link_deps: dependency lists; see ComputeDeps()
14377a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    extra_outputs: any extra outputs that our target should depend on
1438b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com    part_of_all: flag indicating this target is part of 'all'
14397a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """
14407a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org
14410a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    self.WriteLn('### Rules for final target.')
14420a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
14430a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    if extra_outputs:
1444f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      self.WriteDependencyOnExtraOutputs(self.output_binary, extra_outputs)
14450064df5e9ec0afc53d4103d7c61c0c7f75b6c641jrg@chromium.org      self.WriteMakeRule(extra_outputs, deps,
14460064df5e9ec0afc53d4103d7c61c0c7f75b6c641jrg@chromium.org                         comment=('Preserve order dependency of '
14470064df5e9ec0afc53d4103d7c61c0c7f75b6c641jrg@chromium.org                                  'special output on deps.'),
14483b4fb7c911dee3f66a9df392a2becdab9ffacba7bradnelson@google.com                         order_only = True)
14490a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
145042cdbe04ece5da22c61b3e4adbd9083974633e47thakis@chromium.org    target_postbuilds = {}
1451b65bfca8ec1627ff33393a6c1b0807efd923ca01evan@chromium.org    if self.type != 'none':
14520a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      for configname in sorted(configs.keys()):
14530a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org        config = configs[configname]
1454de9a78bf4f4300c34c6dad8c3c00ad2b41dbcae0thakis@chromium.org        if self.flavor == 'mac':
145592176cf8740adbcdc973858b7f87bcdb6e7938b1thakis@chromium.org          ldflags = self.xcode_settings.GetLdflags(configname,
14564d8ab8c5c273662a250ebae3efea2c0368558f32thakis@chromium.org              generator_default_variables['PRODUCT_DIR'],
14574d8ab8c5c273662a250ebae3efea2c0368558f32thakis@chromium.org              lambda p: Sourceify(self.Absolutify(p)))
1458fbddde34332875ce056552ded4d830b2fcf81206thakis@chromium.org
14598d79e520d72b209d9bec107f7dce4c7e79a7d0a6thakis@chromium.org          # TARGET_POSTBUILDS_$(BUILDTYPE) is added to postbuilds later on.
14602724da9e5f57957af502ff40ed586fd6351a5f71thakis@chromium.org          gyp_to_build = gyp.common.InvertRelativePath(self.path)
14613f7d04d67cabfc9b1c45ed551d4885130653d452justincohen@chromium.org          target_postbuild = self.xcode_settings.AddImplicitPostbuilds(
1462abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org              configname,
146306018e293265568ac848cd5ac7b5f02867b82696thakis@chromium.org              QuoteSpaces(os.path.normpath(os.path.join(gyp_to_build,
146406018e293265568ac848cd5ac7b5f02867b82696thakis@chromium.org                                                        self.output))),
146506018e293265568ac848cd5ac7b5f02867b82696thakis@chromium.org              QuoteSpaces(os.path.normpath(os.path.join(gyp_to_build,
146606018e293265568ac848cd5ac7b5f02867b82696thakis@chromium.org                                                        self.output_binary))))
146742cdbe04ece5da22c61b3e4adbd9083974633e47thakis@chromium.org          if target_postbuild:
146842cdbe04ece5da22c61b3e4adbd9083974633e47thakis@chromium.org            target_postbuilds[configname] = target_postbuild
1469de9a78bf4f4300c34c6dad8c3c00ad2b41dbcae0thakis@chromium.org        else:
14705f4f23823ce31a65fca28ca4ea581718b0beabf7evan@chromium.org          ldflags = config.get('ldflags', [])
1471bb5003ac2afa32d3ac1f17140b62d6c559e115d9evan@chromium.org          # Compute an rpath for this output if needed.
14724ca4ae996466c45ff14152560f923a86ead33e68thakis@chromium.org          if any(dep.endswith('.so') or '.so.' in dep for dep in deps):
1473bb5003ac2afa32d3ac1f17140b62d6c559e115d9evan@chromium.org            # We want to get the literal string "$ORIGIN" into the link command,
1474bb5003ac2afa32d3ac1f17140b62d6c559e115d9evan@chromium.org            # so we need lots of escaping.
1475023d71b91d502f776f67c9fced435601070a4349evan@chromium.org            ldflags.append(r'-Wl,-rpath=\$$ORIGIN/lib.%s/' % self.toolset)
1476023d71b91d502f776f67c9fced435601070a4349evan@chromium.org            ldflags.append(r'-Wl,-rpath-link=\$(builddir)/lib.%s/' %
1477023d71b91d502f776f67c9fced435601070a4349evan@chromium.org                           self.toolset)
1478f37c83ad866169311ce41cb09b32116c00c82244dimator@google.com        library_dirs = config.get('library_dirs', [])
1479f37c83ad866169311ce41cb09b32116c00c82244dimator@google.com        ldflags += [('-L%s' % library_dir) for library_dir in library_dirs]
1480de9a78bf4f4300c34c6dad8c3c00ad2b41dbcae0thakis@chromium.org        self.WriteList(ldflags, 'LDFLAGS_%s' % configname)
14815c809bab10c272ab2e34289a2505fc19ccd1da2cthakis@chromium.org        if self.flavor == 'mac':
14825c809bab10c272ab2e34289a2505fc19ccd1da2cthakis@chromium.org          self.WriteList(self.xcode_settings.GetLibtoolflags(configname),
14835c809bab10c272ab2e34289a2505fc19ccd1da2cthakis@chromium.org                         'LIBTOOLFLAGS_%s' % configname)
148461f691a8588fa539cb3172a4c967ad05af69d1d8thestig@chromium.org      libraries = spec.get('libraries')
148561f691a8588fa539cb3172a4c967ad05af69d1d8thestig@chromium.org      if libraries:
148661f691a8588fa539cb3172a4c967ad05af69d1d8thestig@chromium.org        # Remove duplicate entries
148761f691a8588fa539cb3172a4c967ad05af69d1d8thestig@chromium.org        libraries = gyp.common.uniquer(libraries)
1488e255eb2d8ac01e67f8fbcac353ee88049e605018thakis@chromium.org        if self.flavor == 'mac':
148908d6b2cb13257ed4eafd7469e1018e2a3531c42cviettrungluu@chromium.org          libraries = self.xcode_settings.AdjustLibraries(libraries)
149061f691a8588fa539cb3172a4c967ad05af69d1d8thestig@chromium.org      self.WriteList(libraries, 'LIBS')
1491abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org      self.WriteLn('%s: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))' %
1492abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org          QuoteSpaces(self.output_binary))
1493abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org      self.WriteLn('%s: LIBS := $(LIBS)' % QuoteSpaces(self.output_binary))
1494f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org
14955c809bab10c272ab2e34289a2505fc19ccd1da2cthakis@chromium.org      if self.flavor == 'mac':
14965c809bab10c272ab2e34289a2505fc19ccd1da2cthakis@chromium.org        self.WriteLn('%s: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE))' %
14975c809bab10c272ab2e34289a2505fc19ccd1da2cthakis@chromium.org            QuoteSpaces(self.output_binary))
14985c809bab10c272ab2e34289a2505fc19ccd1da2cthakis@chromium.org
149960e8244fa9b6f4bef0606ccc46cc5d23904a952athakis@chromium.org    # Postbuild actions. Like actions, but implicitly depend on the target's
150060e8244fa9b6f4bef0606ccc46cc5d23904a952athakis@chromium.org    # output.
15013c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org    postbuilds = []
15023c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org    if self.flavor == 'mac':
150342cdbe04ece5da22c61b3e4adbd9083974633e47thakis@chromium.org      if target_postbuilds:
15048d79e520d72b209d9bec107f7dce4c7e79a7d0a6thakis@chromium.org        postbuilds.append('$(TARGET_POSTBUILDS_$(BUILDTYPE))')
150560e8244fa9b6f4bef0606ccc46cc5d23904a952athakis@chromium.org      postbuilds.extend(
150606018e293265568ac848cd5ac7b5f02867b82696thakis@chromium.org          gyp.xcode_emulation.GetSpecPostbuildCommands(spec))
1507fbddde34332875ce056552ded4d830b2fcf81206thakis@chromium.org
1508fbddde34332875ce056552ded4d830b2fcf81206thakis@chromium.org    if postbuilds:
150960e8244fa9b6f4bef0606ccc46cc5d23904a952athakis@chromium.org      # Envvars may be referenced by TARGET_POSTBUILDS_$(BUILDTYPE),
151042cdbe04ece5da22c61b3e4adbd9083974633e47thakis@chromium.org      # so we must output its definition first, since we declare variables
151142cdbe04ece5da22c61b3e4adbd9083974633e47thakis@chromium.org      # using ":=".
1512477539a34ba23693c5d7ca49d212d9e99e058c02thakis@chromium.org      self.WriteSortedXcodeEnv(self.output, self.GetSortedXcodePostbuildEnv())
151342cdbe04ece5da22c61b3e4adbd9083974633e47thakis@chromium.org
151442cdbe04ece5da22c61b3e4adbd9083974633e47thakis@chromium.org      for configname in target_postbuilds:
151542cdbe04ece5da22c61b3e4adbd9083974633e47thakis@chromium.org        self.WriteLn('%s: TARGET_POSTBUILDS_%s := %s' %
151642cdbe04ece5da22c61b3e4adbd9083974633e47thakis@chromium.org            (QuoteSpaces(self.output),
151742cdbe04ece5da22c61b3e4adbd9083974633e47thakis@chromium.org             configname,
151842cdbe04ece5da22c61b3e4adbd9083974633e47thakis@chromium.org             gyp.common.EncodePOSIXShellList(target_postbuilds[configname])))
151942cdbe04ece5da22c61b3e4adbd9083974633e47thakis@chromium.org
152006018e293265568ac848cd5ac7b5f02867b82696thakis@chromium.org      # Postbuilds expect to be run in the gyp file's directory, so insert an
152106018e293265568ac848cd5ac7b5f02867b82696thakis@chromium.org      # implicit postbuild to cd to there.
152206018e293265568ac848cd5ac7b5f02867b82696thakis@chromium.org      postbuilds.insert(0, gyp.common.EncodePOSIXShellList(['cd', self.path]))
1523fbddde34332875ce056552ded4d830b2fcf81206thakis@chromium.org      for i in xrange(len(postbuilds)):
1524fbddde34332875ce056552ded4d830b2fcf81206thakis@chromium.org        if not postbuilds[i].startswith('$'):
1525fbddde34332875ce056552ded4d830b2fcf81206thakis@chromium.org          postbuilds[i] = EscapeShellArgument(postbuilds[i])
1526abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org      self.WriteLn('%s: builddir := $(abs_builddir)' % QuoteSpaces(self.output))
1527abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org      self.WriteLn('%s: POSTBUILDS := %s' % (
1528abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org          QuoteSpaces(self.output), ' '.join(postbuilds)))
15293c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org
1530f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org    # A bundle directory depends on its dependencies such as bundle resources
1531f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org    # and bundle binary. When all dependencies have been built, the bundle
1532f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org    # needs to be packaged.
1533f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org    if self.is_mac_bundle:
1534f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      # If the framework doesn't contain a binary, then nothing depends
1535f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      # on the actions -- make the framework depend on them directly too.
1536f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      self.WriteDependencyOnExtraOutputs(self.output, extra_outputs)
1537f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org
1538f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      # Bundle dependencies. Note that the code below adds actions to this
1539f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      # target, so if you move these two lines, move the lines below as well.
1540abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org      self.WriteList(map(QuoteSpaces, bundle_deps), 'BUNDLE_DEPS')
1541abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org      self.WriteLn('%s: $(BUNDLE_DEPS)' % QuoteSpaces(self.output))
1542f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org
1543f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      # After the framework is built, package it. Needs to happen before
1544f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      # postbuilds, since postbuilds depend on this.
15456377b5422801f251819bfcf4761e60a6391a8522thakis@chromium.org      if self.type in ('shared_library', 'loadable_module'):
1546a5628c94ec97f27462345f527bcfd96a8ffa47b7thakis@chromium.org        self.WriteLn('\t@$(call do_cmd,mac_package_framework,,,%s)' %
1547ebba0b9cb08b21f0360197c04bfebdbaf81ecad3thakis@chromium.org            self.xcode_settings.GetFrameworkVersion())
1548f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org
15493c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org      # Bundle postbuilds can depend on the whole bundle, so run them after
15503c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org      # the bundle is packaged, not already after the bundle binary is done.
155142eec3042c210863a48f73b88689c3308619f05athakis@chromium.org      if postbuilds:
155242eec3042c210863a48f73b88689c3308619f05athakis@chromium.org        self.WriteLn('\t@$(call do_postbuilds)')
15533c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org      postbuilds = []  # Don't write postbuilds for target's output.
155408a01e4f39a67236110ffb12ddb0b6c18835d717thakis@chromium.org
1555ecc6a10416a3fb67380964189f9f3af2e308137fthakis@chromium.org      # Needed by test/mac/gyptest-rebuild.py.
1556ecc6a10416a3fb67380964189f9f3af2e308137fthakis@chromium.org      self.WriteLn('\t@true  # No-op, used by tests')
1557ecc6a10416a3fb67380964189f9f3af2e308137fthakis@chromium.org
1558f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      # Since this target depends on binary and resources which are in
1559f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      # nested subfolders, the framework directory will be older than
1560f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      # its dependencies usually. To prevent this rule from executing
1561f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      # on every build (expensive, especially with postbuilds), expliclity
1562f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org      # update the time on the framework directory.
1563abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org      self.WriteLn('\t@touch -c %s' % QuoteSpaces(self.output))
15643c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org
15653c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org    if postbuilds:
15663c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org      assert not self.is_mac_bundle, ('Postbuilds for bundles should be done '
15673c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org          'on the bundle, not the binary (target \'%s\')' % self.target)
15687824cd9bea470b5d7e763fc40eed9b79a5f4d534thakis@chromium.org      assert 'product_dir' not in spec, ('Postbuilds do not work with '
15697824cd9bea470b5d7e763fc40eed9b79a5f4d534thakis@chromium.org          'custom product_dir')
15700a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
15718df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    if self.type == 'executable':
1572abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org      self.WriteLn('%s: LD_INPUTS := %s' % (
1573abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org          QuoteSpaces(self.output_binary),
1574abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org          ' '.join(map(QuoteSpaces, link_deps))))
1575ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org      if self.toolset == 'host' and self.flavor == 'android':
1576ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org        self.WriteDoCmd([self.output_binary], link_deps, 'link_host',
1577ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org                        part_of_all, postbuilds=postbuilds)
1578ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org      else:
1579ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org        self.WriteDoCmd([self.output_binary], link_deps, 'link', part_of_all,
1580ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org                        postbuilds=postbuilds)
1581ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org
15828df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    elif self.type == 'static_library':
15837e0fce30911675f780ba6a3712b6e73b4234c4c1thakis@chromium.org      for link_dep in link_deps:
15847e0fce30911675f780ba6a3712b6e73b4234c4c1thakis@chromium.org        assert ' ' not in link_dep, (
15857e0fce30911675f780ba6a3712b6e73b4234c4c1thakis@chromium.org            "Spaces in alink input filenames not supported (%s)"  % link_dep)
15861ceb9318fc52c93e50c74028f81fc858ab0284a7jochen@chromium.org      if (self.flavor not in ('mac', 'openbsd', 'win') and not
1587012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org          self.is_standalone_static_library):
1588012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org        self.WriteDoCmd([self.output_binary], link_deps, 'alink_thin',
1589012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org                        part_of_all, postbuilds=postbuilds)
1590012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org      else:
1591012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org        self.WriteDoCmd([self.output_binary], link_deps, 'alink', part_of_all,
1592012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org                        postbuilds=postbuilds)
1593afa3616bae66f1b500fe9c481cd9436a607f4546evan@chromium.org    elif self.type == 'shared_library':
1594abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org      self.WriteLn('%s: LD_INPUTS := %s' % (
1595abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org            QuoteSpaces(self.output_binary),
1596abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org            ' '.join(map(QuoteSpaces, link_deps))))
15973c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org      self.WriteDoCmd([self.output_binary], link_deps, 'solink', part_of_all,
15983c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org                      postbuilds=postbuilds)
1599afa3616bae66f1b500fe9c481cd9436a607f4546evan@chromium.org    elif self.type == 'loadable_module':
16007e0fce30911675f780ba6a3712b6e73b4234c4c1thakis@chromium.org      for link_dep in link_deps:
16017e0fce30911675f780ba6a3712b6e73b4234c4c1thakis@chromium.org        assert ' ' not in link_dep, (
16027e0fce30911675f780ba6a3712b6e73b4234c4c1thakis@chromium.org            "Spaces in module input filenames not supported (%s)"  % link_dep)
1603ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org      if self.toolset == 'host' and self.flavor == 'android':
1604ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org        self.WriteDoCmd([self.output_binary], link_deps, 'solink_module_host',
1605ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org                        part_of_all, postbuilds=postbuilds)
1606ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org      else:
1607ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org        self.WriteDoCmd(
1608ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org            [self.output_binary], link_deps, 'solink_module', part_of_all,
1609ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org            postbuilds=postbuilds)
16108df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org    elif self.type == 'none':
16110a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      # Write a stamp line.
16123c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org      self.WriteDoCmd([self.output_binary], deps, 'touch', part_of_all,
16133c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org                      postbuilds=postbuilds)
16140a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    else:
16158df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org      print "WARNING: no output for", self.type, target
16168df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org
16173aebc0b95cda686fe72b3fb77f7e5200e0e3ee78bradnelson@google.com    # Add an alias for each target (if there are any outputs).
1618ef3872e3b2f5311d4a80397c85a0c5fa62ab12d1mmoss@chromium.org    # Installable target aliases are created below.
1619ef3872e3b2f5311d4a80397c85a0c5fa62ab12d1mmoss@chromium.org    if ((self.output and self.output != self.target) and
1620ef3872e3b2f5311d4a80397c85a0c5fa62ab12d1mmoss@chromium.org        (self.type not in self._INSTALLABLE_TARGETS)):
16213aebc0b95cda686fe72b3fb77f7e5200e0e3ee78bradnelson@google.com      self.WriteMakeRule([self.target], [self.output],
1622af505fc205d556ae109fcdfb058eefff43de3a8dmmoss@chromium.org                         comment='Add target alias', phony = True)
1623af505fc205d556ae109fcdfb058eefff43de3a8dmmoss@chromium.org      if part_of_all:
1624af505fc205d556ae109fcdfb058eefff43de3a8dmmoss@chromium.org        self.WriteMakeRule(['all'], [self.target],
1625af505fc205d556ae109fcdfb058eefff43de3a8dmmoss@chromium.org                           comment = 'Add target alias to "all" target.',
1626af505fc205d556ae109fcdfb058eefff43de3a8dmmoss@chromium.org                           phony = True)
1627b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com
1628fbb339dfacf879d2466a66da2e224561d7d31af5evan@chromium.org    # Add special-case rules for our installable targets.
1629fbb339dfacf879d2466a66da2e224561d7d31af5evan@chromium.org    # 1) They need to install to the build dir or "product" dir.
1630fbb339dfacf879d2466a66da2e224561d7d31af5evan@chromium.org    # 2) They get shortcuts for building (e.g. "make chrome").
1631fbb339dfacf879d2466a66da2e224561d7d31af5evan@chromium.org    # 3) They are part of "make all".
1632012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org    if (self.type in self._INSTALLABLE_TARGETS or
1633012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org        self.is_standalone_static_library):
1634f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org      if self.type == 'shared_library':
163513379d1679cf70f1425b6e741146b5f16963b265mmoss@chromium.org        file_desc = 'shared library'
1636012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org      elif self.type == 'static_library':
1637012857d966fb79be79a5cf51d43777428d538a39thakis@chromium.org        file_desc = 'static library'
163813379d1679cf70f1425b6e741146b5f16963b265mmoss@chromium.org      else:
163913379d1679cf70f1425b6e741146b5f16963b265mmoss@chromium.org        file_desc = 'executable'
1640f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org      install_path = self._InstallableTargetInstallPath()
1641ab7c2dc35ce946ca57160d40607d4a5c8cc107c4thestig@chromium.org      installable_deps = [self.output]
1642299eb63862f16469aa6548d0d947f930fa756de7thakis@chromium.org      if (self.flavor == 'mac' and not 'product_dir' in spec and
1643299eb63862f16469aa6548d0d947f930fa756de7thakis@chromium.org          self.toolset == 'target'):
16447824cd9bea470b5d7e763fc40eed9b79a5f4d534thakis@chromium.org        # On mac, products are created in install_path immediately.
1645f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org        assert install_path == self.output, '%s != %s' % (
1646f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org            install_path, self.output)
1647f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org
1648ef3872e3b2f5311d4a80397c85a0c5fa62ab12d1mmoss@chromium.org      # Point the target alias to the final binary output.
1649f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org      self.WriteMakeRule([self.target], [install_path],
16501a5e09d63414fc6a83bf44de43f7f1446b89037bmmoss@chromium.org                         comment='Add target alias', phony = True)
1651f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org      if install_path != self.output:
1652f8fcc8a4851c07bf18a9cbc78376b9712c2c0cc7thakis@chromium.org        assert not self.is_mac_bundle  # See comment a few lines above.
1653f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org        self.WriteDoCmd([install_path], [self.output], 'copy',
165413379d1679cf70f1425b6e741146b5f16963b265mmoss@chromium.org                        comment = 'Copy this to the %s output path.' %
1655b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com                        file_desc, part_of_all=part_of_all)
1656f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org        installable_deps.append(install_path)
16571a5e09d63414fc6a83bf44de43f7f1446b89037bmmoss@chromium.org      if self.output != self.alias and self.alias != self.target:
16580cac27216634036628582961567c25c9f374d23cmmoss@chromium.org        self.WriteMakeRule([self.alias], installable_deps,
16590cac27216634036628582961567c25c9f374d23cmmoss@chromium.org                           comment = 'Short alias for building this %s.' %
16600cac27216634036628582961567c25c9f374d23cmmoss@chromium.org                           file_desc, phony = True)
1661a2942fc614cfa7cf267868f91cc71114de72d5cdbradnelson@google.com      if part_of_all:
1662f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org        self.WriteMakeRule(['all'], [install_path],
1663a2942fc614cfa7cf267868f91cc71114de72d5cdbradnelson@google.com                           comment = 'Add %s to "all" target.' % file_desc,
1664a2942fc614cfa7cf267868f91cc71114de72d5cdbradnelson@google.com                           phony = True)
1665fbb339dfacf879d2466a66da2e224561d7d31af5evan@chromium.org
16660a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
1667235affafcd4202203bbad1bf789d6d5dd5dff57csteveblock@chromium.org  def WriteList(self, value_list, variable=None, prefix='',
1668235affafcd4202203bbad1bf789d6d5dd5dff57csteveblock@chromium.org                quoter=QuoteIfNecessary):
16697a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """Write a variable definition that is a list of values.
16707a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org
16717a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    E.g. WriteList(['a','b'], 'foo', prefix='blah') writes out
16727a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org         foo = blaha blahb
16737a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    but in a pretty-printed style.
16747a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """
1675235affafcd4202203bbad1bf789d6d5dd5dff57csteveblock@chromium.org    values = ''
1676235affafcd4202203bbad1bf789d6d5dd5dff57csteveblock@chromium.org    if value_list:
1677235affafcd4202203bbad1bf789d6d5dd5dff57csteveblock@chromium.org      value_list = [quoter(prefix + l) for l in value_list]
1678235affafcd4202203bbad1bf789d6d5dd5dff57csteveblock@chromium.org      values = ' \\\n\t' + ' \\\n\t'.join(value_list)
1679235affafcd4202203bbad1bf789d6d5dd5dff57csteveblock@chromium.org    self.fp.write('%s :=%s\n\n' % (variable, values))
16800a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
16810a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
16823c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org  def WriteDoCmd(self, outputs, inputs, command, part_of_all, comment=None,
16833c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org                 postbuilds=False):
168424cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org    """Write a Makefile rule that uses do_cmd.
168524cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org
168624cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org    This makes the outputs dependent on the command line that was run,
168724cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org    as well as support the V= make command line flag.
168824cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org    """
16893c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org    suffix = ''
16903c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org    if postbuilds:
16913c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org      assert ',' not in command
16923c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org      suffix = ',,1'  # Tell do_cmd to honor $POSTBUILDS
169324cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org    self.WriteMakeRule(outputs, inputs,
16943c6a659ed056267f0c244875f39b606dd9fb447ethakis@chromium.org                       actions = ['$(call do_cmd,%s%s)' % (command, suffix)],
169524cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org                       comment = comment,
169624cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org                       force = True)
169703f47b7c86543b4d1170c8bf18028b227f0af9d4piman@chromium.org    # Add our outputs to the list of targets we read depfiles from.
16989a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org    # all_deps is only used for deps file reading, and for deps files we replace
16999a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org    # spaces with ? because escaping doesn't work with make's $(sort) and
17009a4bc857d95712446f5f71418e975e08c7b542e7thakis@chromium.org    # other functions.
1701abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org    outputs = [QuoteSpaces(o, SPACE_REPLACEMENT) for o in outputs]
170203f47b7c86543b4d1170c8bf18028b227f0af9d4piman@chromium.org    self.WriteLn('all_deps += %s' % ' '.join(outputs))
170324cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org
170424cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org
17058df7f009111c20f6a70644c00cf2f3ac86fb9b74evan@chromium.org  def WriteMakeRule(self, outputs, inputs, actions=None, comment=None,
17063b4fb7c911dee3f66a9df392a2becdab9ffacba7bradnelson@google.com                    order_only=False, force=False, phony=False):
17077a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """Write a Makefile rule, with some extra tricks.
17087a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org
17097a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    outputs: a list of outputs for the rule (note: this is not directly
17107a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org             supported by make; see comments below)
17117a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    inputs: a list of inputs for the rule
17127a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    actions: a list of shell commands to run for the rule
17137a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    comment: a comment to put in the Makefile above the rule (also useful
17147a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org             for making this Python script's code self-documenting)
17157a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    order_only: if true, makes the dependency order-only
171624cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org    force: if true, include FORCE_DO_CMD as an order-only dep
1717806b4823b31c6c31ffc6f279c63af5a137cd7f0cevan@chromium.org    phony: if true, the rule does not actually generate the named output, the
1718806b4823b31c6c31ffc6f279c63af5a137cd7f0cevan@chromium.org           output is just a name to run the rule
17197a5f7e4bdfa995d5e2f8ffa30935486b5adf1401evan@chromium.org    """
1720abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org    outputs = map(QuoteSpaces, outputs)
1721abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org    inputs = map(QuoteSpaces, inputs)
1722abef36cce0f9e4361c50ca56c1c990d49f81c2ebthakis@chromium.org
17230a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    if comment:
17240a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      self.WriteLn('# ' + comment)
1725806b4823b31c6c31ffc6f279c63af5a137cd7f0cevan@chromium.org    if phony:
1726806b4823b31c6c31ffc6f279c63af5a137cd7f0cevan@chromium.org      self.WriteLn('.PHONY: ' + ' '.join(outputs))
172724cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org    # TODO(evanm): just make order_only a list of deps instead of these hacks.
1728a54d88790b76151b535afff679b3d7e08c10cbf5mmoss@chromium.org    if order_only:
1729a54d88790b76151b535afff679b3d7e08c10cbf5mmoss@chromium.org      order_insert = '| '
17303b4fb7c911dee3f66a9df392a2becdab9ffacba7bradnelson@google.com      pick_output = ' '.join(outputs)
1731a54d88790b76151b535afff679b3d7e08c10cbf5mmoss@chromium.org    else:
1732a54d88790b76151b535afff679b3d7e08c10cbf5mmoss@chromium.org      order_insert = ''
17333b4fb7c911dee3f66a9df392a2becdab9ffacba7bradnelson@google.com      pick_output = outputs[0]
1734a54d88790b76151b535afff679b3d7e08c10cbf5mmoss@chromium.org    if force:
1735a54d88790b76151b535afff679b3d7e08c10cbf5mmoss@chromium.org      force_append = ' FORCE_DO_CMD'
1736a54d88790b76151b535afff679b3d7e08c10cbf5mmoss@chromium.org    else:
1737a54d88790b76151b535afff679b3d7e08c10cbf5mmoss@chromium.org      force_append = ''
1738821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com    if actions:
1739821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com      self.WriteLn("%s: TOOLSET := $(TOOLSET)" % outputs[0])
17403b4fb7c911dee3f66a9df392a2becdab9ffacba7bradnelson@google.com    self.WriteLn('%s: %s%s%s' % (pick_output, order_insert, ' '.join(inputs),
174124cc83cd5dbb7133eea88d2fa229bd7f4c434e35evan@chromium.org                                 force_append))
17420a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    if actions:
17430a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      for action in actions:
17440a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org        self.WriteLn('\t%s' % action)
17453b4fb7c911dee3f66a9df392a2becdab9ffacba7bradnelson@google.com    if not order_only and len(outputs) > 1:
17460a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      # If we have more than one output, a rule like
17470a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      #   foo bar: baz
17480a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      # that for *each* output we must run the action, potentially
17490a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      # in parallel.  That is not what we're trying to write -- what
17500a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      # we want is that we run the action once and it generates all
17510a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      # the files.
17520a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      # http://www.gnu.org/software/hello/manual/automake/Multiple-Outputs.html
17530a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      # discusses this problem and has this solution:
17540a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      # 1) Write the naive rule that would produce parallel runs of
17550a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      # the action.
17560a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      # 2) Make the outputs seralized on each other, so we won't start
17574155edc7a92a7ea77fdcc74dfe54e3c9d445553cmmoss@chromium.org      # a parallel run until the first run finishes, at which point
17580a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      # we'll have generated all the outputs and we're done.
17590a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org      self.WriteLn('%s: %s' % (' '.join(outputs[1:]), outputs[0]))
17604155edc7a92a7ea77fdcc74dfe54e3c9d445553cmmoss@chromium.org      # Add a dummy command to the "extra outputs" rule, otherwise make seems to
17614155edc7a92a7ea77fdcc74dfe54e3c9d445553cmmoss@chromium.org      # think these outputs haven't (couldn't have?) changed, and thus doesn't
17624155edc7a92a7ea77fdcc74dfe54e3c9d445553cmmoss@chromium.org      # flag them as changed (i.e. include in '$?') when evaluating dependent
17634155edc7a92a7ea77fdcc74dfe54e3c9d445553cmmoss@chromium.org      # rules, which in turn causes do_cmd() to skip running dependent commands.
17644155edc7a92a7ea77fdcc74dfe54e3c9d445553cmmoss@chromium.org      self.WriteLn('%s: ;' % (' '.join(outputs[1:])))
17650a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    self.WriteLn()
17660a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
17670a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
1768bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org  def WriteAndroidNdkModuleRule(self, module_name, all_sources, link_deps):
1769bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    """Write a set of LOCAL_XXX definitions for Android NDK.
1770bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org
1771bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    These variable definitions will be used by Android NDK but do nothing for
1772bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    non-Android applications.
1773bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org
1774bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    Arguments:
1775bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org      module_name: Android NDK module name, which must be unique among all
1776bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org          module names.
1777bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org      all_sources: A list of source files (will be filtered by Compilable).
1778bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org      link_deps: A list of link dependencies, which must be sorted in
1779bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org          the order from dependencies to dependents.
1780bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    """
1781bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    if self.type not in ('executable', 'shared_library', 'static_library'):
1782bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org      return
1783bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org
1784bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    self.WriteLn('# Variable definitions for Android applications')
1785bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    self.WriteLn('include $(CLEAR_VARS)')
1786bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    self.WriteLn('LOCAL_MODULE := ' + module_name)
1787bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    self.WriteLn('LOCAL_CFLAGS := $(CFLAGS_$(BUILDTYPE)) '
1788bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org                 '$(DEFS_$(BUILDTYPE)) '
1789bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org                 # LOCAL_CFLAGS is applied to both of C and C++.  There is
1790bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org                 # no way to specify $(CFLAGS_C_$(BUILDTYPE)) only for C
1791bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org                 # sources.
1792bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org                 '$(CFLAGS_C_$(BUILDTYPE)) '
1793bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org                 # $(INCS_$(BUILDTYPE)) includes the prefix '-I' while
1794bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org                 # LOCAL_C_INCLUDES does not expect it.  So put it in
1795bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org                 # LOCAL_CFLAGS.
1796bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org                 '$(INCS_$(BUILDTYPE))')
1797bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    # LOCAL_CXXFLAGS is obsolete and LOCAL_CPPFLAGS is preferred.
1798bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    self.WriteLn('LOCAL_CPPFLAGS := $(CFLAGS_CC_$(BUILDTYPE))')
1799bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    self.WriteLn('LOCAL_C_INCLUDES :=')
1800bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    self.WriteLn('LOCAL_LDLIBS := $(LDFLAGS_$(BUILDTYPE)) $(LIBS)')
1801bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org
1802bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    # Detect the C++ extension.
1803bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    cpp_ext = {'.cc': 0, '.cpp': 0, '.cxx': 0}
1804bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    default_cpp_ext = '.cpp'
1805bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    for filename in all_sources:
1806bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org      ext = os.path.splitext(filename)[1]
1807bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org      if ext in cpp_ext:
1808bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org        cpp_ext[ext] += 1
1809bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org        if cpp_ext[ext] > cpp_ext[default_cpp_ext]:
1810bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org          default_cpp_ext = ext
1811bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    self.WriteLn('LOCAL_CPP_EXTENSION := ' + default_cpp_ext)
1812bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org
1813bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    self.WriteList(map(self.Absolutify, filter(Compilable, all_sources)),
1814bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org                   'LOCAL_SRC_FILES')
1815bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org
1816bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    # Filter out those which do not match prefix and suffix and produce
1817bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    # the resulting list without prefix and suffix.
1818bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    def DepsToModules(deps, prefix, suffix):
1819bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org      modules = []
1820bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org      for filepath in deps:
1821bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org        filename = os.path.basename(filepath)
1822bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org        if filename.startswith(prefix) and filename.endswith(suffix):
1823bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org          modules.append(filename[len(prefix):-len(suffix)])
1824bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org      return modules
1825bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org
182677b811053944ece925c2686a2b7fe4f09e67b195thakis@chromium.org    # Retrieve the default value of 'SHARED_LIB_SUFFIX'
182777b811053944ece925c2686a2b7fe4f09e67b195thakis@chromium.org    params = {'flavor': 'linux'}
182877b811053944ece925c2686a2b7fe4f09e67b195thakis@chromium.org    default_variables = {}
182977b811053944ece925c2686a2b7fe4f09e67b195thakis@chromium.org    CalculateVariables(default_variables, params)
183077b811053944ece925c2686a2b7fe4f09e67b195thakis@chromium.org
1831bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    self.WriteList(
1832bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org        DepsToModules(link_deps,
1833bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org                      generator_default_variables['SHARED_LIB_PREFIX'],
183477b811053944ece925c2686a2b7fe4f09e67b195thakis@chromium.org                      default_variables['SHARED_LIB_SUFFIX']),
1835bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org        'LOCAL_SHARED_LIBRARIES')
1836bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    self.WriteList(
1837bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org        DepsToModules(link_deps,
1838bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org                      generator_default_variables['STATIC_LIB_PREFIX'],
1839bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org                      generator_default_variables['STATIC_LIB_SUFFIX']),
1840bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org        'LOCAL_STATIC_LIBRARIES')
1841bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org
1842bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    if self.type == 'executable':
1843bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org      self.WriteLn('include $(BUILD_EXECUTABLE)')
1844bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    elif self.type == 'shared_library':
1845bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org      self.WriteLn('include $(BUILD_SHARED_LIBRARY)')
1846bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    elif self.type == 'static_library':
1847bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org      self.WriteLn('include $(BUILD_STATIC_LIBRARY)')
1848bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    self.WriteLn()
1849bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org
1850bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org
18510a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org  def WriteLn(self, text=''):
18520a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    self.fp.write(text + '\n')
18530a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
18540a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
1855477539a34ba23693c5d7ca49d212d9e99e058c02thakis@chromium.org  def GetSortedXcodeEnv(self, additional_settings=None):
1856477539a34ba23693c5d7ca49d212d9e99e058c02thakis@chromium.org    return gyp.xcode_emulation.GetSortedXcodeEnv(
185790e4b5779ce263e7101e342ec64cb234db1b3ed7thakis@chromium.org        self.xcode_settings, "$(abs_builddir)",
1858b69d8712f968628199d5cf927657661b11d05e8bthakis@chromium.org        os.path.join("$(abs_srcdir)", self.path), "$(BUILDTYPE)",
1859b69d8712f968628199d5cf927657661b11d05e8bthakis@chromium.org        additional_settings)
18606377b5422801f251819bfcf4761e60a6391a8522thakis@chromium.org
18616377b5422801f251819bfcf4761e60a6391a8522thakis@chromium.org
1862477539a34ba23693c5d7ca49d212d9e99e058c02thakis@chromium.org  def GetSortedXcodePostbuildEnv(self):
186360e8244fa9b6f4bef0606ccc46cc5d23904a952athakis@chromium.org    # CHROMIUM_STRIP_SAVE_FILE is a chromium-specific hack.
186460e8244fa9b6f4bef0606ccc46cc5d23904a952athakis@chromium.org    # TODO(thakis): It would be nice to have some general mechanism instead.
186560e8244fa9b6f4bef0606ccc46cc5d23904a952athakis@chromium.org    strip_save_file = self.xcode_settings.GetPerTargetSetting(
186606018e293265568ac848cd5ac7b5f02867b82696thakis@chromium.org        'CHROMIUM_STRIP_SAVE_FILE', '')
186706018e293265568ac848cd5ac7b5f02867b82696thakis@chromium.org    # Even if strip_save_file is empty, explicitly write it. Else a postbuild
186806018e293265568ac848cd5ac7b5f02867b82696thakis@chromium.org    # might pick up an export from an earlier target.
1869477539a34ba23693c5d7ca49d212d9e99e058c02thakis@chromium.org    return self.GetSortedXcodeEnv(
187060e8244fa9b6f4bef0606ccc46cc5d23904a952athakis@chromium.org        additional_settings={'CHROMIUM_STRIP_SAVE_FILE': strip_save_file})
187160e8244fa9b6f4bef0606ccc46cc5d23904a952athakis@chromium.org
187260e8244fa9b6f4bef0606ccc46cc5d23904a952athakis@chromium.org
1873477539a34ba23693c5d7ca49d212d9e99e058c02thakis@chromium.org  def WriteSortedXcodeEnv(self, target, env):
1874477539a34ba23693c5d7ca49d212d9e99e058c02thakis@chromium.org    for k, v in env:
187591960399794196a9ed93cbe96f1687ed0e7c2d6drsesek@chromium.org      # For
187691960399794196a9ed93cbe96f1687ed0e7c2d6drsesek@chromium.org      #  foo := a\ b
187791960399794196a9ed93cbe96f1687ed0e7c2d6drsesek@chromium.org      # the escaped space does the right thing. For
187891960399794196a9ed93cbe96f1687ed0e7c2d6drsesek@chromium.org      #  export foo := a\ b
187991960399794196a9ed93cbe96f1687ed0e7c2d6drsesek@chromium.org      # it does not -- the backslash is written to the env as literal character.
188090e4b5779ce263e7101e342ec64cb234db1b3ed7thakis@chromium.org      # So don't escape spaces in |env[k]|.
1881477539a34ba23693c5d7ca49d212d9e99e058c02thakis@chromium.org      self.WriteLn('%s: export %s := %s' % (QuoteSpaces(target), k, v))
18826377b5422801f251819bfcf4761e60a6391a8522thakis@chromium.org
18836377b5422801f251819bfcf4761e60a6391a8522thakis@chromium.org
1884821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com  def Objectify(self, path):
1885821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com    """Convert a path to its output directory form."""
1886821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com    if '$(' in path:
1887023d71b91d502f776f67c9fced435601070a4349evan@chromium.org      path = path.replace('$(obj)/', '$(obj).%s/$(TARGET)/' % self.toolset)
1888ec39c78e848f49d3ed33b3775b04b53d9361a67fqsr@chromium.org    if not '$(obj)' in path:
1889ec39c78e848f49d3ed33b3775b04b53d9361a67fqsr@chromium.org      path = '$(obj).%s/$(TARGET)/%s' % (self.toolset, path)
1890ec39c78e848f49d3ed33b3775b04b53d9361a67fqsr@chromium.org    return path
1891821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com
1892bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org
18938347e3181c4b66aeb0a2e86c551f609b645f806dthakis@chromium.org  def Pchify(self, path, lang):
18948347e3181c4b66aeb0a2e86c551f609b645f806dthakis@chromium.org    """Convert a prefix header path to its output directory form."""
1895a402b25fabd2182c4c74dc3cf89c856c93ff5472thakis@chromium.org    path = self.Absolutify(path)
18968347e3181c4b66aeb0a2e86c551f609b645f806dthakis@chromium.org    if '$(' in path:
1897023d71b91d502f776f67c9fced435601070a4349evan@chromium.org      path = path.replace('$(obj)/', '$(obj).%s/$(TARGET)/pch-%s' %
1898023d71b91d502f776f67c9fced435601070a4349evan@chromium.org                          (self.toolset, lang))
18998347e3181c4b66aeb0a2e86c551f609b645f806dthakis@chromium.org      return path
1900023d71b91d502f776f67c9fced435601070a4349evan@chromium.org    return '$(obj).%s/$(TARGET)/pch-%s/%s' % (self.toolset, lang, path)
19018347e3181c4b66aeb0a2e86c551f609b645f806dthakis@chromium.org
19028347e3181c4b66aeb0a2e86c551f609b645f806dthakis@chromium.org
19030a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org  def Absolutify(self, path):
19040a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    """Convert a subdirectory-relative path into a base-relative path.
19050a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    Skips over paths that contain variables."""
19060a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    if '$(' in path:
19071a0fd49a725699cc439ca58aa5aca6c3baa76372thakis@chromium.org      # Don't call normpath in this case, as it might collapse the
19081a0fd49a725699cc439ca58aa5aca6c3baa76372thakis@chromium.org      # path too aggressively if it features '..'. However it's still
19091a0fd49a725699cc439ca58aa5aca6c3baa76372thakis@chromium.org      # important to strip trailing slashes.
19101a0fd49a725699cc439ca58aa5aca6c3baa76372thakis@chromium.org      return path.rstrip('/')
19110a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org    return os.path.normpath(os.path.join(self.path, path))
19120a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
19130a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
1914cdaa7e6d2e12c7d592265333396c6d1307632e22scr@chromium.org  def ExpandInputRoot(self, template, expansion, dirname):
1915cdaa7e6d2e12c7d592265333396c6d1307632e22scr@chromium.org    if '%(INPUT_ROOT)s' not in template and '%(INPUT_DIRNAME)s' not in template:
19165fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org      return template
1917cdaa7e6d2e12c7d592265333396c6d1307632e22scr@chromium.org    path = template % {
1918cdaa7e6d2e12c7d592265333396c6d1307632e22scr@chromium.org        'INPUT_ROOT': expansion,
1919cdaa7e6d2e12c7d592265333396c6d1307632e22scr@chromium.org        'INPUT_DIRNAME': dirname,
1920cdaa7e6d2e12c7d592265333396c6d1307632e22scr@chromium.org        }
19215fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org    return path
19225fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org
19235fb1f55ddfc4eb1346568207669064b25ecafd35thestig@chromium.org
1924f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org  def _InstallableTargetInstallPath(self):
1925f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org    """Returns the location of the final output for an installable target."""
19269ab39383c23368ab17e6f7bd7d6d0a6181a32710thakis@chromium.org    # Xcode puts shared_library results into PRODUCT_DIR, and some gyp files
19279ab39383c23368ab17e6f7bd7d6d0a6181a32710thakis@chromium.org    # rely on this. Emulate this behavior for mac.
1928299eb63862f16469aa6548d0d947f930fa756de7thakis@chromium.org    if (self.type == 'shared_library' and
1929299eb63862f16469aa6548d0d947f930fa756de7thakis@chromium.org        (self.flavor != 'mac' or self.toolset != 'target')):
1930f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org      # Install all shared libs into a common directory (per toolset) for
1931f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org      # convenient access with LD_LIBRARY_PATH.
1932023d71b91d502f776f67c9fced435601070a4349evan@chromium.org      return '$(builddir)/lib.%s/%s' % (self.toolset, self.alias)
1933f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org    return '$(builddir)/' + self.alias
1934f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org
1935f798208936eb91d4d378a65dab79f76b54bcfd1ctony@chromium.org
1936d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.orgdef WriteAutoRegenerationRule(params, root_makefile, makefile_name,
1937d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org                              build_files):
1938d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org  """Write the target to regenerate the Makefile."""
1939d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org  options = params['options']
1940d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org  build_files_args = [gyp.common.RelativePath(filename, options.toplevel_dir)
1941d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org                      for filename in params['build_files_arg']]
1942a497eec67cb0ed918e7eaef070b02349114837f9jochen@chromium.org
1943d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org  gyp_binary = gyp.common.FixIfRelativePath(params['gyp_binary'],
1944d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org                                            options.toplevel_dir)
1945d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org  if not gyp_binary.startswith(os.sep):
1946d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org    gyp_binary = os.path.join('.', gyp_binary)
1947a497eec67cb0ed918e7eaef070b02349114837f9jochen@chromium.org
1948d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org  root_makefile.write(
1949d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org      "quiet_cmd_regen_makefile = ACTION Regenerating $@\n"
1950a497eec67cb0ed918e7eaef070b02349114837f9jochen@chromium.org      "cmd_regen_makefile = cd $(srcdir); %(cmd)s\n"
1951d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org      "%(makefile_name)s: %(deps)s\n"
1952d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org      "\t$(call do_cmd,regen_makefile)\n\n" % {
1953d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org          'makefile_name': makefile_name,
1954d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org          'deps': ' '.join(map(Sourceify, build_files)),
1955d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org          'cmd': gyp.common.EncodePOSIXShellList(
1956d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org                     [gyp_binary, '-fmake'] +
1957d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org                     gyp.RegenerateFlags(options) +
1958d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org                     build_files_args)})
1959d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org
1960d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org
196108fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.orgdef PerformBuild(data, configurations, params):
196208fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org  options = params['options']
196308fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org  for config in configurations:
196408fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org    arguments = ['make']
196508fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org    if options.toplevel_dir and options.toplevel_dir != '.':
196608fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org      arguments += '-C', options.toplevel_dir
196708fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org    arguments.append('BUILDTYPE=' + config)
196808fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org    print 'Building [%s]: %s' % (config, arguments)
196908fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org    subprocess.check_call(arguments)
197008fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org
197108fc464f96f4d8664ae6549d9b7767e8d7fbfa6bsbc@chromium.org
19725c712802f5d54ec659ba0a1a9551ff53db110f41agl@chromium.orgdef GenerateOutput(target_list, target_dicts, data, params):
19738dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org  options = params['options']
19741911d51eee5277f2e1ba9e13a6dbad77b544283cthakis@chromium.org  flavor = gyp.common.GetFlavor(params)
197562cccaf64f861d4a96f48c759ecbf476e9289bf1sgk@chromium.org  generator_flags = params.get('generator_flags', {})
1976ffb7f2a66fb0748a0e8db6943a686f936a9bb8cdthomasvl@chromium.org  builddir_name = generator_flags.get('output_dir', 'out')
1977bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org  android_ndk_version = generator_flags.get('android_ndk_version', None)
19780fc3814647116a3c363d479ae476512b4e60571ejrg@chromium.org  default_target = generator_flags.get('default_target', 'all')
1979a12a9556125cf18f0c09b77a7721097e26d200d4sgk@chromium.org
19808f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org  def CalculateMakefilePath(build_file, base_name):
19818f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    """Determine where to write a Makefile for a given gyp file."""
19828f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    # Paths in gyp files are relative to the .gyp file, but we want
19838f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    # paths relative to the source root for the master makefile.  Grab
19848f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    # the path of the .gyp file as the base to relativize against.
19858f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp".
19868f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    base_path = gyp.common.RelativePath(os.path.dirname(build_file),
19878f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org                                        options.depth)
19888f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    # We write the file in the base_path directory.
19898f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    output_file = os.path.join(options.depth, base_path, base_name)
19908f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    if options.generator_output:
19912ebb8ddcc5d3711ed004bd7d0bdb5305a2b1aebajochen@chromium.org      output_file = os.path.join(
19922ebb8ddcc5d3711ed004bd7d0bdb5305a2b1aebajochen@chromium.org          options.depth, options.generator_output, base_path, base_name)
1993cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org    base_path = gyp.common.RelativePath(os.path.dirname(build_file),
1994cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org                                        options.toplevel_dir)
1995cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org    return base_path, output_file
19968f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org
1997a12a9556125cf18f0c09b77a7721097e26d200d4sgk@chromium.org  # TODO:  search for the first non-'Default' target.  This can go
1998a12a9556125cf18f0c09b77a7721097e26d200d4sgk@chromium.org  # away when we add verification that all targets have the
1999a12a9556125cf18f0c09b77a7721097e26d200d4sgk@chromium.org  # necessary configurations.
2000a12a9556125cf18f0c09b77a7721097e26d200d4sgk@chromium.org  default_configuration = None
2001821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com  toolsets = set([target_dicts[target]['toolset'] for target in target_list])
2002a12a9556125cf18f0c09b77a7721097e26d200d4sgk@chromium.org  for target in target_list:
2003a12a9556125cf18f0c09b77a7721097e26d200d4sgk@chromium.org    spec = target_dicts[target]
2004a12a9556125cf18f0c09b77a7721097e26d200d4sgk@chromium.org    if spec['default_configuration'] != 'Default':
2005a12a9556125cf18f0c09b77a7721097e26d200d4sgk@chromium.org      default_configuration = spec['default_configuration']
2006a12a9556125cf18f0c09b77a7721097e26d200d4sgk@chromium.org      break
2007a12a9556125cf18f0c09b77a7721097e26d200d4sgk@chromium.org  if not default_configuration:
2008a12a9556125cf18f0c09b77a7721097e26d200d4sgk@chromium.org    default_configuration = 'Default'
2009a12a9556125cf18f0c09b77a7721097e26d200d4sgk@chromium.org
2010bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org  srcdir = '.'
2011c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  makefile_name = 'Makefile' + options.suffix
2012cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org  makefile_path = os.path.join(options.toplevel_dir, makefile_name)
2013bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org  if options.generator_output:
2014bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org    global srcdir_prefix
20152ebb8ddcc5d3711ed004bd7d0bdb5305a2b1aebajochen@chromium.org    makefile_path = os.path.join(
20162ebb8ddcc5d3711ed004bd7d0bdb5305a2b1aebajochen@chromium.org        options.toplevel_dir, options.generator_output, makefile_name)
201787be65c3b2317afa26563f0cf0ab7431646c2657mmoss@chromium.org    srcdir = gyp.common.RelativePath(srcdir, options.generator_output)
2018bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org    srcdir_prefix = '$(srcdir)/'
201930dbad1010474d58abd9432759eb4eac0c158644evan@chromium.org
202068058475eca882224d56ce7d24130cdff5be6501thakis@chromium.org  flock_command= 'flock'
202130dbad1010474d58abd9432759eb4eac0c158644evan@chromium.org  header_params = {
20220fc3814647116a3c363d479ae476512b4e60571ejrg@chromium.org      'default_target': default_target,
2023965314078312572b10ace0c8add6ccd6c960e7d0mark@chromium.org      'builddir': builddir_name,
202430dbad1010474d58abd9432759eb4eac0c158644evan@chromium.org      'default_configuration': default_configuration,
202568058475eca882224d56ce7d24130cdff5be6501thakis@chromium.org      'flock': flock_command,
2026c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org      'flock_index': 1,
202766e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org      'link_commands': LINK_COMMANDS_LINUX,
20280c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org      'extra_commands': '',
202966e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org      'srcdir': srcdir,
203030dbad1010474d58abd9432759eb4eac0c158644evan@chromium.org    }
2031c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org  if flavor == 'mac':
203268058475eca882224d56ce7d24130cdff5be6501thakis@chromium.org    flock_command = './gyp-mac-tool flock'
2033c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    header_params.update({
203468058475eca882224d56ce7d24130cdff5be6501thakis@chromium.org        'flock': flock_command,
2035c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org        'flock_index': 2,
203666e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org        'link_commands': LINK_COMMANDS_MAC,
20370c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org        'extra_commands': SHARED_HEADER_MAC_COMMANDS,
2038c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    })
20390c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org  elif flavor == 'android':
2040ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org    header_params.update({
2041ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org        'link_commands': LINK_COMMANDS_ANDROID,
2042ff150236b33b19ea45fe10add312835d5f34254cthakis@chromium.org    })
20430c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org  elif flavor == 'solaris':
20440c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org    header_params.update({
2045f7e483b72ab910e113197f8ab0d1bea4b9cb1dedthakis@chromium.org        'flock': './gyp-flock-tool flock',
20460c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org        'flock_index': 2,
20470c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org    })
2048bc5a25d06d47b9e1bb0bb0c4d6b3c678e3e721a0thakis@chromium.org  elif flavor == 'freebsd':
2049bc5a25d06d47b9e1bb0bb0c4d6b3c678e3e721a0thakis@chromium.org    # Note: OpenBSD has sysutils/flock. lockf seems to be FreeBSD specific.
20500c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org    header_params.update({
20510c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org        'flock': 'lockf',
20520c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org    })
2053b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.org  elif flavor == 'aix':
2054b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.org    header_params.update({
2055b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.org        'link_commands': LINK_COMMANDS_AIX,
2056f7e483b72ab910e113197f8ab0d1bea4b9cb1dedthakis@chromium.org        'flock': './gyp-flock-tool flock',
2057b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.org        'flock_index': 2,
2058b8e58959f8767948aecbc3d8235927401cf3f93dthakis@chromium.org    })
205954d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.org
206054d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.org  header_params.update({
206154d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.org    'CC.target':   GetEnvironFallback(('CC_target', 'CC'), '$(CC)'),
206254d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.org    'AR.target':   GetEnvironFallback(('AR_target', 'AR'), '$(AR)'),
206354d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.org    'CXX.target':  GetEnvironFallback(('CXX_target', 'CXX'), '$(CXX)'),
206444c1a6c35b0c9762c1066afff961068be4808423thakis@chromium.org    'LINK.target': GetEnvironFallback(('LINK_target', 'LINK'), '$(LINK)'),
206554d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.org    'CC.host':     GetEnvironFallback(('CC_host',), 'gcc'),
206654d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.org    'AR.host':     GetEnvironFallback(('AR_host',), 'ar'),
206754d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.org    'CXX.host':    GetEnvironFallback(('CXX_host',), 'g++'),
206844c1a6c35b0c9762c1066afff961068be4808423thakis@chromium.org    'LINK.host':   GetEnvironFallback(('LINK_host',), '$(CXX.host)'),
206954d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.org  })
207030dbad1010474d58abd9432759eb4eac0c158644evan@chromium.org
2071c9521e9c7e7708433823464dc1e52d9b7724172cthakis@chromium.org  build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
207254d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.org  make_global_settings_array = data[build_file].get('make_global_settings', [])
20733951e9b4c490b0a7c822b93384e5f3ebc8abd312ukai@chromium.org  wrappers = {}
20743951e9b4c490b0a7c822b93384e5f3ebc8abd312ukai@chromium.org  wrappers['LINK'] = '%s $(builddir)/linker.lock' % flock_command
20753951e9b4c490b0a7c822b93384e5f3ebc8abd312ukai@chromium.org  for key, value in make_global_settings_array:
20763951e9b4c490b0a7c822b93384e5f3ebc8abd312ukai@chromium.org    if key.endswith('_wrapper'):
20773951e9b4c490b0a7c822b93384e5f3ebc8abd312ukai@chromium.org      wrappers[key[:-len('_wrapper')]] = '$(abspath %s)' % value
2078c9521e9c7e7708433823464dc1e52d9b7724172cthakis@chromium.org  make_global_settings = ''
207954d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.org  for key, value in make_global_settings_array:
20803951e9b4c490b0a7c822b93384e5f3ebc8abd312ukai@chromium.org    if re.match('.*_wrapper', key):
20813951e9b4c490b0a7c822b93384e5f3ebc8abd312ukai@chromium.org      continue
2082c9521e9c7e7708433823464dc1e52d9b7724172cthakis@chromium.org    if value[0] != '$':
2083c9521e9c7e7708433823464dc1e52d9b7724172cthakis@chromium.org      value = '$(abspath %s)' % value
20843951e9b4c490b0a7c822b93384e5f3ebc8abd312ukai@chromium.org    wrapper = wrappers.get(key)
20853951e9b4c490b0a7c822b93384e5f3ebc8abd312ukai@chromium.org    if wrapper:
20863951e9b4c490b0a7c822b93384e5f3ebc8abd312ukai@chromium.org      value = '%s %s' % (wrapper, value)
20873951e9b4c490b0a7c822b93384e5f3ebc8abd312ukai@chromium.org      del wrappers[key]
20883951e9b4c490b0a7c822b93384e5f3ebc8abd312ukai@chromium.org    if key in ('CC', 'CC.host', 'CXX', 'CXX.host'):
20893685595e3c38f1b5ea78c5f9e160f7d3d6dd9d6dthakis@chromium.org      make_global_settings += (
20903685595e3c38f1b5ea78c5f9e160f7d3d6dd9d6dthakis@chromium.org          'ifneq (,$(filter $(origin %s), undefined default))\n' % key)
20913685595e3c38f1b5ea78c5f9e160f7d3d6dd9d6dthakis@chromium.org      # Let gyp-time envvars win over global settings.
209222cb58987910c8486ca89c9ce6f3bf0ba3e4d8fdthakis@chromium.org      env_key = key.replace('.', '_')  # CC.host -> CC_host
209322cb58987910c8486ca89c9ce6f3bf0ba3e4d8fdthakis@chromium.org      if env_key in os.environ:
209422cb58987910c8486ca89c9ce6f3bf0ba3e4d8fdthakis@chromium.org        value = os.environ[env_key]
20953685595e3c38f1b5ea78c5f9e160f7d3d6dd9d6dthakis@chromium.org      make_global_settings += '  %s = %s\n' % (key, value)
20963685595e3c38f1b5ea78c5f9e160f7d3d6dd9d6dthakis@chromium.org      make_global_settings += 'endif\n'
2097c9521e9c7e7708433823464dc1e52d9b7724172cthakis@chromium.org    else:
20983685595e3c38f1b5ea78c5f9e160f7d3d6dd9d6dthakis@chromium.org      make_global_settings += '%s ?= %s\n' % (key, value)
20993951e9b4c490b0a7c822b93384e5f3ebc8abd312ukai@chromium.org  # TODO(ukai): define cmd when only wrapper is specified in
21003951e9b4c490b0a7c822b93384e5f3ebc8abd312ukai@chromium.org  # make_global_settings.
21013951e9b4c490b0a7c822b93384e5f3ebc8abd312ukai@chromium.org
2102c9521e9c7e7708433823464dc1e52d9b7724172cthakis@chromium.org  header_params['make_global_settings'] = make_global_settings
2103c9521e9c7e7708433823464dc1e52d9b7724172cthakis@chromium.org
2104b5a494899379867f5445f29db21fb2b8e5e8e03ethakis@chromium.org  gyp.common.EnsureDirExists(makefile_path)
210530dbad1010474d58abd9432759eb4eac0c158644evan@chromium.org  root_makefile = open(makefile_path, 'w')
210630dbad1010474d58abd9432759eb4eac0c158644evan@chromium.org  root_makefile.write(SHARED_HEADER % header_params)
2107bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org  # Currently any versions have the same effect, but in future the behavior
2108bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org  # could be different.
2109bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org  if android_ndk_version:
2110bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org    root_makefile.write(
2111bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org        '# Define LOCAL_PATH for build of Android applications.\n'
2112bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org        'LOCAL_PATH := $(call my-dir)\n'
2113bae07d9d14e4bc00822f800486ca73d6e863f7a6evan@chromium.org        '\n')
2114821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com  for toolset in toolsets:
2115821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com    root_makefile.write('TOOLSET := %s\n' % toolset)
211666e803050a5019fc92be1e7cfed0162c0dbbbec5thakis@chromium.org    WriteRootHeaderSuffixRules(root_makefile)
2117bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org
2118beab9a2ff9fcbd27d4b1c951d3fc6e6f09230223thakis@chromium.org  # Put build-time support tools next to the root Makefile.
21190c79cca8b06f1dc5883ebee880ea365761676931thakis@chromium.org  dest_path = os.path.dirname(makefile_path)
2120beab9a2ff9fcbd27d4b1c951d3fc6e6f09230223thakis@chromium.org  gyp.common.CopyTool(flavor, dest_path)
2121c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org
212224ba9675396c448775db18a3764849e51f19042fmmoss@chromium.org  # Find the list of targets that derive from the gyp file(s) being built.
212324ba9675396c448775db18a3764849e51f19042fmmoss@chromium.org  needed_targets = set()
212424ba9675396c448775db18a3764849e51f19042fmmoss@chromium.org  for build_file in params['build_files']:
212524ba9675396c448775db18a3764849e51f19042fmmoss@chromium.org    for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
212624ba9675396c448775db18a3764849e51f19042fmmoss@chromium.org      needed_targets.add(target)
212724ba9675396c448775db18a3764849e51f19042fmmoss@chromium.org
2128c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org  build_files = set()
212917528851a6175e4df5282a8001b8a723c122ddbbmmoss@chromium.org  include_list = set()
213097d85aab11bfea53a8ff74f6e47d3e1327bd22d1sgk@chromium.org  for qualified_target in target_list:
2131821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com    build_file, target, toolset = gyp.common.ParseQualifiedTarget(
2132821df584822a40838f71013666f9a9ccd3fa8fcfbradnelson@google.com        qualified_target)
2133c9521e9c7e7708433823464dc1e52d9b7724172cthakis@chromium.org
213454d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.org    this_make_global_settings = data[build_file].get('make_global_settings', [])
213554d2f6fe6d8a7b9d9786bd1f8540df6b4f46b83fsbc@chromium.org    assert make_global_settings_array == this_make_global_settings, (
21361e46da1000bc29679ab4cebf3c1034cb7d6f4487brettw@chromium.org        "make_global_settings needs to be the same for all targets. %s vs. %s" %
21371e46da1000bc29679ab4cebf3c1034cb7d6f4487brettw@chromium.org        (this_make_global_settings, make_global_settings))
2138c9521e9c7e7708433823464dc1e52d9b7724172cthakis@chromium.org
2139cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org    build_files.add(gyp.common.RelativePath(build_file, options.toplevel_dir))
2140c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    included_files = data[build_file]['included_files']
2141c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org    for included_file in included_files:
2142c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      # The included_files entries are relative to the dir of the build file
2143c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      # that included them, so we have to undo that and then make them relative
2144c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org      # to the root dir.
214507b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org      relative_include_file = gyp.common.RelativePath(
2146cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org          gyp.common.UnrelativePath(included_file, build_file),
2147cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org          options.toplevel_dir)
214807b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org      abs_include_file = os.path.abspath(relative_include_file)
214907b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org      # If the include file is from the ~/.gyp dir, we should use absolute path
215007b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org      # so that relocating the src dir doesn't break the path.
215107b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org      if (params['home_dot_gyp'] and
215207b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org          abs_include_file.startswith(params['home_dot_gyp'])):
215307b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org        build_files.add(abs_include_file)
215407b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org      else:
215507b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org        build_files.add(relative_include_file)
2156bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org
2157cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org    base_path, output_file = CalculateMakefilePath(build_file,
21588f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org        target + '.' + toolset + options.suffix + '.mk')
2159bf0ab1b75ee946b39a64b05835d6a8ece3e7c18csgk@chromium.org
2160bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org    spec = target_dicts[qualified_target]
21618dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org    configs = spec['configurations']
21620a445a124e9b7e1069bc405746036256bc515f17evan@chromium.org
2163de9a78bf4f4300c34c6dad8c3c00ad2b41dbcae0thakis@chromium.org    if flavor == 'mac':
21645a5caa1c101713c4bf0b7ca2d0302e3ee0ccff08thakis@chromium.org      gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec)
2165de9a78bf4f4300c34c6dad8c3c00ad2b41dbcae0thakis@chromium.org
2166c27d1917e3441b102ae77b66d792b12c91d7c38cthakis@chromium.org    writer = MakefileWriter(generator_flags, flavor)
2167b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com    writer.Write(qualified_target, base_path, output_file, spec, configs,
2168b58da7bba84dec4311b0a831ddeba071a50b10e4bradnelson@google.com                 part_of_all=qualified_target in needed_targets)
2169baa09c7d913efdf9f53fcc6b5a9859875587d660evan@chromium.org
2170baa09c7d913efdf9f53fcc6b5a9859875587d660evan@chromium.org    # Our root_makefile lives at the source root.  Compute the relative path
2171baa09c7d913efdf9f53fcc6b5a9859875587d660evan@chromium.org    # from there to the output_file for including.
21728f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    mkfile_rel_path = gyp.common.RelativePath(output_file,
21738f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org                                              os.path.dirname(makefile_path))
2174b27c4551897c0ac49f0022eb18b2342b77148077tony@chromium.org    include_list.add(mkfile_rel_path)
21758f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org
21768f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org  # Write out per-gyp (sub-project) Makefiles.
21778f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org  depth_rel_path = gyp.common.RelativePath(options.depth, os.getcwd())
21788f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org  for build_file in build_files:
21798f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    # The paths in build_files were relativized above, so undo that before
21808f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    # testing against the non-relativized items in target_list and before
21818f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    # calculating the Makefile path.
21828f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    build_file = os.path.join(depth_rel_path, build_file)
21838f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    gyp_targets = [target_dicts[target]['target_name'] for target in target_list
21848f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org                   if target.startswith(build_file) and
21858f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org                   target in needed_targets]
21868f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    # Only generate Makefiles for gyp files with targets.
21878f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    if not gyp_targets:
21888f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org      continue
2189cc59ba275c86c0e612818b6ae7cd9c52a2e32d98mmoss@chromium.org    base_path, output_file = CalculateMakefilePath(build_file,
21908f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org        os.path.splitext(os.path.basename(build_file))[0] + '.Makefile')
21918f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org    makefile_rel_path = gyp.common.RelativePath(os.path.dirname(makefile_path),
21928f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org                                                os.path.dirname(output_file))
2193b9cd14d164cfa90a6da1808b103f4717e353044fmmoss@chromium.org    writer.WriteSubMake(output_file, makefile_rel_path, gyp_targets,
2194b9cd14d164cfa90a6da1808b103f4717e353044fmmoss@chromium.org                        builddir_name)
21958f4548b0b9501d03d32499e07eb486408620a2e7mmoss@chromium.org
21962957d730fa32afd0afc4e75c63fc950295b772f9thestig@chromium.org
21972957d730fa32afd0afc4e75c63fc950295b772f9thestig@chromium.org  # Write out the sorted list of includes.
21982957d730fa32afd0afc4e75c63fc950295b772f9thestig@chromium.org  root_makefile.write('\n')
2199b27c4551897c0ac49f0022eb18b2342b77148077tony@chromium.org  for include_file in sorted(include_list):
2200b27c4551897c0ac49f0022eb18b2342b77148077tony@chromium.org    # We wrap each .mk include in an if statement so users can tell make to
2201b27c4551897c0ac49f0022eb18b2342b77148077tony@chromium.org    # not load a file by setting NO_LOAD.  The below make code says, only
2202b27c4551897c0ac49f0022eb18b2342b77148077tony@chromium.org    # load the .mk file if the .mk filename doesn't start with a token in
2203b27c4551897c0ac49f0022eb18b2342b77148077tony@chromium.org    # NO_LOAD.
2204b27c4551897c0ac49f0022eb18b2342b77148077tony@chromium.org    root_makefile.write(
2205b27c4551897c0ac49f0022eb18b2342b77148077tony@chromium.org        "ifeq ($(strip $(foreach prefix,$(NO_LOAD),\\\n"
2206b27c4551897c0ac49f0022eb18b2342b77148077tony@chromium.org        "    $(findstring $(join ^,$(prefix)),\\\n"
2207b27c4551897c0ac49f0022eb18b2342b77148077tony@chromium.org        "                 $(join ^," + include_file + ")))),)\n")
2208b27c4551897c0ac49f0022eb18b2342b77148077tony@chromium.org    root_makefile.write("  include " + include_file + "\n")
2209b27c4551897c0ac49f0022eb18b2342b77148077tony@chromium.org    root_makefile.write("endif\n")
22102957d730fa32afd0afc4e75c63fc950295b772f9thestig@chromium.org  root_makefile.write('\n')
2211bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org
2212365cdc471e361b0bad9f27cbe6cde76abc56a343sbc@chromium.org  if (not generator_flags.get('standalone')
2213365cdc471e361b0bad9f27cbe6cde76abc56a343sbc@chromium.org      and generator_flags.get('auto_regeneration', True)):
2214d88b210073f8fbc99ee7138a0b3108afa4409309tony@chromium.org    WriteAutoRegenerationRule(params, root_makefile, makefile_name, build_files)
2215c01356ff413b71e18e80d081b33e9cc1cb923440evan@chromium.org
22163c02308fe834c7af49f1557ac3d56be58a9b1fc7tony@chromium.org  root_makefile.write(SHARED_FOOTER)
22178dafdc96be95b51813d58a68213457925520bc8bevan@chromium.org
2218bca8da7375cb274c9a62c7cd5290a1e22552420devan@chromium.org  root_makefile.close()
2219