OLD | NEW |
---|---|
1 # Copyright (c) 2013 Google Inc. All rights reserved. | 1 # Copyright (c) 2013 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 collections | 5 import collections |
6 import copy | 6 import copy |
7 import hashlib | 7 import hashlib |
8 import json | 8 import json |
9 import multiprocessing | 9 import multiprocessing |
10 import os.path | 10 import os.path |
(...skipping 1677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1688 (sys.executable, use_separate_mspdbsrv)) | 1688 (sys.executable, use_separate_mspdbsrv)) |
1689 exe_cmd = FullLinkCommand(exe_cmd, '$binary', 'exe') | 1689 exe_cmd = FullLinkCommand(exe_cmd, '$binary', 'exe') |
1690 master_ninja.rule('link' + rule_name_suffix, | 1690 master_ninja.rule('link' + rule_name_suffix, |
1691 description='LINK%s $binary' % rule_name_suffix.upper(), | 1691 description='LINK%s $binary' % rule_name_suffix.upper(), |
1692 command=exe_cmd, | 1692 command=exe_cmd, |
1693 rspfile='$binary.rsp', | 1693 rspfile='$binary.rsp', |
1694 rspfile_content='$in_newline $libs $ldflags', | 1694 rspfile_content='$in_newline $libs $ldflags', |
1695 pool='link_pool') | 1695 pool='link_pool') |
1696 | 1696 |
1697 | 1697 |
1698 class VisitedTarget: | |
1699 """Used to track the set of qualified targets with the same short name as | |
1700 well as if the target is empty.""" | |
1701 def __init__(self): | |
1702 # True if the only targets with this name are empty (not interesting). | |
1703 self.has_empty_target = True | |
1704 # List of qualified targets with the same name. | |
1705 self.qualified_targets = [] | |
1706 | |
1707 | |
1698 def GenerateOutputForConfig(target_list, target_dicts, data, params, | 1708 def GenerateOutputForConfig(target_list, target_dicts, data, params, |
1699 config_name): | 1709 config_name): |
1700 options = params['options'] | 1710 options = params['options'] |
1701 flavor = gyp.common.GetFlavor(params) | 1711 flavor = gyp.common.GetFlavor(params) |
1702 generator_flags = params.get('generator_flags', {}) | 1712 generator_flags = params.get('generator_flags', {}) |
1703 | 1713 |
1704 # build_dir: relative path from source root to our output files. | 1714 # build_dir: relative path from source root to our output files. |
1705 # e.g. "out/Debug" | 1715 # e.g. "out/Debug" |
1706 build_dir = os.path.normpath( | 1716 build_dir = os.path.normpath( |
1707 os.path.join(ComputeOutputDir(params), config_name)) | 1717 os.path.join(ComputeOutputDir(params), config_name)) |
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2143 os.path.normpath(build_file)): | 2153 os.path.normpath(build_file)): |
2144 all_targets.add(target) | 2154 all_targets.add(target) |
2145 all_outputs = set() | 2155 all_outputs = set() |
2146 | 2156 |
2147 # target_outputs is a map from qualified target name to a Target object. | 2157 # target_outputs is a map from qualified target name to a Target object. |
2148 target_outputs = {} | 2158 target_outputs = {} |
2149 # target_short_names is a map from target short name to a list of Target | 2159 # target_short_names is a map from target short name to a list of Target |
2150 # objects. | 2160 # objects. |
2151 target_short_names = {} | 2161 target_short_names = {} |
2152 | 2162 |
2153 # short name of targets that were skipped because they didn't contain anything | 2163 # Maps from short name to a VisitedTarget. |
2154 # interesting. | 2164 name_to_visited = {} |
2155 empty_target_names = [] | |
2156 | 2165 |
2157 for qualified_target in target_list: | 2166 for qualified_target in target_list: |
2158 # qualified_target is like: third_party/icu/icu.gyp:icui18n#target | 2167 # qualified_target is like: third_party/icu/icu.gyp:icui18n#target |
2159 build_file, name, toolset = \ | 2168 build_file, name, toolset = \ |
2160 gyp.common.ParseQualifiedTarget(qualified_target) | 2169 gyp.common.ParseQualifiedTarget(qualified_target) |
2161 | 2170 |
2162 this_make_global_settings = data[build_file].get('make_global_settings', []) | 2171 this_make_global_settings = data[build_file].get('make_global_settings', []) |
2163 assert make_global_settings == this_make_global_settings, ( | 2172 assert make_global_settings == this_make_global_settings, ( |
2164 "make_global_settings needs to be the same for all targets. %s vs. %s" % | 2173 "make_global_settings needs to be the same for all targets. %s vs. %s" % |
2165 (this_make_global_settings, make_global_settings)) | 2174 (this_make_global_settings, make_global_settings)) |
(...skipping 24 matching lines...) Expand all Loading... | |
2190 ninja_file.write(ninja_output.getvalue()) | 2199 ninja_file.write(ninja_output.getvalue()) |
2191 ninja_output.close() | 2200 ninja_output.close() |
2192 master_ninja.subninja(output_file) | 2201 master_ninja.subninja(output_file) |
2193 | 2202 |
2194 if target: | 2203 if target: |
2195 if name != target.FinalOutput() and spec['toolset'] == 'target': | 2204 if name != target.FinalOutput() and spec['toolset'] == 'target': |
2196 target_short_names.setdefault(name, []).append(target) | 2205 target_short_names.setdefault(name, []).append(target) |
2197 target_outputs[qualified_target] = target | 2206 target_outputs[qualified_target] = target |
2198 if qualified_target in all_targets: | 2207 if qualified_target in all_targets: |
2199 all_outputs.add(target.FinalOutput()) | 2208 all_outputs.add(target.FinalOutput()) |
2200 else: | 2209 |
2201 empty_target_names.append(name) | 2210 if name not in name_to_visited: |
2211 name_to_visited[name] = VisitedTarget() | |
2212 name_to_visited[name].has_empty_target = (target == None) | |
Nico
2014/09/08 21:29:02
nit: `target is None`
| |
2213 elif target != None: | |
Nico
2014/09/08 21:29:02
nit: `target is not None`
| |
2214 name_to_visited[name].has_empty_target = False | |
2215 name_to_visited[name].qualified_targets.append(qualified_target) | |
2202 | 2216 |
2203 if target_short_names: | 2217 if target_short_names: |
2204 # Write a short name to build this target. This benefits both the | 2218 # Write a short name to build this target. This benefits both the |
2205 # "build chrome" case as well as the gyp tests, which expect to be | 2219 # "build chrome" case as well as the gyp tests, which expect to be |
2206 # able to run actions and build libraries by their short name. | 2220 # able to run actions and build libraries by their short name. |
2207 master_ninja.newline() | 2221 master_ninja.newline() |
2208 master_ninja.comment('Short names for targets.') | 2222 master_ninja.comment('Short names for targets.') |
2209 for short_name in target_short_names: | 2223 for short_name in target_short_names: |
2210 master_ninja.build(short_name, 'phony', [x.FinalOutput() for x in | 2224 master_ninja.build(short_name, 'phony', [x.FinalOutput() for x in |
2211 target_short_names[short_name]]) | 2225 target_short_names[short_name]]) |
2212 | 2226 |
2227 # Write phony targets for any empty targets that weren't written yet. As | |
2228 # short names are not necessarily unique only do this for short names that | |
2229 # haven't already been output for another target. | |
2230 empty_target_names = [x for x in name_to_visited | |
2231 if name_to_visited[x].has_empty_target] | |
2213 if empty_target_names: | 2232 if empty_target_names: |
2214 # Write out any targets that were skipped because they didn't contain | |
2215 # anything interesting. This way the targets can still be built without | |
2216 # causing build errors. | |
2217 master_ninja.newline() | 2233 master_ninja.newline() |
2218 master_ninja.comment('Empty targets (output for completeness).') | 2234 master_ninja.comment('Empty targets (output for completeness).') |
2219 for name in sorted(empty_target_names): | 2235 for name in sorted(empty_target_names): |
2220 master_ninja.build(name, 'phony') | 2236 master_ninja.build(name, 'phony') |
2221 | 2237 |
2222 if all_outputs: | 2238 if all_outputs: |
2223 master_ninja.newline() | 2239 master_ninja.newline() |
2224 master_ninja.build('all', 'phony', list(all_outputs)) | 2240 master_ninja.build('all', 'phony', list(all_outputs)) |
2225 master_ninja.default(generator_flags.get('default_target', 'all')) | 2241 master_ninja.default(generator_flags.get('default_target', 'all')) |
2226 | 2242 |
2227 master_ninja_file.close() | 2243 master_ninja_file.close() |
2228 | 2244 |
2245 for short_name in \ | |
2246 [x for x in name_to_visited | |
2247 if len(name_to_visited[x].qualified_targets) > 1]: | |
2248 print 'WARNING: %s is defined in multiple places: %s' % \ | |
2249 (short_name, name_to_visited[short_name].qualified_targets) | |
Nico
2014/09/08 21:29:02
That just moves the warning from build time to gyp
sky
2014/09/08 21:50:21
Done.
| |
2250 | |
2229 | 2251 |
2230 def PerformBuild(data, configurations, params): | 2252 def PerformBuild(data, configurations, params): |
2231 options = params['options'] | 2253 options = params['options'] |
2232 for config in configurations: | 2254 for config in configurations: |
2233 builddir = os.path.join(options.toplevel_dir, 'out', config) | 2255 builddir = os.path.join(options.toplevel_dir, 'out', config) |
2234 arguments = ['ninja', '-C', builddir] | 2256 arguments = ['ninja', '-C', builddir] |
2235 print 'Building [%s]: %s' % (config, arguments) | 2257 print 'Building [%s]: %s' % (config, arguments) |
2236 subprocess.check_call(arguments) | 2258 subprocess.check_call(arguments) |
2237 | 2259 |
2238 | 2260 |
(...skipping 30 matching lines...) Expand all Loading... | |
2269 arglists.append( | 2291 arglists.append( |
2270 (target_list, target_dicts, data, params, config_name)) | 2292 (target_list, target_dicts, data, params, config_name)) |
2271 pool.map(CallGenerateOutputForConfig, arglists) | 2293 pool.map(CallGenerateOutputForConfig, arglists) |
2272 except KeyboardInterrupt, e: | 2294 except KeyboardInterrupt, e: |
2273 pool.terminate() | 2295 pool.terminate() |
2274 raise e | 2296 raise e |
2275 else: | 2297 else: |
2276 for config_name in config_names: | 2298 for config_name in config_names: |
2277 GenerateOutputForConfig(target_list, target_dicts, data, params, | 2299 GenerateOutputForConfig(target_list, target_dicts, data, params, |
2278 config_name) | 2300 config_name) |
OLD | NEW |