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 |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |