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

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

Issue 138533006: Improve ninja's Xcode emulation (Closed) Base URL: http://gyp.googlecode.com/svn/trunk
Patch Set: Expand $(ARCHS_STANDARD) for all toolset, both "host" and "target" 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 | test/ios/app-bundle/test-archs.gyp » ('j') | test/ios/gyptest-archs.py » ('J')
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): 274 @classmethod
Nico 2014/02/07 18:57:56 Why this change?
sdefresne 2014/02/07 20:19:33 I want to call this method from the module functio
275 def _GetStdout(cls, cmdlist):
275 job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE) 276 job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE)
276 out = job.communicate()[0] 277 out = job.communicate()[0]
277 if job.returncode != 0: 278 if job.returncode != 0:
278 sys.stderr.write(out + '\n') 279 sys.stderr.write(out + '\n')
279 raise GypError('Error %d running %s' % (job.returncode, cmdlist[0])) 280 raise GypError('Error %d running %s' % (job.returncode, cmdlist[0]))
280 return out.rstrip('\n') 281 return out.rstrip('\n')
281 282
282 def _GetSdkVersionInfoItem(self, sdk, infoitem): 283 def _GetSdkVersionInfoItem(self, sdk, infoitem):
283 # xcodebuild requires Xcode and can't run on Command Line Tools-only 284 # xcodebuild requires Xcode and can't run on Command Line Tools-only
284 # systems from 10.7 onward. 285 # systems from 10.7 onward.
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 '-framework Cocoa', 'libcrypto.dylib' into '-lcrypto', etc. 871 '-framework Cocoa', 'libcrypto.dylib' into '-lcrypto', etc.
871 """ 872 """
872 libraries = [self._AdjustLibrary(library, config_name) 873 libraries = [self._AdjustLibrary(library, config_name)
873 for library in libraries] 874 for library in libraries]
874 return libraries 875 return libraries
875 876
876 def _BuildMachineOSBuild(self): 877 def _BuildMachineOSBuild(self):
877 return self._GetStdout(['sw_vers', '-buildVersion']) 878 return self._GetStdout(['sw_vers', '-buildVersion'])
878 879
879 # This method ported from the logic in Homebrew's CLT version check 880 # This method ported from the logic in Homebrew's CLT version check
880 def _CLTVersion(self): 881 @classmethod
882 def _CLTVersion(cls):
881 # pkgutil output looks like 883 # pkgutil output looks like
882 # package-id: com.apple.pkg.CLTools_Executables 884 # package-id: com.apple.pkg.CLTools_Executables
883 # version: 5.0.1.0.1.1382131676 885 # version: 5.0.1.0.1.1382131676
884 # volume: / 886 # volume: /
885 # location: / 887 # location: /
886 # install-time: 1382544035 888 # install-time: 1382544035
887 # groups: com.apple.FindSystemFiles.pkg-group com.apple.DevToolsBoth.pkg-g roup com.apple.DevToolsNonRelocatableShared.pkg-group 889 # 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" 890 STANDALONE_PKG_ID = "com.apple.pkg.DeveloperToolsCLILeo"
889 FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI" 891 FROM_XCODE_PKG_ID = "com.apple.pkg.DeveloperToolsCLI"
890 MAVERICKS_PKG_ID = "com.apple.pkg.CLTools_Executables" 892 MAVERICKS_PKG_ID = "com.apple.pkg.CLTools_Executables"
891 893
892 regex = re.compile('version: (?P<version>.+)') 894 regex = re.compile('version: (?P<version>.+)')
893 for key in [MAVERICKS_PKG_ID, STANDALONE_PKG_ID, FROM_XCODE_PKG_ID]: 895 for key in [MAVERICKS_PKG_ID, STANDALONE_PKG_ID, FROM_XCODE_PKG_ID]:
894 try: 896 try:
895 output = self._GetStdout(['/usr/sbin/pkgutil', '--pkg-info', key]) 897 output = cls._GetStdout(['/usr/sbin/pkgutil', '--pkg-info', key])
896 return re.search(regex, output).groupdict()['version'] 898 return re.search(regex, output).groupdict()['version']
897 except: 899 except:
898 continue 900 continue
899 901
900 def _XcodeVersion(self): 902 @classmethod
903 def _XcodeVersion(cls):
901 # `xcodebuild -version` output looks like 904 # `xcodebuild -version` output looks like
902 # Xcode 4.6.3 905 # Xcode 4.6.3
903 # Build version 4H1503 906 # Build version 4H1503
904 # or like 907 # or like
905 # Xcode 3.2.6 908 # Xcode 3.2.6
906 # Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0 909 # Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0
907 # BuildVersion: 10M2518 910 # BuildVersion: 10M2518
908 # Convert that to '0463', '4H1503'. 911 # Convert that to '0463', '4H1503'.
909 if len(XcodeSettings._xcode_version_cache) == 0: 912 if not cls._xcode_version_cache:
910 try: 913 try:
911 version_list = self._GetStdout(['xcodebuild', '-version']).splitlines() 914 version_list = cls._GetStdout(['xcodebuild', '-version']).splitlines()
912 # In some circumstances xcodebuild exits 0 but doesn't return 915 # 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 916 # the right results; for example, a user on 10.7 or 10.8 with
914 # a bogus path set via xcode-select 917 # a bogus path set via xcode-select
915 # In that case this may be a CLT-only install so fall back to 918 # In that case this may be a CLT-only install so fall back to
916 # checking that version. 919 # checking that version.
917 if len(version_list) < 2: 920 if len(version_list) < 2:
918 raise GypError, "xcodebuild returned unexpected results" 921 raise GypError, "xcodebuild returned unexpected results"
919 except: 922 except:
920 version = self._CLTVersion() 923 version = cls._CLTVersion()
921 if version: 924 if version:
922 version = re.match('(\d\.\d\.?\d*)', version).groups()[0] 925 version = re.match('(\d\.\d\.?\d*)', version).groups()[0]
923 else: 926 else:
924 raise GypError, "No Xcode or CLT version detected!" 927 raise GypError, "No Xcode or CLT version detected!"
925 # The CLT has no build information, so we return an empty string. 928 # The CLT has no build information, so we return an empty string.
926 version_list = [version, ''] 929 version_list = [version, '']
927 version = version_list[0] 930 version = version_list[0]
928 build = version_list[-1] 931 build = version_list[-1]
929 # Be careful to convert "4.2" to "0420": 932 # Be careful to convert "4.2" to "0420":
930 version = version.split()[-1].replace('.', '') 933 version = version.split()[-1].replace('.', '')
931 version = (version + '0' * (3 - len(version))).zfill(4) 934 version = (version + '0' * (3 - len(version))).zfill(4)
932 if build: 935 if build:
933 build = build.split()[-1] 936 build = build.split()[-1]
934 XcodeSettings._xcode_version_cache = (version, build) 937 cls._xcode_version_cache = (version, build)
935 return XcodeSettings._xcode_version_cache 938 return cls._xcode_version_cache
936 939
937 def _XcodeIOSDeviceFamily(self, configname): 940 def _XcodeIOSDeviceFamily(self, configname):
938 family = self.xcode_settings[configname].get('TARGETED_DEVICE_FAMILY', '1') 941 family = self.xcode_settings[configname].get('TARGETED_DEVICE_FAMILY', '1')
939 return [int(x) for x in family.split(',')] 942 return [int(x) for x in family.split(',')]
940 943
941 def GetExtraPlistItems(self, configname=None): 944 def GetExtraPlistItems(self, configname=None):
942 """Returns a dictionary with extra items to insert into Info.plist.""" 945 """Returns a dictionary with extra items to insert into Info.plist."""
943 if configname not in XcodeSettings._plist_cache: 946 if configname not in XcodeSettings._plist_cache:
944 cache = {} 947 cache = {}
945 cache['BuildMachineOSBuild'] = self._BuildMachineOSBuild() 948 cache['BuildMachineOSBuild'] = self._BuildMachineOSBuild()
(...skipping 29 matching lines...) Expand all
975 items['UIDeviceFamily'] = self._XcodeIOSDeviceFamily(configname) 978 items['UIDeviceFamily'] = self._XcodeIOSDeviceFamily(configname)
976 return items 979 return items
977 980
978 def _DefaultSdkRoot(self): 981 def _DefaultSdkRoot(self):
979 """Returns the default SDKROOT to use. 982 """Returns the default SDKROOT to use.
980 983
981 Prior to version 5.0.0, if SDKROOT was not explicitly set in the Xcode 984 Prior to version 5.0.0, if SDKROOT was not explicitly set in the Xcode
982 project, then the environment variable was empty. Starting with this 985 project, then the environment variable was empty. Starting with this
983 version, Xcode uses the name of the newest SDK installed. 986 version, Xcode uses the name of the newest SDK installed.
984 """ 987 """
985 if self._XcodeVersion() < '0500': 988 xcode, xcode_build = self._XcodeVersion()
989 if xcode < '0500':
986 return '' 990 return ''
987 default_sdk_path = self._XcodeSdkPath('') 991 default_sdk_path = self._XcodeSdkPath('')
988 default_sdk_root = XcodeSettings._sdk_root_cache.get(default_sdk_path) 992 default_sdk_root = XcodeSettings._sdk_root_cache.get(default_sdk_path)
989 if default_sdk_root: 993 if default_sdk_root:
990 return default_sdk_root 994 return default_sdk_root
991 try: 995 try:
992 all_sdks = self._GetStdout(['xcodebuild', '-showsdks']) 996 all_sdks = self._GetStdout(['xcodebuild', '-showsdks'])
993 except: 997 except:
994 # If xcodebuild fails, there will be no valid SDKs 998 # If xcodebuild fails, there will be no valid SDKs
995 return '' 999 return ''
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
1411 def _HasIOSTarget(targets): 1415 def _HasIOSTarget(targets):
1412 """Returns true if any target contains the iOS specific key 1416 """Returns true if any target contains the iOS specific key
1413 IPHONEOS_DEPLOYMENT_TARGET.""" 1417 IPHONEOS_DEPLOYMENT_TARGET."""
1414 for target_dict in targets.values(): 1418 for target_dict in targets.values():
1415 for config in target_dict['configurations'].values(): 1419 for config in target_dict['configurations'].values():
1416 if config.get('xcode_settings', {}).get('IPHONEOS_DEPLOYMENT_TARGET'): 1420 if config.get('xcode_settings', {}).get('IPHONEOS_DEPLOYMENT_TARGET'):
1417 return True 1421 return True
1418 return False 1422 return False
1419 1423
1420 1424
1425 def _IOSIsDeviceSDKROOT(sdkroot):
1426 """Tests if |sdkroot| is a SDK for building for device."""
1427 return 'iphoneos' in sdkroot.lower()
1428
1429
1430 def _IOSDefaultArchForSDKRoot(sdkroot):
1431 xcode, xcode_build = XcodeSettings._XcodeVersion()
1432 if xcode < '0500':
1433 if _IOSIsDeviceSDKROOT(sdkroot):
1434 return {'$(ARCHS_STANDARD)': ['armv7']}
1435 else:
1436 return {'$(ARCHS_STANDARD)': ['i386']}
1437 else:
1438 if _IOSIsDeviceSDKROOT(sdkroot):
1439 return {
1440 '$(ARCHS_STANDARD)': ['armv7', 'armv7s'],
1441 '$(ARCHS_STANDARD_INCLUDING_64_BIT)': ['armv7', 'armv7s', 'arm64'],
1442 }
1443 else:
1444 return {
1445 '$(ARCHS_STANDARD)': ['i386'],
1446 '$(ARCHS_STANDARD_INCLUDING_64_BIT)': ['i386', 'x86_64'],
1447 }
1448
1449
1450 def _FilterIOSArchitectureForSDKROOT(xcode_settings):
1451 """Filter the ARCHS value from the |xcode_settings| dictionary to only
1452 contains architectures valid for the sdk configured in SDKROOT value."""
1453 defaults_archs = _IOSDefaultArchForSDKRoot(xcode_settings.get('SDKROOT', ''))
1454 allowed_archs = set()
1455 for archs in defaults_archs.itervalues():
1456 allowed_archs.update(archs)
1457 selected_archs = set()
1458 for arch in (xcode_settings.get('ARCHS', []) or ['$(ARCHS_STANDARD)']):
Nico 2014/02/07 18:57:56 No need for the default [] if you do `or default`
sdefresne 2014/02/07 20:19:33 There are some xcode_settings objects that don't d
1459 if arch in defaults_archs:
1460 selected_archs.update(defaults_archs[arch])
1461 elif arch in allowed_archs:
1462 selected_archs.add(arch)
1463 valid_archs = set(xcode_settings.get('VALID_ARCHS', []))
1464 if valid_archs:
1465 selected_archs = selected_archs & valid_archs
1466 xcode_settings['ARCHS'] = list(selected_archs)
1467
1468
1421 def _AddIOSDeviceConfigurations(targets): 1469 def _AddIOSDeviceConfigurations(targets):
1422 """Clone all targets and append -iphoneos to the name. Configure these targets 1470 """Clone all targets and append -iphoneos to the name. Configure these targets
1423 to build for iOS devices.""" 1471 to build for iOS devices and use correct architectures for those builds."""
1424 for target_dict in targets.values(): 1472 for target_dict in targets.itervalues():
1425 for config_name in target_dict['configurations'].keys(): 1473 toolset = target_dict['toolset']
1426 config = target_dict['configurations'][config_name] 1474 configs = target_dict['configurations']
1427 new_config_name = config_name + '-iphoneos' 1475 for config_name, config_dict in dict(configs).iteritems():
1428 new_config_dict = copy.deepcopy(config) 1476 iphoneos_config_dict = copy.deepcopy(config_dict)
Nico 2014/02/07 18:57:56 Why this variable name change?
sdefresne 2014/02/07 20:19:33 I found the old name confusing when updating the c
1429 if target_dict['toolset'] == 'target': 1477 configs[config_name + '-iphoneos'] = iphoneos_config_dict
1430 new_config_dict['xcode_settings']['ARCHS'] = ['armv7'] 1478 if toolset == 'target':
1431 new_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos' 1479 iphoneos_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos'
1432 target_dict['configurations'][new_config_name] = new_config_dict 1480 _FilterIOSArchitectureForSDKROOT(iphoneos_config_dict['xcode_settings'])
1481 _FilterIOSArchitectureForSDKROOT(config_dict['xcode_settings'])
1433 return targets 1482 return targets
1434 1483
1435 def CloneConfigurationForDeviceAndEmulator(target_dicts): 1484 def CloneConfigurationForDeviceAndEmulator(target_dicts):
1436 """If |target_dicts| contains any iOS targets, automatically create -iphoneos 1485 """If |target_dicts| contains any iOS targets, automatically create -iphoneos
1437 targets for iOS device builds.""" 1486 targets for iOS device builds."""
1438 if _HasIOSTarget(target_dicts): 1487 if _HasIOSTarget(target_dicts):
1439 return _AddIOSDeviceConfigurations(target_dicts) 1488 return _AddIOSDeviceConfigurations(target_dicts)
1440 return target_dicts 1489 return target_dicts
OLDNEW
« no previous file with comments | « no previous file | test/ios/app-bundle/test-archs.gyp » ('j') | test/ios/gyptest-archs.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698