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 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 if self.spec['type'] in ('loadable_module', 'shared_library'): | 231 if self.spec['type'] in ('loadable_module', 'shared_library'): |
232 default_wrapper_extension = { | 232 default_wrapper_extension = { |
233 'loadable_module': 'bundle', | 233 'loadable_module': 'bundle', |
234 'shared_library': 'framework', | 234 'shared_library': 'framework', |
235 }[self.spec['type']] | 235 }[self.spec['type']] |
236 wrapper_extension = self.GetPerTargetSetting( | 236 wrapper_extension = self.GetPerTargetSetting( |
237 'WRAPPER_EXTENSION', default=default_wrapper_extension) | 237 'WRAPPER_EXTENSION', default=default_wrapper_extension) |
238 return '.' + self.spec.get('product_extension', wrapper_extension) | 238 return '.' + self.spec.get('product_extension', wrapper_extension) |
239 elif self.spec['type'] == 'executable': | 239 elif self.spec['type'] == 'executable': |
240 return '.' + self.spec.get('product_extension', 'app') | 240 return '.' + self.spec.get('product_extension', 'app') |
| 241 elif self.spec['type'] == 'extension': |
| 242 return '.' + self.spec.get('product_extension', 'appex') |
241 else: | 243 else: |
242 assert False, "Don't know extension for '%s', target '%s'" % ( | 244 assert False, "Don't know extension for '%s', target '%s'" % ( |
243 self.spec['type'], self.spec['target_name']) | 245 self.spec['type'], self.spec['target_name']) |
244 | 246 |
245 def GetProductName(self): | 247 def GetProductName(self): |
246 """Returns PRODUCT_NAME.""" | 248 """Returns PRODUCT_NAME.""" |
247 return self.spec.get('product_name', self.spec['target_name']) | 249 return self.spec.get('product_name', self.spec['target_name']) |
248 | 250 |
249 def GetFullProductName(self): | 251 def GetFullProductName(self): |
250 """Returns FULL_PRODUCT_NAME.""" | 252 """Returns FULL_PRODUCT_NAME.""" |
(...skipping 26 matching lines...) Expand all Loading... |
277 Chromium.app/Contents/Resources. Only valid for bundles.""" | 279 Chromium.app/Contents/Resources. Only valid for bundles.""" |
278 assert self._IsBundle() | 280 assert self._IsBundle() |
279 if self.isIOS: | 281 if self.isIOS: |
280 return self.GetBundleContentsFolderPath() | 282 return self.GetBundleContentsFolderPath() |
281 return os.path.join(self.GetBundleContentsFolderPath(), 'Resources') | 283 return os.path.join(self.GetBundleContentsFolderPath(), 'Resources') |
282 | 284 |
283 def GetBundlePlistPath(self): | 285 def GetBundlePlistPath(self): |
284 """Returns the qualified path to the bundle's plist file. E.g. | 286 """Returns the qualified path to the bundle's plist file. E.g. |
285 Chromium.app/Contents/Info.plist. Only valid for bundles.""" | 287 Chromium.app/Contents/Info.plist. Only valid for bundles.""" |
286 assert self._IsBundle() | 288 assert self._IsBundle() |
287 if self.spec['type'] in ('executable', 'loadable_module'): | 289 if self.spec['type'] in ('executable', 'extension', 'loadable_module'): |
288 return os.path.join(self.GetBundleContentsFolderPath(), 'Info.plist') | 290 return os.path.join(self.GetBundleContentsFolderPath(), 'Info.plist') |
289 else: | 291 else: |
290 return os.path.join(self.GetBundleContentsFolderPath(), | 292 return os.path.join(self.GetBundleContentsFolderPath(), |
291 'Resources', 'Info.plist') | 293 'Resources', 'Info.plist') |
292 | 294 |
293 def GetProductType(self): | 295 def GetProductType(self): |
294 """Returns the PRODUCT_TYPE of this target.""" | 296 """Returns the PRODUCT_TYPE of this target.""" |
295 if self._IsBundle(): | 297 if self._IsBundle(): |
296 return { | 298 return { |
297 'executable': 'com.apple.product-type.application', | 299 'executable': 'com.apple.product-type.application', |
| 300 'extension': 'com.apple.product-type.app-extension', |
298 'loadable_module': 'com.apple.product-type.bundle', | 301 'loadable_module': 'com.apple.product-type.bundle', |
299 'shared_library': 'com.apple.product-type.framework', | 302 'shared_library': 'com.apple.product-type.framework', |
300 }[self.spec['type']] | 303 }[self.spec['type']] |
301 else: | 304 else: |
302 return { | 305 return { |
303 'executable': 'com.apple.product-type.tool', | 306 'executable': 'com.apple.product-type.tool', |
| 307 'extension': 'com.apple.product-type.app-extension', |
304 'loadable_module': 'com.apple.product-type.library.dynamic', | 308 'loadable_module': 'com.apple.product-type.library.dynamic', |
305 'shared_library': 'com.apple.product-type.library.dynamic', | 309 'shared_library': 'com.apple.product-type.library.dynamic', |
306 'static_library': 'com.apple.product-type.library.static', | 310 'static_library': 'com.apple.product-type.library.static', |
307 }[self.spec['type']] | 311 }[self.spec['type']] |
308 | 312 |
309 def GetMachOType(self): | 313 def GetMachOType(self): |
310 """Returns the MACH_O_TYPE of this target.""" | 314 """Returns the MACH_O_TYPE of this target.""" |
311 # Weird, but matches Xcode. | 315 # Weird, but matches Xcode. |
312 if not self._IsBundle() and self.spec['type'] == 'executable': | 316 if not self._IsBundle() and (self.spec['type'] == 'executable' or |
| 317 self.spec['type'] == 'extension'): |
313 return '' | 318 return '' |
314 return { | 319 return { |
315 'executable': 'mh_execute', | 320 'executable': 'mh_execute', |
| 321 'extension': 'mh_execute', |
316 'static_library': 'staticlib', | 322 'static_library': 'staticlib', |
317 'shared_library': 'mh_dylib', | 323 'shared_library': 'mh_dylib', |
318 'loadable_module': 'mh_bundle', | 324 'loadable_module': 'mh_bundle', |
319 }[self.spec['type']] | 325 }[self.spec['type']] |
320 | 326 |
321 def _GetBundleBinaryPath(self): | 327 def _GetBundleBinaryPath(self): |
322 """Returns the name of the bundle binary of by this target. | 328 """Returns the name of the bundle binary of by this target. |
323 E.g. Chromium.app/Contents/MacOS/Chromium. Only valid for bundles.""" | 329 E.g. Chromium.app/Contents/MacOS/Chromium. Only valid for bundles.""" |
324 assert self._IsBundle() | 330 assert self._IsBundle() |
325 if self.spec['type'] in ('shared_library') or self.isIOS: | 331 if self.spec['type'] in ('shared_library') or self.isIOS: |
326 path = self.GetBundleContentsFolderPath() | 332 path = self.GetBundleContentsFolderPath() |
327 elif self.spec['type'] in ('executable', 'loadable_module'): | 333 elif self.spec['type'] in ('executable', 'extension', 'loadable_module'): |
328 path = os.path.join(self.GetBundleContentsFolderPath(), 'MacOS') | 334 path = os.path.join(self.GetBundleContentsFolderPath(), 'MacOS') |
329 return os.path.join(path, self.GetExecutableName()) | 335 return os.path.join(path, self.GetExecutableName()) |
330 | 336 |
331 def _GetStandaloneExecutableSuffix(self): | 337 def _GetStandaloneExecutableSuffix(self): |
332 if 'product_extension' in self.spec: | 338 if 'product_extension' in self.spec: |
333 return '.' + self.spec['product_extension'] | 339 return '.' + self.spec['product_extension'] |
334 return { | 340 return { |
335 'executable': '', | 341 'executable': '', |
| 342 'extension': '', |
336 'static_library': '.a', | 343 'static_library': '.a', |
337 'shared_library': '.dylib', | 344 'shared_library': '.dylib', |
338 'loadable_module': '.so', | 345 'loadable_module': '.so', |
339 }[self.spec['type']] | 346 }[self.spec['type']] |
340 | 347 |
341 def _GetStandaloneExecutablePrefix(self): | 348 def _GetStandaloneExecutablePrefix(self): |
342 return self.spec.get('product_prefix', { | 349 return self.spec.get('product_prefix', { |
343 'executable': '', | 350 'executable': '', |
| 351 'extension': '', |
344 'static_library': 'lib', | 352 'static_library': 'lib', |
345 'shared_library': 'lib', | 353 'shared_library': 'lib', |
346 # Non-bundled loadable_modules are called foo.so for some reason | 354 # Non-bundled loadable_modules are called foo.so for some reason |
347 # (that is, .so and no prefix) with the xcode build -- match that. | 355 # (that is, .so and no prefix) with the xcode build -- match that. |
348 'loadable_module': '', | 356 'loadable_module': '', |
349 }[self.spec['type']]) | 357 }[self.spec['type']]) |
350 | 358 |
351 def _GetStandaloneBinaryPath(self): | 359 def _GetStandaloneBinaryPath(self): |
352 """Returns the name of the non-bundle binary represented by this target. | 360 """Returns the name of the non-bundle binary represented by this target. |
353 E.g. hello_world. Only valid for non-bundles.""" | 361 E.g. hello_world. Only valid for non-bundles.""" |
354 assert not self._IsBundle() | 362 assert not self._IsBundle() |
355 assert self.spec['type'] in ( | 363 assert self.spec['type'] in ('executable', 'extension', 'shared_library', |
356 'executable', 'shared_library', 'static_library', 'loadable_module'), ( | 364 'static_library', 'loadable_module'), ( |
357 'Unexpected type %s' % self.spec['type']) | 365 'Unexpected type %s' % self.spec['type']) |
358 target = self.spec['target_name'] | 366 target = self.spec['target_name'] |
359 if self.spec['type'] == 'static_library': | 367 if self.spec['type'] == 'static_library': |
360 if target[:3] == 'lib': | 368 if target[:3] == 'lib': |
361 target = target[3:] | 369 target = target[3:] |
362 elif self.spec['type'] in ('loadable_module', 'shared_library'): | 370 elif self.spec['type'] in ('loadable_module', 'shared_library'): |
363 if target[:3] == 'lib': | 371 if target[:3] == 'lib': |
364 target = target[3:] | 372 target = target[3:] |
365 | 373 |
366 target_prefix = self._GetStandaloneExecutablePrefix() | 374 target_prefix = self._GetStandaloneExecutablePrefix() |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 ldflags.append('-Wl,-rpath,' + rpath) | 795 ldflags.append('-Wl,-rpath,' + rpath) |
788 | 796 |
789 sdk_root = self._SdkPath() | 797 sdk_root = self._SdkPath() |
790 if not sdk_root: | 798 if not sdk_root: |
791 sdk_root = '' | 799 sdk_root = '' |
792 config = self.spec['configurations'][self.configname] | 800 config = self.spec['configurations'][self.configname] |
793 framework_dirs = config.get('mac_framework_dirs', []) | 801 framework_dirs = config.get('mac_framework_dirs', []) |
794 for directory in framework_dirs: | 802 for directory in framework_dirs: |
795 ldflags.append('-F' + directory.replace('$(SDKROOT)', sdk_root)) | 803 ldflags.append('-F' + directory.replace('$(SDKROOT)', sdk_root)) |
796 | 804 |
| 805 if sdk_root and self.spec['type'] == "extension": |
| 806 # Adds the link flags for extensions. These flags are common for all |
| 807 # extensions and provide loader and main function. |
| 808 # These flags reflect the compilation options used by xcode to compile |
| 809 # extensions. |
| 810 ldflags.append('-lpkstart ' + sdk_root + |
| 811 '/System/Library/PrivateFrameworks/PlugInKit.framework/PlugInKit') |
| 812 ldflags.append('-fapplication-extension ' + |
| 813 '-Xlinker -rpath -Xlinker @executable_path/../../Frameworks') |
| 814 |
797 self._Appendf(ldflags, 'CLANG_CXX_LIBRARY', '-stdlib=%s') | 815 self._Appendf(ldflags, 'CLANG_CXX_LIBRARY', '-stdlib=%s') |
798 | 816 |
799 self.configname = None | 817 self.configname = None |
800 return ldflags | 818 return ldflags |
801 | 819 |
802 def GetLibtoolflags(self, configname): | 820 def GetLibtoolflags(self, configname): |
803 """Returns flags that need to be passed to the static linker. | 821 """Returns flags that need to be passed to the static linker. |
804 | 822 |
805 Args: | 823 Args: |
806 configname: The name of the configuration to get ld flags for. | 824 configname: The name of the configuration to get ld flags for. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
863 | 881 |
864 result = [] | 882 result = [] |
865 if (self._Test('DEPLOYMENT_POSTPROCESSING', 'YES', default='NO') and | 883 if (self._Test('DEPLOYMENT_POSTPROCESSING', 'YES', default='NO') and |
866 self._Test('STRIP_INSTALLED_PRODUCT', 'YES', default='NO')): | 884 self._Test('STRIP_INSTALLED_PRODUCT', 'YES', default='NO')): |
867 | 885 |
868 default_strip_style = 'debugging' | 886 default_strip_style = 'debugging' |
869 if self.spec['type'] == 'loadable_module' and self._IsBundle(): | 887 if self.spec['type'] == 'loadable_module' and self._IsBundle(): |
870 default_strip_style = 'non-global' | 888 default_strip_style = 'non-global' |
871 elif self.spec['type'] == 'executable': | 889 elif self.spec['type'] == 'executable': |
872 default_strip_style = 'all' | 890 default_strip_style = 'all' |
| 891 elif self.spec['type'] == 'extension': |
| 892 default_strip_style = 'all' |
873 | 893 |
874 strip_style = self._Settings().get('STRIP_STYLE', default_strip_style) | 894 strip_style = self._Settings().get('STRIP_STYLE', default_strip_style) |
875 strip_flags = { | 895 strip_flags = { |
876 'all': '', | 896 'all': '', |
877 'non-global': '-x', | 897 'non-global': '-x', |
878 'debugging': '-S', | 898 'debugging': '-S', |
879 }[strip_style] | 899 }[strip_style] |
880 | 900 |
881 explicit_strip_flags = self._Settings().get('STRIPFLAGS', '') | 901 explicit_strip_flags = self._Settings().get('STRIPFLAGS', '') |
882 if explicit_strip_flags: | 902 if explicit_strip_flags: |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
914 to run as postbuilds for this target, before the actual postbuilds.""" | 934 to run as postbuilds for this target, before the actual postbuilds.""" |
915 # dSYMs need to build before stripping happens. | 935 # dSYMs need to build before stripping happens. |
916 return ( | 936 return ( |
917 self._GetDebugInfoPostbuilds(configname, output, output_binary, quiet) + | 937 self._GetDebugInfoPostbuilds(configname, output, output_binary, quiet) + |
918 self._GetStripPostbuilds(configname, output_binary, quiet)) | 938 self._GetStripPostbuilds(configname, output_binary, quiet)) |
919 | 939 |
920 def _GetIOSPostbuilds(self, configname, output_binary): | 940 def _GetIOSPostbuilds(self, configname, output_binary): |
921 """Return a shell command to codesign the iOS output binary so it can | 941 """Return a shell command to codesign the iOS output binary so it can |
922 be deployed to a device. This should be run as the very last step of the | 942 be deployed to a device. This should be run as the very last step of the |
923 build.""" | 943 build.""" |
924 if not (self.isIOS and self.spec['type'] == "executable"): | 944 if not (self.isIOS and (self.spec['type'] == "executable" or |
| 945 self.spec['type'] == "extension")): |
925 return [] | 946 return [] |
926 | 947 |
927 settings = self.xcode_settings[configname] | 948 settings = self.xcode_settings[configname] |
928 key = self._GetIOSCodeSignIdentityKey(settings) | 949 key = self._GetIOSCodeSignIdentityKey(settings) |
929 if not key: | 950 if not key: |
930 return [] | 951 return [] |
931 | 952 |
932 # Warn for any unimplemented signing xcode keys. | 953 # Warn for any unimplemented signing xcode keys. |
933 unimpl = ['OTHER_CODE_SIGN_FLAGS'] | 954 unimpl = ['OTHER_CODE_SIGN_FLAGS'] |
934 unimpl = set(unimpl) & set(self.xcode_settings[configname].keys()) | 955 unimpl = set(unimpl) & set(self.xcode_settings[configname].keys()) |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1395 # written for bundles: | 1416 # written for bundles: |
1396 'TARGET_BUILD_DIR' : built_products_dir, | 1417 'TARGET_BUILD_DIR' : built_products_dir, |
1397 'TEMP_DIR' : '${TMPDIR}', | 1418 'TEMP_DIR' : '${TMPDIR}', |
1398 } | 1419 } |
1399 if xcode_settings.GetPerConfigSetting('SDKROOT', configuration): | 1420 if xcode_settings.GetPerConfigSetting('SDKROOT', configuration): |
1400 env['SDKROOT'] = xcode_settings._SdkPath(configuration) | 1421 env['SDKROOT'] = xcode_settings._SdkPath(configuration) |
1401 else: | 1422 else: |
1402 env['SDKROOT'] = '' | 1423 env['SDKROOT'] = '' |
1403 | 1424 |
1404 if spec['type'] in ( | 1425 if spec['type'] in ( |
1405 'executable', 'static_library', 'shared_library', 'loadable_module'): | 1426 'executable', |
| 1427 'extension', |
| 1428 'static_library', |
| 1429 'shared_library', |
| 1430 'loadable_module'): |
1406 env['EXECUTABLE_NAME'] = xcode_settings.GetExecutableName() | 1431 env['EXECUTABLE_NAME'] = xcode_settings.GetExecutableName() |
1407 env['EXECUTABLE_PATH'] = xcode_settings.GetExecutablePath() | 1432 env['EXECUTABLE_PATH'] = xcode_settings.GetExecutablePath() |
1408 env['FULL_PRODUCT_NAME'] = xcode_settings.GetFullProductName() | 1433 env['FULL_PRODUCT_NAME'] = xcode_settings.GetFullProductName() |
1409 mach_o_type = xcode_settings.GetMachOType() | 1434 mach_o_type = xcode_settings.GetMachOType() |
1410 if mach_o_type: | 1435 if mach_o_type: |
1411 env['MACH_O_TYPE'] = mach_o_type | 1436 env['MACH_O_TYPE'] = mach_o_type |
1412 env['PRODUCT_TYPE'] = xcode_settings.GetProductType() | 1437 env['PRODUCT_TYPE'] = xcode_settings.GetProductType() |
1413 if xcode_settings._IsBundle(): | 1438 if xcode_settings._IsBundle(): |
1414 env['CONTENTS_FOLDER_PATH'] = \ | 1439 env['CONTENTS_FOLDER_PATH'] = \ |
1415 xcode_settings.GetBundleContentsFolderPath() | 1440 xcode_settings.GetBundleContentsFolderPath() |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1550 if toolset == 'target': | 1575 if toolset == 'target': |
1551 iphoneos_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos' | 1576 iphoneos_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos' |
1552 return targets | 1577 return targets |
1553 | 1578 |
1554 def CloneConfigurationForDeviceAndEmulator(target_dicts): | 1579 def CloneConfigurationForDeviceAndEmulator(target_dicts): |
1555 """If |target_dicts| contains any iOS targets, automatically create -iphoneos | 1580 """If |target_dicts| contains any iOS targets, automatically create -iphoneos |
1556 targets for iOS device builds.""" | 1581 targets for iOS device builds.""" |
1557 if _HasIOSTarget(target_dicts): | 1582 if _HasIOSTarget(target_dicts): |
1558 return _AddIOSDeviceConfigurations(target_dicts) | 1583 return _AddIOSDeviceConfigurations(target_dicts) |
1559 return target_dicts | 1584 return target_dicts |
OLD | NEW |