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 gyp.common | 10 import gyp.common |
| 11 import os.path | 11 import os.path |
| 12 import re | 12 import re |
| 13 import shlex | 13 import shlex |
| 14 import subprocess | |
| 14 | 15 |
| 15 class XcodeSettings(object): | 16 class XcodeSettings(object): |
| 16 """A class that understands the gyp 'xcode_settings' object.""" | 17 """A class that understands the gyp 'xcode_settings' object.""" |
| 17 | 18 |
| 18 # Computed lazily by _GetSdkBaseDir(). Shared by all XcodeSettings, so cached | 19 # Populated lazily by _SdkPath(). Shared by all XcodeSettings, so cached |
| 19 # at class-level for efficiency. | 20 # at class-level for efficiency. |
| 20 _sdk_base_dir = None | 21 _sdk_path_cache = {} |
| 21 | 22 |
| 22 def __init__(self, spec): | 23 def __init__(self, spec): |
| 23 self.spec = spec | 24 self.spec = spec |
| 24 | 25 |
| 25 # Per-target 'xcode_settings' are pushed down into configs earlier by gyp. | 26 # Per-target 'xcode_settings' are pushed down into configs earlier by gyp. |
| 26 # This means self.xcode_settings[config] always contains all settings | 27 # This means self.xcode_settings[config] always contains all settings |
| 27 # for that config -- the per-target settings as well. Settings that are | 28 # for that config -- the per-target settings as well. Settings that are |
| 28 # the same for all configs are implicitly per-target settings. | 29 # the same for all configs are implicitly per-target settings. |
| 29 self.xcode_settings = {} | 30 self.xcode_settings = {} |
| 30 configs = spec['configurations'] | 31 configs = spec['configurations'] |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 212 return self._GetStandaloneBinaryPath() | 213 return self._GetStandaloneBinaryPath() |
| 213 | 214 |
| 214 def GetExecutablePath(self): | 215 def GetExecutablePath(self): |
| 215 """Returns the directory name of the bundle represented by this target. E.g. | 216 """Returns the directory name of the bundle represented by this target. E.g. |
| 216 Chromium.app/Contents/MacOS/Chromium.""" | 217 Chromium.app/Contents/MacOS/Chromium.""" |
| 217 if self._IsBundle(): | 218 if self._IsBundle(): |
| 218 return self._GetBundleBinaryPath() | 219 return self._GetBundleBinaryPath() |
| 219 else: | 220 else: |
| 220 return self._GetStandaloneBinaryPath() | 221 return self._GetStandaloneBinaryPath() |
| 221 | 222 |
| 222 def _GetSdkBaseDir(self): | 223 def _GetSdkVersionInfoItem(self, sdk, infoitem): |
| 223 """Returns the root of the 'Developer' directory. On Xcode 4.2 and prior, | 224 job = subprocess.Popen(['xcodebuild', '-version', '-sdk', sdk, infoitem], |
|
Nico
2013/03/11 17:14:40
Nice!
| |
| 224 this is usually just /Developer. Xcode 4.3 moved that folder into the Xcode | 225 stdout=subprocess.PIPE, |
| 225 bundle.""" | 226 stderr=subprocess.STDOUT) |
| 226 if not XcodeSettings._sdk_base_dir: | 227 out, err = job.communicate() |
| 227 import subprocess | 228 if job.returncode != 0: |
| 228 job = subprocess.Popen(['xcode-select', '-print-path'], | 229 print out |
|
Nico
2013/03/11 17:14:40
Isn't `err` more interesting?
kal
2013/03/12 13:10:08
'out' gets both stdout and stderr from xcodebuild.
| |
| 229 stdout=subprocess.PIPE, | 230 raise Exception('Error %d running xcodebuild' % job.returncode) |
| 230 stderr=subprocess.STDOUT) | 231 return out.rstrip('\n') |
| 231 out, err = job.communicate() | |
| 232 if job.returncode != 0: | |
| 233 print out | |
| 234 raise Exception('Error %d running xcode-select' % job.returncode) | |
| 235 # The Developer folder moved in Xcode 4.3. | |
| 236 xcode43_sdk_path = os.path.join( | |
| 237 out.rstrip(), 'Platforms/MacOSX.platform/Developer/SDKs') | |
| 238 if os.path.isdir(xcode43_sdk_path): | |
| 239 XcodeSettings._sdk_base_dir = xcode43_sdk_path | |
| 240 else: | |
| 241 XcodeSettings._sdk_base_dir = os.path.join(out.rstrip(), 'SDKs') | |
| 242 return XcodeSettings._sdk_base_dir | |
| 243 | 232 |
| 244 def _SdkPath(self): | 233 def _SdkPath(self): |
| 245 sdk_root = self.GetPerTargetSetting('SDKROOT', default='macosx10.5') | 234 sdk_root = self.GetPerTargetSetting('SDKROOT', default='macosx') |
| 246 if sdk_root.startswith('macosx'): | 235 if sdk_root not in XcodeSettings._sdk_path_cache: |
| 247 return os.path.join(self._GetSdkBaseDir(), | 236 XcodeSettings._sdk_path_cache[sdk_root] = self._GetSdkVersionInfoItem( |
| 248 'MacOSX' + sdk_root[len('macosx'):] + '.sdk') | 237 sdk_root, 'Path') |
| 249 return sdk_root | 238 return XcodeSettings._sdk_path_cache[sdk_root] |
| 239 | |
| 240 def _AppendPlatformVersionMinFlags(self, lst): | |
| 241 self._Appendf(lst, 'MACOSX_DEPLOYMENT_TARGET', '-mmacosx-version-min=%s') | |
| 242 if 'IPHONEOS_DEPLOYMENT_TARGET' in self._Settings(): | |
| 243 # TODO: Implement this better? | |
| 244 sdk_path_basename = os.path.basename(self._SdkPath()) | |
| 245 if sdk_path_basename.lower().startswith('iphonesimulator'): | |
| 246 self._Appendf(lst, 'IPHONEOS_DEPLOYMENT_TARGET', | |
| 247 '-mios-simulator-version-min=%s') | |
| 248 else: | |
| 249 self._Appendf(lst, 'IPHONEOS_DEPLOYMENT_TARGET', | |
| 250 '-miphoneos-version-min=%s') | |
| 250 | 251 |
| 251 def GetCflags(self, configname): | 252 def GetCflags(self, configname): |
| 252 """Returns flags that need to be added to .c, .cc, .m, and .mm | 253 """Returns flags that need to be added to .c, .cc, .m, and .mm |
| 253 compilations.""" | 254 compilations.""" |
| 254 # This functions (and the similar ones below) do not offer complete | 255 # This functions (and the similar ones below) do not offer complete |
| 255 # emulation of all xcode_settings keys. They're implemented on demand. | 256 # emulation of all xcode_settings keys. They're implemented on demand. |
| 256 | 257 |
| 257 self.configname = configname | 258 self.configname = configname |
| 258 cflags = [] | 259 cflags = [] |
| 259 | 260 |
| 260 sdk_root = self._SdkPath() | 261 sdk_root = self._SdkPath() |
| 261 if 'SDKROOT' in self._Settings(): | 262 if 'SDKROOT' in self._Settings(): |
| 262 cflags.append('-isysroot %s' % sdk_root) | 263 cflags.append('-isysroot %s' % sdk_root) |
| 263 | 264 |
| 265 if self._Test('CLANG_WARN_CONSTANT_CONVERSION', 'YES', default='NO'): | |
| 266 cflags.append('-Wconstant-conversion') | |
| 267 | |
| 264 if self._Test('GCC_CHAR_IS_UNSIGNED_CHAR', 'YES', default='NO'): | 268 if self._Test('GCC_CHAR_IS_UNSIGNED_CHAR', 'YES', default='NO'): |
| 265 cflags.append('-funsigned-char') | 269 cflags.append('-funsigned-char') |
| 266 | 270 |
| 267 if self._Test('GCC_CW_ASM_SYNTAX', 'YES', default='YES'): | 271 if self._Test('GCC_CW_ASM_SYNTAX', 'YES', default='YES'): |
| 268 cflags.append('-fasm-blocks') | 272 cflags.append('-fasm-blocks') |
| 269 | 273 |
| 270 if 'GCC_DYNAMIC_NO_PIC' in self._Settings(): | 274 if 'GCC_DYNAMIC_NO_PIC' in self._Settings(): |
| 271 if self._Settings()['GCC_DYNAMIC_NO_PIC'] == 'YES': | 275 if self._Settings()['GCC_DYNAMIC_NO_PIC'] == 'YES': |
| 272 cflags.append('-mdynamic-no-pic') | 276 cflags.append('-mdynamic-no-pic') |
| 273 else: | 277 else: |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 294 | 298 |
| 295 if self._Test('GCC_SYMBOLS_PRIVATE_EXTERN', 'YES', default='NO'): | 299 if self._Test('GCC_SYMBOLS_PRIVATE_EXTERN', 'YES', default='NO'): |
| 296 cflags.append('-fvisibility=hidden') | 300 cflags.append('-fvisibility=hidden') |
| 297 | 301 |
| 298 if self._Test('GCC_TREAT_WARNINGS_AS_ERRORS', 'YES', default='NO'): | 302 if self._Test('GCC_TREAT_WARNINGS_AS_ERRORS', 'YES', default='NO'): |
| 299 cflags.append('-Werror') | 303 cflags.append('-Werror') |
| 300 | 304 |
| 301 if self._Test('GCC_WARN_ABOUT_MISSING_NEWLINE', 'YES', default='NO'): | 305 if self._Test('GCC_WARN_ABOUT_MISSING_NEWLINE', 'YES', default='NO'): |
| 302 cflags.append('-Wnewline-eof') | 306 cflags.append('-Wnewline-eof') |
| 303 | 307 |
| 304 self._Appendf(cflags, 'MACOSX_DEPLOYMENT_TARGET', '-mmacosx-version-min=%s') | 308 self._AppendPlatformVersionMinFlags(cflags) |
| 305 | 309 |
| 306 # TODO: | 310 # TODO: |
| 307 if self._Test('COPY_PHASE_STRIP', 'YES', default='NO'): | 311 if self._Test('COPY_PHASE_STRIP', 'YES', default='NO'): |
| 308 self._WarnUnimplemented('COPY_PHASE_STRIP') | 312 self._WarnUnimplemented('COPY_PHASE_STRIP') |
| 309 self._WarnUnimplemented('GCC_DEBUGGING_SYMBOLS') | 313 self._WarnUnimplemented('GCC_DEBUGGING_SYMBOLS') |
| 310 self._WarnUnimplemented('GCC_ENABLE_OBJC_EXCEPTIONS') | 314 self._WarnUnimplemented('GCC_ENABLE_OBJC_EXCEPTIONS') |
| 311 | 315 |
| 312 # TODO: This is exported correctly, but assigning to it is not supported. | 316 # TODO: This is exported correctly, but assigning to it is not supported. |
| 313 self._WarnUnimplemented('MACH_O_TYPE') | 317 self._WarnUnimplemented('MACH_O_TYPE') |
| 314 self._WarnUnimplemented('PRODUCT_TYPE') | 318 self._WarnUnimplemented('PRODUCT_TYPE') |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 347 cflags_c = [] | 351 cflags_c = [] |
| 348 self._Appendf(cflags_c, 'GCC_C_LANGUAGE_STANDARD', '-std=%s') | 352 self._Appendf(cflags_c, 'GCC_C_LANGUAGE_STANDARD', '-std=%s') |
| 349 cflags_c += self._Settings().get('OTHER_CFLAGS', []) | 353 cflags_c += self._Settings().get('OTHER_CFLAGS', []) |
| 350 self.configname = None | 354 self.configname = None |
| 351 return cflags_c | 355 return cflags_c |
| 352 | 356 |
| 353 def GetCflagsCC(self, configname): | 357 def GetCflagsCC(self, configname): |
| 354 """Returns flags that need to be added to .cc, and .mm compilations.""" | 358 """Returns flags that need to be added to .cc, and .mm compilations.""" |
| 355 self.configname = configname | 359 self.configname = configname |
| 356 cflags_cc = [] | 360 cflags_cc = [] |
| 361 | |
| 362 clang_cxx_language_standard = self._Settings().get( | |
| 363 'CLANG_CXX_LANGUAGE_STANDARD') | |
| 364 if clang_cxx_language_standard == 'c++0x': | |
| 365 cflags_cc.append('-std=c++11') | |
| 366 elif clang_cxx_language_standard == 'gnu++0x': | |
| 367 cflags_cc.append('-std=gnu++11') | |
| 368 elif clang_cxx_language_standard: | |
| 369 cflags_cc.append('-std=%s' % clang_cxx_language_standard) | |
| 370 | |
| 371 self._Appendf(cflags_cc, 'CLANG_CXX_LIBRARY', '-stdlib=%s') | |
| 372 | |
| 357 if self._Test('GCC_ENABLE_CPP_RTTI', 'NO', default='YES'): | 373 if self._Test('GCC_ENABLE_CPP_RTTI', 'NO', default='YES'): |
| 358 cflags_cc.append('-fno-rtti') | 374 cflags_cc.append('-fno-rtti') |
| 359 if self._Test('GCC_ENABLE_CPP_EXCEPTIONS', 'NO', default='YES'): | 375 if self._Test('GCC_ENABLE_CPP_EXCEPTIONS', 'NO', default='YES'): |
| 360 cflags_cc.append('-fno-exceptions') | 376 cflags_cc.append('-fno-exceptions') |
| 361 if self._Test('GCC_INLINES_ARE_PRIVATE_EXTERN', 'YES', default='NO'): | 377 if self._Test('GCC_INLINES_ARE_PRIVATE_EXTERN', 'YES', default='NO'): |
| 362 cflags_cc.append('-fvisibility-inlines-hidden') | 378 cflags_cc.append('-fvisibility-inlines-hidden') |
| 363 if self._Test('GCC_THREADSAFE_STATICS', 'NO', default='YES'): | 379 if self._Test('GCC_THREADSAFE_STATICS', 'NO', default='YES'): |
| 364 cflags_cc.append('-fno-threadsafe-statics') | 380 cflags_cc.append('-fno-threadsafe-statics') |
| 365 if self._Test('GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO', 'NO', default='YES'): | 381 if self._Test('GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO', 'NO', default='YES'): |
| 366 cflags_cc.append('-Wno-invalid-offsetof') | 382 cflags_cc.append('-Wno-invalid-offsetof') |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 517 if self._Test('DEAD_CODE_STRIPPING', 'YES', default='NO'): | 533 if self._Test('DEAD_CODE_STRIPPING', 'YES', default='NO'): |
| 518 ldflags.append('-Wl,-dead_strip') | 534 ldflags.append('-Wl,-dead_strip') |
| 519 | 535 |
| 520 if self._Test('PREBINDING', 'YES', default='NO'): | 536 if self._Test('PREBINDING', 'YES', default='NO'): |
| 521 ldflags.append('-Wl,-prebind') | 537 ldflags.append('-Wl,-prebind') |
| 522 | 538 |
| 523 self._Appendf( | 539 self._Appendf( |
| 524 ldflags, 'DYLIB_COMPATIBILITY_VERSION', '-compatibility_version %s') | 540 ldflags, 'DYLIB_COMPATIBILITY_VERSION', '-compatibility_version %s') |
| 525 self._Appendf( | 541 self._Appendf( |
| 526 ldflags, 'DYLIB_CURRENT_VERSION', '-current_version %s') | 542 ldflags, 'DYLIB_CURRENT_VERSION', '-current_version %s') |
| 527 self._Appendf( | 543 |
| 528 ldflags, 'MACOSX_DEPLOYMENT_TARGET', '-mmacosx-version-min=%s') | 544 self._AppendPlatformVersionMinFlags(ldflags) |
| 545 | |
| 529 if 'SDKROOT' in self._Settings(): | 546 if 'SDKROOT' in self._Settings(): |
| 530 ldflags.append('-isysroot ' + self._SdkPath()) | 547 ldflags.append('-isysroot ' + self._SdkPath()) |
| 531 | 548 |
| 532 for library_path in self._Settings().get('LIBRARY_SEARCH_PATHS', []): | 549 for library_path in self._Settings().get('LIBRARY_SEARCH_PATHS', []): |
| 533 ldflags.append('-L' + gyp_to_build_path(library_path)) | 550 ldflags.append('-L' + gyp_to_build_path(library_path)) |
| 534 | 551 |
| 535 if 'ORDER_FILE' in self._Settings(): | 552 if 'ORDER_FILE' in self._Settings(): |
| 536 ldflags.append('-Wl,-order_file ' + | 553 ldflags.append('-Wl,-order_file ' + |
| 537 '-Wl,' + gyp_to_build_path( | 554 '-Wl,' + gyp_to_build_path( |
| 538 self._Settings()['ORDER_FILE'])) | 555 self._Settings()['ORDER_FILE'])) |
| (...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1056 def GetSpecPostbuildCommands(spec, quiet=False): | 1073 def GetSpecPostbuildCommands(spec, quiet=False): |
| 1057 """Returns the list of postbuilds explicitly defined on |spec|, in a form | 1074 """Returns the list of postbuilds explicitly defined on |spec|, in a form |
| 1058 executable by a shell.""" | 1075 executable by a shell.""" |
| 1059 postbuilds = [] | 1076 postbuilds = [] |
| 1060 for postbuild in spec.get('postbuilds', []): | 1077 for postbuild in spec.get('postbuilds', []): |
| 1061 if not quiet: | 1078 if not quiet: |
| 1062 postbuilds.append('echo POSTBUILD\\(%s\\) %s' % ( | 1079 postbuilds.append('echo POSTBUILD\\(%s\\) %s' % ( |
| 1063 spec['target_name'], postbuild['postbuild_name'])) | 1080 spec['target_name'], postbuild['postbuild_name'])) |
| 1064 postbuilds.append(gyp.common.EncodePOSIXShellList(postbuild['action'])) | 1081 postbuilds.append(gyp.common.EncodePOSIXShellList(postbuild['action'])) |
| 1065 return postbuilds | 1082 return postbuilds |
| OLD | NEW |