| 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 |