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 """Utility functions shared amongst the Windows generators.""" | 5 """Utility functions shared amongst the Windows generators.""" |
6 | 6 |
7 import copy | 7 import copy |
| 8 import os |
| 9 |
| 10 |
| 11 _TARGET_TYPE_EXT = { |
| 12 'executable': '.exe', |
| 13 'shared_library': '.dll' |
| 14 } |
| 15 |
| 16 |
| 17 def _GetLargePdbShimCcPath(): |
| 18 """Returns the path of the large_pdb_shim.cc file.""" |
| 19 this_dir = os.path.abspath(os.path.dirname(__file__)) |
| 20 src_dir = os.path.abspath(os.path.join(this_dir, '..', '..')) |
| 21 win_data_dir = os.path.join(src_dir, 'data', 'win') |
| 22 large_pdb_shim_cc = os.path.join(win_data_dir, 'large-pdb-shim.cc') |
| 23 return large_pdb_shim_cc |
| 24 |
| 25 |
| 26 def _DeepCopySomeKeys(in_dict, keys): |
| 27 """Performs a partial deep-copy on |in_dict|, only copying the keys in |keys|. |
| 28 |
| 29 Arguments: |
| 30 in_dict: The dictionary to copy. |
| 31 keys: The keys to be copied. If a key is in this list and doesn't exist in |
| 32 |in_dict| this is not an error. |
| 33 Returns: |
| 34 The partially deep-copied dictionary. |
| 35 """ |
| 36 d = {} |
| 37 for key in keys: |
| 38 if key not in in_dict: |
| 39 continue |
| 40 d[key] = copy.deepcopy(in_dict[key]) |
| 41 return d |
| 42 |
| 43 |
| 44 def _SuffixName(name, suffix): |
| 45 """Add a suffix to the end of a target. |
| 46 |
| 47 Arguments: |
| 48 name: name of the target (foo#target) |
| 49 suffix: the suffix to be added |
| 50 Returns: |
| 51 Target name with suffix added (foo_suffix#target) |
| 52 """ |
| 53 parts = name.rsplit('#', 1) |
| 54 parts[0] = '%s_%s' % (parts[0], suffix) |
| 55 return '#'.join(parts) |
| 56 |
8 | 57 |
9 def _ShardName(name, number): | 58 def _ShardName(name, number): |
10 """Add a shard number to the end of a target. | 59 """Add a shard number to the end of a target. |
11 | 60 |
12 Arguments: | 61 Arguments: |
13 name: name of the target (foo#target) | 62 name: name of the target (foo#target) |
14 number: shard number | 63 number: shard number |
15 Returns: | 64 Returns: |
16 Target name with shard added (foo_1#target) | 65 Target name with shard added (foo_1#target) |
17 """ | 66 """ |
18 parts = name.rsplit('#', 1) | 67 return _SuffixName(name, str(number)) |
19 parts[0] = '%s_%d' % (parts[0], number) | |
20 return '#'.join(parts) | |
21 | 68 |
22 | 69 |
23 def ShardTargets(target_list, target_dicts): | 70 def ShardTargets(target_list, target_dicts): |
24 """Shard some targets apart to work around the linkers limits. | 71 """Shard some targets apart to work around the linkers limits. |
25 | 72 |
26 Arguments: | 73 Arguments: |
27 target_list: List of target pairs: 'base/base.gyp:base'. | 74 target_list: List of target pairs: 'base/base.gyp:base'. |
28 target_dicts: Dict of target properties keyed on target pair. | 75 target_dicts: Dict of target properties keyed on target pair. |
29 Returns: | 76 Returns: |
30 Tuple of the new sharded versions of the inputs. | 77 Tuple of the new sharded versions of the inputs. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 new_dependencies = [] | 112 new_dependencies = [] |
66 for d in dependencies: | 113 for d in dependencies: |
67 if d in targets_to_shard: | 114 if d in targets_to_shard: |
68 for i in range(targets_to_shard[d]): | 115 for i in range(targets_to_shard[d]): |
69 new_dependencies.append(_ShardName(d, i)) | 116 new_dependencies.append(_ShardName(d, i)) |
70 else: | 117 else: |
71 new_dependencies.append(d) | 118 new_dependencies.append(d) |
72 new_target_dicts[t]['dependencies'] = new_dependencies | 119 new_target_dicts[t]['dependencies'] = new_dependencies |
73 | 120 |
74 return (new_target_list, new_target_dicts) | 121 return (new_target_list, new_target_dicts) |
| 122 |
| 123 |
| 124 def InsertLargePdbShims(target_list, target_dicts, vars): |
| 125 """Insert a shim target that forces the linker to use 4KB pagesize PDBs. |
| 126 |
| 127 This is a workaround for targets with PDBs greater than 1GB in size, the |
| 128 limit for the 1KB pagesize PDBs created by the linker by default. |
| 129 |
| 130 Arguments: |
| 131 target_list: List of target pairs: 'base/base.gyp:base'. |
| 132 target_dicts: Dict of target properties keyed on target pair. |
| 133 vars: A dictionary of common GYP variables with generator-specific values. |
| 134 Returns: |
| 135 Tuple of the shimmed version of the inputs. |
| 136 """ |
| 137 # Determine which targets need shimming. |
| 138 targets_to_shim = [] |
| 139 for t in target_dicts: |
| 140 target_dict = target_dicts[t] |
| 141 # We only want to shim targets that have msvs_large_pdb enabled. |
| 142 if not int(target_dict.get('msvs_large_pdb', 0)): |
| 143 continue |
| 144 # This is intended for executable, shared_library and loadable_module |
| 145 # targets where every configuration is set up to produce a PDB output. |
| 146 # If any of these conditions is not true then the shim logic will fail |
| 147 # below. |
| 148 targets_to_shim.append(t) |
| 149 |
| 150 large_pdb_shim_cc = _GetLargePdbShimCcPath() |
| 151 |
| 152 for t in targets_to_shim: |
| 153 target_dict = target_dicts[t] |
| 154 target_name = target_dict.get('target_name') |
| 155 |
| 156 base_dict = _DeepCopySomeKeys(target_dict, |
| 157 ['configurations', 'default_configuration', 'toolset']) |
| 158 |
| 159 # This is the dict for copying the source file (part of the GYP tree) |
| 160 # to the intermediate directory of the project. This is necessary because |
| 161 # we can't always build a relative path to the shim source file (on Windows |
| 162 # GYP and the project may be on different drives), and Ninja hates absolute |
| 163 # paths (it ends up generating the .obj and .obj.d alongside the source |
| 164 # file, polluting GYPs tree). |
| 165 copy_suffix = '_large_pdb_copy' |
| 166 copy_target_name = target_name + '_' + copy_suffix |
| 167 full_copy_target_name = _SuffixName(t, copy_suffix) |
| 168 shim_cc_basename = os.path.basename(large_pdb_shim_cc) |
| 169 shim_cc_dir = vars['SHARED_INTERMEDIATE_DIR'] + '/' + copy_target_name |
| 170 shim_cc_path = shim_cc_dir + '/' + shim_cc_basename |
| 171 copy_dict = copy.deepcopy(base_dict) |
| 172 copy_dict['target_name'] = copy_target_name |
| 173 copy_dict['type'] = 'none' |
| 174 copy_dict['sources'] = [ large_pdb_shim_cc ] |
| 175 copy_dict['copies'] = [{ |
| 176 'destination': shim_cc_dir, |
| 177 'files': [ large_pdb_shim_cc ] |
| 178 }] |
| 179 |
| 180 # This is the dict for the PDB generating shim target. It depends on the |
| 181 # copy target. |
| 182 shim_suffix = '_large_pdb_shim' |
| 183 shim_target_name = target_name + '_' + shim_suffix |
| 184 full_shim_target_name = _SuffixName(t, shim_suffix) |
| 185 shim_dict = copy.deepcopy(base_dict) |
| 186 shim_dict['target_name'] = shim_target_name |
| 187 shim_dict['type'] = 'static_library' |
| 188 shim_dict['sources'] = [ shim_cc_path ] |
| 189 shim_dict['dependencies'] = [ full_copy_target_name ] |
| 190 |
| 191 # Set up the shim to output its PDB to the same location as the final linker |
| 192 # target. |
| 193 for config in shim_dict.get('configurations').itervalues(): |
| 194 msvs = config.setdefault('msvs_settings') |
| 195 |
| 196 linker = msvs.pop('VCLinkerTool') # We want to clear this dict. |
| 197 pdb_path = linker.get('ProgramDatabaseFile') |
| 198 |
| 199 compiler = msvs.setdefault('VCCLCompilerTool', {}) |
| 200 compiler.setdefault('DebugInformationFormat', '3') |
| 201 compiler.setdefault('ProgramDataBaseFileName', pdb_path) |
| 202 |
| 203 # Add the new targets. |
| 204 target_list.append(full_copy_target_name) |
| 205 target_list.append(full_shim_target_name) |
| 206 target_dicts[full_copy_target_name] = copy_dict |
| 207 target_dicts[full_shim_target_name] = shim_dict |
| 208 |
| 209 # Update the original target to depend on the shim target. |
| 210 target_dict.setdefault('dependencies', []).append(full_shim_target_name) |
| 211 |
| 212 return (target_list, target_dicts) |
OLD | NEW |