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 13 matching lines...) Expand all Loading... |
24 _sdk_path_cache = {} | 24 _sdk_path_cache = {} |
25 | 25 |
26 # Populated lazily by GetExtraPlistItems(). Shared by all XcodeSettings, so | 26 # Populated lazily by GetExtraPlistItems(). Shared by all XcodeSettings, so |
27 # cached at class-level for efficiency. | 27 # cached at class-level for efficiency. |
28 _plist_cache = {} | 28 _plist_cache = {} |
29 | 29 |
30 # Populated lazily by GetIOSPostbuilds. Shared by all XcodeSettings, so | 30 # Populated lazily by GetIOSPostbuilds. Shared by all XcodeSettings, so |
31 # cached at class-level for efficiency. | 31 # cached at class-level for efficiency. |
32 _codesigning_key_cache = {} | 32 _codesigning_key_cache = {} |
33 | 33 |
| 34 # Populated lazily by _XcodeVersion. Shared by all XcodeSettings, so cached |
| 35 # at class-level for efficiency. |
| 36 _xcode_version_cache = () |
| 37 |
34 def __init__(self, spec): | 38 def __init__(self, spec): |
35 self.spec = spec | 39 self.spec = spec |
36 | 40 |
37 self.isIOS = False | 41 self.isIOS = False |
38 | 42 |
39 # Per-target 'xcode_settings' are pushed down into configs earlier by gyp. | 43 # Per-target 'xcode_settings' are pushed down into configs earlier by gyp. |
40 # This means self.xcode_settings[config] always contains all settings | 44 # This means self.xcode_settings[config] always contains all settings |
41 # for that config -- the per-target settings as well. Settings that are | 45 # for that config -- the per-target settings as well. Settings that are |
42 # the same for all configs are implicitly per-target settings. | 46 # the same for all configs are implicitly per-target settings. |
43 self.xcode_settings = {} | 47 self.xcode_settings = {} |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 Chromium.app/Contents/MacOS/Chromium.""" | 259 Chromium.app/Contents/MacOS/Chromium.""" |
256 if self._IsBundle(): | 260 if self._IsBundle(): |
257 return self._GetBundleBinaryPath() | 261 return self._GetBundleBinaryPath() |
258 else: | 262 else: |
259 return self._GetStandaloneBinaryPath() | 263 return self._GetStandaloneBinaryPath() |
260 | 264 |
261 def GetActiveArchs(self, configname): | 265 def GetActiveArchs(self, configname): |
262 """Returns the architectures this target should be built for.""" | 266 """Returns the architectures this target should be built for.""" |
263 # TODO: Look at VALID_ARCHS, ONLY_ACTIVE_ARCH; possibly set | 267 # TODO: Look at VALID_ARCHS, ONLY_ACTIVE_ARCH; possibly set |
264 # CURRENT_ARCH / NATIVE_ARCH env vars? | 268 # CURRENT_ARCH / NATIVE_ARCH env vars? |
265 return self.xcode_settings[configname].get('ARCHS', ['i386']) | 269 return self.xcode_settings[configname].get('ARCHS', [self._DefaultArch()]) |
266 | 270 |
267 def _GetStdout(self, cmdlist): | 271 def _GetStdout(self, cmdlist): |
268 job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE) | 272 job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE) |
269 out = job.communicate()[0] | 273 out = job.communicate()[0] |
270 if job.returncode != 0: | 274 if job.returncode != 0: |
271 sys.stderr.write(out + '\n') | 275 sys.stderr.write(out + '\n') |
272 raise GypError('Error %d running %s' % (job.returncode, cmdlist[0])) | 276 raise GypError('Error %d running %s' % (job.returncode, cmdlist[0])) |
273 return out.rstrip('\n') | 277 return out.rstrip('\n') |
274 | 278 |
275 def _GetSdkVersionInfoItem(self, sdk, infoitem): | 279 def _GetSdkVersionInfoItem(self, sdk, infoitem): |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 self._WarnUnimplemented('GCC_DEBUGGING_SYMBOLS') | 374 self._WarnUnimplemented('GCC_DEBUGGING_SYMBOLS') |
371 self._WarnUnimplemented('GCC_ENABLE_OBJC_EXCEPTIONS') | 375 self._WarnUnimplemented('GCC_ENABLE_OBJC_EXCEPTIONS') |
372 | 376 |
373 # TODO: This is exported correctly, but assigning to it is not supported. | 377 # TODO: This is exported correctly, but assigning to it is not supported. |
374 self._WarnUnimplemented('MACH_O_TYPE') | 378 self._WarnUnimplemented('MACH_O_TYPE') |
375 self._WarnUnimplemented('PRODUCT_TYPE') | 379 self._WarnUnimplemented('PRODUCT_TYPE') |
376 | 380 |
377 if arch is not None: | 381 if arch is not None: |
378 archs = [arch] | 382 archs = [arch] |
379 else: | 383 else: |
380 archs = self._Settings().get('ARCHS', ['i386']) | 384 archs = self._Settings().get('ARCHS', [self._DefaultArch()]) |
381 if len(archs) != 1: | 385 if len(archs) != 1: |
382 # TODO: Supporting fat binaries will be annoying. | 386 # TODO: Supporting fat binaries will be annoying. |
383 self._WarnUnimplemented('ARCHS') | 387 self._WarnUnimplemented('ARCHS') |
384 archs = ['i386'] | 388 archs = ['i386'] |
385 cflags.append('-arch ' + archs[0]) | 389 cflags.append('-arch ' + archs[0]) |
386 | 390 |
387 if archs[0] in ('i386', 'x86_64'): | 391 if archs[0] in ('i386', 'x86_64'): |
388 if self._Test('GCC_ENABLE_SSE3_EXTENSIONS', 'YES', default='NO'): | 392 if self._Test('GCC_ENABLE_SSE3_EXTENSIONS', 'YES', default='NO'): |
389 cflags.append('-msse3') | 393 cflags.append('-msse3') |
390 if self._Test('GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS', 'YES', | 394 if self._Test('GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS', 'YES', |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 ldflags.append('-L' + gyp_to_build_path(library_path)) | 627 ldflags.append('-L' + gyp_to_build_path(library_path)) |
624 | 628 |
625 if 'ORDER_FILE' in self._Settings(): | 629 if 'ORDER_FILE' in self._Settings(): |
626 ldflags.append('-Wl,-order_file ' + | 630 ldflags.append('-Wl,-order_file ' + |
627 '-Wl,' + gyp_to_build_path( | 631 '-Wl,' + gyp_to_build_path( |
628 self._Settings()['ORDER_FILE'])) | 632 self._Settings()['ORDER_FILE'])) |
629 | 633 |
630 if arch is not None: | 634 if arch is not None: |
631 archs = [arch] | 635 archs = [arch] |
632 else: | 636 else: |
633 archs = self._Settings().get('ARCHS', ['i386']) | 637 archs = self._Settings().get('ARCHS', [self._DefaultArch()]) |
634 if len(archs) != 1: | 638 if len(archs) != 1: |
635 # TODO: Supporting fat binaries will be annoying. | 639 # TODO: Supporting fat binaries will be annoying. |
636 self._WarnUnimplemented('ARCHS') | 640 self._WarnUnimplemented('ARCHS') |
637 archs = ['i386'] | 641 archs = ['i386'] |
638 ldflags.append('-arch ' + archs[0]) | 642 ldflags.append('-arch ' + archs[0]) |
639 | 643 |
640 # Xcode adds the product directory by default. | 644 # Xcode adds the product directory by default. |
641 ldflags.append('-L' + product_dir) | 645 ldflags.append('-L' + product_dir) |
642 | 646 |
643 install_name = self.GetInstallName() | 647 install_name = self.GetInstallName() |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
841 | 845 |
842 def _XcodeVersion(self): | 846 def _XcodeVersion(self): |
843 # `xcodebuild -version` output looks like | 847 # `xcodebuild -version` output looks like |
844 # Xcode 4.6.3 | 848 # Xcode 4.6.3 |
845 # Build version 4H1503 | 849 # Build version 4H1503 |
846 # or like | 850 # or like |
847 # Xcode 3.2.6 | 851 # Xcode 3.2.6 |
848 # Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0 | 852 # Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0 |
849 # BuildVersion: 10M2518 | 853 # BuildVersion: 10M2518 |
850 # Convert that to '0463', '4H1503'. | 854 # Convert that to '0463', '4H1503'. |
851 version_list = self._GetStdout(['xcodebuild', '-version']).splitlines() | 855 if len(XcodeSettings._xcode_version_cache) == 0: |
852 version = version_list[0] | 856 version_list = self._GetStdout(['xcodebuild', '-version']).splitlines() |
853 build = version_list[-1] | 857 version = version_list[0] |
854 # Be careful to convert "4.2" to "0420": | 858 build = version_list[-1] |
855 version = version.split()[-1].replace('.', '') | 859 # Be careful to convert "4.2" to "0420": |
856 version = (version + '0' * (3 - len(version))).zfill(4) | 860 version = version.split()[-1].replace('.', '') |
857 build = build.split()[-1] | 861 version = (version + '0' * (3 - len(version))).zfill(4) |
858 return version, build | 862 build = build.split()[-1] |
| 863 XcodeSettings._xcode_version_cache = (version, build) |
| 864 return XcodeSettings._xcode_version_cache |
859 | 865 |
860 def _XcodeIOSDeviceFamily(self, configname): | 866 def _XcodeIOSDeviceFamily(self, configname): |
861 family = self.xcode_settings[configname].get('TARGETED_DEVICE_FAMILY', '1') | 867 family = self.xcode_settings[configname].get('TARGETED_DEVICE_FAMILY', '1') |
862 return [int(x) for x in family.split(',')] | 868 return [int(x) for x in family.split(',')] |
863 | 869 |
864 def GetExtraPlistItems(self, configname=None): | 870 def GetExtraPlistItems(self, configname=None): |
865 """Returns a dictionary with extra items to insert into Info.plist.""" | 871 """Returns a dictionary with extra items to insert into Info.plist.""" |
866 if configname not in XcodeSettings._plist_cache: | 872 if configname not in XcodeSettings._plist_cache: |
867 cache = {} | 873 cache = {} |
868 cache['BuildMachineOSBuild'] = self._BuildMachineOSBuild() | 874 cache['BuildMachineOSBuild'] = self._BuildMachineOSBuild() |
(...skipping 20 matching lines...) Expand all Loading... |
889 cache['CFBundleSupportedPlatforms'] = ['iPhoneSimulator'] | 895 cache['CFBundleSupportedPlatforms'] = ['iPhoneSimulator'] |
890 XcodeSettings._plist_cache[configname] = cache | 896 XcodeSettings._plist_cache[configname] = cache |
891 | 897 |
892 # Include extra plist items that are per-target, not per global | 898 # Include extra plist items that are per-target, not per global |
893 # XcodeSettings. | 899 # XcodeSettings. |
894 items = dict(XcodeSettings._plist_cache[configname]) | 900 items = dict(XcodeSettings._plist_cache[configname]) |
895 if self.isIOS: | 901 if self.isIOS: |
896 items['UIDeviceFamily'] = self._XcodeIOSDeviceFamily(configname) | 902 items['UIDeviceFamily'] = self._XcodeIOSDeviceFamily(configname) |
897 return items | 903 return items |
898 | 904 |
| 905 def _DefaultArch(self): |
| 906 # The default value for ARCHS changed from ['i386'] to ['x86_64'] in |
| 907 # Xcode 5. |
| 908 version, build = self._XcodeVersion() |
| 909 if version >= '0500': |
| 910 return 'x86_64' |
| 911 return 'i386' |
899 | 912 |
900 class MacPrefixHeader(object): | 913 class MacPrefixHeader(object): |
901 """A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature. | 914 """A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature. |
902 | 915 |
903 This feature consists of several pieces: | 916 This feature consists of several pieces: |
904 * If GCC_PREFIX_HEADER is present, all compilations in that project get an | 917 * If GCC_PREFIX_HEADER is present, all compilations in that project get an |
905 additional |-include path_to_prefix_header| cflag. | 918 additional |-include path_to_prefix_header| cflag. |
906 * If GCC_PRECOMPILE_PREFIX_HEADER is present too, then the prefix header is | 919 * If GCC_PRECOMPILE_PREFIX_HEADER is present too, then the prefix header is |
907 instead compiled, and all other compilations in the project get an | 920 instead compiled, and all other compilations in the project get an |
908 additional |-include path_to_compiled_header| instead. | 921 additional |-include path_to_compiled_header| instead. |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1303 new_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos' | 1316 new_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos' |
1304 target_dict['configurations'][new_config_name] = new_config_dict | 1317 target_dict['configurations'][new_config_name] = new_config_dict |
1305 return targets | 1318 return targets |
1306 | 1319 |
1307 def CloneConfigurationForDeviceAndEmulator(target_dicts): | 1320 def CloneConfigurationForDeviceAndEmulator(target_dicts): |
1308 """If |target_dicts| contains any iOS targets, automatically create -iphoneos | 1321 """If |target_dicts| contains any iOS targets, automatically create -iphoneos |
1309 targets for iOS device builds.""" | 1322 targets for iOS device builds.""" |
1310 if _HasIOSTarget(target_dicts): | 1323 if _HasIOSTarget(target_dicts): |
1311 return _AddIOSDeviceConfigurations(target_dicts) | 1324 return _AddIOSDeviceConfigurations(target_dicts) |
1312 return target_dicts | 1325 return target_dicts |
OLD | NEW |