OLD | NEW |
1 # Copyright (c) 2012 Google Inc. All rights reserved. | 1 # Copyright (c) 2012 Google Inc. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import copy | 5 import copy |
6 import hashlib | 6 import hashlib |
7 import multiprocessing | 7 import multiprocessing |
8 import os.path | 8 import os.path |
9 import re | 9 import re |
10 import signal | 10 import signal |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 def Define(d, flavor): | 90 def Define(d, flavor): |
91 """Takes a preprocessor define and returns a -D parameter that's ninja- and | 91 """Takes a preprocessor define and returns a -D parameter that's ninja- and |
92 shell-escaped.""" | 92 shell-escaped.""" |
93 if flavor == 'win': | 93 if flavor == 'win': |
94 # cl.exe replaces literal # characters with = in preprocesor definitions for | 94 # cl.exe replaces literal # characters with = in preprocesor definitions for |
95 # some reason. Octal-encode to work around that. | 95 # some reason. Octal-encode to work around that. |
96 d = d.replace('#', '\\%03o' % ord('#')) | 96 d = d.replace('#', '\\%03o' % ord('#')) |
97 return QuoteShellArgument(ninja_syntax.escape('-D' + d), flavor) | 97 return QuoteShellArgument(ninja_syntax.escape('-D' + d), flavor) |
98 | 98 |
99 | 99 |
100 def InvertRelativePath(path): | |
101 """Given a relative path like foo/bar, return the inverse relative path: | |
102 the path from the relative path back to the origin dir. | |
103 | |
104 E.g. os.path.normpath(os.path.join(path, InvertRelativePath(path))) | |
105 should always produce the empty string.""" | |
106 | |
107 if not path: | |
108 return path | |
109 # Only need to handle relative paths into subdirectories for now. | |
110 assert '..' not in path, path | |
111 depth = len(path.split(os.path.sep)) | |
112 return os.path.sep.join(['..'] * depth) | |
113 | |
114 | |
115 class Target: | 100 class Target: |
116 """Target represents the paths used within a single gyp target. | 101 """Target represents the paths used within a single gyp target. |
117 | 102 |
118 Conceptually, building a single target A is a series of steps: | 103 Conceptually, building a single target A is a series of steps: |
119 | 104 |
120 1) actions/rules/copies generates source/resources/etc. | 105 1) actions/rules/copies generates source/resources/etc. |
121 2) compiles generates .o files | 106 2) compiles generates .o files |
122 3) link generates a binary (library/executable) | 107 3) link generates a binary (library/executable) |
123 4) bundle merges the above in a mac bundle | 108 4) bundle merges the above in a mac bundle |
124 | 109 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 # | 196 # |
212 # - GypPathToNinja translates a gyp path (i.e. relative to the .gyp file) | 197 # - GypPathToNinja translates a gyp path (i.e. relative to the .gyp file) |
213 # into the equivalent ninja path. | 198 # into the equivalent ninja path. |
214 # | 199 # |
215 # - GypPathToUniqueOutput translates a gyp path into a ninja path to write | 200 # - GypPathToUniqueOutput translates a gyp path into a ninja path to write |
216 # an output file; the result can be namespaced such that it is unique | 201 # an output file; the result can be namespaced such that it is unique |
217 # to the input file name as well as the output target name. | 202 # to the input file name as well as the output target name. |
218 | 203 |
219 class NinjaWriter: | 204 class NinjaWriter: |
220 def __init__(self, qualified_target, target_outputs, base_dir, build_dir, | 205 def __init__(self, qualified_target, target_outputs, base_dir, build_dir, |
221 output_file, flavor, abs_build_dir=None): | 206 output_file, flavor, toplevel_dir=None): |
222 """ | 207 """ |
223 base_dir: path from source root to directory containing this gyp file, | 208 base_dir: path from source root to directory containing this gyp file, |
224 by gyp semantics, all input paths are relative to this | 209 by gyp semantics, all input paths are relative to this |
225 build_dir: path from source root to build output | 210 build_dir: path from source root to build output |
226 abs_build_dir: absolute path to the build directory | 211 toplevel_dir: path to the toplevel directory |
227 """ | 212 """ |
228 | 213 |
229 self.qualified_target = qualified_target | 214 self.qualified_target = qualified_target |
230 self.target_outputs = target_outputs | 215 self.target_outputs = target_outputs |
231 self.base_dir = base_dir | 216 self.base_dir = base_dir |
232 self.build_dir = build_dir | 217 self.build_dir = build_dir |
233 self.ninja = ninja_syntax.Writer(output_file) | 218 self.ninja = ninja_syntax.Writer(output_file) |
234 self.flavor = flavor | 219 self.flavor = flavor |
235 self.abs_build_dir = abs_build_dir | 220 self.abs_build_dir = None |
| 221 if toplevel_dir is not None: |
| 222 self.abs_build_dir = os.path.abspath(os.path.join(toplevel_dir, |
| 223 build_dir)) |
236 self.obj_ext = '.obj' if flavor == 'win' else '.o' | 224 self.obj_ext = '.obj' if flavor == 'win' else '.o' |
237 if flavor == 'win': | 225 if flavor == 'win': |
238 # See docstring of msvs_emulation.GenerateEnvironmentFiles(). | 226 # See docstring of msvs_emulation.GenerateEnvironmentFiles(). |
239 self.win_env = {} | 227 self.win_env = {} |
240 for arch in ('x86', 'x64'): | 228 for arch in ('x86', 'x64'): |
241 self.win_env[arch] = 'environment.' + arch | 229 self.win_env[arch] = 'environment.' + arch |
242 | 230 |
243 # Relative path from build output dir to base dir. | 231 # Relative path from build output dir to base dir. |
244 self.build_to_base = os.path.join(InvertRelativePath(build_dir), base_dir) | 232 build_to_top = gyp.common.InvertRelativePath(build_dir, toplevel_dir) |
| 233 self.build_to_base = os.path.join(build_to_top, base_dir) |
245 # Relative path from base dir to build dir. | 234 # Relative path from base dir to build dir. |
246 self.base_to_build = os.path.join(InvertRelativePath(base_dir), build_dir) | 235 base_to_top = gyp.common.InvertRelativePath(base_dir, toplevel_dir) |
| 236 self.base_to_build = os.path.join(base_to_top, build_dir) |
247 | 237 |
248 def ExpandSpecial(self, path, product_dir=None): | 238 def ExpandSpecial(self, path, product_dir=None): |
249 """Expand specials like $!PRODUCT_DIR in |path|. | 239 """Expand specials like $!PRODUCT_DIR in |path|. |
250 | 240 |
251 If |product_dir| is None, assumes the cwd is already the product | 241 If |product_dir| is None, assumes the cwd is already the product |
252 dir. Otherwise, |product_dir| is the relative path to the product | 242 dir. Otherwise, |product_dir| is the relative path to the product |
253 dir. | 243 dir. |
254 """ | 244 """ |
255 | 245 |
256 PRODUCT_DIR = '$!PRODUCT_DIR' | 246 PRODUCT_DIR = '$!PRODUCT_DIR' |
(...skipping 1108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1365 ld = '$cxx' | 1355 ld = '$cxx' |
1366 ld_host = '$cxx_host' | 1356 ld_host = '$cxx_host' |
1367 | 1357 |
1368 cc_host = None | 1358 cc_host = None |
1369 cxx_host = None | 1359 cxx_host = None |
1370 cc_host_global_setting = None | 1360 cc_host_global_setting = None |
1371 cxx_host_global_setting = None | 1361 cxx_host_global_setting = None |
1372 | 1362 |
1373 build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) | 1363 build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) |
1374 make_global_settings = data[build_file].get('make_global_settings', []) | 1364 make_global_settings = data[build_file].get('make_global_settings', []) |
1375 build_to_root = InvertRelativePath(build_dir) | 1365 build_to_root = gyp.common.InvertRelativePath(build_dir, |
| 1366 options.toplevel_dir) |
1376 for key, value in make_global_settings: | 1367 for key, value in make_global_settings: |
1377 if key == 'CC': | 1368 if key == 'CC': |
1378 cc = os.path.join(build_to_root, value) | 1369 cc = os.path.join(build_to_root, value) |
1379 if key == 'CXX': | 1370 if key == 'CXX': |
1380 cxx = os.path.join(build_to_root, value) | 1371 cxx = os.path.join(build_to_root, value) |
1381 if key == 'LD': | 1372 if key == 'LD': |
1382 ld = os.path.join(build_to_root, value) | 1373 ld = os.path.join(build_to_root, value) |
1383 if key == 'CC.host': | 1374 if key == 'CC.host': |
1384 cc_host = os.path.join(build_to_root, value) | 1375 cc_host = os.path.join(build_to_root, value) |
1385 cc_host_global_setting = value | 1376 cc_host_global_setting = value |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1722 | 1713 |
1723 base_path = os.path.dirname(build_file) | 1714 base_path = os.path.dirname(build_file) |
1724 obj = 'obj' | 1715 obj = 'obj' |
1725 if toolset != 'target': | 1716 if toolset != 'target': |
1726 obj += '.' + toolset | 1717 obj += '.' + toolset |
1727 output_file = os.path.join(obj, base_path, name + '.ninja') | 1718 output_file = os.path.join(obj, base_path, name + '.ninja') |
1728 | 1719 |
1729 abs_build_dir = os.path.abspath(toplevel_build) | 1720 abs_build_dir = os.path.abspath(toplevel_build) |
1730 writer = NinjaWriter(qualified_target, target_outputs, base_path, build_dir, | 1721 writer = NinjaWriter(qualified_target, target_outputs, base_path, build_dir, |
1731 OpenOutput(os.path.join(toplevel_build, output_file)), | 1722 OpenOutput(os.path.join(toplevel_build, output_file)), |
1732 flavor, abs_build_dir=abs_build_dir) | 1723 flavor, toplevel_dir=options.toplevel_dir) |
1733 master_ninja.subninja(output_file) | 1724 master_ninja.subninja(output_file) |
1734 | 1725 |
1735 target = writer.WriteSpec( | 1726 target = writer.WriteSpec( |
1736 spec, config_name, generator_flags, case_sensitive_filesystem) | 1727 spec, config_name, generator_flags, case_sensitive_filesystem) |
1737 if target: | 1728 if target: |
1738 if name != target.FinalOutput() and spec['toolset'] == 'target': | 1729 if name != target.FinalOutput() and spec['toolset'] == 'target': |
1739 target_short_names.setdefault(name, []).append(target) | 1730 target_short_names.setdefault(name, []).append(target) |
1740 target_outputs[qualified_target] = target | 1731 target_outputs[qualified_target] = target |
1741 if qualified_target in all_targets: | 1732 if qualified_target in all_targets: |
1742 all_outputs.add(target.FinalOutput()) | 1733 all_outputs.add(target.FinalOutput()) |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1790 arglists.append( | 1781 arglists.append( |
1791 (target_list, target_dicts, data, params, config_name)) | 1782 (target_list, target_dicts, data, params, config_name)) |
1792 pool.map(CallGenerateOutputForConfig, arglists) | 1783 pool.map(CallGenerateOutputForConfig, arglists) |
1793 except KeyboardInterrupt, e: | 1784 except KeyboardInterrupt, e: |
1794 pool.terminate() | 1785 pool.terminate() |
1795 raise e | 1786 raise e |
1796 else: | 1787 else: |
1797 for config_name in config_names: | 1788 for config_name in config_names: |
1798 GenerateOutputForConfig(target_list, target_dicts, data, params, | 1789 GenerateOutputForConfig(target_list, target_dicts, data, params, |
1799 config_name) | 1790 config_name) |
OLD | NEW |