Chromium Code Reviews| 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 |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |