Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(366)

Side by Side Diff: pylib/gyp/xcode_emulation.py

Issue 170773002: Cache Xcode version at the module level (Closed) Base URL: http://gyp.googlecode.com/svn/trunk
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 12 import os
13 import os.path 13 import os.path
14 import re 14 import re
15 import shlex 15 import shlex
16 import subprocess 16 import subprocess
17 import sys 17 import sys
18 import tempfile 18 import tempfile
19 from gyp.common import GypError 19 from gyp.common import GypError
20 20
21 # Populated lazily by XcodeVersion, for efficiency, and to fix an issue when
22 # "xcodebuild" is called too quickly (it has been found to return incorrect
23 # version number).
24 XCODE_VERSION_CACHE = []
25
21 class XcodeSettings(object): 26 class XcodeSettings(object):
22 """A class that understands the gyp 'xcode_settings' object.""" 27 """A class that understands the gyp 'xcode_settings' object."""
23 28
24 # Populated lazily by _SdkPath(). Shared by all XcodeSettings, so cached 29 # Populated lazily by _SdkPath(). Shared by all XcodeSettings, so cached
25 # at class-level for efficiency. 30 # at class-level for efficiency.
26 _sdk_path_cache = {} 31 _sdk_path_cache = {}
27 _sdk_root_cache = {} 32 _sdk_root_cache = {}
28 33
29 # Populated lazily by GetExtraPlistItems(). Shared by all XcodeSettings, so 34 # Populated lazily by GetExtraPlistItems(). Shared by all XcodeSettings, so
30 # cached at class-level for efficiency. 35 # cached at class-level for efficiency.
31 _plist_cache = {} 36 _plist_cache = {}
32 37
33 # Populated lazily by GetIOSPostbuilds. Shared by all XcodeSettings, so 38 # Populated lazily by GetIOSPostbuilds. Shared by all XcodeSettings, so
34 # cached at class-level for efficiency. 39 # cached at class-level for efficiency.
35 _codesigning_key_cache = {} 40 _codesigning_key_cache = {}
36 41
37 # Populated lazily by _XcodeVersion. Shared by all XcodeSettings, so cached
38 # at class-level for efficiency.
39 _xcode_version_cache = ()
40
41 def __init__(self, spec): 42 def __init__(self, spec):
42 self.spec = spec 43 self.spec = spec
43 44
44 self.isIOS = False 45 self.isIOS = False
45 46
46 # Per-target 'xcode_settings' are pushed down into configs earlier by gyp. 47 # Per-target 'xcode_settings' are pushed down into configs earlier by gyp.
47 # This means self.xcode_settings[config] always contains all settings 48 # This means self.xcode_settings[config] always contains all settings
48 # for that config -- the per-target settings as well. Settings that are 49 # for that config -- the per-target settings as well. Settings that are
49 # the same for all configs are implicitly per-target settings. 50 # the same for all configs are implicitly per-target settings.
50 self.xcode_settings = {} 51 self.xcode_settings = {}
(...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 """Transforms entries like 'Cocoa.framework' in libraries into entries like 862 """Transforms entries like 'Cocoa.framework' in libraries into entries like
862 '-framework Cocoa', 'libcrypto.dylib' into '-lcrypto', etc. 863 '-framework Cocoa', 'libcrypto.dylib' into '-lcrypto', etc.
863 """ 864 """
864 libraries = [self._AdjustLibrary(library, config_name) 865 libraries = [self._AdjustLibrary(library, config_name)
865 for library in libraries] 866 for library in libraries]
866 return libraries 867 return libraries
867 868
868 def _BuildMachineOSBuild(self): 869 def _BuildMachineOSBuild(self):
869 return GetStdout(['sw_vers', '-buildVersion']) 870 return GetStdout(['sw_vers', '-buildVersion'])
870 871
871 def _XcodeVersion(self):
872 if len(XcodeSettings._xcode_version_cache) == 0:
873 XcodeSettings._xcode_version_cache = XcodeVersion()
874 return XcodeSettings._xcode_version_cache
875
876 def _XcodeIOSDeviceFamily(self, configname): 872 def _XcodeIOSDeviceFamily(self, configname):
877 family = self.xcode_settings[configname].get('TARGETED_DEVICE_FAMILY', '1') 873 family = self.xcode_settings[configname].get('TARGETED_DEVICE_FAMILY', '1')
878 return [int(x) for x in family.split(',')] 874 return [int(x) for x in family.split(',')]
879 875
880 def GetExtraPlistItems(self, configname=None): 876 def GetExtraPlistItems(self, configname=None):
881 """Returns a dictionary with extra items to insert into Info.plist.""" 877 """Returns a dictionary with extra items to insert into Info.plist."""
882 if configname not in XcodeSettings._plist_cache: 878 if configname not in XcodeSettings._plist_cache:
883 cache = {} 879 cache = {}
884 cache['BuildMachineOSBuild'] = self._BuildMachineOSBuild() 880 cache['BuildMachineOSBuild'] = self._BuildMachineOSBuild()
885 881
886 xcode, xcode_build = self._XcodeVersion() 882 xcode, xcode_build = XcodeVersion()
887 cache['DTXcode'] = xcode 883 cache['DTXcode'] = xcode
888 cache['DTXcodeBuild'] = xcode_build 884 cache['DTXcodeBuild'] = xcode_build
889 885
890 sdk_root = self._SdkRoot(configname) 886 sdk_root = self._SdkRoot(configname)
891 if not sdk_root: 887 if not sdk_root:
892 sdk_root = self._DefaultSdkRoot() 888 sdk_root = self._DefaultSdkRoot()
893 cache['DTSDKName'] = sdk_root 889 cache['DTSDKName'] = sdk_root
894 if xcode >= '0430': 890 if xcode >= '0430':
895 cache['DTSDKBuild'] = self._GetSdkVersionInfoItem( 891 cache['DTSDKBuild'] = self._GetSdkVersionInfoItem(
896 sdk_root, 'ProductBuildVersion') 892 sdk_root, 'ProductBuildVersion')
(...skipping 17 matching lines...) Expand all
914 items['UIDeviceFamily'] = self._XcodeIOSDeviceFamily(configname) 910 items['UIDeviceFamily'] = self._XcodeIOSDeviceFamily(configname)
915 return items 911 return items
916 912
917 def _DefaultSdkRoot(self): 913 def _DefaultSdkRoot(self):
918 """Returns the default SDKROOT to use. 914 """Returns the default SDKROOT to use.
919 915
920 Prior to version 5.0.0, if SDKROOT was not explicitly set in the Xcode 916 Prior to version 5.0.0, if SDKROOT was not explicitly set in the Xcode
921 project, then the environment variable was empty. Starting with this 917 project, then the environment variable was empty. Starting with this
922 version, Xcode uses the name of the newest SDK installed. 918 version, Xcode uses the name of the newest SDK installed.
923 """ 919 """
924 xcode_version, xcode_build = self._XcodeVersion() 920 xcode_version, xcode_build = XcodeVersion()
925 if xcode_version < '0500': 921 if xcode_version < '0500':
926 return '' 922 return ''
927 default_sdk_path = self._XcodeSdkPath('') 923 default_sdk_path = self._XcodeSdkPath('')
928 default_sdk_root = XcodeSettings._sdk_root_cache.get(default_sdk_path) 924 default_sdk_root = XcodeSettings._sdk_root_cache.get(default_sdk_path)
929 if default_sdk_root: 925 if default_sdk_root:
930 return default_sdk_root 926 return default_sdk_root
931 try: 927 try:
932 all_sdks = GetStdout(['xcodebuild', '-showsdks']) 928 all_sdks = GetStdout(['xcodebuild', '-showsdks'])
933 except: 929 except:
934 # If xcodebuild fails, there will be no valid SDKs 930 # If xcodebuild fails, there will be no valid SDKs
(...skipping 18 matching lines...) Expand all
953 # For new projects, ARCHS is set to $(ARCHS_STANDARD_INCLUDING_64_BIT), 949 # For new projects, ARCHS is set to $(ARCHS_STANDARD_INCLUDING_64_BIT),
954 # which correspond to "armv7 armv7s arm64", and when building the simulator 950 # which correspond to "armv7 armv7s arm64", and when building the simulator
955 # the architecture is either "i386" or "x86_64" depending on the simulated 951 # the architecture is either "i386" or "x86_64" depending on the simulated
956 # device (respectively 32-bit or 64-bit device). 952 # device (respectively 32-bit or 64-bit device).
957 # 953 #
958 # Since the value returned by this function is only used when ARCHS is not 954 # Since the value returned by this function is only used when ARCHS is not
959 # set, then on iOS we return "i386", as the default xcode project generator 955 # set, then on iOS we return "i386", as the default xcode project generator
960 # does not set ARCHS if it is not set in the .gyp file. 956 # does not set ARCHS if it is not set in the .gyp file.
961 if self.isIOS: 957 if self.isIOS:
962 return 'i386' 958 return 'i386'
963 version, build = self._XcodeVersion() 959 version, build = XcodeVersion()
964 if version >= '0500': 960 if version >= '0500':
965 return 'x86_64' 961 return 'x86_64'
966 return 'i386' 962 return 'i386'
967 963
968 class MacPrefixHeader(object): 964 class MacPrefixHeader(object):
969 """A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature. 965 """A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature.
970 966
971 This feature consists of several pieces: 967 This feature consists of several pieces:
972 * If GCC_PREFIX_HEADER is present, all compilations in that project get an 968 * If GCC_PREFIX_HEADER is present, all compilations in that project get an
973 additional |-include path_to_prefix_header| cflag. 969 additional |-include path_to_prefix_header| cflag.
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1064 if not self.header or not self.compile_headers: 1060 if not self.header or not self.compile_headers:
1065 return [] 1061 return []
1066 return [ 1062 return [
1067 (self._Gch('c', arch), '-x c-header', 'c', self.header), 1063 (self._Gch('c', arch), '-x c-header', 'c', self.header),
1068 (self._Gch('cc', arch), '-x c++-header', 'cc', self.header), 1064 (self._Gch('cc', arch), '-x c++-header', 'cc', self.header),
1069 (self._Gch('m', arch), '-x objective-c-header', 'm', self.header), 1065 (self._Gch('m', arch), '-x objective-c-header', 'm', self.header),
1070 (self._Gch('mm', arch), '-x objective-c++-header', 'mm', self.header), 1066 (self._Gch('mm', arch), '-x objective-c++-header', 'mm', self.header),
1071 ] 1067 ]
1072 1068
1073 1069
1074 def XcodeVersion(): 1070 def XcodeVersion():
Nico 2014/02/18 17:11:57 Huh, is this new? I don't remember there being a g
sdefresne 2014/02/18 17:28:33 I extracted the function out of the XcodeSettings
1075 """Returns a tuple of version and build version of installed Xcode.""" 1071 """Returns a tuple of version and build version of installed Xcode."""
1076 # `xcodebuild -version` output looks like 1072 # `xcodebuild -version` output looks like
1077 # Xcode 4.6.3 1073 # Xcode 4.6.3
1078 # Build version 4H1503 1074 # Build version 4H1503
1079 # or like 1075 # or like
1080 # Xcode 3.2.6 1076 # Xcode 3.2.6
1081 # Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0 1077 # Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0
1082 # BuildVersion: 10M2518 1078 # BuildVersion: 10M2518
1083 # Convert that to '0463', '4H1503'. 1079 # Convert that to '0463', '4H1503'.
1080 if XCODE_VERSION_CACHE:
1081 assert len(XCODE_VERSION_CACHE) >= 2
1082 return tuple(XCODE_VERSION_CACHE[:2])
1084 try: 1083 try:
1085 version_list = GetStdout(['xcodebuild', '-version']).splitlines() 1084 version_list = GetStdout(['xcodebuild', '-version']).splitlines()
1086 # In some circumstances xcodebuild exits 0 but doesn't return 1085 # In some circumstances xcodebuild exits 0 but doesn't return
1087 # the right results; for example, a user on 10.7 or 10.8 with 1086 # the right results; for example, a user on 10.7 or 10.8 with
1088 # a bogus path set via xcode-select 1087 # a bogus path set via xcode-select
1089 # In that case this may be a CLT-only install so fall back to 1088 # In that case this may be a CLT-only install so fall back to
1090 # checking that version. 1089 # checking that version.
1091 if len(version_list) < 2: 1090 if len(version_list) < 2:
1092 raise GypError, "xcodebuild returned unexpected results" 1091 raise GypError, "xcodebuild returned unexpected results"
1093 except: 1092 except:
1094 version = CLTVersion() 1093 version = CLTVersion()
1095 if version: 1094 if version:
1096 version = re.match('(\d\.\d\.?\d*)', version).groups()[0] 1095 version = re.match('(\d\.\d\.?\d*)', version).groups()[0]
1097 else: 1096 else:
1098 raise GypError, "No Xcode or CLT version detected!" 1097 raise GypError, "No Xcode or CLT version detected!"
1099 # The CLT has no build information, so we return an empty string. 1098 # The CLT has no build information, so we return an empty string.
1100 version_list = [version, ''] 1099 version_list = [version, '']
1101 version = version_list[0] 1100 version = version_list[0]
1102 build = version_list[-1] 1101 build = version_list[-1]
1103 # Be careful to convert "4.2" to "0420": 1102 # Be careful to convert "4.2" to "0420":
1104 version = version.split()[-1].replace('.', '') 1103 version = version.split()[-1].replace('.', '')
1105 version = (version + '0' * (3 - len(version))).zfill(4) 1104 version = (version + '0' * (3 - len(version))).zfill(4)
1106 if build: 1105 if build:
1107 build = build.split()[-1] 1106 build = build.split()[-1]
1107 XCODE_VERSION_CACHE.extend((version, build))
1108 return version, build 1108 return version, build
1109 1109
1110 1110
1111 # This function ported from the logic in Homebrew's CLT version check 1111 # This function ported from the logic in Homebrew's CLT version check
1112 def CLTVersion(): 1112 def CLTVersion():
1113 """Returns the version of command-line tools from pkgutil.""" 1113 """Returns the version of command-line tools from pkgutil."""
1114 # pkgutil output looks like 1114 # pkgutil output looks like
1115 # package-id: com.apple.pkg.CLTools_Executables 1115 # package-id: com.apple.pkg.CLTools_Executables
1116 # version: 5.0.1.0.1.1382131676 1116 # version: 5.0.1.0.1.1382131676
1117 # volume: / 1117 # volume: /
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
1490 _FilterIOSArchitectureForSDKROOT(iphoneos_config_dict['xcode_settings']) 1490 _FilterIOSArchitectureForSDKROOT(iphoneos_config_dict['xcode_settings'])
1491 _FilterIOSArchitectureForSDKROOT(config_dict['xcode_settings']) 1491 _FilterIOSArchitectureForSDKROOT(config_dict['xcode_settings'])
1492 return targets 1492 return targets
1493 1493
1494 def CloneConfigurationForDeviceAndEmulator(target_dicts): 1494 def CloneConfigurationForDeviceAndEmulator(target_dicts):
1495 """If |target_dicts| contains any iOS targets, automatically create -iphoneos 1495 """If |target_dicts| contains any iOS targets, automatically create -iphoneos
1496 targets for iOS device builds.""" 1496 targets for iOS device builds."""
1497 if _HasIOSTarget(target_dicts): 1497 if _HasIOSTarget(target_dicts):
1498 return _AddIOSDeviceConfigurations(target_dicts) 1498 return _AddIOSDeviceConfigurations(target_dicts)
1499 return target_dicts 1499 return target_dicts
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698