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 """ | 5 """ |
6 This module contains classes that help to emulate xcodebuild behavior on top of | 6 This module contains classes that help to emulate xcodebuild behavior on top of |
7 other build systems, such as make and ninja. | 7 other build systems, such as make and ninja. |
8 """ | 8 """ |
9 | 9 |
| 10 from __future__ import print_function |
| 11 |
10 import copy | 12 import copy |
11 import gyp.common | 13 import gyp.common |
12 import os | 14 import os |
13 import os.path | 15 import os.path |
14 import re | 16 import re |
15 import shlex | 17 import shlex |
16 import subprocess | 18 import subprocess |
17 import sys | 19 import sys |
18 import tempfile | 20 import tempfile |
19 from gyp.common import GypError | 21 from gyp.common import GypError |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 expanded_archs = [] | 68 expanded_archs = [] |
67 for arch in archs: | 69 for arch in archs: |
68 if self.variable_pattern.match(arch): | 70 if self.variable_pattern.match(arch): |
69 variable = arch | 71 variable = arch |
70 try: | 72 try: |
71 variable_expansion = variable_mapping[variable] | 73 variable_expansion = variable_mapping[variable] |
72 for arch in variable_expansion: | 74 for arch in variable_expansion: |
73 if arch not in expanded_archs: | 75 if arch not in expanded_archs: |
74 expanded_archs.append(arch) | 76 expanded_archs.append(arch) |
75 except KeyError as e: | 77 except KeyError as e: |
76 print 'Warning: Ignoring unsupported variable "%s".' % variable | 78 print('Warning: Ignoring unsupported variable "%s".' % variable) |
77 elif arch not in expanded_archs: | 79 elif arch not in expanded_archs: |
78 expanded_archs.append(arch) | 80 expanded_archs.append(arch) |
79 return expanded_archs | 81 return expanded_archs |
80 | 82 |
81 def ActiveArchs(self, archs, valid_archs, sdkroot): | 83 def ActiveArchs(self, archs, valid_archs, sdkroot): |
82 """Expands variables references in ARCHS, and filter by VALID_ARCHS if it | 84 """Expands variables references in ARCHS, and filter by VALID_ARCHS if it |
83 is defined (if not set, Xcode accept any value in ARCHS, otherwise, only | 85 is defined (if not set, Xcode accept any value in ARCHS, otherwise, only |
84 values present in VALID_ARCHS are kept).""" | 86 values present in VALID_ARCHS are kept).""" |
85 expanded_archs = self._ExpandArchs(archs or self._default, sdkroot or '') | 87 expanded_archs = self._ExpandArchs(archs or self._default, sdkroot or '') |
86 if valid_archs: | 88 if valid_archs: |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 self.isIOS = False | 166 self.isIOS = False |
165 self.mac_toolchain_dir = None | 167 self.mac_toolchain_dir = None |
166 self.header_map_path = None | 168 self.header_map_path = None |
167 | 169 |
168 # Per-target 'xcode_settings' are pushed down into configs earlier by gyp. | 170 # Per-target 'xcode_settings' are pushed down into configs earlier by gyp. |
169 # This means self.xcode_settings[config] always contains all settings | 171 # This means self.xcode_settings[config] always contains all settings |
170 # for that config -- the per-target settings as well. Settings that are | 172 # for that config -- the per-target settings as well. Settings that are |
171 # the same for all configs are implicitly per-target settings. | 173 # the same for all configs are implicitly per-target settings. |
172 self.xcode_settings = {} | 174 self.xcode_settings = {} |
173 configs = spec['configurations'] | 175 configs = spec['configurations'] |
174 for configname, config in configs.iteritems(): | 176 for configname, config in configs.items(): |
175 self.xcode_settings[configname] = config.get('xcode_settings', {}) | 177 self.xcode_settings[configname] = config.get('xcode_settings', {}) |
176 self._ConvertConditionalKeys(configname) | 178 self._ConvertConditionalKeys(configname) |
177 if self.xcode_settings[configname].get('IPHONEOS_DEPLOYMENT_TARGET', | 179 if self.xcode_settings[configname].get('IPHONEOS_DEPLOYMENT_TARGET', |
178 None): | 180 None): |
179 self.isIOS = True | 181 self.isIOS = True |
180 | 182 |
181 # This is only non-None temporarily during the execution of some methods. | 183 # This is only non-None temporarily during the execution of some methods. |
182 self.configname = None | 184 self.configname = None |
183 | 185 |
184 # Used by _AdjustLibrary to match .a and .dylib entries in libraries. | 186 # Used by _AdjustLibrary to match .a and .dylib entries in libraries. |
185 self.library_re = re.compile(r'^lib([^/]+)\.(a|dylib)$') | 187 self.library_re = re.compile(r'^lib([^/]+)\.(a|dylib)$') |
186 | 188 |
187 def _ConvertConditionalKeys(self, configname): | 189 def _ConvertConditionalKeys(self, configname): |
188 """Converts or warns on conditional keys. Xcode supports conditional keys, | 190 """Converts or warns on conditional keys. Xcode supports conditional keys, |
189 such as CODE_SIGN_IDENTITY[sdk=iphoneos*]. This is a partial implementation | 191 such as CODE_SIGN_IDENTITY[sdk=iphoneos*]. This is a partial implementation |
190 with some keys converted while the rest force a warning.""" | 192 with some keys converted while the rest force a warning.""" |
191 settings = self.xcode_settings[configname] | 193 settings = self.xcode_settings[configname] |
192 conditional_keys = [key for key in settings if key.endswith(']')] | 194 conditional_keys = [key for key in settings if key.endswith(']')] |
193 for key in conditional_keys: | 195 for key in conditional_keys: |
194 # If you need more, speak up at http://crbug.com/122592 | 196 # If you need more, speak up at http://crbug.com/122592 |
195 if key.endswith("[sdk=iphoneos*]"): | 197 if key.endswith("[sdk=iphoneos*]"): |
196 if configname.endswith("iphoneos"): | 198 if configname.endswith("iphoneos"): |
197 new_key = key.split("[")[0] | 199 new_key = key.split("[")[0] |
198 settings[new_key] = settings[key] | 200 settings[new_key] = settings[key] |
199 else: | 201 else: |
200 print 'Warning: Conditional keys not implemented, ignoring:', \ | 202 print('Warning: Conditional keys not implemented, ignoring:', \ |
201 ' '.join(conditional_keys) | 203 ' '.join(conditional_keys)) |
202 del settings[key] | 204 del settings[key] |
203 | 205 |
204 def _Settings(self): | 206 def _Settings(self): |
205 assert self.configname | 207 assert self.configname |
206 return self.xcode_settings[self.configname] | 208 return self.xcode_settings[self.configname] |
207 | 209 |
208 def _Test(self, test_key, cond_key, default): | 210 def _Test(self, test_key, cond_key, default): |
209 return self._Settings().get(test_key, default) == cond_key | 211 return self._Settings().get(test_key, default) == cond_key |
210 | 212 |
211 def _Appendf(self, lst, test_key, format_str, default=None): | 213 def _Appendf(self, lst, test_key, format_str, default=None): |
212 if test_key in self._Settings(): | 214 if test_key in self._Settings(): |
213 lst.append(format_str % str(self._Settings()[test_key])) | 215 lst.append(format_str % str(self._Settings()[test_key])) |
214 elif default: | 216 elif default: |
215 lst.append(format_str % str(default)) | 217 lst.append(format_str % str(default)) |
216 | 218 |
217 def _WarnUnimplemented(self, test_key): | 219 def _WarnUnimplemented(self, test_key): |
218 if test_key in self._Settings(): | 220 if test_key in self._Settings(): |
219 print 'Warning: Ignoring not yet implemented key "%s".' % test_key | 221 print('Warning: Ignoring not yet implemented key "%s".' % test_key) |
220 | 222 |
221 def IsBinaryOutputFormat(self, configname): | 223 def IsBinaryOutputFormat(self, configname): |
222 default = "binary" if self.isIOS else "xml" | 224 default = "binary" if self.isIOS else "xml" |
223 format = self.xcode_settings[configname].get('INFOPLIST_OUTPUT_FORMAT', | 225 format = self.xcode_settings[configname].get('INFOPLIST_OUTPUT_FORMAT', |
224 default) | 226 default) |
225 return format == "binary" | 227 return format == "binary" |
226 | 228 |
227 def IsIosFramework(self): | 229 def IsIosFramework(self): |
228 return self.spec['type'] == 'shared_library' and self._IsBundle() and \ | 230 return self.spec['type'] == 'shared_library' and self._IsBundle() and \ |
229 self.isIOS | 231 self.isIOS |
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
899 def GetPerTargetSettings(self): | 901 def GetPerTargetSettings(self): |
900 """Gets a list of all the per-target settings. This will only fetch keys | 902 """Gets a list of all the per-target settings. This will only fetch keys |
901 whose values are the same across all configurations.""" | 903 whose values are the same across all configurations.""" |
902 first_pass = True | 904 first_pass = True |
903 result = {} | 905 result = {} |
904 for configname in sorted(self.xcode_settings.keys()): | 906 for configname in sorted(self.xcode_settings.keys()): |
905 if first_pass: | 907 if first_pass: |
906 result = dict(self.xcode_settings[configname]) | 908 result = dict(self.xcode_settings[configname]) |
907 first_pass = False | 909 first_pass = False |
908 else: | 910 else: |
909 for key, value in self.xcode_settings[configname].iteritems(): | 911 for key, value in self.xcode_settings[configname].items(): |
910 if key not in result: | 912 if key not in result: |
911 continue | 913 continue |
912 elif result[key] != value: | 914 elif result[key] != value: |
913 del result[key] | 915 del result[key] |
914 return result | 916 return result |
915 | 917 |
916 def GetPerConfigSetting(self, setting, configname, default=None): | 918 def GetPerConfigSetting(self, setting, configname, default=None): |
917 if configname in self.xcode_settings: | 919 if configname in self.xcode_settings: |
918 return self.xcode_settings[configname].get(setting, default) | 920 return self.xcode_settings[configname].get(setting, default) |
919 else: | 921 else: |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1010 | 1012 |
1011 settings = self.xcode_settings[configname] | 1013 settings = self.xcode_settings[configname] |
1012 key = self._GetIOSCodeSignIdentityKey(settings) | 1014 key = self._GetIOSCodeSignIdentityKey(settings) |
1013 if not key: | 1015 if not key: |
1014 return [] | 1016 return [] |
1015 | 1017 |
1016 # Warn for any unimplemented signing xcode keys. | 1018 # Warn for any unimplemented signing xcode keys. |
1017 unimpl = ['OTHER_CODE_SIGN_FLAGS'] | 1019 unimpl = ['OTHER_CODE_SIGN_FLAGS'] |
1018 unimpl = set(unimpl) & set(self.xcode_settings[configname].keys()) | 1020 unimpl = set(unimpl) & set(self.xcode_settings[configname].keys()) |
1019 if unimpl: | 1021 if unimpl: |
1020 print 'Warning: Some codesign keys not implemented, ignoring: %s' % ( | 1022 print('Warning: Some codesign keys not implemented, ignoring: %s' % ( |
1021 ', '.join(sorted(unimpl))) | 1023 ', '.join(sorted(unimpl)))) |
1022 | 1024 |
1023 return ['%s code-sign-bundle "%s" "%s" "%s"' % ( | 1025 return ['%s code-sign-bundle "%s" "%s" "%s"' % ( |
1024 os.path.join('${TARGET_BUILD_DIR}', 'gyp-mac-tool'), key, | 1026 os.path.join('${TARGET_BUILD_DIR}', 'gyp-mac-tool'), key, |
1025 settings.get('CODE_SIGN_ENTITLEMENTS', ''), | 1027 settings.get('CODE_SIGN_ENTITLEMENTS', ''), |
1026 settings.get('PROVISIONING_PROFILE', '')) | 1028 settings.get('PROVISIONING_PROFILE', '')) |
1027 ] | 1029 ] |
1028 | 1030 |
1029 def _GetIOSCodeSignIdentityKey(self, settings): | 1031 def _GetIOSCodeSignIdentityKey(self, settings): |
1030 identity = settings.get('CODE_SIGN_IDENTITY') | 1032 identity = settings.get('CODE_SIGN_IDENTITY') |
1031 if not identity: | 1033 if not identity: |
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1614 assert '${' not in dependee, 'Nested variables not supported: ' + dependee | 1616 assert '${' not in dependee, 'Nested variables not supported: ' + dependee |
1615 return matches | 1617 return matches |
1616 | 1618 |
1617 try: | 1619 try: |
1618 # Topologically sort, and then reverse, because we used an edge definition | 1620 # Topologically sort, and then reverse, because we used an edge definition |
1619 # that's inverted from the expected result of this function (see comment | 1621 # that's inverted from the expected result of this function (see comment |
1620 # above). | 1622 # above). |
1621 order = gyp.common.TopologicallySorted(env.keys(), GetEdges) | 1623 order = gyp.common.TopologicallySorted(env.keys(), GetEdges) |
1622 order.reverse() | 1624 order.reverse() |
1623 return order | 1625 return order |
1624 except gyp.common.CycleError, e: | 1626 except gyp.common.CycleError as e: |
1625 raise GypError( | 1627 raise GypError( |
1626 'Xcode environment variables are cyclically dependent: ' + str(e.nodes)) | 1628 'Xcode environment variables are cyclically dependent: ' + str(e.nodes)) |
1627 | 1629 |
1628 | 1630 |
1629 def GetSortedXcodeEnv(xcode_settings, built_products_dir, srcroot, | 1631 def GetSortedXcodeEnv(xcode_settings, built_products_dir, srcroot, |
1630 configuration, additional_settings=None): | 1632 configuration, additional_settings=None): |
1631 env = _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, | 1633 env = _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, |
1632 additional_settings) | 1634 additional_settings) |
1633 return [(key, env[key]) for key in _TopologicallySortedEnvVarKeys(env)] | 1635 return [(key, env[key]) for key in _TopologicallySortedEnvVarKeys(env)] |
1634 | 1636 |
(...skipping 16 matching lines...) Expand all Loading... |
1651 for target_dict in targets.values(): | 1653 for target_dict in targets.values(): |
1652 for config in target_dict['configurations'].values(): | 1654 for config in target_dict['configurations'].values(): |
1653 if config.get('xcode_settings', {}).get('IPHONEOS_DEPLOYMENT_TARGET'): | 1655 if config.get('xcode_settings', {}).get('IPHONEOS_DEPLOYMENT_TARGET'): |
1654 return True | 1656 return True |
1655 return False | 1657 return False |
1656 | 1658 |
1657 | 1659 |
1658 def _AddIOSDeviceConfigurations(targets): | 1660 def _AddIOSDeviceConfigurations(targets): |
1659 """Clone all targets and append -iphoneos to the name. Configure these targets | 1661 """Clone all targets and append -iphoneos to the name. Configure these targets |
1660 to build for iOS devices and use correct architectures for those builds.""" | 1662 to build for iOS devices and use correct architectures for those builds.""" |
1661 for target_dict in targets.itervalues(): | 1663 for target_dict in targets.values(): |
1662 toolset = target_dict['toolset'] | 1664 toolset = target_dict['toolset'] |
1663 configs = target_dict['configurations'] | 1665 configs = target_dict['configurations'] |
1664 for config_name, config_dict in dict(configs).iteritems(): | 1666 for config_name, config_dict in dict(configs).items(): |
1665 iphoneos_config_dict = copy.deepcopy(config_dict) | 1667 iphoneos_config_dict = copy.deepcopy(config_dict) |
1666 configs[config_name + '-iphoneos'] = iphoneos_config_dict | 1668 configs[config_name + '-iphoneos'] = iphoneos_config_dict |
1667 configs[config_name + '-iphonesimulator'] = config_dict | 1669 configs[config_name + '-iphonesimulator'] = config_dict |
1668 if toolset == 'target': | 1670 if toolset == 'target': |
1669 iphoneos_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos' | 1671 iphoneos_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos' |
1670 return targets | 1672 return targets |
1671 | 1673 |
1672 def CloneConfigurationForDeviceAndEmulator(target_dicts): | 1674 def CloneConfigurationForDeviceAndEmulator(target_dicts): |
1673 """If |target_dicts| contains any iOS targets, automatically create -iphoneos | 1675 """If |target_dicts| contains any iOS targets, automatically create -iphoneos |
1674 targets for iOS device builds.""" | 1676 targets for iOS device builds.""" |
1675 if _HasIOSTarget(target_dicts): | 1677 if _HasIOSTarget(target_dicts): |
1676 return _AddIOSDeviceConfigurations(target_dicts) | 1678 return _AddIOSDeviceConfigurations(target_dicts) |
1677 return target_dicts | 1679 return target_dicts |
OLD | NEW |