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 import copy | 10 import copy |
11 import gyp.common | 11 import gyp.common |
12 import os.path | 12 import os.path |
13 import re | 13 import re |
14 import shlex | 14 import shlex |
15 import subprocess | 15 import subprocess |
16 import sys | 16 import sys |
17 from gyp.common import GypError | 17 from gyp.common import GypError |
18 | 18 |
19 class XcodeSettings(object): | 19 class XcodeSettings(object): |
20 """A class that understands the gyp 'xcode_settings' object.""" | 20 """A class that understands the gyp 'xcode_settings' object.""" |
21 | 21 |
22 # Populated lazily by _SdkPath(). Shared by all XcodeSettings, so cached | 22 # Populated lazily by _SdkPath(). Shared by all XcodeSettings, so cached |
23 # at class-level for efficiency. | 23 # at class-level for efficiency. |
24 _sdk_path_cache = {} | 24 _sdk_path_cache = {} |
25 | 25 |
26 # Populated lazily by GetExtraPlistItems(). Shared by all XcodeSettings, so | 26 # Populated lazily by GetExtraPlistItems(). Shared by all XcodeSettings, so |
27 # cached at class-level for efficiency. | 27 # cached at class-level for efficiency. |
28 _plist_cache = {} | 28 _plist_cache = {} |
29 | 29 |
30 # Populated lazily by GetIOSPostbuilds. Shared by all XcodeSettings, so | |
31 # cached at class-level for efficiency. | |
32 _codesigning_key_cache = {} | |
33 | |
30 def __init__(self, spec): | 34 def __init__(self, spec): |
31 self.spec = spec | 35 self.spec = spec |
32 | 36 |
33 self.isIOS = False | 37 self.isIOS = False |
34 | 38 |
35 # Per-target 'xcode_settings' are pushed down into configs earlier by gyp. | 39 # Per-target 'xcode_settings' are pushed down into configs earlier by gyp. |
36 # This means self.xcode_settings[config] always contains all settings | 40 # This means self.xcode_settings[config] always contains all settings |
37 # for that config -- the per-target settings as well. Settings that are | 41 # for that config -- the per-target settings as well. Settings that are |
38 # the same for all configs are implicitly per-target settings. | 42 # the same for all configs are implicitly per-target settings. |
39 self.xcode_settings = {} | 43 self.xcode_settings = {} |
40 configs = spec['configurations'] | 44 configs = spec['configurations'] |
41 for configname, config in configs.iteritems(): | 45 for configname, config in configs.iteritems(): |
42 self.xcode_settings[configname] = config.get('xcode_settings', {}) | 46 self.xcode_settings[configname] = config.get('xcode_settings', {}) |
47 self._ConvertConditionalKeys(configname) | |
43 if self.xcode_settings[configname].get('IPHONEOS_DEPLOYMENT_TARGET', | 48 if self.xcode_settings[configname].get('IPHONEOS_DEPLOYMENT_TARGET', |
44 None): | 49 None): |
45 self.isIOS = True | 50 self.isIOS = True |
46 | 51 |
47 # If you need this, speak up at http://crbug.com/122592 | |
48 conditional_keys = [key for key in self.xcode_settings[configname] | |
49 if key.endswith(']')] | |
50 if conditional_keys: | |
51 print 'Warning: Conditional keys not implemented, ignoring:', \ | |
52 ' '.join(conditional_keys) | |
53 for key in conditional_keys: | |
54 del self.xcode_settings[configname][key] | |
55 | |
56 # This is only non-None temporarily during the execution of some methods. | 52 # This is only non-None temporarily during the execution of some methods. |
57 self.configname = None | 53 self.configname = None |
58 | 54 |
59 # Used by _AdjustLibrary to match .a and .dylib entries in libraries. | 55 # Used by _AdjustLibrary to match .a and .dylib entries in libraries. |
60 self.library_re = re.compile(r'^lib([^/]+)\.(a|dylib)$') | 56 self.library_re = re.compile(r'^lib([^/]+)\.(a|dylib)$') |
61 | 57 |
58 def _ConvertConditionalKeys(self, configname): | |
Nico
2013/10/15 02:12:57
docstring
justincohen
2013/10/15 16:47:33
Done.
| |
59 settings = self.xcode_settings[configname] | |
60 conditional_keys = [key for key in settings if key.endswith(']')] | |
61 for key in conditional_keys: | |
62 # If you need more, speak up at http://crbug.com/122592 | |
Nico
2013/10/15 02:12:57
indented too far
justincohen
2013/10/15 16:47:33
Done.
| |
63 if key.endswith("[sdk=iphoneos*]"): | |
64 if configname.endswith("iphoneos"): | |
65 new_key = key.split("[")[0] | |
66 settings[new_key] = settings[key] | |
67 else: | |
68 print 'Warning: Conditional keys not implemented, ignoring:', \ | |
69 ' '.join(conditional_keys) | |
70 del settings[key] | |
71 | |
62 def _Settings(self): | 72 def _Settings(self): |
63 assert self.configname | 73 assert self.configname |
64 return self.xcode_settings[self.configname] | 74 return self.xcode_settings[self.configname] |
65 | 75 |
66 def _Test(self, test_key, cond_key, default): | 76 def _Test(self, test_key, cond_key, default): |
67 return self._Settings().get(test_key, default) == cond_key | 77 return self._Settings().get(test_key, default) == cond_key |
68 | 78 |
69 def _Appendf(self, lst, test_key, format_str, default=None): | 79 def _Appendf(self, lst, test_key, format_str, default=None): |
70 if test_key in self._Settings(): | 80 if test_key in self._Settings(): |
71 lst.append(format_str % str(self._Settings()[test_key])) | 81 lst.append(format_str % str(self._Settings()[test_key])) |
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
737 self._Test( | 747 self._Test( |
738 'DEBUG_INFORMATION_FORMAT', 'dwarf-with-dsym', default='dwarf') and | 748 'DEBUG_INFORMATION_FORMAT', 'dwarf-with-dsym', default='dwarf') and |
739 self.spec['type'] != 'static_library'): | 749 self.spec['type'] != 'static_library'): |
740 if not quiet: | 750 if not quiet: |
741 result.append('echo DSYMUTIL\\(%s\\)' % self.spec['target_name']) | 751 result.append('echo DSYMUTIL\\(%s\\)' % self.spec['target_name']) |
742 result.append('dsymutil %s -o %s' % (output_binary, output + '.dSYM')) | 752 result.append('dsymutil %s -o %s' % (output_binary, output + '.dSYM')) |
743 | 753 |
744 self.configname = None | 754 self.configname = None |
745 return result | 755 return result |
746 | 756 |
747 def GetTargetPostbuilds(self, configname, output, output_binary, quiet=False): | 757 def GetTargetPostbuilds(self, configname, output, output_binary, quiet=False): |
Nico
2013/10/15 02:12:57
Can you change make.py to call AddImplicitPostbui
justincohen
2013/10/15 16:47:33
Done.
| |
748 """Returns a list of shell commands that contain the shell commands | 758 """Returns a list of shell commands that contain the shell commands |
749 to run as postbuilds for this target, before the actual postbuilds.""" | 759 to run as postbuilds for this target, before the actual postbuilds.""" |
750 # dSYMs need to build before stripping happens. | 760 # dSYMs need to build before stripping happens. |
751 return ( | 761 return ( |
752 self._GetDebugInfoPostbuilds(configname, output, output_binary, quiet) + | 762 self._GetDebugInfoPostbuilds(configname, output, output_binary, quiet) + |
753 self._GetStripPostbuilds(configname, output_binary, quiet)) | 763 self._GetStripPostbuilds(configname, output_binary, quiet)) |
754 | 764 |
765 def _GetIOSPostbuilds(self, configname, is_app, output_binary): | |
766 """Return a shell command to codesign the iOS output binary so it can | |
767 be deployed to a device. This should be run as the very last step of the | |
768 build.""" | |
769 if not (self.isIOS and is_app): | |
Nico
2013/10/15 02:12:57
this can read self.spec['type'], no need to for th
justincohen
2013/10/15 16:47:33
Done.
| |
770 return [] | |
771 | |
772 self.configname = configname | |
773 identity = self._Settings().get('CODE_SIGN_IDENTITY') | |
774 if identity == None: | |
775 return [] | |
Nico
2013/10/15 02:12:57
now self.configname is wrong
Nico
2013/10/15 02:33:27
Also, setting this to "" (the empty string) appare
justincohen
2013/10/15 16:47:33
Done.
justincohen
2013/10/15 16:47:33
Done
On 2013/10/15 02:33:27, Nico wrote:
| |
776 if identity not in XcodeSettings._codesigning_key_cache: | |
777 proc = subprocess.Popen(['security', 'find-identity', '-p', 'codesigning', | |
778 '-v'], stdout=subprocess.PIPE) | |
Nico
2013/10/15 02:19:29
why -v here?
Nico
2013/10/15 02:22:28
Ignore this, I misread the man page for `security`
justincohen
2013/10/15 16:47:33
Done.
justincohen
2013/10/15 16:47:33
Done.
| |
779 output = proc.communicate()[0].strip() | |
780 key = None | |
781 for item in output.split("\n"): | |
782 if identity in item: | |
783 assert key == None, ( | |
784 "Multiple codesigning identities for identity: %s" % | |
785 identity) | |
786 key = item.split(' ')[1] | |
787 XcodeSettings._codesigning_key_cache[identity] = key | |
788 self.configname = None | |
789 key = XcodeSettings._codesigning_key_cache[identity] | |
790 if key: | |
791 return ["/usr/bin/codesign -v --force --sign %s %s" % | |
Nico
2013/10/15 02:12:57
the rest of this file uses ' quotes
why "/usr/bin
justincohen
2013/10/15 16:47:33
Yeah, it was as verbose. I removed it.
On 2013/1
| |
792 (key, output_binary)] | |
793 return [] | |
794 | |
795 def AddImplicitPostbuilds(self, configname, is_app, output, output_binary, | |
796 postbuilds, quiet=False): | |
Nico
2013/10/15 02:12:57
docstring
justincohen
2013/10/15 16:47:33
Done.
| |
797 assert output_binary is not None | |
798 pre = self.GetTargetPostbuilds(configname, output, output_binary, quiet) | |
799 post = self._GetIOSPostbuilds(configname, is_app, output_binary) | |
800 return (pre + postbuilds + post) | |
Nico
2013/10/15 02:12:57
no parens
justincohen
2013/10/15 16:47:33
Done.
| |
801 | |
755 def _AdjustLibrary(self, library, config_name=None): | 802 def _AdjustLibrary(self, library, config_name=None): |
756 if library.endswith('.framework'): | 803 if library.endswith('.framework'): |
757 l = '-framework ' + os.path.splitext(os.path.basename(library))[0] | 804 l = '-framework ' + os.path.splitext(os.path.basename(library))[0] |
758 else: | 805 else: |
759 m = self.library_re.match(library) | 806 m = self.library_re.match(library) |
760 if m: | 807 if m: |
761 l = '-l' + m.group(1) | 808 l = '-l' + m.group(1) |
762 else: | 809 else: |
763 l = library | 810 l = library |
764 return l.replace('$(SDKROOT)', self._SdkPath(config_name)) | 811 return l.replace('$(SDKROOT)', self._SdkPath(config_name)) |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1227 new_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos' | 1274 new_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos' |
1228 target_dict['configurations'][new_config_name] = new_config_dict | 1275 target_dict['configurations'][new_config_name] = new_config_dict |
1229 return targets | 1276 return targets |
1230 | 1277 |
1231 def CloneConfigurationForDeviceAndEmulator(target_dicts): | 1278 def CloneConfigurationForDeviceAndEmulator(target_dicts): |
1232 """If |target_dicts| contains any iOS targets, automatically create -iphoneos | 1279 """If |target_dicts| contains any iOS targets, automatically create -iphoneos |
1233 targets for iOS device builds.""" | 1280 targets for iOS device builds.""" |
1234 if _HasIOSTarget(target_dicts): | 1281 if _HasIOSTarget(target_dicts): |
1235 return _AddIOSDeviceConfigurations(target_dicts) | 1282 return _AddIOSDeviceConfigurations(target_dicts) |
1236 return target_dicts | 1283 return target_dicts |
OLD | NEW |