Index: pylib/gyp/xcode_emulation.py |
=================================================================== |
--- pylib/gyp/xcode_emulation.py (revision 1755) |
+++ pylib/gyp/xcode_emulation.py (working copy) |
@@ -27,6 +27,10 @@ |
# cached at class-level for efficiency. |
_plist_cache = {} |
+ # Populated lazily by GetIOSPostbuilds. Shared by all XcodeSettings, so |
+ # cached at class-level for efficiency. |
+ _codesigning_key_cache = {} |
+ |
def __init__(self, spec): |
self.spec = spec |
@@ -40,25 +44,34 @@ |
configs = spec['configurations'] |
for configname, config in configs.iteritems(): |
self.xcode_settings[configname] = config.get('xcode_settings', {}) |
+ self._ConvertConditionalKeys(configname) |
if self.xcode_settings[configname].get('IPHONEOS_DEPLOYMENT_TARGET', |
None): |
self.isIOS = True |
- # If you need this, speak up at http://crbug.com/122592 |
- conditional_keys = [key for key in self.xcode_settings[configname] |
- if key.endswith(']')] |
- if conditional_keys: |
- print 'Warning: Conditional keys not implemented, ignoring:', \ |
- ' '.join(conditional_keys) |
- for key in conditional_keys: |
- del self.xcode_settings[configname][key] |
- |
# This is only non-None temporarily during the execution of some methods. |
self.configname = None |
# Used by _AdjustLibrary to match .a and .dylib entries in libraries. |
self.library_re = re.compile(r'^lib([^/]+)\.(a|dylib)$') |
+ def _ConvertConditionalKeys(self, configname): |
+ """Converts or warns on conditional keys. Xcode supports conditional keys, |
+ such as CODE_SIGN_IDENTITY[sdk=iphoneos*]. This is a partial implementation |
+ with some keys converted while the rest force a warning.""" |
+ settings = self.xcode_settings[configname] |
+ conditional_keys = [key for key in settings if key.endswith(']')] |
+ for key in conditional_keys: |
+ # If you need more, speak up at http://crbug.com/122592 |
+ if key.endswith("[sdk=iphoneos*]"): |
+ if configname.endswith("iphoneos"): |
+ new_key = key.split("[")[0] |
+ settings[new_key] = settings[key] |
+ else: |
+ print 'Warning: Conditional keys not implemented, ignoring:', \ |
+ ' '.join(conditional_keys) |
+ del settings[key] |
+ |
def _Settings(self): |
assert self.configname |
return self.xcode_settings[self.configname] |
@@ -744,7 +757,8 @@ |
self.configname = None |
return result |
- def GetTargetPostbuilds(self, configname, output, output_binary, quiet=False): |
+ def _GetTargetPostbuilds(self, configname, output, output_binary, |
+ quiet=False): |
"""Returns a list of shell commands that contain the shell commands |
to run as postbuilds for this target, before the actual postbuilds.""" |
# dSYMs need to build before stripping happens. |
@@ -752,6 +766,50 @@ |
self._GetDebugInfoPostbuilds(configname, output, output_binary, quiet) + |
self._GetStripPostbuilds(configname, output_binary, quiet)) |
+ def _GetIOSPostbuilds(self, configname, output_binary): |
+ """Return a shell command to codesign the iOS output binary so it can |
+ be deployed to a device. This should be run as the very last step of the |
+ build.""" |
+ if not (self.isIOS and self.spec['type'] == "executable"): |
+ return [] |
+ |
+ identity = self.xcode_settings[configname].get('CODE_SIGN_IDENTITY', '') |
+ if identity == '': |
+ return [] |
+ if identity not in XcodeSettings._codesigning_key_cache: |
+ proc = subprocess.Popen(['security', 'find-identity', '-p', 'codesigning', |
+ '-v'], stdout=subprocess.PIPE) |
+ output = proc.communicate()[0].strip() |
+ key = None |
+ for item in output.split("\n"): |
+ if identity in item: |
+ assert key == None, ( |
+ "Multiple codesigning identities for identity: %s" % |
+ identity) |
+ key = item.split(' ')[1] |
+ XcodeSettings._codesigning_key_cache[identity] = key |
+ key = XcodeSettings._codesigning_key_cache[identity] |
+ if key: |
+ # Warn for any unimplemented signing xcode keys. |
+ unimpl = ['CODE_SIGN_RESOURCE_RULES_PATH', 'OTHER_CODE_SIGN_FLAGS', |
+ 'CODE_SIGN_ENTITLEMENTS'] |
+ keys = set(self.xcode_settings[configname].keys()) |
+ unimpl = set(unimpl) & keys |
+ if unimpl: |
+ print 'Warning: Some codesign keys not implemented, ignoring:', \ |
+ ' '.join(unimpl) |
+ return ['codesign --force --sign %s %s' % (key, output_binary)] |
+ return [] |
+ |
+ def AddImplicitPostbuilds(self, configname, output, output_binary, |
+ postbuilds=[], quiet=False): |
+ """Returns a list of shell commands that should run before and after |
+ |postbuilds|.""" |
+ assert output_binary is not None |
+ pre = self._GetTargetPostbuilds(configname, output, output_binary, quiet) |
+ post = self._GetIOSPostbuilds(configname, output_binary) |
+ return pre + postbuilds + post |
+ |
def _AdjustLibrary(self, library, config_name=None): |
if library.endswith('.framework'): |
l = '-framework ' + os.path.splitext(os.path.basename(library))[0] |
@@ -815,15 +873,20 @@ |
cache['DTSDKBuild'] = cache['BuildMachineOSBuild'] |
if self.isIOS: |
- cache['UIDeviceFamily'] = self._XcodeIOSDeviceFamily(configname) |
if configname.endswith("iphoneos"): |
cache['CFBundleSupportedPlatforms'] = ['iPhoneOS'] |
else: |
cache['CFBundleSupportedPlatforms'] = ['iPhoneSimulator'] |
XcodeSettings._plist_cache[configname] = cache |
- return XcodeSettings._plist_cache[configname] |
+ # Include extra plist items that are per-target, not per global |
+ # XcodeSettings. |
+ items = dict(XcodeSettings._plist_cache[configname]) |
+ if self.isIOS: |
+ items['UIDeviceFamily'] = self._XcodeIOSDeviceFamily(configname) |
+ return items |
+ |
class MacPrefixHeader(object): |
"""A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature. |