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

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

Issue 148783005: Extract XcodeVersion to be a standalone module function (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
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 return self._GetBundleBinaryPath() 264 return self._GetBundleBinaryPath()
265 else: 265 else:
266 return self._GetStandaloneBinaryPath() 266 return self._GetStandaloneBinaryPath()
267 267
268 def GetActiveArchs(self, configname): 268 def GetActiveArchs(self, configname):
269 """Returns the architectures this target should be built for.""" 269 """Returns the architectures this target should be built for."""
270 # TODO: Look at VALID_ARCHS, ONLY_ACTIVE_ARCH; possibly set 270 # TODO: Look at VALID_ARCHS, ONLY_ACTIVE_ARCH; possibly set
271 # CURRENT_ARCH / NATIVE_ARCH env vars? 271 # CURRENT_ARCH / NATIVE_ARCH env vars?
272 return self.xcode_settings[configname].get('ARCHS', [self._DefaultArch()]) 272 return self.xcode_settings[configname].get('ARCHS', [self._DefaultArch()])
273 273
274 def _GetStdout(self, cmdlist):
275 job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE)
276 out = job.communicate()[0]
277 if job.returncode != 0:
278 sys.stderr.write(out + '\n')
279 raise GypError('Error %d running %s' % (job.returncode, cmdlist[0]))
280 return out.rstrip('\n')
281
282 def _GetSdkVersionInfoItem(self, sdk, infoitem): 274 def _GetSdkVersionInfoItem(self, sdk, infoitem):
283 # xcodebuild requires Xcode and can't run on Command Line Tools-only 275 # xcodebuild requires Xcode and can't run on Command Line Tools-only
284 # systems from 10.7 onward. 276 # systems from 10.7 onward.
285 # Since the CLT has no SDK paths anyway, returning None is the 277 # Since the CLT has no SDK paths anyway, returning None is the
286 # most sensible route and should still do the right thing. 278 # most sensible route and should still do the right thing.
287 try: 279 try:
288 return self._GetStdout(['xcodebuild', '-version', '-sdk', sdk, infoitem]) 280 return GetStdout(['xcodebuild', '-version', '-sdk', sdk, infoitem])
289 except: 281 except:
290 pass 282 pass
291 283
292 def _SdkRoot(self, configname): 284 def _SdkRoot(self, configname):
293 if configname is None: 285 if configname is None:
294 configname = self.configname 286 configname = self.configname
295 return self.GetPerConfigSetting('SDKROOT', configname, default='') 287 return self.GetPerConfigSetting('SDKROOT', configname, default='')
296 288
297 def _SdkPath(self, configname=None): 289 def _SdkPath(self, configname=None):
298 sdk_root = self._SdkRoot(configname) 290 sdk_root = self._SdkRoot(configname)
(...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after
867 859
868 def AdjustLibraries(self, libraries, config_name=None): 860 def AdjustLibraries(self, libraries, config_name=None):
869 """Transforms entries like 'Cocoa.framework' in libraries into entries like 861 """Transforms entries like 'Cocoa.framework' in libraries into entries like
870 '-framework Cocoa', 'libcrypto.dylib' into '-lcrypto', etc. 862 '-framework Cocoa', 'libcrypto.dylib' into '-lcrypto', etc.
871 """ 863 """
872 libraries = [self._AdjustLibrary(library, config_name) 864 libraries = [self._AdjustLibrary(library, config_name)
873 for library in libraries] 865 for library in libraries]
874 return libraries 866 return libraries
875 867
876 def _BuildMachineOSBuild(self): 868 def _BuildMachineOSBuild(self):
877 return self._GetStdout(['sw_vers', '-buildVersion']) 869 return GetStdout(['sw_vers', '-buildVersion'])
878
879 # This method ported from the logic in Homebrew's CLT version check
880 def _CLTVersion(self):
881 # pkgutil output looks like
882 # package-id: com.apple.pkg.CLTools_Executables
883 # version: 5.0.1.0.1.1382131676
884 # volume: /
885 # location: /
886 # install-time: 1382544035
887 # groups: com.apple.FindSystemFiles.pkg-group com.apple.DevToolsBoth.pkg-g roup com.apple.DevToolsNonRelocatableShared.pkg-group
888 STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo"
889 FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI"
890 MAVERICKS_PKG_ID = "com.apple.pkg.CLTools_Executables"
891
892 regex = re.compile('version: (?P<version>.+)')
893 for key in [MAVERICKS_PKG_ID, STANDALONE_PKG_ID, FROM_XCODE_PKG_ID]:
894 try:
895 output = self._GetStdout(['/usr/sbin/pkgutil', '--pkg-info', key])
896 return re.search(regex, output).groupdict()['version']
897 except:
898 continue
899 870
900 def _XcodeVersion(self): 871 def _XcodeVersion(self):
901 # `xcodebuild -version` output looks like
902 # Xcode 4.6.3
903 # Build version 4H1503
904 # or like
905 # Xcode 3.2.6
906 # Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0
907 # BuildVersion: 10M2518
908 # Convert that to '0463', '4H1503'.
909 if len(XcodeSettings._xcode_version_cache) == 0: 872 if len(XcodeSettings._xcode_version_cache) == 0:
910 try: 873 XcodeSettings._xcode_version_cache = XcodeVersion()
911 version_list = self._GetStdout(['xcodebuild', '-version']).splitlines()
912 # In some circumstances xcodebuild exits 0 but doesn't return
913 # the right results; for example, a user on 10.7 or 10.8 with
914 # a bogus path set via xcode-select
915 # In that case this may be a CLT-only install so fall back to
916 # checking that version.
917 if len(version_list) < 2:
918 raise GypError, "xcodebuild returned unexpected results"
919 except:
920 version = self._CLTVersion()
921 if version:
922 version = re.match('(\d\.\d\.?\d*)', version).groups()[0]
923 else:
924 raise GypError, "No Xcode or CLT version detected!"
925 # The CLT has no build information, so we return an empty string.
926 version_list = [version, '']
927 version = version_list[0]
928 build = version_list[-1]
929 # Be careful to convert "4.2" to "0420":
930 version = version.split()[-1].replace('.', '')
931 version = (version + '0' * (3 - len(version))).zfill(4)
932 if build:
933 build = build.split()[-1]
934 XcodeSettings._xcode_version_cache = (version, build)
935 return XcodeSettings._xcode_version_cache 874 return XcodeSettings._xcode_version_cache
936 875
937 def _XcodeIOSDeviceFamily(self, configname): 876 def _XcodeIOSDeviceFamily(self, configname):
938 family = self.xcode_settings[configname].get('TARGETED_DEVICE_FAMILY', '1') 877 family = self.xcode_settings[configname].get('TARGETED_DEVICE_FAMILY', '1')
939 return [int(x) for x in family.split(',')] 878 return [int(x) for x in family.split(',')]
940 879
941 def GetExtraPlistItems(self, configname=None): 880 def GetExtraPlistItems(self, configname=None):
942 """Returns a dictionary with extra items to insert into Info.plist.""" 881 """Returns a dictionary with extra items to insert into Info.plist."""
943 if configname not in XcodeSettings._plist_cache: 882 if configname not in XcodeSettings._plist_cache:
944 cache = {} 883 cache = {}
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 project, then the environment variable was empty. Starting with this 921 project, then the environment variable was empty. Starting with this
983 version, Xcode uses the name of the newest SDK installed. 922 version, Xcode uses the name of the newest SDK installed.
984 """ 923 """
985 if self._XcodeVersion() < '0500': 924 if self._XcodeVersion() < '0500':
986 return '' 925 return ''
987 default_sdk_path = self._XcodeSdkPath('') 926 default_sdk_path = self._XcodeSdkPath('')
988 default_sdk_root = XcodeSettings._sdk_root_cache.get(default_sdk_path) 927 default_sdk_root = XcodeSettings._sdk_root_cache.get(default_sdk_path)
989 if default_sdk_root: 928 if default_sdk_root:
990 return default_sdk_root 929 return default_sdk_root
991 try: 930 try:
992 all_sdks = self._GetStdout(['xcodebuild', '-showsdks']) 931 all_sdks = GetStdout(['xcodebuild', '-showsdks'])
993 except: 932 except:
994 # If xcodebuild fails, there will be no valid SDKs 933 # If xcodebuild fails, there will be no valid SDKs
995 return '' 934 return ''
996 for line in all_sdks.splitlines(): 935 for line in all_sdks.splitlines():
997 items = line.split() 936 items = line.split()
998 if len(items) >= 3 and items[-2] == '-sdk': 937 if len(items) >= 3 and items[-2] == '-sdk':
999 sdk_root = items[-1] 938 sdk_root = items[-1]
1000 sdk_path = self._XcodeSdkPath(sdk_root) 939 sdk_path = self._XcodeSdkPath(sdk_root)
1001 if sdk_path == default_sdk_path: 940 if sdk_path == default_sdk_path:
1002 return sdk_root 941 return sdk_root
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1124 if not self.header or not self.compile_headers: 1063 if not self.header or not self.compile_headers:
1125 return [] 1064 return []
1126 return [ 1065 return [
1127 (self._Gch('c', arch), '-x c-header', 'c', self.header), 1066 (self._Gch('c', arch), '-x c-header', 'c', self.header),
1128 (self._Gch('cc', arch), '-x c++-header', 'cc', self.header), 1067 (self._Gch('cc', arch), '-x c++-header', 'cc', self.header),
1129 (self._Gch('m', arch), '-x objective-c-header', 'm', self.header), 1068 (self._Gch('m', arch), '-x objective-c-header', 'm', self.header),
1130 (self._Gch('mm', arch), '-x objective-c++-header', 'mm', self.header), 1069 (self._Gch('mm', arch), '-x objective-c++-header', 'mm', self.header),
1131 ] 1070 ]
1132 1071
1133 1072
1073 def XcodeVersion():
1074 """Returns a tuple of version and build version of installed Xcode."""
1075 # `xcodebuild -version` output looks like
1076 # Xcode 4.6.3
1077 # Build version 4H1503
1078 # or like
1079 # Xcode 3.2.6
1080 # Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0
1081 # BuildVersion: 10M2518
1082 # Convert that to '0463', '4H1503'.
1083 try:
1084 version_list = GetStdout(['xcodebuild', '-version']).splitlines()
1085 # In some circumstances xcodebuild exits 0 but doesn't return
1086 # the right results; for example, a user on 10.7 or 10.8 with
1087 # a bogus path set via xcode-select
1088 # In that case this may be a CLT-only install so fall back to
1089 # checking that version.
1090 if len(version_list) < 2:
1091 raise GypError, "xcodebuild returned unexpected results"
1092 except:
1093 version = CLTVersion()
1094 if version:
1095 version = re.match('(\d\.\d\.?\d*)', version).groups()[0]
1096 else:
1097 raise GypError, "No Xcode or CLT version detected!"
1098 # The CLT has no build information, so we return an empty string.
1099 version_list = [version, '']
1100 version = version_list[0]
1101 build = version_list[-1]
1102 # Be careful to convert "4.2" to "0420":
1103 version = version.split()[-1].replace('.', '')
1104 version = (version + '0' * (3 - len(version))).zfill(4)
1105 if build:
1106 build = build.split()[-1]
1107 return version, build
1108
1109
1110 # This function ported from the logic in Homebrew's CLT version check
1111 def CLTVersion():
1112 """Returns the version of command-line tools from pkgutil."""
1113 # pkgutil output looks like
1114 # package-id: com.apple.pkg.CLTools_Executables
1115 # version: 5.0.1.0.1.1382131676
1116 # volume: /
1117 # location: /
1118 # install-time: 1382544035
1119 # groups: com.apple.FindSystemFiles.pkg-group com.apple.DevToolsBoth.pkg-gro up com.apple.DevToolsNonRelocatableShared.pkg-group
1120 STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo"
1121 FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI"
1122 MAVERICKS_PKG_ID = "com.apple.pkg.CLTools_Executables"
1123
1124 regex = re.compile('version: (?P<version>.+)')
1125 for key in [MAVERICKS_PKG_ID, STANDALONE_PKG_ID, FROM_XCODE_PKG_ID]:
1126 try:
1127 output = GetStdout(['/usr/sbin/pkgutil', '--pkg-info', key])
1128 return re.search(regex, output).groupdict()['version']
1129 except:
1130 continue
1131
1132
1133 def GetStdout(cmdlist):
1134 """Returns the content of standard output returned by invoking |cmdlist|.
1135 Raises |GypError| if the command return with a non-zero return code."""
1136 job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE)
1137 out = job.communicate()[0]
1138 if job.returncode != 0:
1139 sys.stderr.write(out + '\n')
1140 raise GypError('Error %d running %s' % (job.returncode, cmdlist[0]))
1141 return out.rstrip('\n')
1142
1143
1134 def MergeGlobalXcodeSettingsToSpec(global_dict, spec): 1144 def MergeGlobalXcodeSettingsToSpec(global_dict, spec):
1135 """Merges the global xcode_settings dictionary into each configuration of the 1145 """Merges the global xcode_settings dictionary into each configuration of the
1136 target represented by spec. For keys that are both in the global and the local 1146 target represented by spec. For keys that are both in the global and the local
1137 xcode_settings dict, the local key gets precendence. 1147 xcode_settings dict, the local key gets precendence.
1138 """ 1148 """
1139 # The xcode generator special-cases global xcode_settings and does something 1149 # The xcode generator special-cases global xcode_settings and does something
1140 # that amounts to merging in the global xcode_settings into each local 1150 # that amounts to merging in the global xcode_settings into each local
1141 # xcode_settings dict. 1151 # xcode_settings dict.
1142 global_xcode_settings = global_dict.get('xcode_settings', {}) 1152 global_xcode_settings = global_dict.get('xcode_settings', {})
1143 for config in spec['configurations'].values(): 1153 for config in spec['configurations'].values():
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
1431 new_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos' 1441 new_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos'
1432 target_dict['configurations'][new_config_name] = new_config_dict 1442 target_dict['configurations'][new_config_name] = new_config_dict
1433 return targets 1443 return targets
1434 1444
1435 def CloneConfigurationForDeviceAndEmulator(target_dicts): 1445 def CloneConfigurationForDeviceAndEmulator(target_dicts):
1436 """If |target_dicts| contains any iOS targets, automatically create -iphoneos 1446 """If |target_dicts| contains any iOS targets, automatically create -iphoneos
1437 targets for iOS device builds.""" 1447 targets for iOS device builds."""
1438 if _HasIOSTarget(target_dicts): 1448 if _HasIOSTarget(target_dicts):
1439 return _AddIOSDeviceConfigurations(target_dicts) 1449 return _AddIOSDeviceConfigurations(target_dicts)
1440 return target_dicts 1450 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